From 89fbd6f896b9d309fbd83af882583a454ecab77c Mon Sep 17 00:00:00 2001 From: olddonkey Date: Tue, 18 Aug 2026 18:20:31 -0700 Subject: [PATCH 1/5] feat(openrouter): enable Fast on the OpenAI-backed slugs, without route pinning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase B2 of the FastWire umbrella (lidge-jun/opencodex#1886), and a documented correction to what that issue proposed. The umbrella specified an atomic route pin for OpenRouter — only inject a tier alongside `provider: { only: [...], allow_fallbacks: false }` — to stop a tier reaching an upstream that would silently bill for it. OpenRouter's own documentation retires that requirement, and shows the proposal would not even have worked: - Tier endpoints are separate suffixed slugs (`openai/priority`), and they are explicitly NOT matched by base slugs. Pinning `only: ["openai"]` would have excluded the very endpoint that serves priority. - Priority tries tier endpoints first and falls back otherwise, and billing always follows the endpoint actually used — so the silent-overbilling risk the pin existed to prevent does not exist. - The response reports the tier actually served. Pinning would therefore have turned a graceful capacity fallback into a hard failure while protecting against nothing. Downgrade safety instead rests on B0's confirmation model, which was built for exactly this contract. What this adds: - The three OpenAI-backed slugs we ship get exact-model capability. The provider stays unclassified, and `anthropic/claude-sonnet-5` is left out because OpenRouter does not list Anthropic among its priority upstreams. - Registry model capability is now guarded by destination. A provider merely named `openrouter` but pointed at someone's own gateway must not inherit evidence gathered about openrouter.ai, and OpenRouter's endpoint is fixed, so the guard reads the operator's configured base URL rather than the routed one. Catalog and runtime both feed it that same configured value, keeping A1's one-resolver invariant intact. - The Chat surface finally reads the upstream's `service_tier` echo, closing the gap B0 left open. Without it every OpenRouter Fast request would have recorded `assumed` even when OpenRouter told us it had fallen back to standard. - A confirmed priority result with no bundled tier price is now billed at the standard rate but flagged a floor rather than silently reported as exact: OpenRouter documents priority as "faster, higher cost", so standard is provably a lower bound. Scoped to canonical priority only — flex is cheaper, so the same argument would be false there. A first attempt scoped capability with the registry's `preserveCustomDestination` flag. It worked, but that flag also decides provider claiming and hosted-tool preference validation, and the full suite caught it changing which configs `openrouter` accepts. The destination guard above replaces it and touches nothing outside FastWire. Full suite: 13361 pass / 10 skip / 1 fail — the pre-existing dev-side key-login-live-update regression, which reproduces on pristine dev. Co-Authored-By: Claude Fable 5 --- .../docs/reference/configuration/providers.md | 29 +++ gui/src/i18n/de.ts | 1 + gui/src/i18n/en.ts | 1 + gui/src/i18n/fr.ts | 1 + gui/src/i18n/ja.ts | 1 + gui/src/i18n/ko.ts | 1 + gui/src/i18n/ru.ts | 1 + gui/src/i18n/tr.ts | 1 + gui/src/i18n/zh-TW.ts | 1 + gui/src/i18n/zh.ts | 1 + gui/src/pages/Logs.tsx | 44 ++-- gui/src/pages/logs-cost-format.ts | 11 + gui/tests/logs-priority-lower-bound.test.ts | 12 + src/adapters/base.ts | 16 +- src/adapters/openai-chat.ts | 33 ++- src/codex/catalog/provider-fetch.ts | 1 + src/config.ts | 5 +- src/providers/derive.ts | 14 +- src/providers/registry.ts | 43 +++- src/providers/service-tier.ts | 41 +++- src/router.ts | 10 +- src/routing/compatibility/behavior.ts | 6 +- src/server/management/shared.ts | 4 +- src/server/responses/core.ts | 17 +- src/usage/cost.ts | 32 ++- tests/fastwire-observability.test.ts | 216 +++++++++++++++++- tests/service-tier-capability.test.ts | 83 ++++++- 27 files changed, 579 insertions(+), 47 deletions(-) create mode 100644 gui/src/pages/logs-cost-format.ts create mode 100644 gui/tests/logs-priority-lower-bound.test.ts diff --git a/docs-site/src/content/docs/reference/configuration/providers.md b/docs-site/src/content/docs/reference/configuration/providers.md index 2c1d2e3eef..900c29e8c1 100644 --- a/docs-site/src/content/docs/reference/configuration/providers.md +++ b/docs-site/src/content/docs/reference/configuration/providers.md @@ -151,6 +151,35 @@ contract; existing configurations see these migration deltas: Explicit capability `false` and Responses caller-tier forwarding retain their existing contracts. +### OpenRouter Fast + +The canonical `https://openrouter.ai/api/v1` preset advertises Fast only for these exact +OpenAI-backed model slugs: + +- `openai/gpt-5.6-sol` +- `openai/gpt-5.6-terra` +- `openai/gpt-5.6-luna` + +`anthropic/claude-sonnet-5` and undeclared OpenRouter models remain unclassified. A provider-level +`supportsServiceTier` default is intentionally absent, and a user-set `supportsServiceTier: false` +still disables the exact-model declarations. The registry declarations apply only while the +provider still targets the canonical OpenRouter base URL; a same-named custom destination is not +assumed to share OpenRouter's contract. + +Fast sends `service_tier: "priority"`. It does not add or rewrite `provider.only`, +`provider.order`, or `provider.allow_fallbacks`. OpenRouter documents priority endpoints as the +first routing choice, followed by graceful fallback to other endpoints when priority capacity is +unavailable. Billing follows the endpoint actually used, and the response reports the actual +top-level `service_tier`. Pinning tier endpoints and disabling fallback would therefore reduce +availability without improving billing safety. + +Request logs use that response echo as the authority. `priority` confirms Fast as applied; +`default` records a downgrade and uses the standard-price estimate; a missing field leaves the +attempt assumed rather than guessing a downgrade. OpenRouter's priority multiplier varies by +upstream and is not bundled here. When priority is confirmed but no exact priority price is known, +the dashboard keeps the standard-price estimate as a documented lower bound and prefixes it with +`≥`; downgraded attempts have no lower-bound marker. + API-key providers may hold a literal key or an environment reference. OAuth providers use the credential store populated by `ocx login`; subscription-backed Claude Code launch behavior is configured under [`claudeCode.authMode`](/reference/configuration/server/#claude-code). diff --git a/gui/src/i18n/de.ts b/gui/src/i18n/de.ts index 5637644402..6405dff15c 100644 --- a/gui/src/i18n/de.ts +++ b/gui/src/i18n/de.ts @@ -711,6 +711,7 @@ export const de: Record = { "logs.detail.estimate.cache_detail_missing": "Cache-Details fehlen; Eingabe ist als Obergrenze geschätzt.", "logs.detail.estimate.expected_price_overlay": "Ein verifizierter Expected-Listenpreis wurde verwendet.", "logs.detail.estimate.provider_cost_overlay": "Ein vom Anbieter konfiguriertes Preis-Overlay wurde verwendet.", + "logs.detail.estimate.priority_lower_bound": "Der bestätigte OpenRouter-Priority-Preis ist nicht verfügbar; die angezeigte Standardpreisschätzung ist eine bekannte Untergrenze.", "logs.col.error": "Fehler", "logs.col.upstreamReason": "Upstream-Grund", "logs.col.duration": "Dauer", diff --git a/gui/src/i18n/en.ts b/gui/src/i18n/en.ts index 6256742991..6600769d66 100644 --- a/gui/src/i18n/en.ts +++ b/gui/src/i18n/en.ts @@ -744,6 +744,7 @@ export const en = { "logs.detail.estimate.cache_detail_missing": "Cache details were unavailable; input is an upper-bound estimate.", "logs.detail.estimate.expected_price_overlay": "A verified expected list price was used.", "logs.detail.estimate.provider_cost_overlay": "A provider-configured price overlay was used.", + "logs.detail.estimate.priority_lower_bound": "The confirmed OpenRouter priority price is unavailable; the displayed standard-price estimate is a known lower bound.", "logs.col.error": "Error", "logs.col.upstreamReason": "Upstream reason", "logs.col.duration": "Duration", diff --git a/gui/src/i18n/fr.ts b/gui/src/i18n/fr.ts index 98b503fd25..71057339fe 100644 --- a/gui/src/i18n/fr.ts +++ b/gui/src/i18n/fr.ts @@ -725,6 +725,7 @@ export const fr: Record = { "logs.detail.estimate.cache_detail_missing": "Les détails du cache n’étaient pas disponibles ; l’entrée est une estimation de la limite supérieure.", "logs.detail.estimate.expected_price_overlay": "Un tarif catalogue attendu et vérifié a été utilisé.", "logs.detail.estimate.provider_cost_overlay": "Un remplacement de tarif configuré pour le fournisseur a été utilisé.", + "logs.detail.estimate.priority_lower_bound": "Le tarif Priority OpenRouter confirmé n’est pas disponible ; l’estimation au tarif standard affichée est une borne inférieure connue.", "logs.col.error": "Erreur", "logs.col.upstreamReason": "Motif en amont", "logs.col.duration": "Durée", diff --git a/gui/src/i18n/ja.ts b/gui/src/i18n/ja.ts index 07e011548d..dd4fcdac63 100644 --- a/gui/src/i18n/ja.ts +++ b/gui/src/i18n/ja.ts @@ -687,6 +687,7 @@ export const ja: Record = { "logs.detail.estimate.cache_detail_missing": "キャッシュの詳細が利用できませんでした; 入力は上限の推定です。", "logs.detail.estimate.expected_price_overlay": "検証済みの予想定価が使用されました。", "logs.detail.estimate.provider_cost_overlay": "プロバイダー設定の価格オーバーレイが使用されました。", + "logs.detail.estimate.priority_lower_bound": "確認済みの OpenRouter Priority 価格は取得できないため、表示される標準価格の見積もりは既知の下限です。", "logs.col.error": "エラー", "logs.col.upstreamReason": "上流の理由", "logs.col.duration": "所要時間", diff --git a/gui/src/i18n/ko.ts b/gui/src/i18n/ko.ts index 93ffebf949..0b35335f48 100644 --- a/gui/src/i18n/ko.ts +++ b/gui/src/i18n/ko.ts @@ -730,6 +730,7 @@ export const ko: Record = { "logs.detail.estimate.cache_detail_missing": "캐시 상세가 없어 입력 전액을 상한으로 추정했습니다.", "logs.detail.estimate.expected_price_overlay": "검증된 expected 정가를 사용했습니다.", "logs.detail.estimate.provider_cost_overlay": "프로바이더 구성 가격 오버레이를 사용했습니다.", + "logs.detail.estimate.priority_lower_bound": "확인된 OpenRouter Priority 가격을 사용할 수 없어 표시된 표준 가격 추정치는 알려진 하한입니다.", "logs.col.error": "오류", "logs.col.upstreamReason": "업스트림 원인", "logs.col.duration": "소요 시간", diff --git a/gui/src/i18n/ru.ts b/gui/src/i18n/ru.ts index d92f2ca9c5..04198c5bc9 100644 --- a/gui/src/i18n/ru.ts +++ b/gui/src/i18n/ru.ts @@ -728,6 +728,7 @@ export const ru: Record = { "logs.detail.estimate.cache_detail_missing": "Детализация кэша недоступна; входные токены оценены по верхней границе.", "logs.detail.estimate.expected_price_overlay": "Использована подтверждённая ожидаемая цена из прайс-листа.", "logs.detail.estimate.provider_cost_overlay": "Использован ценовой оверлей провайдера.", + "logs.detail.estimate.priority_lower_bound": "Подтверждённая цена OpenRouter Priority недоступна; показанная оценка по стандартной цене является известной нижней границей.", "logs.col.error": "Ошибка", "logs.col.upstreamReason": "Причина от провайдера", "logs.col.duration": "Длительность", diff --git a/gui/src/i18n/tr.ts b/gui/src/i18n/tr.ts index 0db71ce089..db6493be81 100644 --- a/gui/src/i18n/tr.ts +++ b/gui/src/i18n/tr.ts @@ -735,6 +735,7 @@ export const tr: Record = { "logs.detail.estimate.cache_detail_missing": "Önbellek detayları eksik.", "logs.detail.estimate.expected_price_overlay": "Doğrulanmış liste fiyatı kullanıldı.", "logs.detail.estimate.provider_cost_overlay": "Kullanıcı tarafından yapılandırılan bir sağlayıcı fiyat katmanı kullanıldı.", + "logs.detail.estimate.priority_lower_bound": "Doğrulanan OpenRouter Priority fiyatı kullanılamıyor; gösterilen standart fiyat tahmini bilinen bir alt sınırdır.", "logs.col.error": "Hata", "logs.col.upstreamReason": "Yukarı akış nedeni", "logs.col.duration": "Süre", diff --git a/gui/src/i18n/zh-TW.ts b/gui/src/i18n/zh-TW.ts index dba3c64621..e7d58be32b 100644 --- a/gui/src/i18n/zh-TW.ts +++ b/gui/src/i18n/zh-TW.ts @@ -1805,6 +1805,7 @@ export const zhTW: Record = { "logs.detail.attempt.recovery.emptyCompletion": "空白完成重試", "logs.detail.attempt.recovery.unknown": "未知的復原原因", "logs.detail.estimate.provider_cost_overlay": "已使用供應商設定的價格覆蓋。", + "logs.detail.estimate.priority_lower_bound": "無法取得已確認的 OpenRouter Priority 價格;目前顯示的標準價格估算是已知下限。", "pws.cockpitImportDescription": "從此裝置匯入 Cockpit Tools Antigravity JSON 匯出檔。不會顯示檔案內容。", "pws.cockpitImportFileLabel": "Cockpit Tools Antigravity JSON 匯出檔", "pws.cockpitImportChooseFile": "選擇 JSON 檔案", diff --git a/gui/src/i18n/zh.ts b/gui/src/i18n/zh.ts index 0499b83ff3..e98836763a 100644 --- a/gui/src/i18n/zh.ts +++ b/gui/src/i18n/zh.ts @@ -723,6 +723,7 @@ export const zh: Record = { "logs.detail.estimate.cache_detail_missing": "缺少缓存明细;输入费用按上限估算。", "logs.detail.estimate.expected_price_overlay": "使用了已验证的 Expected 标价。", "logs.detail.estimate.provider_cost_overlay": "使用了用户配置的提供方价格覆盖。", + "logs.detail.estimate.priority_lower_bound": "暂无已确认的 OpenRouter Priority 价格;当前显示的标准价估算是已知下界。", "logs.col.error": "错误", "logs.col.upstreamReason": "上游原因", "logs.col.duration": "耗时", diff --git a/gui/src/pages/Logs.tsx b/gui/src/pages/Logs.tsx index b7acbb4d02..fef77bc9ac 100644 --- a/gui/src/pages/Logs.tsx +++ b/gui/src/pages/Logs.tsx @@ -17,6 +17,7 @@ import type { LogsTab } from "./logs-tab-keydown"; import { logsTabKeyDown, readTabFromHash, selectLogsTab } from "./logs-tab-keydown"; import { modelTitle } from "./logs-model-title"; import { speedLabel } from "./logs-speed-label"; +import { formatEstimatedUsdValue } from "./logs-cost-format"; import { cacheSplit, isCursorUsageProvider, tokensTitle } from "./logs-token-title"; import type { LogSurface, LogSurfaceFilter } from "./logs-surface-filter"; import { logMatchesSurface } from "./logs-surface-filter"; @@ -53,7 +54,8 @@ type CostEstimateReason = | "usage_estimated" | "cache_detail_missing" | "expected_price_overlay" - | "provider_cost_overlay"; + | "provider_cost_overlay" + | "priority_lower_bound"; type TokPerSecondResult = | { kind: "value"; value: number; estimated: boolean } @@ -75,6 +77,7 @@ type CostResult = estimate: { cost: { input: number; output: number; cacheRead: number; cacheWrite: number; total: number }; estimated: boolean; + priorityLowerBound?: boolean; price?: MatchedPriceInfo; attempts?: Array<{ ordinal: number; price: MatchedPriceInfo }>; }; @@ -240,20 +243,12 @@ function formatTokPerSecond(result: TokPerSecondResult | undefined, localeTag?: function formatEstimatedUsd(result: CostResult | undefined, localeTag?: string): string { if (!result || result.kind === "unavailable" || !Number.isFinite(result.estimate.cost.total) || result.estimate.cost.total < 0) return "\u2014"; const totalUsd = result.estimate.cost.total; - return `~$${new Intl.NumberFormat(localeTag, { + return `${result.estimate.priorityLowerBound ? "≥" : ""}~$${new Intl.NumberFormat(localeTag, { minimumFractionDigits: 4, maximumFractionDigits: 4, }).format(totalUsd)}`; } -function formatEstimatedUsdValue(value: number, localeTag?: string): string { - if (!Number.isFinite(value) || value < 0) return "\u2014"; - return `~$${new Intl.NumberFormat(localeTag, { - minimumFractionDigits: 4, - maximumFractionDigits: 4, - }).format(value)}`; -} - /** Consecutive failed polls before a stale table is called out. Two seconds each, so ~6s. */ const STALE_POLL_FAILURE_LIMIT = 3; @@ -273,6 +268,7 @@ const ESTIMATE_REASON_KEYS = { cache_detail_missing: "logs.detail.estimate.cache_detail_missing", expected_price_overlay: "logs.detail.estimate.expected_price_overlay", provider_cost_overlay: "logs.detail.estimate.provider_cost_overlay", + priority_lower_bound: "logs.detail.estimate.priority_lower_bound", } as const satisfies Record; /** @@ -345,11 +341,13 @@ function summarizeFilteredLogs(entries: LogEntry[]): { requests: number; totalTokens: number; estimatedCostUsd: number; + priorityLowerBound: boolean; unpricedRequests: number; unmeteredRequests: number; } { let totalTokens = 0; let estimatedCostUsd = 0; + let priorityLowerBound = false; let unpricedRequests = 0; let unmeteredRequests = 0; for (const entry of entries) { @@ -363,11 +361,19 @@ function summarizeFilteredLogs(entries: LogEntry[]): { const total = cost?.kind === "value" ? cost.estimate.cost.total : undefined; if (total !== undefined && Number.isFinite(total) && total >= 0) { estimatedCostUsd += total; + priorityLowerBound ||= cost?.kind === "value" && cost.estimate.priorityLowerBound === true; continue; } unpricedRequests += 1; } - return { requests: entries.length, totalTokens, estimatedCostUsd, unpricedRequests, unmeteredRequests }; + return { + requests: entries.length, + totalTokens, + estimatedCostUsd, + priorityLowerBound, + unpricedRequests, + unmeteredRequests, + }; } export default function Logs({ apiBase }: { apiBase: string }) { @@ -612,7 +618,11 @@ export default function Logs({ apiBase }: { apiBase: string }) { {t("logs.conversation.totals", { requests: conversationTotals.requests, tokens: formatTokens(conversationTotals.totalTokens, localeTag ?? locale), - cost: formatEstimatedUsdValue(conversationTotals.estimatedCostUsd, localeTag), + cost: formatEstimatedUsdValue( + conversationTotals.estimatedCostUsd, + localeTag, + conversationTotals.priorityLowerBound, + ), })} {" "} @@ -956,11 +966,11 @@ function LogDetailDialog({ {cost?.kind === "value" ? ( <>
- {t("logs.detail.costTotal")}{formatEstimatedUsdValue(cost.estimate.cost.total, localeTag)} - {t("logs.tokens.input")}{formatEstimatedUsdValue(cost.estimate.cost.input, localeTag)} - {t("logs.tokens.cacheRead")}{formatEstimatedUsdValue(cost.estimate.cost.cacheRead, localeTag)} - {t("logs.tokens.cacheWrite")}{formatEstimatedUsdValue(cost.estimate.cost.cacheWrite, localeTag)} - {t("logs.tokens.output")}{formatEstimatedUsdValue(cost.estimate.cost.output, localeTag)} + {t("logs.detail.costTotal")}{formatEstimatedUsdValue(cost.estimate.cost.total, localeTag, cost.estimate.priorityLowerBound)} + {t("logs.tokens.input")}{formatEstimatedUsdValue(cost.estimate.cost.input, localeTag, cost.estimate.priorityLowerBound)} + {t("logs.tokens.cacheRead")}{formatEstimatedUsdValue(cost.estimate.cost.cacheRead, localeTag, cost.estimate.priorityLowerBound)} + {t("logs.tokens.cacheWrite")}{formatEstimatedUsdValue(cost.estimate.cost.cacheWrite, localeTag, cost.estimate.priorityLowerBound)} + {t("logs.tokens.output")}{formatEstimatedUsdValue(cost.estimate.cost.output, localeTag, cost.estimate.priorityLowerBound)} {cost.estimate.price && ( <> {t("logs.detail.matchedKey")} diff --git a/gui/src/pages/logs-cost-format.ts b/gui/src/pages/logs-cost-format.ts new file mode 100644 index 0000000000..0997737896 --- /dev/null +++ b/gui/src/pages/logs-cost-format.ts @@ -0,0 +1,11 @@ +export function formatEstimatedUsdValue( + value: number, + localeTag?: string, + priorityLowerBound = false, +): string { + if (!Number.isFinite(value) || value < 0) return "\u2014"; + return `${priorityLowerBound ? "≥" : ""}~$${new Intl.NumberFormat(localeTag, { + minimumFractionDigits: 4, + maximumFractionDigits: 4, + }).format(value)}`; +} diff --git a/gui/tests/logs-priority-lower-bound.test.ts b/gui/tests/logs-priority-lower-bound.test.ts new file mode 100644 index 0000000000..6117bcfdd3 --- /dev/null +++ b/gui/tests/logs-priority-lower-bound.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, test } from "bun:test"; +import { formatEstimatedUsdValue } from "../src/pages/logs-cost-format"; + +describe("Logs priority lower-bound formatting", () => { + test("prefixes confirmed unpriced priority estimates with the lower-bound marker", () => { + expect(formatEstimatedUsdValue(1.6, "en-US", true)).toBe("≥~$1.6000"); + }); + + test("keeps ordinary standard-price estimates unchanged", () => { + expect(formatEstimatedUsdValue(1.6, "en-US", false)).toBe("~$1.6000"); + }); +}); diff --git a/src/adapters/base.ts b/src/adapters/base.ts index 06b5f6f087..6ffc420a05 100644 --- a/src/adapters/base.ts +++ b/src/adapters/base.ts @@ -33,8 +33,20 @@ export interface ProviderAdapter { fetchResponse?(request: AdapterRequest, ctx?: AdapterFetchContext): Promise; - parseStream(response: Response, budget: TranslatorBudget): AsyncGenerator; - parseResponse?(response: Response, budget: TranslatorBudget): Promise; + /** + * Parse one upstream response. `tierMetadata` is the same live observer returned on the + * corresponding AdapterRequest; adapters that receive a documented tier echo may update it. + */ + parseStream( + response: Response, + budget: TranslatorBudget, + tierMetadata?: AdapterTierMetadata, + ): AsyncGenerator; + parseResponse?( + response: Response, + budget: TranslatorBudget, + tierMetadata?: AdapterTierMetadata, + ): Promise; runTurn?( parsed: OcxParsedRequest, incoming: IncomingMeta, diff --git a/src/adapters/openai-chat.ts b/src/adapters/openai-chat.ts index a6d13fa1f4..c26537336a 100644 --- a/src/adapters/openai-chat.ts +++ b/src/adapters/openai-chat.ts @@ -19,6 +19,7 @@ import { import { canonicalFastTierMarker, createAdapterTierMetadata, + type AdapterTierMetadata, } from "../providers/fastwire"; import { openaiChatCompletionsUrl } from "./openai-chat-url"; import { stripResponsesOnlyEncryptedMarker } from "./responses-tool-schema"; @@ -1474,7 +1475,11 @@ export function createOpenAIChatAdapter(provider: OcxProviderConfig): ProviderAd }; }, - async *parseStream(response: Response, budget: TranslatorBudget): AsyncGenerator { + async *parseStream( + response: Response, + budget: TranslatorBudget, + tierMetadata?: AdapterTierMetadata, + ): AsyncGenerator { if (!response.body) { yield { type: "error", message: "No response body" }; return; @@ -1543,11 +1548,15 @@ export function createOpenAIChatAdapter(provider: OcxProviderConfig): ProviderAd try { parsed = JSON.parse(payload); } catch { + tierMetadata?.markResponseUnparseable(); yield { type: "error", message: "malformed upstream SSE data frame" }; return "terminate"; } if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return "continue"; const chunk = parsed as Record; + if (Object.hasOwn(chunk, "service_tier")) { + tierMetadata?.observeResponseServiceTier(chunk.service_tier); + } if (chunk.error !== undefined && chunk.error !== null) { const event = upstreamErrorEvent(chunk.error, pendingUsage); @@ -1748,8 +1757,26 @@ export function createOpenAIChatAdapter(provider: OcxProviderConfig): ProviderAd } }, - async parseResponse(response: Response, budget: TranslatorBudget): Promise { - const json = await response.json() as Record; + async parseResponse( + response: Response, + budget: TranslatorBudget, + tierMetadata?: AdapterTierMetadata, + ): Promise { + let parsed: unknown; + try { + parsed = await response.json(); + } catch (error) { + tierMetadata?.markResponseUnparseable(); + throw error; + } + if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) { + tierMetadata?.markResponseUnparseable(); + throw new Error("upstream response was not a JSON object"); + } + const json = parsed as Record; + if (Object.hasOwn(json, "service_tier")) { + tierMetadata?.observeResponseServiceTier(json.service_tier); + } const responseBytes = new TextEncoder().encode(JSON.stringify(json)).byteLength; budget.chargeRetained(responseBytes, { kind: "retained_collectors" }); try { diff --git a/src/codex/catalog/provider-fetch.ts b/src/codex/catalog/provider-fetch.ts index 69203c8940..225c1cb558 100644 --- a/src/codex/catalog/provider-fetch.ts +++ b/src/codex/catalog/provider-fetch.ts @@ -413,6 +413,7 @@ function captureProviderGather( name, provider, registryTransportMatch, + configured, ); const observedAuth = authResolver.kind === "observed" && provider.authMode !== "forward" diff --git a/src/config.ts b/src/config.ts index 4d5547f5fd..a0fa0a3b25 100644 --- a/src/config.ts +++ b/src/config.ts @@ -74,6 +74,7 @@ import { getProviderRegistryEntry, providerMatchesRegistryTransport, providerModelWireDefault, + registryModelServiceTierCapabilityApplies, } from "./providers/registry"; import { resolveOpenAiVirtualModel } from "./providers/openai-virtual-models"; import { parseDesktopProfile } from "./claude/desktop-profile"; @@ -2159,7 +2160,9 @@ function inheritedFastWireConflictProviderNames( if (!registry) continue; const effectiveProviderCapability = provider.supportsServiceTier ?? registry.supportsServiceTier; const effectiveModelCapabilities = { - ...(registry.modelSupportsServiceTier ?? {}), + ...(registryModelServiceTierCapabilityApplies(registry, provider) + ? registry.modelSupportsServiceTier ?? {} + : {}), ...(provider.modelSupportsServiceTier ?? {}), }; if ( diff --git a/src/providers/derive.ts b/src/providers/derive.ts index c5e08065b3..3db91f73df 100644 --- a/src/providers/derive.ts +++ b/src/providers/derive.ts @@ -3,6 +3,7 @@ import { cloneFastWire } from "./fastwire"; import { PROVIDER_REGISTRY, registryEntryForProviderDestination, + registryModelServiceTierCapabilityApplies, type ProviderRegistryEntry, } from "./registry"; import { @@ -377,6 +378,15 @@ function applyServiceTierModelDefaults( }; } +function serviceTierModelDefaultsFor( + entry: ProviderRegistryEntry | undefined, + prov: OcxProviderConfig, +): Readonly> | undefined { + return entry && registryModelServiceTierCapabilityApplies(entry, prov) + ? entry.modelSupportsServiceTier + : undefined; +} + /** * Last-resort enrichment for a provider whose NAME matches no registry id. * @@ -412,7 +422,7 @@ export function enrichProviderFromRegistry(name: string, prov: OcxProviderConfig // which vendor endpoint is this row talking to — and is already restricted to fixed key // destinations, so a templated or overridable base URL cannot be claimed by it. enrichReasoningSummariesByDestination(prov); - applyServiceTierModelDefaults(prov, registryEntryForProviderDestination(prov)?.modelSupportsServiceTier); + applyServiceTierModelDefaults(prov, serviceTierModelDefaultsFor(registryEntryForProviderDestination(prov), prov)); return; } const explicitDirectReasoning: DirectReasoningEffortOverrides = { @@ -466,7 +476,7 @@ export function enrichProviderFromRegistry(name: string, prov: OcxProviderConfig if (prov.supportsServiceTier === undefined && entry.supportsServiceTier !== undefined) prov.supportsServiceTier = entry.supportsServiceTier; if (prov.preserveResponsesReasoningContent === undefined && entry.preserveResponsesReasoningContent !== undefined) prov.preserveResponsesReasoningContent = entry.preserveResponsesReasoningContent; applyReasoningSummaryDefaults(prov, entry.modelSupportsReasoningSummaries); - applyServiceTierModelDefaults(prov, entry.modelSupportsServiceTier); + applyServiceTierModelDefaults(prov, serviceTierModelDefaultsFor(entry, prov)); // Registry-only repair policy (#938): fill only when the runtime provider has // no explicit policy, and deep-clone so saved/user values never alias the // registry constant. diff --git a/src/providers/registry.ts b/src/providers/registry.ts index c81735ba15..364478143d 100644 --- a/src/providers/registry.ts +++ b/src/providers/registry.ts @@ -17,6 +17,7 @@ import { cursorModelReasoningEfforts, } from "../adapters/cursor/discovery"; import { COMMAND_CODE_MODEL_REASONING_EFFORTS } from "./command-code-efforts"; +import { isCanonicalOpenRouterTarget } from "./openrouter-routing"; export type ProviderAuthKind = "forward" | "oauth" | "key" | "local"; export type MetadataModelIdNormalize = "case-insensitive"; @@ -217,6 +218,11 @@ export interface ProviderRegistryEntry { supportsServiceTier?: boolean; /** Registry default for exact model service-tier capability; explicit config keys win. */ modelSupportsServiceTier?: Record; + /** + * Registry-only destination guard for `modelSupportsServiceTier`. This scopes vendor evidence + * without changing provider ownership, routing, authentication, or config validation. + */ + modelServiceTierCapabilityBaseUrlGuard?: (baseUrl: string) => boolean; /** Registry default for plaintext reasoning replay; see `OcxProviderConfig.preserveResponsesReasoningContent`. Registry-only like `supportsServiceTier`. */ preserveResponsesReasoningContent?: boolean; /** Registry defaults for per-model Codex reasoning propagation; explicit user keys win during enrichment. */ @@ -1349,7 +1355,33 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [ autoToolChoiceOnlyModels: ["kimi-k2.7-code"], preserveReasoningContentModels: NEURALWATT_REASONING_HISTORY_MODELS, }, - { id: "openrouter", label: "OpenRouter", adapter: "openai-chat", baseUrl: "https://openrouter.ai/api/v1", authKind: "key", featured: true, dashboardUrl: "https://openrouter.ai/keys", jawcodeBundle: "openrouter", models: ["anthropic/claude-sonnet-5", ...OPENROUTER_GPT56_MODELS], modelContextWindows: { "anthropic/claude-sonnet-5": 1_000_000, ...OPENROUTER_GPT56_CONTEXT_WINDOWS } }, + { + id: "openrouter", + label: "OpenRouter", + adapter: "openai-chat", + baseUrl: "https://openrouter.ai/api/v1", + authKind: "key", + featured: true, + dashboardUrl: "https://openrouter.ai/keys", + jawcodeBundle: "openrouter", + models: ["anthropic/claude-sonnet-5", ...OPENROUTER_GPT56_MODELS], + modelContextWindows: { + "anthropic/claude-sonnet-5": 1_000_000, + ...OPENROUTER_GPT56_CONTEXT_WINDOWS, + }, + // OpenRouter documents priority support for OpenAI endpoints, but not Anthropic. Keep the + // provider unclassified and opt in only the exact OpenAI-backed slugs we ship. These facts + // belong only to the canonical destination; a same-named custom gateway is unknown to us. + modelServiceTierCapabilityBaseUrlGuard: isCanonicalOpenRouterTarget, + modelSupportsServiceTier: { + "openai/gpt-5.6-sol": true, + "openai/gpt-5.6-terra": true, + "openai/gpt-5.6-luna": true, + }, + // Deliberately no OpenRouter route pin: it bills the endpoint actually used and reports the + // actual service_tier. B0 confirmation therefore owns downgrade safety. Forcing `only` plus + // `allow_fallbacks:false` would turn a graceful priority-capacity fallback into a hard failure. + }, { // Primary sources checked 2026-08-02: // - docs.cline.bot/getting-started/clinepass publishes this exact catalog and explicitly @@ -2555,6 +2587,15 @@ export function getProviderRegistryEntry(id: string): ProviderRegistryEntry | un return PROVIDER_REGISTRY.find(entry => entry.id === id); } +/** Whether this registry row's per-model service-tier evidence applies to one configured target. */ +export function registryModelServiceTierCapabilityApplies( + entry: Pick, + provider: Pick, +): boolean { + const guard = entry.modelServiceTierCapabilityBaseUrlGuard; + return guard === undefined || guard(provider.baseUrl); +} + function normalizedProviderEndpoint(value: string): string { const trimmed = value.trim(); try { diff --git a/src/providers/service-tier.ts b/src/providers/service-tier.ts index a06c42c7b4..278f89394e 100644 --- a/src/providers/service-tier.ts +++ b/src/providers/service-tier.ts @@ -4,6 +4,7 @@ import { isCanonicalOpenAiForwardProvider } from "./openai-tiers"; import { getProviderRegistryEntry, providerMatchesRegistryTransport, + registryModelServiceTierCapabilityApplies, type InboundWire, type ModelWireDefault, } from "./registry"; @@ -57,8 +58,14 @@ function buildFastPolicyAuthority( providerName: string, provider: ServiceTierCapabilityProvider, registryTransportMatch: boolean, + capabilityProvider: ServiceTierCapabilityProvider = provider, ): FastPolicyAuthority { const registry = registryTransportMatch ? getProviderRegistryEntry(providerName) : undefined; + const registryModelCapabilities = registry + && registryModelServiceTierCapabilityApplies(registry, capabilityProvider) + ? registry.modelSupportsServiceTier + : undefined; + const providerCapability = capabilityProvider.supportsServiceTier ?? registry?.supportsServiceTier; const authority: FastPolicyAuthority = Object.freeze({ providerAdapter: provider.adapter, fastWireDeclaration: cloneFastWire( @@ -72,8 +79,11 @@ function buildFastPolicyAuthority( provider.apiKeyTransport, ), capability: Object.freeze({ - ...(provider.supportsServiceTier !== undefined ? { provider: provider.supportsServiceTier } : {}), - models: Object.freeze({ ...(provider.modelSupportsServiceTier ?? {}) }), + ...(providerCapability !== undefined ? { provider: providerCapability } : {}), + models: Object.freeze({ + ...(registryModelCapabilities ?? {}), + ...(capabilityProvider.modelSupportsServiceTier ?? {}), + }), ...(provider.chatServiceTier !== undefined ? { chatServiceTier: provider.chatServiceTier } : {}), }), modelAdapters: Object.freeze({ ...(provider.modelAdapters ?? {}) }), @@ -87,8 +97,14 @@ export function captureFastPolicyAuthority( providerName: string, provider: ServiceTierCapabilityProvider, registryTransportMatch: boolean, + capabilityProvider: ServiceTierCapabilityProvider = provider, ): FastPolicyAuthority { - const authority = buildFastPolicyAuthority(providerName, provider, registryTransportMatch); + const authority = buildFastPolicyAuthority( + providerName, + provider, + registryTransportMatch, + capabilityProvider, + ); if (Object.isFrozen(provider)) capturedFastPolicyAuthorities.set(provider, authority); return authority; } @@ -106,12 +122,13 @@ export function captureServiceTierAdapterAuthority( function authorityForProvider( provider: ServiceTierCapabilityProvider, providerName?: string, + capabilityProvider?: ServiceTierCapabilityProvider, ): FastPolicyAuthority { // Preserve the legacy no-name short circuit: serviceTierSupportForModel() used the // provider adapter directly when no provider identity was available, so no configured // override, hard pin, or registry default may participate on this path in A1. if (providerName === undefined) { - const authority = buildFastPolicyAuthority("", provider, false); + const authority = buildFastPolicyAuthority("", provider, false, capabilityProvider ?? provider); return Object.freeze({ ...authority, modelAdapters: Object.freeze({}), @@ -119,12 +136,17 @@ function authorityForProvider( registryWireDefaults: Object.freeze({}), }); } - const captured = Object.isFrozen(provider) + const captured = capabilityProvider === undefined && Object.isFrozen(provider) ? capturedFastPolicyAuthorities.get(provider) : undefined; if (captured) return captured; const registryTransportMatch = providerMatchesRegistryTransport(providerName, provider); - const authority = buildFastPolicyAuthority(providerName, provider, registryTransportMatch); + const authority = buildFastPolicyAuthority( + providerName, + provider, + registryTransportMatch, + capabilityProvider ?? provider, + ); // Frozen provider snapshots cannot drift, so repeated catalog/runtime projections may safely // reuse the registry lookup and detached declaration maps. Mutable configs still rebuild. if (Object.isFrozen(provider)) capturedFastPolicyAuthorities.set(provider, authority); @@ -137,8 +159,13 @@ export function fastPolicyForModel( modelId: string, providerName?: string, inbound: InboundWire = "responses", + capabilityProvider?: ServiceTierCapabilityProvider, ): ResolvedFastPolicy { - return resolveFastPolicy(authorityForProvider(provider, providerName), modelId, inbound); + return resolveFastPolicy( + authorityForProvider(provider, providerName, capabilityProvider), + modelId, + inbound, + ); } /** diff --git a/src/router.ts b/src/router.ts index 723ff8ca84..be06d6c478 100644 --- a/src/router.ts +++ b/src/router.ts @@ -11,7 +11,11 @@ import type { NormalizedComboConfig } from "./combos/types"; import { hasOwnProvider, resolveEnvValue } from "./config"; import { assertProviderDestinationAllowed } from "./lib/destination-policy"; import { redactSecretString, redactUrlForLog } from "./lib/redact"; -import { PROVIDER_REGISTRY, providerCodexAccountMode } from "./providers/registry"; +import { + PROVIDER_REGISTRY, + providerCodexAccountMode, + registryModelServiceTierCapabilityApplies, +} from "./providers/registry"; import { applyDirectReasoningEffortContracts, hasLegacyClinePassReasoningEfforts } from "./providers/derive"; import { cloneFastWire } from "./providers/fastwire"; import { @@ -296,7 +300,9 @@ export function routedProviderConfig(providerName: string, provider: OcxProvider : mergeRecordFill(registryEntry.modelMaxInputTokens, provider.modelMaxInputTokens); const modelMaxOutputTokens = mergeRecordFill(registryEntry.modelMaxOutputTokens, provider.modelMaxOutputTokens); const modelSupportsServiceTier = mergeRecordFill( - registryEntry.modelSupportsServiceTier, + registryModelServiceTierCapabilityApplies(registryEntry, provider) + ? registryEntry.modelSupportsServiceTier + : undefined, provider.modelSupportsServiceTier, ); const noVisionModels = mergeStringArray(registryEntry.noVisionModels, provider.noVisionModels); diff --git a/src/routing/compatibility/behavior.ts b/src/routing/compatibility/behavior.ts index 553e531bb1..434aada342 100644 --- a/src/routing/compatibility/behavior.ts +++ b/src/routing/compatibility/behavior.ts @@ -1,6 +1,6 @@ import type { OcxConfig, OcxProviderConfig } from "../../types"; import { PROVIDER_REGISTRY } from "../../providers/registry"; -import { fastPolicyForModel, serviceTierSupportForModel } from "../../providers/service-tier"; +import { fastPolicyForModel, serviceTierSupportFromPolicy } from "../../providers/service-tier"; import { resolveProviderAuthTransport } from "../../providers/fastwire"; import { localFingerprint } from "../../lab/digest"; import type { LabBehaviorSource, LabBehaviorValues } from "../../lab/live/types"; @@ -93,7 +93,7 @@ export function resolveProductionBehaviorValues( const project = typeof effective.project === "string" && effective.project ? effective.project : null; const location = typeof effective.location === "string" && effective.location ? effective.location : null; const nativeLocalExec = effective.nativeLocalExec === "on" || effective.unsafeAllowNativeLocalExec === true; - const fastPolicy = fastPolicyForModel(effective, modelId, providerName); + const fastPolicy = fastPolicyForModel(effective, modelId, providerName, "responses", provider); const values: LabBehaviorValues = { "wire.adapter": behaviorRow("provider_config", adapter), @@ -112,7 +112,7 @@ export function resolveProductionBehaviorValues( "responses.stateful": behaviorRow("provider_config", effective.statelessResponses !== true), "responses.serviceTier": behaviorRow( "provider_config", - serviceTierSupportForModel(effective, modelId, providerName) ?? null, + serviceTierSupportFromPolicy(fastPolicy) ?? null, ), "responses.fastWireKind": behaviorRow( "provider_config", diff --git a/src/server/management/shared.ts b/src/server/management/shared.ts index 77d1f74264..3ebea685e8 100644 --- a/src/server/management/shared.ts +++ b/src/server/management/shared.ts @@ -86,7 +86,8 @@ export type CostEstimateReason = | "usage_estimated" | "cache_detail_missing" | "expected_price_overlay" - | "provider_cost_overlay"; + | "provider_cost_overlay" + | "priority_lower_bound"; export type CostResult = | { kind: "value"; estimate: NonNullable>; estimateReasons: CostEstimateReason[] } @@ -143,6 +144,7 @@ export function costResult(entry: MetricSource): CostResult { ? "expected_price_overlay" as const : undefined, estimate.price?.source === "user" || estimate.attempts?.some(a => a.price.source === "user") ? "provider_cost_overlay" as const : undefined, + estimate.priorityLowerBound ? "priority_lower_bound" as const : undefined, ].filter((reason): reason is CostEstimateReason => reason !== undefined); return { kind: "value", estimate, estimateReasons }; } diff --git a/src/server/responses/core.ts b/src/server/responses/core.ts index d0cb1b5b13..2a3bb54564 100644 --- a/src/server/responses/core.ts +++ b/src/server/responses/core.ts @@ -1199,6 +1199,7 @@ async function applyFinalRouteRequestNormalization(args: { route.modelId, route.providerName, inboundWire, + config.providers[route.providerName], ); const modelServiceTierSupport = serviceTierSupportFromPolicy(fastPolicy); const callerTier = parsed.options.serviceTier; @@ -4288,9 +4289,9 @@ async function handleResponsesInner( const detachContinuationBodyGuard = cancelBodyOnAbort(response.body, upstream.signal); try { if (nextParsed.stream) { - yield* activeAdapter.parseStream(response, translatorBudget); + yield* activeAdapter.parseStream(response, translatorBudget, logCtx.activeTierMetadata); } else if (activeAdapter.parseResponse) { - yield* await activeAdapter.parseResponse(response, translatorBudget); + yield* await activeAdapter.parseResponse(response, translatorBudget, logCtx.activeTierMetadata); } else { yield { type: "error", message: "Provider continuation does not support response parsing" }; } @@ -4320,7 +4321,11 @@ async function handleResponsesInner( }; if (parsed.stream) { - const initialEventStream = activeAdapter.parseStream(upstreamResponse, translatorBudget); + const initialEventStream = activeAdapter.parseStream( + upstreamResponse, + translatorBudget, + logCtx.activeTierMetadata, + ); const eventStream = terminalGuardEnabled ? guardTerminalEventStream({ parsed, @@ -4388,7 +4393,11 @@ async function handleResponsesInner( if (activeAdapter.parseResponse) { let events: AdapterEvent[]; try { - const initialEvents = await activeAdapter.parseResponse(upstreamResponse, translatorBudget); + const initialEvents = await activeAdapter.parseResponse( + upstreamResponse, + translatorBudget, + logCtx.activeTierMetadata, + ); let guardedEvents: AdapterEvent[]; if (terminalGuardEnabled) { guardedEvents = []; diff --git a/src/usage/cost.ts b/src/usage/cost.ts index 5cf798e144..6a82604722 100644 --- a/src/usage/cost.ts +++ b/src/usage/cost.ts @@ -83,6 +83,8 @@ export interface AttemptCostEstimate { estimated: boolean; /** Applied OpenAI priority-tier multiplier (undefined or 1 = standard). */ priorityMultiplier?: number; + /** Standard-price estimate is a known floor for a confirmed, unpriced priority endpoint. */ + priorityLowerBound?: boolean; /** Set when the published long-context rate was applied (#908). */ contextTier?: ContextTierName; } @@ -95,6 +97,8 @@ export interface CostEstimate { price?: MatchedPrice; /** Applied OpenAI priority-tier multiplier (undefined or 1 = standard). */ priorityMultiplier?: number; + /** Standard-price estimate is a known floor for a confirmed, unpriced priority endpoint. */ + priorityLowerBound?: boolean; /** Set when any priced attempt used the published long-context rate (#908). */ contextTier?: ContextTierName; } @@ -350,7 +354,9 @@ export type ServiceTierInput = string | ServiceTierContext; * and long-context exclusivity depends on that distinction. */ export function serviceTierContext(entry: ServiceTierContext): ServiceTierContext { - if (entry.tierOutcome) return serviceTierContextFromOutcome(entry.tierOutcome); + if (entry.tierOutcome) { + return { ...serviceTierContextFromOutcome(entry.tierOutcome), tierOutcome: entry.tierOutcome }; + } return { responseServiceTier: entry.responseServiceTier, requestedServiceTier: entry.requestedServiceTier, @@ -448,6 +454,22 @@ function applyPriorityMultiplier( }, multiplier]; } +/** + * OpenRouter confirms the actual endpoint tier and documents priority as higher cost, but this + * branch does not bundle its provider-specific priority endpoint prices. A confirmed canonical + * priority result can therefore use the standard price only as a provable lower bound. Do not + * extend this to flex (cheaper) or to other providers without the same pricing contract. + */ +function isOpenRouterPriorityLowerBound( + provider: string, + outcome: AttemptTierOutcome | undefined, +): boolean { + return baseProviderLabel(provider) === "openrouter" + && outcome?.canonical === "priority" + && outcome.fastOutcome === "applied" + && outcome.confirmation === "confirmed"; +} + /** * Per-attempt cost estimate: tokens normalized, price resolved (user overlay → * catalogs), priority/long-context tiers applied. Null when usage or price is @@ -476,6 +498,7 @@ export function estimateAttemptCost( const [effectiveCost4, multiplier] = contextTier ? [tieredCost4, 1] as const : applyPriorityMultiplier(tieredCost4, attempt.provider, attempt.model, attemptServiceTier); + const priorityLowerBound = isOpenRouterPriorityLowerBound(attempt.provider, attempt.tierOutcome); return { ordinal: attempt.ordinal, provider: attempt.provider, @@ -485,6 +508,7 @@ export function estimateAttemptCost( cost: calculateCost(tokens, effectiveCost4), estimated: isEstimated(attempt.usage, attempt.usageStatus, price.status), ...(multiplier !== 1 ? { priorityMultiplier: multiplier } : {}), + ...(priorityLowerBound ? { priorityLowerBound: true } : {}), ...(contextTier ? { contextTier } : {}), }; } @@ -527,6 +551,7 @@ export function estimateComboCost( ...(estimates.some(est => est.priorityMultiplier && est.priorityMultiplier !== 1) ? { priorityMultiplier: estimates.find(est => est.priorityMultiplier)?.priorityMultiplier } : {}), + ...(estimates.some(est => est.priorityLowerBound) ? { priorityLowerBound: true } : {}), ...(estimates.some(est => est.contextTier) ? { contextTier: "long" as const } : {}), }; } @@ -554,12 +579,17 @@ export function estimateRequestCost( const [effectiveCost4, multiplier] = contextTier ? [tieredCost4, 1] as const : applyPriorityMultiplier(tieredCost4, input.provider, input.model, input.serviceTier); + const priorityLowerBound = isOpenRouterPriorityLowerBound( + input.provider, + typeof input.serviceTier === "object" ? input.serviceTier.tierOutcome : undefined, + ); return { tokens, price, cost: calculateCost(tokens, effectiveCost4), estimated: isEstimated(input.usage, input.usageStatus, price.status), ...(multiplier !== 1 ? { priorityMultiplier: multiplier } : {}), + ...(priorityLowerBound ? { priorityLowerBound: true } : {}), ...(contextTier ? { contextTier } : {}), }; } diff --git a/tests/fastwire-observability.test.ts b/tests/fastwire-observability.test.ts index 058ca6c961..f29332f9e0 100644 --- a/tests/fastwire-observability.test.ts +++ b/tests/fastwire-observability.test.ts @@ -1,5 +1,6 @@ import { describe, expect, test } from "bun:test"; import type { AdapterRequest } from "../src/adapters/base"; +import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; import { createResponsesPassthroughAdapter } from "../src/adapters/openai-responses"; import { buildBehaviorFingerprintV1 } from "../src/lab/subject/behavior-fingerprint"; import { sanitizeLogMetadataString } from "../src/lib/redact"; @@ -18,12 +19,13 @@ import { type RequestLogContext, type RequestLogEntry, } from "../src/server/request-log"; -import { applyServiceTierGate } from "../src/server/responses/core"; +import { applyServiceTierGate, handleResponses } from "../src/server/responses/core"; +import { costResult } from "../src/server/management/shared"; import type { OcxConfig, OcxParsedRequest, TierObservationContext } from "../src/types"; import { estimateComboCost, serviceTierContextFromOutcome } from "../src/usage/cost"; import type { ExpectedPriceOverlay } from "../src/usage/expected-prices"; import { normalizeUsageEntryForTest } from "../src/usage/log"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createTestTranslatorBudget, withTestTranslatorBudget } from "./helpers/translator-budget"; const SERVICE_WIRE = { kind: "service-tier" as const, @@ -408,6 +410,120 @@ describe("FastWire logging and persistence", () => { expect(normalized.responseServiceTier).toBe(expected); expect(normalized.tierOutcome?.responseServiceTier).toBe(expected); }); + + test.each([ + { wire: "stream", responseTier: "priority", fastOutcome: "applied", confirmation: "confirmed", canonical: "priority" }, + { wire: "stream", responseTier: "default", fastOutcome: "downgraded", confirmation: "downgraded", canonical: undefined }, + { wire: "stream", responseTier: undefined, fastOutcome: "applied", confirmation: "assumed", canonical: "priority" }, + { wire: "non-stream", responseTier: "priority", fastOutcome: "applied", confirmation: "confirmed", canonical: "priority" }, + { wire: "non-stream", responseTier: "default", fastOutcome: "downgraded", confirmation: "downgraded", canonical: undefined }, + { wire: "non-stream", responseTier: undefined, fastOutcome: "applied", confirmation: "assumed", canonical: "priority" }, + ] as const)( + "OpenAI Chat $wire response tier=$responseTier updates the existing adapter observer", + async ({ wire, responseTier, fastOutcome, confirmation, canonical }) => { + const tracker = createAdapterTierMetadata( + observation(), + { kind: "set", value: "priority" }, + "service-tier", + "priority", + )!; + const adapter = createOpenAIChatAdapter({ + adapter: "openai-chat", + baseUrl: "https://openrouter.ai/api/v1", + }); + const tierField = responseTier === undefined ? {} : { service_tier: responseTier }; + const budget = createTestTranslatorBudget(); + + if (wire === "stream") { + const chunk = { + id: "chatcmpl-tier", + object: "chat.completion.chunk", + ...tierField, + choices: [{ index: 0, delta: { content: "ok" }, finish_reason: "stop" }], + usage: { prompt_tokens: 1, completion_tokens: 1 }, + }; + for await (const _ of adapter.parseStream(new Response( + `data: ${JSON.stringify(chunk)}\n\ndata: [DONE]\n\n`, + ), budget, tracker)) { + // Drain the adapter so the final chunk and tier echo are observed. + } + } else { + await adapter.parseResponse(new Response(JSON.stringify({ + id: "chatcmpl-tier", + object: "chat.completion", + ...tierField, + choices: [{ index: 0, message: { role: "assistant", content: "ok" }, finish_reason: "stop" }], + usage: { prompt_tokens: 1, completion_tokens: 1 }, + })), budget, tracker); + } + + expect(tracker.outcome).toMatchObject({ fastOutcome, confirmation }); + if (canonical === undefined) expect(tracker.outcome).not.toHaveProperty("canonical"); + else expect(tracker.outcome.canonical).toBe(canonical); + if (responseTier === undefined) expect(tracker.outcome).not.toHaveProperty("responseServiceTier"); + else expect(tracker.outcome.responseServiceTier).toBe(responseTier); + }, + ); + + test.each([ + { stream: true, responseTier: "priority", fastOutcome: "applied", confirmation: "confirmed" }, + { stream: false, responseTier: "default", fastOutcome: "downgraded", confirmation: "downgraded" }, + ] as const)( + "the Responses bridge passes the live observer into Chat parsing (stream=$stream)", + async ({ stream, responseTier, fastOutcome, confirmation }) => { + const originalFetch = globalThis.fetch; + globalThis.fetch = (async () => { + const payload = stream + ? `data: ${JSON.stringify({ + service_tier: responseTier, + choices: [{ index: 0, delta: { content: "ok" }, finish_reason: "stop" }], + usage: { prompt_tokens: 1, completion_tokens: 1 }, + })}\n\ndata: [DONE]\n\n` + : JSON.stringify({ + service_tier: responseTier, + choices: [{ index: 0, message: { role: "assistant", content: "ok" }, finish_reason: "stop" }], + usage: { prompt_tokens: 1, completion_tokens: 1 }, + }); + return new Response(payload, { + status: 200, + headers: { "content-type": stream ? "text/event-stream" : "application/json" }, + }); + }) as typeof fetch; + const logCtx: RequestLogContext = { model: "", provider: "" }; + try { + const response = await handleResponses( + new Request("http://localhost/v1/responses", { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ model: "fixture/model", input: "ping", stream }), + }), + { + port: 10100, + defaultProvider: "fixture", + fastMode: true, + providers: { + fixture: { + adapter: "openai-chat", + baseUrl: "https://fixture.example.test/v1", + apiKey: "sk-test", + supportsServiceTier: true, + }, + }, + }, + logCtx, + {}, + ); + await response.text(); + } finally { + globalThis.fetch = originalFetch; + } + expect(logCtx.activeAttempt?.tierOutcome).toMatchObject({ + fastOutcome, + confirmation, + responseServiceTier: responseTier, + }); + }, + ); }); describe("FastWire per-attempt cost", () => { @@ -498,6 +614,102 @@ describe("FastWire per-attempt cost", () => { expect(estimate.cost.total).toBeCloseTo(6.4, 9); expect(estimate.attempts?.every(attempt => attempt.priorityMultiplier === 2)).toBe(true); }); + + test("confirmed OpenRouter priority is a standard-price lower bound, while downgrade and OpenAI stay unchanged", () => { + const openRouterOverlays: ExpectedPriceOverlay[] = [{ + provider: "openrouter", + modelId: "openai/gpt-5.6-sol", + cost4: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 6.25 }, + source: "test", + verifiedAt: "2026-08-18", + status: "verified", + }]; + const confirmedPriority = { + canonical: "priority" as const, + wireKind: "service-tier" as const, + wireValue: "priority", + fastOutcome: "applied" as const, + confirmation: "confirmed" as const, + responseServiceTier: "priority", + }; + const downgraded = { + wireKind: "service-tier" as const, + wireValue: "priority", + fastOutcome: "downgraded" as const, + fastDowngradeReason: "response-declined" as const, + confirmation: "downgraded" as const, + responseServiceTier: "default", + }; + + const priority = estimateComboCost([{ + ordinal: 1, + provider: "openrouter", + model: "openai/gpt-5.6-sol", + usageStatus: "reported", + usage, + tierOutcome: confirmedPriority, + }], openRouterOverlays)!; + expect(priority.cost.total).toBeCloseTo(1.6, 9); + expect(priority.priorityMultiplier).toBeUndefined(); + expect(priority.priorityLowerBound).toBe(true); + expect(priority.attempts?.[0]?.priorityLowerBound).toBe(true); + + const standard = estimateComboCost([{ + ordinal: 1, + provider: "openrouter", + model: "openai/gpt-5.6-sol", + usageStatus: "reported", + usage, + tierOutcome: downgraded, + }], openRouterOverlays)!; + expect(standard.cost.total).toBeCloseTo(1.6, 9); + expect(standard.priorityLowerBound).toBeUndefined(); + + const flex = estimateComboCost([{ + ordinal: 1, + provider: "openrouter", + model: "openai/gpt-5.6-sol", + usageStatus: "reported", + usage, + tierOutcome: { ...downgraded, responseServiceTier: "flex" }, + }], openRouterOverlays)!; + expect(flex.cost.total).toBeCloseTo(1.6, 9); + expect(flex.priorityLowerBound).toBeUndefined(); + + const openAi = estimateComboCost([{ + ordinal: 1, + provider: "openai", + model: "gpt-5.6-sol", + usageStatus: "reported", + usage, + tierOutcome: confirmedPriority, + }], overlays)!; + expect(openAi.cost.total).toBeCloseTo(3.2, 9); + expect(openAi.priorityMultiplier).toBe(2); + expect(openAi.priorityLowerBound).toBeUndefined(); + }); + + test("management cost metadata exposes the aligned priority_lower_bound reason", () => { + const result = costResult({ + provider: "openrouter", + model: "openai/gpt-5.6-sol", + durationMs: 1, + usageStatus: "reported", + usage, + tierOutcome: { + canonical: "priority", + wireKind: "service-tier", + wireValue: "priority", + fastOutcome: "applied", + confirmation: "confirmed", + responseServiceTier: "priority", + }, + }); + expect(result.kind).toBe("value"); + if (result.kind !== "value") throw new Error("expected a priced OpenRouter result"); + expect(result.estimate.priorityLowerBound).toBe(true); + expect(result.estimateReasons).toContain("priority_lower_bound"); + }); }); describe("FastWire gate and compatibility fingerprint", () => { diff --git a/tests/service-tier-capability.test.ts b/tests/service-tier-capability.test.ts index 2e397be86b..49c051b8dc 100644 --- a/tests/service-tier-capability.test.ts +++ b/tests/service-tier-capability.test.ts @@ -7,6 +7,9 @@ * ever receiving an injection (PR #860 family). */ import { afterEach, describe, expect, test } from "bun:test"; +import { applyProviderConfigHints } from "../src/codex/catalog"; +import { applyCatalogModelMetadata } from "../src/codex/catalog/effort"; +import type { RawEntry } from "../src/codex/catalog/parsing"; import { providerConfigSeed, enrichProviderFromRegistry } from "../src/providers/derive"; import { getProviderRegistryEntry } from "../src/providers/registry"; import type { RequestLogContext } from "../src/server/request-log"; @@ -45,6 +48,30 @@ describe("registry capability reaches saved configs without overriding them", () enrichProviderFromRegistry("deepseek", optedIn); expect(optedIn.supportsServiceTier).toBe(true); }); + + test("OpenRouter stays provider-unclassified and declares only its three OpenAI-backed slugs", () => { + const entry = getProviderRegistryEntry("openrouter")!; + expect(entry.supportsServiceTier).toBeUndefined(); + expect(entry.chatServiceTier).toBeUndefined(); + expect(entry.modelSupportsServiceTier).toEqual({ + "openai/gpt-5.6-sol": true, + "openai/gpt-5.6-terra": true, + "openai/gpt-5.6-luna": true, + }); + expect(entry.modelSupportsServiceTier).not.toHaveProperty("anthropic/claude-sonnet-5"); + expect(providerConfigSeed(entry).modelSupportsServiceTier).toBeUndefined(); + }); + + test("OpenRouter registry capability is not inherited by a same-named noncanonical destination", () => { + const provider: OcxProviderConfig = { + ...providerConfigSeed(getProviderRegistryEntry("openrouter")!), + baseUrl: "https://openrouter-proxy.example.test/v1", + apiKey: "sk-test", + }; + enrichProviderFromRegistry("openrouter", provider); + expect(provider.modelSupportsServiceTier).toBeUndefined(); + expect(supportsServiceTierForModel(provider, "openai/gpt-5.6-sol")).toBeUndefined(); + }); }); describe("service-tier capability is exact-model and provider-scoped", () => { @@ -237,6 +264,14 @@ describe("the gate fires on the live handleResponses path", () => { ({ ...providerConfigSeed(getProviderRegistryEntry("deepseek")!), apiKey: "sk-test" }); const openAiKeyProvider = (): OcxProviderConfig => ({ ...providerConfigSeed(getProviderRegistryEntry("openai-apikey")!), apiKey: "sk-test" }); + const openRouterProvider = (overrides: Partial = {}): OcxProviderConfig => { + const provider: OcxProviderConfig = { + ...providerConfigSeed(getProviderRegistryEntry("openrouter")!), + apiKey: "sk-test", + ...overrides, + }; + return provider; + }; test("DeepSeek never receives service_tier, even with fastMode on", async () => { const body = await drive("deepseek", deepseekProvider(), "deepseek-v4-flash", {}, true); @@ -310,6 +345,53 @@ describe("the gate fires on the live handleResponses path", () => { const undeclared = await drive("custom-chat", custom(), "undeclared-model", { service_tier: "priority" }); expect(undeclared).not.toHaveProperty("service_tier"); }); + + test.each([ + "openai/gpt-5.6-sol", + "openai/gpt-5.6-terra", + "openai/gpt-5.6-luna", + ])("OpenRouter %s publishes and injects canonical Fast without route pins", async modelId => { + const provider = openRouterProvider(); + const model = applyProviderConfigHints("openrouter", provider, { id: modelId, provider: "openrouter" }); + const catalogEntry: RawEntry = {}; + applyCatalogModelMetadata(catalogEntry, model); + expect(catalogEntry.service_tiers).toEqual([expect.objectContaining({ id: "priority", name: "Fast" })]); + + const body = await drive("openrouter", provider, modelId, {}, true); + expect(body.service_tier).toBe("priority"); + expect(body).not.toHaveProperty("provider"); + }); + + test("OpenRouter Anthropic and undeclared slugs stay unclassified and receive no Fast injection", async () => { + const provider = openRouterProvider(); + for (const modelId of ["anthropic/claude-sonnet-5", "google/gemini-unknown"]) { + const model = applyProviderConfigHints("openrouter", provider, { id: modelId, provider: "openrouter" }); + const catalogEntry: RawEntry = {}; + applyCatalogModelMetadata(catalogEntry, model); + expect(catalogEntry).not.toHaveProperty("service_tiers"); + expect(await drive("openrouter", provider, modelId, {}, true)).not.toHaveProperty("service_tier"); + } + }); + + test("an explicit OpenRouter provider-level false remains fail-closed", async () => { + const provider = openRouterProvider({ supportsServiceTier: false }); + expect(supportsServiceTierForModel(provider, "openai/gpt-5.6-sol")).toBe(false); + const body = await drive("openrouter", provider, "openai/gpt-5.6-sol", {}, true); + expect(body).not.toHaveProperty("service_tier"); + }); + + test("a same-named noncanonical OpenRouter destination neither publishes nor injects registry Fast", async () => { + const provider = openRouterProvider({ baseUrl: "https://openrouter-proxy.example.test/v1" }); + const model = applyProviderConfigHints("openrouter", provider, { + id: "openai/gpt-5.6-sol", + provider: "openrouter", + }); + const catalogEntry: RawEntry = {}; + applyCatalogModelMetadata(catalogEntry, model); + expect(catalogEntry).not.toHaveProperty("service_tiers"); + const body = await drive("openrouter", provider, "openai/gpt-5.6-sol", {}, true); + expect(body).not.toHaveProperty("service_tier"); + }); }); describe("unclassified chat-wire tier projection (release-audit fix)", () => { @@ -328,4 +410,3 @@ describe("unclassified chat-wire tier projection (release-audit fix)", () => { expect(serviceTierSupportForModel(provider, "some-model")).toBeUndefined(); }); }); - From 5682c62ee427fb9d12be6ca5d2b88f81b3d55700 Mon Sep 17 00:00:00 2001 From: olddonkey Date: Tue, 18 Aug 2026 18:39:35 -0700 Subject: [PATCH 2/5] docs(devlog): capture the OpenRouter Fast lower-bound rendering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Screenshot evidence for lidge-jun/opencodex#2080: the Logs table showing a confirmed-priority OpenRouter request rendered as a floor (≥$) next to a response-declined downgrade and a standard request (~$). Taking this screenshot is what surfaced two defects the test suites missed: the lower-bound marker disagreed with the parallel xAI unit's rendering, and the fix for it initially reached only the detail panel because the table cell had its own inline formatter. Both paths now share one implementation. Co-Authored-By: Claude Fable 5 --- ...0_logs_openrouter_priority_lower_bound.png | Bin 0 -> 164931 bytes .../evidence/README.md | 16 ++++++++++++++++ gui/src/pages/Logs.tsx | 11 +---------- gui/src/pages/logs-cost-format.ts | 17 ++++++++++++++++- gui/tests/logs-priority-lower-bound.test.ts | 18 ++++++++++++++++-- 5 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 devlog/_plan/260818_fastwire_b2_openrouter/evidence/010_logs_openrouter_priority_lower_bound.png create mode 100644 devlog/_plan/260818_fastwire_b2_openrouter/evidence/README.md diff --git a/devlog/_plan/260818_fastwire_b2_openrouter/evidence/010_logs_openrouter_priority_lower_bound.png b/devlog/_plan/260818_fastwire_b2_openrouter/evidence/010_logs_openrouter_priority_lower_bound.png new file mode 100644 index 0000000000000000000000000000000000000000..5ee905fea5fd3718c8bf6b6fac93241cc936e90a GIT binary patch literal 164931 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

yi@puXP{<+%cnKY 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 literal 0 HcmV?d00001 diff --git a/devlog/_plan/260818_fastwire_b2_openrouter/evidence/README.md b/devlog/_plan/260818_fastwire_b2_openrouter/evidence/README.md new file mode 100644 index 0000000000..a713c0f453 --- /dev/null +++ b/devlog/_plan/260818_fastwire_b2_openrouter/evidence/README.md @@ -0,0 +1,16 @@ +# Evidence — FastWire B2 (OpenRouter) + +`010_logs_openrouter_priority_lower_bound.png` — Logs table with three seeded OpenRouter +requests on `openai/gpt-5.6-sol`, captured against a local proxy with a temporary +`OPENCODEX_HOME`: + +| Row | Attempt outcome | Rendering | +| --- | --- | --- | +| `or-priority-confirmed` | upstream echoed `service_tier: "priority"` | `≥$0.1105` — priced at the standard rate but marked a floor, because OpenRouter publishes no bundled tier price and documents priority as higher cost | +| `or-priority-declined` | upstream echoed `service_tier: "default"` | `~$0.1105` — a real downgrade, so no floor marker | +| `or-standard` | no tier requested | `~$0.1105` | + +All three totals match on purpose: without a bundled priority price every row is computed at +the standard rate, so the only thing that differs is whether the cost is presented as an +estimate (`~$`) or as a known lower bound (`≥$`). The marker matches the convention used by +the parallel xAI unit (#2072). diff --git a/gui/src/pages/Logs.tsx b/gui/src/pages/Logs.tsx index fef77bc9ac..62490437eb 100644 --- a/gui/src/pages/Logs.tsx +++ b/gui/src/pages/Logs.tsx @@ -17,7 +17,7 @@ import type { LogsTab } from "./logs-tab-keydown"; import { logsTabKeyDown, readTabFromHash, selectLogsTab } from "./logs-tab-keydown"; import { modelTitle } from "./logs-model-title"; import { speedLabel } from "./logs-speed-label"; -import { formatEstimatedUsdValue } from "./logs-cost-format"; +import { formatEstimatedUsd, formatEstimatedUsdValue } from "./logs-cost-format"; import { cacheSplit, isCursorUsageProvider, tokensTitle } from "./logs-token-title"; import type { LogSurface, LogSurfaceFilter } from "./logs-surface-filter"; import { logMatchesSurface } from "./logs-surface-filter"; @@ -240,15 +240,6 @@ function formatTokPerSecond(result: TokPerSecondResult | undefined, localeTag?: return `${result.estimated ? "~" : ""}${value}`; } -function formatEstimatedUsd(result: CostResult | undefined, localeTag?: string): string { - if (!result || result.kind === "unavailable" || !Number.isFinite(result.estimate.cost.total) || result.estimate.cost.total < 0) return "\u2014"; - const totalUsd = result.estimate.cost.total; - return `${result.estimate.priorityLowerBound ? "≥" : ""}~$${new Intl.NumberFormat(localeTag, { - minimumFractionDigits: 4, - maximumFractionDigits: 4, - }).format(totalUsd)}`; -} - /** Consecutive failed polls before a stale table is called out. Two seconds each, so ~6s. */ const STALE_POLL_FAILURE_LIMIT = 3; diff --git a/gui/src/pages/logs-cost-format.ts b/gui/src/pages/logs-cost-format.ts index 0997737896..ef09e5741b 100644 --- a/gui/src/pages/logs-cost-format.ts +++ b/gui/src/pages/logs-cost-format.ts @@ -4,8 +4,23 @@ export function formatEstimatedUsdValue( priorityLowerBound = false, ): string { if (!Number.isFinite(value) || value < 0) return "\u2014"; - return `${priorityLowerBound ? "≥" : ""}~$${new Intl.NumberFormat(localeTag, { + return `${priorityLowerBound ? "≥$" : "~$"}${new Intl.NumberFormat(localeTag, { minimumFractionDigits: 4, maximumFractionDigits: 4, }).format(value)}`; } + +export function formatEstimatedUsd( + result: { + kind: "value"; + estimate: { cost: { total: number }; priorityLowerBound?: boolean }; + } | { kind: "unavailable" } | undefined, + localeTag?: string, +): string { + if (!result || result.kind === "unavailable") return "\u2014"; + return formatEstimatedUsdValue( + result.estimate.cost.total, + localeTag, + result.estimate.priorityLowerBound, + ); +} diff --git a/gui/tests/logs-priority-lower-bound.test.ts b/gui/tests/logs-priority-lower-bound.test.ts index 6117bcfdd3..a22d23f16e 100644 --- a/gui/tests/logs-priority-lower-bound.test.ts +++ b/gui/tests/logs-priority-lower-bound.test.ts @@ -1,12 +1,26 @@ import { describe, expect, test } from "bun:test"; -import { formatEstimatedUsdValue } from "../src/pages/logs-cost-format"; +import { formatEstimatedUsd, formatEstimatedUsdValue } from "../src/pages/logs-cost-format"; describe("Logs priority lower-bound formatting", () => { test("prefixes confirmed unpriced priority estimates with the lower-bound marker", () => { - expect(formatEstimatedUsdValue(1.6, "en-US", true)).toBe("≥~$1.6000"); + expect(formatEstimatedUsdValue(1.6, "en-US", true)).toBe("≥$1.6000"); }); test("keeps ordinary standard-price estimates unchanged", () => { expect(formatEstimatedUsdValue(1.6, "en-US", false)).toBe("~$1.6000"); }); }); + +describe("Logs table cost formatting", () => { + test("uses the shared value formatter for lower bounds, ordinary estimates, and unavailable costs", () => { + expect(formatEstimatedUsd({ + kind: "value", + estimate: { cost: { total: 1.6 }, priorityLowerBound: true }, + }, "en-US")).toBe("≥$1.6000"); + expect(formatEstimatedUsd({ + kind: "value", + estimate: { cost: { total: 1.6 } }, + }, "en-US")).toBe("~$1.6000"); + expect(formatEstimatedUsd({ kind: "unavailable" }, "en-US")).toBe("—"); + }); +}); From d49538cbb1e73bfde4b6f6fa0b6f23541a23c78e Mon Sep 17 00:00:00 2001 From: olddonkey Date: Tue, 18 Aug 2026 22:56:56 -0700 Subject: [PATCH 3/5] fix(gui): localize estimated cost totals --- gui/src/i18n/de.ts | 3 + gui/src/i18n/en.ts | 3 + gui/src/i18n/fr.ts | 3 + gui/src/i18n/ja.ts | 3 + gui/src/i18n/ko.ts | 3 + gui/src/i18n/ru.ts | 3 + gui/src/i18n/tr.ts | 3 + gui/src/i18n/zh-TW.ts | 3 + gui/src/i18n/zh.ts | 3 + gui/src/pages/Logs.tsx | 40 +++------ gui/src/pages/logs-cost-format.ts | 67 ++++++++++++-- gui/tests/logs-priority-lower-bound.test.ts | 97 +++++++++++++++++++-- 12 files changed, 188 insertions(+), 43 deletions(-) diff --git a/gui/src/i18n/de.ts b/gui/src/i18n/de.ts index c5f7cce3db..6b3483938b 100644 --- a/gui/src/i18n/de.ts +++ b/gui/src/i18n/de.ts @@ -645,6 +645,9 @@ export const de: Record = { "logs.conversation.totals": "{requests} Anfragen · {tokens} Tokens · {cost}", "logs.conversation.scope": "Summen gelten nur für den aktuell geladenen Logs-Ring.", "logs.conversation.excluded": "({unpriced} ohne Preis, {unmetered} ohne Messung vom ~$ ausgenommen)", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.detail.conversation": "Konversation", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/en.ts b/gui/src/i18n/en.ts index a9ecab5e82..997fcdc806 100644 --- a/gui/src/i18n/en.ts +++ b/gui/src/i18n/en.ts @@ -678,6 +678,9 @@ export const en = { "logs.conversation.totals": "{requests} requests · {tokens} tokens · {cost}", "logs.conversation.scope": "Totals cover the currently loaded Logs ring only.", "logs.conversation.excluded": "({unpriced} unpriced, {unmetered} unmetered excluded from ~$)", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.detail.conversation": "Conversation", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/fr.ts b/gui/src/i18n/fr.ts index cf573fb9df..c9a3bb024c 100644 --- a/gui/src/i18n/fr.ts +++ b/gui/src/i18n/fr.ts @@ -659,6 +659,9 @@ export const fr: Record = { "logs.conversation.totals": "{requests} requêtes · {tokens} jetons · {cost}", "logs.conversation.scope": "Les totaux couvrent uniquement le tampon circulaire des journaux actuellement chargé.", "logs.conversation.excluded": "({unpriced} sans tarif, {unmetered} sans mesure exclus du total en ~$)", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.detail.conversation": "Conversation", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/ja.ts b/gui/src/i18n/ja.ts index ce63420d0c..572e8d94f9 100644 --- a/gui/src/i18n/ja.ts +++ b/gui/src/i18n/ja.ts @@ -621,6 +621,9 @@ export const ja: Record = { "logs.conversation.totals": "{requests} 件 · {tokens} トークン · {cost}", "logs.conversation.scope": "合計は現在読み込まれている Logs リングのみです。", "logs.conversation.excluded": "(~$ から価格なし {unpriced} / 未計測 {unmetered} を除外)", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.detail.conversation": "会話", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/ko.ts b/gui/src/i18n/ko.ts index 9e98124c77..9accfcf624 100644 --- a/gui/src/i18n/ko.ts +++ b/gui/src/i18n/ko.ts @@ -664,6 +664,9 @@ export const ko: Record = { "logs.conversation.totals": "{requests}건 요청 · {tokens} 토큰 · {cost}", "logs.conversation.scope": "합계는 현재 로드된 Logs 링만 포함합니다.", "logs.conversation.excluded": "(~$에서 가격 없음 {unpriced}건, 미측정 {unmetered}건 제외)", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.detail.conversation": "대화", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/ru.ts b/gui/src/i18n/ru.ts index cbeef58a72..e7f358db2d 100644 --- a/gui/src/i18n/ru.ts +++ b/gui/src/i18n/ru.ts @@ -662,6 +662,9 @@ export const ru: Record = { "logs.conversation.totals": "{requests} запросов · {tokens} токенов · {cost}", "logs.conversation.scope": "Итоги только по загруженному кольцу Logs.", "logs.conversation.excluded": "(из ~$ исключены {unpriced} без цены, {unmetered} без учёта)", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.detail.conversation": "Диалог", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/tr.ts b/gui/src/i18n/tr.ts index 7028838668..1accd38130 100644 --- a/gui/src/i18n/tr.ts +++ b/gui/src/i18n/tr.ts @@ -669,6 +669,9 @@ export const tr: Record = { "logs.conversation.totals": "{requests} istek · {tokens} jeton · {cost}", "logs.conversation.scope": "Toplamlar yalnızca yüklü günlükleri kapsar.", "logs.conversation.excluded": "({unpriced} fiyatlandırılmamış, {unmetered} ölçülmemiş hariç)", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.detail.conversation": "Sohbet", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/zh-TW.ts b/gui/src/i18n/zh-TW.ts index 838e134410..9eb218183a 100644 --- a/gui/src/i18n/zh-TW.ts +++ b/gui/src/i18n/zh-TW.ts @@ -516,6 +516,9 @@ export const zhTW: Record = { "logs.conversation.totals": "{requests} 次請求 · {tokens} tokens · {cost}", "logs.conversation.scope": "合計僅涵蓋目前已載入的 Logs 環形緩衝。", "logs.conversation.excluded": "(~$ 已排除 {unpriced} 筆無定價、{unmetered} 筆無計量)", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.detail.conversation": "對話", "logs.badge.claude": "Claude", "logs.col.time": "時間", diff --git a/gui/src/i18n/zh.ts b/gui/src/i18n/zh.ts index 5bd1cc024f..44b65d897a 100644 --- a/gui/src/i18n/zh.ts +++ b/gui/src/i18n/zh.ts @@ -657,6 +657,9 @@ export const zh: Record = { "logs.conversation.totals": "{requests} 次请求 · {tokens} tokens · {cost}", "logs.conversation.scope": "合计仅覆盖当前已加载的 Logs 环形缓冲。", "logs.conversation.excluded": "(~$ 已排除 {unpriced} 条无定价、{unmetered} 条无计量)", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.detail.conversation": "会话", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/pages/Logs.tsx b/gui/src/pages/Logs.tsx index 62490437eb..55a7ef634d 100644 --- a/gui/src/pages/Logs.tsx +++ b/gui/src/pages/Logs.tsx @@ -17,7 +17,7 @@ import type { LogsTab } from "./logs-tab-keydown"; import { logsTabKeyDown, readTabFromHash, selectLogsTab } from "./logs-tab-keydown"; import { modelTitle } from "./logs-model-title"; import { speedLabel } from "./logs-speed-label"; -import { formatEstimatedUsd, formatEstimatedUsdValue } from "./logs-cost-format"; +import { formatEstimatedUsd, formatEstimatedUsdValue, summarizeEstimatedCosts } from "./logs-cost-format"; import { cacheSplit, isCursorUsageProvider, tokensTitle } from "./logs-token-title"; import type { LogSurface, LogSurfaceFilter } from "./logs-surface-filter"; import { logMatchesSurface } from "./logs-surface-filter"; @@ -337,33 +337,14 @@ function summarizeFilteredLogs(entries: LogEntry[]): { unmeteredRequests: number; } { let totalTokens = 0; - let estimatedCostUsd = 0; - let priorityLowerBound = false; - let unpricedRequests = 0; - let unmeteredRequests = 0; for (const entry of entries) { const tokens = displayTokenTotal(entry); if (tokens !== undefined) totalTokens += tokens; - if (entry.usageStatus === "unsupported") { - unmeteredRequests += 1; - continue; - } - const cost = entry.displayMetrics?.cost; - const total = cost?.kind === "value" ? cost.estimate.cost.total : undefined; - if (total !== undefined && Number.isFinite(total) && total >= 0) { - estimatedCostUsd += total; - priorityLowerBound ||= cost?.kind === "value" && cost.estimate.priorityLowerBound === true; - continue; - } - unpricedRequests += 1; } return { requests: entries.length, totalTokens, - estimatedCostUsd, - priorityLowerBound, - unpricedRequests, - unmeteredRequests, + ...summarizeEstimatedCosts(entries), }; } @@ -611,6 +592,7 @@ export default function Logs({ apiBase }: { apiBase: string }) { tokens: formatTokens(conversationTotals.totalTokens, localeTag ?? locale), cost: formatEstimatedUsdValue( conversationTotals.estimatedCostUsd, + t, localeTag, conversationTotals.priorityLowerBound, ), @@ -732,7 +714,7 @@ export default function Logs({ apiBase }: { apiBase: string }) { {formatTokPerSecond(log.displayMetrics?.tokPerSecond, localeTag)} - {formatEstimatedUsd(log.displayMetrics?.cost, localeTag)} + {formatEstimatedUsd(log.displayMetrics?.cost, t, localeTag)} @@ -957,11 +939,11 @@ function LogDetailDialog({ {cost?.kind === "value" ? ( <>

- {t("logs.detail.costTotal")}{formatEstimatedUsdValue(cost.estimate.cost.total, localeTag, cost.estimate.priorityLowerBound)} - {t("logs.tokens.input")}{formatEstimatedUsdValue(cost.estimate.cost.input, localeTag, cost.estimate.priorityLowerBound)} - {t("logs.tokens.cacheRead")}{formatEstimatedUsdValue(cost.estimate.cost.cacheRead, localeTag, cost.estimate.priorityLowerBound)} - {t("logs.tokens.cacheWrite")}{formatEstimatedUsdValue(cost.estimate.cost.cacheWrite, localeTag, cost.estimate.priorityLowerBound)} - {t("logs.tokens.output")}{formatEstimatedUsdValue(cost.estimate.cost.output, localeTag, cost.estimate.priorityLowerBound)} + {t("logs.detail.costTotal")}{formatEstimatedUsdValue(cost.estimate.cost.total, t, localeTag, cost.estimate.priorityLowerBound)} + {t("logs.tokens.input")}{formatEstimatedUsdValue(cost.estimate.cost.input, t, localeTag, cost.estimate.priorityLowerBound)} + {t("logs.tokens.cacheRead")}{formatEstimatedUsdValue(cost.estimate.cost.cacheRead, t, localeTag, cost.estimate.priorityLowerBound)} + {t("logs.tokens.cacheWrite")}{formatEstimatedUsdValue(cost.estimate.cost.cacheWrite, t, localeTag, cost.estimate.priorityLowerBound)} + {t("logs.tokens.output")}{formatEstimatedUsdValue(cost.estimate.cost.output, t, localeTag, cost.estimate.priorityLowerBound)} {cost.estimate.price && ( <> {t("logs.detail.matchedKey")} @@ -979,7 +961,7 @@ function LogDetailDialog({ ) : (
- {t("logs.detail.costTotal")}{"\u2014"} + {t("logs.detail.costTotal")}{t("logs.cost.unavailable")} {t("logs.detail.unavailableReason")} {cost?.kind === "unavailable" ? t(metricReasonKey(cost.reason)) : t("logs.detail.reason.usage_missing")}
@@ -1034,7 +1016,7 @@ function LogDetailDialog({ {attempt.durationMs}ms {formatTokPerSecond(attempt.displayMetrics?.tokPerSecond, localeTag)} - {formatEstimatedUsd(attemptCost, localeTag)} + {formatEstimatedUsd(attemptCost, t, localeTag)} {reason} ); diff --git a/gui/src/pages/logs-cost-format.ts b/gui/src/pages/logs-cost-format.ts index ef09e5741b..48a0814097 100644 --- a/gui/src/pages/logs-cost-format.ts +++ b/gui/src/pages/logs-cost-format.ts @@ -1,26 +1,77 @@ +import type { TFn } from "../i18n/shared"; + +type EstimatedCostResult = { + kind: "value"; + estimate: { cost: { total: number }; priorityLowerBound?: boolean }; +} | { kind: "unavailable" }; + export function formatEstimatedUsdValue( value: number, + t: TFn, localeTag?: string, priorityLowerBound = false, ): string { - if (!Number.isFinite(value) || value < 0) return "\u2014"; - return `${priorityLowerBound ? "≥$" : "~$"}${new Intl.NumberFormat(localeTag, { + if (!Number.isFinite(value) || value < 0) return t("logs.cost.unavailable"); + const amount = new Intl.NumberFormat(localeTag, { + style: "currency", + currency: "USD", minimumFractionDigits: 4, maximumFractionDigits: 4, - }).format(value)}`; + }).format(value); + return t(priorityLowerBound ? "logs.cost.lowerBound" : "logs.cost.approximate", { amount }); } export function formatEstimatedUsd( - result: { - kind: "value"; - estimate: { cost: { total: number }; priorityLowerBound?: boolean }; - } | { kind: "unavailable" } | undefined, + result: EstimatedCostResult | undefined, + t: TFn, localeTag?: string, ): string { - if (!result || result.kind === "unavailable") return "\u2014"; + if (!result || result.kind === "unavailable") return t("logs.cost.unavailable"); return formatEstimatedUsdValue( result.estimate.cost.total, + t, localeTag, result.estimate.priorityLowerBound, ); } + +interface CostSummaryEntry { + usageStatus?: string; + displayMetrics?: { cost: EstimatedCostResult }; +} + +export function summarizeEstimatedCosts(entries: readonly CostSummaryEntry[]): { + estimatedCostUsd: number; + priorityLowerBound: boolean; + unpricedRequests: number; + unmeteredRequests: number; +} { + let estimatedCostUsd = 0; + let everyPricedEstimateIsLowerBound = true; + let pricedEstimates = 0; + let unpricedRequests = 0; + let unmeteredRequests = 0; + for (const entry of entries) { + if (entry.usageStatus === "unsupported") { + unmeteredRequests += 1; + continue; + } + const cost = entry.displayMetrics?.cost; + if (cost?.kind === "value") { + const total = cost.estimate.cost.total; + if (Number.isFinite(total) && total >= 0) { + estimatedCostUsd += total; + pricedEstimates += 1; + everyPricedEstimateIsLowerBound &&= cost.estimate.priorityLowerBound === true; + continue; + } + } + unpricedRequests += 1; + } + return { + estimatedCostUsd, + priorityLowerBound: pricedEstimates > 0 && everyPricedEstimateIsLowerBound, + unpricedRequests, + unmeteredRequests, + }; +} diff --git a/gui/tests/logs-priority-lower-bound.test.ts b/gui/tests/logs-priority-lower-bound.test.ts index a22d23f16e..bfd68bae3b 100644 --- a/gui/tests/logs-priority-lower-bound.test.ts +++ b/gui/tests/logs-priority-lower-bound.test.ts @@ -1,13 +1,30 @@ import { describe, expect, test } from "bun:test"; -import { formatEstimatedUsd, formatEstimatedUsdValue } from "../src/pages/logs-cost-format"; +import { DICTS } from "../src/i18n/catalogs"; +import { interpolate, type TFn } from "../src/i18n/shared"; +import { + formatEstimatedUsd, + formatEstimatedUsdValue, + summarizeEstimatedCosts, +} from "../src/pages/logs-cost-format"; + +function translator(locale: keyof typeof DICTS): TFn { + return (key, vars) => interpolate(DICTS[locale][key], vars); +} + +const en = translator("en"); +const de = translator("de"); describe("Logs priority lower-bound formatting", () => { test("prefixes confirmed unpriced priority estimates with the lower-bound marker", () => { - expect(formatEstimatedUsdValue(1.6, "en-US", true)).toBe("≥$1.6000"); + expect(formatEstimatedUsdValue(1.6, en, "en-US", true)).toBe("≥$1.6000"); }); test("keeps ordinary standard-price estimates unchanged", () => { - expect(formatEstimatedUsdValue(1.6, "en-US", false)).toBe("~$1.6000"); + expect(formatEstimatedUsdValue(1.6, en, "en-US", false)).toBe("~$1.6000"); + }); + + test("uses locale-aware USD placement and separators", () => { + expect(formatEstimatedUsdValue(1.6, de, "de-DE", false)).toBe("~1,6000\u00a0$"); }); }); @@ -16,11 +33,79 @@ describe("Logs table cost formatting", () => { expect(formatEstimatedUsd({ kind: "value", estimate: { cost: { total: 1.6 }, priorityLowerBound: true }, - }, "en-US")).toBe("≥$1.6000"); + }, en, "en-US")).toBe("≥$1.6000"); expect(formatEstimatedUsd({ kind: "value", estimate: { cost: { total: 1.6 } }, - }, "en-US")).toBe("~$1.6000"); - expect(formatEstimatedUsd({ kind: "unavailable" }, "en-US")).toBe("—"); + }, en, "en-US")).toBe("~$1.6000"); + expect(formatEstimatedUsd({ kind: "unavailable" }, en, "en-US")).toBe("—"); + expect(formatEstimatedUsdValue(Number.NaN, en, "en-US")).toBe("—"); + }); +}); + +describe("Logs conversation cost aggregation", () => { + test("does not mark a mixed ordinary and lower-bound total as a lower bound", () => { + const summary = summarizeEstimatedCosts([ + { + usageStatus: "reported", + displayMetrics: { + cost: { + kind: "value", + estimate: { cost: { total: 1.6 }, priorityLowerBound: true }, + }, + }, + }, + { + usageStatus: "reported", + displayMetrics: { + cost: { + kind: "value", + estimate: { cost: { total: 0.4 } }, + }, + }, + }, + ]); + + expect(summary.estimatedCostUsd).toBe(2); + expect(summary.priorityLowerBound).toBe(false); + }); + + test("marks a total as a lower bound only when every priced estimate is one", () => { + const summary = summarizeEstimatedCosts([ + { + usageStatus: "reported", + displayMetrics: { + cost: { + kind: "value", + estimate: { cost: { total: 1.6 }, priorityLowerBound: true }, + }, + }, + }, + { + usageStatus: "reported", + displayMetrics: { + cost: { + kind: "value", + estimate: { cost: { total: 0.4 }, priorityLowerBound: true }, + }, + }, + }, + ]); + + expect(summary.estimatedCostUsd).toBe(2); + expect(summary.priorityLowerBound).toBe(true); + }); + + test("does not mark an unpriced-only total as a lower bound", () => { + const summary = summarizeEstimatedCosts([ + { + usageStatus: "reported", + displayMetrics: { cost: { kind: "unavailable" } }, + }, + ]); + + expect(summary.estimatedCostUsd).toBe(0); + expect(summary.priorityLowerBound).toBe(false); + expect(summary.unpricedRequests).toBe(1); }); }); From 9cd3c1c084e4521fcb46717a1cc7c9d5bf189381 Mon Sep 17 00:00:00 2001 From: olddonkey Date: Tue, 18 Aug 2026 23:32:44 -0700 Subject: [PATCH 4/5] fix(gui): translate estimated cost labels --- gui/src/i18n/de.ts | 6 +++--- gui/src/i18n/fr.ts | 6 +++--- gui/src/i18n/ja.ts | 6 +++--- gui/src/i18n/ko.ts | 6 +++--- gui/src/i18n/ru.ts | 6 +++--- gui/src/i18n/tr.ts | 6 +++--- gui/src/i18n/zh-TW.ts | 6 +++--- gui/src/i18n/zh.ts | 6 +++--- gui/tests/logs-priority-lower-bound.test.ts | 2 +- 9 files changed, 25 insertions(+), 25 deletions(-) diff --git a/gui/src/i18n/de.ts b/gui/src/i18n/de.ts index 6b3483938b..113fc419d2 100644 --- a/gui/src/i18n/de.ts +++ b/gui/src/i18n/de.ts @@ -645,9 +645,9 @@ export const de: Record = { "logs.conversation.totals": "{requests} Anfragen · {tokens} Tokens · {cost}", "logs.conversation.scope": "Summen gelten nur für den aktuell geladenen Logs-Ring.", "logs.conversation.excluded": "({unpriced} ohne Preis, {unmetered} ohne Messung vom ~$ ausgenommen)", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "ca. {amount}", + "logs.cost.lowerBound": "mind. {amount}", + "logs.cost.unavailable": "nicht verfügbar", "logs.detail.conversation": "Konversation", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/fr.ts b/gui/src/i18n/fr.ts index c9a3bb024c..112fd7ad2a 100644 --- a/gui/src/i18n/fr.ts +++ b/gui/src/i18n/fr.ts @@ -659,9 +659,9 @@ export const fr: Record = { "logs.conversation.totals": "{requests} requêtes · {tokens} jetons · {cost}", "logs.conversation.scope": "Les totaux couvrent uniquement le tampon circulaire des journaux actuellement chargé.", "logs.conversation.excluded": "({unpriced} sans tarif, {unmetered} sans mesure exclus du total en ~$)", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "env. {amount}", + "logs.cost.lowerBound": "au moins {amount}", + "logs.cost.unavailable": "indisponible", "logs.detail.conversation": "Conversation", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/ja.ts b/gui/src/i18n/ja.ts index 572e8d94f9..69fdac1c93 100644 --- a/gui/src/i18n/ja.ts +++ b/gui/src/i18n/ja.ts @@ -621,9 +621,9 @@ export const ja: Record = { "logs.conversation.totals": "{requests} 件 · {tokens} トークン · {cost}", "logs.conversation.scope": "合計は現在読み込まれている Logs リングのみです。", "logs.conversation.excluded": "(~$ から価格なし {unpriced} / 未計測 {unmetered} を除外)", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "約{amount}", + "logs.cost.lowerBound": "最低{amount}", + "logs.cost.unavailable": "利用不可", "logs.detail.conversation": "会話", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/ko.ts b/gui/src/i18n/ko.ts index 9accfcf624..9f491a1efc 100644 --- a/gui/src/i18n/ko.ts +++ b/gui/src/i18n/ko.ts @@ -664,9 +664,9 @@ export const ko: Record = { "logs.conversation.totals": "{requests}건 요청 · {tokens} 토큰 · {cost}", "logs.conversation.scope": "합계는 현재 로드된 Logs 링만 포함합니다.", "logs.conversation.excluded": "(~$에서 가격 없음 {unpriced}건, 미측정 {unmetered}건 제외)", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "약 {amount}", + "logs.cost.lowerBound": "최소 {amount}", + "logs.cost.unavailable": "사용 불가", "logs.detail.conversation": "대화", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/ru.ts b/gui/src/i18n/ru.ts index e7f358db2d..00aa9cb06b 100644 --- a/gui/src/i18n/ru.ts +++ b/gui/src/i18n/ru.ts @@ -662,9 +662,9 @@ export const ru: Record = { "logs.conversation.totals": "{requests} запросов · {tokens} токенов · {cost}", "logs.conversation.scope": "Итоги только по загруженному кольцу Logs.", "logs.conversation.excluded": "(из ~$ исключены {unpriced} без цены, {unmetered} без учёта)", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "около {amount}", + "logs.cost.lowerBound": "не менее {amount}", + "logs.cost.unavailable": "недоступно", "logs.detail.conversation": "Диалог", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/tr.ts b/gui/src/i18n/tr.ts index 1accd38130..743be2af77 100644 --- a/gui/src/i18n/tr.ts +++ b/gui/src/i18n/tr.ts @@ -669,9 +669,9 @@ export const tr: Record = { "logs.conversation.totals": "{requests} istek · {tokens} jeton · {cost}", "logs.conversation.scope": "Toplamlar yalnızca yüklü günlükleri kapsar.", "logs.conversation.excluded": "({unpriced} fiyatlandırılmamış, {unmetered} ölçülmemiş hariç)", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "yaklaşık {amount}", + "logs.cost.lowerBound": "en az {amount}", + "logs.cost.unavailable": "kullanılamıyor", "logs.detail.conversation": "Sohbet", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/src/i18n/zh-TW.ts b/gui/src/i18n/zh-TW.ts index 9eb218183a..c195aead79 100644 --- a/gui/src/i18n/zh-TW.ts +++ b/gui/src/i18n/zh-TW.ts @@ -516,9 +516,9 @@ export const zhTW: Record = { "logs.conversation.totals": "{requests} 次請求 · {tokens} tokens · {cost}", "logs.conversation.scope": "合計僅涵蓋目前已載入的 Logs 環形緩衝。", "logs.conversation.excluded": "(~$ 已排除 {unpriced} 筆無定價、{unmetered} 筆無計量)", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "約 {amount}", + "logs.cost.lowerBound": "至少 {amount}", + "logs.cost.unavailable": "無法估算", "logs.detail.conversation": "對話", "logs.badge.claude": "Claude", "logs.col.time": "時間", diff --git a/gui/src/i18n/zh.ts b/gui/src/i18n/zh.ts index 44b65d897a..7dd4beb860 100644 --- a/gui/src/i18n/zh.ts +++ b/gui/src/i18n/zh.ts @@ -657,9 +657,9 @@ export const zh: Record = { "logs.conversation.totals": "{requests} 次请求 · {tokens} tokens · {cost}", "logs.conversation.scope": "合计仅覆盖当前已加载的 Logs 环形缓冲。", "logs.conversation.excluded": "(~$ 已排除 {unpriced} 条无定价、{unmetered} 条无计量)", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "约 {amount}", + "logs.cost.lowerBound": "至少 {amount}", + "logs.cost.unavailable": "无法估算", "logs.detail.conversation": "会话", "logs.badge.claude": "Claude", "logs.badge.grok": "Grok", diff --git a/gui/tests/logs-priority-lower-bound.test.ts b/gui/tests/logs-priority-lower-bound.test.ts index bfd68bae3b..877252c07f 100644 --- a/gui/tests/logs-priority-lower-bound.test.ts +++ b/gui/tests/logs-priority-lower-bound.test.ts @@ -24,7 +24,7 @@ describe("Logs priority lower-bound formatting", () => { }); test("uses locale-aware USD placement and separators", () => { - expect(formatEstimatedUsdValue(1.6, de, "de-DE", false)).toBe("~1,6000\u00a0$"); + expect(formatEstimatedUsdValue(1.6, de, "de-DE", false)).toBe("ca. 1,6000\u00a0$"); }); }); From e1ef7942b11a9a5370895f17f881947c889decc2 Mon Sep 17 00:00:00 2001 From: jun Date: Wed, 19 Aug 2026 22:18:16 +0900 Subject: [PATCH 5/5] fix(usage): mark an assumed OpenRouter priority cost as a lower bound An assumed Fast attempt reported the standard total with no uncertainty marker, so the UI received a definite price for a request whose served tier the provider never echoed. OpenRouter bills by the tier actually served and documents priority as more expensive, so an unmarked standard total can understate the real charge. The confirmed case was already a lower bound because the premium endpoint price is not bundled here. The assumed case needs the same marker for a stronger reason: the outcome itself was never observed. Same treatment, different justification. Driven red: restricting the predicate back to confirmed-only fails the new regression and nothing else. --- src/usage/cost.ts | 8 +++++- tests/fastwire-observability.test.ts | 38 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/usage/cost.ts b/src/usage/cost.ts index 6a82604722..608dea31ac 100644 --- a/src/usage/cost.ts +++ b/src/usage/cost.ts @@ -459,6 +459,12 @@ function applyPriorityMultiplier( * branch does not bundle its provider-specific priority endpoint prices. A confirmed canonical * priority result can therefore use the standard price only as a provable lower bound. Do not * extend this to flex (cheaper) or to other providers without the same pricing contract. + * + * An ASSUMED priority attempt needs the same marker for a different reason. There the provider + * never echoed a tier at all, so the standard price is not merely a lower bound on a known + * premium — it is a floor under an outcome we did not observe. Returning it unmarked reports a + * definite standard cost for a request that may well have been billed as priority, which is the + * one thing a cost estimate must never do. */ function isOpenRouterPriorityLowerBound( provider: string, @@ -467,7 +473,7 @@ function isOpenRouterPriorityLowerBound( return baseProviderLabel(provider) === "openrouter" && outcome?.canonical === "priority" && outcome.fastOutcome === "applied" - && outcome.confirmation === "confirmed"; + && (outcome.confirmation === "confirmed" || outcome.confirmation === "assumed"); } /** diff --git a/tests/fastwire-observability.test.ts b/tests/fastwire-observability.test.ts index f29332f9e0..d712a038ad 100644 --- a/tests/fastwire-observability.test.ts +++ b/tests/fastwire-observability.test.ts @@ -689,6 +689,44 @@ describe("FastWire per-attempt cost", () => { expect(openAi.priorityLowerBound).toBeUndefined(); }); + test("an ASSUMED OpenRouter priority attempt is a lower bound, not a definite standard price", () => { + // The provider never echoed a tier, so we do not know which price was billed. Reporting + // the standard total unmarked would tell the UI "this cost 1.6" for a request that may + // have been served -- and billed -- as priority. The confirmed case is a lower bound + // because the premium price is not bundled; the assumed case is a lower bound because + // the OUTCOME itself was never observed. Both must carry the marker. + const usage = { inputTokens: 1_000_000, outputTokens: 0, cachedInputTokens: 0 }; + const assumedPriority = { + canonical: "priority" as const, + wireKind: "service-tier" as const, + wireValue: "priority", + fastOutcome: "applied" as const, + confirmation: "assumed" as const, + }; + const openRouterOverlays: ExpectedPriceOverlay[] = [{ + provider: "openrouter", + modelId: "openai/gpt-5.6-sol", + cost4: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 6.25 }, + source: "test", + verifiedAt: "2026-08-18", + status: "verified", + }]; + + const assumed = estimateComboCost([{ + ordinal: 1, + provider: "openrouter", + model: "openai/gpt-5.6-sol", + usageStatus: "reported", + usage, + tierOutcome: assumedPriority, + }], openRouterOverlays)!; + + expect(assumed.priorityLowerBound).toBe(true); + expect(assumed.attempts?.[0]?.priorityLowerBound).toBe(true); + // No premium multiplier is applied — the standard rate IS the floor being reported. + expect(assumed.priorityMultiplier).toBeUndefined(); + }); + test("management cost metadata exposes the aligned priority_lower_bound reason", () => { const result = costResult({ provider: "openrouter",