mirror of
https://github.com/elder-plinius/OBLITERATUS.git
synced 2026-08-17 16:37:30 +02:00
170 lines
6.3 KiB
Python
170 lines
6.3 KiB
Python
"""
|
|
models_client.py — drop-in BESTIARY catalog reader for any PlinyOS app.
|
|
|
|
Copy this single file into any repo that needs the model list. It reads the
|
|
catalog BESTIARY produces and gives you filtered views, with zero third-party
|
|
deps. No need to import the full bestiary engine.
|
|
|
|
Resolution order for the catalog:
|
|
1. $BESTIARY_CATALOG (explicit path or http(s) URL)
|
|
2. a local catalog.json next to this file
|
|
3. the canonical monorepo path (…/03-PLINYOS/organs/bestiary/state/catalog.json)
|
|
|
|
Usage
|
|
─────
|
|
from models_client import models, model_ids, newest
|
|
|
|
# frontier / hosted apps (godmode, tempest, libertarium):
|
|
api_models = models(channel="api") # OpenRouter-reachable
|
|
ids = model_ids(channel="api", vendor="anthropic") # ["anthropic/claude-opus-4.8", …]
|
|
|
|
# open-weight apps (obliteratus, incanta, pandora):
|
|
weights = models(open_weight=True) # downloadable, with hf_id
|
|
coders = models(open_weight=True, capability="tools")
|
|
|
|
# newest drops across everything:
|
|
for m in newest(days=7):
|
|
print(m["id"], m["released"])
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import urllib.request
|
|
from datetime import datetime, timedelta, timezone
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from .service_contracts import (
|
|
normalized_text_list,
|
|
validate_catalog,
|
|
validate_day_window,
|
|
)
|
|
|
|
_HERE = Path(__file__).resolve().parent
|
|
_CANONICAL = _HERE.parent / "bestiary" / "state" / "catalog.json"
|
|
_LOCAL = _HERE / "catalog.json"
|
|
_CHANNEL_ALIASES = {"api": "openrouter", "hosted": "openrouter",
|
|
"frontier": "openrouter", "hf": "huggingface"}
|
|
_CATALOG_TIMEOUT_SECONDS = 15
|
|
_MAX_CATALOG_BYTES = 8 * 1024 * 1024
|
|
|
|
|
|
def _utc_now() -> datetime:
|
|
return datetime.now(timezone.utc)
|
|
|
|
|
|
def _decode_catalog(payload: bytes, source: str) -> dict[str, Any]:
|
|
if len(payload) > _MAX_CATALOG_BYTES:
|
|
raise ValueError(f"BESTIARY catalog exceeds size limit: {source}")
|
|
try:
|
|
decoded = payload.decode("utf-8")
|
|
parsed = json.loads(decoded)
|
|
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
|
raise ValueError(f"BESTIARY catalog is not valid UTF-8 JSON: {source}") from exc
|
|
return validate_catalog(parsed)
|
|
|
|
|
|
def _read_catalog_path(path: Path) -> dict[str, Any]:
|
|
try:
|
|
size = path.stat().st_size
|
|
except FileNotFoundError:
|
|
raise FileNotFoundError(f"BESTIARY catalog not found: {path}") from None
|
|
if size > _MAX_CATALOG_BYTES:
|
|
raise ValueError(f"BESTIARY catalog exceeds size limit: {path}")
|
|
return _decode_catalog(path.read_bytes(), str(path))
|
|
|
|
|
|
def _load() -> dict[str, Any]:
|
|
src = os.environ.get("BESTIARY_CATALOG", "").strip()
|
|
if src.startswith("http://") or src.startswith("https://"):
|
|
with urllib.request.urlopen(src, timeout=_CATALOG_TIMEOUT_SECONDS) as response:
|
|
return _decode_catalog(response.read(_MAX_CATALOG_BYTES + 1), src)
|
|
if src:
|
|
return _read_catalog_path(Path(src))
|
|
for path in (_LOCAL, _CANONICAL, _HERE / "state" / "catalog.json"):
|
|
if path.exists():
|
|
return _read_catalog_path(path)
|
|
raise FileNotFoundError(
|
|
"BESTIARY catalog not found. Run `python3 bestiary.py update`, or set "
|
|
"$BESTIARY_CATALOG to a catalog.json path or URL."
|
|
)
|
|
|
|
|
|
def _normalize_filter(value: str | None, name: str) -> str | None:
|
|
if value is None:
|
|
return None
|
|
if not isinstance(value, str):
|
|
raise TypeError(f"{name} must be a string")
|
|
normalized = value.strip().casefold()
|
|
return normalized or None
|
|
|
|
|
|
def models(channel: str | None = None, vendor: str | None = None,
|
|
open_weight: bool | None = None, capability: str | None = None) -> list[dict]:
|
|
"""Return catalog records filtered by channel / vendor / open_weight / capability."""
|
|
channel = _normalize_filter(channel, "channel")
|
|
vendor = _normalize_filter(vendor, "vendor")
|
|
capability = _normalize_filter(capability, "capability")
|
|
if channel in ("open-weight", "openweight", "weights"):
|
|
open_weight, channel = True, None
|
|
if channel:
|
|
channel = _CHANNEL_ALIASES.get(channel, channel)
|
|
out = []
|
|
for m in _load().get("models", []):
|
|
channels = normalized_text_list(m, "channels")
|
|
capabilities = normalized_text_list(m, "capabilities")
|
|
record_vendor = m.get("vendor")
|
|
if record_vendor is not None and not isinstance(record_vendor, str):
|
|
raise ValueError("BESTIARY catalog vendor must be a string")
|
|
if channel and channel not in channels:
|
|
continue
|
|
if vendor and (record_vendor or "").strip().casefold() != vendor:
|
|
continue
|
|
if open_weight is not None and bool(m.get("open_weight")) != open_weight:
|
|
continue
|
|
if capability and capability not in capabilities:
|
|
continue
|
|
out.append(m)
|
|
return out
|
|
|
|
|
|
def model_ids(**kw) -> list[str]:
|
|
"""Just the ids — the common case for populating a dropdown or a config."""
|
|
ids = []
|
|
for record in models(**kw):
|
|
model_id = record.get("id")
|
|
if not isinstance(model_id, str) or not model_id.strip():
|
|
raise ValueError("BESTIARY catalog model requires a non-empty string id")
|
|
ids.append(model_id)
|
|
return ids
|
|
|
|
|
|
def newest(days: int = 7, **kw) -> list[dict]:
|
|
"""Models first-seen (≈ released) within the last `days`, newest first."""
|
|
cutoff = _utc_now() - timedelta(days=validate_day_window(days))
|
|
out: list[tuple[datetime, dict]] = []
|
|
for m in models(**kw):
|
|
fs = m.get("first_seen") or m.get("released")
|
|
if not fs:
|
|
continue
|
|
if not isinstance(fs, str):
|
|
raise ValueError("BESTIARY catalog dates must be strings")
|
|
try:
|
|
t = datetime.strptime(fs, "%Y-%m-%d").replace(tzinfo=timezone.utc)
|
|
except ValueError:
|
|
continue
|
|
if t >= cutoff:
|
|
out.append((t, m))
|
|
out.sort(key=lambda item: item[0], reverse=True)
|
|
return [record for _, record in out]
|
|
|
|
|
|
if __name__ == "__main__":
|
|
cat = _load()
|
|
print(f"catalog generated_at={cat.get('generated_at')} count={cat.get('count')}")
|
|
print(f" api models : {len(models(channel='api'))}")
|
|
print(f" open-weight : {len(models(open_weight=True))}")
|
|
print(f" new (7d) : {len(newest(7))}")
|