mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-11-07 13:42:20 +01:00
Compare commits
2
Commits
2a6b09b968
...
032967af4b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
032967af4b | ||
|
|
0e03aea134 |
@@ -1351,14 +1351,14 @@ def _legacy_visible_api_models(ep) -> List[str]:
|
|||||||
def _picker_models_for_endpoint(ep, base_url: str, kind: str):
|
def _picker_models_for_endpoint(ep, base_url: str, kind: str):
|
||||||
"""Return model IDs that should appear in the picker for an endpoint.
|
"""Return model IDs that should appear in the picker for an endpoint.
|
||||||
|
|
||||||
API providers expose remote inventory from /v1/models. Treat that cache as
|
API providers expose remote inventory from /v1/models. Default to that
|
||||||
inventory, not approval: only manually pinned API models should appear in
|
visible inventory until an explicit pinned-model allow-list is saved.
|
||||||
the picker. Local/self-hosted endpoints keep the older hide-list behavior.
|
Local/self-hosted endpoints keep the older hide-list behavior.
|
||||||
"""
|
"""
|
||||||
pinned = _normalize_model_ids(getattr(ep, "pinned_models", None))
|
pinned = _normalize_model_ids(getattr(ep, "pinned_models", None))
|
||||||
if _picker_requires_pinning(base_url, kind):
|
if _picker_requires_pinning(base_url, kind):
|
||||||
if not _has_explicit_pinned_models(ep):
|
if not _has_explicit_pinned_models(ep):
|
||||||
pinned = _legacy_visible_api_models(ep) if _hidden_model_ids(ep) else []
|
pinned = _legacy_visible_api_models(ep)
|
||||||
return pinned, pinned
|
return pinned, pinned
|
||||||
return _visible_models(
|
return _visible_models(
|
||||||
_cached_model_ids(ep),
|
_cached_model_ids(ep),
|
||||||
@@ -2342,9 +2342,7 @@ def setup_model_routes(model_discovery):
|
|||||||
else:
|
else:
|
||||||
response.headers["X-Model-Refresh-Status"] = "failed"
|
response.headers["X-Model-Refresh-Status"] = "failed"
|
||||||
response.headers["X-Model-Refresh-Warning"] = "Model refresh failed or returned no models; kept cached models."
|
response.headers["X-Model-Refresh-Warning"] = "Model refresh failed or returned no models; kept cached models."
|
||||||
pinned = _normalize_model_ids(getattr(ep, "pinned_models", None))
|
_, pinned = _picker_models_for_endpoint(ep, base, kind)
|
||||||
if picker_requires_pinning and not _has_explicit_pinned_models(ep):
|
|
||||||
pinned = _legacy_visible_api_models(ep)
|
|
||||||
pinned_set = set(pinned)
|
pinned_set = set(pinned)
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1107,6 +1107,47 @@ def test_get_api_models_marks_picker_as_pinned_only(monkeypatch):
|
|||||||
assert by_id["anthropic/claude-sonnet-4"]["is_pinned"] is False
|
assert by_id["anthropic/claude-sonnet-4"]["is_pinned"] is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_fresh_api_models_marks_cached_inventory_as_pinned(monkeypatch):
|
||||||
|
ep = _make_endpoint(
|
||||||
|
base_url="https://api.example.test/v1",
|
||||||
|
cached_models=json.dumps(["openai/gpt-image-1", "anthropic/claude-sonnet-4"]),
|
||||||
|
pinned_models=None,
|
||||||
|
)
|
||||||
|
db = _PinnedFakeDb([ep])
|
||||||
|
monkeypatch.setattr(model_routes, "SessionLocal", lambda: db)
|
||||||
|
monkeypatch.setattr(model_routes, "require_admin", lambda request: None)
|
||||||
|
endpoint = _get_route("/api/model-endpoints/{ep_id}/models", "GET")
|
||||||
|
|
||||||
|
result = endpoint("ep1", _PinnedFakeRequest(), SimpleNamespace(headers={}))
|
||||||
|
|
||||||
|
assert [row["id"] for row in result] == [
|
||||||
|
"openai/gpt-image-1",
|
||||||
|
"anthropic/claude-sonnet-4",
|
||||||
|
]
|
||||||
|
assert all(row["picker_requires_pinning"] is True for row in result)
|
||||||
|
assert all(row["is_pinned"] is True for row in result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_legacy_api_models_preserves_hidden_selection_as_pinned(monkeypatch):
|
||||||
|
ep = _make_endpoint(
|
||||||
|
base_url="https://api.example.test/v1",
|
||||||
|
cached_models=json.dumps(["m1", "m2", "m3"]),
|
||||||
|
hidden_models=json.dumps(["m2"]),
|
||||||
|
pinned_models=None,
|
||||||
|
)
|
||||||
|
db = _PinnedFakeDb([ep])
|
||||||
|
monkeypatch.setattr(model_routes, "SessionLocal", lambda: db)
|
||||||
|
monkeypatch.setattr(model_routes, "require_admin", lambda request: None)
|
||||||
|
endpoint = _get_route("/api/model-endpoints/{ep_id}/models", "GET")
|
||||||
|
|
||||||
|
result = endpoint("ep1", _PinnedFakeRequest(), SimpleNamespace(headers={}))
|
||||||
|
|
||||||
|
by_id = {row["id"]: row for row in result}
|
||||||
|
assert by_id["m1"]["is_pinned"] is True
|
||||||
|
assert by_id["m2"]["is_pinned"] is False
|
||||||
|
assert by_id["m3"]["is_pinned"] is True
|
||||||
|
|
||||||
|
|
||||||
def test_reprobe_preserves_pinned_models(monkeypatch):
|
def test_reprobe_preserves_pinned_models(monkeypatch):
|
||||||
ep = _make_endpoint(pinned_models=json.dumps(["deploy-1"]))
|
ep = _make_endpoint(pinned_models=json.dumps(["deploy-1"]))
|
||||||
db = _PinnedFakeDb([ep])
|
db = _PinnedFakeDb([ep])
|
||||||
@@ -1266,7 +1307,7 @@ def test_list_model_endpoints_returns_key_fingerprint(monkeypatch):
|
|||||||
assert result[1]["api_key_fingerprint"] == ""
|
assert result[1]["api_key_fingerprint"] == ""
|
||||||
|
|
||||||
|
|
||||||
def test_list_api_endpoint_reports_inventory_count_when_none_pinned(monkeypatch):
|
def test_list_api_endpoint_defaults_inventory_to_visible_when_none_pinned(monkeypatch):
|
||||||
ep = _make_endpoint(
|
ep = _make_endpoint(
|
||||||
base_url="https://api.example.test/v1",
|
base_url="https://api.example.test/v1",
|
||||||
cached_models=json.dumps(["openai/gpt-image-1", "anthropic/claude-sonnet-4"]),
|
cached_models=json.dumps(["openai/gpt-image-1", "anthropic/claude-sonnet-4"]),
|
||||||
@@ -1279,12 +1320,31 @@ def test_list_api_endpoint_reports_inventory_count_when_none_pinned(monkeypatch)
|
|||||||
|
|
||||||
result = endpoint(_PinnedFakeRequest())
|
result = endpoint(_PinnedFakeRequest())
|
||||||
|
|
||||||
assert result[0]["models"] == []
|
assert result[0]["models"] == [
|
||||||
|
"openai/gpt-image-1",
|
||||||
|
"anthropic/claude-sonnet-4",
|
||||||
|
]
|
||||||
|
assert result[0]["pinned_models"] == result[0]["models"]
|
||||||
assert result[0]["model_count"] == 2
|
assert result[0]["model_count"] == 2
|
||||||
assert result[0]["picker_requires_pinning"] is True
|
assert result[0]["picker_requires_pinning"] is True
|
||||||
assert result[0]["status"] == "online"
|
assert result[0]["status"] == "online"
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_picker_preserves_explicit_empty_selection():
|
||||||
|
ep = _make_endpoint(
|
||||||
|
base_url="https://api.example.test/v1",
|
||||||
|
cached_models=json.dumps(["openai/gpt-image-1", "anthropic/claude-sonnet-4"]),
|
||||||
|
pinned_models=json.dumps([]),
|
||||||
|
)
|
||||||
|
|
||||||
|
models, pinned = model_routes._picker_models_for_endpoint(
|
||||||
|
ep, ep.base_url, ep.endpoint_kind
|
||||||
|
)
|
||||||
|
|
||||||
|
assert models == []
|
||||||
|
assert pinned == []
|
||||||
|
|
||||||
|
|
||||||
def test_list_api_endpoint_returns_pinned_picker_models(monkeypatch):
|
def test_list_api_endpoint_returns_pinned_picker_models(monkeypatch):
|
||||||
ep = _make_endpoint(
|
ep = _make_endpoint(
|
||||||
base_url="https://api.example.test/v1",
|
base_url="https://api.example.test/v1",
|
||||||
@@ -1767,7 +1827,7 @@ def test_api_models_openrouter_uses_pinned_models_not_hidden(monkeypatch):
|
|||||||
assert result["items"][0]["models"] == ["openai/gpt-image-1"]
|
assert result["items"][0]["models"] == ["openai/gpt-image-1"]
|
||||||
|
|
||||||
|
|
||||||
def test_api_models_openrouter_derives_legacy_visible_models(monkeypatch):
|
def test_api_models_openrouter_defaults_cached_models_visible(monkeypatch):
|
||||||
row = _route_ep(
|
row = _route_ep(
|
||||||
"openrouter",
|
"openrouter",
|
||||||
"https://openrouter.ai/api/v1",
|
"https://openrouter.ai/api/v1",
|
||||||
@@ -1775,7 +1835,6 @@ def test_api_models_openrouter_derives_legacy_visible_models(monkeypatch):
|
|||||||
pinned_models=None,
|
pinned_models=None,
|
||||||
api_key="fake-key",
|
api_key="fake-key",
|
||||||
)
|
)
|
||||||
row.hidden_models = json.dumps(["m2"])
|
|
||||||
db = _RouteDb([row])
|
db = _RouteDb([row])
|
||||||
router = model_routes.setup_model_routes(model_discovery=None)
|
router = model_routes.setup_model_routes(model_discovery=None)
|
||||||
|
|
||||||
@@ -1788,7 +1847,7 @@ def test_api_models_openrouter_derives_legacy_visible_models(monkeypatch):
|
|||||||
result = _route_endpoint(router, "/api/models")(_route_request())
|
result = _route_endpoint(router, "/api/models")(_route_request())
|
||||||
|
|
||||||
assert result["items"][0]["endpoint_name"] == "openrouter"
|
assert result["items"][0]["endpoint_name"] == "openrouter"
|
||||||
assert result["items"][0]["models"] == ["m1", "m3"]
|
assert result["items"][0]["models"] == ["m1", "m2", "m3"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
|
|||||||
Reference in New Issue
Block a user