Skip to content

Commit df576cf

Browse files
dallascrilleyDexterStorey
authored andcommitted
settings shows live routing state
1 parent 8999da2 commit df576cf

5 files changed

Lines changed: 69 additions & 6 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
- [2026-09-30] pick which accounts auto-rotation uses first
1+
- [2026-09-30] settings shows live routing state
2+
- [2026-09-30] [pick which accounts auto-rotation uses first](https://github.com/RubricLab/tokenmaxx/commit/8999da2b9c11f204d5b2d932b64fb221e52646dc)
23
- [2026-09-23] price fable 5.1, opus 5.5, sonnet 5, gpt-6 and gpt-5.6 at current rates
34
- [2026-08-21] codex keeps its shell and apply_patch tools on the gpt-5.6 models
45
- [2026-08-18] meter clients that hang up early

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,5 @@
5959
"post-commit": "bun x @rubriclab/package post-commit"
6060
},
6161
"type": "module",
62-
"version": "0.0.68"
62+
"version": "0.0.69"
6363
}

‎src/config-install.test.ts‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,47 @@ describe('installCodexConfig', () => {
8989
expect(status.codexStale).toBe(false)
9090
})
9191

92+
test('installStatus stays truthful when Bun.TOML cannot parse the config', async () => {
93+
// Bun.TOML rejects bare table keys that start with a digit, like
94+
// [mcp_servers.1password]; codex accepts them. A parse failure must not
95+
// read as "not routed" while our selection line is active.
96+
await writeCodexConfig(
97+
`${legacyBrokenConfig}\n[mcp_servers.1password]\ncommand = "1password-mcp"\nenabled = false\n`
98+
)
99+
await installCodexConfig(paths())
100+
const written = await readCodexConfig()
101+
expect(() => Bun.TOML.parse(written)).toThrow()
102+
const status = await installStatus()
103+
expect(status.codexRouted).toBe(true)
104+
})
105+
106+
test('an unparseable config without our selection still reads as not routed', async () => {
107+
await writeCodexConfig(
108+
'model = "gpt-5.6-sol"\n\n[mcp_servers.1password]\ncommand = "1password-mcp"\n'
109+
)
110+
const status = await installStatus()
111+
expect(status.codexRouted).toBe(false)
112+
})
113+
114+
test('the fallback ignores a swallowed legacy selection under a table', async () => {
115+
// legacyBrokenConfig's model_provider = "tokmax" sits under [notice], so
116+
// codex never routes through it; the digit table only breaks parsing.
117+
await writeCodexConfig(
118+
`${legacyBrokenConfig}\n[mcp_servers.1password]\ncommand = "1password-mcp"\n`
119+
)
120+
const status = await installStatus()
121+
expect(status.codexRouted).toBe(false)
122+
expect(status.codexStale).toBe(true)
123+
})
124+
125+
test('the fallback ignores our provider named inside a codex profile', async () => {
126+
await writeCodexConfig(
127+
'model_provider = "ollama"\n\n[profiles.work]\nmodel_provider = "tokenmaxx"\n\n[mcp_servers.1password]\ncommand = "1password-mcp"\n'
128+
)
129+
const status = await installStatus()
130+
expect(status.codexRouted).toBe(false)
131+
})
132+
92133
test('reinstall is idempotent', async () => {
93134
await writeCodexConfig(legacyBrokenConfig)
94135
await installCodexConfig(paths())

‎src/config-install.ts‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,15 @@ export async function installStatus(): Promise<InstallStatus> {
196196
const baseUrl = selected === null ? undefined : parsed.model_providers?.[selected]?.base_url
197197
codexRouted = typeof baseUrl === 'string' && baseUrl.includes('127.0.0.1')
198198
} catch {
199-
codexRouted = false
199+
// Bun.TOML rejects configs codex accepts — bare table keys starting with a
200+
// digit, like [mcp_servers.1password]. Reading that as "not routed" makes
201+
// the dashboard show routing off while traffic flows through the proxy,
202+
// and turns the routing toggle into a re-install. Fall back to our own
203+
// active selection line, scanning only the top-level region: a
204+
// model_provider line under a table belongs to that table, not to codex.
205+
const firstTable = codexRaw.search(/^\[/m)
206+
const topLevel = firstTable === -1 ? codexRaw : codexRaw.slice(0, firstTable)
207+
codexRouted = topLevel.split('\n').some(line => ownProviderSelection.test(line))
200208
}
201209
const codexStale =
202210
!codexRouted &&

‎src/tui/dashboard.ts‎

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { Box, createCliRenderer, parseColor, type RGBA, Text } from '@opentui/core'
2-
import { installPiConfig, type PiStatus, piStatus, uninstallPiConfig } from '../config-install.ts'
2+
import {
3+
installPiConfig,
4+
installStatus,
5+
type PiStatus,
6+
piStatus,
7+
uninstallPiConfig
8+
} from '../config-install.ts'
39
import type {
410
Account,
511
AnalyticsSnapshot,
@@ -1358,6 +1364,11 @@ export async function runTuiDashboard(
13581364
: buildScenario(fixture.name, simulatedNow)
13591365
let rows = orderedRows(analytics.snapshot)
13601366
let pi: PiStatus = live ? await piStatus() : { present: true, routed: true }
1367+
// Routing is derived from the harness config files, which can change while
1368+
// this dashboard is open (tokenmaxx install/uninstall from another shell,
1369+
// first-login auto-enable, daemon heal after an update). options.routing is
1370+
// only the launch-time snapshot; reload() keeps this current.
1371+
let routing = options.routing
13611372
const state: ViewState = {
13621373
addConfirm: null,
13631374
alert: options.alert ?? '',
@@ -1398,7 +1409,7 @@ export async function runTuiDashboard(
13981409
columns,
13991410
now: live ? Date.now() : simulatedNow,
14001411
pi,
1401-
routing: options.routing,
1412+
routing,
14021413
rows: process.stdout.rows ?? 24,
14031414
switchFlagMs: fixture !== undefined && fixture.timewarp > 0 ? 24 * 60_000 : 120_000,
14041415
theme: currentTheme(),
@@ -1447,6 +1458,8 @@ export async function runTuiDashboard(
14471458
analytics = await readAnalytics(socketPath)
14481459
rows = orderedRows(analytics.snapshot)
14491460
pi = await piStatus()
1461+
const status = await installStatus()
1462+
routing = { anthropic: status.claudeRouted, openai: status.codexRouted }
14501463
clampSelection()
14511464
})
14521465

@@ -1608,7 +1621,7 @@ export async function runTuiDashboard(
16081621
}
16091622

16101623
const toggleRouting = (provider: ProviderId) => {
1611-
finish({ enable: !options.routing[provider], kind: 'routing', provider })
1624+
finish({ enable: !routing[provider], kind: 'routing', provider })
16121625
}
16131626

16141627
const adjustSetting = (delta: number) => {

0 commit comments

Comments
 (0)