@iislee/opencodex 2.11.0 → 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS_INSTALL.md +109 -0
- package/README.md +114 -19
- package/bin/ocx.mjs +164 -36
- package/bin/package-main.mjs +1 -1
- package/gui/dist/assets/index-BF38heuV.js +104 -0
- package/gui/dist/assets/index-DMiI18Kv.css +1 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/alibaba-color.svg +1 -1
- package/gui/dist/provider-icons/antigravity-color.svg +1 -1
- package/gui/dist/provider-icons/claude-color.svg +1 -1
- package/gui/dist/provider-icons/cline-color.svg +16 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
- package/gui/dist/provider-icons/commandcode-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -1
- package/gui/dist/provider-icons/cursor-color.svg +1 -1
- package/gui/dist/provider-icons/deepseek-color.svg +1 -1
- package/gui/dist/provider-icons/firepass-color.svg +1 -1
- package/gui/dist/provider-icons/fireworks-color.svg +1 -1
- package/gui/dist/provider-icons/gemini-color.svg +1 -1
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
- package/gui/dist/provider-icons/grok.svg +1 -1
- package/gui/dist/provider-icons/groq-color.svg +1 -1
- package/gui/dist/provider-icons/huggingface-color.svg +1 -1
- package/gui/dist/provider-icons/kimi-color.svg +1 -1
- package/gui/dist/provider-icons/kiro-color.svg +2 -2
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
- package/gui/dist/provider-icons/mistral-color.svg +1 -1
- package/gui/dist/provider-icons/moonshot-color.svg +1 -1
- package/gui/dist/provider-icons/nvidia-color.svg +1 -1
- package/gui/dist/provider-icons/ollama-color.svg +1 -1
- package/gui/dist/provider-icons/openai.svg +1 -1
- package/gui/dist/provider-icons/opencode.svg +2 -1
- package/gui/dist/provider-icons/openrouter-color.svg +1 -1
- package/gui/dist/provider-icons/pi.svg +2 -2
- package/gui/dist/provider-icons/qianfan-color.svg +1 -1
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
- package/gui/dist/provider-icons/vllm-color.svg +1 -1
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
- package/package.json +19 -10
- package/src/adapters/anthropic-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +376 -52
- package/src/adapters/base.ts +54 -7
- package/src/adapters/client-fingerprint.ts +18 -12
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
- package/src/adapters/command-code.ts +601 -0
- package/src/adapters/cursor/checkpoint-store.ts +303 -0
- package/src/adapters/cursor/cursor-errors.ts +129 -6
- package/src/adapters/cursor/discovery.ts +61 -4
- package/src/adapters/cursor/effort-map.ts +27 -3
- package/src/adapters/cursor/framing.ts +39 -0
- package/src/adapters/cursor/h2-pool.ts +123 -0
- package/src/adapters/cursor/http1-bidi.ts +361 -0
- package/src/adapters/cursor/images.ts +704 -0
- package/src/adapters/cursor/live-models.ts +174 -58
- package/src/adapters/cursor/live-transport.ts +609 -170
- package/src/adapters/cursor/native-exec-common.ts +23 -2
- package/src/adapters/cursor/native-exec-fs.ts +10 -7
- package/src/adapters/cursor/native-exec-network.ts +1 -1
- package/src/adapters/cursor/native-exec-shell.ts +0 -1
- package/src/adapters/cursor/native-exec.ts +101 -14
- package/src/adapters/cursor/protobuf-events.ts +829 -11
- package/src/adapters/cursor/protobuf-request.ts +383 -65
- package/src/adapters/cursor/request-builder.ts +237 -31
- package/src/adapters/cursor/tool-definitions.ts +242 -12
- package/src/adapters/cursor/tool-result-normalize.ts +92 -0
- package/src/adapters/cursor/transport.ts +22 -0
- package/src/adapters/cursor/types.ts +28 -1
- package/src/adapters/cursor.ts +133 -7
- package/src/adapters/google-antigravity-replay.ts +558 -34
- package/src/adapters/google-antigravity-wire.ts +43 -10
- package/src/adapters/google-http.ts +38 -10
- package/src/adapters/google-tool-schema.ts +80 -15
- package/src/adapters/google-truncation.ts +11 -0
- package/src/adapters/google.ts +618 -74
- package/src/adapters/identity.ts +39 -6
- package/src/adapters/kiro-errors.ts +11 -0
- package/src/adapters/kiro-events.ts +19 -1
- package/src/adapters/kiro-thinking.ts +18 -2
- package/src/adapters/kiro-tools.ts +10 -1
- package/src/adapters/kiro.ts +92 -54
- package/src/adapters/mimo-free.ts +17 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1311 -336
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +830 -56
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +104 -21
- package/src/adapters/xai-web-search.ts +185 -0
- package/src/bridge.ts +428 -61
- package/src/chat/inbound.ts +43 -19
- package/src/chat/outbound.ts +82 -26
- package/src/claude/agents-inject.ts +32 -9
- package/src/claude/context-windows.ts +21 -5
- package/src/claude/desktop-3p.ts +243 -9
- package/src/claude/gateway-cache.ts +41 -4
- package/src/claude/inbound.ts +72 -3
- package/src/claude/model-info.ts +38 -15
- package/src/claude/outbound.ts +70 -16
- package/src/cli/account-api.ts +35 -1
- package/src/cli/account-auth.ts +33 -6
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +389 -2
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +30 -6
- package/src/cli/agent.ts +45 -1
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +29 -4
- package/src/cli/claude.ts +103 -34
- package/src/cli/codex-log-guard-doctor.ts +103 -0
- package/src/cli/codex-shim-autorestore.ts +2 -0
- package/src/cli/codex-shim-readiness.ts +76 -0
- package/src/cli/combo.ts +8 -0
- package/src/cli/config-command.ts +74 -10
- package/src/cli/dispatch.ts +593 -0
- package/src/cli/doctor.ts +315 -43
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +46 -20
- package/src/cli/help.ts +20 -271
- package/src/cli/index.ts +378 -519
- package/src/cli/init.ts +4 -17
- package/src/cli/integrations.ts +120 -2
- package/src/cli/lab.ts +607 -0
- package/src/cli/launcher-context.ts +77 -0
- package/src/cli/minimax.ts +497 -0
- package/src/cli/models-runtime.ts +35 -2
- package/src/cli/models.ts +100 -14
- package/src/cli/observe.ts +92 -3
- package/src/cli/opencode.ts +4 -2
- package/src/cli/provider-runtime.ts +18 -1
- package/src/cli/provider.ts +24 -3
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +437 -0
- package/src/cli/root.ts +86 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +6 -3
- package/src/cli/star-prompt.ts +71 -15
- package/src/cli/status.ts +10 -3
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +153 -6
- package/src/cli/v2.ts +105 -10
- package/src/cli.ts +1 -1
- package/src/clients/config-export.ts +1358 -21
- package/src/codex/account-label.ts +14 -1
- package/src/codex/account-lifecycle.ts +130 -13
- package/src/codex/account-namespaces.ts +49 -3
- package/src/codex/account-priority.ts +83 -0
- package/src/codex/account-store.ts +29 -2
- package/src/codex/account-usability.ts +25 -2
- package/src/codex/admission.ts +256 -0
- package/src/codex/affinity-debug.ts +162 -0
- package/src/codex/app-server-processes.ts +493 -106
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +849 -242
- package/src/codex/auth-collision.ts +5 -3
- package/src/codex/auth-context.ts +345 -32
- package/src/codex/autostart-health.ts +8 -1
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +68 -10
- package/src/codex/catalog/bundled.ts +331 -33
- package/src/codex/catalog/effort.ts +121 -30
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +529 -45
- package/src/codex/catalog/native-models.ts +72 -0
- package/src/codex/catalog/parsing.ts +224 -30
- package/src/codex/catalog/provider-fetch.ts +1460 -134
- package/src/codex/catalog/sync.ts +1449 -186
- package/src/codex/catalog-admission.ts +199 -0
- package/src/codex/catalog-refresh-status.ts +105 -0
- package/src/codex/catalog-write-serialization.ts +242 -0
- package/src/codex/catalog.ts +6 -3
- package/src/codex/codex-write-lock.ts +384 -0
- package/src/codex/convergence-types.ts +614 -0
- package/src/codex/convergence.ts +651 -0
- package/src/codex/coordinator-doctor.ts +332 -0
- package/src/codex/custom-model-catalog-migration.ts +176 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/features.ts +636 -39
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +407 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-migration-guardian.ts +26 -20
- package/src/codex/history-provider.ts +231 -28
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +220 -0
- package/src/codex/inject-coordination.ts +290 -0
- package/src/codex/inject.ts +1073 -152
- package/src/codex/injected-marker.ts +37 -3
- package/src/codex/integration-record.ts +266 -0
- package/src/codex/internal/catalog-writer.ts +203 -0
- package/src/codex/internal/history-writer.ts +80 -0
- package/src/codex/journal.ts +66 -4
- package/src/codex/log-guard/inspect.ts +506 -0
- package/src/codex/log-guard/lock.ts +150 -0
- package/src/codex/log-guard/maintenance.ts +403 -0
- package/src/codex/log-guard/path-safety.ts +88 -0
- package/src/codex/log-guard/policy.ts +44 -0
- package/src/codex/log-guard/processes.ts +205 -0
- package/src/codex/log-guard/protection.ts +489 -0
- package/src/codex/log-guard/sqlite-errors.ts +9 -0
- package/src/codex/main-account-cache.ts +24 -0
- package/src/codex/main-account.ts +29 -1
- package/src/codex/management-convergence.ts +167 -0
- package/src/codex/model-cache.ts +56 -10
- package/src/codex/model-entitlements.ts +353 -0
- package/src/codex/native-main-admission.ts +47 -0
- package/src/codex/native-main-auth-temp.ts +187 -0
- package/src/codex/native-main-claim.ts +178 -0
- package/src/codex/native-main-lock-file.ts +162 -0
- package/src/codex/native-main-owner.ts +329 -0
- package/src/codex/native-profile-api.ts +247 -0
- package/src/codex/native-profile-manager.ts +1531 -0
- package/src/codex/native-profile-processes.ts +121 -0
- package/src/codex/native-profile-recovery.ts +99 -0
- package/src/codex/native-profile-stage-store.ts +387 -0
- package/src/codex/native-profile-startup.ts +492 -0
- package/src/codex/native-profile-store.ts +855 -0
- package/src/codex/native-profile-types.ts +120 -0
- package/src/codex/native-residue.ts +682 -0
- package/src/codex/paths.ts +80 -1
- package/src/codex/plan-from-token.ts +140 -0
- package/src/codex/plan.ts +40 -0
- package/src/codex/plugins-doctor.ts +1 -1
- package/src/codex/pool-rotation.ts +74 -4
- package/src/codex/project-config-warnings.ts +20 -6
- package/src/codex/prompt-journal.ts +352 -0
- package/src/codex/prompt-layers.ts +967 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/quota-rejection.ts +298 -0
- package/src/codex/quota.ts +175 -13
- package/src/codex/refresh.ts +11 -2
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +505 -94
- package/src/codex/runtime.ts +159 -38
- package/src/codex/shim.ts +1009 -28
- package/src/codex/subagent-model-fallback.ts +350 -35
- package/src/codex/sync.ts +191 -2
- package/src/codex/transition-state.ts +612 -0
- package/src/codex/upstream-host-health.ts +368 -0
- package/src/codex/user-identity.ts +557 -0
- package/src/codex/warmup.ts +187 -81
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +20 -0
- package/src/combos/index.ts +4 -0
- package/src/combos/request.ts +32 -0
- package/src/combos/types.ts +81 -9
- package/src/config/provider-name.ts +24 -0
- package/src/config.ts +1762 -140
- package/src/generated/compatibility-version.json +3164 -0
- package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
- package/src/grok/inject.ts +16 -5
- package/src/grok/inspect.ts +45 -0
- package/src/grok/sync.ts +2 -2
- package/src/images/loop.ts +152 -29
- package/src/images/plan.ts +23 -13
- package/src/integrations/config-io.ts +269 -0
- package/src/integrations/journal.ts +315 -0
- package/src/integrations/merge.ts +135 -0
- package/src/integrations/mutation-flight.ts +71 -0
- package/src/integrations/native/ownership-preflight.ts +202 -0
- package/src/integrations/omp-yaml-source.ts +358 -0
- package/src/integrations/owned-refresh.ts +74 -0
- package/src/integrations/ownership.ts +111 -0
- package/src/integrations/registry.ts +159 -0
- package/src/integrations/serialize.ts +314 -0
- package/src/integrations/state.ts +361 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer-lock.ts +98 -0
- package/src/integrations/writer.ts +691 -0
- package/src/lab/artifacts/sanitize.ts +586 -0
- package/src/lab/artifacts/secure-fs.ts +475 -0
- package/src/lab/artifacts/store.ts +310 -0
- package/src/lab/automation/budgets.ts +78 -0
- package/src/lab/automation/config-persistence.ts +256 -0
- package/src/lab/automation/constants.ts +39 -0
- package/src/lab/automation/cooldown.ts +103 -0
- package/src/lab/automation/dispatch.ts +211 -0
- package/src/lab/automation/index.ts +13 -0
- package/src/lab/automation/orchestrator.ts +499 -0
- package/src/lab/automation/persistence.ts +512 -0
- package/src/lab/automation/planner.ts +371 -0
- package/src/lab/automation/policy.ts +136 -0
- package/src/lab/automation/queue.ts +191 -0
- package/src/lab/automation/recovery.ts +24 -0
- package/src/lab/automation/route-context.ts +21 -0
- package/src/lab/automation/run-key.ts +44 -0
- package/src/lab/automation/runs-query.ts +34 -0
- package/src/lab/automation/types.ts +160 -0
- package/src/lab/conformance/assertion.ts +325 -0
- package/src/lab/conformance/digest.ts +22 -0
- package/src/lab/conformance/executor.ts +741 -0
- package/src/lab/conformance/fixture-provider.ts +27 -0
- package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
- package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
- package/src/lab/conformance/harness-budget.ts +47 -0
- package/src/lab/conformance/index.ts +5 -0
- package/src/lab/conformance/jcs.ts +64 -0
- package/src/lab/conformance/json-pointer.ts +39 -0
- package/src/lab/conformance/manifest.ts +180 -0
- package/src/lab/conformance/mcp-stub.ts +179 -0
- package/src/lab/conformance/negative-controls.ts +164 -0
- package/src/lab/conformance/observation.ts +355 -0
- package/src/lab/conformance/runner.ts +68 -0
- package/src/lab/conformance/sse-normalize.ts +59 -0
- package/src/lab/conformance/suite-manifest.ts +78 -0
- package/src/lab/conformance/types.ts +214 -0
- package/src/lab/constants.ts +126 -0
- package/src/lab/digest.ts +64 -0
- package/src/lab/events/errors.ts +9 -0
- package/src/lab/events/limits.ts +117 -0
- package/src/lab/events/types.ts +229 -0
- package/src/lab/events/validate.ts +781 -0
- package/src/lab/fabric/constants.ts +40 -0
- package/src/lab/fabric/executor.ts +492 -0
- package/src/lab/fabric/index.ts +80 -0
- package/src/lab/fabric/manifest.ts +222 -0
- package/src/lab/fabric/observe.ts +489 -0
- package/src/lab/fabric/patch.ts +79 -0
- package/src/lab/fabric/producer-child.ts +139 -0
- package/src/lab/fabric/producer-isolate.ts +276 -0
- package/src/lab/fabric/producer-protocol.ts +61 -0
- package/src/lab/fabric/scratch.ts +439 -0
- package/src/lab/fabric/subject.ts +106 -0
- package/src/lab/fabric/types.ts +134 -0
- package/src/lab/fabric/verifier.ts +98 -0
- package/src/lab/index.ts +54 -0
- package/src/lab/ledger/artifact-refs.ts +127 -0
- package/src/lab/ledger/invalidation.ts +136 -0
- package/src/lab/ledger/purge.ts +310 -0
- package/src/lab/ledger/store.ts +532 -0
- package/src/lab/live/credential-lease.ts +53 -0
- package/src/lab/live/destination.ts +155 -0
- package/src/lab/live/executor.ts +336 -0
- package/src/lab/live/inert-tools.ts +56 -0
- package/src/lab/live/manifest.ts +85 -0
- package/src/lab/live/mcp-loopback.ts +57 -0
- package/src/lab/live/runner.ts +19 -0
- package/src/lab/live/sandbox.ts +61 -0
- package/src/lab/live/suite-manifest.ts +41 -0
- package/src/lab/live/transport.ts +118 -0
- package/src/lab/live/types.ts +197 -0
- package/src/lab/observe/from-conformance.ts +301 -0
- package/src/lab/observe/from-live.ts +117 -0
- package/src/lab/paths.ts +153 -0
- package/src/lab/projection/rebuild.ts +495 -0
- package/src/lab/projection/schema.ts +135 -0
- package/src/lab/projection/verdicts.ts +474 -0
- package/src/lab/projection/verification.ts +412 -0
- package/src/lab/public/bundle.ts +217 -0
- package/src/lab/public/community-authority.ts +175 -0
- package/src/lab/public/community-files.ts +29 -0
- package/src/lab/public/community.ts +479 -0
- package/src/lab/public/file-safety.ts +155 -0
- package/src/lab/public/ids.ts +26 -0
- package/src/lab/public/index.ts +16 -0
- package/src/lab/public/mutation-lock.ts +424 -0
- package/src/lab/public/operator.ts +353 -0
- package/src/lab/public/origin-purge.ts +79 -0
- package/src/lab/public/origin.ts +203 -0
- package/src/lab/public/privacy.ts +143 -0
- package/src/lab/public/private-file.ts +261 -0
- package/src/lab/public/project.ts +124 -0
- package/src/lab/public/purge-test-fault.ts +21 -0
- package/src/lab/public/purge.ts +223 -0
- package/src/lab/public/registry.ts +44 -0
- package/src/lab/public/revocation.ts +252 -0
- package/src/lab/public/signature.ts +243 -0
- package/src/lab/public/storage.ts +105 -0
- package/src/lab/public/strict-json.ts +206 -0
- package/src/lab/public/time.ts +26 -0
- package/src/lab/public/types.ts +172 -0
- package/src/lab/public/validate.ts +391 -0
- package/src/lab/query/catalog.ts +101 -0
- package/src/lab/query/connection.ts +107 -0
- package/src/lab/query/constants.ts +4 -0
- package/src/lab/query/cursor.ts +132 -0
- package/src/lab/query/dto-map.ts +277 -0
- package/src/lab/query/errors.ts +22 -0
- package/src/lab/query/freshness.ts +53 -0
- package/src/lab/query/index.ts +45 -0
- package/src/lab/query/latest-observation.ts +59 -0
- package/src/lab/query/passive-production.ts +159 -0
- package/src/lab/query/queries.ts +444 -0
- package/src/lab/query/types.ts +266 -0
- package/src/lab/subject/behavior-fingerprint.ts +77 -0
- package/src/lab/subject/installation-salt.ts +112 -0
- package/src/lab/subject/protocol-subject.ts +80 -0
- package/src/lab/subject/route-subject.ts +74 -0
- package/src/lib/app-owned-memory-stores.ts +22 -0
- package/src/lib/bounded-body.ts +153 -9
- package/src/lib/bun-runtime.ts +125 -12
- package/src/lib/bun-stream-caps.ts +13 -9
- package/src/lib/codex-restart-contract.ts +120 -0
- package/src/lib/config-ownership.ts +6 -2
- package/src/lib/destination-policy.ts +65 -1
- package/src/lib/errors.ts +44 -2
- package/src/lib/fabric-task-execution-authority.ts +7 -0
- package/src/lib/fabric-task-host.ts +29 -0
- package/src/lib/lab-activation.ts +223 -0
- package/src/lib/lab-live-execution-authority.ts +13 -0
- package/src/lib/lab-live-host.ts +30 -0
- package/src/lib/lab-live-pinned-sender.ts +56 -0
- package/src/lib/lab-live-route-production.ts +130 -0
- package/src/lib/lab-passive-linker-registration.ts +26 -0
- package/src/lib/local-management-attestation.ts +51 -0
- package/src/lib/local-management-capability.ts +100 -0
- package/src/lib/local-provider-reload-contract.ts +100 -0
- package/src/lib/optional-shutdown-hooks.ts +57 -0
- package/src/lib/pinned-http.ts +145 -26
- package/src/lib/process-control.ts +4 -1
- package/src/lib/provider-outbound.ts +49 -9
- package/src/lib/redact.ts +419 -3
- package/src/lib/self-launch-argv.ts +15 -0
- package/src/lib/server-resource-ownership.ts +71 -0
- package/src/lib/shadow-call.ts +35 -4
- package/src/lib/sse-decoder.ts +41 -0
- package/src/lib/state-store-registrations.ts +10 -2
- package/src/lib/system-restart-contract.ts +73 -0
- package/src/lib/token-estimate.ts +19 -2
- package/src/lib/tool-argument-integers.ts +202 -0
- package/src/lib/translator-budget.ts +44 -0
- package/src/lib/upstream-http-version.ts +57 -0
- package/src/lib/upstream-reachability.ts +95 -0
- package/src/lib/upstream-retry.ts +156 -3
- package/src/lib/windows-atomic-replace.ts +155 -0
- package/src/lib/windows-elevation.ts +70 -2
- package/src/lib/windows-secret-acl.ts +409 -69
- package/src/lib/windows-service-wrappers.ts +72 -0
- package/src/lib/windows-text.ts +106 -0
- package/src/lib/windows-user-principal.ts +341 -0
- package/src/lib/winsw.ts +33 -5
- package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
- package/src/oauth/account-import/index.ts +15 -0
- package/src/oauth/account-import/parser.ts +83 -0
- package/src/oauth/account-import/registry.ts +18 -0
- package/src/oauth/account-import/service.ts +75 -0
- package/src/oauth/account-import/types.ts +91 -0
- package/src/oauth/anthropic.ts +12 -1
- package/src/oauth/callback-server.ts +8 -2
- package/src/oauth/chatgpt.ts +12 -1
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +46 -5
- package/src/oauth/google-antigravity.ts +35 -3
- package/src/oauth/health.ts +20 -12
- package/src/oauth/index.ts +398 -66
- package/src/oauth/key-providers.ts +16 -0
- package/src/oauth/kimi.ts +16 -2
- package/src/oauth/kiro.ts +50 -6
- package/src/oauth/local-token-detect.ts +11 -2
- package/src/oauth/log.ts +3 -1
- package/src/oauth/login-cli.ts +88 -28
- package/src/oauth/nous.ts +798 -0
- package/src/oauth/store.ts +119 -21
- package/src/oauth/token-guardian.ts +9 -3
- package/src/pi/models.ts +2 -2
- package/src/providers/alibaba-region-migration.ts +1 -1
- package/src/providers/antigravity-models.ts +521 -31
- package/src/providers/base-url-choices.ts +10 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +144 -0
- package/src/providers/context-cap.ts +22 -5
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/derive.ts +253 -6
- package/src/providers/fastwire.ts +501 -0
- package/src/providers/free-directory.ts +10 -7
- package/src/providers/google-vertex-location.ts +14 -0
- package/src/providers/key-failover.ts +71 -3
- package/src/providers/label.ts +1 -1
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +115 -22
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -0
- package/src/providers/openai-sidecar.ts +72 -4
- package/src/providers/openai-tier-startup.ts +31 -2
- package/src/providers/openai-tiers.ts +119 -4
- package/src/providers/openai-virtual-models.ts +1 -0
- package/src/providers/opencode-zen-rate-limit.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +29 -0
- package/src/providers/quota.ts +1319 -38
- package/src/providers/registry.ts +1429 -111
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +42 -6
- package/src/providers/static-model-discovery.ts +86 -0
- package/src/providers/xai-responses-opt-in.ts +15 -0
- package/src/providers/xai-transport.ts +11 -4
- package/src/reasoning-effort.ts +49 -1
- package/src/responses/compaction.ts +26 -1
- package/src/responses/custom-tool-compat.ts +266 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/namespace-tool-compat.ts +355 -0
- package/src/responses/parser.ts +220 -38
- package/src/responses/provider-continuation.ts +98 -0
- package/src/responses/provider-opaque-metadata.ts +73 -0
- package/src/responses/reasoning-envelope.ts +9 -1
- package/src/responses/reasoning-replay-cache.ts +426 -0
- package/src/responses/schema.ts +7 -1
- package/src/responses/spill-store.ts +75 -10
- package/src/responses/state.ts +565 -27
- package/src/responses/thought-signature-replay.ts +347 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/router.ts +366 -30
- package/src/routing/analytics.ts +378 -0
- package/src/routing/capability.ts +244 -0
- package/src/routing/compatibility/assemble.ts +73 -0
- package/src/routing/compatibility/behavior.ts +278 -0
- package/src/routing/compatibility/catalog.ts +99 -0
- package/src/routing/compatibility/endpoint.ts +52 -0
- package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
- package/src/routing/compatibility/policy.ts +181 -0
- package/src/routing/compatibility/provider-slot.ts +56 -0
- package/src/routing/compatibility/reader.ts +110 -0
- package/src/routing/compatibility/subject.ts +191 -0
- package/src/routing/compatibility/types.ts +64 -0
- package/src/routing/compatibility/version.ts +104 -0
- package/src/routing/cost.ts +77 -0
- package/src/routing/evaluator.ts +495 -0
- package/src/routing/health.ts +412 -0
- package/src/routing/history/cursor.ts +43 -0
- package/src/routing/history/indexer.ts +605 -0
- package/src/routing/history/schema.ts +72 -0
- package/src/routing/profile-namespace.ts +15 -0
- package/src/routing/profile.ts +547 -0
- package/src/routing/quota.ts +145 -0
- package/src/routing/request-evidence.ts +45 -0
- package/src/routing/trace.ts +776 -0
- package/src/server/adapter-resolve.ts +2 -29
- package/src/server/auth-cors.ts +267 -46
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +130 -56
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +426 -0
- package/src/server/claude-messages.ts +159 -43
- package/src/server/direct-local-http.ts +347 -0
- package/src/server/effort-policy.ts +18 -0
- package/src/server/github-copilot-responses-repair.ts +338 -0
- package/src/server/gui-static.ts +39 -10
- package/src/server/images.ts +94 -12
- package/src/server/index.ts +865 -181
- package/src/server/lifecycle.ts +284 -13
- package/src/server/live.ts +136 -17
- package/src/server/local-management-read-client.ts +90 -0
- package/src/server/local-provider-reload-client.ts +137 -0
- package/src/server/management/agent-settings-routes.ts +398 -103
- package/src/server/management/api-key-usage.ts +31 -5
- package/src/server/management/body.ts +6 -0
- package/src/server/management/combo-routes.ts +62 -24
- package/src/server/management/config-routes.ts +464 -51
- package/src/server/management/context.ts +80 -2
- package/src/server/management/integration-routes.ts +498 -0
- package/src/server/management/lab-automation-routes.ts +206 -0
- package/src/server/management/lab-routes.ts +563 -0
- package/src/server/management/logs-usage-routes.ts +101 -32
- package/src/server/management/model-routes.ts +189 -131
- package/src/server/management/model-rows.ts +163 -0
- package/src/server/management/native-integration-routes.ts +769 -0
- package/src/server/management/oauth-account-routes.ts +80 -4
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +764 -157
- package/src/server/management/request-history-routes.ts +191 -0
- package/src/server/management/routing-analytics-routes.ts +74 -0
- package/src/server/management/routing-profile-routes.ts +380 -0
- package/src/server/management/shared.ts +27 -11
- package/src/server/management/sidebar-routes.ts +47 -31
- package/src/server/management/storage-log-guard-routes.ts +186 -0
- package/src/server/management/sync-response.ts +69 -0
- package/src/server/management/system-restart.ts +288 -32
- package/src/server/management/system-routes.ts +77 -0
- package/src/server/management/usage-summary-cache.ts +9 -1
- package/src/server/management/vision-sidecar-options.ts +167 -0
- package/src/server/management/web-search-sidecar-options.ts +120 -0
- package/src/server/management-api.ts +115 -14
- package/src/server/management-auth.ts +220 -5
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/ports.ts +41 -1
- package/src/server/proxy-liveness.ts +132 -5
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +82 -42
- package/src/server/relay.ts +236 -76
- package/src/server/request-decompress.ts +113 -6
- package/src/server/request-log.ts +235 -22
- package/src/server/responses/agent-task-recovery-cache.ts +143 -0
- package/src/server/responses/agent-task-recovery.ts +465 -0
- package/src/server/responses/collaboration.ts +204 -35
- package/src/server/responses/compact.ts +442 -55
- package/src/server/responses/core.ts +2872 -331
- package/src/server/responses/empty-completion-guard.ts +276 -0
- package/src/server/responses/encrypted-payload.ts +62 -39
- package/src/server/responses/fetch-helpers.ts +79 -4
- package/src/server/responses/input-admission.ts +185 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/policy-fallback.ts +178 -0
- package/src/server/responses/responses-field-backfill.ts +251 -0
- package/src/server/responses/terminal-guard.ts +26 -5
- package/src/server/responses/upstream-error.ts +5 -0
- package/src/server/responses/ws-upstream.ts +308 -0
- package/src/server/responses-custom-tool-repair.ts +282 -0
- package/src/server/responses-item-id-repair.ts +54 -6
- package/src/server/responses-json-events.ts +90 -0
- package/src/server/responses-model-rewrite.ts +29 -0
- package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
- package/src/server/responses-snapshot-repair.ts +621 -0
- package/src/server/responses-terminal-repair.ts +342 -0
- package/src/server/responses-tool-search-repair.ts +267 -0
- package/src/server/responses-undeclared-tool-guard.ts +153 -0
- package/src/server/responses.ts +18 -2
- package/src/server/search.ts +78 -13
- package/src/server/sse-frame-buffer.ts +292 -0
- package/src/server/sse-payload-rewrite.ts +110 -22
- package/src/server/startup-action-control.ts +8 -1
- package/src/server/startup-health-cache.ts +19 -1
- package/src/server/system-env.ts +80 -9
- package/src/server/ws-bridge.ts +39 -38
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +1111 -90
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -0
- package/src/storage/cleanup.ts +2 -2
- package/src/storage/scanner.ts +1 -1
- package/src/storage/worker-lifecycle.ts +14 -14
- package/src/tray/windows-tray.ps1 +83 -9
- package/src/tray/windows.ts +43 -16
- package/src/types/accounts.ts +37 -0
- package/src/types/config.ts +845 -0
- package/src/types/provider.ts +545 -0
- package/src/types/request.ts +384 -0
- package/src/types/tools.ts +131 -0
- package/src/types/wire.ts +80 -0
- package/src/types.ts +104 -1236
- package/src/update/index.ts +32 -19
- package/src/update/job.ts +442 -67
- package/src/update/notify.ts +12 -6
- package/src/update/npm-cache-preflight.d.mts +47 -0
- package/src/update/npm-cache-preflight.mjs +201 -0
- package/src/update/transactional-install.d.mts +22 -0
- package/src/update/transactional-install.mjs +259 -0
- package/src/usage/cost.ts +0 -0
- package/src/usage/expected-prices.ts +268 -16
- package/src/usage/log.ts +606 -41
- package/src/usage/summary.ts +177 -9
- package/src/usage/user-cost-overlay-reconciler.ts +313 -0
- package/src/usage/user-cost-overlays.ts +314 -0
- package/src/vision/anthropic-describe.ts +10 -6
- package/src/vision/backends.ts +97 -0
- package/src/vision/describe.ts +9 -3
- package/src/vision/eligibility.ts +250 -0
- package/src/vision/index.ts +238 -24
- package/src/vision/reasoning.ts +55 -0
- package/src/vision/routed-describe.ts +175 -0
- package/src/vision/timeout-bounds.ts +9 -0
- package/src/web-search/anthropic-executor.ts +13 -7
- package/src/web-search/backends.ts +108 -0
- package/src/web-search/exa-executor.ts +88 -0
- package/src/web-search/executor.ts +11 -3
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +150 -15
- package/src/web-search/loop.ts +279 -50
- package/src/web-search/parse.ts +125 -30
- package/src/web-search/sources.ts +60 -0
- package/src/web-search/xai-executor.ts +219 -0
- package/gui/dist/assets/index-DTpMHS4F.js +0 -67
- package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
- package/gui/dist/provider-icons/antigravity.svg +0 -1
- package/gui/dist/provider-icons/claude.svg +0 -1
- package/gui/dist/provider-icons/copilot.svg +0 -1
- package/gui/dist/provider-icons/cursor.svg +0 -2
- package/gui/dist/provider-icons/gemini.svg +0 -1
- package/gui/dist/provider-icons/grok-color.svg +0 -1
- package/gui/dist/provider-icons/kiro.svg +0 -14
- package/src/cli/internal-dispatch.ts +0 -20
package/src/usage/summary.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { baseProviderLabel } from "../providers/label";
|
|
2
2
|
import { canonicalAntigravityUsageModel } from "../providers/antigravity-models";
|
|
3
3
|
import { usageDisplayTotalTokens } from "./totals";
|
|
4
|
-
import type
|
|
5
|
-
import { estimateComboCost, estimateRequestCost,
|
|
4
|
+
import { isCodexUsageAccountLogLabel, type PersistedUsageEntry, type UsageStatus } from "./log";
|
|
5
|
+
import { estimateAttemptCost, estimateComboCost, estimateRequestCost, serviceTierContext } from "./cost";
|
|
6
6
|
|
|
7
7
|
export type UsageRange = "7d" | "30d" | "all";
|
|
8
8
|
export type UsageSurface = "all" | "codex" | "claude" | "grok";
|
|
@@ -79,6 +79,28 @@ export interface UsageProvider {
|
|
|
79
79
|
estimatedCostUsd?: number;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
export interface UsageAccount {
|
|
83
|
+
accountLogLabel: string;
|
|
84
|
+
ambiguous: boolean;
|
|
85
|
+
requests: number;
|
|
86
|
+
attemptCount: number;
|
|
87
|
+
measuredAttempts: number;
|
|
88
|
+
reportedAttempts: number;
|
|
89
|
+
estimatedAttempts: number;
|
|
90
|
+
unmeteredAttempts: number;
|
|
91
|
+
inputTokens: number;
|
|
92
|
+
outputTokens: number;
|
|
93
|
+
cacheReadInputTokens: number;
|
|
94
|
+
cacheCreationInputTokens: number;
|
|
95
|
+
reasoningOutputTokens: number;
|
|
96
|
+
totalTokens: number;
|
|
97
|
+
usageCoverageRatio: number;
|
|
98
|
+
estimatedCostUsd?: number;
|
|
99
|
+
pricedAttempts: number;
|
|
100
|
+
unpricedAttempts: number;
|
|
101
|
+
priceCoverageRatio: number;
|
|
102
|
+
}
|
|
103
|
+
|
|
82
104
|
export interface UsageSummary {
|
|
83
105
|
range: UsageRange;
|
|
84
106
|
surface: UsageSurface;
|
|
@@ -88,6 +110,7 @@ export interface UsageSummary {
|
|
|
88
110
|
days: UsageDay[];
|
|
89
111
|
models: UsageModel[];
|
|
90
112
|
providers: UsageProvider[];
|
|
113
|
+
accounts: UsageAccount[];
|
|
91
114
|
}
|
|
92
115
|
|
|
93
116
|
const DAY_MS = 86_400_000;
|
|
@@ -113,9 +136,23 @@ export function parseUsageSurface(input: string | null | undefined): UsageSurfac
|
|
|
113
136
|
return "all";
|
|
114
137
|
}
|
|
115
138
|
|
|
116
|
-
function
|
|
117
|
-
|
|
118
|
-
|
|
139
|
+
function startOfLocalDay(ts: number): number {
|
|
140
|
+
const d = new Date(ts);
|
|
141
|
+
d.setHours(0, 0, 0, 0);
|
|
142
|
+
return d.getTime();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function rangeWindow(range: UsageRange, now: number): { since: number | null; days: number } {
|
|
146
|
+
if (range === "7d") {
|
|
147
|
+
const start = new Date(startOfLocalDay(now));
|
|
148
|
+
start.setDate(start.getDate() - 6);
|
|
149
|
+
return { since: start.getTime(), days: 7 };
|
|
150
|
+
}
|
|
151
|
+
if (range === "30d") {
|
|
152
|
+
const start = new Date(startOfLocalDay(now));
|
|
153
|
+
start.setDate(start.getDate() - 29);
|
|
154
|
+
return { since: start.getTime(), days: 30 };
|
|
155
|
+
}
|
|
119
156
|
return { since: null, days: 0 };
|
|
120
157
|
}
|
|
121
158
|
|
|
@@ -286,7 +323,7 @@ function addEstimatedCost(
|
|
|
286
323
|
totals.unmeteredRequests += 1;
|
|
287
324
|
return;
|
|
288
325
|
}
|
|
289
|
-
const tier =
|
|
326
|
+
const tier = serviceTierContext(entry);
|
|
290
327
|
const estimate = entry.attempts?.length
|
|
291
328
|
? estimateComboCost(entry.attempts, undefined, tier)
|
|
292
329
|
: estimateRequestCost({ provider: entry.provider, model: entry.model, usage: entry.usage, usageStatus: entry.usageStatus, serviceTier: tier });
|
|
@@ -324,8 +361,11 @@ function buildDayGrid(range: UsageRange, since: number | null, now: number, entr
|
|
|
324
361
|
m.attemptCount += 1;
|
|
325
362
|
m.totalTokens += usageDisplayTotalTokens(attribution.usage, attribution.totalTokens) ?? 0;
|
|
326
363
|
};
|
|
364
|
+
const startOfToday = startOfLocalDay(now);
|
|
327
365
|
for (let i = days - 1; i >= 0; i--) {
|
|
328
|
-
const
|
|
366
|
+
const d = new Date(startOfToday);
|
|
367
|
+
d.setDate(d.getDate() - i);
|
|
368
|
+
const key = localDateKey(d.getTime());
|
|
329
369
|
grid.set(key, { date: key, requests: 0, measuredRequests: 0, reportedRequests: 0, totalTokens: 0, models: [] });
|
|
330
370
|
}
|
|
331
371
|
for (const entry of entries) {
|
|
@@ -415,7 +455,7 @@ function buildModels(entries: PersistedUsageEntry[], totalTokens: number): Usage
|
|
|
415
455
|
}
|
|
416
456
|
// Accumulate per-model estimated cost
|
|
417
457
|
for (const entry of entries) {
|
|
418
|
-
const tier =
|
|
458
|
+
const tier = serviceTierContext(entry);
|
|
419
459
|
const estimate = entry.attempts?.length
|
|
420
460
|
? estimateComboCost(entry.attempts, undefined, tier)
|
|
421
461
|
: estimateRequestCost({ provider: entry.provider, model: entry.model, usage: entry.usage, usageStatus: entry.usageStatus, serviceTier: tier });
|
|
@@ -524,7 +564,7 @@ function buildProviders(entries: PersistedUsageEntry[], totalTokens: number): Us
|
|
|
524
564
|
}
|
|
525
565
|
}
|
|
526
566
|
for (const entry of entries) {
|
|
527
|
-
const tier =
|
|
567
|
+
const tier = serviceTierContext(entry);
|
|
528
568
|
const estimate = entry.attempts?.length
|
|
529
569
|
? estimateComboCost(entry.attempts, undefined, tier)
|
|
530
570
|
: estimateRequestCost({ provider: entry.provider, model: entry.model, usage: entry.usage, usageStatus: entry.usageStatus, serviceTier: tier });
|
|
@@ -547,6 +587,133 @@ function buildProviders(entries: PersistedUsageEntry[], totalTokens: number): Us
|
|
|
547
587
|
return providers.sort((a, b) => b.requests - a.requests);
|
|
548
588
|
}
|
|
549
589
|
|
|
590
|
+
const LEGACY_AMBIGUOUS_ACCOUNT_LABEL = "legacy-ambiguous";
|
|
591
|
+
|
|
592
|
+
function legacyCodexAccountLabel(provider: string): string | null {
|
|
593
|
+
if (baseProviderLabel(provider) !== "openai") return null;
|
|
594
|
+
const suffix = provider.match(/-(main|p[a-f0-9]{6})$/)?.[1];
|
|
595
|
+
return suffix ?? LEGACY_AMBIGUOUS_ACCOUNT_LABEL;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
function accountLabelForAttribution(provider: string, explicit: unknown): string | null {
|
|
599
|
+
if (isCodexUsageAccountLogLabel(explicit)) return explicit;
|
|
600
|
+
return legacyCodexAccountLabel(provider);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
function buildAccounts(entries: PersistedUsageEntry[]): UsageAccount[] {
|
|
604
|
+
const byLabel = new Map<string, UsageAccount>();
|
|
605
|
+
const requestIds = new Map<string, Set<string>>();
|
|
606
|
+
|
|
607
|
+
const add = (input: {
|
|
608
|
+
requestId: string;
|
|
609
|
+
provider: string;
|
|
610
|
+
accountLogLabel?: string;
|
|
611
|
+
usageStatus: UsageStatus;
|
|
612
|
+
usage?: PersistedUsageEntry["usage"];
|
|
613
|
+
totalTokens?: number;
|
|
614
|
+
estimate: ReturnType<typeof estimateRequestCost>;
|
|
615
|
+
}): void => {
|
|
616
|
+
const label = accountLabelForAttribution(input.provider, input.accountLogLabel);
|
|
617
|
+
if (!label) return;
|
|
618
|
+
let row = byLabel.get(label);
|
|
619
|
+
if (!row) {
|
|
620
|
+
row = {
|
|
621
|
+
accountLogLabel: label,
|
|
622
|
+
ambiguous: label === LEGACY_AMBIGUOUS_ACCOUNT_LABEL,
|
|
623
|
+
requests: 0,
|
|
624
|
+
attemptCount: 0,
|
|
625
|
+
measuredAttempts: 0,
|
|
626
|
+
reportedAttempts: 0,
|
|
627
|
+
estimatedAttempts: 0,
|
|
628
|
+
unmeteredAttempts: 0,
|
|
629
|
+
inputTokens: 0,
|
|
630
|
+
outputTokens: 0,
|
|
631
|
+
cacheReadInputTokens: 0,
|
|
632
|
+
cacheCreationInputTokens: 0,
|
|
633
|
+
reasoningOutputTokens: 0,
|
|
634
|
+
totalTokens: 0,
|
|
635
|
+
usageCoverageRatio: 0,
|
|
636
|
+
pricedAttempts: 0,
|
|
637
|
+
unpricedAttempts: 0,
|
|
638
|
+
priceCoverageRatio: 0,
|
|
639
|
+
};
|
|
640
|
+
byLabel.set(label, row);
|
|
641
|
+
requestIds.set(label, new Set());
|
|
642
|
+
}
|
|
643
|
+
requestIds.get(label)!.add(input.requestId);
|
|
644
|
+
row.requests = requestIds.get(label)!.size;
|
|
645
|
+
row.attemptCount += 1;
|
|
646
|
+
const measured = input.usage !== undefined && isMeasuredStatus(input.usageStatus);
|
|
647
|
+
if (!measured) {
|
|
648
|
+
row.unmeteredAttempts += 1;
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
row.measuredAttempts += 1;
|
|
653
|
+
if (input.usageStatus === "reported") row.reportedAttempts += 1;
|
|
654
|
+
else if (input.usageStatus === "estimated") row.estimatedAttempts += 1;
|
|
655
|
+
row.inputTokens += input.usage!.inputTokens;
|
|
656
|
+
row.outputTokens += input.usage!.outputTokens;
|
|
657
|
+
const creation = input.usage!.cacheCreationInputTokens;
|
|
658
|
+
const read = typeof input.usage!.cacheReadInputTokens === "number"
|
|
659
|
+
? input.usage!.cacheReadInputTokens
|
|
660
|
+
: typeof input.usage!.cachedInputTokens === "number" && typeof creation === "number"
|
|
661
|
+
? Math.max(0, input.usage!.cachedInputTokens - creation)
|
|
662
|
+
: input.usage!.cachedInputTokens;
|
|
663
|
+
if (typeof read === "number") row.cacheReadInputTokens += read;
|
|
664
|
+
if (typeof creation === "number") row.cacheCreationInputTokens += creation;
|
|
665
|
+
if (typeof input.usage!.reasoningOutputTokens === "number") {
|
|
666
|
+
row.reasoningOutputTokens += input.usage!.reasoningOutputTokens;
|
|
667
|
+
}
|
|
668
|
+
row.totalTokens += usageDisplayTotalTokens(input.usage, input.totalTokens) ?? 0;
|
|
669
|
+
if (input.estimate) {
|
|
670
|
+
row.pricedAttempts += 1;
|
|
671
|
+
row.estimatedCostUsd = (row.estimatedCostUsd ?? 0) + input.estimate.cost.total;
|
|
672
|
+
} else {
|
|
673
|
+
row.unpricedAttempts += 1;
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
for (const entry of entries) {
|
|
678
|
+
const tier = serviceTierContext(entry);
|
|
679
|
+
if (entry.attempts?.length) {
|
|
680
|
+
for (const attempt of entry.attempts) {
|
|
681
|
+
add({
|
|
682
|
+
requestId: entry.requestId,
|
|
683
|
+
provider: attempt.provider,
|
|
684
|
+
...(attempt.accountLogLabel ? { accountLogLabel: attempt.accountLogLabel } : {}),
|
|
685
|
+
usageStatus: attempt.usageStatus,
|
|
686
|
+
...(attempt.usage ? { usage: attempt.usage } : {}),
|
|
687
|
+
...(attempt.totalTokens !== undefined ? { totalTokens: attempt.totalTokens } : {}),
|
|
688
|
+
estimate: estimateAttemptCost(attempt, undefined, tier),
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
add({
|
|
694
|
+
requestId: entry.requestId,
|
|
695
|
+
provider: entry.provider,
|
|
696
|
+
...(entry.accountLogLabel ? { accountLogLabel: entry.accountLogLabel } : {}),
|
|
697
|
+
usageStatus: entry.usageStatus,
|
|
698
|
+
...(entry.usage ? { usage: entry.usage } : {}),
|
|
699
|
+
...(entry.totalTokens !== undefined ? { totalTokens: entry.totalTokens } : {}),
|
|
700
|
+
estimate: estimateRequestCost({
|
|
701
|
+
provider: entry.provider,
|
|
702
|
+
model: entry.model,
|
|
703
|
+
usage: entry.usage,
|
|
704
|
+
usageStatus: entry.usageStatus,
|
|
705
|
+
serviceTier: tier,
|
|
706
|
+
}),
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
for (const row of byLabel.values()) {
|
|
711
|
+
row.usageCoverageRatio = row.attemptCount === 0 ? 0 : row.measuredAttempts / row.attemptCount;
|
|
712
|
+
row.priceCoverageRatio = row.measuredAttempts === 0 ? 0 : row.pricedAttempts / row.measuredAttempts;
|
|
713
|
+
}
|
|
714
|
+
return [...byLabel.values()].sort((a, b) => b.totalTokens - a.totalTokens);
|
|
715
|
+
}
|
|
716
|
+
|
|
550
717
|
export function summarizeUsage(
|
|
551
718
|
entries: PersistedUsageEntry[],
|
|
552
719
|
range: UsageRange,
|
|
@@ -581,5 +748,6 @@ export function summarizeUsage(
|
|
|
581
748
|
days: buildDayGrid(range, since, now, filteredEntries),
|
|
582
749
|
models: buildModels(filteredEntries, totals.totalTokens),
|
|
583
750
|
providers: buildProviders(filteredEntries, totals.totalTokens),
|
|
751
|
+
accounts: buildAccounts(filteredEntries),
|
|
584
752
|
};
|
|
585
753
|
}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-process reconciliation for user cost overlays.
|
|
3
|
+
*
|
|
4
|
+
* `refreshUserCostOverlays` is process-local by design: `ocx config set`
|
|
5
|
+
* executes `saveConfig()` in the CLI process, and a direct `config.json` edit
|
|
6
|
+
* runs no in-process code at all. A running proxy therefore keeps its previous
|
|
7
|
+
* `activeUserCostOverlays()`/version until restart or another in-process
|
|
8
|
+
* refresh.
|
|
9
|
+
*
|
|
10
|
+
* This module gives the long-lived server a lightweight stat-based poller:
|
|
11
|
+
* when `config.json` changes on disk, it re-reads the persisted config, mirrors
|
|
12
|
+
* the disk `modelCosts` rows into the live provider rows (so a later in-process
|
|
13
|
+
* save cannot erase the external edit), and refreshes the overlay registry so
|
|
14
|
+
* Logs/Usage estimates follow the edit without a restart.
|
|
15
|
+
*
|
|
16
|
+
* The reconciler is owner-scoped: every `startServer` acquires its own lease
|
|
17
|
+
* (with its own live config), and the shared timer is torn down only when the
|
|
18
|
+
* LAST owner stops. This mirrors `acquireServerBackgroundLifecycle` so stopping
|
|
19
|
+
* one of several servers cannot kill reconciliation for the others.
|
|
20
|
+
*/
|
|
21
|
+
import { statSync } from "node:fs";
|
|
22
|
+
|
|
23
|
+
import { getConfigPath, readConfigDiagnostics } from "../config";
|
|
24
|
+
import type { OcxConfig, OcxProviderConfig } from "../types";
|
|
25
|
+
import {
|
|
26
|
+
refreshPreservedProviderOwner,
|
|
27
|
+
refreshUserCostOverlays,
|
|
28
|
+
registerPreservedProviderOwner,
|
|
29
|
+
setPreservedDiskOnlyProviders,
|
|
30
|
+
unregisterPreservedProviderOwner,
|
|
31
|
+
} from "./user-cost-overlays";
|
|
32
|
+
|
|
33
|
+
/** Default poll cadence for external config edits. */
|
|
34
|
+
export const USER_COST_OVERLAY_RECONCILE_INTERVAL_MS = 5_000;
|
|
35
|
+
|
|
36
|
+
let reconcileTimer: ReturnType<typeof setInterval> | null = null;
|
|
37
|
+
let reconcileTimerMs = 0;
|
|
38
|
+
const owners = new Map<symbol, OcxConfig | null>();
|
|
39
|
+
const ownerIntervals = new Map<symbol, number>();
|
|
40
|
+
let lastStamp: { mtimeMs: number; size: number; ctimeMs: number; ino: number } | null = null;
|
|
41
|
+
let invalidReconcileCount = 0;
|
|
42
|
+
|
|
43
|
+
function configStamp(): { mtimeMs: number; size: number; ctimeMs: number; ino: number } | null {
|
|
44
|
+
try {
|
|
45
|
+
const stat = statSync(getConfigPath());
|
|
46
|
+
return {
|
|
47
|
+
mtimeMs: stat.mtimeMs,
|
|
48
|
+
size: stat.size,
|
|
49
|
+
ctimeMs: stat.ctimeMs,
|
|
50
|
+
ino: Number(stat.ino),
|
|
51
|
+
};
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Registered live configs plus an optional one-shot config, deduped by object identity. */
|
|
58
|
+
function liveConfigsForPreservation(extra?: OcxConfig | null): OcxConfig[] {
|
|
59
|
+
const liveConfigs: OcxConfig[] = [];
|
|
60
|
+
const seen = new Set<OcxConfig>();
|
|
61
|
+
if (extra) {
|
|
62
|
+
seen.add(extra);
|
|
63
|
+
liveConfigs.push(extra);
|
|
64
|
+
}
|
|
65
|
+
for (const config of owners.values()) {
|
|
66
|
+
if (!config || seen.has(config)) continue;
|
|
67
|
+
seen.add(config);
|
|
68
|
+
liveConfigs.push(config);
|
|
69
|
+
}
|
|
70
|
+
return liveConfigs;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Mirror disk `modelCosts` rows into provider rows the live config already
|
|
75
|
+
* knows. Providers added by the external edit are left out of the live config
|
|
76
|
+
* (they would change the routing surface); their overlays still become active
|
|
77
|
+
* because the registry below is refreshed from the disk config.
|
|
78
|
+
*/
|
|
79
|
+
function adoptDiskModelCosts(live: OcxConfig, disk: OcxConfig): void {
|
|
80
|
+
if (!live.providers || !disk.providers) return;
|
|
81
|
+
for (const [name, diskProvider] of Object.entries(disk.providers)) {
|
|
82
|
+
const liveProvider = live.providers[name];
|
|
83
|
+
if (!liveProvider) continue;
|
|
84
|
+
if (diskProvider?.modelCosts === undefined) {
|
|
85
|
+
delete liveProvider.modelCosts;
|
|
86
|
+
} else {
|
|
87
|
+
liveProvider.modelCosts = structuredClone(diskProvider.modelCosts);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Remember provider rows present on disk that at least one live routing
|
|
94
|
+
* config does NOT own. They stay out of the live configs that lack them
|
|
95
|
+
* (adding them would change the routing surface), but
|
|
96
|
+
* `persistConfigUnlocked` merges them back at serialization so ANY owner's
|
|
97
|
+
* unrelated save preserves a provider row that another active owner owns.
|
|
98
|
+
*
|
|
99
|
+
* A row is preserved when it is missing from at least one live config: the
|
|
100
|
+
* writer that lacks it would otherwise erase it. Rows every live config owns
|
|
101
|
+
* need no protection because every writer carries them from its own config.
|
|
102
|
+
*/
|
|
103
|
+
function rememberDiskOnlyProviders(liveConfigs: readonly OcxConfig[], disk: OcxConfig): void {
|
|
104
|
+
const preserved: Record<string, OcxProviderConfig> = {};
|
|
105
|
+
if (disk.providers && liveConfigs.length > 0) {
|
|
106
|
+
for (const [name, provider] of Object.entries(disk.providers)) {
|
|
107
|
+
if (!provider) continue;
|
|
108
|
+
const ownedByAll = liveConfigs.every(live => Object.hasOwn(live.providers ?? {}, name));
|
|
109
|
+
if (!ownedByAll) preserved[name] = structuredClone(provider);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
setPreservedDiskOnlyProviders(Object.keys(preserved).length > 0 ? preserved : null);
|
|
113
|
+
// Update only registered server owners. One-shot callers without a lease do
|
|
114
|
+
// not become deletion authorities merely by asking for a reconciliation.
|
|
115
|
+
for (const live of liveConfigs) refreshPreservedProviderOwner(live, disk);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Re-read the persisted config and recompute the disk-only provider
|
|
120
|
+
* preservation registry against the CURRENT owner set. Used when an owner
|
|
121
|
+
* stops but others remain: a newer owner may have owned a provider that an
|
|
122
|
+
* older owner still treats as disk-only, and the registry must reflect the
|
|
123
|
+
* remaining owners rather than the stale pre-stop snapshot.
|
|
124
|
+
*
|
|
125
|
+
* A missing or transiently invalid file leaves the registry untouched so a
|
|
126
|
+
* bad write cannot erase preservation state.
|
|
127
|
+
*/
|
|
128
|
+
function recomputePreservedDiskOnlyProviders(): void {
|
|
129
|
+
const diagnostics = readConfigDiagnostics();
|
|
130
|
+
if (diagnostics.source !== "file") return;
|
|
131
|
+
const liveConfigs = liveConfigsForPreservation();
|
|
132
|
+
if (liveConfigs.length > 0) {
|
|
133
|
+
rememberDiskOnlyProviders(liveConfigs, diagnostics.config);
|
|
134
|
+
} else {
|
|
135
|
+
// No live routing configuration remains to protect disk-only providers;
|
|
136
|
+
// clear the cache so a later save cannot resurrect externally deleted rows.
|
|
137
|
+
setPreservedDiskOnlyProviders(null);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Re-read the persisted config and make external overlay edits live.
|
|
143
|
+
*
|
|
144
|
+
* Returns `false` (and leaves the registry untouched) when the file is missing
|
|
145
|
+
* or invalid, so a transient bad write cannot wipe display-only prices.
|
|
146
|
+
*/
|
|
147
|
+
export function reconcileUserCostOverlaysFromDisk(liveConfig?: OcxConfig | null): boolean {
|
|
148
|
+
const diagnostics = readConfigDiagnostics();
|
|
149
|
+
if (diagnostics.source !== "file") return false;
|
|
150
|
+
const disk = diagnostics.config;
|
|
151
|
+
if (liveConfig) {
|
|
152
|
+
adoptDiskModelCosts(liveConfig, disk);
|
|
153
|
+
// A one-shot caller is not the whole process. Existing server owners still
|
|
154
|
+
// participate in global preservation or this call can drop protection for
|
|
155
|
+
// a provider absent from an older live projection.
|
|
156
|
+
rememberDiskOnlyProviders(liveConfigsForPreservation(liveConfig), disk);
|
|
157
|
+
} else {
|
|
158
|
+
// No live routing config was supplied: mirror the owners path so a stale
|
|
159
|
+
// preservation registry cannot resurrect externally deleted providers on
|
|
160
|
+
// the next saveConfig. Registered owners still protect disk-only rows;
|
|
161
|
+
// without any, preservation is cleared.
|
|
162
|
+
const liveConfigs = liveConfigsForPreservation();
|
|
163
|
+
if (liveConfigs.length > 0) {
|
|
164
|
+
for (const live of liveConfigs) adoptDiskModelCosts(live, disk);
|
|
165
|
+
rememberDiskOnlyProviders(liveConfigs, disk);
|
|
166
|
+
} else {
|
|
167
|
+
setPreservedDiskOnlyProviders(null);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Refresh from the DISK config: overlays for providers only added by the
|
|
171
|
+
// external edit are display-only and must still resolve for historical rows.
|
|
172
|
+
refreshUserCostOverlays(disk);
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function reconcileForOwners(): void {
|
|
177
|
+
const diagnostics = readConfigDiagnostics();
|
|
178
|
+
if (diagnostics.source !== "file") {
|
|
179
|
+
if (diagnostics.source === "fallback") invalidReconcileCount += 1;
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const disk = diagnostics.config;
|
|
183
|
+
const liveConfigs = liveConfigsForPreservation();
|
|
184
|
+
if (liveConfigs.length > 0) {
|
|
185
|
+
for (const live of liveConfigs) adoptDiskModelCosts(live, disk);
|
|
186
|
+
rememberDiskOnlyProviders(liveConfigs, disk);
|
|
187
|
+
} else {
|
|
188
|
+
// Overlay-only refresh with no live routing configuration: do not treat
|
|
189
|
+
// every disk provider as protected, and do not let a stale preservation
|
|
190
|
+
// cache resurrect providers that were intentionally removed.
|
|
191
|
+
setPreservedDiskOnlyProviders(null);
|
|
192
|
+
}
|
|
193
|
+
refreshUserCostOverlays(disk);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Test-only observation that proves the timer actually read an invalid config fallback. */
|
|
197
|
+
export function userCostOverlayInvalidReconcileCountForTests(): number {
|
|
198
|
+
return invalidReconcileCount;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** Smallest poll interval across all active owners (the effective cadence). */
|
|
202
|
+
function effectiveIntervalMs(): number {
|
|
203
|
+
let min = Number.POSITIVE_INFINITY;
|
|
204
|
+
for (const interval of ownerIntervals.values()) {
|
|
205
|
+
if (interval < min) min = interval;
|
|
206
|
+
}
|
|
207
|
+
return min === Number.POSITIVE_INFINITY ? USER_COST_OVERLAY_RECONCILE_INTERVAL_MS : min;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Keep the shared timer on the effective minimum cadence across owners. A
|
|
212
|
+
* later owner may request a smaller interval, which restarts the timer; when
|
|
213
|
+
* an owner stops, the cadence relaxes back up to the smallest still-active
|
|
214
|
+
* owner's request. The timer therefore never outlives or ignores an owner's
|
|
215
|
+
* faster polling need, and never polls faster than the active set requires.
|
|
216
|
+
*/
|
|
217
|
+
function syncReconcileTimer(): void {
|
|
218
|
+
const intervalMs = effectiveIntervalMs();
|
|
219
|
+
if (reconcileTimer && reconcileTimerMs === intervalMs) return;
|
|
220
|
+
if (reconcileTimer) clearInterval(reconcileTimer);
|
|
221
|
+
reconcileTimer = setInterval(() => {
|
|
222
|
+
const stamp = configStamp();
|
|
223
|
+
if (!stamp) return;
|
|
224
|
+
if (
|
|
225
|
+
lastStamp
|
|
226
|
+
&& lastStamp.mtimeMs === stamp.mtimeMs
|
|
227
|
+
&& lastStamp.size === stamp.size
|
|
228
|
+
&& lastStamp.ctimeMs === stamp.ctimeMs
|
|
229
|
+
&& lastStamp.ino === stamp.ino
|
|
230
|
+
) return;
|
|
231
|
+
lastStamp = stamp;
|
|
232
|
+
try {
|
|
233
|
+
reconcileForOwners();
|
|
234
|
+
} catch {
|
|
235
|
+
// Display-only reconciliation must never take the proxy down.
|
|
236
|
+
}
|
|
237
|
+
}, intervalMs);
|
|
238
|
+
reconcileTimer.unref?.();
|
|
239
|
+
reconcileTimerMs = intervalMs;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Start the stat-based reconciler. Each call registers an owner lease; the
|
|
244
|
+
* shared timer starts with the first owner and stops when the last owner's
|
|
245
|
+
* `stop()` releases it.
|
|
246
|
+
*/
|
|
247
|
+
export function startUserCostOverlayReconciler(
|
|
248
|
+
options: { intervalMs?: number; liveConfig?: OcxConfig | null } = {},
|
|
249
|
+
): { stop(): void } {
|
|
250
|
+
const token = Symbol("user-cost-overlay-reconciler");
|
|
251
|
+
const liveConfig = options.liveConfig ?? null;
|
|
252
|
+
owners.set(token, liveConfig);
|
|
253
|
+
ownerIntervals.set(token, options.intervalMs ?? USER_COST_OVERLAY_RECONCILE_INTERVAL_MS);
|
|
254
|
+
if (liveConfig) registerPreservedProviderOwner(liveConfig);
|
|
255
|
+
syncReconcileTimer();
|
|
256
|
+
return {
|
|
257
|
+
stop() {
|
|
258
|
+
const ownedConfig = owners.get(token) ?? null;
|
|
259
|
+
owners.delete(token);
|
|
260
|
+
ownerIntervals.delete(token);
|
|
261
|
+
if (ownedConfig) unregisterPreservedProviderOwner(ownedConfig);
|
|
262
|
+
if (owners.size === 0) {
|
|
263
|
+
if (reconcileTimer) clearInterval(reconcileTimer);
|
|
264
|
+
reconcileTimer = null;
|
|
265
|
+
reconcileTimerMs = 0;
|
|
266
|
+
lastStamp = null;
|
|
267
|
+
// No live routing config remains, so nothing can keep disk-only
|
|
268
|
+
// providers alive: clear the cache to prevent a later save from
|
|
269
|
+
// resurrecting an externally deleted provider.
|
|
270
|
+
setPreservedDiskOnlyProviders(null);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
syncReconcileTimer();
|
|
274
|
+
// Other owners remain: recompute preservation against their live
|
|
275
|
+
// configs. A newer owner may have owned providers that an older owner
|
|
276
|
+
// still sees as disk-only; without this recompute the older owner's next
|
|
277
|
+
// unrelated save could erase them.
|
|
278
|
+
try {
|
|
279
|
+
recomputePreservedDiskOnlyProviders();
|
|
280
|
+
} catch {
|
|
281
|
+
// Preservation is display-only; a failed recompute must not break stop.
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Process-wide stop: releases EVERY owner's lease and the shared timer.
|
|
289
|
+
* Intended for tests and full process teardown. A per-server shutdown must
|
|
290
|
+
* call its own owner-scoped `stop()` handle instead — this function would
|
|
291
|
+
* otherwise tear down reconciliation (and disk-only preservation) for every
|
|
292
|
+
* other server still running in the same process.
|
|
293
|
+
*/
|
|
294
|
+
export function stopUserCostOverlayReconciler(): void {
|
|
295
|
+
for (const config of owners.values()) {
|
|
296
|
+
if (config) unregisterPreservedProviderOwner(config);
|
|
297
|
+
}
|
|
298
|
+
owners.clear();
|
|
299
|
+
ownerIntervals.clear();
|
|
300
|
+
if (reconcileTimer) clearInterval(reconcileTimer);
|
|
301
|
+
reconcileTimer = null;
|
|
302
|
+
reconcileTimerMs = 0;
|
|
303
|
+
lastStamp = null;
|
|
304
|
+
// No live routing config remains; drop preservation so a later save cannot
|
|
305
|
+
// resurrect externally deleted providers.
|
|
306
|
+
setPreservedDiskOnlyProviders(null);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/** Test-only reset for module-global reconciler state. */
|
|
310
|
+
export function resetUserCostOverlayReconcilerForTests(): void {
|
|
311
|
+
stopUserCostOverlayReconciler();
|
|
312
|
+
invalidReconcileCount = 0;
|
|
313
|
+
}
|