Repository navigation
feat(gui): live routing tab: see which account answered, why others were skipped, and where the time went - #8730
Closed
andrew05060414 wants to merge 8 commits into
Closed
andrew05060414 wants to merge 8 commits into
andrew05060414 wants to merge 8 commits into
Conversation
…he final request row The final request log of a request served by a multi-account generic OAuth provider now carries accountRoster: each account's hashed o-label and whether it was available, paused, needing re-auth, cooling down, out of quota, or not listing the model. It stays in memory for /api/logs and never reaches usage.jsonl. /api/oauth/accounts returns the same logLabel per account so the dashboard can name the account a roster label belongs to.
… long privacy redaction took Adds upstreamSendMs (request start to the final attempt's start, which includes earlier failed attempts) and an optional privacyRedactionMs to the in-memory request row, so the live routing view can split a request's time into measured phases without inventing DNS or TLS numbers.
Models gains a Live routing tab (#models/live) that polls /api/logs while visible. For the latest or a pinned request it shows client -> OpenCodex -> candidates, marking the account or target that answered, the ones that failed with their status and reason, and the ones skipped with the reason the route decision or the account pool recorded. An outcome sentence and a step list explain the route. The request list groups by request, session or key and shows account, model, effort, duration, time to first token, tokens, cache-hit rate, tok/s and estimated cost; unknown values show a dash, never zero. Combos and accounts keep their own pages and are linked.
The live routing view gains a time bar for the pinned or latest request: privacy redaction, OpenCodex internal time, earlier failed attempts, the wait for the upstream's first token, and streaming. Every segment comes from a measured field; a request without timing says so instead of drawing a bar, and no DNS or TLS split is shown because Bun's fetch does not expose one.
…nly in the live routing view A combo row showed the target it landed on as what the client asked for; it now shows the combo. An API-key account reads as its provider plus a short fingerprint instead of a 33-character digest, and the explicit-provider, alias, rule and native route reasons have plain sentences.
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
7 tasks done
Contributor
|
Contributor
⏳ DRAFT
What to do
Review readiness checklist
✅ 4/4 boxes ticked. This pull request was already a draft. Its draft status will be preserved after every issue above is resolved. Hygiene
|
7 tasks done
Contributor
Author
|
Superseded by #8741, which carries this change together with the related live routing PRs as one commit each on current |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The problem. When a request goes through OpenCodex there is no single place to see how it was routed: which account or combo target answered, why the other accounts were passed over, where the time went. The Logs page has the raw rows, but the reasoning is spread across
routeDecision,attempts[]and account state that is never recorded at all.What changes. The Models page gets a Live routing tab (
#models/live), modeled on the routing page of Magpie (MIT, © yetone; ported logic carries the notice). For the latest request, or one selected in the list, it shows:fetchdoes not expose one.Combos and accounts keep their own pages; the tab links to them (Models › Combos, and the provider's Accounts tab with a one-line pool summary).
Who notices. Anyone running several OAuth accounts or combos can now answer "why did this request land on that account?" without reading JSON.
Backend (small, in-memory only)
accountRosteron the final request row: for a request served by a multi-account generic OAuth provider, each account's hashedo-label and its state when the request finished (available,paused,needs-reauth,cooldown,quota-exhausted,model-unlisted), classified with the same checks the selector uses. Registered by the OAuth layer into a slot (src/server/request-log-route-live.ts), sorequest-log.tsdoes not importsrc/oauth, and an install that never loads OAuth pays one null check. The gate is the servedo-label, which needs no config read.upstreamSendMs(request start to the final attempt's start) and an optionalprivacyRedactionMs, so the time bar is built from measurements only.GET /api/oauth/accountsreturns the samelogLabelper generic OAuth account, so the dashboard can show the account's display label for a roster entry.usage.jsonl: the persistence projection rebuilds its row field by field and does not copy them. No bodies, account ids, emails or secrets are recorded.request-log.tsgrows by 3 lines (1983 → 1986, cap 2000); everything else lives in new sibling files. No new import reachessrc/lab/from the core path.A stacked follow-up PR (#8731) adds the context-window breakdown (system prompt, tools, skills, memory files, files, tool results, per-turn) on top of this.
Screenshots
Local test instance with a fake upstream: four OAuth accounts (one rate-limited, one paused, one needing sign-in) and a failover combo. Account labels are aliases from the fake store.
(The screenshot was taken on the stacked branch, so it also shows the context-window card from the follow-up PR.)
Verification
bun run typecheck,bun run structure:check,bun run privacy:scan: pass.tests/usage/request-log-account-roster.test.ts,tests/usage/request-log-route-live-timing.test.ts,tests/oauth/oauth-accounts-log-label.test.ts,tests/usage/request-log.test.ts,tests/lab/core-lab-boundary.test.ts,tests/ci-workflows/file-size-ratchet.test.ts,tests/test-layout.test.ts,tests/gui/models-workspace-tabs.test.ts: pass.cd gui && bun test tests/route-live* tests/fr-localization.test.ts tests/locale-parity.test.ts tests/models-workspace-panels.test.tsx tests/compatibility-lab.test.tsx tests/models-keep-native-v1-placement.test.ts(includes newroute-live-model,route-live-time,route-live-render),bun run lint,bun run lint:i18n,tsc --noEmit,bun run build: pass.bun run testsuite. Several sessions were running suites on the same Windows machine, so full-suite timeouts there were load, not signal; and the test preload's git-config guard rejectsGIT_CONFIG_GLOBAL=NULwith this machine's git 2.56, failing the first case of every file and a handful oftest-layout-toolingcases on unmodifieddevas well. Focused files ran withOCX_GIT_CONFIG_GUARD_CHECKOUTpointing at a directory without.git. A local GUI suite run showed no failures in files this PR touches beyond one French-copy case, which is fixed here. Full coverage is left to CI.Readiness (2026-11-13)
dev(873ec9b), inside the gate's window; no rebase for review.bun run typecheck,structure:check,skill:surface:check,privacy:scan, the layout and file-size guards and this PR's focused tests; after the deploy one real request each through Claude, GPT, Gemini, DeepSeek and Grok returned 200 and the error rate did not rise.maintainer-sponsoredlabel: the hygiene gate flagssrc/oauth/generic-account-failover.tsandsrc/server/management/oauth-account-routes.ts. Everything else is ready for review.Checklist
docs-site/.../guides/model-routing.md, "Watching routing live")/api/oauth/accountsgains a non-secret hashed label.)Review readiness checklist
This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:
Required local validation passed; commands, results, and any full-suite exception are documented.
I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).
I resolved all correct Codex and CodeRabbit findings.
My PR is ready for review.