From cb245d951f35a1a4e795314ed82ed2ba9f06c928 Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Fri, 16 Oct 2026 10:37:03 +0900 Subject: [PATCH 1/7] Add ocx usage compare for previous-window usage totals (carry #7211) Carried from #7211. Co-authored-by: Matt Van Horn --- .../src/content/docs/reference/cli/agents.md | 740 +------ scripts/test-layout/layout.json | 1912 +---------------- .../ocx/references/01_management_surface.md | 8 +- .../references/01_surface_observe-system.md | 29 +- skills/ocx/references/02_json_shapes.md | 7 + skills/ocx/references/03_recipes.md | 4 + src/cli/capabilities-base.ts | 2 +- src/cli/capabilities-observe-system.ts | 19 + src/cli/observe-stream.ts | 2 + src/cli/observe.ts | 306 +-- src/cli/registry.ts | 325 --- src/cli/usage-compare.ts | 279 +++ structure/cli-management.md | 19 +- structure/runtime.md | 2 +- tests/cli/cli-capabilities.test.ts | 2 +- ...cli-capability-operation-workflows.test.ts | 22 + tests/cli/cli-usage-compare.test.ts | 223 ++ tests/fixtures/test-layout-expected.json | 1 + 18 files changed, 600 insertions(+), 3302 deletions(-) create mode 100644 src/cli/usage-compare.ts create mode 100644 tests/cli/cli-usage-compare.test.ts diff --git a/docs-site/src/content/docs/reference/cli/agents.md b/docs-site/src/content/docs/reference/cli/agents.md index a5fdc6319f7..77a0c25ec3a 100644 --- a/docs-site/src/content/docs/reference/cli/agents.md +++ b/docs-site/src/content/docs/reference/cli/agents.md @@ -416,742 +416,4 @@ Inspect proxy requests, usage, storage, memory, and debug data. The direct alias | Alias | Equivalent resource | | --- | --- | | `ocx logs [filters] [--follow] [--json|--jsonl|--events]` | `ocx observe logs` | -| `ocx usage [--range ] [--since --until ] [--surface ] [--provider ] [--model ] [--api-key-id ] [--search ] [--top <1-1000>] [--json]` | `ocx observe usage` | -| `ocx storage [--json]` | `ocx observe storage` | -| `ocx memory [--json]` | `ocx observe memory` | - -```bash -ocx observe usage --range 30d --json -ocx usage --since 2026-09-01T09:00:00Z --until 2026-09-01T10:59:59.999Z --json -``` - -`--since` and `--until` must be supplied together. They accept integer epoch milliseconds or -full ISO datetimes with an explicit timezone, include both endpoints, and override `--range`. -Invalid or reversed bounds fail before the request. Human output prints the requested interval; -`--json` includes `customWindow`, `since`, and `until`. Existing surface/provider/model filters -still apply. These commands query the running proxy; they do not provide offline reports. - -`--range today` (alias `1d`) reports the current local day. `--provider` and -`--model` narrow the report to one upstream target — distinct from -`--surface`, which selects the calling client (Codex, Claude Code, Grok) -rather than the provider serving the request. - -The default view prints request, token and estimated-cost totals plus -per-provider and per-model breakdowns. Costs are API list-price equivalents, -not a billing receipt: subscription plans and provider credits are billed -separately, and requests with no matching price row are counted as -`unpriced`/`unmetered` rather than folded in as zero. - -```bash -ocx usage --range today --provider xai -``` - -When some usage records cannot be included, human output warns, including when there are zero readable rows. -Any displayed totals reflect readable records only. If a filter has no readable matches, the output shows -the warning and guidance instead of total lines; skipped records may contain matches. -`--json` preserves the response-level `usageIncomplete` diagnostic and reason. - -### Filter a bounded log snapshot - -```bash -ocx logs filter --surface claude --status errors --time-window 1h --scan-limit 2000 --limit 50 --json -``` - -`ocx observe logs filter` is the equivalent family form. This reads one recent -window, filters locally, then keeps the newest matches in their original order. -`--scan-limit` controls fetched rows (1–2000, default 2000); `--limit` controls -returned rows (1–2000, default 200). JSON reports -`{schemaVersion:1,logs,cursor,filters,window:{scanLimit,loaded,matched,returned,limit}}`. -Counts describe this observed window, not all history. JSONL emits rows only; -empty matches succeed. Cursor metadata is not a resumable search token. - -Selectors include `--surface all|codex|claude|grok`, `--status all|success|errors`, -`--time-window all|15m|1h|24h`, `--model`, `--provider`, `--conversation` -(alias `--conversationId`), `--intercepted-only`, `--min-tok-per-sec`, -`--max-tok-per-sec`, and `--protocol-mode all|native|translated|legacy-bridge|blocked|none`. -Model/provider equality is trimmed and case-insensitive, including -resolved/served models and attempts. Claude includes Desktop; Codex means absent -surface. Success is HTTP 200–299, errors 400–599. Time lower bounds are inclusive. -Speed uses observed value-kind tok/s, with inclusive minimum and exclusive -maximum; unavailable values fail active speed filters. Protocol none includes -absent or invalid traces. Conversation matching uses the same hash-aware IDs as -ordinary logs. Interception selects string-valued rewrite markers. - -Unknown/repeated/conflicting flags, invalid bounds, and follow/events fail before -discovery. Malformed, oversized or failed reads are nonzero, not empty results. -To reduce response size, reduce the scan limit; reducing output limit does not -change the fetch. For streaming use the separate follow forms below. - -### Search usage model rows - -```bash -ocx usage --range 7d --search 'model-a' --json -``` - -`--search` matches a trimmed case-insensitive substring in model, provider or -resolved model after reading the report. It sorts model rows by descending total -tokens with stable ties and keeps up to 100 by default. JSON adds -`modelView:{query,matchedModelCount,returnedModelCount,limit:100,truncated}`; -human output labels the view and shows its selected model rows. Report totals, -provider/day/account rows, exact filters and incomplete/window metadata remain -unchanged. No model match does not mean no report usage. - -An explicit blank query (`--search=`) selects the top-100 view; omitting search -preserves the existing output. Exact `--provider`/`--model` still scope the -underlying report. Search does not broaden selected-key or connected-client -self scope and is never sent as a new Hub API query parameter. - -`ocx usage --top 25` (also `ocx observe usage --top 25`) sets the human model table limit to an integer from 1 to 1000. The default is 10, or 100 with `--search`; the limit applies after search filtering. It changes local display only: report totals, provider/account rows and API parameters stay unchanged. With `--json`, a valid `--top` is ignored; JSON retains its existing full report or 100-row search view. Invalid limits return exit 2 before fetching. - -### Saved companion usage totals - -```bash -ocx companion show --json -ocx companion usage --json -``` - -The second command reads saved companion settings, then today and 30d usage -sequentially on the same management runtime. It applies the saved `models` and -`hiddenProviders` preferences and preserves unknown/unmeasured costs and tokens. -Null model selection means all; an empty selection means none. It does not -change settings, operate native windows or relay through a connected client. - -JSON returns `schemaVersion:1`, `filters`, `settingsUpdatedAt`, -`settingsCorrupt`, `settingsFallback`, `ranges` and `partial`. Each range has -`status:"available"` with filtered `data`, or `status:"unavailable"`. -An unavailable range sets partial and exit 1 while retaining the other range. -Available incomplete data retains its own metadata; it is not measured zero. -Valid server defaults retain a null settings timestamp and set fallback; -corrupt-file defaults additionally set corrupt and warn in human output. -Malformed settings stop before usage reads. These reads are not an atomic -snapshot. Each GET has a 10-second fetch/body deadline after discovery and a -32 MiB response cap; this is not a whole-command deadline. Signals exit 130/143 -without late results. - -### Follow request windows or injection sequences - -```bash -ocx logs --help -ocx logs --limit 200 --json -ocx logs --follow --events --limit 200 -``` - -`--events` requires follow and implies JSONL; redundant `--jsonl` is accepted. -`--json` remains one-shot and conflicts with follow/events. Each events-v1 line -is `{schemaVersion:1,type:"snapshot"|"append",rows,cursor,limit}`. Replace the -consumer window on snapshot, append/trim on append, preserving order and repeated -IDs. Initial empty and reset/removal snapshots are emitted; stable empty polls -remain silent. Legacy arrays are snapshots with cursor null, not invented cursors. -These are observed windows, not a lossless replay of traffic missed between polls -or after ring eviction. - -`ocx logs --follow --jsonl --limit 200` retains row-shaped output. It re-emits changed -occurrences, including same-ID status/token amendments and repeated IDs. Do not -collapse everything by request ID. This legacy output cannot encode removals, -resets or exact window order; choose events when those distinctions matter. -Log follow limit is 1–2000, default 200. - -```bash -ocx observe injection --limit 500 --json -ocx observe injection --follow --jsonl --limit 500 -``` - -Injection emits ordered `{seq,at,line}` rows, where `at` is epoch milliseconds; -internal `after` advances with seq. Follow limit is 1–2000, default 500. JSON is -one-shot and JSONL requires follow. Observation does not enable capture. Empty -polls do not identify disabled capture or prove absence of gaps. Detectable runtime -drift stops; undetectable restart/latest-N gaps cannot be excluded without an API -epoch/gap marker. - -Both follow loops use serial one-second waits, 10-second fetch/body deadlines and -32 MiB response limits. Malformed/oversized/transport errors stop with stderr and -exit 1, without automatic retry/reconnect. Reduce limit for oversized windows. -SIGINT/Ctrl-C exits 130, SIGTERM 143, with no later polls/output. Inspect exit state -and retained rows instead of treating cancellation as complete history. - -### Companion timeline and key-scoped usage - -```bash -ocx companion timeline --help -ocx companion timeline --hours 24 --bucket-minutes 60 --metric total --aggregation sum --grouping model --model example/model-a --hide-provider excluded-provider --json -``` - -Replace fictional IDs with the selected filters. Repeat `--model` for individual -provider/model IDs (nested slashes allowed; not CSV); repeat `--hide-provider` to -exclude providers. Positive `--provider` is unsupported. Hours are 6/24/72/168, -bucket minutes 1–1440 with at most 2000 buckets, metric total/input/output/cached, -aggregation sum/average/max, grouping model/modelAccount. The API limits filter -inputs to 100 items. This reads usage without changing companion settings. - -Check `appliedFilters.models/hiddenProviders`. Timeline bounds are epoch seconds, -with exclusive end, unlike ordinary usage's millisecond custom window. The end must -match the request-time bucket, or its immediate successor if the request crosses -a bucket boundary; an older aligned window is refused. Empty -series retains bucket/filter metadata. `missingMeasurements` and `truncated` must -remain visible: zero-filled points do not prove complete zero usage. - -On a non-client management host: - -```bash -ocx access key list --json -ocx usage --api-key-id key-example --range 7d --json -``` - -Use a non-secret actual key ID. The CLI requires exact response acknowledgment in -`filter.apiKeyId`; ignored filters fail rather than showing unscoped totals. -An unknown acknowledged ID can return `matched:false` and empty traffic, not 404. -Keep incomplete/custom-window facts. Connected clients reject `--api-key-id` -before enrolled-key access or transport; omit it for existing self-only Hub usage -or perform the selected-key view on the Hub. No data key grants management authority. - -### `ocx debug ` - -Read or change runtime debug overrides through the running proxy's management API. - -```bash -ocx debug provider on|off|status|reset -ocx debug provider logs [-f|--follow] -ocx debug usage on|off|status|reset -ocx debug usage logs [-f|--follow] -``` - -With no scope, `ocx debug` prints usage and, when the proxy is stopped, the next-start environment -defaults. Provider debug defaults from `OCX_DEBUG=1` (legacy `OCX_DEBUG_FRAMES=1` also works); usage -debug defaults from `OPENCODEX_USAGE_DEBUG=1`. - -## API access - -### `ocx access ...` - -Inspect admission keys, external endpoints and models with the access family. -`ocx api-key` aliases the access-key family. Creation and rotation-start return a -one-time plaintext credential in text and JSON output. Agents must leave those -steps to a human-operated terminal outside the agent session; request only -confirmation and non-secret key/rotation IDs, never the credential. - -```bash -ocx access key list --json -``` - -After the human configures and verifies the replacement, committing its rotation -or removing the old key requires separate explicit revocation authority. Safe -non-secret follow-ups are `ocx access key rotate commit --json` -and `ocx access key rotate abort --json`, with authority for -the chosen action. Re-list afterward. Missing pending state alone does not prove -commit: expiry or abort can also clear it. Do not route around consent by issuing -the secret-returning management request directly. - -### Rename one key without changing its access policy - -```bash -ocx access key rename key-example 'Research client' --json -ocx access key list --json -``` - -Use an actual unique ID or unambiguous name. Rename sends only `{id,name}` and -preserves provider/model scopes; it does not rotate/delete a key. The response -contains id/name/createdAt and optional allowedProviders/allowedModels, never -plaintext or a prefix. List remains masked. Names are control-free, trimmed, -nonempty and at most 64 JavaScript string units. The read/rename sequence is not -CAS; inspect the masked roster after an unknown outcome before retrying. The -root `api-key rename` alias uses the same command. - -### Explicit-key model and audio checks - -Discover the installed syntax without contacting upstream: - -```bash -ocx access test --help -ocx access audio transcribe --help -ocx access audio live-check --help -``` - -Model requests, audio uploads and live-session checks require explicit operator -authorization for that particular upstream operation and possible quota/cost. -The operator supplies the selected key from an approved private stdin source in -a human-operated terminal outside the agent session. Agents must not capture it -or ask for it in chat. Never put it in argv/environment. These are the ocx side -of that private pipe, not direct interactive key prompts or an agent-run batch: - -```bash -ocx access test example/model --protocol responses --api-key-stdin --json -ocx access audio transcribe sample.wav --model gpt-4o-mini-transcribe --api-key-stdin --json -ocx access audio live-check --model gpt-live-1-codex --api-key-stdin --json -``` - -Choose only the authorized task and real model/file. TTY input is refused. Input -is bounded to 4096 bytes/30 seconds, valid UTF-8 printable ASCII, without outer -whitespace, controls or extra lines; one final LF/CRLF is allowed. This deliberately -covers currently issued keys, not every Unicode value the server configuration -might accept. Exact supplied-key occurrences in permitted text become `[redacted]`; -arbitrary encodings are not guaranteed detected. No encoded key carrier is printed. - -Targets are the checked local serving origin or existing normalized enrolled Hub -origin, with identity checked around asynchronous work. There is no custom-origin, -admin or enrolled-key fallback, redirect following, credential cache or automatic -retry. The operator reports only the non-secret result to the agent. - -#### Model control and response limits - -Protocols are chat (default), responses or messages. Selected-key mode first -sends one credentialless malformed-JSON control to that endpoint. Only the native -key-required 401 advances to one fixed 16-token model request using the supplied -key. The control has a 5-second/4096-byte response budget; the request has a -60-second/2 MiB response budget including body reads. Authless/unrecognized -controls stop before inference. Local logging/admission bookkeeping may still occur. - -JSON is `{schemaVersion:1,control:{outcome,status?},request:{outcome,status?},response?}`. -Safe response contains protocol, ordered text, complete/limited completion and -optional measured token counts. A usable length-limited reply is `limited`; -refusal/content-filter/tool-only or malformed responses are unsupported, even -with HTTP 2xx. Error metadata, IDs, tools and reasoning are not printed. -Operational failure retains one versioned report plus fixed stderr/exit 1; -invalid grammar/key input exits 2 without a fabricated report. - -Success says only: “Credentialless request was refused; the model request using -the supplied key succeeded.” Listener/policy changes between calls remain possible; -this does not certify key scope, atomic admission or billing identity. Without -`--api-key-stdin`, legacy test JSON remains its original payload and says nothing -about a newly selected key. - -#### Transcription and live readiness - -Transcription requires a nonempty regular file of at most 25,000,000 bytes with a -30-second local read limit, and a multipart body capped at 32 MiB. Models are -gpt-4o-transcribe, gpt-4o-mini-transcribe or whisper-1, subject to target support. -Upload/response share 130 seconds; response is capped at 2 MiB. Success returns -only `{text}`, including empty text, with exact-key redaction. Failure leaves -stdout empty and prints fixed stderr/nonzero; no JSON error envelope or raw body. - -Audio uses explicit-key admission without the model control. Live-check sends -fixed session.update and session.close only. Readiness requires session.started -or session.updated with nonblank native session ID within 15 seconds; socket-open -or session.created alone is insufficient. After readiness it waits at most 2 -seconds for normal code-1000 closure. Each UTF-8 frame is capped at 64 KiB, aggregate -2 MiB; there is no retained frame history. - -Live JSON is `{schemaVersion:1,ready,close:"confirmed"|"unverified",check:"session-readiness",event?}`. -Operational failure preserves that observation without raw frames. Partial readiness -with unverified close exits 1; a later normal close cannot erase an earlier error. -Signals exit 130/143. This checks readiness/closure only, not microphone, upload, -tool execution, full voice roundtrip or server lease release. Opening the upstream -session is not guaranteed free. No reconnect or retry is automatic. - -### `ocx api ...` - -Inspect and set how requests travel between the client APIs and provider wires. See -[Protocol paths](/guides/protocol-paths/) for the vocabulary. - -| Command | Route | Changes state | -| --- | --- | --- | -| `ocx api protocols [--provider ] [--json]` | `GET /api/protocols` | No | -| `ocx api explain --model --inbound [--feature ]... [--json]` | `POST /api/protocols/plan` | No | -| `ocx api policy [--json]` | `GET /api/protocols` | No | -| `ocx api policy [--messages ] [--unrepresentable ] [--rollout =]... [--json]` | `PATCH /api/protocols/settings` | Yes | - -- `protocols` prints the contract version, whether each client API is served and why, the - unrepresentable policy, every rollout switch, and the policy revision. `--provider` adds the - upstream wire that provider receives, who decided it, and the models on another wire. -- `explain` previews the path a model would take from one client API. `--feature` is repeatable - and accepts a comma-separated list; `ocx api protocols --json` lists the known feature keys. The - preview is computed from configuration: nothing is sent upstream, no combo rotation advances, and - the input is not logged. -- `policy` without a setting flag only reads. With one it sends a single change to the running - proxy, which validates it, saves the configuration, and answers with the new policy. - `--messages off` also turns the Claude integration off, as the dashboard toggle does. Switch - names and combinations are validated by the proxy; for example - `--rollout managedMessagesNativeOAuth=on` is refused unless `managedMessagesNative` is - already on or turned on in the same command. - -```bash -ocx api explain --model combo/main --inbound chat --feature request.seed,request.tools -ocx api policy --rollout shadowPlan=on -``` - -Usage errors exit 2 before any request is sent. `--json` prints the management API body as is. - -## Client integrations - -### Basic integration commands - -| Command | Action | -| --- | --- | -| `ocx integration client status [--client ] [--profile ] [--json]` | Read all managed file integrations, one client, or Aside profiles. `show` and `list` alias `status`. | -| `ocx integration client history [--client ] [--profile ] [--json]` | Read rollback operations and snapshot availability. `journal` aliases `history`. | -| `ocx integration client enable --client [--profile ] [--overwrite-conflict] [--json]` | Apply the managed file integration. Overwriting a conflicting block requires the explicit flag. | -| `ocx integration client disable --client [--profile ] [--json]` | Remove the selected managed integration through its runtime owner. | -| `ocx integration client restore --op [--client aside --profile ] [--confirm-drift] [--json]` | Restore a recorded operation; replacing later edits requires explicit drift confirmation. | -| `ocx integration native [list] [--json]` | Read native integration state. | -| `ocx integration native [--json]` | Write the selected native client's configuration through its runtime owner. | - -These commands require a running proxy. `--profile` selects a nonnegative Aside account ID and -requires `--client aside`; omitted profiles select the aggregate for reads and all profiles for -unbound enable/disable. Native toggles change client configuration; Cursor has separate read-only -inspection commands below. For preview and bound-write options, continue with the recipes below. - -### Preview and recover managed file integrations - -```bash -ocx integration client preview --client hermes --operation apply --json -ocx integration client restore --op op-example --preview --json -``` - -`op-example` is fictional; use an ID from history. Preview operations are apply, -overwrite and disable; restore uses `--preview` on its existing command. Review -structural changes and `canApply`/`willChange`; valid refusal/no-op exits 0 without -applying. Enable/disable/restore accept optional `--plan-fingerprint` for an -explicit bound commit. Direct legacy writes remain available. Aside preview or -bound writes require `--client aside --profile N`. Drift confirmation and overwrite -are never automatic; stale binding exits 5 with empty stdout and a re-preview -instruction on stderr. Follow the [complete preview/commit and drift recipes](/guides/integrations/#preview-and-bind-a-terminal-write). - -Droid apply/overwrite supports repeated `--reasoning-default MODEL=EFFORT` for -full map replacement, or exclusive `--clear-reasoning-defaults` for `{}`. Omission -preserves the map. Repeat the exact map in preview and commit; see -[Droid defaults](/guides/integrations/#factory-droid). - -History removal is irreversible and requires an exact opId plus `--yes`: -`ocx integration client history remove --op op-example --yes --json` addresses the -global journal. Only `--client aside` and optional `--profile N` provide narrower -delete scopes. The newest row is protected. `snapshotRemoved:false` exits 1 after -retirement with cleanup incomplete; do not retry deletion or claim rollback. - -`ocx integration client sync --client aside --json` refreshes eligible profiles -through the attested owner, with no profile selector or local fallback. Empty -`results` is successful observation of no eligible profiles; a failed row makes -the aggregate nonzero while preserving other successes. Read status and recovery -facts before retrying; [Aside controls](/guides/integrations/#aside-profile-controls) -explain profile intent versus file state. - -### Inspect Cursor without installing it - -```bash -ocx integration native cursor status --json -ocx integration native cursor local-installer --json -``` - -Status can gather model inventory; installer lookup may fetch a public manifest. -They do not download/install or toggle Cursor. Status distinguishes credential -from placeholder gateway mode; the placeholder is not an access credential. -Installer `{available:false,url:null,version:null,reason:null}` is valid, including -when Private Inference is already installed. A valid unavailable read exits 0. - -### `ocx integration ...` - -Manage supported Claude and Grok integrations. The direct command families below expose their -client-specific controls. - -### `ocx claude [claude args...]` - -Ensure the proxy is running, then launch Claude Code with `ANTHROPIC_BASE_URL`, -`ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1`, and model slots from -`config.claudeCode`. Routed models appear in the native `/model` picker through stable slot aliases -with Claude Code 2.1.129 or newer. On older versions, select with `ANTHROPIC_MODEL` or `/model `. -User-exported `ANTHROPIC_*` variables always take precedence. - -Claude Desktop profile commands are: - -```text -ocx claude desktop [apply] Save and apply the four-family profile -ocx claude desktop show [--json] Show routes, families, and defaults -ocx claude desktop status [--json] Show applied state, drift, and health -ocx claude desktop move [--default] -ocx claude desktop default -ocx claude desktop export Export versioned JSON (`-` = stdout) -ocx claude desktop import [--apply] Validate and import JSON -``` - -The families are `opus`, `fable`, `sonnet`, and `haiku`; new routes start in `opus`. `none` is valid -only when that family is empty. Legacy apply flags `--static`, `--hybrid`, and `--discovery-only` -remain supported. Use `ocx claude config ...` for Claude Code settings. - -#### Read or save the selected runtime's Desktop profile - -The existing show/import commands above are local. The `profile` family targets -the running management runtime and can gather model inventory: - -```bash -ocx claude desktop profile show --json > desktop-observed.json -jq '.profile' desktop-observed.json > desktop-profile.json -``` - -Edit/review the versioned profile, preserving server-owned applied markers. For -an authorized save, then read-back: - -```bash -ocx claude desktop profile import desktop-profile.json --json -ocx claude desktop profile show --json -``` - -Import accepts the profile itself, not the outer `{profile,models,rendered,port}` -response, using bounded regular JSON files or explicit stdin `-` (4 MiB/30 seconds). -It returns those observed fields plus `ok:true`, meaning saved only. `--apply` and -native-mode flags are rejected; failed runtime save has no local fallback. Apply -is a separate existing Desktop action on its machine, so verify host/context -before choosing it. Rendered models are not proof of native application. - -### `ocx opencode [opencode args...]` - -Ensure the proxy is running, then launch opencode with the generated `provider.opencodex` and -`providers.opencodex` blocks in OpenCode's inline runtime layer (`OPENCODE_CONFIG_CONTENT`). The -legacy block keeps V1 clients working with variant maps; the V2 block carries native arrays -for the same reasoning-effort choices and defaults. Existing inline config is preserved and only those two keys are replaced -for this launch. Global or project `opencode.json` files may be read to warn about an existing -override, but on-disk files are never modified. Routed models appear as -`opencodex//`. Launching plain `opencode` later behaves exactly as before. - -### `ocx grok ...` - -Manage and apply the Grok Build model fence. - -## Client config export - -### `ocx export --client ` - -Print a client config wired to the running proxy. The command serializes the -`opencodex` provider block — base URL, model list, and the client's credential -reference or loopback placeholder — in the selected client's native format. - -The proxy must be running; the command resolves its live port, reads `/api/models`, and emits only -models Codex can currently see. - -OpenCode and Kilo exports preserve effective model limits, known capabilities, declared reasoning -choices and defaults, including metadata inherited by custom rows. Explicit overrides still win; -unknown capabilities and defaults are not invented. The OpenCode launcher uses the same metadata. -See [client integrations](/guides/integrations/) for managed refresh and upgrade behavior. - -| Flag | Action | -| --- | --- | -| `--client ` | Required. Selects the client config dialect. | -| `--json` | Print the generated document as JSON on stdout for scripts. This is JSON even when the selected client's native format is YAML, TOML, or JSON5. | -| `--out ` | Write the client's native config format to ``. Refuses to replace an existing file. | -| `--force` | Allow `--out` to replace an existing file. | - -```bash -ocx export --client opencode # config plus destination, merge warning, and counts -ocx export --client pi --json > pi-models.json # JSON document for a pipe or a diff -ocx export --client omp --out ./omp-models.yml # native OMP YAML -ocx export --client opencode --out ~/opencodex-opencode.json -``` - -Without `--json` the generated config leads, then the canonical destination path, the merge warning, the env -export line where the client has one, and a model count with how many rows omit context limits (the -client applies its own defaults for those). - -| Client | Canonical destination | Download filename | Env var | -| --- | --- | --- | --- | -| `opencode` | `~/.config/opencode/opencode.json` (`XDG_CONFIG_HOME` wins when set) | `opencode.json` | `OPENCODEX_OPENCODE_API_KEY` | -| `pi` | `~/.pi/agent/models.json` (`PI_CODING_AGENT_DIR` wins when set; a relative value is refused) | `pi-models.json` | none — the block carries the literal `opencodex-loopback` | -| `omp` | `~/.omp/agent/models.yml` (`OMP_PROFILE` wins over `PI_PROFILE`, even when empty; named profiles use the home-relative `PI_CONFIG_DIR` directory name and ignore `PI_CODING_AGENT_DIR`, while the default profile lets `PI_CODING_AGENT_DIR` win) | `omp-models.yaml` | none — loopback placeholder | -| `hermes` | `~/.hermes/config.yaml` | `hermes-config.yaml` | `OPENCODEX_HERMES_API_KEY` | -| `openclaw` | `~/.openclaw/openclaw.json` | `openclaw.json5` | `OPENCODEX_OPENCLAW_API_KEY` | -| `kimi` | `~/.kimi-code/config.toml` | `kimi-config.toml` | none — loopback placeholder | -| `gajae` | `~/.gjc/agent/models.yml` | `gajae-models.yaml` | non-secret loopback placeholder | -| `dsh` | `$DSH_HOME/settings.yaml` (default `~/.dsh/settings.yaml`) | `settings.yaml` | none — non-secret loopback bearer placeholder | -| `mcode` | `~/.minimax/config.yaml` (`MINIMAX_DATA_DIR`, then the legacy `MAVIS_DATA_DIR`, win when set; a relative value is refused) | `mcode-config.yaml` | none — loopback placeholder | -| `zcode` | `~/.zcode/v2/config.json` (`dataBaseDir` in the default-home `setting.json` relocates the root; `ZCODE_DATA_DIR` wins when set; relative values are refused) | `config.json` | none — loopback placeholder | -| `prime` | `~/.prime/agent/models.json` (`PRIME_AGENT_CODING_AGENT_DIR` wins when set; a relative value is refused) | `prime-models.json` | none — loopback placeholder | -| `aside` | `~/.aside/u//models.json` for the account Aside's own `accounts.json` names as current; an unreadable manifest is refused rather than defaulting to an account | `aside-models.json` | none — loopback placeholder | -| `raycast` | `~/.config/raycast/ai/providers.yaml` on macOS and Windows alike (Raycast does not honor `XDG_CONFIG_HOME`) | `raycast-providers.yaml` | none — loopback only, no `api_keys` entry is written | -| `omo` | `~/.omo/agent/models.json` (`OMO_CODING_AGENT_DIR`, then `SENPI_CODING_AGENT_DIR`, then `PI_CODING_AGENT_DIR` win in that order when set; a relative value is refused) | `omo-models.json` | none — loopback placeholder | -| `kilo` | first existing `kilo.jsonc`, `kilo.json`, `opencode.jsonc`, `opencode.json`, or `config.json` under `~/.config/kilo` (`XDG_CONFIG_HOME` relocates that directory); uses `kilo.jsonc` when none exists | `kilo.jsonc` | `OPENCODEX_KILO_API_KEY` | -| `commandcode` | `~/.commandcode/providers.json` (on Windows with the default home: use `HOME ?? USERPROFILE` only if nonblank and Windows-absolute, otherwise `homedir()`; a separately supplied home is preserved; append `.commandcode\providers.json`) | `providers.json` | loopback only; `apiKey: false`; no environment variable | -| `droid` | `~/.factory/settings.json` (`%USERPROFILE%\.factory\settings.json` on Windows) | `factory-settings.json` | loopback only; no environment variable | - -The managed DSH export requires DSH 0.1.0-rc.6 or newer and owns only -`llm-pi-ai.providers.opencodex`. DSH hot reloads that provider; the user's default model and -`deepseek-official` remain untouched. This export is loopback-only and carries no real credential. -DSH 0.1.7 and newer import `settings.yaml` once into the first profile that boots and then rename -it, so the dashboard integration writes the same provider into the `llm-pi-ai` row of the Desktop -profile's `$DSH_HOME/profiles/desktop/cordis.patch.yml` once that profile exists. - -opencode interpolates `{env:OPENCODEX_OPENCODE_API_KEY}`. The generated Pi and OMP exports do -not require an environment variable: each carries the literal `opencodex-loopback` placeholder. -This is load-bearing because both clients resolve `apiKey` while building their model lists and -hide the whole provider when an existing config contains an unset env reference. The proxy never -checks the generated placeholder on loopback. OMP supports provider-level headers, but this initial -integration deliberately remains loopback-only; remote `x-opencodex-api-key` wiring is deferred. - -The Raycast export is a standalone `providers.yaml` document with one `id: opencodex` element -in the `providers` sequence: `name: OpenCodex`, the proxy's `/v1` base URL, and every routed model -with its `abilities` (`tools` and `system_message` always supported, `vision` from the catalog's -input modalities, `reasoning_effort` when the model has an effort ladder, `temperature` off for -reasoning models). Custom Providers is a Raycast Pro feature, and Raycast watches the file, so a -saved change takes effect without a restart. The format is documented at -[manual.raycast.com/ai/custom-providers](https://manual.raycast.com/ai/custom-providers). No -`api_keys` entry is written, so this export is loopback-only and a non-loopback bind is refused. - -The MCode, ZCode and Prime exports are loopback-only for the same reason and likewise carry the -`opencodex-loopback` placeholder rather than a real credential. Prime Agent reads the same -`models.json` contract Pi does, so the two exports produce the same document; only the destination -differs. A relative path in any of those three environment overrides is refused, because the proxy -and the client can have different working directories and would otherwise disagree about which -file is meant. - -ZCode 3.8.1 may save runtime-derived `reasoning`, `limit.output`, and default context metadata back -into the generated `provider.opencodex.models` entries. Managed integration status treats only -those documented additions as refreshable drift. Provider identity and connection settings, -including `options.baseURL`, model membership, names, modalities, and any context limit OpenCodex -emitted authoritatively remain protected; editing them reports `conflict / foreign-edit` instead of -overwriting the file. An ownership record created by an older OpenCodex version can recover -automatically when the generated catalog is otherwise unchanged. If both the catalog and the block -changed, re-apply only after reviewing the file because the older record cannot prove which change -was ZCode-derived. - -:::caution[Merge, never replace] -`ocx export` never writes your real client config. The destination is printed for you to merge by -hand, and `--out` refuses to overwrite an existing file without `--force`, because replacing a -config destroys the other providers, agents, and MCP entries already in it. -::: - -No key is ever serialized. Configs carry either a documented environment reference or a -non-secret loopback placeholder. A loopback address (`127.0.0.1`) alone does not establish keyless -admission: check the target policy and endpoint. Selected-key model/audio commands -still require explicit key input on loopback. Set a referenced variable only when the client schema supports it and -the proxy binds beyond loopback; see -[Remote access](/reference/configuration/server/#remote-access) for how admission keys are issued. Keys for -the upstream providers themselves are a separate thing entirely, configured per -[Providers](/guides/providers/). -The generated gjc integration uses a non-secret loopback placeholder and needs no environment variable. It remains loopback-only; it does not configure remote admission credentials. - -The same payload is served by `GET /api/client-config` and rendered on the dashboard's API tab, so -the CLI, the API, and the GUI use the same bytes. - -## Runtime and configuration - -### `ocx system ...` - -Manage headless runtime settings, startup, sync, diagnostics, and updates. - -`ocx system codex-restart --yes` restarts Codex app-servers through the same module as -`ocx sync --restart-codex`. It quits and relaunches the Codex desktop app when the app launched before the current model catalog was written or this request changed -its `model_catalog_json` binding, because the model picker is built at -launch. Otherwise the app stays open, respawns its own app-server, and keeps unsaved drafts and -pending approvals. If the app or catalog state cannot be read, it takes the full restart. When -the proxy itself is running inside the Codex app, the desktop restart refuses with an actionable -message instead of promising a handoff it cannot complete. - -A `model_catalog_json` binding changed by this request also forces the desktop restart, even when the shell started after the catalog file was written. - -```bash -ocx system settings --stream-mode eager-relay -``` - -Additional system booleans take on/off: `--show-codex-credits`, `--account-picker`, -`--main-account-hard-lock`, `--ultra-fast-tier`, and `--fast-rows`. They write only -explicit fields and may combine with existing system options. Showing credits is -a display preference, not paid-credit opt-in; system Ultra Fast is separate from -provider Fast. - -Ultra Fast is an opt-in setting, default off. With `--ultra-fast-tier on`, the -generated catalog adds the Ultrafast speed choice to native `gpt-6-astra` and -`gpt-6.1-sol` (including account-bound rows), so the Codex picker offers it next to -Fast. Ultrafast requires an eligible ChatGPT plan; the catalog cannot check that, -so turn the setting on only if your plan includes it. Other models and the default -speed are unchanged. - -For routed models, sync and catalog convergence retain an existing routed -row's operator-supplied `ultrafast` entries in `service_tiers` and -`additional_speed_tiers` alongside its current Fast capability. Declarations belong -to the exact provider/model slug; they are not copied to other models. The setting -does not create missing declarations or restore removed models. Turning it off -removes Ultra Fast from ordinary routed rows and the generated native choice on the -next catalog regeneration. - -The proxy's Fast mode decides what reaches the backend: when it is unset, a selected -Ultrafast request is forwarded as `service_tier: "ultrafast"`; `fastMode: true` -replaces any tier with Fast (`priority`), and `fastMode: false` removes the tier. -Leave Fast mode unset to use Ultrafast. - -```bash -ocx system settings --json -ocx system settings --show-codex-credits on --json -ocx system settings --json -``` - -New-option writes report `{ok:true, settings: observedFields, catalogRefreshPending}`. -Ultra Fast performs same-target GET read-back because PUT omits that value. A -missing/mismatched/read-failed observation stays `verification:"unverified"` with -`unverifiedFields` and a nonzero exit after acceptance; requested values are never -substituted for observations. Combined desktop switches retain stored/effective -and apply facts. Pending catalog or deferred/refused native apply is distinct from -a saved setting. False pending is not proof that every client has reloaded. - -`ocx system update` updates OpenCodex itself. The separate Codex CLI inspection surface is: - -```bash -ocx system codex-cli-update check --json -``` - -`check` makes no package-registry request and inspects bounded configured-candidate provenance evidence, -including a redacted executable location and ownership evidence. Trusted published-launcher context authenticates -the candidate snapshot, not successful Codex execution. Because this one-shot command never executes Codex, -environment and persisted candidates remain report-only (`managed: false`, normally `selection_unattested`); -`selectionAttested` remains `false`. The JSON report exposes `candidateAvailable`, `candidateVersion`, `candidateSource`, -and `selectionAttested`. Inspecting the configured candidate requires a trusted published-launcher context; -a direct Bun/source launch has no such proof, ignores ambient and persisted candidate state, and may report -`candidate_unavailable` on POSIX. On Windows this first slice performs no candidate or configuration filesystem I/O: -only a proof-captured absolute environment candidate can receive lexical app-bundle or version-manager labels; -every other Windows candidate fails closed. Because that slice never consults persisted state, a Windows run -with no captured environment candidate reports `windows_inspection_deferred` rather than `candidate_unavailable`: -the command cannot observe whether a Codex CLI is installed, so it reports the deferral instead of asserting -that no candidate exists. The command does not execute Codex or a package manager, repair a shim, -write configuration or cache state, stop a process, or install anything. App-bundled, recognized -version-manager, unverified standalone, and ambiguous shim states are reported as unmanaged or unknown -and are never classified as managed. - -On Windows, a captured bare command such as `CODEX_CLI_PATH=codex`, a remote path, or a device path reports `candidate_path_unavailable` instead. Those cases have a captured candidate; its path is not eligible for this inspection. - -#### Explicit installation observation on Windows x64 - -```text -ocx system codex-cli-update attest [--json] -ocx system codex-cli-update attest --candidate --npm-prefix --npm-cli --node [--json] -``` - -`attest` is an opt-in, read-only observation of a Windows x64 npm installation. With no options it identifies the selected candidate from the proof-bound launcher snapshot — the configured `CODEX_CLI_PATH` or the first `codex` on the captured PATH, with an OpenCodex wrapper resolving to its renamed `codex.opencodex-real.cmd` npm backing. Supplying all four absolute paths overrides discovery; discovery only proposes paths and the held-handle observation remains the authority. `--candidate` must name the standard npm `/codex.cmd` or `/node_modules/@openai/codex/bin/codex.js`. `--npm-cli` must end in `node_modules/npm/bin/npm-cli.js`; `--node` names an explicit `node.exe`. App bundles, recognized version-manager layouts, opencodex-owned shims without their npm backing, and custom wrappers are refused. - -Native handles hold the ancestor directories and files during bounded reads. Unsupported platforms, reparse points/junctions, conflicting writers, unsafe paths, and oversized files are refused. The fixed report contains no paths: `status` is `observed` or `refused`, with `installationIdentityObserved`; `selectionAttested`, `managed`, and `applyAllowed` remain `false`. Check `status`, not just the process exit code: a reported refusal can exit 0. - -An observed identity or digest describes those files during this observation. It is not a durable update permit and does not prove the selected runtime, the past installer, effective npm configuration, or tool authenticity. The supplied Node is observed only, not proven to be the Node a launcher would select. No target is executed; no registry request, installation, configuration write, or process control occurs. The existing Windows `check` command still performs no candidate/configuration filesystem I/O. - -### `ocx config [show|get|set|unset|validate|export|import] ...` - -`ocx config [show] [--json] [--source]` displays the local configuration without a running proxy. Omitting `show` also works with either flag or both, in either order. `--source` includes diagnostic source, error, and warning fields and is only accepted for display. `--json` may precede an explicit action; it does not change which action runs. Repeated `--json` or `--source` flags and unknown arguments are rejected. - -Inspect and safely modify validated OpenCodex configuration. `show` and `get` mask secrets. Import -validates before writing and requires `--yes`. - -Display and mutation output strip credentials from proxy URLs while retaining the host and port. -`direct` and credential-free proxy values stay readable. `export` preserves credentials so the -backup can restore the configuration; store exported files as secrets. - -### Usage from a connected client - -`ocx usage` reads the connected hub with this client's enrolled data key. Human output identifies the hub source and client-key scope; `--json` returns the same scoped data. Range, surface, provider/model filters and custom `--since`/`--until` bounds remain available. Account breakdowns and other clients' records are not shared. An old or unavailable hub produces an explicit error instead of substituting local usage; upgrade the hub if it does not support this read. - -The read-only data-plane endpoint is `GET /v1/usage`, using `x-opencodex-api-key` with a configured client key. Environment-wide and admin keys are refused. It accepts `range`, `surface`, `provider`, `model`, `since`, and `until`; unknown/repeated options and caller-selected key IDs are rejected. Oversized skipped rows retain the explicit incomplete-history warning. - -## Explain a listed request - -Human `ocx logs` output includes `id=`. Pass that value to `ocx logs explain ` to inspect routing decisions. Rows without an ID or with control characters in their ID omit the field instead of displaying a different lookup key. JSON and JSONL output retain their existing schema. - -## Routing profile lookup status - -`ocx route policy show ` exits 4 when the profile does not exist. Missing or invalid command arguments exit 2. Scripts can distinguish a missing profile from incorrect usage. - -## Upstream error details - -When an upstream error envelope contains several message fields, OpenCodex uses the first nonblank string in its established priority order. Empty or malformed fields no longer hide a valid fallback diagnostic. - -### Forced Claude Code subagent model - -The Subagents page offers **Force all subagents onto one model**, off by default. Select an exposed roster-style id, such as `combo/tev-auto`, then enable the switch. The roster is offered first; unavailable saved roster entries cannot be force targets. - -`ocx agent subagents force combo/tev-auto` sets `claudeCode.subagentModelForce`; `ocx agent subagents force -` clears it. `ocx agent status` reports the setting. `GET /api/subagent-models` returns `force`, `forceAvailable`, and `forceStatus`; `PUT` accepts `{ "force": "combo/tev-auto" }` or `{ "force": null }` without changing the roster. Omitting `force` leaves it unchanged. Invalid or unexposed targets are rejected on write; stale targets are reported and skipped at launch. - -This takes effect on the **next routed `ocx claude` launch**, injecting `CLAUDE_CODE_SUBAGENT_MODEL` as an explicit proxy alias (with `[1m]` only for an authoritative million-token window; native Claude targets use a reversible native alias) and `CLAUDE_CODE_SUBAGENT_MODEL_FORCE=1`. Each nonempty shell-exported variable independently wins. Native launches inject neither variable; plain `claude` is not affected. No plugin files or `settings.json` are modified by this setting. - -Claude Code **2.1.257 or newer** is required for FORCE. Plugin and built-in agents (including Explore/Plan) and per-call model arguments are overridden. Forks and subagent skills with `model: inherit` keep the main conversation model. The main loop and Haiku/small-fast sidecars are unaffected. Existing roster files remain available. - -The dashboard warns about old or unknown CLI versions, unavailable targets, and either variable already present in `settings.json` → `env` (which overrides launch env). Detection is read-only and server-local: it cannot inspect another launch shell, another machine, or project-local settings. An unknown result is not proof of force support. +| `ocx usage compare [--range ] [--json]` | `ocx observe usage compare` | diff --git a/scripts/test-layout/layout.json b/scripts/test-layout/layout.json index 9925e111815..e93ae61b72a 100644 --- a/scripts/test-layout/layout.json +++ b/scripts/test-layout/layout.json @@ -24,1914 +24,4 @@ "provider-anthropic-instance.test.ts": "providers", "config-anthropic-instance-pool.test.ts": "config", "oauth-anthropic-instance-registration.test.ts": "oauth", "oauth-anthropic-instance-refresh.test.ts": "oauth", "model-costs-pricing-cache.test.ts": "server", "model-costs-prompt-length-pricing.test.ts": "server", "cli-models-prompt-length-pricing.test.ts": "cli", "usage-prompt-length-pricing.test.ts": "usage", "claude-picker-upload.test.ts": "claude-integration", "claude-picker-linger.test.ts": "claude-integration", "messages-native-scope.test.ts": "claude-integration", "catalog-auto-review-row.test.ts": "codex-integration", - "codex-use-remaining-quota.test.ts": "codex-integration", - "cli-log-view-filter.test.ts": "cli", "cli-usage-model-search.test.ts": "cli", "cli-usage-top.test.ts": "cli", "cli-companion-usage.test.ts": "cli", "cli-account-key-quota.test.ts": "cli", - "cli-observe-snapshot.test.ts": "cli", "cli-access-data-plane.test.ts": "cli", "cli-access-key-guard.test.ts": "cli", "cli-access-rename.test.ts": "cli", - "cli-access-audio.test.ts": "cli", "cli-access-audio-live.test.ts": "cli", "cli-log-follow.test.ts": "cli", "cli-injection-follow.test.ts": "cli", - "cli-usage-scope.test.ts": "cli", "cli-system-health.test.ts": "cli", "cli-companion-timeline.test.ts": "cli", "server-cli-key-probe-admission.test.ts": "server", - "cli-integration-preview.test.ts": "cli", "cli-integration-droid.test.ts": "cli", "cli-integration-journal.test.ts": "cli", "cli-aside-sync.test.ts": "cli", - "cli-claude-desktop-profile.test.ts": "cli", "cli-integration-cursor.test.ts": "cli", "cli-remote-workspace-hub.test.ts": "cli", "cli-storage-policy-fields.test.ts": "cli", "cli-link-force.test.ts": "cli", - "cli-account-policy.test.ts": "cli", "cli-account-login-options.test.ts": "cli", "cli-logout-runtime.test.ts": "cli", "cli-agent-settings.test.ts": "cli", - "cli-v2-runtime.test.ts": "cli", "cli-agent-runtime-settings.test.ts": "cli", "cli-system-settings-parity.test.ts": "cli", - "cli-catalog-command-result.test.ts": "cli", "cli-models-local-result.test.ts": "cli", "cli-models-custom-runtime.test.ts": "cli", "cli-models-order.test.ts": "cli", - "cli-models-display-name.test.ts": "cli", "cli-route-policy-write.test.ts": "cli", "cli-combo-parity.test.ts": "cli", "cli-combo-stats.test.ts": "cli", - "cli-json-input.test.ts": "cli", "cli-provider-lifecycle-runtime.test.ts": "cli", "cli-provider-settings.test.ts": "cli", "cli-provider-batch.test.ts": "cli", - "cli-provider-result.test.ts": "cli", "cli-provider-sync-result.test.ts": "cli", - "cli-capability-integration-workflows.test.ts": "cli", "cli-capability-account-workflows.test.ts": "cli", "cli-capability-agent-workflows.test.ts": "cli", "cli-capability-operation-workflows.test.ts": "cli", - "cli-capability-provider-workflows.test.ts": "cli", "cli-capability-access-workflows.test.ts": "cli", "cli-capability-lab-workflows.test.ts": "cli", "skill-ocx-workflows.test.ts": "ci-workflows", - "cli-capability-data.test.ts": "cli", "skill-ocx-generated.test.ts": "ci-workflows", - "cli-update-restart.test.ts": "cli", "cli-update-restart-child.test.ts": "cli", "cli-update-restart-transport.test.ts": "cli", "cli-update-restart-home.test.ts": "cli", - "cli-update-restart-service-record.test.ts": "cli", "cli-update-restart-supervision.test.ts": "cli", "cli-update-restart-admission.test.ts": "cli", "cli-update-restart-desktop-service.test.ts": "cli", - "codex-shim-overlay.test.ts": "codex-integration", "codex-shim-migration.test.ts": "codex-integration", - "codex-shim-overlay-transaction.test.ts": "codex-integration", "codex-shim-overlay-readiness.test.ts": "codex-integration", - "codex-shim-overlay-candidates.test.ts": "codex-integration", - "gui-pair-delivery.test.ts": "gui", - "usage-antigravity-55.test.ts": "usage", - "provider-antigravity-wire-snapshot.test.ts": "providers", - "antigravity-discovered-families.test.ts": "adapters/google", - "provider-antigravity-effort-families.test.ts": "providers", - "provider-antigravity-family-catalog.test.ts": "providers", - "claude-subagent-model-force.test.ts": "claude-integration", "claude-config-home-isolation.test.ts": "claude-integration", - "subagent-model-force-api.test.ts": "server", - "caller-session-identity.test.ts": "server", - "caller-session-ingress.test.ts": "server", - "agent-subagent-force.test.ts": "cli", - "compaction-event-ownership.test.ts": "responses", - "zed-retained-budget.test.ts": "providers", - "jev-decision-scope.test.ts": "server", - "server-combo-plan-model-refusal.test.ts": "server", - "codex-main-token-invalidated.test.ts": "codex-integration", - "codex-main-grant-refusal.test.ts": "codex-integration", - "responses-alternate-main-cancellation.test.ts": "responses", - "codex-shim-path-readiness.test.ts": "codex-integration", - "codex-shim-fnm.test.ts": "codex-integration", - "claude-intercept-cleanup.test.ts": "claude-integration", - "management-droid-reasoning-defaults.test.ts": "server", - "droid-reasoning-defaults.test.ts": "responses", - "claude-intercept-on-demand.test.ts": "claude-integration", - "main-account-hard-lock-thresholds.test.ts": "codex-integration", - "main-account-external-usage.test.ts": "codex-integration", - "jev-decision-model-config.test.ts": "routing", - "cli-combo-partial-update.test.ts": "cli", - "owner-registry-acl.test.ts": "config", - "minimax-combo-image-input.test.ts": "providers", - "web-search-forced-declaration.test.ts": "web-search", - "claude-devin-output-order.test.ts": "claude-integration", - "codex-config-preservation.test.ts": "codex-integration", - "codex-credits.test.ts": "codex-integration", - "codex-credits-settings.test.ts": "codex-integration", - "codex-credits-probes.test.ts": "codex-integration", - "codex-credits-after-limit.test.ts": "codex-integration", - "codex-pool-credit-policy.test.ts": "codex-integration", - "codex-sidecar-credit-policy.test.ts": "codex-integration", - "codex-credits-after-limit-main.test.ts": "codex-integration", - "service-runtime-preflight.test.ts": "service", "service-desktop-runtime-preflight.test.ts": "service", - "service-desktop-login-registration.test.ts": "service", "service-desktop-startup-health.test.ts": "service", "service-desktop-startup-linux.test.ts": "service", "service-desktop-startup.test.ts": "service", "service-desktop-supervision-windows.test.ts": "service", - "startup-health-packaged-probe.test.ts": "server", - "discovered-native-models.test.ts": "codex-integration", - "responses-hosted-image-delivery.test.ts": "responses", - "responses-hosted-image-display.test.ts": "responses", - "responses-hosted-image-limits.test.ts": "responses", - "dsh-login.test.ts": "oauth", - "dsh-account.test.ts": "providers", - "dsh-account-adapter.test.ts": "adapters", - "cursor-local-installer.test.ts": "providers/cursor", - "codex-quota-query-backoff.test.ts": "codex-integration", - "pnpm-command-isolation.test.ts": "update", "provider-antigravity-quota-retry.test.ts": "providers", "project-config-warning-snapshot.test.ts": "codex-integration", "codex-quota-auto-refresh-generation.test.ts": "codex-integration", "codex-account-clear-paused.test.ts": "codex-integration", - "low-quota-protection.test.ts": "codex-integration", - "bun-runtime-preflight.test.ts": "lib", - "responses-compaction-recovery.test.ts": "responses", "responses-canonical-nonstream.test.ts": "responses", "compaction-recovery-settings.test.ts": "config", "responses-compaction-recovery-policy.test.ts": "responses", "plugin-loader.test.ts": "lib", "plugin-upstream-hooks.test.ts": "lib", - "cli-kiro-auto-selection.test.ts": "cli", "codebuddy-live-models.test.ts": "providers", "kiro-auto-selection.test.ts": "providers/kiro", "kiro-quota-metrics.test.ts": "providers/kiro", "management-provider-request-pacing.test.ts": "server", - "cli-restart-handoff.test.ts": "cli", - "restart-replacement.test.ts": "server", "deepseek-artifact-tool-schema.test.ts": "providers", - "client-config-export-output-limit.test.ts": "config", "qoder-client.test.ts": "clients", "responses-skills-snapshot.test.ts": "responses", "responses-code-mode-mcp-direct.test.ts": "responses", "local-read-response-proof.test.ts": "server", - "claude-desktop-system-proxy.test.ts": "claude-integration", "codex-config-drift-heal.test.ts": "codex-integration", - "openai-chat-serialized-tool-call-scaling.test.ts": "adapters/openai", - "openai-chat-tool-call-id-remint.test.ts": "adapters/openai", - "coding-agent-json-lines-scaling.test.ts": "providers", - "usage-snapshot-digest-reuse.test.ts": "usage", - "worker-embed.test.ts": "lib", - "worker-embed-coverage.test.ts": "lib", - "jev-stats.test.ts": "usage", - "responses-devin-401-replay.test.ts": "responses", - "responses-oauth-refresh-capacity.test.ts": "responses", - "responses-grok-devin-preflight.test.ts": "responses", - "deepseek-quota-currency.test.ts": "providers", - "mimo-token-plan-capacity.test.ts": "providers", - "command-code-tool-text-prose-split.test.ts": "providers", - "cli-effort-slug.test.ts": "cli", - "grok-47-build-fast-metadata.test.ts": "providers/xai", - "grok-47-fast-model.test.ts": "providers/xai", - "grok-47-fast-model-wire.test.ts": "providers/xai", - "abort-idle-deadline.test.ts": "lib", - "tool-envelope-echo-whole-line.test.ts": "adapters", - "abort-race.test.ts": "adapters", - "account-import.test.ts": "server", - "account-pool-management-api.test.ts": "server", - "link-listener-admission.test.ts": "server", "link-management-relay.test.ts": "server", - "link-listener-lifecycle.test.ts": "server", "link-listener-mutation.test.ts": "server", - "link-join-route.test.ts": "server", - "core-link-boundary.test.ts": "lab", - "acl-error-classification.test.ts": "lib", - "active-registry-admission.test.ts": "codex-integration", "active-turn-disconnect.test.ts": "codex-integration", - "adapter-buffered-tool-conformance.test.ts": "adapters", - "adapter-error-inline.test.ts": "adapters", - "adapter-event-oauth-failover.test.ts": "oauth", - "adapter-inner-send-budget-wiring.test.ts": "adapters", - "adapter-inner-send-budget.test.ts": "adapters", - "adapter-input-media-guard.test.ts": "adapters", - "adapter-registry-authority.test.ts": "adapters", - "adapter-resolve.test.ts": "server", - "inference-client-wire.test.ts": "server", - "inference-attempt.test.ts": "server", - "inference-final-log.test.ts": "server", - "inference-send-budget.test.ts": "server", - "inference-client-encoder-delivery.test.ts": "server", - "adapter-tool-conformance.test.ts": "adapters", - "zed-hosted-provider.test.ts": "providers", - "adapter-usage.test.ts": "adapters", - "agent-driven.test.ts": "cli", - "agent-task-recovery-cache.test.ts": "server", - "agent-task-recovery-combo.test.ts": "server", - "agent-task-recovery-fallback.test.ts": "server", - "agent-task-recovery-security.test.ts": "server", - "agent-task-recovery.test.ts": "server", - "alias-management-api.test.ts": "server", - "alibaba-intl-token-plan.test.ts": "gui", - "alibaba-region-backup.test.ts": "providers", - "alibaba-region-migration.test.ts": "providers", - "alibaba-region-startup.test.ts": "providers", - "alibaba-token-plan-responses-optin.test.ts": "providers", - "alibaba-token-plan-wire-defaults.test.ts": "providers", - "always-on-429-failover.test.ts": "routing", - "ambiguous-resend-composition.test.ts": "lib", - "ambiguous-resend-gate.test.ts": "lib", - "anthropic-client-identity.test.ts": "adapters/anthropic", - "anthropic-account-metadata.test.ts": "adapters/anthropic", - "anthropic-account-pool.test.ts": "adapters/anthropic", - "anthropic-account-pause-outbound.test.ts": "adapters/anthropic", - "anthropic-account-pause.test.ts": "adapters/anthropic", - "anthropic-account-threshold.test.ts": "adapters/anthropic", - "anthropic-combo-account-cooldown.test.ts": "adapters/anthropic", - "cli-alias-json.test.ts": "cli", - "cli-anthropic-account-threshold.test.ts": "cli", - "anthropic-model-routes.test.ts": "adapters/anthropic", - "anthropic-agentrouter-language-framing.test.ts": "adapters/anthropic", - "anthropic-baseurl-override.test.ts": "adapters/anthropic", - "anthropic-compatible-stream.test.ts": "adapters/anthropic", - "anthropic-message-stop-termination.test.ts": "adapters/anthropic", - "anthropic-cooldown-recovery.test.ts": "adapters/anthropic", - "anthropic-empty-content.test.ts": "adapters/anthropic", - "anthropic-eof-tolerance.test.ts": "adapters/anthropic", - "anthropic-error-body.test.ts": "adapters/anthropic", - "anthropic-error-stop-reason.test.ts": "adapters/anthropic", "anthropic-thinking-usage.test.ts": "adapters/anthropic", - "anthropic-fast-opt-in.test.ts": "adapters/anthropic", - "anthropic-fast-speed.test.ts": "adapters/anthropic", - "anthropic-hardening.test.ts": "adapters/anthropic", - "anthropic-image-guard.test.ts": "adapters/anthropic", - "anthropic-image-normalize.test.ts": "adapters/anthropic", - "anthropic-image-retry-e2e.test.ts": "adapters/anthropic", - "anthropic-image-retry.test.ts": "adapters/anthropic", - "anthropic-sonnet-5-5-contract.test.ts": "adapters/anthropic", "anthropic-haiku-5-5-contract.test.ts": "adapters/anthropic", - "anthropic-output-maxima.test.ts": "adapters/anthropic", - "anthropic-parallel-tool-disable.test.ts": "adapters/anthropic", - "anthropic-pool-toggle-copy.test.ts": "adapters/anthropic", - "anthropic-quorum-cache.test.ts": "routing", - "anthropic-quota-dispatch.test.ts": "adapters/anthropic", - "anthropic-model-weekly-admission.test.ts": "adapters/anthropic", - "anthropic-429-policy.test.ts": "adapters/anthropic", - "anthropic-ratelimit-headers.test.ts": "adapters/anthropic", - "anthropic-reasoning.test.ts": "adapters/anthropic", - "anthropic-reset-grants.test.ts": "adapters/anthropic", - "anthropic-sidecar-account-failover.test.ts": "adapters/anthropic", - "anthropic-stream-hardening.test.ts": "adapters/anthropic", - "anthropic-tail-guard.test.ts": "adapters/anthropic", - "anthropic-progress-updates.test.ts": "adapters/anthropic", - "anthropic-thinking-signature.test.ts": "adapters/anthropic", - "anthropic-opaque-strip.test.ts": "adapters/anthropic", - "anthropic-tool-call-id.test.ts": "adapters/anthropic", - "anthropic-messages-passthrough.test.ts": "adapters/anthropic", - "anthropic-beta-allowlist.test.ts": "adapters/anthropic", - "anthropic-beta-body-pairs.test.ts": "adapters/anthropic", - "anthropic-messages-passthrough-oauth.test.ts": "adapters/anthropic", - "anthropic-tool-declaration-constraints.test.ts": "adapters/anthropic", - "anthropic-tool-schema.test.ts": "adapters/anthropic", - "antigravity-baseurl-override.test.ts": "adapters/google", - "antigravity-refusal.test.ts": "adapters/google", - "antigravity-static-catalog.test.ts": "adapters/google", - "api-access-endpoints.test.ts": "server", - "api-catalog-route.test.ts": "server", - "api-codex-log-guard-compact.test.ts": "server", - "api-codex-log-guard-protection.test.ts": "server", - "api-codex-log-guard.test.ts": "server", - "api-debug.test.ts": "server", - "api-key-attribution.test.ts": "server", - "api-key-catalog-authority.test.ts": "providers", - "api-key-model-scope.test.ts": "server", - "api-key-scope-alpha-search.test.ts": "server", - "api-key-scope-audio.test.ts": "server", - "api-key-scope-images.test.ts": "server", - "api-key-scope-live.test.ts": "server", - "api-key-selection-capture.test.ts": "providers", - "api-keys-routes.test.ts": "server", - "api-storage-cleanup.test.ts": "storage", - "api-storage-policy-already-running.test.ts": "storage", - "api-storage-policy-mutation-busy.test.ts": "storage", - "api-storage-policy-put-race.test.ts": "storage", - "api-storage-policy-run.test.ts": "storage", - "api-storage-policy.test.ts": "storage", - "api-storage.test.ts": "storage", - "api-usage.test.ts": "server", - "app-owned-memory.test.ts": "codex-integration", - "apply-patch-envelope.test.ts": "responses", - "artifacts-prune.test.ts": "images", - "artifacts-ssrf.test.ts": "images", - "aside-client.test.ts": "providers", - "aside-profiles-routes.test.ts": "server", - "assert-mergeable-review.test.ts": "ci-workflows", - "audio-client.test.ts": "server", - "audio-dictation.test.ts": "server", - "audio-transcriptions.test.ts": "server", - "auto-compact-budget.test.ts": "providers", - "autostart-health.test.ts": "service", - "azure-adapter.test.ts": "providers", - "azure-model-router-tool-schema.test.ts": "providers", - "bare-echo-alias.test.ts": "responses", - "baseten-provider.test.ts": "providers", - "bearer-admission-routed-provider.test.ts": "codex-integration", - "bounded-body.test.ts": "server", - "brand-favicons.test.ts": "ci-workflows", - "bridge-legacy-shell-normalization.test.ts": "adapters", - "bridge-lifecycle.test.ts": "adapters", - "bridge-live-delivery.test.ts": "server", - "bridge-nonstreaming-terminal.test.ts": "adapters", - "bridge-raw-reasoning-hidden.test.ts": "adapters", - "bridge-reasoning-replay-batch.test.ts": "adapters", - "bridge-stall.test.ts": "adapters", - "bridge-terminal-singleness.test.ts": "adapters", - "bridge.test.ts": "adapters", - "buffered-response-shape-guards.test.ts": "adapters", - "build-desktop-icon-set.test.ts": "ci-workflows", - "build-release-changelog.test.ts": "ci-workflows", - "bump-dev-version.test.ts": "ci-workflows", - "bun-runtime.test.ts": "ci-workflows", - "bun-stream-caps.test.ts": "lib", - "cache-diagnostic.test.ts": "usage", - "cancel-body-on-abort.test.ts": "server", - "catalog-auto-refresh-client-fanout.test.ts": "codex-integration", "catalog-auto-refresh-scheduler.test.ts": "codex-integration", - "catalog-cursor-search.test.ts": "codex-integration", - "catalog-custom-ordering.test.ts": "codex-integration", - "catalog-duplicate-slug-dedup.test.ts": "codex-integration", - "catalog-free-pricing-status.test.ts": "codex-integration", - "catalog-full-picker-order.test.ts": "codex-integration", - "catalog-gated-native-suppression-reason.test.ts": "codex-integration", - "catalog-go-exact-efforts.test.ts": "codex-integration", - "catalog-hub-context-window.test.ts": "codex-integration", - "catalog-input-modality-enum.test.ts": "codex-integration", - "catalog-llamacpp-capabilities.test.ts": "codex-integration", - "catalog-modelalias-unique-sync.test.ts": "codex-integration", - "catalog-oauth-observation.test.ts": "codex-integration", - "catalog-opencode-go-context-window.test.ts": "codex-integration", - "catalog-remote-pull.test.ts": "codex-integration", - "catalog-retain-models.test.ts": "codex-integration", - "catalog-routed-comp-hash.test.ts": "codex-integration", - "catalog-seed-window-fill.test.ts": "codex-integration", - "catalog-slug-uniqueness-boundary.test.ts": "codex-integration", - "catalog-verbosity-default.test.ts": "codex-integration", - "catalog-vision-sidecar-modalities.test.ts": "codex-integration", - "catalog-zero-credit-picker.test.ts": "codex-integration", - "chat-completions-deferred-tools.test.ts": "responses", "passthrough-deferred-tools.test.ts": "responses", - "chat-completions-endpoint.test.ts": "responses", - "chat-completions-pool-mode.test.ts": "responses", - "chat-conversation-affinity.test.ts": "responses", - "chat-inbound-developer-position.test.ts": "responses", - "protocol-contract.test.ts": "responses", - "protocol-features.test.ts": "responses", - "protocol-opaque-state.test.ts": "responses", - "protocol-baseline.test.ts": "responses", - "protocol-dto.test.ts": "responses", - "protocol-path.test.ts": "responses", - "protocol-trace.test.ts": "responses", - "protocol-plan.test.ts": "responses", - "protocol-plan-snapshot.test.ts": "responses", - "protocol-shadow-plan.test.ts": "responses", - "protocol-envelope.test.ts": "responses", - "protocol-guard.test.ts": "responses", - "protocol-ingress-guard.test.ts": "responses", - "protocol-direct-encoders-chat.test.ts": "responses", - "protocol-direct-encoders-stall-disabled.test.ts": "responses", - "protocol-direct-encoders-local-upstream.test.ts": "responses", - "protocol-direct-encoders-messages.test.ts": "responses", - "protocol-chat-ir-parity.test.ts": "responses", - "protocol-antigravity-direct-chat.test.ts": "responses", - "protocol-antigravity-direct-eligibility.test.ts": "responses", - "protocol-messages-ir-parity.test.ts": "responses", - "protocol-antigravity-direct-messages.test.ts": "responses", - "chat-native-combo.test.ts": "responses", "jev-initial-effort-wire.test.ts": "responses", - "messages-native-eligibility.test.ts": "responses", - "responses-first-send-reservation.test.ts": "responses", "responses-first-send-spend-policy.test.ts": "responses", "responses-dispatch-receipt.test.ts": "responses", "responses-hosted-send-hop.test.ts": "responses", "responses-hosted-send-producer.test.ts": "responses", "responses-hosted-send-reservation.test.ts": "responses", "responses-hosted-send-round-parity.test.ts": "responses", "responses-hosted-send-unsent-hop.test.ts": "responses", "responses-hosted-send-ws.test.ts": "responses", - "messages-native-bridge-policy.test.ts": "responses", - "messages-native-oauth-eligibility.test.ts": "responses", - "chat-inbound-reasoning-none.test.ts": "responses", - "chat-native-decline-reason.test.ts": "responses", - "chat-inbound-reasoning-replay.test.ts": "responses", - "chat-inline-document-bytes.test.ts": "responses", - "chat-json-sse-fallback.test.ts": "responses", - "chat-media-translation.test.ts": "responses", - "chat-native-developer-role.test.ts": "responses", - "chat-native-reasoning-replay.test.ts": "responses", - "chat-native-reasoning-scope.test.ts": "responses", - "chat-native-image-normalization.test.ts": "responses", - "chat-native-spend.test.ts": "responses", - "chat-refusal-scope.test.ts": "responses", - "chat-refusal.test.ts": "responses", - "chat-responses-control-integration.test.ts": "responses", - "chat-responses-control-scope.test.ts": "responses", - "chat-tool-choice-allowed-tools.test.ts": "responses", - "chatgpt-device-auth.test.ts": "oauth", - "chatgpt-oauth.test.ts": "oauth", - "chatgpt-token-expiry.test.ts": "oauth", - "chatgpt-token-boundaries.test.ts": "oauth", - "chutes-provider.test.ts": "providers", - "ci-bun-crash-classifier.test.ts": "ci-workflows", - "ci-crash-disposition.test.ts": "ci-workflows", - "ci-gui-typecheck-gate.test.ts": "ci-workflows", - "ci-privacy-gate.test.ts": "ci-workflows", - "ci-review-lanes.test.ts": "ci-workflows", - "ci-scope-reduction.test.ts": "ci-workflows", - "ci-scope-gaps.test.ts": "ci-workflows", - "ci-shard-balance.test.ts": "ci-workflows", - "ci-structure-gate.test.ts": "ci-workflows", - "ci-workflows.test.ts": "ci-workflows", - "citation-markers.test.ts": "responses", - "visualization-directives.test.ts": "responses", - "cl01-claude-outbound-review-regressions.test.ts": "routing", - "cl01-openai-chat-review-regressions.test.ts": "routing", - "cl01-review-regressions.test.ts": "routing", - "claude-529-mapping.test.ts": "claude-integration", - "claude-agent-startup-sync.test.ts": "claude-integration", - "claude-agents-inject-client.test.ts": "claude-integration", - "claude-agents-inject.test.ts": "claude-integration", - "claude-alias.test.ts": "claude-integration", - "claude-auth-detect.test.ts": "claude-integration", - "claude-auth-mode.test.ts": "claude-integration", - "claude-authmode-migration.test.ts": "claude-integration", - "claude-cli-adapter.test.ts": "providers", - "claude-cli-client-http.test.ts": "providers", - "claude-cli-efficiency.test.ts": "providers", - "claude-cli-tool-capture.test.ts": "providers", - "claude-cli-usage-admission.test.ts": "providers", - "claude-cli.test.ts": "claude-integration", - "claude-config-first-party.test.ts": "cli", - "claude-code-thought-signature-scope.test.ts": "claude-integration", - "claude-compatibility.test.ts": "claude-integration", - "claude-context-windows.test.ts": "claude-integration", - "claude-desktop-1m.test.ts": "claude-integration", - "claude-desktop-cli.test.ts": "claude-integration", - "claude-desktop-config-path.test.ts": "claude-integration", - "claude-desktop-discovery.test.ts": "claude-integration", - "claude-desktop-first-party.test.ts": "claude-integration", - "claude-desktop-first-party-guards.test.ts": "claude-integration", - "claude-desktop-mode-explanation.test.ts": "claude-integration", - "claude-desktop-picker.test.ts": "claude-integration", - "claude-desktop-picker-profile.test.ts": "claude-integration", - "claude-desktop-picker-routes.test.ts": "claude-integration", - "claude-desktop-native-context.test.ts": "claude-integration", - "claude-desktop-policy.test.ts": "claude-integration", - "claude-cli-picker.test.ts": "claude-integration", - "claude-cli-picker-surface.test.ts": "claude-integration", - "claude-picker-bootstrap.test.ts": "claude-integration", "claude-picker-ca.test.ts": "claude-integration", "claude-picker-ca-store.test.ts": "claude-integration", - "claude-picker-listener.test.ts": "claude-integration", "claude-picker-models.test.ts": "claude-integration", "claude-picker-recovery.test.ts": "claude-integration", - "claude-picker-runtime.test.ts": "claude-integration", "claude-picker-startup.test.ts": "claude-integration", "claude-picker-trust.test.ts": "claude-integration", - "claude-desktop-remote-hub.test.ts": "claude-integration", - "claude-dotenv-provenance-transport.test.ts": "claude-integration", - "claude-estimate-projection.test.ts": "claude-integration", - "claude-first-party-agent-sync.test.ts": "claude-integration", - "claude-first-party-union.test.ts": "claude-integration", - "claude-gateway-cache.test.ts": "claude-integration", - "claude-inbound-cache-stabilize.test.ts": "claude-integration", "claude-inbound-token-footer.test.ts": "claude-integration", - "claude-inbound-debug.test.ts": "claude-integration", - "claude-inbound.test.ts": "claude-integration", "claude-inbound-tool-reference.test.ts": "claude-integration", "claude-native-reasoning-continuity.test.ts": "claude-integration", "claude-native-reasoning-provenance.test.ts": "claude-integration", - "claude-output-schema-strict.test.ts": "claude-integration", - "claude-intercept-integration.test.ts": "server", - "claude-intercept-local-ca.test.ts": "claude-integration", - "claude-intercept-local-ca-files.test.ts": "claude-integration", - "claude-intercept-local-ca-windows.test.ts": "claude-integration", - "claude-intercept-model-bindings.test.ts": "claude-integration", - "claude-intercept-proxy.test.ts": "claude-integration", - "claude-intercept-client-class.test.ts": "claude-integration", - "claude-intercept-proxy-auth.test.ts": "claude-integration", - "claude-model-default-labels.test.ts": "claude-integration", "claude-intercept-settings.test.ts": "claude-integration", "claude-intercept-no-proxy.test.ts": "claude-integration", - "claude-management-api.test.ts": "claude-integration", - "claude-manual-env.test.ts": "gui", - "claude-messages-endpoint.test.ts": "claude-integration", - "claude-messages-thread.test.ts": "claude-integration", - "messages-native.test.ts": "claude-integration", - "messages-native-decline-trace.test.ts": "claude-integration", - "messages-native-oauth.test.ts": "claude-integration", - "messages-native-opaque-state.test.ts": "claude-integration", - "messages-surface-matrix.test.ts": "claude-integration", "claude-long-context-eligibility.test.ts": "claude-integration", - "claude-context-accounting.test.ts": "claude-integration", "claude-model-info.test.ts": "claude-integration", - "claude-models-discovery.test.ts": "claude-integration", - "claude-native-affinity.test.ts": "claude-integration", - "claude-native-passthrough.test.ts": "claude-integration", - "claude-native-rate-limit-headers.test.ts": "claude-integration", - "claude-outbound.test.ts": "claude-integration", - "claude-prompt-too-long.test.ts": "claude-integration", - "claude-shell-hook.test.ts": "claude-integration", - "claude-sidecar-override.test.ts": "claude-integration", - "claude-source-envelope.test.ts": "claude-integration", - "claude-system-env-auto.test.ts": "claude-integration", - "cleanup-orphaned-workflows.test.ts": "ci-workflows", - "clearable-deadline.test.ts": "lib", - "cli-account-alias-target.test.ts": "cli", - "cli-account-cancel-flow.test.ts": "cli", - "cli-account-kiro-device.test.ts": "cli", "cli-account-orca-import.test.ts": "cli", - "cli-account-pin-drain.test.ts": "cli", - "cli-account-pool-verbs.test.ts": "cli", - "cli-account-threshold.test.ts": "cli", - "cli-account-verify-status.test.ts": "cli", - "cli-account.test.ts": "cli", - "cli-capabilities-arguments.test.ts": "cli", - "cli-capabilities.test.ts": "cli", - "cli-api-protocols.test.ts": "cli", - "cli-catalog-prewarm.test.ts": "cli", - "cli-ensure-readiness.test.ts": "cli", - "cli-codex-cli-update.test.ts": "cli", - "cli-codex-log-guard-compact.test.ts": "cli", - "cli-codex-log-guard-protection.test.ts": "cli", - "cli-codex-log-guard.test.ts": "cli", - "cli-companion.test.ts": "cli", - "cli-config-bom.test.ts": "cli", - "cli-config-command.test.ts": "cli", - "cli-config-default-show.test.ts": "cli", - "cli-config-show-client.test.ts": "cli", - "cli-connect-readiness.test.ts": "cli", - "cli-dispatch.test.ts": "cli", - "cli-client-start-fence.test.ts": "cli", - "cli-ensure-client-state.test.ts": "cli", - "cli-client-start-owner-e2e.test.ts": "cli", - "cli-dto-fidelity.test.ts": "cli", - "cli-export-command.test.ts": "cli", - "cli-head.test.ts": "cli", - "cli-headless-parity.test.ts": "cli", - "cli-help.test.ts": "cli", - "cli-help-paths.test.ts": "cli", - "cli-help-navigation.test.ts": "cli", - "cli-help-recovery.test.ts": "cli", - "cli-integer-options.test.ts": "cli", - "cli-init-port.test.ts": "cli", - "cli-json-contract.test.ts": "cli", - "cli-logs-request-id.test.ts": "cli", - "cli-management-auth.test.ts": "cli", - "cli-models-free-only.test.ts": "cli", - "cli-models-price.test.ts": "cli", - "cli-models-reasoning.test.ts": "cli", - "cli-models-runtime-dispatch.test.ts": "cli", "cli-models-set.test.ts": "cli", - "cli-models.test.ts": "cli", - "cli-native-profile.test.ts": "cli", - "cli-observe-logs.test.ts": "cli", - "cli-provider.test.ts": "cli", - "cli-ready-subprocess.test.ts": "cli", - "cli-ready.test.ts": "cli", - "cli-registry.test.ts": "cli", - "cli-resolve-subprocess.test.ts": "cli", - "cli-resolve.test.ts": "cli", - "cli-restart-health.test.ts": "cli", - "cli-restore-back.test.ts": "cli", - "cli-route-policy-not-found.test.ts": "cli", - "cli-start-auxiliary-bind.test.ts": "cli", - "cli-start-journal-order.test.ts": "cli", - "sibling-home-client-sync.test.ts": "cli", - "cli-status-hub-state.test.ts": "cli", - "cli-status-json.test.ts": "cli", - "cli-status-oauth-health.test.ts": "cli", - "cli-stop-json.test.ts": "cli", - "cli-storage-inspect.test.ts": "cli", - "cli-transport-honesty.test.ts": "cli", - "cli-update-badge.test.ts": "cli", - "cli-usage-hub.test.ts": "cli", - "cli-usage-report.test.ts": "cli", - "cli-version-skew.test.ts": "cli", - "client-config-export-new-clients.test.ts": "config", - "client-config-export.test.ts": "config", - "client-config-new-clients.test.ts": "config", - "client-injection-guard.test.ts": "codex-integration", - "cli-link-child.test.ts": "cli", - "cline-pass-deepseek-v4-tool-replay.test.ts": "providers", - "cline-pass-provider.test.ts": "providers", - "cline-pass-reasoning-efforts.test.ts": "providers", - "cline-provider.test.ts": "providers", - "closed-pr-branch-cleanup.test.ts": "ci-workflows", - "codebuddy-adapter.test.ts": "providers", - "codebuddy-live-acceptance.test.ts": "providers", - "codebuddy-mcp-server.test.ts": "providers", - "codebuddy-protocol.test.ts": "providers", - "codebuddy-tool-bridge-turn.test.ts": "providers", - "codebuddy-tool-bridge.test.ts": "providers", - "codex-account-delete-atomicity.test.ts": "codex-integration", - "codex-account-selection-atomicity.test.ts": "codex-integration", - "codex-account-label.test.ts": "codex-integration", - "codex-account-mode-state.test.ts": "gui", - "codex-account-namespaces.test.ts": "codex-integration", - "codex-account-selection-preferences.test.ts": "codex-integration", - "codex-account-store-refresh-classification.test.ts": "codex-integration", - "codex-account-store.test.ts": "codex-integration", - "codex-account-threshold-api.test.ts": "codex-integration", - "codex-account-threshold-auth.test.ts": "codex-integration", - "codex-account-threshold-routing.test.ts": "codex-integration", - "codex-account-unusable-reason.test.ts": "codex-integration", - "codex-admission-primitives.test.ts": "codex-integration", - "codex-admission.test.ts": "codex-integration", - "codex-affinity-debug.test.ts": "codex-integration", - "codex-app-server-path-spaces.test.ts": "codex-integration", - "codex-app-server-processes.test.ts": "codex-integration", - "codex-app-server-restart-service.test.ts": "codex-integration", - "codex-auth-api.test.ts": "codex-integration", - "codex-linked-account-pause.test.ts": "codex-integration", - "codex-auth-cancel-ownership.test.ts": "codex-integration", - "codex-auth-collision.test.ts": "codex-integration", - "codex-auth-context.test.ts": "codex-integration", - "codex-auth-modal-status.test.ts": "gui", "codex-set-prompt.test.ts": "gui", - "codex-catalog-admission.test.ts": "codex-integration", - "codex-catalog-exclusions.test.ts": "codex-integration", - "codex-catalog-golden.test.ts": "codex-integration", - "codex-catalog-identity-neutral.test.ts": "codex-integration", - "codex-catalog-ladders.test.ts": "codex-integration", - "codex-catalog-model-picker-order.test.ts": "codex-integration", - "codex-catalog-refresh-status.test.ts": "codex-integration", - "codex-catalog-restore.test.ts": "codex-integration", - "codex-catalog-sync-hardening.test.ts": "codex-integration", - "codex-catalog-routed-removal.test.ts": "codex-integration", - "codex-catalog-intent.test.ts": "codex-integration", - "codex-catalog-write-audit.test.ts": "codex-integration", - "codex-catalog-self-heal.test.ts": "codex-integration", - "codex-catalog-heal-integration.test.ts": "codex-integration", - "codex-home-owner.test.ts": "codex-integration", - "codex-home-owner-lifecycle.test.ts": "codex-integration", - "codex-catalog-write-serialization.test.ts": "codex-integration", - "codex-catalog-writer.test.ts": "codex-integration", - "vendor-context.test.ts": "codex-integration", "codex-catalog.test.ts": "codex-integration", - "codex-cli-install-provenance.test.ts": "codex-integration", - "codex-cli-installation-identity.test.ts": "codex-integration", - "codex-cli-installation-targets.test.ts": "codex-integration", - "codex-cli-update-launcher-policy.test.ts": "codex-integration", - "codex-cli-update-zero-effect.test.ts": "codex-integration", - "codex-cli-windows-installation-files.test.ts": "codex-integration", - "codex-forward-access-programs-writer.test.ts": "codex-integration", - "codex-composed-acceptance.test.ts": "codex-integration", - "codex-config-generation.test.ts": "codex-integration", - "codex-context-owner.test.ts": "codex-integration", - "codex-convergence-account-selectors.test.ts": "codex-integration", - "codex-convergence-contract.test.ts": "codex-integration", - "codex-cooldown-recovery.test.ts": "codex-integration", - "codex-coordinator-doctor.test.ts": "codex-integration", - "codex-desired-state.test.ts": "codex-integration", - "codex-entitlement-identity-read-fence.test.ts": "codex-integration", - "codex-envkey-admission-substitution.test.ts": "codex-integration", - "codex-exec-invocation.test.ts": "codex-integration", "messaging-local-discovery.test.ts": "codex-integration", "messaging-local-cli.test.ts": "codex-integration", "messaging-local-envelope.test.ts": "codex-integration", - "messaging-local-send.test.ts": "codex-integration", "messaging-local-lifecycle.test.ts": "codex-integration", "messaging-local-socket.test.ts": "codex-integration", "codex-features-cache.test.ts": "codex-integration", - "codex-features-residual.test.ts": "codex-integration", "codex-failure-window.test.ts": "codex-integration", - "codex-filesystem-evidence.test.ts": "codex-integration", - "codex-gather-authority.test.ts": "codex-integration", - "codex-history-job.test.ts": "codex-integration", - "codex-history-lock.test.ts": "codex-integration", - "codex-history-provider.test.ts": "codex-integration", - "codex-history-reachability.test.ts": "codex-integration", - "codex-history-worker-boundary.test.ts": "codex-integration", - "codex-history-worker.test.ts": "codex-integration", - "codex-history-writer.test.ts": "codex-integration", - "codex-home-wsl.test.ts": "codex-integration", - "codex-home-wsl-local-state.test.ts": "codex-integration", - "codex-inject-history-wording.test.ts": "codex-integration", - "codex-inject-integration.test.ts": "codex-integration", - "codex-inject-missing-config.test.ts": "codex-integration", - "codex-inject-retained-table.test.ts": "codex-integration", - "codex-inject-v1-reconcile.test.ts": "codex-integration", - "codex-inject-write-lock.test.ts": "codex-integration", - "codex-inject.test.ts": "codex-integration", - "codex-injected-marker.test.ts": "codex-integration", - "codex-integration-record.test.ts": "codex-integration", - "codex-journal-recovery.test.ts": "codex-integration", "codex-journal.test.ts": "codex-integration", - "codex-legacy-config-keys.test.ts": "codex-integration", - "codex-lineage-placement.test.ts": "codex-integration", - "codex-log-guard-coderabbit.test.ts": "codex-integration", - "codex-log-guard-doctor-coderabbit.test.ts": "codex-integration", - "codex-log-guard-doctor-protection.test.ts": "codex-integration", - "codex-log-guard-doctor.test.ts": "codex-integration", - "codex-log-guard-inspect.test.ts": "codex-integration", - "codex-log-guard-lock.test.ts": "codex-integration", - "codex-log-guard-maintenance-coderabbit.test.ts": "codex-integration", - "codex-log-guard-maintenance.test.ts": "codex-integration", - "codex-log-guard-policy.test.ts": "codex-integration", - "codex-log-guard-processes.test.ts": "codex-integration", - "codex-log-guard-protection.test.ts": "codex-integration", - "codex-log-guard-status-zero-write.test.ts": "codex-integration", - "codex-main-account-refresh.test.ts": "codex-integration", - "codex-main-rotation.test.ts": "codex-integration", - "codex-management-convergence.test.ts": "codex-integration", - "codex-metadata-integrity.test.ts": "codex-integration", - "codex-model-availability-error.test.ts": "codex-integration", - "codex-model-denial-evidence.test.ts": "codex-integration", - "codex-model-entitlement-admission.test.ts": "codex-integration", - "codex-model-entitlements-program-shape.test.ts": "codex-integration", - "codex-native-availability-nux.test.ts": "codex-integration", - "codex-model-entitlements.test.ts": "codex-integration", - "codex-models-cache-invalidate.test.ts": "codex-integration", - "codex-native-residue.test.ts": "codex-integration", - "codex-pin-drain-projection.test.ts": "codex-integration", - "codex-plan.test.ts": "codex-integration", - "codex-plugins-doctor.test.ts": "codex-integration", - "codex-pool-plan-exclusion.test.ts": "codex-integration", - "codex-pool-refresh-backoff.test.ts": "codex-integration", - "codex-pool-request-owned-main.test.ts": "codex-integration", - "codex-pool-rotation.test.ts": "codex-integration", "codex-auth-release.test.ts": "codex-integration", - "codex-priority-failback.test.ts": "codex-integration", - "codex-idle-window.test.ts": "codex-integration", - "codex-prompt-adopt.test.ts": "codex-integration", - "codex-prompt-base-variants.test.ts": "codex-integration", "codex-prompt-writes.test.ts": "codex-integration", "codex-prompt-scalar-scope.test.ts": "codex-integration", - "codex-prompt-journal.test.ts": "codex-integration", - "codex-prompt-layers-read.test.ts": "codex-integration", - "codex-prompt-layers-write.test.ts": "codex-integration", - "codex-prompt-layers.test.ts": "codex-integration", - "codex-prompt-lock-sharing.test.ts": "codex-integration", - "codex-prompt-lock.test.ts": "codex-integration", "codex-config-write-lock.test.ts": "codex-integration", "codex-missing-home.test.ts": "codex-integration", - "codex-prompt-route.test.ts": "codex-integration", - "codex-prompt-text-probe.test.ts": "codex-integration", - "codex-provider-table-retention.test.ts": "codex-integration", - "codex-quota-auto-refresh-main-admission.test.ts": "codex-integration", - "codex-quota-auto-refresh.test.ts": "codex-integration", - "codex-quota-capacity.test.ts": "codex-integration", - "codex-quota-history.test.ts": "codex-integration", - "codex-quota-parser-parity.test.ts": "codex-integration", - "codex-quota-prime.test.ts": "codex-integration", - "codex-quota-rejection.test.ts": "codex-integration", - "codex-refresh.test.ts": "codex-integration", - "codex-reset-credit-auto-redeem.test.ts": "codex-integration", - "codex-reset-credit-operation-ledger.test.ts": "codex-integration", - "codex-reset-credit-recovery.test.ts": "codex-integration", - "codex-restart-contract-parity.test.ts": "codex-integration", - "codex-restart-route.test.ts": "codex-integration", - "codex-restore-app-rewrite.test.ts": "codex-integration", - "codex-retained-root-serialization.test.ts": "codex-integration", - "codex-routing-cache-affinity-detour.test.ts": "codex-integration", - "codex-routing.test.ts": "codex-integration", - "codex-runtime.test.ts": "codex-integration", "codex-runtime-macos-desktop.test.ts": "codex-integration", "codex-clamp-notice.test.ts": "codex-integration", - "codex-runtime-wsl-desktop.test.ts": "codex-integration", - "codex-service-manager-probe-hardening.test.ts": "codex-integration", - "codex-service-manager-probe.test.ts": "codex-integration", - "codex-systemd-env-probe.test.ts": "codex-integration", - "codex-shim-autorestore.test.ts": "codex-integration", - "codex-shim-destroyed-probe.test.ts": "codex-integration", - "codex-shim-ensure-failure.test.ts": "codex-integration", - "codex-shim-readiness.test.ts": "codex-integration", - "codex-shim-standalone.test.ts": "codex-integration", - "codex-shim.test.ts": "codex-integration", - "codex-signin-lockout.test.ts": "codex-integration", - "codex-spark-visibility.test.ts": "codex-integration", - "codex-sqlite-home.test.ts": "codex-integration", - "codex-sync-api.test.ts": "codex-integration", - "codex-sync-new-model-policy.test.ts": "codex-integration", - "codex-sync-response.test.ts": "codex-integration", - "codex-tool-mode.test.ts": "codex-integration", - "codex-transition-state-adoption.test.ts": "codex-integration", - "codex-transition-state-first-use-regression.test.ts": "codex-integration", - "codex-transition-state-race.test.ts": "codex-integration", - "codex-transition-state.test.ts": "codex-integration", - "codex-user-identity.test.ts": "codex-integration", - "codex-v2-gate.test.ts": "codex-integration", - "codex-agent-thread-limit.test.ts": "codex-integration", - "codex-warmup.test.ts": "codex-integration", - "codex-web-search-switch.test.ts": "codex-integration", - "codex-websocket-registry.test.ts": "codex-integration", - "codex-write-lock.test.ts": "codex-integration", - "coding-agent-tool-result-images.test.ts": "adapters", - "cold-spawn-warmup.test.ts": "ci-workflows", - "combo-authoritative-reset.test.ts": "codex-integration", - "combo-codex-exhaustion-cooldown.test.ts": "codex-integration", - "combo-permanent-failure-cooldown.test.ts": "codex-integration", - "combo-reset-window-model-scope.test.ts": "codex-integration", - "combo-child-headers.test.ts": "routing", - "combo-last-resort.test.ts": "codex-integration", - "combo-management-api.test.ts": "routing", - "combo-vision-enrollment.test.ts": "routing", - "combo-stream-preflight.test.ts": "routing", - "combo-workspace-data.test.ts": "gui", - "combo-workspace-jev-decision.test.ts": "gui", - "combos.test.ts": "codex-integration", - "command-code-error-finish.test.ts": "providers", - "command-code-efforts.test.ts": "providers", - "command-code-project-context.test.ts": "providers", - "command-code-provider.test.ts": "providers", - "command-code-quota.test.ts": "providers", - "command-code-tool-text.test.ts": "providers", - "command-code-workspace-cache.test.ts": "providers", - "commandcode-provider.test.ts": "providers", - "compaction-progress.test.ts": "responses", - "companion-settings.test.ts": "server", - "compatibility-manifest.test.ts": "codex-integration", - "compatibility-provider-equivalence.test.ts": "routing", - "compatibility-version.test.ts": "ci-workflows", - "config-account-thresholds.test.ts": "config", - "config-blocked-model-redirects.test.ts": "config", - "config-catalog-auto-refresh.test.ts": "config", - "config-commandcode-claude-pin.test.ts": "config", - "config-load-degrade.test.ts": "config", - "protocol-settings.test.ts": "config", - "config-mutation-lock.test.ts": "config", - "config-non-object-backup.test.ts": "config", - "config-ownership-uninstall.test.ts": "config", - "config-rebase-provenance-writers.test.ts": "config", - "config-save-boundary.test.ts": "config", - "config-spend-ceilings.test.ts": "config", - "config-spend-pool-collision.test.ts": "config", - "config-user-edits.test.ts": "config", "hub-disable-live-save.test.ts": "config", - "config.test.ts": "server", - "configured-native-models.test.ts": "codex-integration", - "gui-desktop-sidecar-signing.test.ts": "gui", - "linux-desktop-packaged-ci.test.ts": "ci-workflows", - "probe-timeout-env.test.ts": "server", - "subagent-roster-migration.test.ts": "routing", - "consume-for-inspection-cancel.test.ts": "server", - "container-bootstrap.test.ts": "service", - "context-cap-unknown-window.test.ts": "providers", - "context-compat.test.ts": "codex-integration", - "context-history-ownership.test.ts": "server", - "context-history.test.ts": "server", - "context-window-seed-repair.test.ts": "providers", - "continuation-dedup.test.ts": "responses", - "core-lab-boundary.test.ts": "lab", - "cost-cap-unknown-evidence.test.ts": "usage", - "cost-scoring.test.ts": "usage", - "crash-guard.test.ts": "service", - "credential-redirect-guard.test.ts": "lib", - "crusoe-provider.test.ts": "providers", - "cursor-adapter.test.ts": "providers/cursor", - "cursor-arg-normalize.test.ts": "providers/cursor", - "cursor-blob-integrity.test.ts": "providers/cursor", - "cursor-blob-claude-client-tools.test.ts": "providers/cursor", "cursor-blob.test.ts": "providers/cursor", - "cursor-call-id.test.ts": "providers/cursor", - "cursor-cancel-provenance.test.ts": "providers/cursor", - "cursor-catalog.test.ts": "providers/cursor", - "cursor-claude-id.test.ts": "providers/cursor", - "cursor-continuation-invariants.test.ts": "providers/cursor", - "cursor-continuity-retention.test.ts": "providers/cursor", - "cursor-default-catalog-suppression.test.ts": "providers/cursor", - "cursor-desktop-exec.test.ts": "providers/cursor", - "cursor-discovery.test.ts": "providers/cursor", - "cursor-display-names.test.ts": "providers/cursor", - "cursor-effort-rows.test.ts": "providers/cursor", - "cursor-effort-suffix.test.ts": "providers/cursor", - "cursor-effort-table.test.ts": "providers/cursor", - "cursor-envelope-echo-retry.test.ts": "providers/cursor", - "cursor-eof-terminal.test.ts": "providers/cursor", - "cursor-errors.test.ts": "providers/cursor", - "cursor-exec-empty-result.test.ts": "providers/cursor", - "cursor-fast-listing.test.ts": "providers/cursor", - "cursor-fast-tier.test.ts": "providers/cursor", - "cursor-framing.test.ts": "providers/cursor", - "cursor-h2-pool-shutdown.test.ts": "providers/cursor", - "cursor-hardening.test.ts": "providers/cursor", - "cursor-http1-transport.test.ts": "providers/cursor", - "cursor-images.test.ts": "providers/cursor", - "cursor-integration-status.test.ts": "providers/cursor", - "cursor-interaction-query.test.ts": "providers/cursor", - "cursor-kv-store.test.ts": "providers/cursor", - "cursor-live-smoke-gate.test.ts": "providers/cursor", - "cursor-live-transport.test.ts": "providers/cursor", - "cursor-local-models-schema.test.ts": "providers/cursor", - "cursor-mcp-manager.test.ts": "providers/cursor", - "cursor-mcp-stdio.test.ts": "providers/cursor", - "cursor-message-mapper.test.ts": "providers/cursor", - "cursor-native-exec-common.test.ts": "providers/cursor", - "cursor-native-exec-policy.test.ts": "providers/cursor", - "cursor-native-exec-shell.test.ts": "providers/cursor", - "cursor-foreground-shell.test.ts": "providers/cursor", - "cursor-native-exec.test.ts": "providers/cursor", - "cursor-oauth-shell.test.ts": "providers/cursor", - "cursor-oauth.test.ts": "providers/cursor", - "cursor-pool.test.ts": "providers/cursor", - "cursor-protobuf-events.test.ts": "providers/cursor", - "cursor-repetition-breaker.test.ts": "providers/cursor", - "cursor-request-builder.test.ts": "providers/cursor", - "cursor-request-compat.test.ts": "providers/cursor", - "cursor-roster-account-scope.test.ts": "providers/cursor", - "cursor-silent-redirect.test.ts": "providers/cursor", - "cursor-static-catalog.test.ts": "providers/cursor", - "cursor-stream-health.test.ts": "providers/cursor", - "cursor-structured-edit.test.ts": "providers/cursor", - "cursor-tool-arg-decoding.test.ts": "providers/cursor", - "cursor-tool-choice.test.ts": "providers/cursor", - "cursor-tool-continuation.test.ts": "providers/cursor", - "cursor-tool-definitions.test.ts": "providers/cursor", - "cursor-tool-finalize-race.test.ts": "providers/cursor", "cursor-freeform-args.test.ts": "providers/cursor", - "cursor-tool-result-image.test.ts": "providers/cursor", - "cursor-tool-result-invocation.test.ts": "providers/cursor", - "cursor-tool-suspended-checkpoint.test.ts": "providers/cursor", "cursor-tool-wording.test.ts": "providers/cursor", - "cursor-toolresult-normalize.test.ts": "providers/cursor", - "cursor-transport-retry.test.ts": "providers/cursor", - "cursor-ultra-mode.test.ts": "providers/cursor", - "cursor-umbrella-rows.test.ts": "providers/cursor", - "cursor-uncallable-quarantine.test.ts": "providers/cursor", - "cursor-vision-wire-harness.test.ts": "providers/cursor", - "custom-model-catalog-migration.test.ts": "codex-integration", - "custom-tool-compat.test.ts": "responses", - "cyber-policy-error-fidelity.test.ts": "providers", - "dashboard-sidecar-codex-write.test.ts": "gui", - "dashboard-uptime.test.ts": "gui", - "data-plane-admission-identity.test.ts": "server", - "debug-settings.test.ts": "server", - "debug.test.ts": "lib", - "decision-discovery.test.ts": "server", - "server-jev-model-decision-e2e.test.ts": "server", - "decision-routes.test.ts": "server", - "deepinfra-provider.test.ts": "providers", - "deepseek-inbound-wire.test.ts": "providers", - "deepseek-reasoning-replay-gaps.test.ts": "providers", - "deepseek-reasoning-replay.test.ts": "providers", - "deepseek-responses-item-id-repair.test.ts": "providers", - "management-desktop-compatibility-routes.test.ts": "server", "management-desktop-compatibility-runtime-routes.test.ts": "server", "server-desktop-compatibility-startup.test.ts": "server", "management-desktop-compatibility-settings.test.ts": "server", - "optional-desktop-upstream.test.ts": "lib", - "destination-policy-resolved.test.ts": "routing", - "devin-adapter-reset-wait.test.ts": "providers", - "devin-adapter.test.ts": "providers", - "devin-chat-wire-fixes.test.ts": "providers", - "devin-cli-authmode-migration.test.ts": "providers", - "devin-effort-ladder.test.ts": "providers", - "devin-family-resolution.test.ts": "providers", - "devin-hardening.test.ts": "providers", - "devin-image-passthrough.test.ts": "providers", - "devin-live-models.test.ts": "providers", - "devin-login.test.ts": "providers", - "devin-quota.test.ts": "providers", - "devin-output-budget.test.ts": "providers", - "devin-prompt-cache.test.ts": "providers", - "devin-trajectory.test.ts": "providers", - "devin-provider-merge-migration.test.ts": "providers", - "devin-stated-reset-hardening.test.ts": "providers", - "devin-stated-reset-retry.test.ts": "providers", - "devin-anthropic-signature-fallback.test.ts": "providers", - "devin-reasoning-continuation.test.ts": "providers", - "devin-stream-deadline.test.ts": "providers", - "digitalocean-scaleway-provider.test.ts": "providers", - "docs-429-failover-claims.test.ts": "ci-workflows", - "docs-bun-source-requirement.test.ts": "ci-workflows", - "docs-developer-role-policy.test.ts": "ci-workflows", - "docs-gui-screenshot-policy.test.ts": "ci-workflows", - "docs-link-targets.test.ts": "ci-workflows", - "docs-gjc-reasoning-export.test.ts": "ci-workflows", - "docs-provider-billing-claims.test.ts": "ci-workflows", - "docs-provider-discovery-limits.test.ts": "ci-workflows", - "docs-provider-preset-counts.test.ts": "ci-workflows", - "docs-readme-memory-inventory.test.ts": "ci-workflows", - "docs-readme-translation-parity.test.ts": "ci-workflows", - "docs-remote-hub-claims.test.ts": "ci-workflows", - "doctor-codex-envkey-readiness.test.ts": "service", - "doctor-oauth.test.ts": "service", - "doctor-provider-apikey.test.ts": "service", - "doctor-service-memory-contract.test.ts": "service", - "doctor.test.ts": "codex-integration", - "download-cap-default.test.ts": "images", - "download-connect-deadline-default.test.ts": "images", - "dsh-path-contract.test.ts": "ci-workflows", - "dsh-rc6-compat-script.test.ts": "ci-workflows", - "dsh-writer-lock.test.ts": "ci-workflows", - "effort-policy.test.ts": "codex-integration", - "empty-completion-core.test.ts": "responses", - "empty-completion-guard.test.ts": "responses", - "empty-completion-hardening.test.ts": "responses", - "empty-tool-output-annotation.test.ts": "adapters", - "ensure-desired-integrations-race.test.ts": "cli", - "error-fidelity.test.ts": "server", - "errors-adapter-failure.test.ts": "server", - "eventstream-decoder.test.ts": "responses", - "exa-web-search.test.ts": "providers", - "exec-tool-result-normalize.test.ts": "adapters", - "execution-budget-permits.test.ts": "lib", - "exhaustive-deps-suppression.test.ts": "ci-workflows", - "expand-user-path.test.ts": "config", - "failure-attribution.test.ts": "lib", - "failure-stage-model.test.ts": "lib", - "fast-row-ingress.test.ts": "providers", - "fast-row-listing.test.ts": "codex-integration", - "fast-row.test.ts": "codex-integration", - "fastwire-characterization-routing.test.ts": "routing", - "fastwire-characterization-wire.test.ts": "routing", - "fastwire-observability.test.ts": "routing", - "fastwire-response-authority.test.ts": "routing", - "fastwire-policy.test.ts": "routing", - "featherless-provider.test.ts": "providers", - "fetch-header-timeout.test.ts": "server", - "file-size-ratchet.test.ts": "ci-workflows", - "fixture-dir-uniqueness.test.ts": "ci-workflows", - "flash-route-image-modalities.test.ts": "providers", - "format-result.test.ts": "web-search", - "forward-admission-separation.test.ts": "providers", - "fresh-connection-optout.test.ts": "responses", - "fulfill-video.test.ts": "videos", - "gather-routed-models-single-flight.test.ts": "codex-integration", - "gcp-adc.test.ts": "adapters/google", - "gemini-37-flash-migration.test.ts": "adapters/google", - "gemini-4-argon-antigravity.test.ts": "adapters/google", - "antigravity-account-roster.test.ts": "adapters/google", - "gemini-inline.test.ts": "images", - "gemini-web-search.test.ts": "adapters/google", - "generic-session-affinity.test.ts": "oauth", - "server-generic-oauth-affinity.test.ts": "server", - "generic-oauth-failover.test.ts": "oauth", - "generic-oauth-refusal-composition.test.ts": "oauth", "github-copilot-auto.test.ts": "providers/github-copilot", "github-copilot-auto-runtime.test.ts": "providers/github-copilot", "github-copilot-catalog-hints.test.ts": "providers/github-copilot", - "github-copilot-account-origin.test.ts": "providers/github-copilot", - "github-copilot-context-tier.test.ts": "providers/github-copilot", - "github-copilot-oauth.test.ts": "providers/github-copilot", - "github-copilot-sse-rewrite.test.ts": "providers/github-copilot", - "github-copilot-stream-contract.test.ts": "providers/github-copilot", - "github-copilot-wire-defaults.test.ts": "providers/github-copilot", - "google-adapter.test.ts": "adapters/google", - "google-antigravity-oauth.test.ts": "adapters/google", - "google-antigravity-replay.test.ts": "adapters/google", - "google-antigravity-wire.test.ts": "adapters/google", - "google-buffered-stop-reason.test.ts": "adapters/google", - "google-claude-prefill-guard.test.ts": "adapters/google", - "google-empty-content.test.ts": "adapters/google", - "google-errors.test.ts": "adapters/google", - "google-hardening.test.ts": "adapters/google", - "google-models-listing.test.ts": "adapters/google", - "google-output-clamp.test.ts": "adapters/google", - "google-provider-metadata-roundtrip.test.ts": "adapters/google", - "google-signature-history-roundtrip.test.ts": "adapters/google", - "google-strict-tool-validated-mode.test.ts": "adapters/google", - "google-structured-output.test.ts": "adapters/google", - "google-tool-result-adjacency.test.ts": "adapters/google", - "google-tool-schema-contract.test.ts": "adapters/google", - "google-tool-schema.test.ts": "adapters/google", - "google-vertex-http.test.ts": "adapters/google", - "google-vertex-stream.test.ts": "adapters/google", - "google-vertex-thought-signature.test.ts": "adapters/google", - "google-wire-compiler.test.ts": "adapters/google", - "google-wire-shape.test.ts": "adapters/google", - "gpt6-native-rows.test.ts": "codex-integration", - "gpt61-sol-rows.test.ts": "codex-integration", - "grok-attribution.test.ts": "providers/xai", - "grok-config-inject.test.ts": "providers/xai", "grok-config-write-lock.test.ts": "providers/xai", - "grok-effort-inject.test.ts": "providers/xai", - "grok-lifecycle.test.ts": "providers/xai", - "grok-management-api.test.ts": "providers/xai", - "grok-models-effort-list.test.ts": "providers/xai", - "grok-orphan-adoption.test.ts": "providers/xai", - "grok-reset-coupon-cli.test.ts": "providers/xai", - "grok-reset-coupons.test.ts": "providers/xai", "grok-coupon-reconcile.test.ts": "providers/xai", "grok-coupon-claim.test.ts": "providers/xai", - "grok-selection.test.ts": "providers/xai", - "grok-session-identity.test.ts": "providers/xai", - "grok-status.test.ts": "providers/xai", - "grok-sync.test.ts": "providers/xai", - "grok-writer-boundary.test.ts": "providers/xai", - "gui-api-error.test.ts": "gui", - "html-lang-boot-script.test.ts": "gui", - "gui-codex-usage-score-parity.test.ts": "gui", - "gui-desktop-sidecar-script.test.ts": "gui", - "gui-management-session.test.ts": "gui", - "gui-pair-capability.test.ts": "gui", - "gui-pair-client.test.ts": "gui", - "gui-pair-http.test.ts": "gui", - "gui-static.test.ts": "gui", - "gui-tray-vibrancy-surface.test.ts": "gui", - "health-scoring.test.ts": "server", - "history-migration-guardian.test.ts": "codex-integration", - "history-ocx-compaction-recovery.test.ts": "codex-integration", - "history-paginated-openai-compat.test.ts": "codex-integration", - "history-paginated-transition-destinations.test.ts": "codex-integration", - "hub-gated-local-clients.test.ts": "cli", - "hub-invite.test.ts": "cli", "hub-disable.test.ts": "cli", - "hub-usage.test.ts": "server", - "hyperbolic-provider.test.ts": "providers", - "identity-neutralize.test.ts": "adapters", - "identity-subagent.test.ts": "adapters", - "init-backup-cleanup.test.ts": "service", - "init-eof.test.ts": "service", - "initial-model-selection.test.ts": "providers", - "initial-selection-write-fence.test.ts": "providers", - "injection-model-api.test.ts": "codex-integration", - "inline-think-boundaries.test.ts": "adapters/openai", - "input-admission.test.ts": "server", - "install-scripts.test.ts": "ci-workflows", - "installed-gate-drivers.test.ts": "ci-workflows", - "integrations-invariants.test.ts": "gui", - "interactive-confirm.test.ts": "cli", - "issue-452-empty-503.test.ts": "codex-integration", - "issue-702-expired-replay-state.test.ts": "codex-integration", - "issue-914-transport-attribution.test.ts": "codex-integration", - "key-attribution.test.ts": "usage", - "key-failover.test.ts": "adapters", - "key-login-live-update.test.ts": "oauth", - "key-login-preserves-model-costs.test.ts": "oauth", - "jev-decision.test.ts": "routing", "jev-decision-destination.test.ts": "routing", "jev-service-exchange.test.ts": "routing", - "jev-decision-provider-combo.test.ts": "routing", - "jev-typesafe-golden.test.ts": "routing", - "jev-model-backend.test.ts": "routing", - "jev-provider.test.ts": "providers", - "keyring-smoke.test.ts": "ci-workflows", - "kimi-oauth-identity.test.ts": "providers", - "kimi-responses-adjacency.test.ts": "providers", - "kiro-account-load.test.ts": "providers/kiro", - "kiro-account-quota.test.ts": "providers/kiro", - "kiro-account-state-disk.test.ts": "providers/kiro", - "kiro-account-state-imports.test.ts": "providers/kiro", - "kiro-adapter.test.ts": "providers/kiro", - "kiro-auth-context-continuation.test.ts": "providers/kiro", - "kiro-builder-id-profile.test.ts": "providers/kiro", - "kiro-calibration.test.ts": "providers/kiro", - "kiro-device-builder.test.ts": "providers/kiro", "kiro-device-social.test.ts": "providers/kiro", - "kiro-fallback-error-body.test.ts": "providers/kiro", - "kiro-images.test.ts": "providers/kiro", - "kiro-leased-responses.test.ts": "providers/kiro", - "kiro-model-catalog.test.ts": "providers/kiro", "kiro-model-preference.test.ts": "providers/kiro", - "kiro-oauth.test.ts": "providers/kiro", "oauth-kiro-refresh-attention.test.ts": "oauth", "kiro-org-user-identity.test.ts": "providers/kiro", - "kiro-pool-load-settings.test.ts": "providers/kiro", - "kiro-pool-rank.test.ts": "providers/kiro", - "kiro-reasoning-roundtrip.test.ts": "providers/kiro", - "kiro-refusal-failover.test.ts": "providers/kiro", - "kiro-refusal.test.ts": "providers/kiro", - "kiro-remote-image.test.ts": "providers/kiro", - "kiro-retry.test.ts": "providers/kiro", - "kiro-review-regressions.test.ts": "providers/kiro", - "kiro-metering-events.test.ts": "providers/kiro", - "kiro-metering-usage.test.ts": "providers/kiro", - "kiro-single-final.test.ts": "providers/kiro", - "kiro-stream.test.ts": "providers/kiro", - "kiro-transport-parity.test.ts": "providers/kiro", - "kiro-usage-quota.test.ts": "providers/kiro", - "kiro-usage-restart.test.ts": "providers/kiro", - "kiro-windows-cli-db-path.test.ts": "providers/kiro", - "kiro-windows-cli-executable-path.test.ts": "providers/kiro", - "kiro-wire-estimate.test.ts": "providers/kiro", - "lab-activation.test.ts": "lab", - "lab-automation-coderabbit-regressions.test.ts": "lab", - "lab-automation-final-coderabbit-regressions.test.ts": "lab", - "lab-automation-ingwannu-regressions.test.ts": "lab", - "lab-automation-management-http.test.ts": "lab", - "lab-automation-persisted-cap-regression.test.ts": "lab", - "lab-automation-review-regressions.test.ts": "lab", - "lab-automation.test.ts": "lab", - "lab-community-evidence.test.ts": "lab", - "lab-community-filename-contract.test.ts": "lab", - "lab-community-mutation-lock.test.ts": "lab", - "lab-community-publisher-continuity.test.ts": "lab", - "lab-conformance-harness.test.ts": "lab", - "lab-conformance-runner-failures.test.ts": "lab", - "lab-evidence-ledger.test.ts": "lab", - "lab-evidence-sanitization.test.ts": "lab", - "lab-fabric-outcome-validation.test.ts": "lab", - "lab-fabric-persistence-boundary.test.ts": "lab", - "lab-fabric-producer-deadline.test.ts": "lab", - "lab-fabric-task.test.ts": "lab", - "lab-installation-salt-cache.test.ts": "lab", - "lab-ledger-mutation-lock.test.ts": "lab", - "lab-live-pinned-timeouts.test.ts": "lab", - "lab-live-probe.test.ts": "lab", - "lab-live-receipt-integrity.test.ts": "lab", - "lab-live-review-regressions.test.ts": "lab", - "lab-live-sandbox.test.ts": "lab", - "lab-passive-production-evidence.test.ts": "lab", - "lab-passive-production-surfaces.test.ts": "lab", - "lab-paths-security.test.ts": "lab", - "lab-post-merge-hardening.test.ts": "lab", - "lab-post-merge-projection.test.ts": "lab", - "lab-private-file-consumer-recovery.test.ts": "lab", - "lab-private-file-durability.test.ts": "lab", - "lab-public-api-json.test.ts": "lab", - "lab-public-artifact-policy.test.ts": "lab", - "lab-public-coderabbit-regressions.test.ts": "lab", - "lab-public-core-contract.test.ts": "lab", - "lab-public-deep-review-regressions.test.ts": "lab", - "lab-public-evidence.test.ts": "lab", - "lab-public-export-transaction.test.ts": "lab", - "lab-public-file-safety.test.ts": "lab", - "lab-public-final-review-regressions.test.ts": "lab", - "lab-public-lifecycle-hardening.test.ts": "lab", - "lab-public-privacy-ipv6.test.ts": "lab", - "lab-public-provenance-recovery.test.ts": "lab", - "lab-public-review-fixes.test.ts": "lab", - "lab-public-route-registry.test.ts": "lab", - "lab-public-security-regressions.test.ts": "lab", - "lab-public-surfaces.test.ts": "lab", - "lab-public-wire-contract.test.ts": "lab", - "lab-read-filter-validation.test.ts": "lab", - "lab-read-surfaces.test.ts": "lab", - "launchd-repair.test.ts": "service", - "legacy-shell-compat.test.ts": "responses", - "live-call-bindings.test.ts": "server", "live-native-calls.test.ts": "server", - "live-service-manager-guard.test.ts": "service", - "linux-desktop-packaged-e2e.test.ts": "ci-workflows", - "local-aside-sync-capability.test.ts": "server", - "local-account-switch-capability.test.ts": "server", - "local-account-switch-ingress.test.ts": "server", - "local-destinations.test.ts": "lib", - "local-management-attestation.test.ts": "server", - "local-management-capability.test.ts": "server", - "local-management-direct-transport.test.ts": "server", - "local-provider-reload-client.test.ts": "server", - "local-token-detect.test.ts": "oauth", - "local-upstream.test.ts": "lib", - "logs-model-tier-confirmation.test.ts": "gui", - "logs-timezone.test.ts": "server", - "loop-reasoning-replay.test.ts": "images", - "loop.test.ts": "images", - "loopback-companion-client-targets.test.ts": "server", - "loopback-listener-admission.test.ts": "server", - "loopback-listener-integration.test.ts": "server", - "macos-serial-lanes.test.ts": "ci-workflows", - "main-account-hard-lock-auth.test.ts": "codex-integration", "main-account-hard-lock-fallback-routing.test.ts": "codex-integration", "main-account-hard-lock-usage-limit.test.ts": "codex-integration", - "main-account-hard-lock-default.test.ts": "codex-integration", - "main-account-hard-lock-policy.test.ts": "codex-integration", - "main-account-hard-lock-recovery.test.ts": "codex-integration", "main-account-credit-renewal.test.ts": "codex-integration", - "main-account-policy-binding-wait.test.ts": "codex-integration", - "main-device-reauth-api.test.ts": "codex-integration", - "main-device-reauth-ui.test.ts": "gui", - "main-device-reauth.test.ts": "codex-integration", - "main-quota-evidence-validation.test.ts": "codex-integration", - "main-account-hard-lock-retirement.test.ts": "codex-integration", - "main-quota-provenance.test.ts": "codex-integration", - "main-quota-window-observation.test.ts": "codex-integration", - "management-anthropic-reset-grants.test.ts": "server", - "management-api-logs-metrics.test.ts": "server", - "management-api-logs-timing-basis.test.ts": "server", - "management-client-config-route.test.ts": "server", - "management-inference-port.test.ts": "server", - "management-google-tool-schema-policy.test.ts": "server", - "management-integration-journal-delete.test.ts": "server", - "management-integration-routes.test.ts": "server", - "management-metrics-export.test.ts": "server", - "management-model-roster-gather-race.test.ts": "server", - "management-model-roster.test.ts": "server", - "model-export-new-model-policy.test.ts": "server", - "management-origin-tls.test.ts": "server", - "management-provider-compat-carry.test.ts": "server", - "management-provider-hide-raw-reasoning.test.ts": "server", "management-provider-responses-reasoning.test.ts": "server", - "management-provider-atomicity.test.ts": "server", - "management-provider-pinsless-validation.test.ts": "server", - "management-provider-proto-override.test.ts": "server", - "management-provider-reasoning-lists.test.ts": "server", - "management-provider-reset-replay.test.ts": "server", - "management-provider-synthetic-max.test.ts": "server", - "management-provider-upstream-websocket.test.ts": "server", - "management-provider-context-inference.test.ts": "server", "management-provider-validation.test.ts": "server", - "management-provider-verbosity.test.ts": "server", - "management-route-registry.test.ts": "server", - "protocol-routes.test.ts": "server", - "protocol-settings-route.test.ts": "server", - "protocol-provider-summary.test.ts": "server", - "management-workflow-budget-routes.test.ts": "server", - "managing-cli.test.ts": "service", - "memory-watchdog.test.ts": "server", - "meta-model-api-provider.test.ts": "providers", "meta-muse-wonder.test.ts": "providers", - "meta-muse-oauth.test.ts": "providers", - "meta-muse-keychain.test.ts": "providers", - "oauth-meta-muse-login-diagnostics.test.ts": "oauth", - "mimo-effort.test.ts": "providers", - "mimo-free-provider.test.ts": "providers", - "mimo-token-plan-provider.test.ts": "providers", - "mimo-v26-catalog.test.ts": "providers", - "minimax-clients.test.ts": "providers", - "minimax-quota.test.ts": "providers", - "minimax-reasoning-split.test.ts": "providers", - "model-cache-generation-tombstone.test.ts": "codex-integration", - "model-cache.test.ts": "codex-integration", - "model-costs-management-api.test.ts": "server", - "model-discovery-management-api.test.ts": "server", - "server-new-model-policy-arrival.test.ts": "server", - "model-display-names-management-api.test.ts": "codex-integration", - "model-metadata-sync.test.ts": "codex-integration", - "model-pinned-effort-config.test.ts": "config", - "model-pinned-effort.test.ts": "codex-integration", - "model-presets.test.ts": "providers", - "model-rename-migration.test.ts": "providers", - "model-roster-seed-repair.test.ts": "providers", - "model-selection-guidance.test.ts": "cli", "model-settings-management-api.test.ts": "server", - "model-visibility-management-api.test.ts": "codex-integration", - "models-feedback-callback.test.ts": "gui", - "models-free-filter.test.ts": "gui", - "models-page-groups.test.ts": "gui", - "models-workspace-tabs.test.ts": "gui", - "moonshot-endpoints.test.ts": "providers", - "moonshot-tool-schema.test.ts": "providers", - "multi-agent-compat.test.ts": "codex-integration", "code-mode-collab-surface.test.ts": "codex-integration", "deferred-collab-surface.test.ts": "codex-integration", - "multi-agent-keep-native-v1.test.ts": "codex-integration", - "multi-agent-origin.test.ts": "codex-integration", - "muse-passive-quota-cache.test.ts": "providers", - "muse-passive-quota-observation.test.ts": "providers", - "muse-spark-web-search-compat.test.ts": "providers", - "muse-subscription-usage.test.ts": "providers", - "muse-tool-name-alias.test.ts": "providers", - "namespace-tool-compat.test.ts": "responses", - "native-alias-maintainer-regressions.test.ts": "codex-integration", - "native-claude-code-toggle.test.ts": "codex-integration", - "native-claude-desktop-toggle.test.ts": "codex-integration", - "native-codex-toggle.test.ts": "codex-integration", - "native-grok-toggle.test.ts": "codex-integration", - "native-main-auth-temp.test.ts": "codex-integration", - "native-main-claim-cache.test.ts": "codex-integration", - "native-main-claim.test.ts": "codex-integration", - "native-main-owner-lifetime.test.ts": "codex-integration", - "native-model-toggle.test.ts": "codex-integration", - "native-profile-api.test.ts": "codex-integration", - "native-profile-crash-boundaries.test.ts": "codex-integration", - "native-profile-drain-server.test.ts": "codex-integration", - "native-profile-manager.test.ts": "codex-integration", - "native-profile-processes.test.ts": "codex-integration", - "native-profile-recovery.test.ts": "codex-integration", - "native-profile-route-security.test.ts": "codex-integration", - "native-profile-stage-lifecycle.test.ts": "codex-integration", - "native-profile-startup-release.test.ts": "codex-integration", - "native-profile-startup.test.ts": "codex-integration", - "native-profile-store.test.ts": "codex-integration", - "new-model-policy.test.ts": "providers", - "new-model-policy-runtime.test.ts": "providers", - "nous-oauth-live.test.ts": "providers", - "nous-oauth.test.ts": "providers", - "novita-provider.test.ts": "providers", - "nscale-vultr-provider.test.ts": "providers", - "nvidia-nim-hardening.test.ts": "providers", - "oauth-account-attribution.test.ts": "oauth", - "oauth-account-id-collision.test.ts": "oauth", - "oauth-account-quota-rank.test.ts": "oauth", - "oauth-accounts-api.test.ts": "oauth", - "oauth-anthropic-identity.test.ts": "oauth", - "oauth-callback-binds.test.ts": "oauth", - "oauth-callback-server.test.ts": "oauth", - "oauth-device-code-contract.test.ts": "oauth", - "oauth-first-add-hint.test.ts": "gui", - "oauth-health.test.ts": "oauth", - "oauth-log.test.ts": "oauth", - "oauth-login-cli-browser-launch.test.ts": "oauth", - "oauth-login-cli-errors.test.ts": "oauth", - "oauth-login-cli-live-update.test.ts": "oauth", - "oauth-login-open-browser.test.ts": "oauth", - "oauth-login-summary.test.ts": "oauth", - "oauth-code-login.test.ts": "oauth", - "oauth-manual-code.test.ts": "oauth", - "oauth-open-browser-choice.test.ts": "oauth", - "oauth-open-url-result.test.ts": "oauth", - "oauth-provider-reconcile.test.ts": "oauth", - "oauth-reconcile-operator-maps.test.ts": "oauth", - "oauth-public-surface.test.ts": "oauth", - "oauth-reauth-bind.test.ts": "oauth", - "oauth-refresh-generic-lock.test.ts": "oauth", - "oauth-refresh-stale-capacity.test.ts": "oauth", - "oauth-refresh-lock-multiprocess.test.ts": "oauth", - "oauth-refresh.test.ts": "oauth", - "oauth-status-privacy.test.ts": "oauth", - "oauth-store-multi.test.ts": "oauth", - "oauth-tos-warning.test.ts": "gui", - "oauth-upsert-preserves-api-key.test.ts": "oauth", - "ocx-launcher-runtime.test.ts": "cli", - "ocx-launcher-desktop-handoff.test.ts": "cli", "cli-path-diagnostics.test.ts": "cli", - "ocx-launcher-source.test.ts": "cli", - "ocx-run.test.ts": "cli", - "ollama-native-parser.test.ts": "providers/ollama", "ollama-native-reasoning-wire.test.ts": "providers/ollama", "ollama-native-structured-output.test.ts": "providers/ollama", "ollama-native-tool-continuations.test.ts": "providers/ollama", - "ollama-native-v4.test.ts": "providers/ollama", "ollama-native.test.ts": "providers/ollama", "ollama-show-enrichment-v7.test.ts": "providers/ollama", "ollama-show-enrichment.test.ts": "providers/ollama", - "ollama-show-ignore-abort.test.ts": "providers/ollama", - "opaque-blob-wrapped-rejection.test.ts": "responses", "openai-api-virtual-models.test.ts": "adapters/openai", "openai-chat-bounded-tool-names.test.ts": "adapters/openai", "openai-chat-dangling-toolcalls.test.ts": "adapters/openai", - "openai-chat-developer-position.test.ts": "adapters/openai", "openai-chat-eof.test.ts": "adapters/openai", "openai-chat-hardening.test.ts": "adapters/openai", "openai-empty-assistant-history.test.ts": "adapters/openai", "openai-chat-image-normalization.test.ts": "adapters/openai", - "openai-chat-inline-think-tags.test.ts": "adapters/openai", "openai-chat-invalid-tool-call-diagnostics.test.ts": "adapters/openai", "openai-chat-mistral-content.test.ts": "adapters/openai", "openai-chat-model-suffix.test.ts": "adapters/openai", "openai-chat-native-policy.test.ts": "adapters/openai", - "openai-chat-parallel-stream.test.ts": "adapters/openai", "openai-chat-path-override.test.ts": "adapters/openai", "openai-chat-qwen38-leading-system.test.ts": "adapters/openai", "openai-chat-reasoning-wire-policy.test.ts": "adapters/openai", - "openai-chat-sanitization-review-regressions.test.ts": "adapters/openai", "openai-chat-serialized-tool-call-content.test.ts": "adapters/openai", "openai-chat-serialized-tool-call-hold-bound.test.ts": "adapters/openai", "openai-chat-serialized-tool-call-think.test.ts": "adapters/openai", - "openai-chat-system-order.test.ts": "adapters/openai", "responses-chat-tool-call-content.test.ts": "responses", "openai-chat-tool-result-images.test.ts": "adapters/openai", "openai-chat-url.test.ts": "adapters/openai", - "openai-chat-video-part.test.ts": "adapters/openai", "openai-provider-option-e2e.test.ts": "adapters/openai", "openai-provider-option-migration.test.ts": "adapters/openai", "openai-provider-option-startup.test.ts": "adapters/openai", - "openai-provider-option-tooling.test.ts": "adapters/openai", - "openai-provider-option.test.ts": "adapters/openai", - "responses-forward-client-headers.test.ts": "responses", - "openai-responses-passthrough.test.ts": "responses", - "responses-native-item-extensions.test.ts": "responses", - "responses-native-item-extensions-compact.test.ts": "responses", - "responses-main-quota-observation.test.ts": "responses", "compaction-continuation-note.test.ts": "responses", "compaction-continuation-wire.test.ts": "responses", - "external-task-input-repair.test.ts": "responses", - "openai-responses-summary-none.test.ts": "responses", - "responses-forward-output-cap.test.ts": "responses", - "opencode-cli.test.ts": "providers", - "opencode-free-provider.test.ts": "providers", - "opencode-go-deepseek.test.ts": "providers", - "opencode-go-grok46-responses.test.ts": "providers", - "opencode-go-luna-wire.test.ts": "providers", - "opencode-go-muse-context.test.ts": "providers", - "opencode-go-muse-vision.test.ts": "providers", - "opencode-go-quota.test.ts": "providers", - "opencode-go-session-header.test.ts": "providers", - "opencode-management-transport.test.ts": "providers", - "opencode-zen-deepseek-reasoning.test.ts": "providers", - "opencode-zen-rate-limit.test.ts": "providers", - "opengateway-provider.test.ts": "providers", - "opengateway-key-validation.test.ts": "providers", - "openrouter-provider-routing.test.ts": "providers", - "openrouter-quota-reset-cooldown-4024.test.ts": "providers", - "opper-provider.test.ts": "providers", "modelflare-provider.test.ts": "providers", - "tokenlab-protocols.test.ts": "providers", - "tokenlab-provider.test.ts": "providers", - "optional-shutdown-hooks.test.ts": "lib", - "orca-import.test.ts": "codex-integration", - "orcarouter-provider.test.ts": "providers", - "outbound-body-guard.test.ts": "server", - "owned-service-home.test.ts": "server", - "package-tree-fenced-restart.test.ts": "ci-workflows", - "package-tree-integrity.test.ts": "ci-workflows", - "package-tree-restart-ownership.test.ts": "ci-workflows", - "package-tree-retarget.test.ts": "ci-workflows", - "parallel-tool-calls-optin.test.ts": "codex-integration", - "parser-content-audio.test.ts": "responses", - "passive-route-linker.test.ts": "server", - "passthrough-abort.test.ts": "responses", - "passthrough-grok-upstream-envelope-echo.test.ts": "responses", - "passthrough-headers.test.ts": "responses", - "passthrough-override.test.ts": "responses", - "phase100-native-parity.test.ts": "e2e-style", - "physical-send.test.ts": "adapters", - "pinned-http-content-coding.test.ts": "lib", - "pinned-http.test.ts": "lib", - "pinned-https-get.test.ts": "images", - "plaintext-v2-agent-messages-server.test.ts": "server", - "plaintext-v2-agent-messages.test.ts": "responses", - "plan-video.test.ts": "videos", - "plan.test.ts": "images", - "platform-dialog-guard.test.ts": "gui", - "policy-execution.test.ts": "routing", - "pool-kernel-generic-sweep.test.ts": "oauth", - "port-reclaim.test.ts": "server", - "ports.test.ts": "server", - "pr-readiness-reattest.test.ts": "ci-workflows", - "privacy-mask-account.test.ts": "lib", - "privacy-scan-asset-names.test.ts": "ci-workflows", - "privacy-scan-meta-key.test.ts": "ci-workflows", - "privacy-scan-ssh-endpoint.test.ts": "ci-workflows", - "probe-lease-dispatch-wiring.test.ts": "routing", - "probe-lease.test.ts": "routing", - "process-control-graceful.test.ts": "lib", - "process-control.test.ts": "lib", - "process-state.test.ts": "service", - "project-config-warnings.test.ts": "codex-integration", - "provider-account-quota-persistence.test.ts": "providers", - "provider-account-quota-routes.test.ts": "server", - "provider-account-quota.test.ts": "providers", - "provider-api-keys.test.ts": "providers", - "provider-capacity.test.ts": "providers", - "provider-config-batch-management.test.ts": "providers", - "provider-config-validation.test.ts": "providers", - "provider-connection-test.test.ts": "providers", - "provider-cost-overlay-config.test.ts": "providers", - "provider-discovery-log-suppression.test.ts": "providers", - "provider-egress-fetch.test.ts": "responses", - "provider-egress-management-validation.test.ts": "server", - "provider-egress-outbound.test.ts": "providers", - "provider-egress.test.ts": "lib", - "provider-id-rewrite.test.ts": "providers", - "provider-key-store.test.ts": "providers", - "provider-live-models.test.ts": "providers", - "provider-model-aliases.test.ts": "providers", - "provider-model-discovery-contract.test.ts": "providers", - "provider-outbound-private-network.test.ts": "providers", - "provider-outbound.test.ts": "providers", - "provider-runtime-fetch.test.ts": "providers", - "provider-tls-profile.test.ts": "providers", - "provider-payload.test.ts": "gui", - "provider-quota-label-sanitize.test.ts": "providers", - "provider-quota-observed-marker.test.ts": "providers", - "provider-quota-ollama-cloud.test.ts": "providers", - "provider-quota.test.ts": "providers", - "provider-registry-parity.test.ts": "providers", "haiku-5-5-catalog.test.ts": "providers", - "provider-send-path-import.test.ts": "server", - "provider-static-model-discovery.test.ts": "providers", - "provider-subscription-cli.test.ts": "gui", - "provider-workspace-auth.test.ts": "gui", - "provider-workspace-data.test.ts": "gui", - "provider-workspace-rail.test.ts": "gui", - "provider-workspace-state.test.ts": "gui", - "proxy-env-macos.test.ts": "server", - "proxy-env.test.ts": "server", - "proxy-liveness-package-tree-fence.test.ts": "server", - "proxy-liveness.test.ts": "server", - "qoder-adapter.test.ts": "providers", "qoder-live-models.test.ts": "providers", "qoder-mcp-server.test.ts": "providers", - "qoder-scaffold-guard.test.ts": "providers", - "quota-401-recovery-runtime.test.ts": "usage", - "quota-401-recovery.test.ts": "usage", - "quota-bars-rows.test.ts": "gui", - "quota-reset-account-key.test.ts": "usage", - "quota-reset-core-boundary.test.ts": "usage", - "quota-reset-detector.test.ts": "usage", - "quota-reset-notify-config.test.ts": "usage", - "quota-reset-notify.test.ts": "usage", - "quota-reset-observation.test.ts": "usage", - "quota-reset-seen-store.test.ts": "usage", - "quota-scoring.test.ts": "usage", - "qwen-cloud-endpoints.test.ts": "gui", - "qwen38-preserve-reasoning.test.ts": "providers", - "rate-limit-reset-credits.test.ts": "gui", - "rate-limit-retry.test.ts": "providers", - "reasoning-effort-summary-default.test.ts": "responses", - "reasoning-effort.test.ts": "codex-integration", - "reasoning-envelope.test.ts": "responses", - "reasoning-metadata.test.ts": "codex-integration", - "reasoning-replay-identity.test.ts": "adapters", - "reasoning-replay-robustness.test.ts": "adapters", - "reasoning-replay-scope-source.test.ts": "lib", - "redact.test.ts": "lib", - "relay-eager.test.ts": "server", - "release-desktop-scripts.test.ts": "ci-workflows", - "release-helper.test.ts": "ci-workflows", - "release-notes.test.ts": "ci-workflows", - "release-outcome-report.test.ts": "ci-workflows", - "release-pipeline-contract.test.ts": "ci-workflows", - "release-preflight.test.ts": "ci-workflows", - "release-resume-identity.test.ts": "ci-workflows", - "release-version-line.test.ts": "ci-workflows", - "release-version-sources.test.ts": "ci-workflows", - "remove-tree-helper.test.ts": "lib", - "fixture-teardown-helper.test.ts": "ci-workflows", - "replay-refusal-parity.test.ts": "server", - "repo-hygiene.test.ts": "ci-workflows", - "request-decompress.test.ts": "usage", - "request-evidence.test.ts": "usage", - "request-history-index.test.ts": "usage", - "request-log-attempt-identity.test.ts": "usage", - "request-log-conversation.test.ts": "usage", - "request-log-estimate-cap.test.ts": "usage", - "request-log-jev.test.ts": "usage", - "request-log-nonstream.test.ts": "usage", - "request-log-protocol-trace.test.ts": "usage", - "request-log-served-model.test.ts": "usage", "request-log-model-filter.test.ts": "usage", - "request-log-generation-window.test.ts": "usage", - "request-log.test.ts": "usage", "upstream-failure-diagnostics.test.ts": "usage", - "request-outcome-agreement.test.ts": "usage", - "request-pacing.test.ts": "usage", - "reserve-auth-context.test.ts": "codex-integration", - "reserve-availability.test.ts": "codex-integration", - "reserve-catalog-lifecycle.test.ts": "codex-integration", - "reserve-catalog.test.ts": "codex-integration", - "reserve-claude-policy.test.ts": "server", - "reserve-dispatch-ws.test.ts": "responses", - "reserve-dispatch.test.ts": "codex-integration", - "reserve-helper-boundary.test.ts": "codex-integration", - "reserve-ingress.test.ts": "server", - "reserve-passive-revocation.test.ts": "codex-integration", - "reserve-quota-scope.test.ts": "codex-integration", - "resolved-model-policy-consumers.test.ts": "routing", - "resolved-model-policy.test.ts": "providers", - "response-log-inspection.test.ts": "server", - "response-model-identity.test.ts": "server", - "responses-4546-incident-regression.test.ts": "responses", - "responses-account-change-scrub.test.ts": "responses", - "responses-account-label.test.ts": "responses", - "responses-anthropic-fast-downgrade.test.ts": "responses", - "responses-azure-opaque-blob-recovery.test.ts": "responses", - "responses-bare-echo-helper-fence.test.ts": "responses", - "responses-canonical-only-top-level-fields.test.ts": "responses", - "responses-chatgpt-web-replay-metadata.test.ts": "responses", - "responses-code-mode-goal-helpers.test.ts": "responses", - "responses-code-mode-patch-compile.test.ts": "responses", - "responses-code-mode-shell-compile.test.ts": "responses", - "responses-compact-handoff-admission.test.ts": "responses", - "responses-compaction-override.test.ts": "responses", - "responses-compaction-policy-identity.test.ts": "responses", - "responses-compaction-http-isolation.test.ts": "responses", "responses-compaction-routing.test.ts": "responses", - "responses-compaction.test.ts": "responses", - "responses-console-go-upload-retry.test.ts": "responses", - "responses-context-overflow.test.ts": "responses", - "responses-continuation-boundaries.test.ts": "responses", - "responses-core-modules.test.ts": "responses", - "responses-custom-tool-guidance.test.ts": "responses", - "responses-custom-tool-historical-replay.test.ts": "responses", - "responses-custom-tool-repair-dispatch.test.ts": "responses", - "responses-custom-tool-repair.test.ts": "responses", - "responses-custom-tool-stream-consistency.test.ts": "responses", - "responses-default-namespace-emit-normalize.test.ts": "responses", - "responses-fetch-helpers-boundary.test.ts": "responses", - "responses-field-backfill.test.ts": "responses", - "responses-forward-dangling-call.test.ts": "responses", - "responses-forward-incomplete-quota.test.ts": "responses", - "responses-forward-posit-continuation.test.ts": "responses", - "responses-forward-prompt-envelope.test.ts": "responses", - "responses-freeform-wrapper-keys.test.ts": "responses", - "responses-function-tool-repair.test.ts": "responses", - "responses-hosted-tool-declaration.test.ts": "responses", - "responses-hosted-tool-min-spread.test.ts": "responses", - "responses-hide-raw-reasoning.test.ts": "responses", - "responses-image-gen-repair.test.ts": "responses", - "responses-inbound-store-default.test.ts": "responses", - "responses-item-id-repair.test.ts": "responses", - "responses-json-events.test.ts": "responses", - "responses-legacy-dotted-tool-name-repair.test.ts": "responses", - "responses-muse-tool-name-alias.test.ts": "responses", - "responses-muse-tool-choice.test.ts": "responses", - "responses-native-main-refresh.test.ts": "responses", - "responses-opaque-blob-recovery.test.ts": "responses", - "responses-parser-agent-message.test.ts": "responses", - "responses-parser-malformed-content.test.ts": "responses", - "responses-parser.test.ts": "responses", - "responses-passthrough-transient-policy.test.ts": "responses", - "responses-pool-401-refresh.test.ts": "responses", - "responses-pool-refresh-attribution.test.ts": "responses", - "responses-preview-main-read-fence.test.ts": "responses", - "responses-reasoning-effort-downgrade.test.ts": "responses", - "responses-reasoning-summary-passthrough.test.ts": "responses", - "responses-reset-replay.test.ts": "responses", - "responses-translated-reset.test.ts": "responses", - "responses-routed-web-search-fields.test.ts": "responses", - "responses-self-named-namespace-scrub.test.ts": "responses", - "responses-combo-exhausted-error.test.ts": "responses", - "responses-combo-run-turn-classified-failure.test.ts": "responses", - "responses-send-budget-counts.test.ts": "responses", - "responses-send-budget-errors.test.ts": "responses", - "responses-memory-models.test.ts": "responses", - "responses-shadow-intercept.test.ts": "responses", - "responses-show-thinking-summary.test.ts": "responses", - "responses-snapshot-repair-server.test.ts": "responses", - "responses-snapshot-repair.test.ts": "responses", - "responses-sparse-terminal-tool-scope.test.ts": "responses", - "responses-spend-ledger-wiring.test.ts": "responses", - "responses-spend-contract-c.test.ts": "responses", - "responses-spend-anchor.test.ts": "responses", - "responses-spend-capacity-guard.test.ts": "responses", - "responses-spill-acl-recovery.test.ts": "responses", - "responses-spill-admission-headroom.test.ts": "responses", - "responses-spill-inspection.test.ts": "responses", - "responses-spill-orphan-sweep.test.ts": "responses", - "responses-spill-shutdown-clock.test.ts": "responses", - "responses-state-flush-race.test.ts": "responses", - "responses-state-snapshot-select.test.ts": "responses", - "responses-state-snapshot-stubs.test.ts": "responses", "responses-state-store-false.test.ts": "responses", - "responses-state-write-amplification.test.ts": "responses", - "responses-state.test.ts": "responses", - "responses-stateless-dangling-call-repair.test.ts": "responses", - "responses-stream-tool-events.test.ts": "responses", - "responses-terminal-repair.test.ts": "responses", - "responses-tool-conformance.test.ts": "responses", - "responses-tool-groups.test.ts": "responses", - "responses-tool-search-repair.test.ts": "responses", - "responses-undeclared-tool-guard.test.ts": "responses", - "responses-usage-passthrough.test.ts": "responses", - "responses-xai-request-compat.test.ts": "responses", - "restore-completes-shared-teardown.test.ts": "cli", - "retry-after-429.test.ts": "server", - "route-decision-trace.test.ts": "server", - "route-explainability.test.ts": "cli", - "routed-agent-messages.test.ts": "adapters", - "router-blocked-cross-provider.test.ts": "routing", - "router-combo-failover-classification.test.ts": "routing", - "router-discarded-baseurl-warning.test.ts": "routing", - "router-template-baseurl.test.ts": "routing", - "router.test.ts": "routing", - "routing-analytics.test.ts": "routing", - "routing-capability-catalog.test.ts": "routing", - "routing-capability-model-matching.test.ts": "routing", - "routing-compatibility-auth-identity.test.ts": "routing", - "routing-compatibility-boundaries.test.ts": "routing", - "routing-compatibility-model-matching.test.ts": "routing", - "routing-compatibility.test.ts": "routing", - "routing-identity-domains.test.ts": "routing", - "routing-intelligence-ui.test.ts": "gui", - "routing-policy-dispatch-scope.test.ts": "routing", - "routing-policy-fallback.test.ts": "routing", - "routing-policy-pool-quota.test.ts": "routing", - "routing-policy-surface-parity.test.ts": "routing", - "routing-profile-editor-data.test.ts": "gui", - "routing-profile-management-editor.test.ts": "routing", - "routing-profile.test.ts": "routing", - "run-turn-queue.test.ts": "adapters", - "sambanova-nebius-provider.test.ts": "providers", - "selected-models.test.ts": "codex-integration", - "self-launch-argv.test.ts": "lib", - "server-403-permission-e2e.test.ts": "server", - "server-agent-task-recovery-replay.test.ts": "server", - "server-antigravity-verify-replay-scope.test.ts": "server", - "server-auth-localhost-bind.test.ts": "server", - "server-auth-scoped-quota.test.ts": "server", - "server-auth.test.ts": "server", - "server-background-lifecycle.test.ts": "server", - "server-clickjacking-headers.test.ts": "server", - "server-combo-cooldown-fallback.test.ts": "server", - "server-combo-failover-e2e.test.ts": "server", - "server-combo-held-response.test.ts": "server", - "server-combo-reasoning-replay-eligibility.test.ts": "server", - "server-combo-zero-output-failover.test.ts": "server", - "server-google-antigravity-oauth-401-replay.test.ts": "server", - "server-antigravity-web-search-validation.test.ts": "server", "server-google-antigravity-oauth-429-budget.test.ts": "server", - "server-gui-bundle-freshness.test.ts": "server", - "server-images-bodyless-content-length.test.ts": "server", - "server-images-pool-admission.test.ts": "server", - "server-images.test.ts": "server", - "server-key-failover-e2e.test.ts": "server", - "server-jev-combo-e2e.test.ts": "server", "combo-requested-effort.test.ts": "server", - "server-kiro-completion-e2e.test.ts": "server", - "server-kiro-device-login.test.ts": "server", "server-kiro-oauth-401-replay.test.ts": "server", - "server-kiro-refusal-e2e.test.ts": "server", "server-live-existing-call.test.ts": "server", - "server-live-frame-log.test.ts": "server", - "server-live-realtime-fixtures.test.ts": "server", - "server-live.test.ts": "server", - "server-loopback-host-gate.test.ts": "server", - "server-management-auth.test.ts": "server", "server-management-log-admission.test.ts": "server", - "server-opencode-go-goal-streaming.test.ts": "server", - "server-rate-limit-retry-e2e.test.ts": "server", - "server-request-body-size.test.ts": "server", - "server-search.test.ts": "server", - "server-startup-reconcile-resilience.test.ts": "server", - "server-stop-config-hardening.test.ts": "server", - "server-xai-chat-reasoning-streaming.test.ts": "server", - "server-xai-header-parity.test.ts": "server", - "server-xai-oauth-401-replay.test.ts": "server", - "server-xai-responses-streaming.test.ts": "server", - "service-auth-qualified-localhost.test.ts": "service", - "service-child-ownership.test.ts": "service", - "service-handled-signal-exit.test.ts": "service", "service-health-sentinel-linux.test.ts": "service", "service-health-sentinel-launch.test.ts": "service", "service-health-sentinel-policy.test.ts": "service", "service-health-sentinel-process.test.ts": "service", "service-health-sentinel-runner.test.ts": "service", - "service-claim.test.ts": "service", - "service-ownership-compatibility.test.ts": "service", - "service-ownership-handover.test.ts": "service", - "service-ownership-state.test.ts": "service", "ownership-mutation-lease-diagnostics.test.ts": "service", - "service-probe-docker.test.ts": "service", - "service-secrets.test.ts": "service", - "service-sqlite-home.test.ts": "service", - "service-stop-verification.test.ts": "service", - "service-tier-capability.test.ts": "service", - "service-wsl-home-ownership.test.ts": "service", - "service.test.ts": "service", - "service-multishell-path.test.ts": "service", - "serving-runtimes.test.ts": "config", - "session-affinity.test.ts": "server", - "session-lane-recall-harness.test.ts": "server", - "settings-desktop-switch-apply.test.ts": "config", - "settings-fast-rows.test.ts": "config", - "settings-main-account-hard-lock.test.ts": "config", - "settings-memory-models.test.ts": "config", - "settings-oauth-open-browser.test.ts": "config", - "settings-startup-health-seam.test.ts": "config", - "settings-stream-mode.test.ts": "config", - "setup-hooks.test.ts": "ci-workflows", - "shadow-intercept-target-lifecycle.test.ts": "responses", - "shutdown-drain.test.ts": "service", - "shutdown-launcher.test.ts": "service", - "sidebar-routes.test.ts": "server", - "sidebar-star-state.test.ts": "server", - "sidecar-abort.test.ts": "vision", - "sidecar-auth.test.ts": "vision", - "sidecar-candidates.test.ts": "vision", - "sidecar-settings-vision-controls.test.ts": "vision", - "sidecar-settings-vision-filter.test.ts": "vision", - "sidecar-settings-web-search-gate.test.ts": "vision", - "sidecar-settings-web-search-off.test.ts": "vision", - "sidecar-settings-web-search-stream.test.ts": "vision", - "sidecar-tracker.test.ts": "vision", - "skill-ocx.test.ts": "ci-workflows", - "slug-codec.test.ts": "codex-integration", - "socks5-fetch.test.ts": "lib", "socks5-tls-lifecycle.test.ts": "lib", - "socks5-upload-lifecycle.test.ts": "lib", - "spend-ceiling-enforcement.test.ts": "lib", - "spend-instrumentation-log.test.ts": "server", - "spend-ledger-file-journal.test.ts": "lib", - "spend-ledger-lifecycle.test.ts": "server", - "spend-ledger-owner-startup.test.ts": "server", - "spend-ledger-owner.test.ts": "lib", - "spend-pool-continuity.test.ts": "lib", - "spend-contract-c.test.ts": "lib", - "spend-corruption-compat.test.ts": "lib", - "spend-unbound-expiry.test.ts": "lib", - "spend-seed-overflow.test.ts": "lib", - "spend-zero-config-compat.test.ts": "lib", - "spend-experimental-history.test.ts": "lib", - "spend-reservation-ledger.test.ts": "lib", - "sponsor-presets.test.ts": "providers", - "sse-carriage-return.test.ts": "responses", - "sse-client-frame-bounds.test.ts": "responses", - "sse-decoder.test.ts": "responses", - "sse-failed-tail.test.ts": "responses", - "sse-inspector-bounds.test.ts": "responses", - "sse-null-data-frame.test.ts": "responses", - "sse-payload-rewrite.test.ts": "responses", - "sse-rewrite-line-endings.test.ts": "responses", - "chat-sse-framing-guard.test.ts": "responses", - "sse-unspaced-data-fields.test.ts": "responses", - "stale-state-purge.test.ts": "service", - "stall-subprocess-exit.test.ts": "lib", - "stall-timeout.test.ts": "lib", - "standalone-build-script.test.ts": "gui", - "standalone-service.test.ts": "service", - "standalone.test.ts": "lib", - "star-deferral.test.ts": "cli", - "start-args.test.ts": "cli", - "start-ownership-publication.test.ts": "cli", - "startup-action-control-elevation.test.ts": "server", - "startup-action-control.test.ts": "server", "login-shell-path.test.ts": "server", - "startup-health-ui.test.ts": "gui", - "startup-prompt.test.ts": "server", - "state-store-sweeper.test.ts": "oauth", - "stepfun-provider.test.ts": "providers", - "stop-deferred-teardown.test.ts": "service", - "storage-cleanup.test.ts": "storage", - "storage-mutation-race.test.ts": "storage", - "storage-policy-config-race.test.ts": "storage", - "storage-policy-job-responsive.test.ts": "storage", - "storage-policy.test.ts": "storage", - "storage-restore-job-errors.test.ts": "storage", - "storage-restore-job-responsive.test.ts": "storage", - "storage-scanner.test.ts": "storage", - "storage-worker-lifecycle.test.ts": "storage", - "storage-worker-os-join-settle.test.ts": "storage", - "storage-worker-teardown-isolate.test.ts": "storage", - "stream-aborted-marker.test.ts": "server", - "strict-semver.test.ts": "lib", - "structure-ssot.test.ts": "ci-workflows", - "subagent-context-staleness.test.ts": "routing", - "subagent-defaults.test.ts": "routing", - "subagent-fallback-handle-responses.test.ts": "routing", - "subagent-fallback-preview-sites.test.ts": "routing", - "subagent-model-fallback-api.test.ts": "routing", - "subagent-model-fallback.test.ts": "routing", - "codex-agent-role-models.test.ts": "routing", - "codex-role-sizing.test.ts": "routing", - "codex-role-auto-assign.test.ts": "routing", - "codex-agent-role-routes.test.ts": "server", - "codex-role-auto-assign-routes.test.ts": "server", - "local-chat-completion.test.ts": "lib", - "injection-model-suggest-routes.test.ts": "codex-integration", - "subagent-roster-retention.test.ts": "routing", - "synced-state-location.test.ts": "lib", - "synthetic-tool.test.ts": "images", - "system-env.test.ts": "server", - "system-restart-client-package-tree.test.ts": "cli", - "system-restart-client.test.ts": "cli", - "system-restart-contract-security.test.ts": "lib", - "system-restart-admission.test.ts": "server", - "system-restart.test.ts": "server", - "system-routes.test.ts": "server", - "systemd-install-cleanup-hardening.test.ts": "service", - "tencent-siliconflow-providers.test.ts": "gui", - "terminal-continuation-owner-rotation.test.ts": "adapters", - "terminal-guard-server.test.ts": "server", - "terminal-guard.test.ts": "server", - "test-home-guard.test.ts": "ci-workflows", - "test-runner.test.ts": "ci-workflows", "test-runner-bun.test.ts": "ci-workflows", "test-runner-spawnsync-finalizer.test.ts": "ci-workflows", "test-sandbox-cleanup.test.ts": "ci-workflows", "test-temp-quarantine.test.ts": "ci-workflows", - "thought-signature-credential-scope.test.ts": "responses", - "token-estimate.test.ts": "lib", - "token-guardian.test.ts": "codex-integration", - "tool-argument-integers.test.ts": "adapters", - "tool-catalog-nudge.test.ts": "adapters", - "tool-choice-performance.test.ts": "adapters", - "transient-budget-scope-source.test.ts": "lib", - "translator-budget.test.ts": "adapters", "translator-budget-lifetime.test.ts": "adapters", "catalog-async-lifetime.test.ts": "codex-integration", - "transport-null-body.test.ts": "lib", - "tray-proxy-deadline.test.ts": "windows", - "tray-proxy.test.ts": "windows", - "types-barrel-identity.test.ts": "config", - "ultrafast-tier-honesty.test.ts": "codex-integration", "configured-ultrafast-picker.test.ts": "codex-integration", "native-ultrafast-picker.test.ts": "codex-integration", - "umans-provider.test.ts": "providers", - "uninstall.test.ts": "cli", - "update-async-routes.test.ts": "server", - "update-badge.test.ts": "update", "update-bun-ownership-lease.test.ts": "update", - "update-desktop-badge.test.ts": "update", "update-desktop-owner.test.ts": "update", "update-supervised-recovery.test.ts": "update", - "update-job.test.ts": "update", "update-job-supervised-restart.test.ts": "update", "update-standalone.test.ts": "update", "update-worker-launch.test.ts": "update", - "update-notify.test.ts": "update", "update-npm-cache-preflight.test.ts": "update", - "update-npm-invocation.test.ts": "update", "update-mise-launcher-target.test.ts": "update", - "update-mise.test.ts": "update", "update-mise-node-runtime.test.ts": "update", - "update-pnpm.test.ts": "update", - "update-refresh.test.ts": "update", - "update-restart-lease.test.ts": "update", - "update-stop-classification.test.ts": "update", - "update-stop-first.test.ts": "update", - "update-transactional-leftovers.test.ts": "update", - "update-transactional.test.ts": "update", - "update-tray-handoff.test.ts": "update", - "update-tree-ownership.test.ts": "update", - "upstream-connect-error.test.ts": "server", - "upstream-error-message-fallback.test.ts": "lib", - "upstream-http-error.test.ts": "adapters", - "upstream-http-version.test.ts": "server", - "upstream-reachability.test.ts": "codex-integration", - "upstream-retry.test.ts": "lib", - "upstream-retry-zero-output.test.ts": "lib", - "upstream-transient-retry.test.ts": "providers", - "url-normalization.test.ts": "config", - "usage-aggregate-cache.test.ts": "usage", - "usage-anthropic-fast-pricing.test.ts": "usage", - "usage-cursor-fast-pricing.test.ts": "usage", - "usage-attempt-delivery.test.ts": "usage", - "usage-cost.test.ts": "usage", "usage-haiku-5-5-pricing.test.ts": "usage", - "usage-debug.test.ts": "usage", - "usage-failure-fingerprint.test.ts": "usage", - "usage-failure-persistence.test.ts": "usage", - "usage-failure-projection.test.ts": "usage", - "usage-ledger-retention.test.ts": "usage", - "usage-ledger-scanner.test.ts": "usage", - "usage-log-ws-stage.test.ts": "usage", - "usage-log.test.ts": "usage", - "usage-provider-label.test.ts": "usage", - "usage-shape-extraction.test.ts": "usage", - "usage-spend-cache-provenance.test.ts": "usage", - "usage-summary.test.ts": "usage", - "usage-throughput.test.ts": "usage", - "usage-surfaces.test.ts": "usage", - "usage-time-range.test.ts": "usage", - "usage-timeline.test.ts": "usage", - "user-cost-overlay-coderabbit-regressions.test.ts": "usage", - "user-cost-overlay-live-reconcile.test.ts": "usage", - "user-cost-overlay-provider-delete.test.ts": "usage", - "v1-hub-state.test.ts": "server", - "v2-agent-message-failfast.test.ts": "server", - "vercel-gateway-provider-routing.test.ts": "providers", - "version-line.test.ts": "ci-workflows", - "vertex-catalog.test.ts": "adapters/google", - "vision-anthropic.test.ts": "vision", - "vision-backend-union.test.ts": "vision", - "vision-cache.test.ts": "vision", - "vision-classification-seed-repair.test.ts": "providers", - "vision-custom-row-precedence.test.ts": "vision", - "vision-eligibility.test.ts": "vision", - "vision-fail-closed.test.ts": "vision", - "vision-reasoning-contract.test.ts": "vision", - "vision-routed.test.ts": "vision", - "vision-sidecar-e2e.test.ts": "vision", - "vision-sidecar-timeout-bounds.test.ts": "gui", - "vision-text-only-predicate.test.ts": "vision", - "volcengine-ark-assistant-content.test.ts": "providers", - "volcengine-providers.test.ts": "gui", - "warmup-registration.test.ts": "ci-workflows", - "warmup.test.ts": "codex-integration", - "web-search-anthropic.test.ts": "web-search", - "devin-web-search.test.ts": "web-search", - "web-search-recovery-kind.test.ts": "web-search", - "chat-legacy-functions-combo.test.ts": "responses", - "web-search-backend-union.test.ts": "web-search", - "web-search-bridge-replay.test.ts": "web-search", - "web-search-candidates.test.ts": "web-search", - "web-search-parse.test.ts": "web-search", - "web-search-passthrough-bridge.test.ts": "web-search", - "web-search-progress-stream.test.ts": "web-search", - "web-search-retry-heartbeat.test.ts": "web-search", - "web-search-sidecar-429.test.ts": "web-search", - "web-search-sources.test.ts": "web-search", - "web-search-timeout-contract.test.ts": "web-search", "web-search-pacing-deadline.test.ts": "web-search", - "web-search-timeout-plan.test.ts": "web-search", - "web-search.test.ts": "web-search", - "win-exec.test.ts": "windows", - "win-paths.test.ts": "windows", - "windows-acl-start-cost.test.ts": "windows", - "windows-atomic-replace.test.ts": "windows", - "windows-deploy-close-regressions.test.ts": "windows", - "windows-elevation-spawn.test.ts": "windows", - "windows-elevation.test.ts": "windows", - "windows-guarded-manager.test.ts": "windows", - "windows-popup-fix.test.ts": "windows", - "windows-process-priority.test.ts": "windows", - "windows-scheduler-install-verification.test.ts": "windows", - "windows-secret-acl.test.ts": "windows", "windows-secret-acl-removal-flight.test.ts": "windows", - "windows-config-read-acl-memo.test.ts": "windows", - "windows-service-mutation-lock.test.ts": "windows", - "windows-service-wrappers.test.ts": "windows", - "windows-text-decoding.test.ts": "windows", - "windows-tray-restart-hardening.test.ts": "windows", - "windows-tray-run-limit.test.ts": "windows", - "windows-tray.test.ts": "windows", - "windows-user-principal-nonascii.test.ts": "windows", - "windows-user-principal.test.ts": "windows", - "winsw-stop-hardening.test.ts": "windows", - "winsw.test.ts": "service", - "workflow-budget.test.ts": "lib", - "ws-ambiguous-resend.test.ts": "responses", "ws-pre-output-refusal.test.ts": "responses", "responses-pool-overload-failover.test.ts": "responses", "compact-transient-alternate.test.ts": "responses", - "ws-endpoint.test.ts": "responses", - "ws-failure-stage.test.ts": "responses", - "ws-native-injection.test.ts": "responses", - "ws-native-result-continuations.test.ts": "responses", - "ws-native-steering.test.ts": "responses", - "ws-steering-completion.test.ts": "responses", - "ws-steering-smoke.test.ts": "responses", - "ws-steering-stability.test.ts": "responses", - "ws-upstream-reuse.test.ts": "responses", "codex-ws-pool-contention.test.ts": "responses", - "ws-upstream-socks5.test.ts": "responses", - "ws-upstream.test.ts": "responses", - "xai-client.test.ts": "images", - "xai-empty-catalog-tool-choice.test.ts": "providers/xai", - "xai-no-stop.test.ts": "providers/xai", - "xai-oauth-retry.test.ts": "providers/xai", - "xai-refresh-lock.test.ts": "providers/xai", - "xai-responses-adjacency.test.ts": "providers/xai", - "xai-tool-schema.test.ts": "providers/xai", - "xai-transport.test.ts": "providers/xai", - "xai-video-client.test.ts": "videos", - "xai-web-search-compat.test.ts": "providers/xai", - "xai-web-search.test.ts": "providers/xai", - "yaml-fragment-source.test.ts": "config", - "z-fulfill.test.ts": "images", - "z-handler-activation.test.ts": "images", - "zai-reasoning-replay.test.ts": "providers", - "zcode-client.test.ts": "providers", - "zhipu-bigmodel-provider.test.ts": "providers", - "zhipu-bigmodel-responses-quota.test.ts": "providers", - "zz-ci-api-usage-isolation.test.ts": "ci-workflows", - "zz-ci-storage-policy-isolation.test.ts": "ci-workflows", - "zz-pr-coderabbit-readiness-revalidation.test.ts": "ci-workflows", - "injection-link-websocket.test.ts": "codex-integration", - "cli-link.test.ts": "cli", "cli-link-enrollment.test.ts": "cli", - "link-management-routes.test.ts": "server", "link-enrollment.test.ts": "server", - "web-search-run-turn-loop.test.ts": "web-search", - "responses-run-turn-web-search.test.ts": "responses", - "responses-claude-preflight-lease.test.ts": "responses", - "server-combo-cooldown-recording.test.ts": "server", - "injection-routing-drift.test.ts": "codex-integration", "injection-routing-healer.test.ts": "codex-integration", - "injection-routing-heal-apply.test.ts": "codex-integration", "cli-start-routing-heal-wiring.test.ts": "cli", - "cli-status-codex-routing-drift.test.ts": "cli", "advisor-settings.test.ts": "advisor", "advisor-context.test.ts": "advisor", "advisor-state.test.ts": "advisor", "advisor-guard.test.ts": "advisor", "advisor-consult.test.ts": "advisor", "advisor-plan.test.ts": "advisor", "advisor-responses-wiring.test.ts": "advisor", "advisor-routes.test.ts": "server", "advisor-internal-authority.test.ts": "advisor", "advisor-core-boundary.test.ts": "advisor", "advisor-continuation-limit.test.ts": "advisor", "advisor-authority-transport.test.ts": "advisor" - } -} + "cli-usage-compare.test.ts": "cli", diff --git a/skills/ocx/references/01_management_surface.md b/skills/ocx/references/01_management_surface.md index 63329af9470..21cf6f40bf3 100644 --- a/skills/ocx/references/01_management_surface.md +++ b/skills/ocx/references/01_management_surface.md @@ -30,7 +30,7 @@ These answer in the CLI head and never reach the proxy, so they work with nothin | [accounts](01_surface_accounts.md) | 42 | | [agents-routing](01_surface_agents-routing.md) | 51 | | [integrations](01_surface_integrations.md) | 41 | -| [observe-system](01_surface_observe-system.md) | 92 | +| [observe-system](01_surface_observe-system.md) | 93 | | [access-remote](01_surface_access-remote.md) | 32 | | [lab](01_surface_lab.md) | 21 | @@ -947,6 +947,10 @@ Original invocation order. These headings preserve links to the previous single- [Read-oriented task](01_surface_observe-system.md#ocx-observe-usage) +### `ocx usage compare` + +[Read-oriented task](01_surface_observe-system.md#ocx-usage-compare) + ### `ocx observe storage` [Read-oriented task](01_surface_observe-system.md#ocx-observe-storage) @@ -1401,6 +1405,6 @@ Original invocation order. These headings preserve links to the previous single- ## Counts -- declared capabilities: 338 +- declared capabilities: 339 - of those, state-changing: 207 - head-resolved invocations: 2 diff --git a/skills/ocx/references/01_surface_observe-system.md b/skills/ocx/references/01_surface_observe-system.md index f35bcf379aa..33d088d8375 100644 --- a/skills/ocx/references/01_surface_observe-system.md +++ b/skills/ocx/references/01_surface_observe-system.md @@ -8,7 +8,7 @@ Use these declarations to choose a task, then check its flags and authority before execution. Non-mutating probes may still contact providers, consume quota or refresh caches. -Declared capabilities: 92. +Declared capabilities: 93. ### `ocx companion` @@ -62,6 +62,7 @@ JSON mode: `payload`. - Alias of observe usage. Connected clients read only their enrolled-key Hub report through /v1/usage; caller --api-key-id is refused before key read/transport and never grants management authority. - Nonclient --api-key-id uses /api/usage and requires matching filter acknowledgment. An unknown acknowledged key is empty/matched:false, not404. Custom-window acknowledgment remains required. - --search filters only returned model rows after scope acknowledgment. Blank search selects the top100 model rows; modelView reports match/return counts without recomputing totals. +- Nested compare reads the named range and the previous equal window; --range all is refused. ### `ocx logs` @@ -655,6 +656,32 @@ JSON mode: `payload`. - Nonclient --api-key-id uses /api/usage and requires matching filter acknowledgment. An unknown acknowledged key is empty/matched:false, not404. Custom-window acknowledgment remains required. - --search filters only returned model rows after scope acknowledgment. Blank search selects the top100 model rows by default; modelView reports match/return counts without recomputing totals. +### `ocx usage compare` + +Usage: `ocx usage compare [--range ] [--surface ] [--provider ] [--model ] [--api-key-id ] [--json]` + +Compare a usage range with the previous equal window. + +State-changing: no. + +| Method | Route | +|---|---| +| GET | `/api/usage` | + +| Flag | Value | Meaning | +|---|---|---| +| `--range` | string | today \| 1d \| 7d \| 30d; default 30d. all is refused. | +| `--surface` | string | all \| codex \| claude \| grok; default all. | +| `--provider` | string | Filter provider. | +| `--model` | string | Filter model. | +| `--api-key-id` | string | Exact nonblank management key scope; connected clients refuse this. | +| `--json` | boolean | Emit current, previous, delta and change percentages. | + +JSON mode: `envelope`. + +- Two sequential GET /api/usage reads: the named range at now, then the same range shifted back one equal window. Custom since/until must be acknowledged on both. --range all is refused. +- Also accepted after observe usage. Default range is 30d. This is not an atomic snapshot. + ### `ocx observe storage` Usage: `ocx observe storage [--limit ] [--json]` diff --git a/skills/ocx/references/02_json_shapes.md b/skills/ocx/references/02_json_shapes.md index 0a36442ff36..a8cd0a9063c 100644 --- a/skills/ocx/references/02_json_shapes.md +++ b/skills/ocx/references/02_json_shapes.md @@ -86,6 +86,13 @@ Two honesty markers to respect: - Under `--provider` or `--model`, per-account rows are **withheld** rather than filtered, because account totals cannot be honestly re-partitioned by provider. +## `ocx usage compare --json` + +CLI envelope `schemaVersion: 1` with `range`, `days`, `filter`, then `current` and `previous` +(`since`, `until`, `summary`, `usageIncomplete`), plus `delta`, `change` (percent, or `null` when +the previous value is zero and the current value is not), and `incomplete`. Totals are request, +token and estimated-cost fields only; use `ocx usage --json` for provider/model/account rows. + ## `ocx account list --json` `accounts[]` with `id`, `email`, `plan`, `paused`, `selected`, `priority`, and `needsReauth`. Quota diff --git a/skills/ocx/references/03_recipes.md b/skills/ocx/references/03_recipes.md index 30ce49ec610..73659b8c67c 100644 --- a/skills/ocx/references/03_recipes.md +++ b/skills/ocx/references/03_recipes.md @@ -88,8 +88,12 @@ actually served it, not only the one requested. ```bash ocx usage --range 7d --json +ocx usage compare --range 7d --json ``` +`ocx usage compare` reads the named range and the previous equal window. `--range all` is refused. +`--json` carries `delta` and `change` (percent). The two reads are sequential. + Read `accounts[]`. Two things to respect: - A row with `ambiguous: true` (label `legacy-ambiguous`) aggregates several accounts from before diff --git a/src/cli/capabilities-base.ts b/src/cli/capabilities-base.ts index e80b99f6335..29343b3e718 100644 --- a/src/cli/capabilities-base.ts +++ b/src/cli/capabilities-base.ts @@ -326,7 +326,7 @@ export const CAPABILITIES: readonly Capability[] = [ flags: [{"name":"--range","value":"string","summary":"today | 1d | 7d | 30d | all; default 30d."},{"name":"--surface","value":"string","summary":"all | codex | claude | grok; default all."},{"name":"--since","value":"string","summary":"Inclusive epoch milliseconds or ISO datetime with timezone; requires --until."},{"name":"--until","value":"string","summary":"Inclusive end; requires --since. Custom bounds override --range."},{"name":"--provider","value":"string","summary":"Filter provider."},{"name":"--model","value":"string","summary":"Filter model."},{"name":"--json","value":"boolean","summary":"Emit the result as JSON."},{"name":"--api-key-id","value":"string","summary":"Exact nonblank management key scope; connected clients refuse this before reading their enrolled key."},{"name":"--search","value":"string","summary":"Model-row substring view over model/provider/resolvedModel; top100 by tokens. Whole-report totals stay unchanged."}], mutates: false, json: "payload", - details: ["Alias of observe usage. Connected clients read only their enrolled-key Hub report through /v1/usage; caller --api-key-id is refused before key read/transport and never grants management authority.","Nonclient --api-key-id uses /api/usage and requires matching filter acknowledgment. An unknown acknowledged key is empty/matched:false, not404. Custom-window acknowledgment remains required.","--search filters only returned model rows after scope acknowledgment. Blank search selects the top100 model rows; modelView reports match/return counts without recomputing totals."], + details: ["Alias of observe usage. Connected clients read only their enrolled-key Hub report through /v1/usage; caller --api-key-id is refused before key read/transport and never grants management authority.","Nonclient --api-key-id uses /api/usage and requires matching filter acknowledgment. An unknown acknowledged key is empty/matched:false, not404. Custom-window acknowledgment remains required.","--search filters only returned model rows after scope acknowledgment. Blank search selects the top100 model rows; modelView reports match/return counts without recomputing totals.","Nested compare reads the named range and the previous equal window; --range all is refused."], usage: "ocx usage [--range ] [--surface ] [--since ] [--until ] [--provider ] [--model ] [--api-key-id ] [--search ] [--json]", }, { diff --git a/src/cli/capabilities-observe-system.ts b/src/cli/capabilities-observe-system.ts index dd42e66f50d..85e7f40812f 100644 --- a/src/cli/capabilities-observe-system.ts +++ b/src/cli/capabilities-observe-system.ts @@ -50,6 +50,25 @@ export const OBSERVE_SYSTEM_CAPABILITIES: readonly Capability[] = [ json: "payload", details: ["Also available as ocx usage. Connected clients read only their enrolled-key Hub report through /v1/usage; caller --api-key-id is refused before key read/transport and never grants management authority.","Nonclient --api-key-id uses /api/usage and requires matching filter acknowledgment. An unknown acknowledged key is empty/matched:false, not404. Custom-window acknowledgment remains required.","--search filters only returned model rows after scope acknowledgment. Blank search selects the top100 model rows by default; modelView reports match/return counts without recomputing totals."], }, + { + command: ["usage", "compare"], + summary: "Compare a usage range with the previous equal window.", + usage: "ocx usage compare [--range ] [--surface ] [--provider ] [--model ] [--api-key-id ] [--json]", + routes: [{"method": "GET", "path": "/api/usage"}], + flags: [ + {"name": "--range", "value": "string", "summary": "today | 1d | 7d | 30d; default 30d. all is refused."}, + {"name": "--surface", "value": "string", "summary": "all | codex | claude | grok; default all."}, + {"name": "--provider", "value": "string", "summary": "Filter provider."}, + {"name": "--model", "value": "string", "summary": "Filter model."}, + {"name": "--api-key-id", "value": "string", "summary": "Exact nonblank management key scope; connected clients refuse this."}, + {"name": "--json", "value": "boolean", "summary": "Emit current, previous, delta and change percentages."}, + ], + mutates: false, json: "envelope", + details: [ + "Two sequential GET /api/usage reads: the named range at now, then the same range shifted back one equal window. Custom since/until must be acknowledged on both. --range all is refused.", + "Also accepted after observe usage. Default range is 30d. This is not an atomic snapshot.", + ], + }, { command: ["observe", "storage"], summary: "Read storage diagnostics.", usage: "ocx observe storage [--limit ] [--json]", diff --git a/src/cli/observe-stream.ts b/src/cli/observe-stream.ts index bd32fbeee98..21890cba0ea 100644 --- a/src/cli/observe-stream.ts +++ b/src/cli/observe-stream.ts @@ -14,6 +14,8 @@ export interface ObserveStreamDeps extends RuntimeApiDeps { /** Reduced timings for isolated tests only; never command-line options. */ pollIntervalMs?: number; requestTimeoutMs?: number; + /** Frozen clock for usage-compare tests; never a command-line option. */ + now?: () => number; } export class ObservationError extends Error {} diff --git a/src/cli/observe.ts b/src/cli/observe.ts index 2b7a4f53651..b45ea423310 100644 --- a/src/cli/observe.ts +++ b/src/cli/observe.ts @@ -17,6 +17,7 @@ import { handleLogFilterCommand } from "./log-view-filter"; import { followInjection } from "./injection-follow"; import type { ObserveStreamDeps } from "./observe-stream"; import { formatUsageReport } from "./usage-report"; +import { handleUsageCompareCommand } from "./usage-compare"; import { selectUsageModelView, takeUsageSearchOption } from "./usage-model-search"; import { USAGE_RANGES, USAGE_SURFACES, type UsageSummary, type UsageFilterEcho } from "../usage/summary"; import { parseUsageTimeWindow, type UsageTimeWindow } from "../usage/time-range"; @@ -35,306 +36,5 @@ const USAGE = `Usage: ocx logs index-status ocx observe usage [--range ] [--surface ] [--since ] [--until ] - [--provider ] [--model ] [--api-key-id ] [--search ] [--top <1-1000>] [--json] - ocx observe storage [codex-logs [status|protect|unprotect|repair|compact] [--mode ]] [--json] - ocx observe memory [--json] - ocx observe debug [--json] - ocx observe claude-inbound [--limit ] [--json] - ocx observe injection [--limit ] [--follow [--jsonl]] [--json]`; - -type LogEntry = Record & { id?: string | number; timestamp?: string; provider?: string; model?: string; status?: number }; - -function query(params: Record): string { - const search = new URLSearchParams(); - for (const [key, value] of Object.entries(params)) if (value !== undefined) search.set(key, String(value)); - const encoded = search.toString(); - return encoded ? `?${encoded}` : ""; -} - -function logRows(data: unknown): LogEntry[] { - if (Array.isArray(data)) return data as LogEntry[]; - if (data && typeof data === "object") { - const record = data as Record; - for (const key of ["logs", "entries", "requests"]) if (Array.isArray(record[key])) return record[key] as LogEntry[]; - } - return []; -} - -/** Render one human log row with an exact, control-free request ID suitable for history lookup. */ -function formatLog(row: LogEntry): string { - const time = String(row.timestamp ?? row.createdAt ?? ""); - const route = [row.provider, row.model].filter(Boolean).join("/"); - const status = row.status ?? row.statusCode ?? "?"; - const duration = row.durationMs !== undefined ? `${String(row.durationMs)}ms` : ""; - // The conversation id is shown because a conversation FILTER whose output never names the - // conversation is hard to trust: an empty result and a wrong-id result look identical (#2704). - const conversation = typeof row.conversationId === "string" && row.conversationId.length > 0 - ? `conv=${row.conversationId}` - : ""; - // The account label is printed for the same reason, and for one more: it is the answer to - // "which of my accounts served this?" (#4057). It is only ever the stable non-PII label the - // proxy already persists (`main`, `p`, `o`) — never an email, a key, or an - // upstream account id. Rows from a single-account provider carry no label and print none. - const account = typeof row.accountLogLabel === "string" && row.accountLogLabel.length > 0 - ? `acct=${row.accountLogLabel}` - : ""; - const requestId = typeof row.requestId === "string" && row.requestId.length > 0 - && !/[\x00-\x1f\x7f-\x9f\u2028\u2029]/.test(row.requestId) - ? `id=${row.requestId}` : ""; - return [time, String(status), route, duration, account, conversation, requestId].filter(Boolean).join(" "); -} - -/** Read or follow request logs while preserving raw JSON and JSONL output. */ -async function logs(argv: string[], deps: ObserveStreamDeps): Promise { - const args = [...argv]; - const wantsJson = takeFlag(args, "--json"); - const wantsEvents = takeFlag(args, "--events"); - const wantsJsonl = takeFlag(args, "--jsonl") || wantsEvents; - const follow = takeFlag(args, "--follow") || takeFlag(args, "-f"); - const provider = takeOption(args, "--provider"); - const model = takeOption(args, "--model"); - const status = takeOption(args, "--status"); - // Both spellings, because the server accepts both (`request-log.ts:1032`) and an operator - // should not have to remember which one this surface wanted. - const conversationId = takeOption(args, "--conversation") ?? takeOption(args, "--conversationId"); - // Server-side, so `--limit` caps the rows that MATCHED rather than the rows scanned; a - // client-side filter after a 200-row cap would silently hide older matches. - const account = takeOption(args, "--account"); - const limit = takeIntegerOption(args, "--limit", { min: 1 }) ?? 200; - rejectArgs(args, USAGE); - if (wantsJson && wantsJsonl) throw new CliUsageError("--json and --jsonl cannot be combined", USAGE); - if (follow && wantsJson) { - throw new CliUsageError("--follow cannot be combined with --json; use --jsonl for streaming JSONL", USAGE); - } - if (wantsEvents && !follow) throw new CliUsageError("--events requires --follow", USAGE); - const params = { provider, model, status, conversationId, account, limit }; - if (follow) { - if (limit > 2000) throw new CliUsageError("--limit must be between 1 and 2000 for follow", USAGE); - return followLogs({ query: new URLSearchParams(query(params)), limit, jsonl: wantsJsonl, events: wantsEvents, formatRow: formatLog }, deps); - } - const data = await runtimeRequest(`/api/logs${query(params)}`, {}, deps); - const rows = logRows(data); - if (!wantsJson && !wantsJsonl && rows.length === 0 && [provider, model, status, conversationId, account].some(Boolean)) { - console.log("No log entry matched the filters."); - } - if (wantsJson) printData(data, true); - else for (const row of rows) { - if (wantsJsonl) console.log(JSON.stringify(row)); - else console.log(formatLog(row)); - } - return 0; -} - -async function explain(argv: string[], deps: RuntimeApiDeps): Promise { - const args = [...argv]; - const requestId = args.shift(); - const wantsJson = takeFlag(args, "--json"); - if (!requestId) throw new CliUsageError("request id is required", USAGE); - rejectArgs(args, USAGE); - const encoded = encodeURIComponent(requestId); - const result = await runtimeRequest(`/api/request-history/${encoded}/route-decision`, {}, deps); - // One entry per line: printData escapes control characters per entry, so a single - // pretty-printed string would print its line breaks as literal `\x0a`. - printData(result, wantsJson, wantsJson ? undefined : JSON.stringify(result, null, 2).split("\n")); -} - -async function rebuildIndex(argv: string[], deps: RuntimeApiDeps): Promise { - const args = [...argv]; - const wantsJson = takeFlag(args, "--json"); - rejectArgs(args, USAGE); - const { rebuildRequestHistoryIndex } = await import("../routing/history/indexer"); - const meta = await rebuildRequestHistoryIndex(); - if (wantsJson) printData(meta, true); - else { - console.log(`Request-history index rebuilt (${meta.dbPath})`); - console.log(` schema version: ${meta.schemaVersion}`); - console.log(` indexed rows: ${meta.indexedRows}`); - console.log(` source size: ${meta.sourceSize} bytes`); - console.log(` last error: ${meta.lastError ?? "none"}`); - } -} - -async function indexStatus(argv: string[], deps: RuntimeApiDeps): Promise { - const args = [...argv]; - const wantsJson = takeFlag(args, "--json"); - rejectArgs(args, USAGE); - const { requestHistoryIndexStatus } = await import("../routing/history/indexer"); - const meta = await requestHistoryIndexStatus(); - if (wantsJson) printData(meta, true); - else { - console.log(`Request-history index (${meta.dbPath})`); - console.log(` schema version: ${meta.schemaVersion}`); - console.log(` indexed rows: ${meta.indexedRows}`); - console.log(` source size: ${meta.sourceSize} bytes`); - console.log(` indexed offset: ${meta.indexedOffset} bytes`); - console.log(` last error: ${meta.lastError ?? "none"}`); - } -} - -async function usage(argv: string[], deps: RuntimeApiDeps): Promise { - const args = [...argv]; - const search = takeUsageSearchOption(args); - const top = takeIntegerOption(args, "--top", { min: 1, max: 1000 }); - const wantsJson = takeFlag(args, "--json"); - const range = takeOption(args, "--range") ?? "30d"; - const surface = takeOption(args, "--surface") ?? "all"; - const provider = takeOption(args, "--provider"); - const model = takeOption(args, "--model"); - const since = takeOption(args, "--since"); - const until = takeOption(args, "--until"); - const rawKeyId = takeOptionWithSyntax(args, "--api-key-id")?.value; - const apiKeyId = rawKeyId?.trim(); - if (apiKeyId !== undefined && !apiKeyId) throw new CliUsageError("--api-key-id must not be blank", USAGE); - let window: UsageTimeWindow | undefined; - try { - window = parseUsageTimeWindow(since, until); - } catch (error) { - throw new CliUsageError(error instanceof Error ? error.message : "invalid usage time window", USAGE); - } - // `1d` is accepted here as well as server-side so the CLI does not reject an - // alias the API would have understood. - const ranges = [...USAGE_RANGES, "1d"]; - if (!ranges.includes(range)) throw new CliUsageError(`--range must be one of ${USAGE_RANGES.join(", ")} (1d aliases today)`, USAGE); - if (!USAGE_SURFACES.includes(surface as (typeof USAGE_SURFACES)[number])) { - throw new CliUsageError(`--surface must be one of ${USAGE_SURFACES.join(", ")}`, USAGE); - } - rejectArgs(args.map(redactSecretString), USAGE); - const suffix = query({ range, surface, provider, model, apiKeyId, since: window?.since, until: window?.until }); - const connection = readClientConnectionState(); - let result: (UsageSummary & { filter?: UsageFilterEcho }) | HubUsageReport; - if (connection.kind === "invalid" || connection.kind === "mismatched") { - throw new Error(`Client usage unavailable: ${connection.reason}`); - } - if (connection.kind === "connected") { - if (apiKeyId !== undefined) throw new CliUsageError("--api-key-id is unavailable on connected clients; run on the hub for a selected key, or omit it for this client's usage", USAGE); - const token = readServiceApiTokenState(); - if (token.kind !== "present" || token.fingerprint !== connection.value.tokenFingerprint) { - throw new Error("Client usage unavailable: the enrolled data key is missing or changed; repair the client connection"); - } - // A Remote Link Child sends this read through the connection-bound link relay (#6957). - const link = connection.value.transport === "link" && connection.value.link; - const peerFetch = deps.fetchImpl - ?? (link ? (await import("../client/link-home")).linkBoundFetch(connection.value, token.token) : undefined); - result = await fetchHubUsage(connection.value.serverUrl, token.token, new URLSearchParams(suffix), { - fetchImpl: peerFetch, timeoutMs: 60_000, ...(link ? { peer: "Home" as const } : {}), - }); - const current = readClientConnectionState(); - const currentToken = readServiceApiTokenState(); - if (current.kind !== "connected" || !sameClientConnectionOwner(current.value, connection.value) - || current.value.tokenFingerprint !== token.fingerprint - || currentToken.kind !== "present" || currentToken.fingerprint !== token.fingerprint) { - throw new Error("Client connection changed while reading usage; retry for the current connection"); - } - } else { - if (apiKeyId === undefined) result = await runtimeRequest(`/api/usage${suffix}`, {}, deps); - else { - try { - result = await runtimeRequest(`/api/usage${suffix}`, { redirect: "error", credentials: "omit" }, deps); - } catch (error) { - if (error instanceof RuntimeApiError && error.code === "proxy_not_running") throw error; - throw new Error("Key-scoped usage could not be read. Check runtime access and retry."); - } - if (result?.filter?.apiKeyId !== apiKeyId) { - throw new Error("The server did not confirm the requested API key scope. Upgrade and restart the proxy, then retry."); - } - } - } - // Older daemons ignore custom bounds and return successful preset reports. - if (window && (result?.customWindow !== true || result.since !== window.since || result.until !== window.until)) { - throw new Error("The server did not confirm the requested custom usage window. Upgrade and restart the proxy, then retry."); - } - // Built only when it will be printed: JavaScript evaluates arguments before - // the call, so passing formatUsageReport(...) inline would run the human - // renderer during --json and let its assumptions affect a path that is meant - // to bypass it entirely. - const view = search === undefined ? undefined : selectUsageModelView(result, search, wantsJson ? undefined : top); - const displayed = view ?? result; - if (wantsJson) printData(displayed, true); - else printData(displayed, false, formatUsageReport(displayed as Parameters[0], { modelView: view?.modelView, modelRowLimit: top })); -} - -async function simple(path: string, argv: string[], deps: RuntimeApiDeps): Promise { - const args = [...argv]; - const wantsJson = takeFlag(args, "--json"); - const limit = takeIntegerOption(args, "--limit", { min: 1 }); - rejectArgs(args, USAGE); - const result = await runtimeRequest(`${path}${query({ limit })}`, {}, deps); - printData(result, wantsJson, summaryLines(result)); -} - -async function storage(argv: string[], deps: RuntimeApiDeps): Promise { - if (argv[0] !== "codex-logs") { - await simple("/api/storage", argv, deps); - return; - } - - const args = argv.slice(1); - const action = args[0] && !args[0].startsWith("-") ? args.shift()! : "status"; - const wantsJson = takeFlag(args, "--json"); - const mode = takeOption(args, "--mode"); - rejectArgs(args, USAGE); - - let result: unknown; - if (action === "status") { - if (mode !== undefined) throw new CliUsageError("--mode is only valid with codex-logs protect", USAGE); - result = await runtimeRequest("/api/storage/codex-logs", {}, deps); - } else if (action === "protect") { - const requestedMode = mode ?? "compat"; - if (requestedMode !== "compat" && requestedMode !== "quiet") { - throw new CliUsageError("--mode must be compat or quiet", USAGE); - } - result = await runtimeRequest("/api/storage/codex-logs/protect", { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ mode: requestedMode }), - }, deps); - } else if (action === "unprotect" || action === "repair" || action === "compact") { - if (mode !== undefined) throw new CliUsageError("--mode is only valid with codex-logs protect", USAGE); - result = await runtimeRequest(`/api/storage/codex-logs/${action}`, { method: "POST" }, deps); - } else { - throw new CliUsageError(`unknown codex-logs action ${action}`, USAGE); - } - - printData(result, wantsJson, summaryLines(result)); -} - -async function injection(argv: string[], deps: ObserveStreamDeps): Promise { - const args = [...argv]; - const follow = takeFlag(args, "--follow"); - const jsonl = takeFlag(args, "--jsonl"); - if (!follow) { - if (jsonl) throw new CliUsageError("--jsonl requires --follow for injection logs", USAGE); - await simple("/api/debug/injection-logs", args, deps); - return 0; - } - if (takeFlag(args, "--json")) throw new CliUsageError("--follow cannot be combined with --json; use --jsonl", USAGE); - const limit = takeIntegerOption(args, "--limit", { min: 1 }) ?? 500; - if (limit > 2000) throw new CliUsageError("--limit must be between 1 and 2000 for follow", USAGE); - rejectArgs(args, USAGE); - return followInjection(limit, jsonl, deps); -} - -export async function handleObserveCommand(argv: string[], deps: ObserveStreamDeps = {}): Promise { - let streamExit = 0; - const exit = await runCliAction(async () => { - const [sub = "logs", ...rest] = argv; - if (sub === "logs") { - const action = rest[0]; - if (action === "filter") streamExit = await handleLogFilterCommand(rest.slice(1), deps, formatLog); - else if (action === "explain") await explain(rest.slice(1), deps); - else if (action === "rebuild-index") await rebuildIndex(rest.slice(1), deps); - else if (action === "index-status") await indexStatus(rest.slice(1), deps); - else streamExit = await logs(rest, deps); - } - else if (sub === "usage") await usage(rest, deps); - else if (sub === "storage") await storage(rest, deps); - else if (sub === "memory") await simple("/api/system/memory", rest, deps); - else if (sub === "debug") await simple("/api/debug", rest, deps); - else if (sub === "claude-inbound") await simple("/api/claude/inbound-debug", rest, deps); - else if (sub === "injection") streamExit = await injection(rest, deps); - else throw new CliUsageError(`unknown observe command ${sub}`, USAGE); - }); - return exit || streamExit; -} - -export const OBSERVE_USAGE = USAGE; + ocx usage compare [--range ] [--surface ] + [--provider ] [--model ] [--api-key-id ] [--json] diff --git a/src/cli/registry.ts b/src/cli/registry.ts index 17adee29ee6..75f8111b323 100644 --- a/src/cli/registry.ts +++ b/src/cli/registry.ts @@ -449,328 +449,3 @@ export const CLI_COMMANDS: CliCommandEntry[] = [ { name: "logs", usage: "ocx logs [filters] [--follow] [--json|--jsonl|--events]", summary: "Read or follow request logs." }, { name: "usage", - usage: "ocx usage [--range ] [--surface ] [--provider ] [--model ] [--api-key-id ] [--search ] [--top <1-1000>] [--json]", - summary: "Report token usage and estimated cost (alias of ocx observe usage).", - }, - { - name: "storage", - usage: "ocx storage ...", - summary: "Storage report, archived-session cleanup, trash restore, and the cleanup policy.", - details: [ - "A bare `ocx storage` prints the report, as it did when this was an alias of `observe storage`.", - "`cleanup` previews by default and only deletes under --yes; `trash restore` and `policy run` also require --yes.", - ], - }, - { name: "memory", usage: "ocx memory [--json]", summary: "Alias of ocx observe memory." }, - { - name: "access", - usage: "ocx access ...", - summary: "Manage OpenCodex admission API keys and inspect external endpoints.", - details: [ - "Key rotation start uses POST /api/keys/rotate and returns the replacement secret once.", - "Commit uses POST /api/keys/rotate/commit; abort uses DELETE /api/keys/rotate with the returned rotation id.", - "key rename changes a masked key's name without clearing its scopes.", - "test --api-key-stdin uses one supplied data key; it never substitutes management or enrolled credentials.", - "audio transcribe/live-check use explicit piped key input and may use provider quota; authorize the operation first.", - ], - }, - { name: "api-key", usage: "ocx api-key ...", summary: "Alias of ocx access key." }, - { - name: "api", - usage: "ocx api ...", - summary: "Inspect protocol paths, preview a request path, and read or change the protocol policy.", - details: [ - "protocols [--provider ] Contract version, API surfaces, protocol settings and feature vocabulary.", - "explain --model --inbound [--feature ]... Preview the request path; sends nothing upstream.", - "policy Read the protocol policy; with --messages, --unrepresentable or --rollout = it changes config.", - "Every rollout switch defaults off except antigravityDirect. `ocx api policy` writes only when a setting flag is given.", - ], - }, - { - name: "export", - usage: "ocx export --client [--json] [--out ] [--force]", - summary: "Print a client config (OpenCode, Pi, OMP, Hermes, OpenClaw, Kimi Code, gjc, DeepSeek Harness, MiniMax Code, ZCode, Command Code, Prime Agent, Aside, Raycast, omo, Cline, Kilo, Factory Droid, Qoder) wired to the running proxy.", - details: [ - "--json prints the generated document as JSON on stdout; use --out for the client's native format.", - "--out writes the native config there and refuses to replace an existing file without --force.", - "Cline exports a two-document bundle: settings for providers.json and catalog for sibling models.json. Use integration client enable --client cline for a journaled write.", - "Droid exports documented customModels for settings.json; use integration client enable --client droid for a journaled write.", - "The config never contains a real key; it carries a documented env reference or a non-secret loopback placeholder.", - "The destination path is printed for merging by hand — ocx never writes your real client config.", - ], - }, - { - name: "grok", - usage: "ocx grok ...", - summary: "Manage and apply the Grok Build model fence.", - }, - { - name: "integration", - usage: "ocx integration ...", - summary: "Manage supported client integrations, and the native client toggles.", - details: [ - "`native` shows or flips the native Claude/Claude Desktop/Codex/Grok toggles; the other subcommands manage the reversible file integrations.", - "client preview shows a proposed change; enable/disable/restore accept an optional --plan-fingerprint.", - "client history remove requires --yes; client sync --client aside refreshes managed Aside profiles.", - "native cursor status/local-installer are reads; installer lookup does not install anything.", - ], - }, - { - name: "system", - usage: "ocx system ...", - summary: "Manage headless runtime settings, startup, sync, diagnostics, OpenCodex updates, and read-only Codex CLI inspection.", - details: [ - "system update manages OpenCodex itself.", - "system health reads authenticated service and spend-ledger diagnostics; root health remains liveness.", - "ocx system codex-cli-update check [--json]", - "ocx system codex-cli-update attest [--json]", - "ocx system codex-cli-update attest --candidate --npm-prefix --npm-cli --node [--json]", - "The Codex CLI inspection command makes no package-registry request, does not execute Codex or npm, install or repair software, control a process, or write configuration or cache state.", - ], - }, - { - name: "config", - usage: "ocx config [show|get|set|unset|validate|export|import] ...", - summary: "Inspect and safely modify validated OpenCodex configuration.", - details: [ - "show is the default: ocx config [show] [--json] [--source]. Flags alone also display the local configuration without a running proxy.", - "--json may precede an explicit action without changing which action runs.", - "--source is only supported for show and includes diagnostic source, error, and warning fields.", - "Secrets are masked by show/get. Import requires --yes and validates before writing.", - ], - }, - { - name: "claude", - usage: "ocx claude [claude args...]", - summary: "Launch Claude Code through the proxy, with native fallback when Claude routing is disabled.", - details: [ - "Ensures the proxy is running, then execs `claude` with ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN,", - "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 and model slots from config.claudeCode.", - "When Claude routing is explicitly disabled, it launches natively after removing proven OpenCodex-owned proxy state.", - "Routed models appear in the native /model picker with stable claude-opus-4-8-YYYYMMDD slot aliases,", - "where the year runs 2026-2035 and 2026 slots are allocated first (Claude Code >= 2.1.129).", - "Older versions: pick models via ANTHROPIC_MODEL or /model directly (any string passes through).", - "User-exported ANTHROPIC_* variables take precedence for routed launches; native fallback removes only proven OpenCodex-owned proxy values.", - "", - "Claude Desktop profile:", - " ocx claude desktop [apply] Save and apply the four-family profile", - " ocx claude desktop show [--json] Show routes, families, and defaults", - " ocx claude desktop status [--json] Show applied state, drift, and health", - " ocx claude desktop bind First-party: serve a Code tab picker model with a route", - " ocx claude desktop unbind Remove a first-party binding", - " ocx claude desktop move [--default]", - " ocx claude desktop default ", - " ocx claude desktop export Export versioned JSON (`-` = stdout)", - " ocx claude desktop import [--apply] Validate and import JSON", - " ocx claude desktop profile show [--json] Read the running proxy's profile", - " ocx claude desktop profile import [--json] Save the running profile without applying", - "Families: opus, fable, sonnet, haiku. New routes start in opus.", - "`none` is valid only when that family is empty.", - "Legacy apply flags remain supported: --static, --hybrid, --discovery-only.", - "", - "Claude Code settings: ocx claude config ...", - ], - }, - { - name: "opencode", - usage: "ocx opencode [opencode args...]", - summary: "Launch opencode wired to the proxy (runtime provider config).", - details: [ - "Ensures the proxy is running, then execs `opencode` with the generated `provider.opencodex`", - "and `providers.opencodex` blocks injected through OpenCode's inline runtime layer", - "(`OPENCODE_CONFIG_CONTENT`). Any existing inline config in the environment is preserved", - "and only `provider.opencodex` and `providers.opencodex` are overwritten for this launch.", - "V1 receives reasoning-effort variant maps; V2 receives native variant arrays for the same declared choices and defaults.", - "Global/project opencode.json may be read to warn about an existing provider.opencodex or", - "providers.opencodex override; on-disk files are never modified.", - "Routed models appear in the model picker as opencodex//.", - "Stop using `ocx opencode` and plain `opencode` behaves exactly as before.", - ], - }, - { - name: "mcode", - usage: "ocx mcode [mcode args...]", - summary: "Launch MiniMax Code through its managed OpenCodex provider.", - details: [ - "First connect the reversible file integration: ocx integration client enable --client mcode", - "The launcher verifies that custom_provider.opencodex targets the current loopback proxy before starting MCode.", - "Select custom_provider:opencodex/ from MCode's model picker.", - ], - }, - { - name: "mmx", - usage: "ocx mmx text [mmx args...]", - summary: "Launch MiniMax CLI text commands through the proxy.", - details: [ - "Only the official MMX Anthropic-compatible text surface is proxied.", - "Use plain mmx for MiniMax-native image, video, speech, music, vision, search, quota, auth, config, file, and update commands.", - "The wrapper isolates ~/.mmx credentials and refuses --api-key/--base-url overrides.", - ], - }, - { - name: "zcode", - usage: "ocx zcode [status|enable|disable|history|restore] [--json]", - summary: "Connect ZCode (Z.ai desktop client) to the proxy via its managed provider.", - details: [ - "Alias of ocx integration client --client zcode.", - "enable manages ~/.zcode/v2/provider_config.json with schemaVersion 1; if the store is absent, it writes the legacy provider.opencodex block into ~/.zcode/v2/config.json.", - "A surviving owned legacy block prevents switching stores. Run `ocx zcode disable` before enabling the current store. Unknown store schemas are refused.", - "ZCode reads its config at startup — restart ZCode after enable/disable.", - "Select OpenCodex Proxy// from ZCode's model picker.", - ], - }, - { - name: "commandcode", - usage: "ocx commandcode [status|show|list|enable|disable|history|journal|restore --op ] [--json]", - summary: "Connect Command Code CLI to the proxy via its managed provider.", - details: [ - "Alias of ocx integration client --client commandcode.", - "enable manages the opencodex block under the existing provider or providers root in ~/.commandcode/providers.json; disable removes only that block.", - "Command Code reads providers on startup.", - "`restore --op ` replays the exact previous managed block; take the id from `ocx commandcode history`.", - ], - }, - { - name: "cmd", - usage: "ocx cmd [status|show|list|enable|disable|history|journal|restore --op ] [--json]", - summary: "Alias of ocx commandcode.", - }, - { - name: "restart", - usage: "ocx restart", - summary: "Request a graceful restart of the verified running proxy, preserving routing.", - details: [ - "If no proxy is running, use the normal `ocx ensure` start policy, including the Codex autostart setting.", - "Unverifiable running targets are refused without a stop/start fallback.", - "Restarting an older proxy from this newer CLI requires standalone macOS/Linux proxies; supervised, shared, foreground, or unverifiable targets are refused.", - "For a service-managed update, run `ocx service restart`; for a desktop-managed update, restart through the OpenCodex desktop app.", - ], - }, - { - name: "v2", - usage: "ocx v2 |keep-native-v1 |threads >", - summary: "Toggle the Codex multi_agent_v2 feature (multi-agent surface).", - details: [ - "status Show flag, multi-agent mode, and thread limit.", - "on | off Enable/disable multi_agent_v2 (catalog resyncs).", - "mode Force all models to one surface, or respect upstream pins.", - "keep-native-v1 Under mode v2, keep ChatGPT-native models on v1.", - "threads Set max_concurrent_threads_per_session (integer >= 1).", - "Flips preserve the active thread limit while moving between v1/v2 modes.", - ], - }, - { - name: "health", - usage: "ocx health [--json]", - summary: "Check proxy health. Exits 0 if healthy, 1 otherwise.", - details: ["Use --json for structured output: {ok, pid, port}."], - }, - { - name: "capabilities", - usage: "ocx capabilities [--json] [--mutating-only] [--route ]", - summary: "List the declared CLI capabilities and the management routes they drive.", - details: [ - "The machine-readable surface index: start here when driving ocx programmatically instead of parsing help text.", - "--route answers the inverse question: which commands drive this management route.", - ], - }, - { - name: "ready", - usage: "ocx ready [--json] [--wait [--timeout ]]", - summary: "Check post-sync readiness. Exits 0 only when ready.", - details: [ - "Exact unauthenticated GET /readyz returns HTTP 200 when ready, or 503 with Retry-After: 1 for pending or failed.", - "Its sanitized HTTP identity is {service, version, uptime, pid, port, status}; /healthz is separate liveness, not readiness.", - "Default is a single identity-checked /readyz probe; old proxies without /readyz fail closed as unreachable.", - "--wait polls until ready or timeout, but exits immediately on terminal failed (default 45s, max 300s).", - "--timeout requires --wait and accepts a positive integer (1..300).", - "--json emits {ready, status, pid, port}; status is one of ready|pending|failed|unreachable.", - "Invalid or unknown arguments exit 64. Not-ready, pending, failed, timeout, and unreachable exit 1.", - ], - }, - { - name: "resolve", - usage: "ocx resolve [--json]", - summary: "Emit the resolved config home, effective port, and identity-checked proxy liveness as one JSON document.", - details: [ - "Machine surface for embedding shells: it replaces a second home/port/liveness implementation beside the CLI.", - "The port is the live listener's port when an opencodex proxy answers, otherwise the configured port (default 10100).", - "Liveness is three-valued: live, absent-proven (every recorded and configured endpoint definitively dead), or unknown — unknown exits 1 and never reads as absent.", - "--json emits one versioned document (schema ocx-resolve/1); the default prints two human lines.", - "Exit 0 carries a trustworthy verdict; exit 1 means the CLI could not resolve (invalid config or undecidable liveness) and callers must refuse to guess.", - "Any unknown argument exits 64 before preflight side effects.", - ], - }, - { - name: "lab", - usage: "ocx lab [options] [--json]", - summary: "Inspect local Compatibility Lab evidence and explicitly control automation.", - details: [ - "status Projection availability, schema versions, and row counts.", - "verdicts Paginated derived compatibility verdicts with filters.", - "subjects List subjects; subject returns one typed subject.", - "observations Paginated observation rows from the projection.", - "events Event history; event returns one safe typed event.", - "artifacts Artifact metadata only (no content download).", - "catalog Packaged protocol/live scenario catalog metadata.", - "production-signals Local passive routing evidence for a subject.", - "public Preview/export local evidence; verify/import a bundle.", - "automation Read status/runs or explicitly enable/disable local policy.", - "run Explicit manual scenario; live probes can consume quota.", - "Reads never rebuild the projection, trigger probes, or require the proxy.", - ], - }, - { - name: "__refresh-version", - hidden: true, - usage: "ocx __refresh-version [preview|latest]", - summary: "Hidden detached helper: refresh the cached latest version.", - }, - { - name: "__update-badge", - hidden: true, - usage: "ocx __update-badge", - summary: "Hidden internal: print cached package update badge JSON.", - }, - { - name: "__tray-start", - hidden: true, - usage: "ocx __tray-start", - summary: "Hidden internal: start the tray proxy.", - }, - { - name: "__tray-restart", - hidden: true, - usage: "ocx __tray-restart", - summary: "Hidden internal: restart the tray proxy.", - }, - { - name: "__startup-health", - hidden: true, - usage: "ocx __startup-health", - summary: "Hidden internal: print startup health JSON.", - }, - { - name: "__tray-host", - hidden: true, - usage: "ocx __tray-host", - summary: "Hidden internal: run the Windows tray host.", - }, - { - name: "__gui-update-worker", - hidden: true, - usage: "ocx __gui-update-worker [channel] [restart]", - summary: "Hidden internal: run the GUI update worker.", - }, -]; - -export function findCommand(name: string): CliCommandEntry | undefined { - // Exact-name wins so alias-name entries (setup/eject/remove/model) keep their - // own help text; the canonical entry is the fallback for alias lookups. - return CLI_COMMANDS.find(entry => entry.name === name) - ?? CLI_COMMANDS.find(entry => entry.aliases?.includes(name)); -} - -export function commandNames(): string[] { - return CLI_COMMANDS.map(entry => entry.name); -} diff --git a/src/cli/usage-compare.ts b/src/cli/usage-compare.ts new file mode 100644 index 00000000000..6a081a2186d --- /dev/null +++ b/src/cli/usage-compare.ts @@ -0,0 +1,279 @@ +/** + * Compare a bounded usage range with the previous equal window. + * + * Two sequential GET /api/usage reads with acknowledged custom bounds. + * `--range all` is refused: there is no previous equal window for open history. + */ +import { readClientConnectionState, sameClientConnectionOwner } from "../client/state"; +import { fetchHubUsage } from "../client/hub-client"; +import { readServiceApiTokenState } from "../lib/service-secrets"; +import { redactSecretString } from "../lib/redact"; +import { rangeWindow, USAGE_SURFACES } from "../usage/summary"; +import type { UsageTimeWindow } from "../usage/time-range"; +import { + CliUsageError, + printData, + rejectArgs, + RuntimeApiError, + runtimeRequest, + takeFlag, + takeOption, + takeOptionWithSyntax, + type RuntimeApiDeps, +} from "./runtime-api"; + +export const USAGE_COMPARE_USAGE = `Usage: + ocx usage compare [--range ] [--surface ] + [--provider ] [--model ] [--api-key-id ] [--json]`; + +export type CompareRange = "today" | "7d" | "30d"; +export type UsageCompareDeps = RuntimeApiDeps & { now?: () => number }; + +const METRICS = ["requests", "totalTokens", "inputTokens", "outputTokens", "cachedInputTokens", "estimatedCostUsd"] as const; +type Metric = typeof METRICS[number]; +type Totals = Partial>; +type ScopedUsage = { + customWindow?: boolean; + since?: number | null; + until?: number; + summary?: Totals; + usageIncomplete?: boolean; + filter?: Record; +}; + +function query(params: Record): string { + const search = new URLSearchParams(); + for (const [key, value] of Object.entries(params)) { + if (value !== undefined) search.set(key, String(value)); + } + const encoded = search.toString(); + return encoded ? `?${encoded}` : ""; +} + +function parseCompareRange(raw: string): CompareRange { + if (raw === "all") throw new CliUsageError("--range all has no previous equal window; use today, 1d, 7d or 30d", USAGE_COMPARE_USAGE); + if (raw === "today" || raw === "1d") return "today"; + if (raw === "7d" || raw === "30d") return raw; + throw new CliUsageError("--range must be one of today, 1d, 7d, 30d", USAGE_COMPARE_USAGE); +} + +/** Named range at `now`, then the same range evaluated one equal window earlier. */ +export function compareUsageWindows(range: CompareRange, now: number): { + current: UsageTimeWindow; + previous: UsageTimeWindow; + days: number; +} { + const days = range === "today" ? 1 : range === "7d" ? 7 : 30; + const { since } = rangeWindow(range, now); + if (since === null) throw new Error("compare requires a bounded usage range"); + const prior = new Date(now); + prior.setDate(prior.getDate() - days); + const priorNow = prior.getTime(); + const { since: previousSince } = rangeWindow(range, priorNow); + if (previousSince === null) throw new Error("compare requires a bounded usage range"); + return { + current: Object.freeze({ since, until: now }), + previous: Object.freeze({ since: previousSince, until: priorNow }), + days, + }; +} + +function metric(value: unknown): number | undefined { + return typeof value === "number" && Number.isFinite(value) ? value : undefined; +} + +function totalsOf(report: ScopedUsage): Totals { + const row = report.summary ?? {}; + const totals: Totals = {}; + for (const key of METRICS) { + const value = metric((row as Totals)[key]); + if (value !== undefined) totals[key] = value; + } + return totals; +} + +function delta(current?: number, previous?: number): number | undefined { + if (current === undefined || previous === undefined) return undefined; + return current - previous; +} + +function changePct(current?: number, previous?: number): number | null | undefined { + if (current === undefined || previous === undefined) return undefined; + if (previous === 0) return current === 0 ? 0 : null; + return (current - previous) / previous * 100; +} + +function count(value: number | undefined): string { + return value === undefined ? "—" : value.toLocaleString("en-US"); +} + +function usd(value: number | undefined): string { + return value === undefined ? "—" : `~$${value.toFixed(4)}`; +} + +function signed(value: number | undefined, money: boolean): string { + if (value === undefined) return "—"; + const abs = money ? usd(Math.abs(value)) : count(Math.abs(value)); + if (value === 0) return money ? usd(0) : "0"; + return `${value > 0 ? "+" : "-"}${abs}`; +} + +function pct(value: number | null | undefined): string { + if (value === undefined) return "—"; + if (value === null) return "n/a"; + const abs = Math.abs(value).toFixed(1); + if (value === 0) return "0.0%"; + return `${value > 0 ? "+" : "-"}${abs}%`; +} + +function iso(ms: number): string { + return new Date(ms).toISOString(); +} + +function formatCompare(input: { + range: CompareRange; + days: number; + currentWindow: UsageTimeWindow; + previousWindow: UsageTimeWindow; + current: Totals; + previous: Totals; + incomplete: boolean; +}): string[] { + const lines = [ + `Usage compare — ${input.range} vs previous ${input.days} local day${input.days === 1 ? "" : "s"} (equal window)`, + `Current ${iso(input.currentWindow.since)} to ${iso(input.currentWindow.until)}`, + `Previous ${iso(input.previousWindow.since)} to ${iso(input.previousWindow.until)}`, + "", + ]; + if (input.incomplete) { + lines.push("WARNING: Usage is incomplete; some records could not be included. Totals reflect readable records only.", ""); + } + const labels: Record = { + requests: "Requests", + totalTokens: "Tokens", + inputTokens: "Input", + outputTokens: "Output", + cachedInputTokens: "Cached", + estimatedCostUsd: "Est. cost", + }; + const rows = METRICS.map(key => { + const money = key === "estimatedCostUsd"; + const show = money ? usd : count; + return [ + labels[key], + show(input.current[key]), + show(input.previous[key]), + signed(delta(input.current[key], input.previous[key]), money), + pct(changePct(input.current[key], input.previous[key])), + ]; + }); + const header = ["METRIC", "CURRENT", "PREVIOUS", "DELTA", "CHANGE"]; + const widths = header.map((h, i) => Math.max(h.length, ...rows.map(row => row[i]!.length))); + const line = (cols: string[]) => cols.map((c, i) => c.padEnd(widths[i]!)).join(" ").trimEnd(); + lines.push(line(header), ...rows.map(line), "", "Not a billing receipt. Subscription usage or provider credits may apply instead."); + return lines; +} + +async function readUsage( + suffix: string, + window: UsageTimeWindow, + apiKeyId: string | undefined, + deps: RuntimeApiDeps, +): Promise { + const connection = readClientConnectionState(); + if (connection.kind === "invalid" || connection.kind === "mismatched") { + throw new Error(`Client usage unavailable: ${connection.reason}`); + } + let result: ScopedUsage; + if (connection.kind === "connected") { + if (apiKeyId !== undefined) { + throw new CliUsageError("--api-key-id is unavailable on connected clients; run on the hub for a selected key, or omit it for this client's usage", USAGE_COMPARE_USAGE); + } + const token = readServiceApiTokenState(); + if (token.kind !== "present" || token.fingerprint !== connection.value.tokenFingerprint) { + throw new Error("Client usage unavailable: the enrolled data key is missing or changed; repair the client connection"); + } + const link = connection.value.transport === "link" && connection.value.link; + const peerFetch = deps.fetchImpl + ?? (link ? (await import("../client/link-home")).linkBoundFetch(connection.value, token.token) : undefined); + result = await fetchHubUsage(connection.value.serverUrl, token.token, new URLSearchParams(suffix.replace(/^\?/, "")), { + fetchImpl: peerFetch, timeoutMs: 60_000, ...(link ? { peer: "Home" as const } : {}), + }); + const current = readClientConnectionState(); + const currentToken = readServiceApiTokenState(); + if (current.kind !== "connected" || !sameClientConnectionOwner(current.value, connection.value) + || current.value.tokenFingerprint !== token.fingerprint + || currentToken.kind !== "present" || currentToken.fingerprint !== token.fingerprint) { + throw new Error("Client connection changed while reading usage; retry for the current connection"); + } + } else if (apiKeyId === undefined) { + result = await runtimeRequest(`/api/usage${suffix}`, {}, deps); + } else { + try { + result = await runtimeRequest(`/api/usage${suffix}`, { redirect: "error", credentials: "omit" }, deps); + } catch (error) { + if (error instanceof RuntimeApiError && error.code === "proxy_not_running") throw error; + throw new Error("Key-scoped usage could not be read. Check runtime access and retry."); + } + if (result.filter?.apiKeyId !== apiKeyId) { + throw new Error("The server did not confirm the requested API key scope. Upgrade and restart the proxy, then retry."); + } + } + if (result?.customWindow !== true || result.since !== window.since || result.until !== window.until) { + throw new Error("The server did not confirm the requested custom usage window. Upgrade and restart the proxy, then retry."); + } + return result; +} + +/** Compare the current named range with the previous equal window through two /api/usage reads. */ +export async function handleUsageCompareCommand(argv: string[], deps: UsageCompareDeps = {}): Promise { + const args = [...argv]; + const wantsJson = takeFlag(args, "--json"); + const range = parseCompareRange(takeOption(args, "--range") ?? "30d"); + const surface = takeOption(args, "--surface") ?? "all"; + const provider = takeOption(args, "--provider"); + const model = takeOption(args, "--model"); + const rawKeyId = takeOptionWithSyntax(args, "--api-key-id")?.value; + const apiKeyId = rawKeyId?.trim(); + if (apiKeyId !== undefined && !apiKeyId) throw new CliUsageError("--api-key-id must not be blank", USAGE_COMPARE_USAGE); + if (takeOption(args, "--since") !== undefined || takeOption(args, "--until") !== undefined) { + throw new CliUsageError("compare derives both windows; do not pass --since or --until", USAGE_COMPARE_USAGE); + } + if (!USAGE_SURFACES.includes(surface as (typeof USAGE_SURFACES)[number])) { + throw new CliUsageError(`--surface must be one of ${USAGE_SURFACES.join(", ")}`, USAGE_COMPARE_USAGE); + } + rejectArgs(args.map(redactSecretString), USAGE_COMPARE_USAGE); + const now = deps.now?.() ?? Date.now(); + if (!Number.isSafeInteger(now) || now < 0) throw new CliUsageError("compare clock is invalid", USAGE_COMPARE_USAGE); + const windows = compareUsageWindows(range, now); + const filters = { range, surface, provider, model, apiKeyId }; + const currentReport = await readUsage(query({ ...filters, since: windows.current.since, until: windows.current.until }), windows.current, apiKeyId, deps); + const previousReport = await readUsage(query({ ...filters, since: windows.previous.since, until: windows.previous.until }), windows.previous, apiKeyId, deps); + const current = totalsOf(currentReport); + const previous = totalsOf(previousReport); + const deltaTotals: Totals = {}; + const change: Partial> = {}; + for (const key of METRICS) { + const d = delta(current[key], previous[key]); + if (d !== undefined) deltaTotals[key] = d; + const pctValue = changePct(current[key], previous[key]); + if (pctValue !== undefined) change[key] = pctValue; + } + const incomplete = currentReport.usageIncomplete === true || previousReport.usageIncomplete === true; + const result = { + schemaVersion: 1, + range, + surface, + days: windows.days, + filter: { provider: provider ?? null, model: model ?? null, apiKeyId: apiKeyId ?? null }, + current: { since: windows.current.since, until: windows.current.until, summary: current, usageIncomplete: currentReport.usageIncomplete === true }, + previous: { since: windows.previous.since, until: windows.previous.until, summary: previous, usageIncomplete: previousReport.usageIncomplete === true }, + delta: deltaTotals, + change, + incomplete, + }; + printData(result, wantsJson, wantsJson ? undefined : formatCompare({ + range, days: windows.days, currentWindow: windows.current, previousWindow: windows.previous, + current, previous, incomplete, + })); +} diff --git a/structure/cli-management.md b/structure/cli-management.md index 8e9910f831c..87034142098 100644 --- a/structure/cli-management.md +++ b/structure/cli-management.md @@ -114,22 +114,5 @@ Storage policy flags in `src/cli/storage.ts` preserve omitted enable/settings an `src/cli/log-view-filter.ts` owns the additive logs-filter snapshot, separate from existing follow/event transport. It fetches only the fixed log endpoint with a scan limit of at most 2000, applies GUI-equivalent local selectors, then returns the newest matches in source order without deduplicating. Model/provider matching covers resolved/served/attempt identities; protocol and conversation matching reuse their actual owners. Speed bounds accept observed value-kind metrics only. The versioned JSON view separates loaded, matched and returned counts from configured scan/output limits; JSONL is rows only. Neither a match count nor a cursor claims historical completeness or resumable search. Invalid options fail before discovery; malformed windows never become empty success. -`src/cli/usage-model-search.ts` applies optional substring search only after the existing usage target/scope acknowledgment. A copied model list sorts stably by total tokens, searches model/provider/resolvedModel and caps at 100 by default. The report's other fields remain intact; explicit modelView metadata distinguishes a view miss from no usage. `src/cli/usage-report.ts` retains the legacy renderer when no view is supplied and renders the selected rows when one is supplied. `--top` accepts 1–1000 human model rows (default 10 without search, 100 with search), applies after search and is never sent to the API. JSON ignores `--top`, including the existing 100-row search view and its metadata. Search never becomes a server attribution query or widens connected-client/key scope. +`src/cli/usage-compare.ts` reads `GET /api/usage` twice: the named range at now, then the same range shifted back one equal window. `--range all` is refused. Both responses must acknowledge the derived custom bounds. Key-scoped reads keep redirect-error transport and echoed `apiKeyId`. Connected clients reuse the existing hub usage path and refuse caller `--api-key-id`. Default range is 30d. The two reads are sequential, not an atomic snapshot. -`src/cli/companion-usage.ts` reads settings and two usage ranges sequentially on a pinned management target through `src/cli/observe-stream.ts`. Its safe projection follows the saved model/provider filters and measured-totals rules in `gui/src/pages/tray-data.ts` without importing GUI runtime code. It retains unknown/incomplete metrics, valid server defaults with null update time, and explicit corrupt/fallback flags. Malformed settings stop before usage reads. Range failure retains the other observed range, labels unavailable data, and returns partial/nonzero; signal cancellation emits no late report. The observation owner supplies a separate 10-second fetch/body deadline after discovery and 32 MiB cap for each fixed GET, not a command-wide budget. Snapshot context supplies truthful retry wording without altering default follow behavior. - -`src/cli/account-api.ts` forwards explicit quota/refresh intent to the existing per-key owner; ordinary key listing omits both. Opt-in requests reject redirects. `src/cli/account-key-quota.ts` rebuilds the public ProviderQuota projection, including custom windows and credits, with finite-field validation and no credential or private publication fields. Missing mode evidence is unverified/nonzero. Human rendering separates probe/passive/unsupported, unavailable and unmeasured from actual zero; Codex/OAuth rendering remains separate. This read can invoke upstream quota work but does not change key selection or provider aggregate caches. Account list/current rows additionally project, through `src/cli/account-next-actions.ts`, only an allow-listed server health label, a locally generated recovery command built from shell-safe selectors (never server summary/action text), and the Codex boolean `creditsAfterLimit` as read-only consent readback; empty listings add a fixed next-action note to human output and JSON `notes`. - -The operating guide's eight-domain workflow table is navigation rather than parity measurement. Handwritten JSON, recipe, recovery and target docs qualify bounded windows, model-only search, partial/default results and human-only/session actions. Generated chapter counts still derive exclusively from capability declarations. - -## ocx command selection - -`src/cli/cli-path-diagnostics.ts` reads the settled Desktop record through `src/lib/desktop-cli-record.mjs` and observes regular executable candidates on this process's PATH without executing them. `pathFirst` follows PATH/PATHEXT order, including cwd-relative and empty entries; Windows's possible cmd current-directory candidate is separate. The expected command is the owned POSIX shim or the recorded Windows bundled executable. Windows package-launcher handoff is disabled before any record read or target check; user `Path` order selects the Desktop executable, while diagnostics still read the record and report PATH order. A stale package candidate first on PATH is reported even if its current launcher would hand off. `src/cli/status.ts` exposes additive `cliCommand` JSON and a human-view line; `src/cli/doctor.ts` prints the separate “ocx command selection” checks. Neither observation supplies runtime ownership or service control authority. Parent-shell aliases, functions and caches remain unobserved. Before JSON interpretation, the POSIX reader requires a real private directory and regular non-symlink record owned by the effective uid, no group/other bits, and matching descriptor dev/ino/uid/mode after nonblocking no-follow open; macOS also refuses extended ACL entries or a failed one-second ACL check. Safety failures report `record-unsafe`. Invalid, unsafe or enabled-pending records and unusable Desktop targets are FAIL; disabled records with `cleanupPending` report `cleanup-pending` as WARN, as do PATH ordering and incomplete scans. - -Internal version observations in `src/service/managing-cli.ts` (`probeVersionOnce`) set `OCX_NO_DESKTOP_HANDOFF=1` in the spawned child's environment so the selected package executable reports its own version. This flag suppresses the package launcher's Desktop handoff only; it does not bypass service ownership or update guards. Normal user `ocx --version` remains eligible for handoff. - -`src/cli/account-auth.ts` creates a Grok coupon operation UUID before every explicitly confirmed consume request unless the caller supplies one. Uncertain delivery and unknown-outcome API responses, including `operation_state_changed`, print guidance to preserve that same `--operation-id`; the CLI performs no automatic redemption retry. Ledger and reconciliation semantics are owned by [Grok reset coupons](providers/xai-grok.md#grok-reset-coupons-billing-api-parity). - -Remote Link enrollment is shared with the dashboard through `src/server/management/link-enrollment.ts` and `src/cli/link-enrollment.ts`. `ocx link probe ` returns a temporary SSH fingerprint/key type/version offer. `ocx link add --expect-fingerprint SHA256:…` confirms exact trust and applies under loopback admin authority, with TTY explicit confirmation when the flag is omitted. Non-TTY omission fails before discovery. One Home URL and a 360-second deadline cover all requests and bodies; redirects are refused, credentials are never printed, and post-connect residual failures retain fixed recovery. `tests/cli/cli-link-enrollment.test.ts` verifies these boundaries. Child `link status` fallback uses the shared projector with persisted client connection and `clientLinkTunnelStatus`, plus validated client-owned sidecar/marker initiation identity; ambiguous evidence never invents direction. An unobserved Home-owned tunnel is conservatively idle. Link-mode `status` reads supported Hub projections via the local Child without sending a credential; a standalone Home role-based 404 explains absent Hub state rather than recommending an upgrade. - -`ocx account preserve-signed-in openai` reads or updates the runtime-owned [signed-in quota policy](providers/openai-accounts.md#preserve-signed-in-quota), with affected entries, next choice and explicit next-request binding release. It never reads a local account roster. diff --git a/structure/runtime.md b/structure/runtime.md index dc720c31f82..ab3cd9af483 100644 --- a/structure/runtime.md +++ b/structure/runtime.md @@ -384,7 +384,7 @@ Usage consumers preserve positive incomplete-history metadata as specified in as a complete ledger. The same contract owns `src/usage/log.ts` append-path permission rechecks and their bounded cache. -Connected `ocx usage` reads `/v1/usage` through `src/client/hub-client.ts`, using its enrolled data key and checking connection/token ownership before and after the read. It reports hub/client scope and never substitutes local totals on failure. Standalone commands retain their management endpoint. +Connected `ocx usage` and `ocx usage compare` read `/v1/usage` through `src/client/hub-client.ts`, using the enrolled data key and checking connection/token ownership before and after each read. They report hub/client scope and never substitute local totals on failure. Standalone commands retain their management endpoint. The client usage read requires HTTPS or loopback HTTP before adding the enrolled credential, and sets request `cache: "no-store"`; the hub response also forbids caching. diff --git a/tests/cli/cli-capabilities.test.ts b/tests/cli/cli-capabilities.test.ts index 6ad31c359e6..b85ba586a98 100644 --- a/tests/cli/cli-capabilities.test.ts +++ b/tests/cli/cli-capabilities.test.ts @@ -142,7 +142,7 @@ describe("ocx capabilities output", () => { try { code = await runCapabilities(["--json", "--route", "/api/usage"]); } finally { cap.restore(); } expect(code).toBe(0); const parsed = JSON.parse(cap.lines.join("\n")) as { capabilities: { invocation: string }[] }; - expect(parsed.capabilities.map(c => c.invocation)).toEqual(["ocx usage", "ocx models order set", "ocx combo stats", "ocx companion usage", "ocx observe usage"]); + expect(parsed.capabilities.map(c => c.invocation)).toEqual(["ocx usage", "ocx models order set", "ocx combo stats", "ocx companion usage", "ocx observe usage", "ocx usage compare"]); }); test("an unmatched route exits non-zero instead of reporting empty success", async () => { diff --git a/tests/cli/cli-capability-operation-workflows.test.ts b/tests/cli/cli-capability-operation-workflows.test.ts index 04359da9d1f..7d8a7eb5dcf 100644 --- a/tests/cli/cli-capability-operation-workflows.test.ts +++ b/tests/cli/cli-capability-operation-workflows.test.ts @@ -86,6 +86,28 @@ describe("operation capability workflows use existing handlers", () => { expect(await handleObserveCommand(["usage", "--range", "7d", "--surface", "claude", "--since", "1000", "--until", "2000", "--json"], io.deps)).toBe(0); expect(io.requests).toEqual([{ method: "GET", path: "/api/usage?range=7d&surface=claude&since=1000&until=2000", body: null }]); }); + test("usage compare reads current then previous equal windows", async () => { + expect(capability("usage compare").routes).toEqual([{ method: "GET", path: "/api/usage" }]); + const requests: string[] = []; + const deps = { + baseUrl: "http://capability.invalid", + now: () => Date.UTC(2026, 9, 15, 15, 30, 0), + fetchImpl: async (input: RequestInfo | URL) => { + const url = new URL(String(input)); + requests.push(url.pathname + url.search); + return Response.json({ + customWindow: true, + since: Number(url.searchParams.get("since")), + until: Number(url.searchParams.get("until")), + summary: { requests: 1, totalTokens: 1, estimatedCostUsd: 1 }, + }); + }, + }; + expect(await handleObserveCommand(["usage", "compare", "--range", "today", "--json"], deps)).toBe(0); + expect(requests).toHaveLength(2); + expect(requests[0]!.startsWith("/api/usage?range=today&")).toBe(true); + expect(requests[1]!.startsWith("/api/usage?range=today&")).toBe(true); + }); test("system settings distinguishes read from submitted field writes", async () => { const leaf = capability("system settings"); expect(leaf.mutates).toBe(true); diff --git a/tests/cli/cli-usage-compare.test.ts b/tests/cli/cli-usage-compare.test.ts new file mode 100644 index 00000000000..b5123a0dd30 --- /dev/null +++ b/tests/cli/cli-usage-compare.test.ts @@ -0,0 +1,223 @@ +/** + * `ocx usage compare` reads the named range, then the previous equal window. + */ +import { describe, expect, test } from "bun:test"; +import { handleObserveCommand } from "../../src/cli/observe"; +import { compareUsageWindows } from "../../src/cli/usage-compare"; + +const NOW = Date.UTC(2026, 9, 15, 15, 30, 0); + +function report(url: URL, requests: number): Record { + return { + customWindow: true, + since: Number(url.searchParams.get("since")), + until: Number(url.searchParams.get("until")), + summary: { + requests, + totalTokens: requests * 10, + inputTokens: requests * 6, + outputTokens: requests * 4, + cachedInputTokens: requests, + estimatedCostUsd: requests * 0.01, + }, + }; +} + +async function run( + argv: string[], + status = 200, +): Promise<{ code: number; out: string; err: string; urls: URL[]; inits: RequestInit[] }> { + const urls: URL[] = []; + const inits: RequestInit[] = []; + let n = 0; + const fetchImpl: typeof fetch = async (input, init) => { + const url = new URL(String(input)); + urls.push(url); + inits.push(init ?? {}); + n += 1; + return new Response(JSON.stringify(status === 200 ? report(url, n === 1 ? 20 : 10) : { error: "not found" }), { + status, + headers: { "content-type": "application/json" }, + }); + }; + const lines: string[] = []; + const errors: string[] = []; + const originalLog = console.log; + const originalErr = console.error; + console.log = (...args: unknown[]) => { lines.push(args.map(String).join(" ")); }; + console.error = (...args: unknown[]) => { errors.push(args.map(String).join(" ")); }; + try { + const code = await handleObserveCommand(argv, { baseUrl: "http://cli.test", fetchImpl, now: () => NOW }); + return { code, out: lines.join("\n"), err: errors.join("\n"), urls, inits }; + } finally { + console.log = originalLog; + console.error = originalErr; + } +} + +describe("compareUsageWindows", () => { + test("today shifts one local day and keeps equal elapsed length", () => { + const windows = compareUsageWindows("today", NOW); + expect(windows.days).toBe(1); + expect(windows.current.until).toBe(NOW); + expect(windows.previous.until).toBeLessThan(windows.current.since); + expect(windows.previous.until - windows.previous.since).toBe(windows.current.until - windows.current.since); + }); + + test("7d and 30d shift by that many local days", () => { + expect(compareUsageWindows("7d", NOW).days).toBe(7); + expect(compareUsageWindows("30d", NOW).days).toBe(30); + const week = compareUsageWindows("7d", NOW); + expect(week.previous.until).toBeLessThan(week.current.since); + }); +}); + +describe("ocx usage compare", () => { + test("reads current then previous equal windows and prints signed deltas", async () => { + const expected = compareUsageWindows("today", NOW); + const result = await run(["usage", "compare", "--range", "today", "--surface", "claude", "--provider", "xai", "--model", "grok"]); + expect(result.code).toBe(0); + expect(result.urls).toHaveLength(2); + expect(result.urls[0]!.pathname).toBe("/api/usage"); + expect(result.urls[0]!.searchParams.get("range")).toBe("today"); + expect(result.urls[0]!.searchParams.get("surface")).toBe("claude"); + expect(result.urls[0]!.searchParams.get("provider")).toBe("xai"); + expect(result.urls[0]!.searchParams.get("model")).toBe("grok"); + expect(result.urls[0]!.searchParams.get("since")).toBe(String(expected.current.since)); + expect(result.urls[0]!.searchParams.get("until")).toBe(String(expected.current.until)); + expect(result.urls[1]!.searchParams.get("since")).toBe(String(expected.previous.since)); + expect(result.urls[1]!.searchParams.get("until")).toBe(String(expected.previous.until)); + expect(result.out).toContain("Usage compare — today vs previous 1 local day"); + expect(result.out).toContain("Requests"); + expect(result.out).toContain("+10"); + expect(result.out).toContain("+100.0%"); + expect(result.out).toContain("~$0.2000"); + expect(result.out).toContain("~$0.1000"); + }); + + test("JSON carries delta, percent change, and 1d as today", async () => { + const expected = compareUsageWindows("today", NOW); + const result = await run(["usage", "compare", "--range", "1d", "--json"]); + expect(result.code).toBe(0); + const body = JSON.parse(result.out) as { + schemaVersion: number; + range: string; + days: number; + current: { since: number; summary: { requests: number } }; + previous: { since: number; summary: { requests: number } }; + delta: { requests: number }; + change: { requests: number }; + }; + expect(body.schemaVersion).toBe(1); + expect(body.range).toBe("today"); + expect(body.days).toBe(1); + expect(body.current.since).toBe(expected.current.since); + expect(body.previous.since).toBe(expected.previous.since); + expect(body.current.summary.requests).toBe(20); + expect(body.previous.summary.requests).toBe(10); + expect(body.delta.requests).toBe(10); + expect(body.change.requests).toBe(100); + }); + + test("default range is 30d and a zero previous window reports n/a change", async () => { + const expected = compareUsageWindows("30d", NOW); + const urls: URL[] = []; + let n = 0; + const fetchImpl: typeof fetch = async input => { + const url = new URL(String(input)); + urls.push(url); + n += 1; + const requests = n === 1 ? 5 : 0; + return Response.json({ + customWindow: true, + since: Number(url.searchParams.get("since")), + until: Number(url.searchParams.get("until")), + summary: { requests, totalTokens: requests, inputTokens: 0, outputTokens: 0, cachedInputTokens: 0, estimatedCostUsd: 0 }, + }); + }; + const lines: string[] = []; + const original = console.log; + console.log = (...args: unknown[]) => { lines.push(args.map(String).join(" ")); }; + try { + expect(await handleObserveCommand(["usage", "compare"], { baseUrl: "http://cli.test", fetchImpl, now: () => NOW })).toBe(0); + } finally { + console.log = original; + } + expect(urls[0]!.searchParams.get("range")).toBe("30d"); + expect(urls[0]!.searchParams.get("since")).toBe(String(expected.current.since)); + expect(lines.join("\n")).toContain("n/a"); + }); + + test("rejects all, unknown ranges, custom bounds, and inverted surfaces before transport", async () => { + expect((await run(["usage", "compare", "--range", "all"])).code).toBe(2); + expect((await run(["usage", "compare", "--range", "all"])).urls).toHaveLength(0); + expect((await run(["usage", "compare", "--range", "year"])).code).toBe(2); + expect((await run(["usage", "compare", "--since", "1", "--until", "2"])).code).toBe(2); + expect((await run(["usage", "compare", "--surface", "web"])).code).toBe(2); + expect((await run(["usage", "compare", "--range", "all"])).err).toContain("no previous equal window"); + }); + + test("unacknowledged custom windows and key-scope mismatch fail closed", async () => { + const fetchImpl: typeof fetch = async () => Response.json({ summary: { requests: 1 } }); + const errors: string[] = []; + const original = console.error; + console.error = (...args: unknown[]) => { errors.push(args.map(String).join(" ")); }; + try { + expect(await handleObserveCommand(["usage", "compare", "--range", "today", "--json"], { + baseUrl: "http://cli.test", fetchImpl, now: () => NOW, + })).toBe(1); + expect(errors.join("\n")).toContain("did not confirm the requested custom usage window"); + } finally { + console.error = original; + } + + const scoped: typeof fetch = async () => Response.json({ + customWindow: true, since: 1, until: 2, filter: { apiKeyId: "other" }, summary: { requests: 1 }, + }); + errors.length = 0; + console.error = (...args: unknown[]) => { errors.push(args.map(String).join(" ")); }; + try { + expect(await handleObserveCommand(["usage", "compare", "--api-key-id", "Key-A", "--json"], { + baseUrl: "http://cli.test", fetchImpl: scoped, now: () => NOW, + })).toBe(1); + expect(errors.join("\n")).toContain("did not confirm the requested API key scope"); + } finally { + console.error = original; + } + }); + + test("key scope uses redirect-error transport and echoes the id", async () => { + const expected = compareUsageWindows("7d", NOW); + const urls: URL[] = []; + const inits: RequestInit[] = []; + const fetchImpl: typeof fetch = async (input, init) => { + const url = new URL(String(input)); + urls.push(url); + inits.push(init ?? {}); + return Response.json({ + customWindow: true, + since: Number(url.searchParams.get("since")), + until: Number(url.searchParams.get("until")), + filter: { apiKeyId: "Key-A", provider: null, model: null, matched: true, comboOverlap: false }, + summary: { requests: 3, totalTokens: 9, inputTokens: 1, outputTokens: 1, cachedInputTokens: 0, estimatedCostUsd: 0.1 }, + }); + }; + const lines: string[] = []; + const original = console.log; + console.log = (...args: unknown[]) => { lines.push(args.map(String).join(" ")); }; + try { + expect(await handleObserveCommand(["usage", "compare", "--range", "7d", "--api-key-id", "Key-A", "--json"], { + baseUrl: "http://cli.test", fetchImpl, now: () => NOW, + })).toBe(0); + } finally { + console.log = original; + } + expect(urls).toHaveLength(2); + expect(urls[0]!.searchParams.get("apiKeyId")).toBe("Key-A"); + expect(urls[0]!.searchParams.get("range")).toBe("7d"); + expect(urls[0]!.searchParams.get("since")).toBe(String(expected.current.since)); + expect(inits[0]!.redirect).toBe("error"); + expect(inits[0]!.credentials).toBe("omit"); + expect(JSON.parse(lines.join("\n")).filter.apiKeyId).toBe("Key-A"); + }); +}); diff --git a/tests/fixtures/test-layout-expected.json b/tests/fixtures/test-layout-expected.json index f5047535934..3941e57e8e7 100644 --- a/tests/fixtures/test-layout-expected.json +++ b/tests/fixtures/test-layout-expected.json @@ -52,6 +52,7 @@ "messages-native-scope.test.ts": "claude-integration", "catalog-auto-review-row.test.ts": "codex-integration", "codex-use-remaining-quota.test.ts": "codex-integration", "cli-log-view-filter.test.ts": "cli", + "cli-usage-compare.test.ts": "cli", "cli-usage-model-search.test.ts": "cli", "cli-usage-top.test.ts": "cli", "cli-companion-usage.test.ts": "cli", From 6a67aed8e1feba4777769f36c0b9c1d27a6e4896 Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Fri, 16 Oct 2026 10:37:59 +0900 Subject: [PATCH 2/7] Add ocx logs history and ocx logs get for indexed request history (carry #7212) Carried from #7212. Preserve the complete dev files when resolving overlapping usage and log declarations. Co-authored-by: Matt Van Horn --- .../src/content/docs/reference/cli/agents.md | 756 +++++++ .../docs/reference/configuration/routing.md | 3 +- scripts/test-layout/layout.json | 1912 +++++++++++++++++ .../ocx/references/01_management_surface.md | 12 +- .../references/01_surface_observe-system.md | 61 +- skills/ocx/references/02_json_shapes.md | 12 +- skills/ocx/references/03_recipes.md | 11 +- src/cli/capabilities-base.ts | 2 +- src/cli/capabilities-observe-system.ts | 41 + src/cli/log-history.ts | 172 ++ src/cli/observe.ts | 311 +++ src/cli/registry.ts | 337 ++- structure/cli-management.md | 21 + structure/dashboard-and-usage.md | 2 +- tests/cli/cli-capabilities.test.ts | 2 - ...cli-capability-operation-workflows.test.ts | 10 + tests/cli/cli-log-history.test.ts | 146 ++ tests/fixtures/test-layout-expected.json | 1 + 18 files changed, 3797 insertions(+), 15 deletions(-) create mode 100644 src/cli/log-history.ts create mode 100644 tests/cli/cli-log-history.test.ts diff --git a/docs-site/src/content/docs/reference/cli/agents.md b/docs-site/src/content/docs/reference/cli/agents.md index 77a0c25ec3a..f8f51ef8781 100644 --- a/docs-site/src/content/docs/reference/cli/agents.md +++ b/docs-site/src/content/docs/reference/cli/agents.md @@ -416,4 +416,760 @@ Inspect proxy requests, usage, storage, memory, and debug data. The direct alias | Alias | Equivalent resource | | --- | --- | | `ocx logs [filters] [--follow] [--json|--jsonl|--events]` | `ocx observe logs` | +| `ocx usage [--range ] [--since --until ] [--surface ] [--provider ] [--model ] [--api-key-id ] [--search ] [--top <1-1000>] [--json]` | `ocx observe usage` | | `ocx usage compare [--range ] [--json]` | `ocx observe usage compare` | +| `ocx storage [--json]` | `ocx observe storage` | +| `ocx memory [--json]` | `ocx observe memory` | + +```bash +ocx observe usage --range 30d --json +ocx usage --since 2026-09-01T09:00:00Z --until 2026-09-01T10:59:59.999Z --json +``` + +`--since` and `--until` must be supplied together. They accept integer epoch milliseconds or +full ISO datetimes with an explicit timezone, include both endpoints, and override `--range`. +Invalid or reversed bounds fail before the request. Human output prints the requested interval; +`--json` includes `customWindow`, `since`, and `until`. Existing surface/provider/model filters +still apply. These commands query the running proxy; they do not provide offline reports. + +`--range today` (alias `1d`) reports the current local day. `--provider` and +`--model` narrow the report to one upstream target — distinct from +`--surface`, which selects the calling client (Codex, Claude Code, Grok) +rather than the provider serving the request. + +The default view prints request, token and estimated-cost totals plus +per-provider and per-model breakdowns. Costs are API list-price equivalents, +not a billing receipt: subscription plans and provider credits are billed +separately, and requests with no matching price row are counted as +`unpriced`/`unmetered` rather than folded in as zero. + +```bash +ocx usage --range today --provider xai +``` + +When some usage records cannot be included, human output warns, including when there are zero readable rows. +Any displayed totals reflect readable records only. If a filter has no readable matches, the output shows +the warning and guidance instead of total lines; skipped records may contain matches. +`--json` preserves the response-level `usageIncomplete` diagnostic and reason. + +### Compare a range with the previous equal window + +```bash +ocx usage compare --range today --json +ocx usage compare --range 7d --provider xai +``` + +`ocx observe usage compare` is the equivalent family form. The command reads `GET /api/usage` +twice: the named range ending now, then the same range evaluated one equal window earlier +(one local day for `today`/`1d`, seven for `7d`, thirty for `30d`). Default range is `30d`. +`--range all` is refused because open history has no previous equal window. `--since` and +`--until` are not accepted; the windows are derived. Surface, provider, model, and API-key +filters apply to both reads. Human output prints current, previous, signed delta, and percent +change. `--json` is `{schemaVersion,range,current,previous,delta,change,incomplete}`. The two +reads are sequential, not an atomic snapshot. Custom `since`/`until` on each response must +match the requested window. + +### Filter a bounded log snapshot + +```bash +ocx logs filter --surface claude --status errors --time-window 1h --scan-limit 2000 --limit 50 --json +``` + +`ocx observe logs filter` is the equivalent family form. This reads one recent +window, filters locally, then keeps the newest matches in their original order. +`--scan-limit` controls fetched rows (1–2000, default 2000); `--limit` controls +returned rows (1–2000, default 200). JSON reports +`{schemaVersion:1,logs,cursor,filters,window:{scanLimit,loaded,matched,returned,limit}}`. +Counts describe this observed window, not all history. JSONL emits rows only; +empty matches succeed. Cursor metadata is not a resumable search token. + +Selectors include `--surface all|codex|claude|grok`, `--status all|success|errors`, +`--time-window all|15m|1h|24h`, `--model`, `--provider`, `--conversation` +(alias `--conversationId`), `--intercepted-only`, `--min-tok-per-sec`, +`--max-tok-per-sec`, and `--protocol-mode all|native|translated|legacy-bridge|blocked|none`. +Model/provider equality is trimmed and case-insensitive, including +resolved/served models and attempts. Claude includes Desktop; Codex means absent +surface. Success is HTTP 200–299, errors 400–599. Time lower bounds are inclusive. +Speed uses observed value-kind tok/s, with inclusive minimum and exclusive +maximum; unavailable values fail active speed filters. Protocol none includes +absent or invalid traces. Conversation matching uses the same hash-aware IDs as +ordinary logs. Interception selects string-valued rewrite markers. + +Unknown/repeated/conflicting flags, invalid bounds, and follow/events fail before +discovery. Malformed, oversized or failed reads are nonzero, not empty results. +To reduce response size, reduce the scan limit; reducing output limit does not +change the fetch. For streaming use the separate follow forms below. + +### Search usage model rows + +```bash +ocx usage --range 7d --search 'model-a' --json +``` + +`--search` matches a trimmed case-insensitive substring in model, provider or +resolved model after reading the report. It sorts model rows by descending total +tokens with stable ties and keeps up to 100 by default. JSON adds +`modelView:{query,matchedModelCount,returnedModelCount,limit:100,truncated}`; +human output labels the view and shows its selected model rows. Report totals, +provider/day/account rows, exact filters and incomplete/window metadata remain +unchanged. No model match does not mean no report usage. + +An explicit blank query (`--search=`) selects the top-100 view; omitting search +preserves the existing output. Exact `--provider`/`--model` still scope the +underlying report. Search does not broaden selected-key or connected-client +self scope and is never sent as a new Hub API query parameter. + +`ocx usage --top 25` (also `ocx observe usage --top 25`) sets the human model table limit to an integer from 1 to 1000. The default is 10, or 100 with `--search`; the limit applies after search filtering. It changes local display only: report totals, provider/account rows and API parameters stay unchanged. With `--json`, a valid `--top` is ignored; JSON retains its existing full report or 100-row search view. Invalid limits return exit 2 before fetching. + +### Saved companion usage totals + +```bash +ocx companion show --json +ocx companion usage --json +``` + +The second command reads saved companion settings, then today and 30d usage +sequentially on the same management runtime. It applies the saved `models` and +`hiddenProviders` preferences and preserves unknown/unmeasured costs and tokens. +Null model selection means all; an empty selection means none. It does not +change settings, operate native windows or relay through a connected client. + +JSON returns `schemaVersion:1`, `filters`, `settingsUpdatedAt`, +`settingsCorrupt`, `settingsFallback`, `ranges` and `partial`. Each range has +`status:"available"` with filtered `data`, or `status:"unavailable"`. +An unavailable range sets partial and exit 1 while retaining the other range. +Available incomplete data retains its own metadata; it is not measured zero. +Valid server defaults retain a null settings timestamp and set fallback; +corrupt-file defaults additionally set corrupt and warn in human output. +Malformed settings stop before usage reads. These reads are not an atomic +snapshot. Each GET has a 10-second fetch/body deadline after discovery and a +32 MiB response cap; this is not a whole-command deadline. Signals exit 130/143 +without late results. + +### Follow request windows or injection sequences + +```bash +ocx logs --help +ocx logs --limit 200 --json +ocx logs --follow --events --limit 200 +``` + +`--events` requires follow and implies JSONL; redundant `--jsonl` is accepted. +`--json` remains one-shot and conflicts with follow/events. Each events-v1 line +is `{schemaVersion:1,type:"snapshot"|"append",rows,cursor,limit}`. Replace the +consumer window on snapshot, append/trim on append, preserving order and repeated +IDs. Initial empty and reset/removal snapshots are emitted; stable empty polls +remain silent. Legacy arrays are snapshots with cursor null, not invented cursors. +These are observed windows, not a lossless replay of traffic missed between polls +or after ring eviction. + +`ocx logs --follow --jsonl --limit 200` retains row-shaped output. It re-emits changed +occurrences, including same-ID status/token amendments and repeated IDs. Do not +collapse everything by request ID. This legacy output cannot encode removals, +resets or exact window order; choose events when those distinctions matter. +Log follow limit is 1–2000, default 200. + +```bash +ocx observe injection --limit 500 --json +ocx observe injection --follow --jsonl --limit 500 +``` + +Injection emits ordered `{seq,at,line}` rows, where `at` is epoch milliseconds; +internal `after` advances with seq. Follow limit is 1–2000, default 500. JSON is +one-shot and JSONL requires follow. Observation does not enable capture. Empty +polls do not identify disabled capture or prove absence of gaps. Detectable runtime +drift stops; undetectable restart/latest-N gaps cannot be excluded without an API +epoch/gap marker. + +Both follow loops use serial one-second waits, 10-second fetch/body deadlines and +32 MiB response limits. Malformed/oversized/transport errors stop with stderr and +exit 1, without automatic retry/reconnect. Reduce limit for oversized windows. +SIGINT/Ctrl-C exits 130, SIGTERM 143, with no later polls/output. Inspect exit state +and retained rows instead of treating cancellation as complete history. + +### Companion timeline and key-scoped usage + +```bash +ocx companion timeline --help +ocx companion timeline --hours 24 --bucket-minutes 60 --metric total --aggregation sum --grouping model --model example/model-a --hide-provider excluded-provider --json +``` + +Replace fictional IDs with the selected filters. Repeat `--model` for individual +provider/model IDs (nested slashes allowed; not CSV); repeat `--hide-provider` to +exclude providers. Positive `--provider` is unsupported. Hours are 6/24/72/168, +bucket minutes 1–1440 with at most 2000 buckets, metric total/input/output/cached, +aggregation sum/average/max, grouping model/modelAccount. The API limits filter +inputs to 100 items. This reads usage without changing companion settings. + +Check `appliedFilters.models/hiddenProviders`. Timeline bounds are epoch seconds, +with exclusive end, unlike ordinary usage's millisecond custom window. The end must +match the request-time bucket, or its immediate successor if the request crosses +a bucket boundary; an older aligned window is refused. Empty +series retains bucket/filter metadata. `missingMeasurements` and `truncated` must +remain visible: zero-filled points do not prove complete zero usage. + +On a non-client management host: + +```bash +ocx access key list --json +ocx usage --api-key-id key-example --range 7d --json +``` + +Use a non-secret actual key ID. The CLI requires exact response acknowledgment in +`filter.apiKeyId`; ignored filters fail rather than showing unscoped totals. +An unknown acknowledged ID can return `matched:false` and empty traffic, not 404. +Keep incomplete/custom-window facts. Connected clients reject `--api-key-id` +before enrolled-key access or transport; omit it for existing self-only Hub usage +or perform the selected-key view on the Hub. No data key grants management authority. + +### `ocx debug ` + +Read or change runtime debug overrides through the running proxy's management API. + +```bash +ocx debug provider on|off|status|reset +ocx debug provider logs [-f|--follow] +ocx debug usage on|off|status|reset +ocx debug usage logs [-f|--follow] +``` + +With no scope, `ocx debug` prints usage and, when the proxy is stopped, the next-start environment +defaults. Provider debug defaults from `OCX_DEBUG=1` (legacy `OCX_DEBUG_FRAMES=1` also works); usage +debug defaults from `OPENCODEX_USAGE_DEBUG=1`. + +## API access + +### `ocx access ...` + +Inspect admission keys, external endpoints and models with the access family. +`ocx api-key` aliases the access-key family. Creation and rotation-start return a +one-time plaintext credential in text and JSON output. Agents must leave those +steps to a human-operated terminal outside the agent session; request only +confirmation and non-secret key/rotation IDs, never the credential. + +```bash +ocx access key list --json +``` + +After the human configures and verifies the replacement, committing its rotation +or removing the old key requires separate explicit revocation authority. Safe +non-secret follow-ups are `ocx access key rotate commit --json` +and `ocx access key rotate abort --json`, with authority for +the chosen action. Re-list afterward. Missing pending state alone does not prove +commit: expiry or abort can also clear it. Do not route around consent by issuing +the secret-returning management request directly. + +### Rename one key without changing its access policy + +```bash +ocx access key rename key-example 'Research client' --json +ocx access key list --json +``` + +Use an actual unique ID or unambiguous name. Rename sends only `{id,name}` and +preserves provider/model scopes; it does not rotate/delete a key. The response +contains id/name/createdAt and optional allowedProviders/allowedModels, never +plaintext or a prefix. List remains masked. Names are control-free, trimmed, +nonempty and at most 64 JavaScript string units. The read/rename sequence is not +CAS; inspect the masked roster after an unknown outcome before retrying. The +root `api-key rename` alias uses the same command. + +### Explicit-key model and audio checks + +Discover the installed syntax without contacting upstream: + +```bash +ocx access test --help +ocx access audio transcribe --help +ocx access audio live-check --help +``` + +Model requests, audio uploads and live-session checks require explicit operator +authorization for that particular upstream operation and possible quota/cost. +The operator supplies the selected key from an approved private stdin source in +a human-operated terminal outside the agent session. Agents must not capture it +or ask for it in chat. Never put it in argv/environment. These are the ocx side +of that private pipe, not direct interactive key prompts or an agent-run batch: + +```bash +ocx access test example/model --protocol responses --api-key-stdin --json +ocx access audio transcribe sample.wav --model gpt-4o-mini-transcribe --api-key-stdin --json +ocx access audio live-check --model gpt-live-1-codex --api-key-stdin --json +``` + +Choose only the authorized task and real model/file. TTY input is refused. Input +is bounded to 4096 bytes/30 seconds, valid UTF-8 printable ASCII, without outer +whitespace, controls or extra lines; one final LF/CRLF is allowed. This deliberately +covers currently issued keys, not every Unicode value the server configuration +might accept. Exact supplied-key occurrences in permitted text become `[redacted]`; +arbitrary encodings are not guaranteed detected. No encoded key carrier is printed. + +Targets are the checked local serving origin or existing normalized enrolled Hub +origin, with identity checked around asynchronous work. There is no custom-origin, +admin or enrolled-key fallback, redirect following, credential cache or automatic +retry. The operator reports only the non-secret result to the agent. + +#### Model control and response limits + +Protocols are chat (default), responses or messages. Selected-key mode first +sends one credentialless malformed-JSON control to that endpoint. Only the native +key-required 401 advances to one fixed 16-token model request using the supplied +key. The control has a 5-second/4096-byte response budget; the request has a +60-second/2 MiB response budget including body reads. Authless/unrecognized +controls stop before inference. Local logging/admission bookkeeping may still occur. + +JSON is `{schemaVersion:1,control:{outcome,status?},request:{outcome,status?},response?}`. +Safe response contains protocol, ordered text, complete/limited completion and +optional measured token counts. A usable length-limited reply is `limited`; +refusal/content-filter/tool-only or malformed responses are unsupported, even +with HTTP 2xx. Error metadata, IDs, tools and reasoning are not printed. +Operational failure retains one versioned report plus fixed stderr/exit 1; +invalid grammar/key input exits 2 without a fabricated report. + +Success says only: “Credentialless request was refused; the model request using +the supplied key succeeded.” Listener/policy changes between calls remain possible; +this does not certify key scope, atomic admission or billing identity. Without +`--api-key-stdin`, legacy test JSON remains its original payload and says nothing +about a newly selected key. + +#### Transcription and live readiness + +Transcription requires a nonempty regular file of at most 25,000,000 bytes with a +30-second local read limit, and a multipart body capped at 32 MiB. Models are +gpt-4o-transcribe, gpt-4o-mini-transcribe or whisper-1, subject to target support. +Upload/response share 130 seconds; response is capped at 2 MiB. Success returns +only `{text}`, including empty text, with exact-key redaction. Failure leaves +stdout empty and prints fixed stderr/nonzero; no JSON error envelope or raw body. + +Audio uses explicit-key admission without the model control. Live-check sends +fixed session.update and session.close only. Readiness requires session.started +or session.updated with nonblank native session ID within 15 seconds; socket-open +or session.created alone is insufficient. After readiness it waits at most 2 +seconds for normal code-1000 closure. Each UTF-8 frame is capped at 64 KiB, aggregate +2 MiB; there is no retained frame history. + +Live JSON is `{schemaVersion:1,ready,close:"confirmed"|"unverified",check:"session-readiness",event?}`. +Operational failure preserves that observation without raw frames. Partial readiness +with unverified close exits 1; a later normal close cannot erase an earlier error. +Signals exit 130/143. This checks readiness/closure only, not microphone, upload, +tool execution, full voice roundtrip or server lease release. Opening the upstream +session is not guaranteed free. No reconnect or retry is automatic. + +### `ocx api ...` + +Inspect and set how requests travel between the client APIs and provider wires. See +[Protocol paths](/guides/protocol-paths/) for the vocabulary. + +| Command | Route | Changes state | +| --- | --- | --- | +| `ocx api protocols [--provider ] [--json]` | `GET /api/protocols` | No | +| `ocx api explain --model --inbound [--feature ]... [--json]` | `POST /api/protocols/plan` | No | +| `ocx api policy [--json]` | `GET /api/protocols` | No | +| `ocx api policy [--messages ] [--unrepresentable ] [--rollout =]... [--json]` | `PATCH /api/protocols/settings` | Yes | + +- `protocols` prints the contract version, whether each client API is served and why, the + unrepresentable policy, every rollout switch, and the policy revision. `--provider` adds the + upstream wire that provider receives, who decided it, and the models on another wire. +- `explain` previews the path a model would take from one client API. `--feature` is repeatable + and accepts a comma-separated list; `ocx api protocols --json` lists the known feature keys. The + preview is computed from configuration: nothing is sent upstream, no combo rotation advances, and + the input is not logged. +- `policy` without a setting flag only reads. With one it sends a single change to the running + proxy, which validates it, saves the configuration, and answers with the new policy. + `--messages off` also turns the Claude integration off, as the dashboard toggle does. Switch + names and combinations are validated by the proxy; for example + `--rollout managedMessagesNativeOAuth=on` is refused unless `managedMessagesNative` is + already on or turned on in the same command. + +```bash +ocx api explain --model combo/main --inbound chat --feature request.seed,request.tools +ocx api policy --rollout shadowPlan=on +``` + +Usage errors exit 2 before any request is sent. `--json` prints the management API body as is. + +## Client integrations + +### Basic integration commands + +| Command | Action | +| --- | --- | +| `ocx integration client status [--client ] [--profile ] [--json]` | Read all managed file integrations, one client, or Aside profiles. `show` and `list` alias `status`. | +| `ocx integration client history [--client ] [--profile ] [--json]` | Read rollback operations and snapshot availability. `journal` aliases `history`. | +| `ocx integration client enable --client [--profile ] [--overwrite-conflict] [--json]` | Apply the managed file integration. Overwriting a conflicting block requires the explicit flag. | +| `ocx integration client disable --client [--profile ] [--json]` | Remove the selected managed integration through its runtime owner. | +| `ocx integration client restore --op [--client aside --profile ] [--confirm-drift] [--json]` | Restore a recorded operation; replacing later edits requires explicit drift confirmation. | +| `ocx integration native [list] [--json]` | Read native integration state. | +| `ocx integration native [--json]` | Write the selected native client's configuration through its runtime owner. | + +These commands require a running proxy. `--profile` selects a nonnegative Aside account ID and +requires `--client aside`; omitted profiles select the aggregate for reads and all profiles for +unbound enable/disable. Native toggles change client configuration; Cursor has separate read-only +inspection commands below. For preview and bound-write options, continue with the recipes below. + +### Preview and recover managed file integrations + +```bash +ocx integration client preview --client hermes --operation apply --json +ocx integration client restore --op op-example --preview --json +``` + +`op-example` is fictional; use an ID from history. Preview operations are apply, +overwrite and disable; restore uses `--preview` on its existing command. Review +structural changes and `canApply`/`willChange`; valid refusal/no-op exits 0 without +applying. Enable/disable/restore accept optional `--plan-fingerprint` for an +explicit bound commit. Direct legacy writes remain available. Aside preview or +bound writes require `--client aside --profile N`. Drift confirmation and overwrite +are never automatic; stale binding exits 5 with empty stdout and a re-preview +instruction on stderr. Follow the [complete preview/commit and drift recipes](/guides/integrations/#preview-and-bind-a-terminal-write). + +Droid apply/overwrite supports repeated `--reasoning-default MODEL=EFFORT` for +full map replacement, or exclusive `--clear-reasoning-defaults` for `{}`. Omission +preserves the map. Repeat the exact map in preview and commit; see +[Droid defaults](/guides/integrations/#factory-droid). + +History removal is irreversible and requires an exact opId plus `--yes`: +`ocx integration client history remove --op op-example --yes --json` addresses the +global journal. Only `--client aside` and optional `--profile N` provide narrower +delete scopes. The newest row is protected. `snapshotRemoved:false` exits 1 after +retirement with cleanup incomplete; do not retry deletion or claim rollback. + +`ocx integration client sync --client aside --json` refreshes eligible profiles +through the attested owner, with no profile selector or local fallback. Empty +`results` is successful observation of no eligible profiles; a failed row makes +the aggregate nonzero while preserving other successes. Read status and recovery +facts before retrying; [Aside controls](/guides/integrations/#aside-profile-controls) +explain profile intent versus file state. + +### Inspect Cursor without installing it + +```bash +ocx integration native cursor status --json +ocx integration native cursor local-installer --json +``` + +Status can gather model inventory; installer lookup may fetch a public manifest. +They do not download/install or toggle Cursor. Status distinguishes credential +from placeholder gateway mode; the placeholder is not an access credential. +Installer `{available:false,url:null,version:null,reason:null}` is valid, including +when Private Inference is already installed. A valid unavailable read exits 0. + +### `ocx integration ...` + +Manage supported Claude and Grok integrations. The direct command families below expose their +client-specific controls. + +### `ocx claude [claude args...]` + +Ensure the proxy is running, then launch Claude Code with `ANTHROPIC_BASE_URL`, +`ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1`, and model slots from +`config.claudeCode`. Routed models appear in the native `/model` picker through stable slot aliases +with Claude Code 2.1.129 or newer. On older versions, select with `ANTHROPIC_MODEL` or `/model `. +User-exported `ANTHROPIC_*` variables always take precedence. + +Claude Desktop profile commands are: + +```text +ocx claude desktop [apply] Save and apply the four-family profile +ocx claude desktop show [--json] Show routes, families, and defaults +ocx claude desktop status [--json] Show applied state, drift, and health +ocx claude desktop move [--default] +ocx claude desktop default +ocx claude desktop export Export versioned JSON (`-` = stdout) +ocx claude desktop import [--apply] Validate and import JSON +``` + +The families are `opus`, `fable`, `sonnet`, and `haiku`; new routes start in `opus`. `none` is valid +only when that family is empty. Legacy apply flags `--static`, `--hybrid`, and `--discovery-only` +remain supported. Use `ocx claude config ...` for Claude Code settings. + +#### Read or save the selected runtime's Desktop profile + +The existing show/import commands above are local. The `profile` family targets +the running management runtime and can gather model inventory: + +```bash +ocx claude desktop profile show --json > desktop-observed.json +jq '.profile' desktop-observed.json > desktop-profile.json +``` + +Edit/review the versioned profile, preserving server-owned applied markers. For +an authorized save, then read-back: + +```bash +ocx claude desktop profile import desktop-profile.json --json +ocx claude desktop profile show --json +``` + +Import accepts the profile itself, not the outer `{profile,models,rendered,port}` +response, using bounded regular JSON files or explicit stdin `-` (4 MiB/30 seconds). +It returns those observed fields plus `ok:true`, meaning saved only. `--apply` and +native-mode flags are rejected; failed runtime save has no local fallback. Apply +is a separate existing Desktop action on its machine, so verify host/context +before choosing it. Rendered models are not proof of native application. + +### `ocx opencode [opencode args...]` + +Ensure the proxy is running, then launch opencode with the generated `provider.opencodex` and +`providers.opencodex` blocks in OpenCode's inline runtime layer (`OPENCODE_CONFIG_CONTENT`). The +legacy block keeps V1 clients working with variant maps; the V2 block carries native arrays +for the same reasoning-effort choices and defaults. Existing inline config is preserved and only those two keys are replaced +for this launch. Global or project `opencode.json` files may be read to warn about an existing +override, but on-disk files are never modified. Routed models appear as +`opencodex//`. Launching plain `opencode` later behaves exactly as before. + +### `ocx grok ...` + +Manage and apply the Grok Build model fence. + +## Client config export + +### `ocx export --client ` + +Print a client config wired to the running proxy. The command serializes the +`opencodex` provider block — base URL, model list, and the client's credential +reference or loopback placeholder — in the selected client's native format. + +The proxy must be running; the command resolves its live port, reads `/api/models`, and emits only +models Codex can currently see. + +OpenCode and Kilo exports preserve effective model limits, known capabilities, declared reasoning +choices and defaults, including metadata inherited by custom rows. Explicit overrides still win; +unknown capabilities and defaults are not invented. The OpenCode launcher uses the same metadata. +See [client integrations](/guides/integrations/) for managed refresh and upgrade behavior. + +| Flag | Action | +| --- | --- | +| `--client ` | Required. Selects the client config dialect. | +| `--json` | Print the generated document as JSON on stdout for scripts. This is JSON even when the selected client's native format is YAML, TOML, or JSON5. | +| `--out ` | Write the client's native config format to ``. Refuses to replace an existing file. | +| `--force` | Allow `--out` to replace an existing file. | + +```bash +ocx export --client opencode # config plus destination, merge warning, and counts +ocx export --client pi --json > pi-models.json # JSON document for a pipe or a diff +ocx export --client omp --out ./omp-models.yml # native OMP YAML +ocx export --client opencode --out ~/opencodex-opencode.json +``` + +Without `--json` the generated config leads, then the canonical destination path, the merge warning, the env +export line where the client has one, and a model count with how many rows omit context limits (the +client applies its own defaults for those). + +| Client | Canonical destination | Download filename | Env var | +| --- | --- | --- | --- | +| `opencode` | `~/.config/opencode/opencode.json` (`XDG_CONFIG_HOME` wins when set) | `opencode.json` | `OPENCODEX_OPENCODE_API_KEY` | +| `pi` | `~/.pi/agent/models.json` (`PI_CODING_AGENT_DIR` wins when set; a relative value is refused) | `pi-models.json` | none — the block carries the literal `opencodex-loopback` | +| `omp` | `~/.omp/agent/models.yml` (`OMP_PROFILE` wins over `PI_PROFILE`, even when empty; named profiles use the home-relative `PI_CONFIG_DIR` directory name and ignore `PI_CODING_AGENT_DIR`, while the default profile lets `PI_CODING_AGENT_DIR` win) | `omp-models.yaml` | none — loopback placeholder | +| `hermes` | `~/.hermes/config.yaml` | `hermes-config.yaml` | `OPENCODEX_HERMES_API_KEY` | +| `openclaw` | `~/.openclaw/openclaw.json` | `openclaw.json5` | `OPENCODEX_OPENCLAW_API_KEY` | +| `kimi` | `~/.kimi-code/config.toml` | `kimi-config.toml` | none — loopback placeholder | +| `gajae` | `~/.gjc/agent/models.yml` | `gajae-models.yaml` | non-secret loopback placeholder | +| `dsh` | `$DSH_HOME/settings.yaml` (default `~/.dsh/settings.yaml`) | `settings.yaml` | none — non-secret loopback bearer placeholder | +| `mcode` | `~/.minimax/config.yaml` (`MINIMAX_DATA_DIR`, then the legacy `MAVIS_DATA_DIR`, win when set; a relative value is refused) | `mcode-config.yaml` | none — loopback placeholder | +| `zcode` | `~/.zcode/v2/config.json` (`dataBaseDir` in the default-home `setting.json` relocates the root; `ZCODE_DATA_DIR` wins when set; relative values are refused) | `config.json` | none — loopback placeholder | +| `prime` | `~/.prime/agent/models.json` (`PRIME_AGENT_CODING_AGENT_DIR` wins when set; a relative value is refused) | `prime-models.json` | none — loopback placeholder | +| `aside` | `~/.aside/u//models.json` for the account Aside's own `accounts.json` names as current; an unreadable manifest is refused rather than defaulting to an account | `aside-models.json` | none — loopback placeholder | +| `raycast` | `~/.config/raycast/ai/providers.yaml` on macOS and Windows alike (Raycast does not honor `XDG_CONFIG_HOME`) | `raycast-providers.yaml` | none — loopback only, no `api_keys` entry is written | +| `omo` | `~/.omo/agent/models.json` (`OMO_CODING_AGENT_DIR`, then `SENPI_CODING_AGENT_DIR`, then `PI_CODING_AGENT_DIR` win in that order when set; a relative value is refused) | `omo-models.json` | none — loopback placeholder | +| `kilo` | first existing `kilo.jsonc`, `kilo.json`, `opencode.jsonc`, `opencode.json`, or `config.json` under `~/.config/kilo` (`XDG_CONFIG_HOME` relocates that directory); uses `kilo.jsonc` when none exists | `kilo.jsonc` | `OPENCODEX_KILO_API_KEY` | +| `commandcode` | `~/.commandcode/providers.json` (on Windows with the default home: use `HOME ?? USERPROFILE` only if nonblank and Windows-absolute, otherwise `homedir()`; a separately supplied home is preserved; append `.commandcode\providers.json`) | `providers.json` | loopback only; `apiKey: false`; no environment variable | +| `droid` | `~/.factory/settings.json` (`%USERPROFILE%\.factory\settings.json` on Windows) | `factory-settings.json` | loopback only; no environment variable | + +The managed DSH export requires DSH 0.1.0-rc.6 or newer and owns only +`llm-pi-ai.providers.opencodex`. DSH hot reloads that provider; the user's default model and +`deepseek-official` remain untouched. This export is loopback-only and carries no real credential. +DSH 0.1.7 and newer import `settings.yaml` once into the first profile that boots and then rename +it, so the dashboard integration writes the same provider into the `llm-pi-ai` row of the Desktop +profile's `$DSH_HOME/profiles/desktop/cordis.patch.yml` once that profile exists. + +opencode interpolates `{env:OPENCODEX_OPENCODE_API_KEY}`. The generated Pi and OMP exports do +not require an environment variable: each carries the literal `opencodex-loopback` placeholder. +This is load-bearing because both clients resolve `apiKey` while building their model lists and +hide the whole provider when an existing config contains an unset env reference. The proxy never +checks the generated placeholder on loopback. OMP supports provider-level headers, but this initial +integration deliberately remains loopback-only; remote `x-opencodex-api-key` wiring is deferred. + +The Raycast export is a standalone `providers.yaml` document with one `id: opencodex` element +in the `providers` sequence: `name: OpenCodex`, the proxy's `/v1` base URL, and every routed model +with its `abilities` (`tools` and `system_message` always supported, `vision` from the catalog's +input modalities, `reasoning_effort` when the model has an effort ladder, `temperature` off for +reasoning models). Custom Providers is a Raycast Pro feature, and Raycast watches the file, so a +saved change takes effect without a restart. The format is documented at +[manual.raycast.com/ai/custom-providers](https://manual.raycast.com/ai/custom-providers). No +`api_keys` entry is written, so this export is loopback-only and a non-loopback bind is refused. + +The MCode, ZCode and Prime exports are loopback-only for the same reason and likewise carry the +`opencodex-loopback` placeholder rather than a real credential. Prime Agent reads the same +`models.json` contract Pi does, so the two exports produce the same document; only the destination +differs. A relative path in any of those three environment overrides is refused, because the proxy +and the client can have different working directories and would otherwise disagree about which +file is meant. + +ZCode 3.8.1 may save runtime-derived `reasoning`, `limit.output`, and default context metadata back +into the generated `provider.opencodex.models` entries. Managed integration status treats only +those documented additions as refreshable drift. Provider identity and connection settings, +including `options.baseURL`, model membership, names, modalities, and any context limit OpenCodex +emitted authoritatively remain protected; editing them reports `conflict / foreign-edit` instead of +overwriting the file. An ownership record created by an older OpenCodex version can recover +automatically when the generated catalog is otherwise unchanged. If both the catalog and the block +changed, re-apply only after reviewing the file because the older record cannot prove which change +was ZCode-derived. + +:::caution[Merge, never replace] +`ocx export` never writes your real client config. The destination is printed for you to merge by +hand, and `--out` refuses to overwrite an existing file without `--force`, because replacing a +config destroys the other providers, agents, and MCP entries already in it. +::: + +No key is ever serialized. Configs carry either a documented environment reference or a +non-secret loopback placeholder. A loopback address (`127.0.0.1`) alone does not establish keyless +admission: check the target policy and endpoint. Selected-key model/audio commands +still require explicit key input on loopback. Set a referenced variable only when the client schema supports it and +the proxy binds beyond loopback; see +[Remote access](/reference/configuration/server/#remote-access) for how admission keys are issued. Keys for +the upstream providers themselves are a separate thing entirely, configured per +[Providers](/guides/providers/). +The generated gjc integration uses a non-secret loopback placeholder and needs no environment variable. It remains loopback-only; it does not configure remote admission credentials. + +The same payload is served by `GET /api/client-config` and rendered on the dashboard's API tab, so +the CLI, the API, and the GUI use the same bytes. + +## Runtime and configuration + +### `ocx system ...` + +Manage headless runtime settings, startup, sync, diagnostics, and updates. + +`ocx system codex-restart --yes` restarts Codex app-servers through the same module as +`ocx sync --restart-codex`. It quits and relaunches the Codex desktop app when the app launched before the current model catalog was written or this request changed +its `model_catalog_json` binding, because the model picker is built at +launch. Otherwise the app stays open, respawns its own app-server, and keeps unsaved drafts and +pending approvals. If the app or catalog state cannot be read, it takes the full restart. When +the proxy itself is running inside the Codex app, the desktop restart refuses with an actionable +message instead of promising a handoff it cannot complete. + +A `model_catalog_json` binding changed by this request also forces the desktop restart, even when the shell started after the catalog file was written. + +```bash +ocx system settings --stream-mode eager-relay +``` + +Additional system booleans take on/off: `--show-codex-credits`, `--account-picker`, +`--main-account-hard-lock`, `--ultra-fast-tier`, and `--fast-rows`. They write only +explicit fields and may combine with existing system options. Showing credits is +a display preference, not paid-credit opt-in; system Ultra Fast is separate from +provider Fast. + +Ultra Fast is an opt-in setting, default off. With `--ultra-fast-tier on`, the +generated catalog adds the Ultrafast speed choice to native `gpt-6-astra` and +`gpt-6.1-sol` (including account-bound rows), so the Codex picker offers it next to +Fast. Ultrafast requires an eligible ChatGPT plan; the catalog cannot check that, +so turn the setting on only if your plan includes it. Other models and the default +speed are unchanged. + +For routed models, sync and catalog convergence retain an existing routed +row's operator-supplied `ultrafast` entries in `service_tiers` and +`additional_speed_tiers` alongside its current Fast capability. Declarations belong +to the exact provider/model slug; they are not copied to other models. The setting +does not create missing declarations or restore removed models. Turning it off +removes Ultra Fast from ordinary routed rows and the generated native choice on the +next catalog regeneration. + +The proxy's Fast mode decides what reaches the backend: when it is unset, a selected +Ultrafast request is forwarded as `service_tier: "ultrafast"`; `fastMode: true` +replaces any tier with Fast (`priority`), and `fastMode: false` removes the tier. +Leave Fast mode unset to use Ultrafast. + +```bash +ocx system settings --json +ocx system settings --show-codex-credits on --json +ocx system settings --json +``` + +New-option writes report `{ok:true, settings: observedFields, catalogRefreshPending}`. +Ultra Fast performs same-target GET read-back because PUT omits that value. A +missing/mismatched/read-failed observation stays `verification:"unverified"` with +`unverifiedFields` and a nonzero exit after acceptance; requested values are never +substituted for observations. Combined desktop switches retain stored/effective +and apply facts. Pending catalog or deferred/refused native apply is distinct from +a saved setting. False pending is not proof that every client has reloaded. + +`ocx system update` updates OpenCodex itself. The separate Codex CLI inspection surface is: + +```bash +ocx system codex-cli-update check --json +``` + +`check` makes no package-registry request and inspects bounded configured-candidate provenance evidence, +including a redacted executable location and ownership evidence. Trusted published-launcher context authenticates +the candidate snapshot, not successful Codex execution. Because this one-shot command never executes Codex, +environment and persisted candidates remain report-only (`managed: false`, normally `selection_unattested`); +`selectionAttested` remains `false`. The JSON report exposes `candidateAvailable`, `candidateVersion`, `candidateSource`, +and `selectionAttested`. Inspecting the configured candidate requires a trusted published-launcher context; +a direct Bun/source launch has no such proof, ignores ambient and persisted candidate state, and may report +`candidate_unavailable` on POSIX. On Windows this first slice performs no candidate or configuration filesystem I/O: +only a proof-captured absolute environment candidate can receive lexical app-bundle or version-manager labels; +every other Windows candidate fails closed. Because that slice never consults persisted state, a Windows run +with no captured environment candidate reports `windows_inspection_deferred` rather than `candidate_unavailable`: +the command cannot observe whether a Codex CLI is installed, so it reports the deferral instead of asserting +that no candidate exists. The command does not execute Codex or a package manager, repair a shim, +write configuration or cache state, stop a process, or install anything. App-bundled, recognized +version-manager, unverified standalone, and ambiguous shim states are reported as unmanaged or unknown +and are never classified as managed. + +On Windows, a captured bare command such as `CODEX_CLI_PATH=codex`, a remote path, or a device path reports `candidate_path_unavailable` instead. Those cases have a captured candidate; its path is not eligible for this inspection. + +#### Explicit installation observation on Windows x64 + +```text +ocx system codex-cli-update attest [--json] +ocx system codex-cli-update attest --candidate --npm-prefix --npm-cli --node [--json] +``` + +`attest` is an opt-in, read-only observation of a Windows x64 npm installation. With no options it identifies the selected candidate from the proof-bound launcher snapshot — the configured `CODEX_CLI_PATH` or the first `codex` on the captured PATH, with an OpenCodex wrapper resolving to its renamed `codex.opencodex-real.cmd` npm backing. Supplying all four absolute paths overrides discovery; discovery only proposes paths and the held-handle observation remains the authority. `--candidate` must name the standard npm `/codex.cmd` or `/node_modules/@openai/codex/bin/codex.js`. `--npm-cli` must end in `node_modules/npm/bin/npm-cli.js`; `--node` names an explicit `node.exe`. App bundles, recognized version-manager layouts, opencodex-owned shims without their npm backing, and custom wrappers are refused. + +Native handles hold the ancestor directories and files during bounded reads. Unsupported platforms, reparse points/junctions, conflicting writers, unsafe paths, and oversized files are refused. The fixed report contains no paths: `status` is `observed` or `refused`, with `installationIdentityObserved`; `selectionAttested`, `managed`, and `applyAllowed` remain `false`. Check `status`, not just the process exit code: a reported refusal can exit 0. + +An observed identity or digest describes those files during this observation. It is not a durable update permit and does not prove the selected runtime, the past installer, effective npm configuration, or tool authenticity. The supplied Node is observed only, not proven to be the Node a launcher would select. No target is executed; no registry request, installation, configuration write, or process control occurs. The existing Windows `check` command still performs no candidate/configuration filesystem I/O. + +### `ocx config [show|get|set|unset|validate|export|import] ...` + +`ocx config [show] [--json] [--source]` displays the local configuration without a running proxy. Omitting `show` also works with either flag or both, in either order. `--source` includes diagnostic source, error, and warning fields and is only accepted for display. `--json` may precede an explicit action; it does not change which action runs. Repeated `--json` or `--source` flags and unknown arguments are rejected. + +Inspect and safely modify validated OpenCodex configuration. `show` and `get` mask secrets. Import +validates before writing and requires `--yes`. + +Display and mutation output strip credentials from proxy URLs while retaining the host and port. +`direct` and credential-free proxy values stay readable. `export` preserves credentials so the +backup can restore the configuration; store exported files as secrets. + +### Usage from a connected client + +`ocx usage` reads the connected hub with this client's enrolled data key. Human output identifies the hub source and client-key scope; `--json` returns the same scoped data. Range, surface, provider/model filters and custom `--since`/`--until` bounds remain available. Account breakdowns and other clients' records are not shared. An old or unavailable hub produces an explicit error instead of substituting local usage; upgrade the hub if it does not support this read. + +The read-only data-plane endpoint is `GET /v1/usage`, using `x-opencodex-api-key` with a configured client key. Environment-wide and admin keys are refused. It accepts `range`, `surface`, `provider`, `model`, `since`, and `until`; unknown/repeated options and caller-selected key IDs are rejected. Oversized skipped rows retain the explicit incomplete-history warning. + +## Explain a listed request + +Human `ocx logs` output includes `id=`. Pass that value to `ocx logs explain ` to inspect routing decisions. Rows without an ID or with control characters in their ID omit the field instead of displaying a different lookup key. JSON and JSONL output retain their existing schema. + +## Routing profile lookup status + +`ocx route policy show ` exits 4 when the profile does not exist. Missing or invalid command arguments exit 2. Scripts can distinguish a missing profile from incorrect usage. + +## Upstream error details + +When an upstream error envelope contains several message fields, OpenCodex uses the first nonblank string in its established priority order. Empty or malformed fields no longer hide a valid fallback diagnostic. + +### Forced Claude Code subagent model + +The Subagents page offers **Force all subagents onto one model**, off by default. Select an exposed roster-style id, such as `combo/tev-auto`, then enable the switch. The roster is offered first; unavailable saved roster entries cannot be force targets. + +`ocx agent subagents force combo/tev-auto` sets `claudeCode.subagentModelForce`; `ocx agent subagents force -` clears it. `ocx agent status` reports the setting. `GET /api/subagent-models` returns `force`, `forceAvailable`, and `forceStatus`; `PUT` accepts `{ "force": "combo/tev-auto" }` or `{ "force": null }` without changing the roster. Omitting `force` leaves it unchanged. Invalid or unexposed targets are rejected on write; stale targets are reported and skipped at launch. + +This takes effect on the **next routed `ocx claude` launch**, injecting `CLAUDE_CODE_SUBAGENT_MODEL` as an explicit proxy alias (with `[1m]` only for an authoritative million-token window; native Claude targets use a reversible native alias) and `CLAUDE_CODE_SUBAGENT_MODEL_FORCE=1`. Each nonempty shell-exported variable independently wins. Native launches inject neither variable; plain `claude` is not affected. No plugin files or `settings.json` are modified by this setting. + +Claude Code **2.1.257 or newer** is required for FORCE. Plugin and built-in agents (including Explore/Plan) and per-call model arguments are overridden. Forks and subagent skills with `model: inherit` keep the main conversation model. The main loop and Haiku/small-fast sidecars are unaffected. Existing roster files remain available. + +The dashboard warns about old or unknown CLI versions, unavailable targets, and either variable already present in `settings.json` → `env` (which overrides launch env). Detection is read-only and server-local: it cannot inspect another launch shell, another machine, or project-local settings. An unknown result is not proof of force support. diff --git a/docs-site/src/content/docs/reference/configuration/routing.md b/docs-site/src/content/docs/reference/configuration/routing.md index 0a299f7cf93..1534eac27ed 100644 --- a/docs-site/src/content/docs/reference/configuration/routing.md +++ b/docs-site/src/content/docs/reference/configuration/routing.md @@ -368,7 +368,8 @@ Returned history and route-decision payloads expose only masked request metadata (for example opaque `apiKeyId` labels). They do not include credentials, raw prompt bodies, or provider secrets. -CLI: `ocx logs explain `, `ocx logs rebuild-index`, +CLI: `ocx logs history`, `ocx logs get `, +`ocx logs explain `, `ocx logs rebuild-index`, `ocx logs index-status`, `ocx route policy list | show | dry-run | evaluate`. ## Migration diff --git a/scripts/test-layout/layout.json b/scripts/test-layout/layout.json index e93ae61b72a..35a54e225e7 100644 --- a/scripts/test-layout/layout.json +++ b/scripts/test-layout/layout.json @@ -24,4 +24,1916 @@ "provider-anthropic-instance.test.ts": "providers", "config-anthropic-instance-pool.test.ts": "config", "oauth-anthropic-instance-registration.test.ts": "oauth", "oauth-anthropic-instance-refresh.test.ts": "oauth", "model-costs-pricing-cache.test.ts": "server", "model-costs-prompt-length-pricing.test.ts": "server", "cli-models-prompt-length-pricing.test.ts": "cli", "usage-prompt-length-pricing.test.ts": "usage", "claude-picker-upload.test.ts": "claude-integration", "claude-picker-linger.test.ts": "claude-integration", "messages-native-scope.test.ts": "claude-integration", "catalog-auto-review-row.test.ts": "codex-integration", + "codex-use-remaining-quota.test.ts": "codex-integration", + "cli-log-view-filter.test.ts": "cli", "cli-usage-model-search.test.ts": "cli", "cli-usage-top.test.ts": "cli", "cli-companion-usage.test.ts": "cli", "cli-account-key-quota.test.ts": "cli", "cli-usage-compare.test.ts": "cli", + "cli-log-history.test.ts": "cli", + "cli-observe-snapshot.test.ts": "cli", "cli-access-data-plane.test.ts": "cli", "cli-access-key-guard.test.ts": "cli", "cli-access-rename.test.ts": "cli", + "cli-access-audio.test.ts": "cli", "cli-access-audio-live.test.ts": "cli", "cli-log-follow.test.ts": "cli", "cli-injection-follow.test.ts": "cli", + "cli-usage-scope.test.ts": "cli", "cli-system-health.test.ts": "cli", "cli-companion-timeline.test.ts": "cli", "server-cli-key-probe-admission.test.ts": "server", + "cli-integration-preview.test.ts": "cli", "cli-integration-droid.test.ts": "cli", "cli-integration-journal.test.ts": "cli", "cli-aside-sync.test.ts": "cli", + "cli-claude-desktop-profile.test.ts": "cli", "cli-integration-cursor.test.ts": "cli", "cli-remote-workspace-hub.test.ts": "cli", "cli-storage-policy-fields.test.ts": "cli", "cli-link-force.test.ts": "cli", + "cli-account-policy.test.ts": "cli", "cli-account-login-options.test.ts": "cli", "cli-logout-runtime.test.ts": "cli", "cli-agent-settings.test.ts": "cli", + "cli-v2-runtime.test.ts": "cli", "cli-agent-runtime-settings.test.ts": "cli", "cli-system-settings-parity.test.ts": "cli", + "cli-catalog-command-result.test.ts": "cli", "cli-models-local-result.test.ts": "cli", "cli-models-custom-runtime.test.ts": "cli", "cli-models-order.test.ts": "cli", + "cli-models-display-name.test.ts": "cli", "cli-route-policy-write.test.ts": "cli", "cli-combo-parity.test.ts": "cli", "cli-combo-stats.test.ts": "cli", + "cli-json-input.test.ts": "cli", "cli-provider-lifecycle-runtime.test.ts": "cli", "cli-provider-settings.test.ts": "cli", "cli-provider-batch.test.ts": "cli", + "cli-provider-result.test.ts": "cli", "cli-provider-sync-result.test.ts": "cli", + "cli-capability-integration-workflows.test.ts": "cli", "cli-capability-account-workflows.test.ts": "cli", "cli-capability-agent-workflows.test.ts": "cli", "cli-capability-operation-workflows.test.ts": "cli", + "cli-capability-provider-workflows.test.ts": "cli", "cli-capability-access-workflows.test.ts": "cli", "cli-capability-lab-workflows.test.ts": "cli", "skill-ocx-workflows.test.ts": "ci-workflows", + "cli-capability-data.test.ts": "cli", "skill-ocx-generated.test.ts": "ci-workflows", + "cli-update-restart.test.ts": "cli", "cli-update-restart-child.test.ts": "cli", "cli-update-restart-transport.test.ts": "cli", "cli-update-restart-home.test.ts": "cli", + "cli-update-restart-service-record.test.ts": "cli", "cli-update-restart-supervision.test.ts": "cli", "cli-update-restart-admission.test.ts": "cli", "cli-update-restart-desktop-service.test.ts": "cli", + "codex-shim-overlay.test.ts": "codex-integration", "codex-shim-migration.test.ts": "codex-integration", + "codex-shim-overlay-transaction.test.ts": "codex-integration", "codex-shim-overlay-readiness.test.ts": "codex-integration", + "codex-shim-overlay-candidates.test.ts": "codex-integration", + "gui-pair-delivery.test.ts": "gui", + "usage-antigravity-55.test.ts": "usage", + "provider-antigravity-wire-snapshot.test.ts": "providers", + "antigravity-discovered-families.test.ts": "adapters/google", + "provider-antigravity-effort-families.test.ts": "providers", + "provider-antigravity-family-catalog.test.ts": "providers", + "claude-subagent-model-force.test.ts": "claude-integration", "claude-config-home-isolation.test.ts": "claude-integration", + "subagent-model-force-api.test.ts": "server", + "caller-session-identity.test.ts": "server", + "caller-session-ingress.test.ts": "server", + "agent-subagent-force.test.ts": "cli", + "compaction-event-ownership.test.ts": "responses", + "zed-retained-budget.test.ts": "providers", + "jev-decision-scope.test.ts": "server", + "server-combo-plan-model-refusal.test.ts": "server", + "codex-main-token-invalidated.test.ts": "codex-integration", + "codex-main-grant-refusal.test.ts": "codex-integration", + "responses-alternate-main-cancellation.test.ts": "responses", + "codex-shim-path-readiness.test.ts": "codex-integration", + "codex-shim-fnm.test.ts": "codex-integration", + "claude-intercept-cleanup.test.ts": "claude-integration", + "management-droid-reasoning-defaults.test.ts": "server", + "droid-reasoning-defaults.test.ts": "responses", + "claude-intercept-on-demand.test.ts": "claude-integration", + "main-account-hard-lock-thresholds.test.ts": "codex-integration", + "main-account-external-usage.test.ts": "codex-integration", + "jev-decision-model-config.test.ts": "routing", + "cli-combo-partial-update.test.ts": "cli", + "owner-registry-acl.test.ts": "config", + "minimax-combo-image-input.test.ts": "providers", + "web-search-forced-declaration.test.ts": "web-search", + "claude-devin-output-order.test.ts": "claude-integration", + "codex-config-preservation.test.ts": "codex-integration", + "codex-credits.test.ts": "codex-integration", + "codex-credits-settings.test.ts": "codex-integration", + "codex-credits-probes.test.ts": "codex-integration", + "codex-credits-after-limit.test.ts": "codex-integration", + "codex-pool-credit-policy.test.ts": "codex-integration", + "codex-sidecar-credit-policy.test.ts": "codex-integration", + "codex-credits-after-limit-main.test.ts": "codex-integration", + "service-runtime-preflight.test.ts": "service", "service-desktop-runtime-preflight.test.ts": "service", + "service-desktop-login-registration.test.ts": "service", "service-desktop-startup-health.test.ts": "service", "service-desktop-startup-linux.test.ts": "service", "service-desktop-startup.test.ts": "service", "service-desktop-supervision-windows.test.ts": "service", + "startup-health-packaged-probe.test.ts": "server", + "discovered-native-models.test.ts": "codex-integration", + "responses-hosted-image-delivery.test.ts": "responses", + "responses-hosted-image-display.test.ts": "responses", + "responses-hosted-image-limits.test.ts": "responses", + "dsh-login.test.ts": "oauth", + "dsh-account.test.ts": "providers", + "dsh-account-adapter.test.ts": "adapters", + "cursor-local-installer.test.ts": "providers/cursor", + "codex-quota-query-backoff.test.ts": "codex-integration", + "pnpm-command-isolation.test.ts": "update", "provider-antigravity-quota-retry.test.ts": "providers", "project-config-warning-snapshot.test.ts": "codex-integration", "codex-quota-auto-refresh-generation.test.ts": "codex-integration", "codex-account-clear-paused.test.ts": "codex-integration", + "low-quota-protection.test.ts": "codex-integration", + "bun-runtime-preflight.test.ts": "lib", + "responses-compaction-recovery.test.ts": "responses", "responses-canonical-nonstream.test.ts": "responses", "compaction-recovery-settings.test.ts": "config", "responses-compaction-recovery-policy.test.ts": "responses", "plugin-loader.test.ts": "lib", "plugin-upstream-hooks.test.ts": "lib", + "cli-kiro-auto-selection.test.ts": "cli", "codebuddy-live-models.test.ts": "providers", "kiro-auto-selection.test.ts": "providers/kiro", "kiro-quota-metrics.test.ts": "providers/kiro", "management-provider-request-pacing.test.ts": "server", + "cli-restart-handoff.test.ts": "cli", + "restart-replacement.test.ts": "server", "deepseek-artifact-tool-schema.test.ts": "providers", + "client-config-export-output-limit.test.ts": "config", "qoder-client.test.ts": "clients", "responses-skills-snapshot.test.ts": "responses", "responses-code-mode-mcp-direct.test.ts": "responses", "local-read-response-proof.test.ts": "server", + "claude-desktop-system-proxy.test.ts": "claude-integration", "codex-config-drift-heal.test.ts": "codex-integration", + "openai-chat-serialized-tool-call-scaling.test.ts": "adapters/openai", + "openai-chat-tool-call-id-remint.test.ts": "adapters/openai", + "coding-agent-json-lines-scaling.test.ts": "providers", + "usage-snapshot-digest-reuse.test.ts": "usage", + "worker-embed.test.ts": "lib", + "worker-embed-coverage.test.ts": "lib", + "jev-stats.test.ts": "usage", + "responses-devin-401-replay.test.ts": "responses", + "responses-oauth-refresh-capacity.test.ts": "responses", + "responses-grok-devin-preflight.test.ts": "responses", + "deepseek-quota-currency.test.ts": "providers", + "mimo-token-plan-capacity.test.ts": "providers", + "command-code-tool-text-prose-split.test.ts": "providers", + "cli-effort-slug.test.ts": "cli", + "grok-47-build-fast-metadata.test.ts": "providers/xai", + "grok-47-fast-model.test.ts": "providers/xai", + "grok-47-fast-model-wire.test.ts": "providers/xai", + "abort-idle-deadline.test.ts": "lib", + "tool-envelope-echo-whole-line.test.ts": "adapters", + "abort-race.test.ts": "adapters", + "account-import.test.ts": "server", + "account-pool-management-api.test.ts": "server", + "link-listener-admission.test.ts": "server", "link-management-relay.test.ts": "server", + "link-listener-lifecycle.test.ts": "server", "link-listener-mutation.test.ts": "server", + "link-join-route.test.ts": "server", + "core-link-boundary.test.ts": "lab", + "acl-error-classification.test.ts": "lib", + "active-registry-admission.test.ts": "codex-integration", "active-turn-disconnect.test.ts": "codex-integration", + "adapter-buffered-tool-conformance.test.ts": "adapters", + "adapter-error-inline.test.ts": "adapters", + "adapter-event-oauth-failover.test.ts": "oauth", + "adapter-inner-send-budget-wiring.test.ts": "adapters", + "adapter-inner-send-budget.test.ts": "adapters", + "adapter-input-media-guard.test.ts": "adapters", + "adapter-registry-authority.test.ts": "adapters", + "adapter-resolve.test.ts": "server", + "inference-client-wire.test.ts": "server", + "inference-attempt.test.ts": "server", + "inference-final-log.test.ts": "server", + "inference-send-budget.test.ts": "server", + "inference-client-encoder-delivery.test.ts": "server", + "adapter-tool-conformance.test.ts": "adapters", + "zed-hosted-provider.test.ts": "providers", + "adapter-usage.test.ts": "adapters", + "agent-driven.test.ts": "cli", + "agent-task-recovery-cache.test.ts": "server", + "agent-task-recovery-combo.test.ts": "server", + "agent-task-recovery-fallback.test.ts": "server", + "agent-task-recovery-security.test.ts": "server", + "agent-task-recovery.test.ts": "server", + "alias-management-api.test.ts": "server", + "alibaba-intl-token-plan.test.ts": "gui", + "alibaba-region-backup.test.ts": "providers", + "alibaba-region-migration.test.ts": "providers", + "alibaba-region-startup.test.ts": "providers", + "alibaba-token-plan-responses-optin.test.ts": "providers", + "alibaba-token-plan-wire-defaults.test.ts": "providers", + "always-on-429-failover.test.ts": "routing", + "ambiguous-resend-composition.test.ts": "lib", + "ambiguous-resend-gate.test.ts": "lib", + "anthropic-client-identity.test.ts": "adapters/anthropic", + "anthropic-account-metadata.test.ts": "adapters/anthropic", + "anthropic-account-pool.test.ts": "adapters/anthropic", + "anthropic-account-pause-outbound.test.ts": "adapters/anthropic", + "anthropic-account-pause.test.ts": "adapters/anthropic", + "anthropic-account-threshold.test.ts": "adapters/anthropic", + "anthropic-combo-account-cooldown.test.ts": "adapters/anthropic", + "cli-alias-json.test.ts": "cli", + "cli-anthropic-account-threshold.test.ts": "cli", + "anthropic-model-routes.test.ts": "adapters/anthropic", + "anthropic-agentrouter-language-framing.test.ts": "adapters/anthropic", + "anthropic-baseurl-override.test.ts": "adapters/anthropic", + "anthropic-compatible-stream.test.ts": "adapters/anthropic", + "anthropic-message-stop-termination.test.ts": "adapters/anthropic", + "anthropic-cooldown-recovery.test.ts": "adapters/anthropic", + "anthropic-empty-content.test.ts": "adapters/anthropic", + "anthropic-eof-tolerance.test.ts": "adapters/anthropic", + "anthropic-error-body.test.ts": "adapters/anthropic", + "anthropic-error-stop-reason.test.ts": "adapters/anthropic", "anthropic-thinking-usage.test.ts": "adapters/anthropic", + "anthropic-fast-opt-in.test.ts": "adapters/anthropic", + "anthropic-fast-speed.test.ts": "adapters/anthropic", + "anthropic-hardening.test.ts": "adapters/anthropic", + "anthropic-image-guard.test.ts": "adapters/anthropic", + "anthropic-image-normalize.test.ts": "adapters/anthropic", + "anthropic-image-retry-e2e.test.ts": "adapters/anthropic", + "anthropic-image-retry.test.ts": "adapters/anthropic", + "anthropic-sonnet-5-5-contract.test.ts": "adapters/anthropic", "anthropic-haiku-5-5-contract.test.ts": "adapters/anthropic", + "anthropic-output-maxima.test.ts": "adapters/anthropic", + "anthropic-parallel-tool-disable.test.ts": "adapters/anthropic", + "anthropic-pool-toggle-copy.test.ts": "adapters/anthropic", + "anthropic-quorum-cache.test.ts": "routing", + "anthropic-quota-dispatch.test.ts": "adapters/anthropic", + "anthropic-model-weekly-admission.test.ts": "adapters/anthropic", + "anthropic-429-policy.test.ts": "adapters/anthropic", + "anthropic-ratelimit-headers.test.ts": "adapters/anthropic", + "anthropic-reasoning.test.ts": "adapters/anthropic", + "anthropic-reset-grants.test.ts": "adapters/anthropic", + "anthropic-sidecar-account-failover.test.ts": "adapters/anthropic", + "anthropic-stream-hardening.test.ts": "adapters/anthropic", + "anthropic-tail-guard.test.ts": "adapters/anthropic", + "anthropic-progress-updates.test.ts": "adapters/anthropic", + "anthropic-thinking-signature.test.ts": "adapters/anthropic", + "anthropic-opaque-strip.test.ts": "adapters/anthropic", + "anthropic-tool-call-id.test.ts": "adapters/anthropic", + "anthropic-messages-passthrough.test.ts": "adapters/anthropic", + "anthropic-beta-allowlist.test.ts": "adapters/anthropic", + "anthropic-beta-body-pairs.test.ts": "adapters/anthropic", + "anthropic-messages-passthrough-oauth.test.ts": "adapters/anthropic", + "anthropic-tool-declaration-constraints.test.ts": "adapters/anthropic", + "anthropic-tool-schema.test.ts": "adapters/anthropic", + "antigravity-baseurl-override.test.ts": "adapters/google", + "antigravity-refusal.test.ts": "adapters/google", + "antigravity-static-catalog.test.ts": "adapters/google", + "api-access-endpoints.test.ts": "server", + "api-catalog-route.test.ts": "server", + "api-codex-log-guard-compact.test.ts": "server", + "api-codex-log-guard-protection.test.ts": "server", + "api-codex-log-guard.test.ts": "server", + "api-debug.test.ts": "server", + "api-key-attribution.test.ts": "server", + "api-key-catalog-authority.test.ts": "providers", + "api-key-model-scope.test.ts": "server", + "api-key-scope-alpha-search.test.ts": "server", + "api-key-scope-audio.test.ts": "server", + "api-key-scope-images.test.ts": "server", + "api-key-scope-live.test.ts": "server", + "api-key-selection-capture.test.ts": "providers", + "api-keys-routes.test.ts": "server", + "api-storage-cleanup.test.ts": "storage", + "api-storage-policy-already-running.test.ts": "storage", + "api-storage-policy-mutation-busy.test.ts": "storage", + "api-storage-policy-put-race.test.ts": "storage", + "api-storage-policy-run.test.ts": "storage", + "api-storage-policy.test.ts": "storage", + "api-storage.test.ts": "storage", + "api-usage.test.ts": "server", + "app-owned-memory.test.ts": "codex-integration", + "apply-patch-envelope.test.ts": "responses", + "artifacts-prune.test.ts": "images", + "artifacts-ssrf.test.ts": "images", + "aside-client.test.ts": "providers", + "aside-profiles-routes.test.ts": "server", + "assert-mergeable-review.test.ts": "ci-workflows", + "audio-client.test.ts": "server", + "audio-dictation.test.ts": "server", + "audio-transcriptions.test.ts": "server", + "auto-compact-budget.test.ts": "providers", + "autostart-health.test.ts": "service", + "azure-adapter.test.ts": "providers", + "azure-model-router-tool-schema.test.ts": "providers", + "bare-echo-alias.test.ts": "responses", + "baseten-provider.test.ts": "providers", + "bearer-admission-routed-provider.test.ts": "codex-integration", + "bounded-body.test.ts": "server", + "brand-favicons.test.ts": "ci-workflows", + "bridge-legacy-shell-normalization.test.ts": "adapters", + "bridge-lifecycle.test.ts": "adapters", + "bridge-live-delivery.test.ts": "server", + "bridge-nonstreaming-terminal.test.ts": "adapters", + "bridge-raw-reasoning-hidden.test.ts": "adapters", + "bridge-reasoning-replay-batch.test.ts": "adapters", + "bridge-stall.test.ts": "adapters", + "bridge-terminal-singleness.test.ts": "adapters", + "bridge.test.ts": "adapters", + "buffered-response-shape-guards.test.ts": "adapters", + "build-desktop-icon-set.test.ts": "ci-workflows", + "build-release-changelog.test.ts": "ci-workflows", + "bump-dev-version.test.ts": "ci-workflows", + "bun-runtime.test.ts": "ci-workflows", + "bun-stream-caps.test.ts": "lib", + "cache-diagnostic.test.ts": "usage", + "cancel-body-on-abort.test.ts": "server", + "catalog-auto-refresh-client-fanout.test.ts": "codex-integration", "catalog-auto-refresh-scheduler.test.ts": "codex-integration", + "catalog-cursor-search.test.ts": "codex-integration", + "catalog-custom-ordering.test.ts": "codex-integration", + "catalog-duplicate-slug-dedup.test.ts": "codex-integration", + "catalog-free-pricing-status.test.ts": "codex-integration", + "catalog-full-picker-order.test.ts": "codex-integration", + "catalog-gated-native-suppression-reason.test.ts": "codex-integration", + "catalog-go-exact-efforts.test.ts": "codex-integration", + "catalog-hub-context-window.test.ts": "codex-integration", + "catalog-input-modality-enum.test.ts": "codex-integration", + "catalog-llamacpp-capabilities.test.ts": "codex-integration", + "catalog-modelalias-unique-sync.test.ts": "codex-integration", + "catalog-oauth-observation.test.ts": "codex-integration", + "catalog-opencode-go-context-window.test.ts": "codex-integration", + "catalog-remote-pull.test.ts": "codex-integration", + "catalog-retain-models.test.ts": "codex-integration", + "catalog-routed-comp-hash.test.ts": "codex-integration", + "catalog-seed-window-fill.test.ts": "codex-integration", + "catalog-slug-uniqueness-boundary.test.ts": "codex-integration", + "catalog-verbosity-default.test.ts": "codex-integration", + "catalog-vision-sidecar-modalities.test.ts": "codex-integration", + "catalog-zero-credit-picker.test.ts": "codex-integration", + "chat-completions-deferred-tools.test.ts": "responses", "passthrough-deferred-tools.test.ts": "responses", + "chat-completions-endpoint.test.ts": "responses", + "chat-completions-pool-mode.test.ts": "responses", + "chat-conversation-affinity.test.ts": "responses", + "chat-inbound-developer-position.test.ts": "responses", + "protocol-contract.test.ts": "responses", + "protocol-features.test.ts": "responses", + "protocol-opaque-state.test.ts": "responses", + "protocol-baseline.test.ts": "responses", + "protocol-dto.test.ts": "responses", + "protocol-path.test.ts": "responses", + "protocol-trace.test.ts": "responses", + "protocol-plan.test.ts": "responses", + "protocol-plan-snapshot.test.ts": "responses", + "protocol-shadow-plan.test.ts": "responses", + "protocol-envelope.test.ts": "responses", + "protocol-guard.test.ts": "responses", + "protocol-ingress-guard.test.ts": "responses", + "protocol-direct-encoders-chat.test.ts": "responses", + "protocol-direct-encoders-stall-disabled.test.ts": "responses", + "protocol-direct-encoders-local-upstream.test.ts": "responses", + "protocol-direct-encoders-messages.test.ts": "responses", + "protocol-chat-ir-parity.test.ts": "responses", + "protocol-antigravity-direct-chat.test.ts": "responses", + "protocol-antigravity-direct-eligibility.test.ts": "responses", + "protocol-messages-ir-parity.test.ts": "responses", + "protocol-antigravity-direct-messages.test.ts": "responses", + "chat-native-combo.test.ts": "responses", "jev-initial-effort-wire.test.ts": "responses", + "messages-native-eligibility.test.ts": "responses", + "responses-first-send-reservation.test.ts": "responses", "responses-first-send-spend-policy.test.ts": "responses", "responses-dispatch-receipt.test.ts": "responses", "responses-hosted-send-hop.test.ts": "responses", "responses-hosted-send-producer.test.ts": "responses", "responses-hosted-send-reservation.test.ts": "responses", "responses-hosted-send-round-parity.test.ts": "responses", "responses-hosted-send-unsent-hop.test.ts": "responses", "responses-hosted-send-ws.test.ts": "responses", + "messages-native-bridge-policy.test.ts": "responses", + "messages-native-oauth-eligibility.test.ts": "responses", + "chat-inbound-reasoning-none.test.ts": "responses", + "chat-native-decline-reason.test.ts": "responses", + "chat-inbound-reasoning-replay.test.ts": "responses", + "chat-inline-document-bytes.test.ts": "responses", + "chat-json-sse-fallback.test.ts": "responses", + "chat-media-translation.test.ts": "responses", + "chat-native-developer-role.test.ts": "responses", + "chat-native-reasoning-replay.test.ts": "responses", + "chat-native-reasoning-scope.test.ts": "responses", + "chat-native-image-normalization.test.ts": "responses", + "chat-native-spend.test.ts": "responses", + "chat-refusal-scope.test.ts": "responses", + "chat-refusal.test.ts": "responses", + "chat-responses-control-integration.test.ts": "responses", + "chat-responses-control-scope.test.ts": "responses", + "chat-tool-choice-allowed-tools.test.ts": "responses", + "chatgpt-device-auth.test.ts": "oauth", + "chatgpt-oauth.test.ts": "oauth", + "chatgpt-token-expiry.test.ts": "oauth", + "chatgpt-token-boundaries.test.ts": "oauth", + "chutes-provider.test.ts": "providers", + "ci-bun-crash-classifier.test.ts": "ci-workflows", + "ci-crash-disposition.test.ts": "ci-workflows", + "ci-gui-typecheck-gate.test.ts": "ci-workflows", + "ci-privacy-gate.test.ts": "ci-workflows", + "ci-review-lanes.test.ts": "ci-workflows", + "ci-scope-reduction.test.ts": "ci-workflows", + "ci-scope-gaps.test.ts": "ci-workflows", + "ci-shard-balance.test.ts": "ci-workflows", + "ci-structure-gate.test.ts": "ci-workflows", + "ci-workflows.test.ts": "ci-workflows", + "citation-markers.test.ts": "responses", + "visualization-directives.test.ts": "responses", + "cl01-claude-outbound-review-regressions.test.ts": "routing", + "cl01-openai-chat-review-regressions.test.ts": "routing", + "cl01-review-regressions.test.ts": "routing", + "claude-529-mapping.test.ts": "claude-integration", + "claude-agent-startup-sync.test.ts": "claude-integration", + "claude-agents-inject-client.test.ts": "claude-integration", + "claude-agents-inject.test.ts": "claude-integration", + "claude-alias.test.ts": "claude-integration", + "claude-auth-detect.test.ts": "claude-integration", + "claude-auth-mode.test.ts": "claude-integration", + "claude-authmode-migration.test.ts": "claude-integration", + "claude-cli-adapter.test.ts": "providers", + "claude-cli-client-http.test.ts": "providers", + "claude-cli-efficiency.test.ts": "providers", + "claude-cli-tool-capture.test.ts": "providers", + "claude-cli-usage-admission.test.ts": "providers", + "claude-cli.test.ts": "claude-integration", + "claude-config-first-party.test.ts": "cli", + "claude-code-thought-signature-scope.test.ts": "claude-integration", + "claude-compatibility.test.ts": "claude-integration", + "claude-context-windows.test.ts": "claude-integration", + "claude-desktop-1m.test.ts": "claude-integration", + "claude-desktop-cli.test.ts": "claude-integration", + "claude-desktop-config-path.test.ts": "claude-integration", + "claude-desktop-discovery.test.ts": "claude-integration", + "claude-desktop-first-party.test.ts": "claude-integration", + "claude-desktop-first-party-guards.test.ts": "claude-integration", + "claude-desktop-mode-explanation.test.ts": "claude-integration", + "claude-desktop-picker.test.ts": "claude-integration", + "claude-desktop-picker-profile.test.ts": "claude-integration", + "claude-desktop-picker-routes.test.ts": "claude-integration", + "claude-desktop-native-context.test.ts": "claude-integration", + "claude-desktop-policy.test.ts": "claude-integration", + "claude-cli-picker.test.ts": "claude-integration", + "claude-cli-picker-surface.test.ts": "claude-integration", + "claude-picker-bootstrap.test.ts": "claude-integration", "claude-picker-ca.test.ts": "claude-integration", "claude-picker-ca-store.test.ts": "claude-integration", + "claude-picker-listener.test.ts": "claude-integration", "claude-picker-models.test.ts": "claude-integration", "claude-picker-recovery.test.ts": "claude-integration", + "claude-picker-runtime.test.ts": "claude-integration", "claude-picker-startup.test.ts": "claude-integration", "claude-picker-trust.test.ts": "claude-integration", + "claude-desktop-remote-hub.test.ts": "claude-integration", + "claude-dotenv-provenance-transport.test.ts": "claude-integration", + "claude-estimate-projection.test.ts": "claude-integration", + "claude-first-party-agent-sync.test.ts": "claude-integration", + "claude-first-party-union.test.ts": "claude-integration", + "claude-gateway-cache.test.ts": "claude-integration", + "claude-inbound-cache-stabilize.test.ts": "claude-integration", "claude-inbound-token-footer.test.ts": "claude-integration", + "claude-inbound-debug.test.ts": "claude-integration", + "claude-inbound.test.ts": "claude-integration", "claude-inbound-tool-reference.test.ts": "claude-integration", "claude-native-reasoning-continuity.test.ts": "claude-integration", "claude-native-reasoning-provenance.test.ts": "claude-integration", + "claude-output-schema-strict.test.ts": "claude-integration", + "claude-intercept-integration.test.ts": "server", + "claude-intercept-local-ca.test.ts": "claude-integration", + "claude-intercept-local-ca-files.test.ts": "claude-integration", + "claude-intercept-local-ca-windows.test.ts": "claude-integration", + "claude-intercept-model-bindings.test.ts": "claude-integration", + "claude-intercept-proxy.test.ts": "claude-integration", + "claude-intercept-client-class.test.ts": "claude-integration", + "claude-intercept-proxy-auth.test.ts": "claude-integration", + "claude-model-default-labels.test.ts": "claude-integration", "claude-intercept-settings.test.ts": "claude-integration", "claude-intercept-no-proxy.test.ts": "claude-integration", + "claude-management-api.test.ts": "claude-integration", + "claude-manual-env.test.ts": "gui", + "claude-messages-endpoint.test.ts": "claude-integration", + "claude-messages-thread.test.ts": "claude-integration", + "messages-native.test.ts": "claude-integration", + "messages-native-decline-trace.test.ts": "claude-integration", + "messages-native-oauth.test.ts": "claude-integration", + "messages-native-opaque-state.test.ts": "claude-integration", + "messages-surface-matrix.test.ts": "claude-integration", "claude-long-context-eligibility.test.ts": "claude-integration", + "claude-context-accounting.test.ts": "claude-integration", "claude-model-info.test.ts": "claude-integration", + "claude-models-discovery.test.ts": "claude-integration", + "claude-native-affinity.test.ts": "claude-integration", + "claude-native-passthrough.test.ts": "claude-integration", + "claude-native-rate-limit-headers.test.ts": "claude-integration", + "claude-outbound.test.ts": "claude-integration", + "claude-prompt-too-long.test.ts": "claude-integration", + "claude-shell-hook.test.ts": "claude-integration", + "claude-sidecar-override.test.ts": "claude-integration", + "claude-source-envelope.test.ts": "claude-integration", + "claude-system-env-auto.test.ts": "claude-integration", + "cleanup-orphaned-workflows.test.ts": "ci-workflows", + "clearable-deadline.test.ts": "lib", + "cli-account-alias-target.test.ts": "cli", + "cli-account-cancel-flow.test.ts": "cli", + "cli-account-kiro-device.test.ts": "cli", "cli-account-orca-import.test.ts": "cli", + "cli-account-pin-drain.test.ts": "cli", + "cli-account-pool-verbs.test.ts": "cli", + "cli-account-threshold.test.ts": "cli", + "cli-account-verify-status.test.ts": "cli", + "cli-account.test.ts": "cli", + "cli-capabilities-arguments.test.ts": "cli", + "cli-capabilities.test.ts": "cli", + "cli-api-protocols.test.ts": "cli", + "cli-catalog-prewarm.test.ts": "cli", + "cli-ensure-readiness.test.ts": "cli", + "cli-codex-cli-update.test.ts": "cli", + "cli-codex-log-guard-compact.test.ts": "cli", + "cli-codex-log-guard-protection.test.ts": "cli", + "cli-codex-log-guard.test.ts": "cli", + "cli-companion.test.ts": "cli", + "cli-config-bom.test.ts": "cli", + "cli-config-command.test.ts": "cli", + "cli-config-default-show.test.ts": "cli", + "cli-config-show-client.test.ts": "cli", + "cli-connect-readiness.test.ts": "cli", + "cli-dispatch.test.ts": "cli", + "cli-client-start-fence.test.ts": "cli", + "cli-ensure-client-state.test.ts": "cli", + "cli-client-start-owner-e2e.test.ts": "cli", + "cli-dto-fidelity.test.ts": "cli", + "cli-export-command.test.ts": "cli", + "cli-head.test.ts": "cli", + "cli-headless-parity.test.ts": "cli", + "cli-help.test.ts": "cli", + "cli-help-paths.test.ts": "cli", + "cli-help-navigation.test.ts": "cli", + "cli-help-recovery.test.ts": "cli", + "cli-integer-options.test.ts": "cli", + "cli-init-port.test.ts": "cli", + "cli-json-contract.test.ts": "cli", + "cli-logs-request-id.test.ts": "cli", + "cli-management-auth.test.ts": "cli", + "cli-models-free-only.test.ts": "cli", + "cli-models-price.test.ts": "cli", + "cli-models-reasoning.test.ts": "cli", + "cli-models-runtime-dispatch.test.ts": "cli", "cli-models-set.test.ts": "cli", + "cli-models.test.ts": "cli", + "cli-native-profile.test.ts": "cli", + "cli-observe-logs.test.ts": "cli", + "cli-provider.test.ts": "cli", + "cli-ready-subprocess.test.ts": "cli", + "cli-ready.test.ts": "cli", + "cli-registry.test.ts": "cli", + "cli-resolve-subprocess.test.ts": "cli", + "cli-resolve.test.ts": "cli", + "cli-restart-health.test.ts": "cli", + "cli-restore-back.test.ts": "cli", + "cli-route-policy-not-found.test.ts": "cli", + "cli-start-auxiliary-bind.test.ts": "cli", + "cli-start-journal-order.test.ts": "cli", + "sibling-home-client-sync.test.ts": "cli", + "cli-status-hub-state.test.ts": "cli", + "cli-status-json.test.ts": "cli", + "cli-status-oauth-health.test.ts": "cli", + "cli-stop-json.test.ts": "cli", + "cli-storage-inspect.test.ts": "cli", + "cli-transport-honesty.test.ts": "cli", + "cli-update-badge.test.ts": "cli", + "cli-usage-hub.test.ts": "cli", + "cli-usage-report.test.ts": "cli", + "cli-version-skew.test.ts": "cli", + "client-config-export-new-clients.test.ts": "config", + "client-config-export.test.ts": "config", + "client-config-new-clients.test.ts": "config", + "client-injection-guard.test.ts": "codex-integration", + "cli-link-child.test.ts": "cli", + "cline-pass-deepseek-v4-tool-replay.test.ts": "providers", + "cline-pass-provider.test.ts": "providers", + "cline-pass-reasoning-efforts.test.ts": "providers", + "cline-provider.test.ts": "providers", + "closed-pr-branch-cleanup.test.ts": "ci-workflows", + "codebuddy-adapter.test.ts": "providers", + "codebuddy-live-acceptance.test.ts": "providers", + "codebuddy-mcp-server.test.ts": "providers", + "codebuddy-protocol.test.ts": "providers", + "codebuddy-tool-bridge-turn.test.ts": "providers", + "codebuddy-tool-bridge.test.ts": "providers", + "codex-account-delete-atomicity.test.ts": "codex-integration", + "codex-account-selection-atomicity.test.ts": "codex-integration", + "codex-account-label.test.ts": "codex-integration", + "codex-account-mode-state.test.ts": "gui", + "codex-account-namespaces.test.ts": "codex-integration", + "codex-account-selection-preferences.test.ts": "codex-integration", + "codex-account-store-refresh-classification.test.ts": "codex-integration", + "codex-account-store.test.ts": "codex-integration", + "codex-account-threshold-api.test.ts": "codex-integration", + "codex-account-threshold-auth.test.ts": "codex-integration", + "codex-account-threshold-routing.test.ts": "codex-integration", + "codex-account-unusable-reason.test.ts": "codex-integration", + "codex-admission-primitives.test.ts": "codex-integration", + "codex-admission.test.ts": "codex-integration", + "codex-affinity-debug.test.ts": "codex-integration", + "codex-app-server-path-spaces.test.ts": "codex-integration", + "codex-app-server-processes.test.ts": "codex-integration", + "codex-app-server-restart-service.test.ts": "codex-integration", + "codex-auth-api.test.ts": "codex-integration", + "codex-linked-account-pause.test.ts": "codex-integration", + "codex-auth-cancel-ownership.test.ts": "codex-integration", + "codex-auth-collision.test.ts": "codex-integration", + "codex-auth-context.test.ts": "codex-integration", + "codex-auth-modal-status.test.ts": "gui", "codex-set-prompt.test.ts": "gui", + "codex-catalog-admission.test.ts": "codex-integration", + "codex-catalog-exclusions.test.ts": "codex-integration", + "codex-catalog-golden.test.ts": "codex-integration", + "codex-catalog-identity-neutral.test.ts": "codex-integration", + "codex-catalog-ladders.test.ts": "codex-integration", + "codex-catalog-model-picker-order.test.ts": "codex-integration", + "codex-catalog-refresh-status.test.ts": "codex-integration", + "codex-catalog-restore.test.ts": "codex-integration", + "codex-catalog-sync-hardening.test.ts": "codex-integration", + "codex-catalog-routed-removal.test.ts": "codex-integration", + "codex-catalog-intent.test.ts": "codex-integration", + "codex-catalog-write-audit.test.ts": "codex-integration", + "codex-catalog-self-heal.test.ts": "codex-integration", + "codex-catalog-heal-integration.test.ts": "codex-integration", + "codex-home-owner.test.ts": "codex-integration", + "codex-home-owner-lifecycle.test.ts": "codex-integration", + "codex-catalog-write-serialization.test.ts": "codex-integration", + "codex-catalog-writer.test.ts": "codex-integration", + "vendor-context.test.ts": "codex-integration", "codex-catalog.test.ts": "codex-integration", + "codex-cli-install-provenance.test.ts": "codex-integration", + "codex-cli-installation-identity.test.ts": "codex-integration", + "codex-cli-installation-targets.test.ts": "codex-integration", + "codex-cli-update-launcher-policy.test.ts": "codex-integration", + "codex-cli-update-zero-effect.test.ts": "codex-integration", + "codex-cli-windows-installation-files.test.ts": "codex-integration", + "codex-forward-access-programs-writer.test.ts": "codex-integration", + "codex-composed-acceptance.test.ts": "codex-integration", + "codex-config-generation.test.ts": "codex-integration", + "codex-context-owner.test.ts": "codex-integration", + "codex-convergence-account-selectors.test.ts": "codex-integration", + "codex-convergence-contract.test.ts": "codex-integration", + "codex-cooldown-recovery.test.ts": "codex-integration", + "codex-coordinator-doctor.test.ts": "codex-integration", + "codex-desired-state.test.ts": "codex-integration", + "codex-entitlement-identity-read-fence.test.ts": "codex-integration", + "codex-envkey-admission-substitution.test.ts": "codex-integration", + "codex-exec-invocation.test.ts": "codex-integration", "messaging-local-discovery.test.ts": "codex-integration", "messaging-local-cli.test.ts": "codex-integration", "messaging-local-envelope.test.ts": "codex-integration", + "messaging-local-send.test.ts": "codex-integration", "messaging-local-lifecycle.test.ts": "codex-integration", "messaging-local-socket.test.ts": "codex-integration", "codex-features-cache.test.ts": "codex-integration", + "codex-features-residual.test.ts": "codex-integration", "codex-failure-window.test.ts": "codex-integration", + "codex-filesystem-evidence.test.ts": "codex-integration", + "codex-gather-authority.test.ts": "codex-integration", + "codex-history-job.test.ts": "codex-integration", + "codex-history-lock.test.ts": "codex-integration", + "codex-history-provider.test.ts": "codex-integration", + "codex-history-reachability.test.ts": "codex-integration", + "codex-history-worker-boundary.test.ts": "codex-integration", + "codex-history-worker.test.ts": "codex-integration", + "codex-history-writer.test.ts": "codex-integration", + "codex-home-wsl.test.ts": "codex-integration", + "codex-home-wsl-local-state.test.ts": "codex-integration", + "codex-inject-history-wording.test.ts": "codex-integration", + "codex-inject-integration.test.ts": "codex-integration", + "codex-inject-missing-config.test.ts": "codex-integration", + "codex-inject-retained-table.test.ts": "codex-integration", + "codex-inject-v1-reconcile.test.ts": "codex-integration", + "codex-inject-write-lock.test.ts": "codex-integration", + "codex-inject.test.ts": "codex-integration", + "codex-injected-marker.test.ts": "codex-integration", + "codex-integration-record.test.ts": "codex-integration", + "codex-journal-recovery.test.ts": "codex-integration", "codex-journal.test.ts": "codex-integration", + "codex-legacy-config-keys.test.ts": "codex-integration", + "codex-lineage-placement.test.ts": "codex-integration", + "codex-log-guard-coderabbit.test.ts": "codex-integration", + "codex-log-guard-doctor-coderabbit.test.ts": "codex-integration", + "codex-log-guard-doctor-protection.test.ts": "codex-integration", + "codex-log-guard-doctor.test.ts": "codex-integration", + "codex-log-guard-inspect.test.ts": "codex-integration", + "codex-log-guard-lock.test.ts": "codex-integration", + "codex-log-guard-maintenance-coderabbit.test.ts": "codex-integration", + "codex-log-guard-maintenance.test.ts": "codex-integration", + "codex-log-guard-policy.test.ts": "codex-integration", + "codex-log-guard-processes.test.ts": "codex-integration", + "codex-log-guard-protection.test.ts": "codex-integration", + "codex-log-guard-status-zero-write.test.ts": "codex-integration", + "codex-main-account-refresh.test.ts": "codex-integration", + "codex-main-rotation.test.ts": "codex-integration", + "codex-management-convergence.test.ts": "codex-integration", + "codex-metadata-integrity.test.ts": "codex-integration", + "codex-model-availability-error.test.ts": "codex-integration", + "codex-model-denial-evidence.test.ts": "codex-integration", + "codex-model-entitlement-admission.test.ts": "codex-integration", + "codex-model-entitlements-program-shape.test.ts": "codex-integration", + "codex-native-availability-nux.test.ts": "codex-integration", + "codex-model-entitlements.test.ts": "codex-integration", + "codex-models-cache-invalidate.test.ts": "codex-integration", + "codex-native-residue.test.ts": "codex-integration", + "codex-pin-drain-projection.test.ts": "codex-integration", + "codex-plan.test.ts": "codex-integration", + "codex-plugins-doctor.test.ts": "codex-integration", + "codex-pool-plan-exclusion.test.ts": "codex-integration", + "codex-pool-refresh-backoff.test.ts": "codex-integration", + "codex-pool-request-owned-main.test.ts": "codex-integration", + "codex-pool-rotation.test.ts": "codex-integration", "codex-auth-release.test.ts": "codex-integration", + "codex-priority-failback.test.ts": "codex-integration", + "codex-idle-window.test.ts": "codex-integration", + "codex-prompt-adopt.test.ts": "codex-integration", + "codex-prompt-base-variants.test.ts": "codex-integration", "codex-prompt-writes.test.ts": "codex-integration", "codex-prompt-scalar-scope.test.ts": "codex-integration", + "codex-prompt-journal.test.ts": "codex-integration", + "codex-prompt-layers-read.test.ts": "codex-integration", + "codex-prompt-layers-write.test.ts": "codex-integration", + "codex-prompt-layers.test.ts": "codex-integration", + "codex-prompt-lock-sharing.test.ts": "codex-integration", + "codex-prompt-lock.test.ts": "codex-integration", "codex-config-write-lock.test.ts": "codex-integration", "codex-missing-home.test.ts": "codex-integration", + "codex-prompt-route.test.ts": "codex-integration", + "codex-prompt-text-probe.test.ts": "codex-integration", + "codex-provider-table-retention.test.ts": "codex-integration", + "codex-quota-auto-refresh-main-admission.test.ts": "codex-integration", + "codex-quota-auto-refresh.test.ts": "codex-integration", + "codex-quota-capacity.test.ts": "codex-integration", + "codex-quota-history.test.ts": "codex-integration", + "codex-quota-parser-parity.test.ts": "codex-integration", + "codex-quota-prime.test.ts": "codex-integration", + "codex-quota-rejection.test.ts": "codex-integration", + "codex-refresh.test.ts": "codex-integration", + "codex-reset-credit-auto-redeem.test.ts": "codex-integration", + "codex-reset-credit-operation-ledger.test.ts": "codex-integration", + "codex-reset-credit-recovery.test.ts": "codex-integration", + "codex-restart-contract-parity.test.ts": "codex-integration", + "codex-restart-route.test.ts": "codex-integration", + "codex-restore-app-rewrite.test.ts": "codex-integration", + "codex-retained-root-serialization.test.ts": "codex-integration", + "codex-routing-cache-affinity-detour.test.ts": "codex-integration", + "codex-routing.test.ts": "codex-integration", + "codex-runtime.test.ts": "codex-integration", "codex-runtime-macos-desktop.test.ts": "codex-integration", "codex-clamp-notice.test.ts": "codex-integration", + "codex-runtime-wsl-desktop.test.ts": "codex-integration", + "codex-service-manager-probe-hardening.test.ts": "codex-integration", + "codex-service-manager-probe.test.ts": "codex-integration", + "codex-systemd-env-probe.test.ts": "codex-integration", + "codex-shim-autorestore.test.ts": "codex-integration", + "codex-shim-destroyed-probe.test.ts": "codex-integration", + "codex-shim-ensure-failure.test.ts": "codex-integration", + "codex-shim-readiness.test.ts": "codex-integration", + "codex-shim-standalone.test.ts": "codex-integration", + "codex-shim.test.ts": "codex-integration", + "codex-signin-lockout.test.ts": "codex-integration", + "codex-spark-visibility.test.ts": "codex-integration", + "codex-sqlite-home.test.ts": "codex-integration", + "codex-sync-api.test.ts": "codex-integration", + "codex-sync-new-model-policy.test.ts": "codex-integration", + "codex-sync-response.test.ts": "codex-integration", + "codex-tool-mode.test.ts": "codex-integration", + "codex-transition-state-adoption.test.ts": "codex-integration", + "codex-transition-state-first-use-regression.test.ts": "codex-integration", + "codex-transition-state-race.test.ts": "codex-integration", + "codex-transition-state.test.ts": "codex-integration", + "codex-user-identity.test.ts": "codex-integration", + "codex-v2-gate.test.ts": "codex-integration", + "codex-agent-thread-limit.test.ts": "codex-integration", + "codex-warmup.test.ts": "codex-integration", + "codex-web-search-switch.test.ts": "codex-integration", + "codex-websocket-registry.test.ts": "codex-integration", + "codex-write-lock.test.ts": "codex-integration", + "coding-agent-tool-result-images.test.ts": "adapters", + "cold-spawn-warmup.test.ts": "ci-workflows", + "combo-authoritative-reset.test.ts": "codex-integration", + "combo-codex-exhaustion-cooldown.test.ts": "codex-integration", + "combo-permanent-failure-cooldown.test.ts": "codex-integration", + "combo-reset-window-model-scope.test.ts": "codex-integration", + "combo-child-headers.test.ts": "routing", + "combo-last-resort.test.ts": "codex-integration", + "combo-management-api.test.ts": "routing", + "combo-vision-enrollment.test.ts": "routing", + "combo-stream-preflight.test.ts": "routing", + "combo-workspace-data.test.ts": "gui", + "combo-workspace-jev-decision.test.ts": "gui", + "combos.test.ts": "codex-integration", + "command-code-error-finish.test.ts": "providers", + "command-code-efforts.test.ts": "providers", + "command-code-project-context.test.ts": "providers", + "command-code-provider.test.ts": "providers", + "command-code-quota.test.ts": "providers", + "command-code-tool-text.test.ts": "providers", + "command-code-workspace-cache.test.ts": "providers", + "commandcode-provider.test.ts": "providers", + "compaction-progress.test.ts": "responses", + "companion-settings.test.ts": "server", + "compatibility-manifest.test.ts": "codex-integration", + "compatibility-provider-equivalence.test.ts": "routing", + "compatibility-version.test.ts": "ci-workflows", + "config-account-thresholds.test.ts": "config", + "config-blocked-model-redirects.test.ts": "config", + "config-catalog-auto-refresh.test.ts": "config", + "config-commandcode-claude-pin.test.ts": "config", + "config-load-degrade.test.ts": "config", + "protocol-settings.test.ts": "config", + "config-mutation-lock.test.ts": "config", + "config-non-object-backup.test.ts": "config", + "config-ownership-uninstall.test.ts": "config", + "config-rebase-provenance-writers.test.ts": "config", + "config-save-boundary.test.ts": "config", + "config-spend-ceilings.test.ts": "config", + "config-spend-pool-collision.test.ts": "config", + "config-user-edits.test.ts": "config", "hub-disable-live-save.test.ts": "config", + "config.test.ts": "server", + "configured-native-models.test.ts": "codex-integration", + "gui-desktop-sidecar-signing.test.ts": "gui", + "linux-desktop-packaged-ci.test.ts": "ci-workflows", + "probe-timeout-env.test.ts": "server", + "subagent-roster-migration.test.ts": "routing", + "consume-for-inspection-cancel.test.ts": "server", + "container-bootstrap.test.ts": "service", + "context-cap-unknown-window.test.ts": "providers", + "context-compat.test.ts": "codex-integration", + "context-history-ownership.test.ts": "server", + "context-history.test.ts": "server", + "context-window-seed-repair.test.ts": "providers", + "continuation-dedup.test.ts": "responses", + "core-lab-boundary.test.ts": "lab", + "cost-cap-unknown-evidence.test.ts": "usage", + "cost-scoring.test.ts": "usage", + "crash-guard.test.ts": "service", + "credential-redirect-guard.test.ts": "lib", + "crusoe-provider.test.ts": "providers", + "cursor-adapter.test.ts": "providers/cursor", + "cursor-arg-normalize.test.ts": "providers/cursor", + "cursor-blob-integrity.test.ts": "providers/cursor", + "cursor-blob-claude-client-tools.test.ts": "providers/cursor", "cursor-blob.test.ts": "providers/cursor", + "cursor-call-id.test.ts": "providers/cursor", + "cursor-cancel-provenance.test.ts": "providers/cursor", + "cursor-catalog.test.ts": "providers/cursor", + "cursor-claude-id.test.ts": "providers/cursor", + "cursor-continuation-invariants.test.ts": "providers/cursor", + "cursor-continuity-retention.test.ts": "providers/cursor", + "cursor-default-catalog-suppression.test.ts": "providers/cursor", + "cursor-desktop-exec.test.ts": "providers/cursor", + "cursor-discovery.test.ts": "providers/cursor", + "cursor-display-names.test.ts": "providers/cursor", + "cursor-effort-rows.test.ts": "providers/cursor", + "cursor-effort-suffix.test.ts": "providers/cursor", + "cursor-effort-table.test.ts": "providers/cursor", + "cursor-envelope-echo-retry.test.ts": "providers/cursor", + "cursor-eof-terminal.test.ts": "providers/cursor", + "cursor-errors.test.ts": "providers/cursor", + "cursor-exec-empty-result.test.ts": "providers/cursor", + "cursor-fast-listing.test.ts": "providers/cursor", + "cursor-fast-tier.test.ts": "providers/cursor", + "cursor-framing.test.ts": "providers/cursor", + "cursor-h2-pool-shutdown.test.ts": "providers/cursor", + "cursor-hardening.test.ts": "providers/cursor", + "cursor-http1-transport.test.ts": "providers/cursor", + "cursor-images.test.ts": "providers/cursor", + "cursor-integration-status.test.ts": "providers/cursor", + "cursor-interaction-query.test.ts": "providers/cursor", + "cursor-kv-store.test.ts": "providers/cursor", + "cursor-live-smoke-gate.test.ts": "providers/cursor", + "cursor-live-transport.test.ts": "providers/cursor", + "cursor-local-models-schema.test.ts": "providers/cursor", + "cursor-mcp-manager.test.ts": "providers/cursor", + "cursor-mcp-stdio.test.ts": "providers/cursor", + "cursor-message-mapper.test.ts": "providers/cursor", + "cursor-native-exec-common.test.ts": "providers/cursor", + "cursor-native-exec-policy.test.ts": "providers/cursor", + "cursor-native-exec-shell.test.ts": "providers/cursor", + "cursor-foreground-shell.test.ts": "providers/cursor", + "cursor-native-exec.test.ts": "providers/cursor", + "cursor-oauth-shell.test.ts": "providers/cursor", + "cursor-oauth.test.ts": "providers/cursor", + "cursor-pool.test.ts": "providers/cursor", + "cursor-protobuf-events.test.ts": "providers/cursor", + "cursor-repetition-breaker.test.ts": "providers/cursor", + "cursor-request-builder.test.ts": "providers/cursor", + "cursor-request-compat.test.ts": "providers/cursor", + "cursor-roster-account-scope.test.ts": "providers/cursor", + "cursor-silent-redirect.test.ts": "providers/cursor", + "cursor-static-catalog.test.ts": "providers/cursor", + "cursor-stream-health.test.ts": "providers/cursor", + "cursor-structured-edit.test.ts": "providers/cursor", + "cursor-tool-arg-decoding.test.ts": "providers/cursor", + "cursor-tool-choice.test.ts": "providers/cursor", + "cursor-tool-continuation.test.ts": "providers/cursor", + "cursor-tool-definitions.test.ts": "providers/cursor", + "cursor-tool-finalize-race.test.ts": "providers/cursor", "cursor-freeform-args.test.ts": "providers/cursor", + "cursor-tool-result-image.test.ts": "providers/cursor", + "cursor-tool-result-invocation.test.ts": "providers/cursor", + "cursor-tool-suspended-checkpoint.test.ts": "providers/cursor", "cursor-tool-wording.test.ts": "providers/cursor", + "cursor-toolresult-normalize.test.ts": "providers/cursor", + "cursor-transport-retry.test.ts": "providers/cursor", + "cursor-ultra-mode.test.ts": "providers/cursor", + "cursor-umbrella-rows.test.ts": "providers/cursor", + "cursor-uncallable-quarantine.test.ts": "providers/cursor", + "cursor-vision-wire-harness.test.ts": "providers/cursor", + "custom-model-catalog-migration.test.ts": "codex-integration", + "custom-tool-compat.test.ts": "responses", + "cyber-policy-error-fidelity.test.ts": "providers", + "dashboard-sidecar-codex-write.test.ts": "gui", + "dashboard-uptime.test.ts": "gui", + "data-plane-admission-identity.test.ts": "server", + "debug-settings.test.ts": "server", + "debug.test.ts": "lib", + "decision-discovery.test.ts": "server", + "server-jev-model-decision-e2e.test.ts": "server", + "decision-routes.test.ts": "server", + "deepinfra-provider.test.ts": "providers", + "deepseek-inbound-wire.test.ts": "providers", + "deepseek-reasoning-replay-gaps.test.ts": "providers", + "deepseek-reasoning-replay.test.ts": "providers", + "deepseek-responses-item-id-repair.test.ts": "providers", + "management-desktop-compatibility-routes.test.ts": "server", "management-desktop-compatibility-runtime-routes.test.ts": "server", "server-desktop-compatibility-startup.test.ts": "server", "management-desktop-compatibility-settings.test.ts": "server", + "optional-desktop-upstream.test.ts": "lib", + "destination-policy-resolved.test.ts": "routing", + "devin-adapter-reset-wait.test.ts": "providers", + "devin-adapter.test.ts": "providers", + "devin-chat-wire-fixes.test.ts": "providers", + "devin-cli-authmode-migration.test.ts": "providers", + "devin-effort-ladder.test.ts": "providers", + "devin-family-resolution.test.ts": "providers", + "devin-hardening.test.ts": "providers", + "devin-image-passthrough.test.ts": "providers", + "devin-live-models.test.ts": "providers", + "devin-login.test.ts": "providers", + "devin-quota.test.ts": "providers", + "devin-output-budget.test.ts": "providers", + "devin-prompt-cache.test.ts": "providers", + "devin-trajectory.test.ts": "providers", + "devin-provider-merge-migration.test.ts": "providers", + "devin-stated-reset-hardening.test.ts": "providers", + "devin-stated-reset-retry.test.ts": "providers", + "devin-anthropic-signature-fallback.test.ts": "providers", + "devin-reasoning-continuation.test.ts": "providers", + "devin-stream-deadline.test.ts": "providers", + "digitalocean-scaleway-provider.test.ts": "providers", + "docs-429-failover-claims.test.ts": "ci-workflows", + "docs-bun-source-requirement.test.ts": "ci-workflows", + "docs-developer-role-policy.test.ts": "ci-workflows", + "docs-gui-screenshot-policy.test.ts": "ci-workflows", + "docs-link-targets.test.ts": "ci-workflows", + "docs-gjc-reasoning-export.test.ts": "ci-workflows", + "docs-provider-billing-claims.test.ts": "ci-workflows", + "docs-provider-discovery-limits.test.ts": "ci-workflows", + "docs-provider-preset-counts.test.ts": "ci-workflows", + "docs-readme-memory-inventory.test.ts": "ci-workflows", + "docs-readme-translation-parity.test.ts": "ci-workflows", + "docs-remote-hub-claims.test.ts": "ci-workflows", + "doctor-codex-envkey-readiness.test.ts": "service", + "doctor-oauth.test.ts": "service", + "doctor-provider-apikey.test.ts": "service", + "doctor-service-memory-contract.test.ts": "service", + "doctor.test.ts": "codex-integration", + "download-cap-default.test.ts": "images", + "download-connect-deadline-default.test.ts": "images", + "dsh-path-contract.test.ts": "ci-workflows", + "dsh-rc6-compat-script.test.ts": "ci-workflows", + "dsh-writer-lock.test.ts": "ci-workflows", + "effort-policy.test.ts": "codex-integration", + "empty-completion-core.test.ts": "responses", + "empty-completion-guard.test.ts": "responses", + "empty-completion-hardening.test.ts": "responses", + "empty-tool-output-annotation.test.ts": "adapters", + "ensure-desired-integrations-race.test.ts": "cli", + "error-fidelity.test.ts": "server", + "errors-adapter-failure.test.ts": "server", + "eventstream-decoder.test.ts": "responses", + "exa-web-search.test.ts": "providers", + "exec-tool-result-normalize.test.ts": "adapters", + "execution-budget-permits.test.ts": "lib", + "exhaustive-deps-suppression.test.ts": "ci-workflows", + "expand-user-path.test.ts": "config", + "failure-attribution.test.ts": "lib", + "failure-stage-model.test.ts": "lib", + "fast-row-ingress.test.ts": "providers", + "fast-row-listing.test.ts": "codex-integration", + "fast-row.test.ts": "codex-integration", + "fastwire-characterization-routing.test.ts": "routing", + "fastwire-characterization-wire.test.ts": "routing", + "fastwire-observability.test.ts": "routing", + "fastwire-response-authority.test.ts": "routing", + "fastwire-policy.test.ts": "routing", + "featherless-provider.test.ts": "providers", + "fetch-header-timeout.test.ts": "server", + "file-size-ratchet.test.ts": "ci-workflows", + "fixture-dir-uniqueness.test.ts": "ci-workflows", + "flash-route-image-modalities.test.ts": "providers", + "format-result.test.ts": "web-search", + "forward-admission-separation.test.ts": "providers", + "fresh-connection-optout.test.ts": "responses", + "fulfill-video.test.ts": "videos", + "gather-routed-models-single-flight.test.ts": "codex-integration", + "gcp-adc.test.ts": "adapters/google", + "gemini-37-flash-migration.test.ts": "adapters/google", + "gemini-4-argon-antigravity.test.ts": "adapters/google", + "antigravity-account-roster.test.ts": "adapters/google", + "gemini-inline.test.ts": "images", + "gemini-web-search.test.ts": "adapters/google", + "generic-session-affinity.test.ts": "oauth", + "server-generic-oauth-affinity.test.ts": "server", + "generic-oauth-failover.test.ts": "oauth", + "generic-oauth-refusal-composition.test.ts": "oauth", "github-copilot-auto.test.ts": "providers/github-copilot", "github-copilot-auto-runtime.test.ts": "providers/github-copilot", "github-copilot-catalog-hints.test.ts": "providers/github-copilot", + "github-copilot-account-origin.test.ts": "providers/github-copilot", + "github-copilot-context-tier.test.ts": "providers/github-copilot", + "github-copilot-oauth.test.ts": "providers/github-copilot", + "github-copilot-sse-rewrite.test.ts": "providers/github-copilot", + "github-copilot-stream-contract.test.ts": "providers/github-copilot", + "github-copilot-wire-defaults.test.ts": "providers/github-copilot", + "google-adapter.test.ts": "adapters/google", + "google-antigravity-oauth.test.ts": "adapters/google", + "google-antigravity-replay.test.ts": "adapters/google", + "google-antigravity-wire.test.ts": "adapters/google", + "google-buffered-stop-reason.test.ts": "adapters/google", + "google-claude-prefill-guard.test.ts": "adapters/google", + "google-empty-content.test.ts": "adapters/google", + "google-errors.test.ts": "adapters/google", + "google-hardening.test.ts": "adapters/google", + "google-models-listing.test.ts": "adapters/google", + "google-output-clamp.test.ts": "adapters/google", + "google-provider-metadata-roundtrip.test.ts": "adapters/google", + "google-signature-history-roundtrip.test.ts": "adapters/google", + "google-strict-tool-validated-mode.test.ts": "adapters/google", + "google-structured-output.test.ts": "adapters/google", + "google-tool-result-adjacency.test.ts": "adapters/google", + "google-tool-schema-contract.test.ts": "adapters/google", + "google-tool-schema.test.ts": "adapters/google", + "google-vertex-http.test.ts": "adapters/google", + "google-vertex-stream.test.ts": "adapters/google", + "google-vertex-thought-signature.test.ts": "adapters/google", + "google-wire-compiler.test.ts": "adapters/google", + "google-wire-shape.test.ts": "adapters/google", + "gpt6-native-rows.test.ts": "codex-integration", + "gpt61-sol-rows.test.ts": "codex-integration", + "grok-attribution.test.ts": "providers/xai", + "grok-config-inject.test.ts": "providers/xai", "grok-config-write-lock.test.ts": "providers/xai", + "grok-effort-inject.test.ts": "providers/xai", + "grok-lifecycle.test.ts": "providers/xai", + "grok-management-api.test.ts": "providers/xai", + "grok-models-effort-list.test.ts": "providers/xai", + "grok-orphan-adoption.test.ts": "providers/xai", + "grok-reset-coupon-cli.test.ts": "providers/xai", + "grok-reset-coupons.test.ts": "providers/xai", "grok-coupon-reconcile.test.ts": "providers/xai", "grok-coupon-claim.test.ts": "providers/xai", + "grok-selection.test.ts": "providers/xai", + "grok-session-identity.test.ts": "providers/xai", + "grok-status.test.ts": "providers/xai", + "grok-sync.test.ts": "providers/xai", + "grok-writer-boundary.test.ts": "providers/xai", + "gui-api-error.test.ts": "gui", + "html-lang-boot-script.test.ts": "gui", + "gui-codex-usage-score-parity.test.ts": "gui", + "gui-desktop-sidecar-script.test.ts": "gui", + "gui-management-session.test.ts": "gui", + "gui-pair-capability.test.ts": "gui", + "gui-pair-client.test.ts": "gui", + "gui-pair-http.test.ts": "gui", + "gui-static.test.ts": "gui", + "gui-tray-vibrancy-surface.test.ts": "gui", + "health-scoring.test.ts": "server", + "history-migration-guardian.test.ts": "codex-integration", + "history-ocx-compaction-recovery.test.ts": "codex-integration", + "history-paginated-openai-compat.test.ts": "codex-integration", + "history-paginated-transition-destinations.test.ts": "codex-integration", + "hub-gated-local-clients.test.ts": "cli", + "hub-invite.test.ts": "cli", "hub-disable.test.ts": "cli", + "hub-usage.test.ts": "server", + "hyperbolic-provider.test.ts": "providers", + "identity-neutralize.test.ts": "adapters", + "identity-subagent.test.ts": "adapters", + "init-backup-cleanup.test.ts": "service", + "init-eof.test.ts": "service", + "initial-model-selection.test.ts": "providers", + "initial-selection-write-fence.test.ts": "providers", + "injection-model-api.test.ts": "codex-integration", + "inline-think-boundaries.test.ts": "adapters/openai", + "input-admission.test.ts": "server", + "install-scripts.test.ts": "ci-workflows", + "installed-gate-drivers.test.ts": "ci-workflows", + "integrations-invariants.test.ts": "gui", + "interactive-confirm.test.ts": "cli", + "issue-452-empty-503.test.ts": "codex-integration", + "issue-702-expired-replay-state.test.ts": "codex-integration", + "issue-914-transport-attribution.test.ts": "codex-integration", + "key-attribution.test.ts": "usage", + "key-failover.test.ts": "adapters", + "key-login-live-update.test.ts": "oauth", + "key-login-preserves-model-costs.test.ts": "oauth", + "jev-decision.test.ts": "routing", "jev-decision-destination.test.ts": "routing", "jev-service-exchange.test.ts": "routing", + "jev-decision-provider-combo.test.ts": "routing", + "jev-typesafe-golden.test.ts": "routing", + "jev-model-backend.test.ts": "routing", + "jev-provider.test.ts": "providers", + "keyring-smoke.test.ts": "ci-workflows", + "kimi-oauth-identity.test.ts": "providers", + "kimi-responses-adjacency.test.ts": "providers", + "kiro-account-load.test.ts": "providers/kiro", + "kiro-account-quota.test.ts": "providers/kiro", + "kiro-account-state-disk.test.ts": "providers/kiro", + "kiro-account-state-imports.test.ts": "providers/kiro", + "kiro-adapter.test.ts": "providers/kiro", + "kiro-auth-context-continuation.test.ts": "providers/kiro", + "kiro-builder-id-profile.test.ts": "providers/kiro", + "kiro-calibration.test.ts": "providers/kiro", + "kiro-device-builder.test.ts": "providers/kiro", "kiro-device-social.test.ts": "providers/kiro", + "kiro-fallback-error-body.test.ts": "providers/kiro", + "kiro-images.test.ts": "providers/kiro", + "kiro-leased-responses.test.ts": "providers/kiro", + "kiro-model-catalog.test.ts": "providers/kiro", "kiro-model-preference.test.ts": "providers/kiro", + "kiro-oauth.test.ts": "providers/kiro", "oauth-kiro-refresh-attention.test.ts": "oauth", "kiro-org-user-identity.test.ts": "providers/kiro", + "kiro-pool-load-settings.test.ts": "providers/kiro", + "kiro-pool-rank.test.ts": "providers/kiro", + "kiro-reasoning-roundtrip.test.ts": "providers/kiro", + "kiro-refusal-failover.test.ts": "providers/kiro", + "kiro-refusal.test.ts": "providers/kiro", + "kiro-remote-image.test.ts": "providers/kiro", + "kiro-retry.test.ts": "providers/kiro", + "kiro-review-regressions.test.ts": "providers/kiro", + "kiro-metering-events.test.ts": "providers/kiro", + "kiro-metering-usage.test.ts": "providers/kiro", + "kiro-single-final.test.ts": "providers/kiro", + "kiro-stream.test.ts": "providers/kiro", + "kiro-transport-parity.test.ts": "providers/kiro", + "kiro-usage-quota.test.ts": "providers/kiro", + "kiro-usage-restart.test.ts": "providers/kiro", + "kiro-windows-cli-db-path.test.ts": "providers/kiro", + "kiro-windows-cli-executable-path.test.ts": "providers/kiro", + "kiro-wire-estimate.test.ts": "providers/kiro", + "lab-activation.test.ts": "lab", + "lab-automation-coderabbit-regressions.test.ts": "lab", + "lab-automation-final-coderabbit-regressions.test.ts": "lab", + "lab-automation-ingwannu-regressions.test.ts": "lab", + "lab-automation-management-http.test.ts": "lab", + "lab-automation-persisted-cap-regression.test.ts": "lab", + "lab-automation-review-regressions.test.ts": "lab", + "lab-automation.test.ts": "lab", + "lab-community-evidence.test.ts": "lab", + "lab-community-filename-contract.test.ts": "lab", + "lab-community-mutation-lock.test.ts": "lab", + "lab-community-publisher-continuity.test.ts": "lab", + "lab-conformance-harness.test.ts": "lab", + "lab-conformance-runner-failures.test.ts": "lab", + "lab-evidence-ledger.test.ts": "lab", + "lab-evidence-sanitization.test.ts": "lab", + "lab-fabric-outcome-validation.test.ts": "lab", + "lab-fabric-persistence-boundary.test.ts": "lab", + "lab-fabric-producer-deadline.test.ts": "lab", + "lab-fabric-task.test.ts": "lab", + "lab-installation-salt-cache.test.ts": "lab", + "lab-ledger-mutation-lock.test.ts": "lab", + "lab-live-pinned-timeouts.test.ts": "lab", + "lab-live-probe.test.ts": "lab", + "lab-live-receipt-integrity.test.ts": "lab", + "lab-live-review-regressions.test.ts": "lab", + "lab-live-sandbox.test.ts": "lab", + "lab-passive-production-evidence.test.ts": "lab", + "lab-passive-production-surfaces.test.ts": "lab", + "lab-paths-security.test.ts": "lab", + "lab-post-merge-hardening.test.ts": "lab", + "lab-post-merge-projection.test.ts": "lab", + "lab-private-file-consumer-recovery.test.ts": "lab", + "lab-private-file-durability.test.ts": "lab", + "lab-public-api-json.test.ts": "lab", + "lab-public-artifact-policy.test.ts": "lab", + "lab-public-coderabbit-regressions.test.ts": "lab", + "lab-public-core-contract.test.ts": "lab", + "lab-public-deep-review-regressions.test.ts": "lab", + "lab-public-evidence.test.ts": "lab", + "lab-public-export-transaction.test.ts": "lab", + "lab-public-file-safety.test.ts": "lab", + "lab-public-final-review-regressions.test.ts": "lab", + "lab-public-lifecycle-hardening.test.ts": "lab", + "lab-public-privacy-ipv6.test.ts": "lab", + "lab-public-provenance-recovery.test.ts": "lab", + "lab-public-review-fixes.test.ts": "lab", + "lab-public-route-registry.test.ts": "lab", + "lab-public-security-regressions.test.ts": "lab", + "lab-public-surfaces.test.ts": "lab", + "lab-public-wire-contract.test.ts": "lab", + "lab-read-filter-validation.test.ts": "lab", + "lab-read-surfaces.test.ts": "lab", + "launchd-repair.test.ts": "service", + "legacy-shell-compat.test.ts": "responses", + "live-call-bindings.test.ts": "server", "live-native-calls.test.ts": "server", + "live-service-manager-guard.test.ts": "service", + "linux-desktop-packaged-e2e.test.ts": "ci-workflows", + "local-aside-sync-capability.test.ts": "server", + "local-account-switch-capability.test.ts": "server", + "local-account-switch-ingress.test.ts": "server", + "local-destinations.test.ts": "lib", + "local-management-attestation.test.ts": "server", + "local-management-capability.test.ts": "server", + "local-management-direct-transport.test.ts": "server", + "local-provider-reload-client.test.ts": "server", + "local-token-detect.test.ts": "oauth", + "local-upstream.test.ts": "lib", + "logs-model-tier-confirmation.test.ts": "gui", + "logs-timezone.test.ts": "server", + "loop-reasoning-replay.test.ts": "images", + "loop.test.ts": "images", + "loopback-companion-client-targets.test.ts": "server", + "loopback-listener-admission.test.ts": "server", + "loopback-listener-integration.test.ts": "server", + "macos-serial-lanes.test.ts": "ci-workflows", + "main-account-hard-lock-auth.test.ts": "codex-integration", "main-account-hard-lock-fallback-routing.test.ts": "codex-integration", "main-account-hard-lock-usage-limit.test.ts": "codex-integration", + "main-account-hard-lock-default.test.ts": "codex-integration", + "main-account-hard-lock-policy.test.ts": "codex-integration", + "main-account-hard-lock-recovery.test.ts": "codex-integration", "main-account-credit-renewal.test.ts": "codex-integration", + "main-account-policy-binding-wait.test.ts": "codex-integration", + "main-device-reauth-api.test.ts": "codex-integration", + "main-device-reauth-ui.test.ts": "gui", + "main-device-reauth.test.ts": "codex-integration", + "main-quota-evidence-validation.test.ts": "codex-integration", + "main-account-hard-lock-retirement.test.ts": "codex-integration", + "main-quota-provenance.test.ts": "codex-integration", + "main-quota-window-observation.test.ts": "codex-integration", + "management-anthropic-reset-grants.test.ts": "server", + "management-api-logs-metrics.test.ts": "server", + "management-api-logs-timing-basis.test.ts": "server", + "management-client-config-route.test.ts": "server", + "management-inference-port.test.ts": "server", + "management-google-tool-schema-policy.test.ts": "server", + "management-integration-journal-delete.test.ts": "server", + "management-integration-routes.test.ts": "server", + "management-metrics-export.test.ts": "server", + "management-model-roster-gather-race.test.ts": "server", + "management-model-roster.test.ts": "server", + "model-export-new-model-policy.test.ts": "server", + "management-origin-tls.test.ts": "server", + "management-provider-compat-carry.test.ts": "server", + "management-provider-hide-raw-reasoning.test.ts": "server", "management-provider-responses-reasoning.test.ts": "server", + "management-provider-atomicity.test.ts": "server", + "management-provider-pinsless-validation.test.ts": "server", + "management-provider-proto-override.test.ts": "server", + "management-provider-reasoning-lists.test.ts": "server", + "management-provider-reset-replay.test.ts": "server", + "management-provider-synthetic-max.test.ts": "server", + "management-provider-upstream-websocket.test.ts": "server", + "management-provider-context-inference.test.ts": "server", "management-provider-validation.test.ts": "server", + "management-provider-verbosity.test.ts": "server", + "management-route-registry.test.ts": "server", + "protocol-routes.test.ts": "server", + "protocol-settings-route.test.ts": "server", + "protocol-provider-summary.test.ts": "server", + "management-workflow-budget-routes.test.ts": "server", + "managing-cli.test.ts": "service", + "memory-watchdog.test.ts": "server", + "meta-model-api-provider.test.ts": "providers", "meta-muse-wonder.test.ts": "providers", + "meta-muse-oauth.test.ts": "providers", + "meta-muse-keychain.test.ts": "providers", + "oauth-meta-muse-login-diagnostics.test.ts": "oauth", + "mimo-effort.test.ts": "providers", + "mimo-free-provider.test.ts": "providers", + "mimo-token-plan-provider.test.ts": "providers", + "mimo-v26-catalog.test.ts": "providers", + "minimax-clients.test.ts": "providers", + "minimax-quota.test.ts": "providers", + "minimax-reasoning-split.test.ts": "providers", + "model-cache-generation-tombstone.test.ts": "codex-integration", + "model-cache.test.ts": "codex-integration", + "model-costs-management-api.test.ts": "server", + "model-discovery-management-api.test.ts": "server", + "server-new-model-policy-arrival.test.ts": "server", + "model-display-names-management-api.test.ts": "codex-integration", + "model-metadata-sync.test.ts": "codex-integration", + "model-pinned-effort-config.test.ts": "config", + "model-pinned-effort.test.ts": "codex-integration", + "model-presets.test.ts": "providers", + "model-rename-migration.test.ts": "providers", + "model-roster-seed-repair.test.ts": "providers", + "model-selection-guidance.test.ts": "cli", "model-settings-management-api.test.ts": "server", + "model-visibility-management-api.test.ts": "codex-integration", + "models-feedback-callback.test.ts": "gui", + "models-free-filter.test.ts": "gui", + "models-page-groups.test.ts": "gui", + "models-workspace-tabs.test.ts": "gui", + "moonshot-endpoints.test.ts": "providers", + "moonshot-tool-schema.test.ts": "providers", + "multi-agent-compat.test.ts": "codex-integration", "code-mode-collab-surface.test.ts": "codex-integration", "deferred-collab-surface.test.ts": "codex-integration", + "multi-agent-keep-native-v1.test.ts": "codex-integration", + "multi-agent-origin.test.ts": "codex-integration", + "muse-passive-quota-cache.test.ts": "providers", + "muse-passive-quota-observation.test.ts": "providers", + "muse-spark-web-search-compat.test.ts": "providers", + "muse-subscription-usage.test.ts": "providers", + "muse-tool-name-alias.test.ts": "providers", + "namespace-tool-compat.test.ts": "responses", + "native-alias-maintainer-regressions.test.ts": "codex-integration", + "native-claude-code-toggle.test.ts": "codex-integration", + "native-claude-desktop-toggle.test.ts": "codex-integration", + "native-codex-toggle.test.ts": "codex-integration", + "native-grok-toggle.test.ts": "codex-integration", + "native-main-auth-temp.test.ts": "codex-integration", + "native-main-claim-cache.test.ts": "codex-integration", + "native-main-claim.test.ts": "codex-integration", + "native-main-owner-lifetime.test.ts": "codex-integration", + "native-model-toggle.test.ts": "codex-integration", + "native-profile-api.test.ts": "codex-integration", + "native-profile-crash-boundaries.test.ts": "codex-integration", + "native-profile-drain-server.test.ts": "codex-integration", + "native-profile-manager.test.ts": "codex-integration", + "native-profile-processes.test.ts": "codex-integration", + "native-profile-recovery.test.ts": "codex-integration", + "native-profile-route-security.test.ts": "codex-integration", + "native-profile-stage-lifecycle.test.ts": "codex-integration", + "native-profile-startup-release.test.ts": "codex-integration", + "native-profile-startup.test.ts": "codex-integration", + "native-profile-store.test.ts": "codex-integration", + "new-model-policy.test.ts": "providers", + "new-model-policy-runtime.test.ts": "providers", + "nous-oauth-live.test.ts": "providers", + "nous-oauth.test.ts": "providers", + "novita-provider.test.ts": "providers", + "nscale-vultr-provider.test.ts": "providers", + "nvidia-nim-hardening.test.ts": "providers", + "oauth-account-attribution.test.ts": "oauth", + "oauth-account-id-collision.test.ts": "oauth", + "oauth-account-quota-rank.test.ts": "oauth", + "oauth-accounts-api.test.ts": "oauth", + "oauth-anthropic-identity.test.ts": "oauth", + "oauth-callback-binds.test.ts": "oauth", + "oauth-callback-server.test.ts": "oauth", + "oauth-device-code-contract.test.ts": "oauth", + "oauth-first-add-hint.test.ts": "gui", + "oauth-health.test.ts": "oauth", + "oauth-log.test.ts": "oauth", + "oauth-login-cli-browser-launch.test.ts": "oauth", + "oauth-login-cli-errors.test.ts": "oauth", + "oauth-login-cli-live-update.test.ts": "oauth", + "oauth-login-open-browser.test.ts": "oauth", + "oauth-login-summary.test.ts": "oauth", + "oauth-code-login.test.ts": "oauth", + "oauth-manual-code.test.ts": "oauth", + "oauth-open-browser-choice.test.ts": "oauth", + "oauth-open-url-result.test.ts": "oauth", + "oauth-provider-reconcile.test.ts": "oauth", + "oauth-reconcile-operator-maps.test.ts": "oauth", + "oauth-public-surface.test.ts": "oauth", + "oauth-reauth-bind.test.ts": "oauth", + "oauth-refresh-generic-lock.test.ts": "oauth", + "oauth-refresh-stale-capacity.test.ts": "oauth", + "oauth-refresh-lock-multiprocess.test.ts": "oauth", + "oauth-refresh.test.ts": "oauth", + "oauth-status-privacy.test.ts": "oauth", + "oauth-store-multi.test.ts": "oauth", + "oauth-tos-warning.test.ts": "gui", + "oauth-upsert-preserves-api-key.test.ts": "oauth", + "ocx-launcher-runtime.test.ts": "cli", + "ocx-launcher-desktop-handoff.test.ts": "cli", "cli-path-diagnostics.test.ts": "cli", + "ocx-launcher-source.test.ts": "cli", + "ocx-run.test.ts": "cli", + "ollama-native-parser.test.ts": "providers/ollama", "ollama-native-reasoning-wire.test.ts": "providers/ollama", "ollama-native-structured-output.test.ts": "providers/ollama", "ollama-native-tool-continuations.test.ts": "providers/ollama", + "ollama-native-v4.test.ts": "providers/ollama", "ollama-native.test.ts": "providers/ollama", "ollama-show-enrichment-v7.test.ts": "providers/ollama", "ollama-show-enrichment.test.ts": "providers/ollama", + "ollama-show-ignore-abort.test.ts": "providers/ollama", + "opaque-blob-wrapped-rejection.test.ts": "responses", "openai-api-virtual-models.test.ts": "adapters/openai", "openai-chat-bounded-tool-names.test.ts": "adapters/openai", "openai-chat-dangling-toolcalls.test.ts": "adapters/openai", + "openai-chat-developer-position.test.ts": "adapters/openai", "openai-chat-eof.test.ts": "adapters/openai", "openai-chat-hardening.test.ts": "adapters/openai", "openai-empty-assistant-history.test.ts": "adapters/openai", "openai-chat-image-normalization.test.ts": "adapters/openai", + "openai-chat-inline-think-tags.test.ts": "adapters/openai", "openai-chat-invalid-tool-call-diagnostics.test.ts": "adapters/openai", "openai-chat-mistral-content.test.ts": "adapters/openai", "openai-chat-model-suffix.test.ts": "adapters/openai", "openai-chat-native-policy.test.ts": "adapters/openai", + "openai-chat-parallel-stream.test.ts": "adapters/openai", "openai-chat-path-override.test.ts": "adapters/openai", "openai-chat-qwen38-leading-system.test.ts": "adapters/openai", "openai-chat-reasoning-wire-policy.test.ts": "adapters/openai", + "openai-chat-sanitization-review-regressions.test.ts": "adapters/openai", "openai-chat-serialized-tool-call-content.test.ts": "adapters/openai", "openai-chat-serialized-tool-call-hold-bound.test.ts": "adapters/openai", "openai-chat-serialized-tool-call-think.test.ts": "adapters/openai", + "openai-chat-system-order.test.ts": "adapters/openai", "responses-chat-tool-call-content.test.ts": "responses", "openai-chat-tool-result-images.test.ts": "adapters/openai", "openai-chat-url.test.ts": "adapters/openai", + "openai-chat-video-part.test.ts": "adapters/openai", "openai-provider-option-e2e.test.ts": "adapters/openai", "openai-provider-option-migration.test.ts": "adapters/openai", "openai-provider-option-startup.test.ts": "adapters/openai", + "openai-provider-option-tooling.test.ts": "adapters/openai", + "openai-provider-option.test.ts": "adapters/openai", + "responses-forward-client-headers.test.ts": "responses", + "openai-responses-passthrough.test.ts": "responses", + "responses-native-item-extensions.test.ts": "responses", + "responses-native-item-extensions-compact.test.ts": "responses", + "responses-main-quota-observation.test.ts": "responses", "compaction-continuation-note.test.ts": "responses", "compaction-continuation-wire.test.ts": "responses", + "external-task-input-repair.test.ts": "responses", + "openai-responses-summary-none.test.ts": "responses", + "responses-forward-output-cap.test.ts": "responses", + "opencode-cli.test.ts": "providers", + "opencode-free-provider.test.ts": "providers", + "opencode-go-deepseek.test.ts": "providers", + "opencode-go-grok46-responses.test.ts": "providers", + "opencode-go-luna-wire.test.ts": "providers", + "opencode-go-muse-context.test.ts": "providers", + "opencode-go-muse-vision.test.ts": "providers", + "opencode-go-quota.test.ts": "providers", + "opencode-go-session-header.test.ts": "providers", + "opencode-management-transport.test.ts": "providers", + "opencode-zen-deepseek-reasoning.test.ts": "providers", + "opencode-zen-rate-limit.test.ts": "providers", + "opengateway-provider.test.ts": "providers", + "opengateway-key-validation.test.ts": "providers", + "openrouter-provider-routing.test.ts": "providers", + "openrouter-quota-reset-cooldown-4024.test.ts": "providers", + "opper-provider.test.ts": "providers", "modelflare-provider.test.ts": "providers", + "tokenlab-protocols.test.ts": "providers", + "tokenlab-provider.test.ts": "providers", + "optional-shutdown-hooks.test.ts": "lib", + "orca-import.test.ts": "codex-integration", + "orcarouter-provider.test.ts": "providers", + "outbound-body-guard.test.ts": "server", + "owned-service-home.test.ts": "server", + "package-tree-fenced-restart.test.ts": "ci-workflows", + "package-tree-integrity.test.ts": "ci-workflows", + "package-tree-restart-ownership.test.ts": "ci-workflows", + "package-tree-retarget.test.ts": "ci-workflows", + "parallel-tool-calls-optin.test.ts": "codex-integration", + "parser-content-audio.test.ts": "responses", + "passive-route-linker.test.ts": "server", + "passthrough-abort.test.ts": "responses", + "passthrough-grok-upstream-envelope-echo.test.ts": "responses", + "passthrough-headers.test.ts": "responses", + "passthrough-override.test.ts": "responses", + "phase100-native-parity.test.ts": "e2e-style", + "physical-send.test.ts": "adapters", + "pinned-http-content-coding.test.ts": "lib", + "pinned-http.test.ts": "lib", + "pinned-https-get.test.ts": "images", + "plaintext-v2-agent-messages-server.test.ts": "server", + "plaintext-v2-agent-messages.test.ts": "responses", + "plan-video.test.ts": "videos", + "plan.test.ts": "images", + "platform-dialog-guard.test.ts": "gui", + "policy-execution.test.ts": "routing", + "pool-kernel-generic-sweep.test.ts": "oauth", + "port-reclaim.test.ts": "server", + "ports.test.ts": "server", + "pr-readiness-reattest.test.ts": "ci-workflows", + "privacy-mask-account.test.ts": "lib", + "privacy-scan-asset-names.test.ts": "ci-workflows", + "privacy-scan-meta-key.test.ts": "ci-workflows", + "privacy-scan-ssh-endpoint.test.ts": "ci-workflows", + "probe-lease-dispatch-wiring.test.ts": "routing", + "probe-lease.test.ts": "routing", + "process-control-graceful.test.ts": "lib", + "process-control.test.ts": "lib", + "process-state.test.ts": "service", + "project-config-warnings.test.ts": "codex-integration", + "provider-account-quota-persistence.test.ts": "providers", + "provider-account-quota-routes.test.ts": "server", + "provider-account-quota.test.ts": "providers", + "provider-api-keys.test.ts": "providers", + "provider-capacity.test.ts": "providers", + "provider-config-batch-management.test.ts": "providers", + "provider-config-validation.test.ts": "providers", + "provider-connection-test.test.ts": "providers", + "provider-cost-overlay-config.test.ts": "providers", + "provider-discovery-log-suppression.test.ts": "providers", + "provider-egress-fetch.test.ts": "responses", + "provider-egress-management-validation.test.ts": "server", + "provider-egress-outbound.test.ts": "providers", + "provider-egress.test.ts": "lib", + "provider-id-rewrite.test.ts": "providers", + "provider-key-store.test.ts": "providers", + "provider-live-models.test.ts": "providers", + "provider-model-aliases.test.ts": "providers", + "provider-model-discovery-contract.test.ts": "providers", + "provider-outbound-private-network.test.ts": "providers", + "provider-outbound.test.ts": "providers", + "provider-runtime-fetch.test.ts": "providers", + "provider-tls-profile.test.ts": "providers", + "provider-payload.test.ts": "gui", + "provider-quota-label-sanitize.test.ts": "providers", + "provider-quota-observed-marker.test.ts": "providers", + "provider-quota-ollama-cloud.test.ts": "providers", + "provider-quota.test.ts": "providers", + "provider-registry-parity.test.ts": "providers", "haiku-5-5-catalog.test.ts": "providers", + "provider-send-path-import.test.ts": "server", + "provider-static-model-discovery.test.ts": "providers", + "provider-subscription-cli.test.ts": "gui", + "provider-workspace-auth.test.ts": "gui", + "provider-workspace-data.test.ts": "gui", + "provider-workspace-rail.test.ts": "gui", + "provider-workspace-state.test.ts": "gui", + "proxy-env-macos.test.ts": "server", + "proxy-env.test.ts": "server", + "proxy-liveness-package-tree-fence.test.ts": "server", + "proxy-liveness.test.ts": "server", + "qoder-adapter.test.ts": "providers", "qoder-live-models.test.ts": "providers", "qoder-mcp-server.test.ts": "providers", + "qoder-scaffold-guard.test.ts": "providers", + "quota-401-recovery-runtime.test.ts": "usage", + "quota-401-recovery.test.ts": "usage", + "quota-bars-rows.test.ts": "gui", + "quota-reset-account-key.test.ts": "usage", + "quota-reset-core-boundary.test.ts": "usage", + "quota-reset-detector.test.ts": "usage", + "quota-reset-notify-config.test.ts": "usage", + "quota-reset-notify.test.ts": "usage", + "quota-reset-observation.test.ts": "usage", + "quota-reset-seen-store.test.ts": "usage", + "quota-scoring.test.ts": "usage", + "qwen-cloud-endpoints.test.ts": "gui", + "qwen38-preserve-reasoning.test.ts": "providers", + "rate-limit-reset-credits.test.ts": "gui", + "rate-limit-retry.test.ts": "providers", + "reasoning-effort-summary-default.test.ts": "responses", + "reasoning-effort.test.ts": "codex-integration", + "reasoning-envelope.test.ts": "responses", + "reasoning-metadata.test.ts": "codex-integration", + "reasoning-replay-identity.test.ts": "adapters", + "reasoning-replay-robustness.test.ts": "adapters", + "reasoning-replay-scope-source.test.ts": "lib", + "redact.test.ts": "lib", + "relay-eager.test.ts": "server", + "release-desktop-scripts.test.ts": "ci-workflows", + "release-helper.test.ts": "ci-workflows", + "release-notes.test.ts": "ci-workflows", + "release-outcome-report.test.ts": "ci-workflows", + "release-pipeline-contract.test.ts": "ci-workflows", + "release-preflight.test.ts": "ci-workflows", + "release-resume-identity.test.ts": "ci-workflows", + "release-version-line.test.ts": "ci-workflows", + "release-version-sources.test.ts": "ci-workflows", + "remove-tree-helper.test.ts": "lib", + "fixture-teardown-helper.test.ts": "ci-workflows", + "replay-refusal-parity.test.ts": "server", + "repo-hygiene.test.ts": "ci-workflows", + "request-decompress.test.ts": "usage", + "request-evidence.test.ts": "usage", + "request-history-index.test.ts": "usage", + "request-log-attempt-identity.test.ts": "usage", + "request-log-conversation.test.ts": "usage", + "request-log-estimate-cap.test.ts": "usage", + "request-log-jev.test.ts": "usage", + "request-log-nonstream.test.ts": "usage", + "request-log-protocol-trace.test.ts": "usage", + "request-log-served-model.test.ts": "usage", "request-log-model-filter.test.ts": "usage", + "request-log-generation-window.test.ts": "usage", + "request-log.test.ts": "usage", "upstream-failure-diagnostics.test.ts": "usage", + "request-outcome-agreement.test.ts": "usage", + "request-pacing.test.ts": "usage", + "reserve-auth-context.test.ts": "codex-integration", + "reserve-availability.test.ts": "codex-integration", + "reserve-catalog-lifecycle.test.ts": "codex-integration", + "reserve-catalog.test.ts": "codex-integration", + "reserve-claude-policy.test.ts": "server", + "reserve-dispatch-ws.test.ts": "responses", + "reserve-dispatch.test.ts": "codex-integration", + "reserve-helper-boundary.test.ts": "codex-integration", + "reserve-ingress.test.ts": "server", + "reserve-passive-revocation.test.ts": "codex-integration", + "reserve-quota-scope.test.ts": "codex-integration", + "resolved-model-policy-consumers.test.ts": "routing", + "resolved-model-policy.test.ts": "providers", + "response-log-inspection.test.ts": "server", + "response-model-identity.test.ts": "server", + "responses-4546-incident-regression.test.ts": "responses", + "responses-account-change-scrub.test.ts": "responses", + "responses-account-label.test.ts": "responses", + "responses-anthropic-fast-downgrade.test.ts": "responses", + "responses-azure-opaque-blob-recovery.test.ts": "responses", + "responses-bare-echo-helper-fence.test.ts": "responses", + "responses-canonical-only-top-level-fields.test.ts": "responses", + "responses-chatgpt-web-replay-metadata.test.ts": "responses", + "responses-code-mode-goal-helpers.test.ts": "responses", + "responses-code-mode-patch-compile.test.ts": "responses", + "responses-code-mode-shell-compile.test.ts": "responses", + "responses-compact-handoff-admission.test.ts": "responses", + "responses-compaction-override.test.ts": "responses", + "responses-compaction-policy-identity.test.ts": "responses", + "responses-compaction-http-isolation.test.ts": "responses", "responses-compaction-routing.test.ts": "responses", + "responses-compaction.test.ts": "responses", + "responses-console-go-upload-retry.test.ts": "responses", + "responses-context-overflow.test.ts": "responses", + "responses-continuation-boundaries.test.ts": "responses", + "responses-core-modules.test.ts": "responses", + "responses-custom-tool-guidance.test.ts": "responses", + "responses-custom-tool-historical-replay.test.ts": "responses", + "responses-custom-tool-repair-dispatch.test.ts": "responses", + "responses-custom-tool-repair.test.ts": "responses", + "responses-custom-tool-stream-consistency.test.ts": "responses", + "responses-default-namespace-emit-normalize.test.ts": "responses", + "responses-fetch-helpers-boundary.test.ts": "responses", + "responses-field-backfill.test.ts": "responses", + "responses-forward-dangling-call.test.ts": "responses", + "responses-forward-incomplete-quota.test.ts": "responses", + "responses-forward-posit-continuation.test.ts": "responses", + "responses-forward-prompt-envelope.test.ts": "responses", + "responses-freeform-wrapper-keys.test.ts": "responses", + "responses-function-tool-repair.test.ts": "responses", + "responses-hosted-tool-declaration.test.ts": "responses", + "responses-hosted-tool-min-spread.test.ts": "responses", + "responses-hide-raw-reasoning.test.ts": "responses", + "responses-image-gen-repair.test.ts": "responses", + "responses-inbound-store-default.test.ts": "responses", + "responses-item-id-repair.test.ts": "responses", + "responses-json-events.test.ts": "responses", + "responses-legacy-dotted-tool-name-repair.test.ts": "responses", + "responses-muse-tool-name-alias.test.ts": "responses", + "responses-muse-tool-choice.test.ts": "responses", + "responses-native-main-refresh.test.ts": "responses", + "responses-opaque-blob-recovery.test.ts": "responses", + "responses-parser-agent-message.test.ts": "responses", + "responses-parser-malformed-content.test.ts": "responses", + "responses-parser.test.ts": "responses", + "responses-passthrough-transient-policy.test.ts": "responses", + "responses-pool-401-refresh.test.ts": "responses", + "responses-pool-refresh-attribution.test.ts": "responses", + "responses-preview-main-read-fence.test.ts": "responses", + "responses-reasoning-effort-downgrade.test.ts": "responses", + "responses-reasoning-summary-passthrough.test.ts": "responses", + "responses-reset-replay.test.ts": "responses", + "responses-translated-reset.test.ts": "responses", + "responses-routed-web-search-fields.test.ts": "responses", + "responses-self-named-namespace-scrub.test.ts": "responses", + "responses-combo-exhausted-error.test.ts": "responses", + "responses-combo-run-turn-classified-failure.test.ts": "responses", + "responses-send-budget-counts.test.ts": "responses", + "responses-send-budget-errors.test.ts": "responses", + "responses-memory-models.test.ts": "responses", + "responses-shadow-intercept.test.ts": "responses", + "responses-show-thinking-summary.test.ts": "responses", + "responses-snapshot-repair-server.test.ts": "responses", + "responses-snapshot-repair.test.ts": "responses", + "responses-sparse-terminal-tool-scope.test.ts": "responses", + "responses-spend-ledger-wiring.test.ts": "responses", + "responses-spend-contract-c.test.ts": "responses", + "responses-spend-anchor.test.ts": "responses", + "responses-spend-capacity-guard.test.ts": "responses", + "responses-spill-acl-recovery.test.ts": "responses", + "responses-spill-admission-headroom.test.ts": "responses", + "responses-spill-inspection.test.ts": "responses", + "responses-spill-orphan-sweep.test.ts": "responses", + "responses-spill-shutdown-clock.test.ts": "responses", + "responses-state-flush-race.test.ts": "responses", + "responses-state-snapshot-select.test.ts": "responses", + "responses-state-snapshot-stubs.test.ts": "responses", "responses-state-store-false.test.ts": "responses", + "responses-state-write-amplification.test.ts": "responses", + "responses-state.test.ts": "responses", + "responses-stateless-dangling-call-repair.test.ts": "responses", + "responses-stream-tool-events.test.ts": "responses", + "responses-terminal-repair.test.ts": "responses", + "responses-tool-conformance.test.ts": "responses", + "responses-tool-groups.test.ts": "responses", + "responses-tool-search-repair.test.ts": "responses", + "responses-undeclared-tool-guard.test.ts": "responses", + "responses-usage-passthrough.test.ts": "responses", + "responses-xai-request-compat.test.ts": "responses", + "restore-completes-shared-teardown.test.ts": "cli", + "retry-after-429.test.ts": "server", + "route-decision-trace.test.ts": "server", + "route-explainability.test.ts": "cli", + "routed-agent-messages.test.ts": "adapters", + "router-blocked-cross-provider.test.ts": "routing", + "router-combo-failover-classification.test.ts": "routing", + "router-discarded-baseurl-warning.test.ts": "routing", + "router-template-baseurl.test.ts": "routing", + "router.test.ts": "routing", + "routing-analytics.test.ts": "routing", + "routing-capability-catalog.test.ts": "routing", + "routing-capability-model-matching.test.ts": "routing", + "routing-compatibility-auth-identity.test.ts": "routing", + "routing-compatibility-boundaries.test.ts": "routing", + "routing-compatibility-model-matching.test.ts": "routing", + "routing-compatibility.test.ts": "routing", + "routing-identity-domains.test.ts": "routing", + "routing-intelligence-ui.test.ts": "gui", + "routing-policy-dispatch-scope.test.ts": "routing", + "routing-policy-fallback.test.ts": "routing", + "routing-policy-pool-quota.test.ts": "routing", + "routing-policy-surface-parity.test.ts": "routing", + "routing-profile-editor-data.test.ts": "gui", + "routing-profile-management-editor.test.ts": "routing", + "routing-profile.test.ts": "routing", + "run-turn-queue.test.ts": "adapters", + "sambanova-nebius-provider.test.ts": "providers", + "selected-models.test.ts": "codex-integration", + "self-launch-argv.test.ts": "lib", + "server-403-permission-e2e.test.ts": "server", + "server-agent-task-recovery-replay.test.ts": "server", + "server-antigravity-verify-replay-scope.test.ts": "server", + "server-auth-localhost-bind.test.ts": "server", + "server-auth-scoped-quota.test.ts": "server", + "server-auth.test.ts": "server", + "server-background-lifecycle.test.ts": "server", + "server-clickjacking-headers.test.ts": "server", + "server-combo-cooldown-fallback.test.ts": "server", + "server-combo-failover-e2e.test.ts": "server", + "server-combo-held-response.test.ts": "server", + "server-combo-reasoning-replay-eligibility.test.ts": "server", + "server-combo-zero-output-failover.test.ts": "server", + "server-google-antigravity-oauth-401-replay.test.ts": "server", + "server-antigravity-web-search-validation.test.ts": "server", "server-google-antigravity-oauth-429-budget.test.ts": "server", + "server-gui-bundle-freshness.test.ts": "server", + "server-images-bodyless-content-length.test.ts": "server", + "server-images-pool-admission.test.ts": "server", + "server-images.test.ts": "server", + "server-key-failover-e2e.test.ts": "server", + "server-jev-combo-e2e.test.ts": "server", "combo-requested-effort.test.ts": "server", + "server-kiro-completion-e2e.test.ts": "server", + "server-kiro-device-login.test.ts": "server", "server-kiro-oauth-401-replay.test.ts": "server", + "server-kiro-refusal-e2e.test.ts": "server", "server-live-existing-call.test.ts": "server", + "server-live-frame-log.test.ts": "server", + "server-live-realtime-fixtures.test.ts": "server", + "server-live.test.ts": "server", + "server-loopback-host-gate.test.ts": "server", + "server-management-auth.test.ts": "server", "server-management-log-admission.test.ts": "server", + "server-opencode-go-goal-streaming.test.ts": "server", + "server-rate-limit-retry-e2e.test.ts": "server", + "server-request-body-size.test.ts": "server", + "server-search.test.ts": "server", + "server-startup-reconcile-resilience.test.ts": "server", + "server-stop-config-hardening.test.ts": "server", + "server-xai-chat-reasoning-streaming.test.ts": "server", + "server-xai-header-parity.test.ts": "server", + "server-xai-oauth-401-replay.test.ts": "server", + "server-xai-responses-streaming.test.ts": "server", + "service-auth-qualified-localhost.test.ts": "service", + "service-child-ownership.test.ts": "service", + "service-handled-signal-exit.test.ts": "service", "service-health-sentinel-linux.test.ts": "service", "service-health-sentinel-launch.test.ts": "service", "service-health-sentinel-policy.test.ts": "service", "service-health-sentinel-process.test.ts": "service", "service-health-sentinel-runner.test.ts": "service", + "service-claim.test.ts": "service", + "service-ownership-compatibility.test.ts": "service", + "service-ownership-handover.test.ts": "service", + "service-ownership-state.test.ts": "service", "ownership-mutation-lease-diagnostics.test.ts": "service", + "service-probe-docker.test.ts": "service", + "service-secrets.test.ts": "service", + "service-sqlite-home.test.ts": "service", + "service-stop-verification.test.ts": "service", + "service-tier-capability.test.ts": "service", + "service-wsl-home-ownership.test.ts": "service", + "service.test.ts": "service", + "service-multishell-path.test.ts": "service", + "serving-runtimes.test.ts": "config", + "session-affinity.test.ts": "server", + "session-lane-recall-harness.test.ts": "server", + "settings-desktop-switch-apply.test.ts": "config", + "settings-fast-rows.test.ts": "config", + "settings-main-account-hard-lock.test.ts": "config", + "settings-memory-models.test.ts": "config", + "settings-oauth-open-browser.test.ts": "config", + "settings-startup-health-seam.test.ts": "config", + "settings-stream-mode.test.ts": "config", + "setup-hooks.test.ts": "ci-workflows", + "shadow-intercept-target-lifecycle.test.ts": "responses", + "shutdown-drain.test.ts": "service", + "shutdown-launcher.test.ts": "service", + "sidebar-routes.test.ts": "server", + "sidebar-star-state.test.ts": "server", + "sidecar-abort.test.ts": "vision", + "sidecar-auth.test.ts": "vision", + "sidecar-candidates.test.ts": "vision", + "sidecar-settings-vision-controls.test.ts": "vision", + "sidecar-settings-vision-filter.test.ts": "vision", + "sidecar-settings-web-search-gate.test.ts": "vision", + "sidecar-settings-web-search-off.test.ts": "vision", + "sidecar-settings-web-search-stream.test.ts": "vision", + "sidecar-tracker.test.ts": "vision", + "skill-ocx.test.ts": "ci-workflows", + "slug-codec.test.ts": "codex-integration", + "socks5-fetch.test.ts": "lib", "socks5-tls-lifecycle.test.ts": "lib", + "socks5-upload-lifecycle.test.ts": "lib", + "spend-ceiling-enforcement.test.ts": "lib", + "spend-instrumentation-log.test.ts": "server", + "spend-ledger-file-journal.test.ts": "lib", + "spend-ledger-lifecycle.test.ts": "server", + "spend-ledger-owner-startup.test.ts": "server", + "spend-ledger-owner.test.ts": "lib", + "spend-pool-continuity.test.ts": "lib", + "spend-contract-c.test.ts": "lib", + "spend-corruption-compat.test.ts": "lib", + "spend-unbound-expiry.test.ts": "lib", + "spend-seed-overflow.test.ts": "lib", + "spend-zero-config-compat.test.ts": "lib", + "spend-experimental-history.test.ts": "lib", + "spend-reservation-ledger.test.ts": "lib", + "sponsor-presets.test.ts": "providers", + "sse-carriage-return.test.ts": "responses", + "sse-client-frame-bounds.test.ts": "responses", + "sse-decoder.test.ts": "responses", + "sse-failed-tail.test.ts": "responses", + "sse-inspector-bounds.test.ts": "responses", + "sse-null-data-frame.test.ts": "responses", + "sse-payload-rewrite.test.ts": "responses", + "sse-rewrite-line-endings.test.ts": "responses", + "chat-sse-framing-guard.test.ts": "responses", + "sse-unspaced-data-fields.test.ts": "responses", + "stale-state-purge.test.ts": "service", + "stall-subprocess-exit.test.ts": "lib", + "stall-timeout.test.ts": "lib", + "standalone-build-script.test.ts": "gui", + "standalone-service.test.ts": "service", + "standalone.test.ts": "lib", + "star-deferral.test.ts": "cli", + "start-args.test.ts": "cli", + "start-ownership-publication.test.ts": "cli", + "startup-action-control-elevation.test.ts": "server", + "startup-action-control.test.ts": "server", "login-shell-path.test.ts": "server", + "startup-health-ui.test.ts": "gui", + "startup-prompt.test.ts": "server", + "state-store-sweeper.test.ts": "oauth", + "stepfun-provider.test.ts": "providers", + "stop-deferred-teardown.test.ts": "service", + "storage-cleanup.test.ts": "storage", + "storage-mutation-race.test.ts": "storage", + "storage-policy-config-race.test.ts": "storage", + "storage-policy-job-responsive.test.ts": "storage", + "storage-policy.test.ts": "storage", + "storage-restore-job-errors.test.ts": "storage", + "storage-restore-job-responsive.test.ts": "storage", + "storage-scanner.test.ts": "storage", + "storage-worker-lifecycle.test.ts": "storage", + "storage-worker-os-join-settle.test.ts": "storage", + "storage-worker-teardown-isolate.test.ts": "storage", + "stream-aborted-marker.test.ts": "server", + "strict-semver.test.ts": "lib", + "structure-ssot.test.ts": "ci-workflows", + "subagent-context-staleness.test.ts": "routing", + "subagent-defaults.test.ts": "routing", + "subagent-fallback-handle-responses.test.ts": "routing", + "subagent-fallback-preview-sites.test.ts": "routing", + "subagent-model-fallback-api.test.ts": "routing", + "subagent-model-fallback.test.ts": "routing", + "codex-agent-role-models.test.ts": "routing", + "codex-role-sizing.test.ts": "routing", + "codex-role-auto-assign.test.ts": "routing", + "codex-agent-role-routes.test.ts": "server", + "codex-role-auto-assign-routes.test.ts": "server", + "local-chat-completion.test.ts": "lib", + "injection-model-suggest-routes.test.ts": "codex-integration", + "subagent-roster-retention.test.ts": "routing", + "synced-state-location.test.ts": "lib", + "synthetic-tool.test.ts": "images", + "system-env.test.ts": "server", + "system-restart-client-package-tree.test.ts": "cli", + "system-restart-client.test.ts": "cli", + "system-restart-contract-security.test.ts": "lib", + "system-restart-admission.test.ts": "server", + "system-restart.test.ts": "server", + "system-routes.test.ts": "server", + "systemd-install-cleanup-hardening.test.ts": "service", + "tencent-siliconflow-providers.test.ts": "gui", + "terminal-continuation-owner-rotation.test.ts": "adapters", + "terminal-guard-server.test.ts": "server", + "terminal-guard.test.ts": "server", + "test-home-guard.test.ts": "ci-workflows", + "test-runner.test.ts": "ci-workflows", "test-runner-bun.test.ts": "ci-workflows", "test-runner-spawnsync-finalizer.test.ts": "ci-workflows", "test-sandbox-cleanup.test.ts": "ci-workflows", "test-temp-quarantine.test.ts": "ci-workflows", + "thought-signature-credential-scope.test.ts": "responses", + "token-estimate.test.ts": "lib", + "token-guardian.test.ts": "codex-integration", + "tool-argument-integers.test.ts": "adapters", + "tool-catalog-nudge.test.ts": "adapters", + "tool-choice-performance.test.ts": "adapters", + "transient-budget-scope-source.test.ts": "lib", + "translator-budget.test.ts": "adapters", "translator-budget-lifetime.test.ts": "adapters", "catalog-async-lifetime.test.ts": "codex-integration", + "transport-null-body.test.ts": "lib", + "tray-proxy-deadline.test.ts": "windows", + "tray-proxy.test.ts": "windows", + "types-barrel-identity.test.ts": "config", + "ultrafast-tier-honesty.test.ts": "codex-integration", "configured-ultrafast-picker.test.ts": "codex-integration", "native-ultrafast-picker.test.ts": "codex-integration", + "umans-provider.test.ts": "providers", + "uninstall.test.ts": "cli", + "update-async-routes.test.ts": "server", + "update-badge.test.ts": "update", "update-bun-ownership-lease.test.ts": "update", + "update-desktop-badge.test.ts": "update", "update-desktop-owner.test.ts": "update", "update-supervised-recovery.test.ts": "update", + "update-job.test.ts": "update", "update-job-supervised-restart.test.ts": "update", "update-standalone.test.ts": "update", "update-worker-launch.test.ts": "update", + "update-notify.test.ts": "update", "update-npm-cache-preflight.test.ts": "update", + "update-npm-invocation.test.ts": "update", "update-mise-launcher-target.test.ts": "update", + "update-mise.test.ts": "update", "update-mise-node-runtime.test.ts": "update", + "update-pnpm.test.ts": "update", + "update-refresh.test.ts": "update", + "update-restart-lease.test.ts": "update", + "update-stop-classification.test.ts": "update", + "update-stop-first.test.ts": "update", + "update-transactional-leftovers.test.ts": "update", + "update-transactional.test.ts": "update", + "update-tray-handoff.test.ts": "update", + "update-tree-ownership.test.ts": "update", + "upstream-connect-error.test.ts": "server", + "upstream-error-message-fallback.test.ts": "lib", + "upstream-http-error.test.ts": "adapters", + "upstream-http-version.test.ts": "server", + "upstream-reachability.test.ts": "codex-integration", + "upstream-retry.test.ts": "lib", + "upstream-retry-zero-output.test.ts": "lib", + "upstream-transient-retry.test.ts": "providers", + "url-normalization.test.ts": "config", + "usage-aggregate-cache.test.ts": "usage", + "usage-anthropic-fast-pricing.test.ts": "usage", + "usage-cursor-fast-pricing.test.ts": "usage", + "usage-attempt-delivery.test.ts": "usage", + "usage-cost.test.ts": "usage", "usage-haiku-5-5-pricing.test.ts": "usage", + "usage-debug.test.ts": "usage", + "usage-failure-fingerprint.test.ts": "usage", + "usage-failure-persistence.test.ts": "usage", + "usage-failure-projection.test.ts": "usage", + "usage-ledger-retention.test.ts": "usage", + "usage-ledger-scanner.test.ts": "usage", + "usage-log-ws-stage.test.ts": "usage", + "usage-log.test.ts": "usage", + "usage-provider-label.test.ts": "usage", + "usage-shape-extraction.test.ts": "usage", + "usage-spend-cache-provenance.test.ts": "usage", + "usage-summary.test.ts": "usage", + "usage-throughput.test.ts": "usage", + "usage-surfaces.test.ts": "usage", + "usage-time-range.test.ts": "usage", + "usage-timeline.test.ts": "usage", + "user-cost-overlay-coderabbit-regressions.test.ts": "usage", + "user-cost-overlay-live-reconcile.test.ts": "usage", + "user-cost-overlay-provider-delete.test.ts": "usage", + "v1-hub-state.test.ts": "server", + "v2-agent-message-failfast.test.ts": "server", + "vercel-gateway-provider-routing.test.ts": "providers", + "version-line.test.ts": "ci-workflows", + "vertex-catalog.test.ts": "adapters/google", + "vision-anthropic.test.ts": "vision", + "vision-backend-union.test.ts": "vision", + "vision-cache.test.ts": "vision", + "vision-classification-seed-repair.test.ts": "providers", + "vision-custom-row-precedence.test.ts": "vision", + "vision-eligibility.test.ts": "vision", + "vision-fail-closed.test.ts": "vision", + "vision-reasoning-contract.test.ts": "vision", + "vision-routed.test.ts": "vision", + "vision-sidecar-e2e.test.ts": "vision", + "vision-sidecar-timeout-bounds.test.ts": "gui", + "vision-text-only-predicate.test.ts": "vision", + "volcengine-ark-assistant-content.test.ts": "providers", + "volcengine-providers.test.ts": "gui", + "warmup-registration.test.ts": "ci-workflows", + "warmup.test.ts": "codex-integration", + "web-search-anthropic.test.ts": "web-search", + "devin-web-search.test.ts": "web-search", + "web-search-recovery-kind.test.ts": "web-search", + "chat-legacy-functions-combo.test.ts": "responses", + "web-search-backend-union.test.ts": "web-search", + "web-search-bridge-replay.test.ts": "web-search", + "web-search-candidates.test.ts": "web-search", + "web-search-parse.test.ts": "web-search", + "web-search-passthrough-bridge.test.ts": "web-search", + "web-search-progress-stream.test.ts": "web-search", + "web-search-retry-heartbeat.test.ts": "web-search", + "web-search-sidecar-429.test.ts": "web-search", + "web-search-sources.test.ts": "web-search", + "web-search-timeout-contract.test.ts": "web-search", "web-search-pacing-deadline.test.ts": "web-search", + "web-search-timeout-plan.test.ts": "web-search", + "web-search.test.ts": "web-search", + "win-exec.test.ts": "windows", + "win-paths.test.ts": "windows", + "windows-acl-start-cost.test.ts": "windows", + "windows-atomic-replace.test.ts": "windows", + "windows-deploy-close-regressions.test.ts": "windows", + "windows-elevation-spawn.test.ts": "windows", + "windows-elevation.test.ts": "windows", + "windows-guarded-manager.test.ts": "windows", + "windows-popup-fix.test.ts": "windows", + "windows-process-priority.test.ts": "windows", + "windows-scheduler-install-verification.test.ts": "windows", + "windows-secret-acl.test.ts": "windows", "windows-secret-acl-removal-flight.test.ts": "windows", + "windows-config-read-acl-memo.test.ts": "windows", + "windows-service-mutation-lock.test.ts": "windows", + "windows-service-wrappers.test.ts": "windows", + "windows-text-decoding.test.ts": "windows", + "windows-tray-restart-hardening.test.ts": "windows", + "windows-tray-run-limit.test.ts": "windows", + "windows-tray.test.ts": "windows", + "windows-user-principal-nonascii.test.ts": "windows", + "windows-user-principal.test.ts": "windows", + "winsw-stop-hardening.test.ts": "windows", + "winsw.test.ts": "service", + "workflow-budget.test.ts": "lib", + "ws-ambiguous-resend.test.ts": "responses", "ws-pre-output-refusal.test.ts": "responses", "responses-pool-overload-failover.test.ts": "responses", "compact-transient-alternate.test.ts": "responses", + "ws-endpoint.test.ts": "responses", + "ws-failure-stage.test.ts": "responses", + "ws-native-injection.test.ts": "responses", + "ws-native-result-continuations.test.ts": "responses", + "ws-native-steering.test.ts": "responses", + "ws-steering-completion.test.ts": "responses", + "ws-steering-smoke.test.ts": "responses", + "ws-steering-stability.test.ts": "responses", + "ws-upstream-reuse.test.ts": "responses", "codex-ws-pool-contention.test.ts": "responses", + "ws-upstream-socks5.test.ts": "responses", + "ws-upstream.test.ts": "responses", + "xai-client.test.ts": "images", + "xai-empty-catalog-tool-choice.test.ts": "providers/xai", + "xai-no-stop.test.ts": "providers/xai", + "xai-oauth-retry.test.ts": "providers/xai", + "xai-refresh-lock.test.ts": "providers/xai", + "xai-responses-adjacency.test.ts": "providers/xai", + "xai-tool-schema.test.ts": "providers/xai", + "xai-transport.test.ts": "providers/xai", + "xai-video-client.test.ts": "videos", + "xai-web-search-compat.test.ts": "providers/xai", + "xai-web-search.test.ts": "providers/xai", + "yaml-fragment-source.test.ts": "config", + "z-fulfill.test.ts": "images", + "z-handler-activation.test.ts": "images", + "zai-reasoning-replay.test.ts": "providers", + "zcode-client.test.ts": "providers", + "zhipu-bigmodel-provider.test.ts": "providers", + "zhipu-bigmodel-responses-quota.test.ts": "providers", + "zz-ci-api-usage-isolation.test.ts": "ci-workflows", + "zz-ci-storage-policy-isolation.test.ts": "ci-workflows", + "zz-pr-coderabbit-readiness-revalidation.test.ts": "ci-workflows", + "injection-link-websocket.test.ts": "codex-integration", + "cli-link.test.ts": "cli", "cli-link-enrollment.test.ts": "cli", + "link-management-routes.test.ts": "server", "link-enrollment.test.ts": "server", + "web-search-run-turn-loop.test.ts": "web-search", + "responses-run-turn-web-search.test.ts": "responses", + "responses-claude-preflight-lease.test.ts": "responses", + "server-combo-cooldown-recording.test.ts": "server", + "injection-routing-drift.test.ts": "codex-integration", "injection-routing-healer.test.ts": "codex-integration", + "injection-routing-heal-apply.test.ts": "codex-integration", "cli-start-routing-heal-wiring.test.ts": "cli", + "cli-status-codex-routing-drift.test.ts": "cli", "advisor-settings.test.ts": "advisor", "advisor-context.test.ts": "advisor", "advisor-state.test.ts": "advisor", "advisor-guard.test.ts": "advisor", "advisor-consult.test.ts": "advisor", "advisor-plan.test.ts": "advisor", "advisor-responses-wiring.test.ts": "advisor", "advisor-routes.test.ts": "server", "advisor-internal-authority.test.ts": "advisor", "advisor-core-boundary.test.ts": "advisor", "advisor-continuation-limit.test.ts": "advisor", "advisor-authority-transport.test.ts": "advisor" + } +} diff --git a/skills/ocx/references/01_management_surface.md b/skills/ocx/references/01_management_surface.md index 21cf6f40bf3..ed99772afba 100644 --- a/skills/ocx/references/01_management_surface.md +++ b/skills/ocx/references/01_management_surface.md @@ -30,7 +30,7 @@ These answer in the CLI head and never reach the proxy, so they work with nothin | [accounts](01_surface_accounts.md) | 42 | | [agents-routing](01_surface_agents-routing.md) | 51 | | [integrations](01_surface_integrations.md) | 41 | -| [observe-system](01_surface_observe-system.md) | 93 | +| [observe-system](01_surface_observe-system.md) | 95 | | [access-remote](01_surface_access-remote.md) | 32 | | [lab](01_surface_lab.md) | 21 | @@ -931,6 +931,14 @@ Original invocation order. These headings preserve links to the previous single- [Read-oriented task](01_surface_observe-system.md#ocx-observe-logs) +### `ocx logs history` + +[Read-oriented task](01_surface_observe-system.md#ocx-logs-history) + +### `ocx logs get` + +[Read-oriented task](01_surface_observe-system.md#ocx-logs-get) + ### `ocx logs explain` [Read-oriented task](01_surface_observe-system.md#ocx-logs-explain) @@ -1405,6 +1413,6 @@ Original invocation order. These headings preserve links to the previous single- ## Counts -- declared capabilities: 339 +- declared capabilities: 341 - of those, state-changing: 207 - head-resolved invocations: 2 diff --git a/skills/ocx/references/01_surface_observe-system.md b/skills/ocx/references/01_surface_observe-system.md index 33d088d8375..d0a0a4e3970 100644 --- a/skills/ocx/references/01_surface_observe-system.md +++ b/skills/ocx/references/01_surface_observe-system.md @@ -8,7 +8,7 @@ Use these declarations to choose a task, then check its flags and authority before execution. Non-mutating probes may still contact providers, consume quota or refresh caches. -Declared capabilities: 93. +Declared capabilities: 95. ### `ocx companion` @@ -96,7 +96,7 @@ JSON mode: `payload`. - Follow uses the server cursor and a bounded ordered window, preserving same-ID amendments and repeated row occurrences. It never enables logging. - --events emits version1 snapshots/appends with cursor and limit for observed-window reconstruction. Legacy row JSONL cannot express removals or resets exactly; neither mode promises lossless history between polls. - Follow limit is1–2000, default200. Polling is serial and cancellable; SIGINT exits130 and SIGTERM143. Malformed/oversized/unavailable responses stop without a fabricated empty snapshot or retry. -- Nested explain reads recorded decisions; rebuild-index and index-status touch the local derived index and retain separate declarations. +- Nested history pages the derived index and get reads one canonical row; explain reads recorded decisions; rebuild-index and index-status touch the local derived index and retain separate declarations. ### `ocx storage report` @@ -566,6 +566,63 @@ JSON mode: `payload`. - --events emits version1 snapshots/appends with cursor and limit for observed-window reconstruction. Legacy row JSONL cannot express removals or resets exactly; neither mode promises lossless history between polls. - Follow limit is1–2000, default200. Polling is serial and cancellable; SIGINT exits130 and SIGTERM143. Malformed/oversized/unavailable responses stop without a fabricated empty snapshot or retry. +### `ocx logs history` + +Usage: `ocx logs history [--provider ] [--model ] [--requested-model ] [--status ] [--conversation ] [--surface ] [--protocol ] [--api-key-id ] [--profile ] [--fallback ] [--from ] [--to ] [--cursor ] [--limit <1-100>] [--json|--jsonl]` + +Page the indexed request-history ledger with filters and a resumable cursor. + +State-changing: no. + +| Method | Route | +|---|---| +| GET | `/api/request-history` | + +| Flag | Value | Meaning | +|---|---|---| +| `--provider` | string | Filter provider, including failover attempts. | +| `--model` | string | Filter served model, including failover attempts. | +| `--requested-model` | string | Filter the model the client asked for. | +| `--status` | number | HTTP status 100-599. | +| `--conversation` | string | Conversation ID or stored hash. | +| `--conversationId` | string | Alias of --conversation. | +| `--surface` | string | Calling client surface recorded on the row. | +| `--protocol` | string | Inbound wire: responses, chat or messages. | +| `--api-key-id` | string | Exact management key id recorded on the row. | +| `--profile` | string | Routing profile id. | +| `--fallback` | string | true selects rows that failed over; false selects rows that did not. | +| `--from` | string | Inclusive start as epoch milliseconds or ISO datetime with timezone. | +| `--to` | string | Inclusive end as epoch milliseconds or ISO datetime with timezone. | +| `--cursor` | string | Opaque nextCursor from a previous page. | +| `--limit` | number | 1-100 rows; default 50. | +| `--json` | boolean | Emit the management payload, including hasMore, nextCursor and index. | +| `--jsonl` | boolean | Matching rows only; hasMore and nextCursor go to stderr. | + +JSON mode: `payload`. + +- Pages the derived request-history index, not the recent /api/logs ring. Empty matches succeed. Also accepted after observe logs. +- JSON is the management payload. JSONL emits entries only; resume with --cursor from stderr when hasMore is true. + +### `ocx logs get` + +Usage: `ocx logs get [--json]` + +Read one canonical request-history row by request ID. + +State-changing: no. + +| Method | Route | +|---|---| +| GET | `/api/request-history/{id}` | + +| Flag | Value | Meaning | +|---|---|---| +| `--json` | boolean | Emit the canonical row as JSON. | + +JSON mode: `payload`. + +- The request ID is URI-encoded. This is the stored row, not the route-decision view from logs explain. A missing id is a 404. Also accepted after observe logs. + ### `ocx logs explain` Usage: `ocx logs explain [--json]` diff --git a/skills/ocx/references/02_json_shapes.md b/skills/ocx/references/02_json_shapes.md index a8cd0a9063c..5e80e75536c 100644 --- a/skills/ocx/references/02_json_shapes.md +++ b/skills/ocx/references/02_json_shapes.md @@ -40,7 +40,7 @@ One row per line. The fields worth branching on: | Field | Meaning | |---|---| -| `requestId` | pass to `ocx logs explain` | +| `requestId` | pass to `ocx logs get` or `ocx logs explain` | | `conversationId` | groups a conversation; also printed as `conv=` in human output | | `accountLogLabel` | which account served it (`main`, `p`, `o`); also printed as `acct=