Identify OrcaRouter route ids as the routed model, not a branded label

This commit is contained in:
Aditya Vikram Singh 2026-08-23 17:59:27 +05:30
parent 5b25641440
commit dcab9a451c
3 changed files with 34 additions and 24 deletions

View file

@ -11,7 +11,7 @@
- **`CODEBURN_CACHE_SCOPE=all` forces a full session-cache read.** A ranged query reads only the month shards that can contribute a turn to it, which is a real behaviour change on a warm cache; this is the escape hatch for the case where a number looks wrong and you want to know whether the scoped read is why. Set it and every load ignores its scope and reads every shard, one-shot runs and the resident `codeburn serve` alike. It is a read policy, not an input to any cache fingerprint: setting or unsetting it re-parses nothing and invalidates nothing.
### Added (OrcaRouter)
- **OrcaRouter sessions now price and label like the model they route to.** OrcaRouter is a gateway that exposes route ids (`orcarouter/auto`, `orcarouter/fusion`, …) plus plain upstream ids (`deepseek/deepseek-v4-pro`), and reports the upstream id that actually ran in the completion response's `model` field. The `orcarouter/` prefix is now a routing wrapper like `cmd/` / `antigravity/`, so a routed spelling prices at its upstream LiteLLM row instead of $0; the smart route `orcarouter/auto` aliases to a fast Sonnet rate and the fusion routes alias to their current `openai/gpt-oss-120b` target, each keeping a branded route label (like the other `*-auto` presets); and an unknown vendor nested inside the route still fails closed.
- **OrcaRouter sessions now price and label like the model they route to.** OrcaRouter is a gateway that exposes route ids (`orcarouter/auto`, `orcarouter/fusion`, …) plus plain upstream ids (`deepseek/deepseek-v4-pro`), and reports the upstream id that actually ran in the completion response's `model` field. The `orcarouter/` prefix is now a routing wrapper like `cmd/` / `antigravity/`, so a routed spelling prices at its upstream LiteLLM row instead of $0; the smart route `orcarouter/auto` aliases to a fast Sonnet rate and the fusion routes alias to their current `openai/gpt-oss-120b` target, so display and report identity match those routed models; and an unknown vendor nested inside the route still fails closed.
### Added (Windows)
- **`codeburn menubar` installs and launches the tray app on Windows.** The same command that installs the macOS menubar now does the Windows one, through the same pinned-release path: it resolves `windows-v<cliVersion>`, falls back to a scan of the newest `windows-v*` release carrying both assets when that tag has none, downloads the `.msi` with the same retry and backoff, and verifies its sha256 before anything executes it — a mismatch aborts without ever handing the file to the installer. It then runs `msiexec` out of `%SystemRoot%\System32` (never a bare name, so nothing dropped next to the CLI can impersonate it) with `/i <msi> /passive /norestart`, treats exit 3010 as installed-pending-restart and 1602 as a cancelled install rather than failures, and launches the exe named by the product's Uninstall registry key. An already-installed matching version skips the download and just launches; `--force` reinstalls.

View file

