mirror of
https://github.com/Routstr/routstr-core.git
synced 2026-10-06 12:38:23 +00:00
fix(admin): show the operator the rate that needs fixing
The admin listing includes disabled models, so it is the one view still carrying a row the served-catalog backstop holds back — including one whose stored rate is not a usable number. The encoder reported that rate as `null`, indistinguishable from a missing one, so the operator could see the row but not the reason it was withheld. Reuses the non-finite renderer the 422 handler already uses, promoted to a shared name now that it has a second caller. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011cKHVF5LA7TR5QuYi6ErLM
This commit is contained in:
co-authored by
Claude Opus 5
parent
41fed7413a
commit
6e5a388ee4
@@ -35,6 +35,7 @@ from .db import (
|
||||
from .db import (
|
||||
store_cashu_transaction_with_retry as store_cashu_transaction,
|
||||
)
|
||||
from .exceptions import json_compliant
|
||||
from .log_manager import log_manager
|
||||
from .logging import get_logger
|
||||
from .provider_slugs import allocate_unique_provider_slug
|
||||
@@ -1273,8 +1274,13 @@ async def get_provider_models(provider_id: str) -> dict[str, object]:
|
||||
"provider_type": provider.provider_type,
|
||||
"base_url": provider.base_url,
|
||||
},
|
||||
"db_models": [m.dict() for m in db_models],
|
||||
"remote_models": [m.dict() for m in filtered_remote_models],
|
||||
# This listing includes disabled models, so it is the one view that
|
||||
# still carries a row the served-catalog backstop holds back —
|
||||
# including one whose stored rate is not a usable number. The
|
||||
# encoder would report that rate as `null`, indistinguishable from a
|
||||
# missing one; show the operator the value that needs fixing.
|
||||
"db_models": [json_compliant(m.dict()) for m in db_models],
|
||||
"remote_models": [json_compliant(m.dict()) for m in filtered_remote_models],
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -259,3 +259,52 @@ async def test_non_finite_literal_price_is_rejected_in_batch_override(
|
||||
|
||||
assert resp.status_code == 422
|
||||
assert await integration_session.get(ModelRow, ("odd-batch", provider_id)) is None
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@pytest.mark.asyncio
|
||||
async def test_admin_model_listing_shows_a_non_finite_stored_rate(
|
||||
integration_client: AsyncClient, integration_session: AsyncSession
|
||||
) -> None:
|
||||
"""The operator must be able to see the rate that needs fixing.
|
||||
|
||||
The admin listing deliberately includes disabled models, so it is the one
|
||||
view that still carries a row the served-catalog backstop holds back.
|
||||
FastAPI's encoder rendered a stored ``Infinity`` rate as ``null``, which is
|
||||
indistinguishable from a rate the row never carried — the operator could see
|
||||
the row but not the reason it was withheld. Render the offending value as
|
||||
text instead, as the 422 handler already does.
|
||||
"""
|
||||
provider_id = await _make_provider(integration_session)
|
||||
integration_session.add(
|
||||
ModelRow(
|
||||
id="inf-rate",
|
||||
name="inf-rate",
|
||||
description="d",
|
||||
created=0,
|
||||
context_length=8192,
|
||||
architecture=json.dumps(
|
||||
{
|
||||
"modality": "text",
|
||||
"input_modalities": ["text"],
|
||||
"output_modalities": ["text"],
|
||||
"tokenizer": "unknown",
|
||||
"instruct_type": None,
|
||||
}
|
||||
),
|
||||
pricing=json.dumps({"prompt": float("inf"), "completion": 2e-06}),
|
||||
upstream_provider_id=provider_id,
|
||||
enabled=True,
|
||||
forwarded_model_id="inf-rate",
|
||||
)
|
||||
)
|
||||
await integration_session.commit()
|
||||
|
||||
resp = await integration_client.get(
|
||||
f"/admin/api/upstream-providers/{provider_id}/models",
|
||||
headers=_admin_headers(),
|
||||
)
|
||||
|
||||
assert resp.status_code == 200
|
||||
listed = {m["id"]: m for m in resp.json()["db_models"]}
|
||||
assert listed["inf-rate"]["pricing"]["prompt"] == "inf"
|
||||
|
||||
Reference in New Issue
Block a user