From a191c0fd21e35d3863ce464b155866fada857d1a Mon Sep 17 00:00:00 2001 From: mlsmaycon Date: Mon, 24 Aug 2026 08:39:02 +0000 Subject: [PATCH] Keep the prices discovery returns for a loaded model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Loading a provider's models merged anything the catalog did not already carry by exact id, and hardcoded both rates to zero on the way in. The comment gave the reason: the discovery response carried no prices. That stopped being true when the endpoint began returning the same rates the proxy bills with. Bedrock feels all of it. Its listing returns geography-prefixed ids — eu.anthropic.claude-opus-4-7 — while the catalog holds the bare anthropic.claude-opus-4-7, so no Bedrock model ever matches by string and every one of them takes this branch. Selecting one filled its row with $0, and the form then warned that the model had no cost set, while the API had reported a rate for it. Usage against it records nothing. Exact-id matching stays. Collapsing a geography-prefixed id onto its catalog entry would hand back the bare form, and only the prefixed one is invocable at AWS. --- src/modules/agent-network/AIProviderModal.tsx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/modules/agent-network/AIProviderModal.tsx b/src/modules/agent-network/AIProviderModal.tsx index 75f0600a..1d13c3ac 100644 --- a/src/modules/agent-network/AIProviderModal.tsx +++ b/src/modules/agent-network/AIProviderModal.tsx @@ -567,8 +567,8 @@ export default function AIProviderModal({ // catalog does not already carry. Both the per-row picker and "Add More" // read this one list, so merging here is all the wiring either needs. // - // A catalog entry wins on collision — it carries prices, and the discovery - // response deliberately carries none. + // A catalog entry wins on collision. Both sides price from the same table, + // so their rates agree; the catalog's label is the curated one. const catalogModelOptions = useMemo(() => { const base = catalog?.models ?? []; if (discovered.models.length === 0) return base; @@ -579,8 +579,17 @@ export default function AIProviderModal({ .map((m) => ({ id: m.id, label: m.label || m.id, - input_per_1k: 0, - output_per_1k: 0, + // The rates the response carries. Bedrock is why this matters: its + // listing returns geography-prefixed ids, which never match a catalog + // entry by string, so every one of them arrives through this branch. + // The backend prices them off the normalized id and reports the rate + // for each — dropping it here registered a whole account's models at + // zero while the API was saying what they cost. + input_per_1k: m.input_per_1k, + output_per_1k: m.output_per_1k, + cached_input_per_1k: m.cached_input_per_1k, + cache_read_per_1k: m.cache_read_per_1k, + cache_creation_per_1k: m.cache_creation_per_1k, pricing_known: m.pricing_known, })); return [...base, ...extra];