@ -290,8 +290,9 @@ export async function loadPricing(): Promise<void> {
// Known model name variants that providers emit but LiteLLM/fallback don't index under.
// OMP emits 'anthropic--claude-4.6-opus' (double-dash, dot version, tier-last).
// getCanonicalName strips a KNOWN vendor/router prefix first, so only the
// post-strip forms need to be listed here.
// getCanonicalName strips a KNOWN vendor/router prefix first unless the
// full cleaned id itself is an alias (orcarouter/auto). Post-strip forms
// still cover every other entry here.
const BUILTIN_ALIASES: Record<string, string> = {
'anthropic--claude-4.6-opus': 'claude-opus-4-6',
'anthropic--claude-4.6-sonnet': 'claude-sonnet-4-6',
@ -347,11 +348,12 @@ const BUILTIN_ALIASES: Record<string, string> = {
// OrcaRouter's smart route. The route picks a model per request; at the time
// of writing it lands on a Qwen/Llama flash model, so a fast Sonnet rate is
// the honest estimate until the route's target stabilizes (mirrors the
// `*-auto` presets above).
// `*-auto` presets above). Display and report identity follow this target.
'orcarouter/auto': 'claude-sonnet-4-5',
// OrcaRouter's fusion routes currently serve openai/gpt-oss-120b (verified
// live 2026-08). If the gateway re-routes them, these drift like any other
// preset estimate; they keep a priced row instead of reporting $0.
// preset estimate; they keep a priced row instead of reporting $0. Display
// and report identity follow this target, not a branded route label.
'orcarouter/fusion': 'openai/gpt-oss-120b',
'orcarouter/fusion-flash': 'openai/gpt-oss-120b',
'orcarouter/fusion-mini': 'openai/gpt-oss-120b',
@ -785,12 +787,21 @@ function resolveAlias(model: string): string {
return model
}
function getCanonicalName(model: string): string {
return stripKnownFirstNamespace(
model
.replace(/@.*$/, '')
.replace(/-\d{8}$/, '')
.replace(/\[[^\]]*\]$/, ''),
)
const cleaned = model
.replace(/@.*$/, '')
.replace(/-\d{8}$/, '')
.replace(/\[[^\]]*\]$/, '')
// Full-id aliases (orcarouter/auto) must stay visible so resolveAlias can
// see them. Stripping first would leave a leaf (`auto`) with no mapping.
// Nested wrappers without an alias still peel as before.
if (Object.hasOwn(userAliases, cleaned) || Object.hasOwn(BUILTIN_ALIASES, cleaned)) {
return cleaned
}
const lowercase = cleaned.toLowerCase()
if (lowercase !== cleaned && Object.hasOwn(BUILTIN_ALIASES, lowercase)) {
return cleaned
}
return stripKnownFirstNamespace(cleaned)
}
/// Alias-resolved identity for report merge. Display names stay cosmetic —
@ -1167,14 +1178,6 @@ const autoModelNames: Record<string, string> = {
'openclaw-auto': 'OpenClaw (auto)',
'qwen-auto': 'Qwen (auto)',
'kimi-auto': 'Kimi (auto)',
// OrcaRouter route ids. The smart route routes per request and the fusion
// routes resolve to a gateway-picked upstream, so each keeps its branded
// route label rather than the current upstream's display name. Prices are
// aliased in BUILTIN_ALIASES to the route's current target.
'orcarouter/auto': 'OrcaRouter (auto)',
'orcarouter/fusion': 'OrcaRouter Fusion',
'orcarouter/fusion-flash': 'OrcaRouter Fusion Flash',
'orcarouter/fusion-mini': 'OrcaRouter Fusion Mini',
'codex-auto-review': 'Codex Auto Review',
}

View file

@ -218,6 +218,13 @@ describe('resolveCanonicalModelId', () => {
expect(resolveCanonicalModelId('claude-opus-4.6')).toBe('claude-opus-4-6')
expect(resolveCanonicalModelId('kimi-code')).toBe('kimi-k2-thinking')
expect(resolveCanonicalModelId('cline-pass/kimi-k3')).toBe('kimi-k3')
expect(resolveCanonicalModelId('orcarouter/auto')).toBe(resolveCanonicalModelId('claude-sonnet-4-5'))
expect(resolveCanonicalModelId('orcarouter/fusion')).toBe(resolveCanonicalModelId('openai/gpt-oss-120b'))
expect(resolveCanonicalModelId('orcarouter/fusion-flash')).toBe(resolveCanonicalModelId('openai/gpt-oss-120b'))
expect(resolveCanonicalModelId('orcarouter/fusion-mini')).toBe(resolveCanonicalModelId('openai/gpt-oss-120b'))
expect(resolveCanonicalModelId('orcarouter/deepseek/deepseek-v4-pro')).toBe(
resolveCanonicalModelId('deepseek/deepseek-v4-pro'),
)
})
})
@ -282,11 +289,11 @@ describe('getShortModelName', () => {
expect(getShortModelName('cp/cline-pass/glm-5.3')).toBe('GLM-5.3')
// OrcaRouter route ids peel to the upstream id, which keeps the upstream label.
expect(getShortModelName('orcarouter/deepseek/deepseek-v4-pro')).toBe('DeepSeek v4 Pro')
// The route ids keep their branded labels (like the other `*-auto` presets).
expect(getShortModelName('orcarouter/auto')).toBe('OrcaRouter (auto)')
expect(getShortModelName('orcarouter/fusion')).toBe('OrcaRouter Fusion')
expect(getShortModelName('orcarouter/fusion-flash')).toBe('OrcaRouter Fusion Flash')
expect(getShortModelName('orcarouter/fusion-mini')).toBe('OrcaRouter Fusion Mini')
// Route ids display as the model they route to, not a branded gateway label.
expect(getShortModelName('orcarouter/auto')).toBe(getShortModelName('claude-sonnet-4-5'))
expect(getShortModelName('orcarouter/fusion')).toBe(getShortModelName('openai/gpt-oss-120b'))
expect(getShortModelName('orcarouter/fusion-flash')).toBe(getShortModelName('openai/gpt-oss-120b'))
expect(getShortModelName('orcarouter/fusion-mini')).toBe(getShortModelName('openai/gpt-oss-120b'))
// Grok Build prices via the grok-build-0.1 sibling.
expect(getShortModelName('grok-build')).toBe('Grok Build')
expect(getShortModelName('grok-build-0.1')).toBe('Grok Build')