Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions devlog/_plan/260818_fastwire_b2_xai/evidence/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# FastWire B2 (xAI) — UI evidence

`010_logs_priority_lower_bound.png` — Logs & Debug, three seeded `xai/grok-4.6` rows
that exercise every branch of the new pricing path:

| Row | Situation | Cost cell |
| --- | --- | --- |
| `req-standard` | no Fast requested | `~$0.0300` |
| `req-priority` | response-confirmed priority, prompt under the long-context threshold | `~$0.0600` — exactly the documented 2x premium over the row above |
| `req-longctx-priority` | response-confirmed priority, prompt at or above 200k | `≥$0.8760` — the published long-context rate, marked a lower bound because xAI publishes no combined price |

The `≥` prefix is the visible change: a cost that is a known floor rather than an
estimate now says so instead of rendering as `~$`. The detail drawer explains why
via the `priority_lower_bound` estimate reason.

Captured against a local proxy with a seeded `usage.jsonl`; no live xAI request was
billed to produce it.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ differing backup and rewrites known legacy namespaced selected ids to bare ids.
| `modelMaxInputTokens?` | `Record<string, number>` | Positive per-model max input limits used for catalog auto-compaction hints. |
| `defaultMaxOutputTokens?` | `number` | Provider-wide `openai-chat` fallback when the client omits `max_output_tokens`. |
| `modelMaxOutputTokens?` | `Record<string, number>` | Positive per-model `openai-chat` fallback budgets; exact/pattern matches beat the provider default. |
| `modelCosts?` | `Record<string, Cost4>` | Per-model display prices (USD per 1M tokens), keyed by that provider's exact upstream model id — not a provider identifier or a routed `provider/model` label, e.g. `{ "deepseek-v4-flash": { "input": 0.14, "output": 0.28, "cacheRead": 0.0028, "cacheWrite": 0 } }`. Any model id is a valid key — custom providers may target any OpenAI-compatible endpoint through the `openai-chat` adapter, and local or internal provider ids work even when they are absent from the built-in catalogs. User-configured prices win over the built-in catalogs in the Logs `~$` and Usage estimates; historical entries are repriced from the current overlay, so editing a price can move past totals. The fallback order is user `modelCosts` → jawcode catalog → expected-price overlay → model-level vendor fallback, and an all-zero entry falls through to the next source in that sequence. Each rate must be a non-negative finite number at most 1,000,000 (USD per 1M tokens); out-of-range rows are rejected by the management boundary and dropped on load. Display-time estimation only: overlays never affect routing, account selection, quotas, or billing. |
| `modelCosts?` | `Record<string, Cost4>` | Per-model display prices (USD per 1M tokens), keyed by that provider's exact upstream model id — not a provider identifier or a routed `provider/model` label, e.g. `{ "deepseek-v4-flash": { "input": 0.14, "output": 0.28, "cacheRead": 0.0028, "cacheWrite": 0 } }`. Any model id is a valid key — custom providers may target any OpenAI-compatible endpoint through the `openai-chat` adapter, and local or internal provider ids work even when they are absent from the built-in catalogs. User-configured prices win over the built-in catalogs in the Logs `~$` and Usage estimates; historical entries are repriced from the current overlay, so editing a price can move past totals. The fallback order is user `modelCosts` → exact official correction → jawcode catalog → expected-price overlay → model-level vendor fallback, and an all-zero entry falls through to the next source in that sequence. Each rate must be a non-negative finite number at most 1,000,000 (USD per 1M tokens); out-of-range rows are rejected by the management boundary and dropped on load. Display-time estimation only: overlays never affect routing, account selection, quotas, or billing. |
| `headers?` | `Record<string, string>` | Extra upstream headers. Authorization, cookies, API-key headers, embedded newlines, and invalid names are rejected. |
| `openRouterRouting?` | `OpenRouterProviderRouting` | Default OpenRouter `order`, `only`, and `allowFallbacks` preferences; valid only for canonical OpenRouter with `openai-chat`. |
| `modelOpenRouterRouting?` | `Record<string, OpenRouterProviderRouting>` | Exact model-id overrides that replace the provider-wide OpenRouter preference. |
Expand Down Expand Up @@ -151,6 +151,25 @@ contract; existing configurations see these migration deltas:

Explicit capability `false` and Responses caller-tier forwarding retain their existing contracts.

### xAI Priority Processing

The built-in `xai` preset advertises and injects Fast only when its effective transport uses
`authMode: "key"`. API-key mode targets `https://api.x.ai/v1` through the `openai-chat` adapter and
sends `service_tier: "priority"` through Chat Completions. `ocx login xai`
instead stores OAuth credentials for the separate Grok CLI subscription-gateway flow, so OAuth
remains unclassified: its catalog rows do not advertise Fast and the proxy does not inject a tier.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

xAI charges Priority Processing at 2× the standard token price for input, output, cached, and
reasoning tokens; cache discounts are applied before the multiplier. Cost estimates use that premium
only when xAI's response confirms `service_tier: "priority"`. A missing or unparsed response tier is
not confirmation, and an echoed `default` is a downgrade; all three stay at the standard price.

For `grok-4.6`, the standard rate per 1M tokens is $2.00 input, $0.50 cached input, and $6.00
output. A prompt of at least 200,000 tokens reprices the whole request at $4.00 / $1.00 / $12.00.
xAI has not published how that long-context band combines with Priority Processing. When a
long-context response confirms `priority`, the dashboard therefore shows the published long-context
cost with a `≥` marker and a lower-bound explanation; it never invents a stacked multiplier.

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).
Expand Down
4 changes: 4 additions & 0 deletions gui/src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,9 @@ export const de: Record<TKey, string> = {
"logs.col.tokens": "Tokens",
"logs.col.tokPerSec": "tok/s",
"logs.col.estimatedCost": "~$",
"logs.cost.approximate": "ca. {amount}",
"logs.cost.lowerBound": "mind. {amount}",
"logs.cost.unavailable": "nicht verfügbar",
"logs.metric.tokPerSecTitle": "Ausgabe-Tokens pro Sekunde über die gesamte Anfragedauer",
"logs.metric.estimatedCostTitle": "API-Listenpreis-Äquivalent, keine tatsächliche Belastung; bei fehlendem Preisabgleich nicht verfügbar",
"usage.cost.total": "API-Listenpreis-Äquivalent (dieser Zeitraum)",
Expand Down Expand Up @@ -711,6 +714,7 @@ export const de: Record<TKey, string> = {
"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": "xAI hat keinen kombinierten Preis für Priority und langen Kontext veröffentlicht; die angezeigten Kosten sind eine Untergrenze.",
"logs.col.error": "Fehler",
"logs.col.upstreamReason": "Upstream-Grund",
"logs.col.duration": "Dauer",
Expand Down
4 changes: 4 additions & 0 deletions gui/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,9 @@ export const en = {
"logs.col.tokens": "Tokens",
"logs.col.tokPerSec": "tok/s",
"logs.col.estimatedCost": "~$",
"logs.cost.approximate": "~{amount}",
"logs.cost.lowerBound": "≥{amount}",
"logs.cost.unavailable": "—",
"logs.metric.tokPerSecTitle": "Output tokens per second over the full request duration",
"logs.metric.estimatedCostTitle": "API list-price equivalent, not an actual charge; unmatched pricing is unavailable",
"usage.cost.total": "API list-price equivalent (this range)",
Expand Down Expand Up @@ -744,6 +747,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": "xAI has not published a combined Priority and long-context price; the displayed cost is a lower bound.",
"logs.col.error": "Error",
"logs.col.upstreamReason": "Upstream reason",
"logs.col.duration": "Duration",
Expand Down
4 changes: 4 additions & 0 deletions gui/src/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,9 @@ export const fr: Record<TKey, string> = {
"logs.col.tokens": "Jetons",
"logs.col.tokPerSec": "jetons/s",
"logs.col.estimatedCost": "~$",
"logs.cost.approximate": "env. {amount}",
"logs.cost.lowerBound": "au moins {amount}",
"logs.cost.unavailable": "indisponible",
"logs.metric.tokPerSecTitle": "Jetons de sortie par seconde sur toute la durée de la requête",
"logs.metric.estimatedCostTitle": "Équivalent au tarif catalogue de l’API, et non montant réellement facturé ; aucun tarif n’est disponible en l’absence de correspondance",
"usage.cost.total": "Équivalent au tarif catalogue de l’API (cette période)",
Expand Down Expand Up @@ -725,6 +728,7 @@ export const fr: Record<TKey, string> = {
"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": "xAI n’a pas publié de tarif combinant Priority et contexte long ; le coût affiché est une borne inférieure.",
"logs.col.error": "Erreur",
"logs.col.upstreamReason": "Motif en amont",
"logs.col.duration": "Durée",
Expand Down
4 changes: 4 additions & 0 deletions gui/src/i18n/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,9 @@ export const ja: Record<TKey, string> = {
"logs.col.tokens": "トークン",
"logs.col.tokPerSec": "tok/s",
"logs.col.estimatedCost": "~$",
"logs.cost.approximate": "約{amount}",
"logs.cost.lowerBound": "最低{amount}",
"logs.cost.unavailable": "利用不可",
"logs.metric.tokPerSecTitle": "リクエスト全体の所要時間あたりの出力トークン数",
"logs.metric.estimatedCostTitle": "API 定価相当額(実際の請求ではありません); 未対応の価格は利用できません",
"usage.cost.total": "API 定価相当額(この期間)",
Expand Down Expand Up @@ -687,6 +690,7 @@ export const ja: Record<TKey, string> = {
"logs.detail.estimate.cache_detail_missing": "キャッシュの詳細が利用できませんでした; 入力は上限の推定です。",
"logs.detail.estimate.expected_price_overlay": "検証済みの予想定価が使用されました。",
"logs.detail.estimate.provider_cost_overlay": "プロバイダー設定の価格オーバーレイが使用されました。",
"logs.detail.estimate.priority_lower_bound": "xAI は Priority と長いコンテキストの組み合わせ価格を公開していないため、表示額は下限です。",
"logs.col.error": "エラー",
"logs.col.upstreamReason": "上流の理由",
"logs.col.duration": "所要時間",
Expand Down
4 changes: 4 additions & 0 deletions gui/src/i18n/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,9 @@ export const ko: Record<TKey, string> = {
"logs.col.tokens": "토큰",
"logs.col.tokPerSec": "tok/s",
"logs.col.estimatedCost": "~$",
"logs.cost.approximate": "약 {amount}",
"logs.cost.lowerBound": "최소 {amount}",
"logs.cost.unavailable": "사용 불가",
"logs.metric.tokPerSecTitle": "전체 요청 시간 기준 초당 출력 토큰",
"logs.metric.estimatedCostTitle": "API 정가 환산치이며 실제 청구액이 아닙니다. 가격 미매칭은 표시하지 않습니다.",
"usage.cost.total": "API 정가 환산치 (이 기간)",
Expand Down Expand Up @@ -730,6 +733,7 @@ export const ko: Record<TKey, string> = {
"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": "xAI가 Priority와 긴 컨텍스트의 결합 가격을 공개하지 않아 표시 비용은 하한입니다.",
"logs.col.error": "오류",
"logs.col.upstreamReason": "업스트림 원인",
"logs.col.duration": "소요 시간",
Expand Down
4 changes: 4 additions & 0 deletions gui/src/i18n/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,9 @@ export const ru: Record<TKey, string> = {
"logs.col.tokens": "Токены",
"logs.col.tokPerSec": "tok/s",
"logs.col.estimatedCost": "~$",
"logs.cost.approximate": "около {amount}",
"logs.cost.lowerBound": "не менее {amount}",
"logs.cost.unavailable": "недоступно",
"logs.metric.tokPerSecTitle": "Выходные токены в секунду за полную длительность запроса",
"logs.metric.estimatedCostTitle": "Эквивалент стоимости по прайс-листу API, а не фактическое списание; если цену не удалось сопоставить, значение недоступно",
"usage.cost.total": "Эквивалент стоимости по прайс-листу API (за этот период)",
Expand Down Expand Up @@ -728,6 +731,7 @@ export const ru: Record<TKey, string> = {
"logs.detail.estimate.cache_detail_missing": "Детализация кэша недоступна; входные токены оценены по верхней границе.",
"logs.detail.estimate.expected_price_overlay": "Использована подтверждённая ожидаемая цена из прайс-листа.",
"logs.detail.estimate.provider_cost_overlay": "Использован ценовой оверлей провайдера.",
"logs.detail.estimate.priority_lower_bound": "xAI не опубликовала совмещённую цену Priority и длинного контекста; показанная стоимость является нижней границей.",
"logs.col.error": "Ошибка",
"logs.col.upstreamReason": "Причина от провайдера",
"logs.col.duration": "Длительность",
Expand Down
4 changes: 4 additions & 0 deletions gui/src/i18n/tr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,9 @@ export const tr: Record<TKey, string> = {
"logs.col.tokens": "Jetonlar",
"logs.col.tokPerSec": "jeton/sn",
"logs.col.estimatedCost": "~$",
"logs.cost.approximate": "yaklaşık {amount}",
"logs.cost.lowerBound": "en az {amount}",
"logs.cost.unavailable": "kullanılamıyor",
"logs.metric.tokPerSecTitle": "Çıktı jetonu / saniye",
"logs.metric.estimatedCostTitle": "Tahmini API liste fiyatı",
"usage.cost.total": "API liste fiyatı eşdeğeri",
Expand Down Expand Up @@ -735,6 +738,7 @@ export const tr: Record<TKey, string> = {
"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": "xAI, Priority ile uzun bağlamın birleşik fiyatını yayımlamadı; gösterilen maliyet alt sınırdır.",
"logs.col.error": "Hata",
"logs.col.upstreamReason": "Yukarı akış nedeni",
"logs.col.duration": "Süre",
Expand Down
4 changes: 4 additions & 0 deletions gui/src/i18n/zh-TW.ts
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,9 @@ export const zhTW: Record<TKey, string> = {
"logs.col.tokens": "Token 數",
"logs.col.tokPerSec": "tok/s",
"logs.col.estimatedCost": "~$",
"logs.cost.approximate": "約 {amount}",
"logs.cost.lowerBound": "至少 {amount}",
"logs.cost.unavailable": "無法估算",
"logs.metric.tokPerSecTitle": "按完整請求耗時計算的每秒輸出 token",
"logs.metric.estimatedCostTitle": "按 API 標價估算,並非實際扣費;價格無法符合時不顯示",
"usage.cost.total": "API 標價折算(當前範圍)",
Expand Down Expand Up @@ -1809,6 +1812,7 @@ export const zhTW: Record<TKey, string> = {
"logs.detail.attempt.recovery.emptyCompletion": "空白完成重試",
"logs.detail.attempt.recovery.unknown": "未知的復原原因",
"logs.detail.estimate.provider_cost_overlay": "已使用供應商設定的價格覆蓋。",
"logs.detail.estimate.priority_lower_bound": "xAI 尚未公布 Priority 與長上下文的組合價格;目前顯示的是費用下界。",
"pws.cockpitImportDescription": "從此裝置匯入 Cockpit Tools Antigravity JSON 匯出檔。不會顯示檔案內容。",
"pws.cockpitImportFileLabel": "Cockpit Tools Antigravity JSON 匯出檔",
"pws.cockpitImportChooseFile": "選擇 JSON 檔案",
Expand Down
4 changes: 4 additions & 0 deletions gui/src/i18n/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,9 @@ export const zh: Record<TKey, string> = {
"logs.col.tokens": "Token 数",
"logs.col.tokPerSec": "tok/s",
"logs.col.estimatedCost": "~$",
"logs.cost.approximate": "约 {amount}",
"logs.cost.lowerBound": "至少 {amount}",
"logs.cost.unavailable": "无法估算",
"logs.metric.tokPerSecTitle": "按完整请求耗时计算的每秒输出 token",
"logs.metric.estimatedCostTitle": "按 API 标价估算,并非实际扣费;价格无法匹配时不显示",
"usage.cost.total": "API 标价折算(当前范围)",
Expand Down Expand Up @@ -723,6 +726,7 @@ export const zh: Record<TKey, string> = {
"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": "xAI 尚未公布 Priority 与长上下文的组合价格;当前显示的是费用下界。",
"logs.col.error": "错误",
"logs.col.upstreamReason": "上游原因",
"logs.col.duration": "耗时",
Expand Down
Loading
Loading