@yansigit/opencodex 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/LICENSE +21 -0
- package/README.md +303 -0
- package/assets/architecture.png +0 -0
- package/assets/banner.png +0 -0
- package/assets/claude-code-models.gif +0 -0
- package/assets/codex-app-picker.png +0 -0
- package/bin/ocx.mjs +587 -0
- package/bin/package-main.mjs +9 -0
- package/gui/dist/assets/index-BNJ7r4Gd.js +102 -0
- package/gui/dist/assets/index-CGoDO3uO.css +1 -0
- package/gui/dist/favicon.png +0 -0
- package/gui/dist/icons.svg +24 -0
- package/gui/dist/index.html +25 -0
- package/gui/dist/logo.png +0 -0
- package/gui/dist/provider-icons/alibaba-color.svg +1 -0
- package/gui/dist/provider-icons/antigravity-color.svg +1 -0
- package/gui/dist/provider-icons/claude-color.svg +1 -0
- package/gui/dist/provider-icons/cline-color.svg +16 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/commandcode-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -0
- package/gui/dist/provider-icons/cursor-color.svg +2 -0
- package/gui/dist/provider-icons/deepseek-color.svg +1 -0
- package/gui/dist/provider-icons/discord.svg +1 -0
- package/gui/dist/provider-icons/firepass-color.svg +1 -0
- package/gui/dist/provider-icons/fireworks-color.svg +1 -0
- package/gui/dist/provider-icons/gemini-color.svg +1 -0
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
- package/gui/dist/provider-icons/grok.svg +1 -0
- package/gui/dist/provider-icons/groq-color.svg +1 -0
- package/gui/dist/provider-icons/huggingface-color.svg +1 -0
- package/gui/dist/provider-icons/kimi-color.svg +1 -0
- package/gui/dist/provider-icons/kiro-color.svg +15 -0
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
- package/gui/dist/provider-icons/mistral-color.svg +1 -0
- package/gui/dist/provider-icons/moonshot-color.svg +1 -0
- package/gui/dist/provider-icons/nvidia-color.svg +1 -0
- package/gui/dist/provider-icons/ollama-color.svg +1 -0
- package/gui/dist/provider-icons/openai.svg +1 -0
- package/gui/dist/provider-icons/opencode.svg +2 -0
- package/gui/dist/provider-icons/openrouter-color.svg +1 -0
- package/gui/dist/provider-icons/pi.svg +21 -0
- package/gui/dist/provider-icons/qianfan-color.svg +1 -0
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
- package/gui/dist/provider-icons/telegram.svg +1 -0
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/vllm-color.svg +1 -0
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
- package/package.json +108 -0
- package/src/AGENTS.md +28 -0
- package/src/adapters/anthropic-image-guard.ts +251 -0
- package/src/adapters/anthropic-image-normalize.ts +518 -0
- package/src/adapters/anthropic-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +1327 -0
- package/src/adapters/azure.ts +36 -0
- package/src/adapters/base.ts +121 -0
- package/src/adapters/client-fingerprint.ts +65 -0
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
- package/src/adapters/command-code.ts +601 -0
- package/src/adapters/cursor/arg-codec.ts +38 -0
- package/src/adapters/cursor/arg-normalize.ts +104 -0
- package/src/adapters/cursor/checkpoint-store.ts +303 -0
- package/src/adapters/cursor/cursor-errors.ts +288 -0
- package/src/adapters/cursor/discovery.ts +333 -0
- package/src/adapters/cursor/effort-map.ts +151 -0
- package/src/adapters/cursor/exec-policy.ts +88 -0
- package/src/adapters/cursor/framing.ts +250 -0
- package/src/adapters/cursor/gen/agent_pb.ts +15274 -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/kv-store.ts +52 -0
- package/src/adapters/cursor/live-models.ts +269 -0
- package/src/adapters/cursor/live-smoke-gate.ts +41 -0
- package/src/adapters/cursor/live-transport.ts +1653 -0
- package/src/adapters/cursor/mcp-config.ts +42 -0
- package/src/adapters/cursor/mcp-manager.ts +333 -0
- package/src/adapters/cursor/message-mapper.ts +49 -0
- package/src/adapters/cursor/native-exec-common.ts +76 -0
- package/src/adapters/cursor/native-exec-desktop.ts +184 -0
- package/src/adapters/cursor/native-exec-fs.ts +332 -0
- package/src/adapters/cursor/native-exec-mcp.ts +153 -0
- package/src/adapters/cursor/native-exec-network.ts +43 -0
- package/src/adapters/cursor/native-exec-shell.ts +547 -0
- package/src/adapters/cursor/native-exec-tools.ts +118 -0
- package/src/adapters/cursor/native-exec.ts +663 -0
- package/src/adapters/cursor/protobuf-events.ts +1381 -0
- package/src/adapters/cursor/protobuf-request.ts +1032 -0
- package/src/adapters/cursor/request-builder.ts +461 -0
- package/src/adapters/cursor/thread-continuity.ts +67 -0
- package/src/adapters/cursor/tool-definitions.ts +735 -0
- package/src/adapters/cursor/tool-result-normalize.ts +92 -0
- package/src/adapters/cursor/transport-retry.ts +132 -0
- package/src/adapters/cursor/transport.ts +79 -0
- package/src/adapters/cursor/types.ts +79 -0
- package/src/adapters/cursor.ts +322 -0
- package/src/adapters/google-antigravity-hosts.ts +48 -0
- package/src/adapters/google-antigravity-replay.ts +827 -0
- package/src/adapters/google-antigravity-tools.ts +105 -0
- package/src/adapters/google-antigravity-wire.ts +141 -0
- package/src/adapters/google-errors.ts +92 -0
- package/src/adapters/google-http.ts +460 -0
- package/src/adapters/google-tool-schema.ts +238 -0
- package/src/adapters/google-truncation.ts +24 -0
- package/src/adapters/google-wire-compiler.ts +232 -0
- package/src/adapters/google.ts +1377 -0
- package/src/adapters/identity.ts +77 -0
- package/src/adapters/image.ts +23 -0
- package/src/adapters/kiro-constants.ts +16 -0
- package/src/adapters/kiro-errors.ts +208 -0
- package/src/adapters/kiro-events.ts +197 -0
- package/src/adapters/kiro-images.ts +129 -0
- package/src/adapters/kiro-retry.ts +312 -0
- package/src/adapters/kiro-thinking.ts +112 -0
- package/src/adapters/kiro-tool-fallback.ts +36 -0
- package/src/adapters/kiro-tools.ts +224 -0
- package/src/adapters/kiro-truncation.ts +33 -0
- package/src/adapters/kiro-wire.ts +129 -0
- package/src/adapters/kiro.ts +1936 -0
- package/src/adapters/mimo-free.ts +280 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1980 -0
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +1911 -0
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/run-turn-queue.ts +114 -0
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +154 -0
- package/src/adapters/upstream-http-error.ts +48 -0
- package/src/adapters/xai-web-search.ts +185 -0
- package/src/bridge.ts +1986 -0
- package/src/chat/inbound.ts +319 -0
- package/src/chat/outbound.ts +821 -0
- package/src/claude/agents-inject.ts +266 -0
- package/src/claude/alias.ts +149 -0
- package/src/claude/auth-detect.ts +229 -0
- package/src/claude/auth-mode-migration.ts +32 -0
- package/src/claude/auth-mode.ts +62 -0
- package/src/claude/context-windows.ts +205 -0
- package/src/claude/desktop-3p-guard.ts +35 -0
- package/src/claude/desktop-3p-paths.ts +84 -0
- package/src/claude/desktop-3p.ts +615 -0
- package/src/claude/desktop-health.ts +26 -0
- package/src/claude/desktop-profile.ts +263 -0
- package/src/claude/gateway-cache.ts +107 -0
- package/src/claude/inbound-debug.ts +163 -0
- package/src/claude/inbound.ts +578 -0
- package/src/claude/model-info.ts +174 -0
- package/src/claude/outbound.ts +926 -0
- package/src/cli/access.ts +108 -0
- package/src/cli/account-api.ts +302 -0
- package/src/cli/account-auth.ts +250 -0
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +737 -0
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +299 -0
- package/src/cli/agent-driven.ts +70 -0
- package/src/cli/agent.ts +290 -0
- package/src/cli/catalog-prewarm.ts +27 -0
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +213 -0
- package/src/cli/claude.ts +355 -0
- package/src/cli/codex-log-guard-doctor.ts +103 -0
- package/src/cli/codex-shim-autorestore.ts +47 -0
- package/src/cli/codex-shim-readiness.ts +76 -0
- package/src/cli/combo.ts +127 -0
- package/src/cli/config-command.ts +209 -0
- package/src/cli/debug.ts +228 -0
- package/src/cli/dispatch.ts +585 -0
- package/src/cli/doctor.ts +1202 -0
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +213 -0
- package/src/cli/help.ts +101 -0
- package/src/cli/index.ts +973 -0
- package/src/cli/init.ts +211 -0
- package/src/cli/integrations.ts +260 -0
- package/src/cli/interactive-confirm.ts +133 -0
- 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 +245 -0
- package/src/cli/models.ts +422 -0
- package/src/cli/observe.ts +206 -0
- package/src/cli/opencode.ts +588 -0
- package/src/cli/provider-replit.ts +232 -0
- package/src/cli/provider-runtime.ts +179 -0
- package/src/cli/provider.ts +492 -0
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +422 -0
- package/src/cli/replit-gateway-key-input.ts +138 -0
- package/src/cli/root.ts +86 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +328 -0
- package/src/cli/star-prompt.ts +211 -0
- package/src/cli/status-oauth.ts +78 -0
- package/src/cli/status.ts +328 -0
- package/src/cli/system-command.ts +112 -0
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +199 -0
- package/src/cli/v2.ts +268 -0
- package/src/cli.ts +10 -0
- package/src/clients/config-export.ts +1704 -0
- package/src/codex/account-id.ts +34 -0
- package/src/codex/account-label.ts +47 -0
- package/src/codex/account-lifecycle.ts +172 -0
- package/src/codex/account-namespace-match.ts +63 -0
- package/src/codex/account-namespaces.ts +195 -0
- package/src/codex/account-pause.ts +20 -0
- package/src/codex/account-priority.ts +83 -0
- package/src/codex/account-runtime-state.ts +31 -0
- package/src/codex/account-store.ts +544 -0
- package/src/codex/account-usability.ts +43 -0
- package/src/codex/admission.ts +256 -0
- package/src/codex/affinity-debug.ts +162 -0
- package/src/codex/agent-roles-sync.ts +225 -0
- package/src/codex/agent-roles.ts +238 -0
- package/src/codex/app-server-processes.ts +1143 -0
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +2147 -0
- package/src/codex/auth-collision.ts +109 -0
- package/src/codex/auth-context.ts +665 -0
- package/src/codex/autostart-health.ts +156 -0
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +436 -0
- package/src/codex/catalog/bundled.ts +549 -0
- package/src/codex/catalog/effort.ts +446 -0
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +664 -0
- package/src/codex/catalog/native-models.ts +72 -0
- package/src/codex/catalog/parsing.ts +650 -0
- package/src/codex/catalog/provider-fetch.ts +2064 -0
- package/src/codex/catalog/sync.ts +1883 -0
- 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 +14 -0
- 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/data/upstream-models.json +830 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/exec-invocation.ts +22 -0
- package/src/codex/features.ts +1566 -0
- 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 +108 -0
- package/src/codex/history-provider.ts +979 -0
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +220 -0
- package/src/codex/home.ts +206 -0
- package/src/codex/inject-coordination.ts +290 -0
- package/src/codex/inject.ts +1733 -0
- package/src/codex/injected-marker.ts +106 -0
- 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 +225 -0
- 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 +56 -0
- package/src/codex/main-account.ts +68 -0
- package/src/codex/management-convergence.ts +167 -0
- package/src/codex/model-cache.ts +273 -0
- 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 +144 -0
- package/src/codex/plan-from-token.ts +140 -0
- package/src/codex/plan.ts +40 -0
- package/src/codex/plugins-doctor.ts +242 -0
- package/src/codex/pool-rotation.ts +295 -0
- package/src/codex/project-config-warnings.ts +425 -0
- 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 +573 -0
- package/src/codex/refresh.ts +62 -0
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +1888 -0
- package/src/codex/runtime.ts +659 -0
- package/src/codex/shim.ts +2170 -0
- package/src/codex/subagent-defaults.ts +550 -0
- package/src/codex/subagent-model-fallback.ts +784 -0
- package/src/codex/sync.ts +319 -0
- 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 +298 -0
- package/src/codex/websocket-registry.ts +100 -0
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +160 -0
- package/src/combos/index.ts +45 -0
- package/src/combos/request.ts +94 -0
- package/src/combos/resolve.ts +232 -0
- package/src/combos/types.ts +398 -0
- package/src/config/provider-name.ts +24 -0
- package/src/config.ts +4041 -0
- package/src/fork/register.ts +3 -0
- package/src/generated/compatibility-version.json +3116 -0
- package/src/generated/model-metadata.ts +106 -0
- package/src/github/star-state.ts +203 -0
- package/src/grok/inject.ts +530 -0
- package/src/grok/inspect.ts +45 -0
- package/src/grok/status.ts +121 -0
- package/src/grok/sync.ts +66 -0
- package/src/images/artifacts.ts +516 -0
- package/src/images/fulfill-video.ts +163 -0
- package/src/images/fulfill.ts +149 -0
- package/src/images/index.ts +4 -0
- package/src/images/loop.ts +955 -0
- package/src/images/plan.ts +143 -0
- package/src/images/synthetic-tool.ts +133 -0
- package/src/images/types.ts +41 -0
- package/src/images/xai-client.ts +141 -0
- package/src/images/xai-video-client.ts +163 -0
- package/src/index.ts +22 -0
- 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/abort.ts +146 -0
- package/src/lib/admin-secrets.ts +25 -0
- package/src/lib/admission.ts +83 -0
- package/src/lib/app-owned-memory-stores.ts +195 -0
- package/src/lib/app-owned-memory.ts +265 -0
- package/src/lib/bounded-body.ts +346 -0
- package/src/lib/bun-binary-validator.d.mts +3 -0
- package/src/lib/bun-binary-validator.mjs +18 -0
- package/src/lib/bun-runtime.ts +184 -0
- package/src/lib/bun-stream-caps.ts +130 -0
- package/src/lib/codex-restart-contract.ts +120 -0
- package/src/lib/config-ownership.ts +364 -0
- package/src/lib/crash-guard.ts +344 -0
- package/src/lib/debug-log-buffer.ts +83 -0
- package/src/lib/debug-settings.ts +108 -0
- package/src/lib/debug.ts +31 -0
- package/src/lib/destination-policy.ts +380 -0
- package/src/lib/errors.ts +406 -0
- package/src/lib/eventstream-decoder.ts +253 -0
- package/src/lib/fabric-task-execution-authority.ts +7 -0
- package/src/lib/fabric-task-host.ts +29 -0
- package/src/lib/gcp-adc.ts +341 -0
- package/src/lib/injection-debug-log.ts +58 -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/open-url.ts +25 -0
- package/src/lib/optional-shutdown-hooks.ts +57 -0
- package/src/lib/pinned-http.ts +270 -0
- package/src/lib/privacy.ts +20 -0
- package/src/lib/process-control.ts +168 -0
- package/src/lib/provider-outbound.ts +210 -0
- package/src/lib/provider-url.ts +14 -0
- package/src/lib/proxy-env.ts +18 -0
- package/src/lib/redact.ts +521 -0
- package/src/lib/retry-after.ts +55 -0
- package/src/lib/self-launch-argv.ts +15 -0
- package/src/lib/server-resource-ownership.ts +71 -0
- package/src/lib/service-secrets.ts +25 -0
- package/src/lib/shadow-call.ts +61 -0
- package/src/lib/sidecar-tracker.ts +52 -0
- package/src/lib/sse-decoder.ts +364 -0
- package/src/lib/state-store-registrations.ts +119 -0
- package/src/lib/state-store-sweeper.ts +184 -0
- package/src/lib/system-restart-contract.ts +73 -0
- package/src/lib/test-home-guard.ts +90 -0
- package/src/lib/token-estimate.ts +86 -0
- package/src/lib/tool-argument-integers.ts +202 -0
- package/src/lib/translator-budget.ts +400 -0
- package/src/lib/upstream-http-version.ts +57 -0
- package/src/lib/upstream-reachability.ts +95 -0
- package/src/lib/upstream-retry.ts +392 -0
- package/src/lib/win-exec.ts +115 -0
- package/src/lib/win-paths.ts +68 -0
- package/src/lib/windows-atomic-replace.ts +156 -0
- package/src/lib/windows-elevation.ts +773 -0
- package/src/lib/windows-secret-acl.ts +854 -0
- 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 +403 -0
- 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-routing.ts +594 -0
- package/src/oauth/anthropic.ts +188 -0
- package/src/oauth/antigravity-routing.ts +151 -0
- package/src/oauth/callback-server.ts +300 -0
- package/src/oauth/chatgpt.ts +161 -0
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +252 -0
- package/src/oauth/github-copilot.ts +428 -0
- package/src/oauth/google-antigravity.ts +262 -0
- package/src/oauth/health.ts +407 -0
- package/src/oauth/index.ts +1504 -0
- package/src/oauth/key-providers.ts +124 -0
- package/src/oauth/kimi.ts +227 -0
- package/src/oauth/kiro-credentials.ts +726 -0
- package/src/oauth/kiro.ts +621 -0
- package/src/oauth/local-token-detect.ts +130 -0
- package/src/oauth/log.ts +50 -0
- package/src/oauth/login-cli.ts +223 -0
- package/src/oauth/nous.ts +798 -0
- package/src/oauth/pkce.ts +15 -0
- package/src/oauth/store.ts +728 -0
- package/src/oauth/token-guardian.ts +309 -0
- package/src/oauth/types.ts +62 -0
- package/src/oauth/xai.ts +241 -0
- package/src/providers/alibaba-region-backup.ts +75 -0
- package/src/providers/alibaba-region-migration.ts +156 -0
- package/src/providers/alibaba-region-startup.ts +36 -0
- package/src/providers/antigravity-models.ts +695 -0
- package/src/providers/antigravity-quota.ts +216 -0
- package/src/providers/api-keys.ts +140 -0
- package/src/providers/base-url-choices.ts +74 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +144 -0
- package/src/providers/context-cap.ts +82 -0
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/derive.ts +586 -0
- package/src/providers/fastwire.ts +501 -0
- package/src/providers/free-directory.ts +187 -0
- package/src/providers/github-copilot-transport.ts +56 -0
- package/src/providers/google-vertex-location.ts +14 -0
- package/src/providers/key-failover.ts +271 -0
- package/src/providers/kiro-models.ts +67 -0
- package/src/providers/label.ts +19 -0
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +449 -0
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -0
- package/src/providers/openai-sidecar.ts +243 -0
- package/src/providers/openai-tier-startup.ts +56 -0
- package/src/providers/openai-tiers.ts +423 -0
- package/src/providers/openai-virtual-models.ts +83 -0
- package/src/providers/opencode-zen-rate-limit.ts +102 -0
- package/src/providers/openrouter-routing.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +185 -0
- package/src/providers/quota.ts +2345 -0
- package/src/providers/registry.ts +2918 -0
- package/src/providers/replit/constants.ts +27 -0
- package/src/providers/replit/derive.ts +85 -0
- package/src/providers/replit/headers.ts +28 -0
- package/src/providers/replit/origin.ts +55 -0
- package/src/providers/replit/pair-install-response.ts +72 -0
- package/src/providers/replit/probe.ts +199 -0
- package/src/providers/replit/setup.ts +350 -0
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +103 -0
- 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 +148 -0
- package/src/reasoning-effort.ts +183 -0
- package/src/responses/compaction.ts +142 -0
- 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 +838 -0
- package/src/responses/provider-continuation.ts +98 -0
- package/src/responses/provider-opaque-metadata.ts +73 -0
- package/src/responses/reasoning-envelope.ts +60 -0
- package/src/responses/reasoning-replay-cache.ts +426 -0
- package/src/responses/schema.ts +165 -0
- package/src/responses/spill-store.ts +459 -0
- package/src/responses/state.ts +1433 -0
- package/src/responses/thought-signature-replay.ts +347 -0
- package/src/responses/tool-groups.ts +19 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/router.ts +761 -0
- 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 +53 -0
- package/src/server/auth-cors.ts +751 -0
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +442 -0
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +426 -0
- package/src/server/claude-messages.ts +1030 -0
- package/src/server/direct-local-http.ts +347 -0
- package/src/server/effort-policy.ts +190 -0
- package/src/server/github-copilot-responses-repair.ts +338 -0
- package/src/server/gui-static.ts +152 -0
- package/src/server/image-retry.ts +42 -0
- package/src/server/images.ts +568 -0
- package/src/server/index.ts +1813 -0
- package/src/server/lifecycle.ts +498 -0
- package/src/server/live.ts +717 -0
- 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 +1433 -0
- package/src/server/management/api-access.ts +141 -0
- package/src/server/management/api-key-usage.ts +193 -0
- package/src/server/management/body.ts +41 -0
- package/src/server/management/combo-routes.ts +263 -0
- package/src/server/management/config-routes.ts +835 -0
- package/src/server/management/context.ts +113 -0
- 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 +586 -0
- package/src/server/management/model-routes.ts +560 -0
- 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 +637 -0
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +1033 -0
- package/src/server/management/replit-provider-routes.ts +86 -0
- 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 +385 -0
- package/src/server/management/shared.ts +286 -0
- package/src/server/management/sidebar-routes.ts +106 -0
- 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 +435 -0
- package/src/server/management/system-routes.ts +194 -0
- package/src/server/management/usage-summary-cache.ts +94 -0
- 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 +314 -0
- package/src/server/management-auth.ts +482 -0
- package/src/server/memory-watchdog.ts +156 -0
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/port-reclaim.ts +307 -0
- package/src/server/ports.ts +156 -0
- package/src/server/proxy-liveness.ts +328 -0
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +353 -0
- package/src/server/relay.ts +1209 -0
- package/src/server/request-decompress.ts +239 -0
- package/src/server/request-log-conversation.ts +168 -0
- package/src/server/request-log.ts +1259 -0
- 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 +551 -0
- package/src/server/responses/compact.ts +771 -0
- package/src/server/responses/core.ts +5389 -0
- package/src/server/responses/empty-completion-guard.ts +276 -0
- package/src/server/responses/encrypted-payload.ts +331 -0
- package/src/server/responses/fetch-helpers.ts +232 -0
- package/src/server/responses/input-admission.ts +185 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/passthrough-error.ts +78 -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 +251 -0
- package/src/server/responses/upstream-error.ts +53 -0
- package/src/server/responses/ws-upstream.ts +308 -0
- package/src/server/responses-custom-tool-repair.ts +282 -0
- package/src/server/responses-image-gen-repair.ts +132 -0
- package/src/server/responses-item-id-repair.ts +272 -0
- 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 +25 -0
- package/src/server/search.ts +201 -0
- package/src/server/sse-frame-buffer.ts +292 -0
- package/src/server/sse-payload-rewrite.ts +263 -0
- package/src/server/startup-action-control.ts +315 -0
- package/src/server/startup-health-cache.ts +131 -0
- package/src/server/system-env.ts +484 -0
- package/src/server/windows-tcp-drop.ts +184 -0
- package/src/server/windows-tray-control.ts +41 -0
- package/src/server/ws-bridge.ts +472 -0
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +3575 -0
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -0
- package/src/stall-timeout.ts +20 -0
- package/src/storage/cleanup-job.ts +57 -0
- package/src/storage/cleanup.ts +3085 -0
- package/src/storage/policy-job.ts +457 -0
- package/src/storage/policy-scheduler.ts +40 -0
- package/src/storage/policy-worker.ts +59 -0
- package/src/storage/policy.ts +527 -0
- package/src/storage/restore-job.ts +299 -0
- package/src/storage/restore-worker.ts +58 -0
- package/src/storage/scanner.ts +238 -0
- package/src/storage/storage-mutation-coordinator.ts +139 -0
- package/src/storage/worker-lifecycle.ts +215 -0
- package/src/tray/assets/opencodex-tray-offline.ico +0 -0
- package/src/tray/assets/opencodex-tray-online.ico +0 -0
- package/src/tray/assets/opencodex-tray-warning.ico +0 -0
- package/src/tray/assets/opencodex-tray.png +0 -0
- package/src/tray/windows-tray.ps1 +364 -0
- package/src/tray/windows.ts +757 -0
- package/src/types/accounts.ts +37 -0
- package/src/types/config.ts +876 -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 +106 -0
- package/src/update/badge.ts +72 -0
- package/src/update/index.ts +415 -0
- package/src/update/job.ts +1887 -0
- package/src/update/notify.ts +263 -0
- package/src/update/npm-cache-preflight.d.mts +47 -0
- package/src/update/npm-cache-preflight.mjs +201 -0
- package/src/update/npm-invocation.d.mts +23 -0
- package/src/update/npm-invocation.mjs +94 -0
- package/src/update/transactional-install.d.mts +22 -0
- package/src/update/transactional-install.mjs +259 -0
- package/src/update/tray-update-plan.d.mts +18 -0
- package/src/update/tray-update-plan.mjs +38 -0
- package/src/usage/cost.ts +625 -0
- package/src/usage/debug.ts +97 -0
- package/src/usage/expected-prices.ts +416 -0
- package/src/usage/log.ts +1223 -0
- package/src/usage/summary.ts +753 -0
- package/src/usage/totals.ts +14 -0
- 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 +189 -0
- package/src/vision/backends.ts +97 -0
- package/src/vision/describe.ts +131 -0
- package/src/vision/eligibility.ts +250 -0
- package/src/vision/index.ts +681 -0
- 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 +195 -0
- package/src/web-search/backends.ts +108 -0
- package/src/web-search/exa-executor.ts +88 -0
- package/src/web-search/executor.ts +113 -0
- package/src/web-search/format-result.ts +89 -0
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +331 -0
- package/src/web-search/loop.ts +896 -0
- package/src/web-search/parse.ts +315 -0
- package/src/web-search/progress-stream.ts +342 -0
- package/src/web-search/sources.ts +60 -0
- package/src/web-search/synthetic-tool.ts +47 -0
- package/src/web-search/xai-executor.ts +219 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { isAbsolute } from "node:path";
|
|
2
|
+
import { codexExecInvocation } from "../codex/exec-invocation";
|
|
3
|
+
import { resolveAndPersistCodexRuntime, type ResolveCodexRuntimeDeps } from "../codex/runtime";
|
|
4
|
+
import type { ResolveDeps, SpawnInvocation } from "../lib/win-exec";
|
|
5
|
+
import {
|
|
6
|
+
apiError,
|
|
7
|
+
apiJson,
|
|
8
|
+
proxyUnreachable,
|
|
9
|
+
resolveBaseUrl,
|
|
10
|
+
type AccountDeps,
|
|
11
|
+
type NativeMainLoginChild,
|
|
12
|
+
type StageLeaseClock,
|
|
13
|
+
} from "./account-api";
|
|
14
|
+
|
|
15
|
+
const USAGE = `Usage:
|
|
16
|
+
ocx account main doctor [--json]
|
|
17
|
+
ocx account main list [--json]
|
|
18
|
+
ocx account main register <label> [--json]
|
|
19
|
+
ocx account main add <label>
|
|
20
|
+
ocx account main switch <profile-id-or-label> --yes [--json]
|
|
21
|
+
ocx account main recover [--rollback --yes] [--json]
|
|
22
|
+
|
|
23
|
+
Native main login profiles change the physical Codex App/CLI login in the effective CODEX_HOME.
|
|
24
|
+
They are independent from the OpenCodex Pool selected by 'ocx account use openai'.`;
|
|
25
|
+
|
|
26
|
+
const STAGE_LEASE_SAFETY_MARGIN_MS = 30_000;
|
|
27
|
+
|
|
28
|
+
const systemStageLeaseClock: StageLeaseClock = {
|
|
29
|
+
now: Date.now,
|
|
30
|
+
setTimeout: (callback, ms) => setTimeout(callback, ms),
|
|
31
|
+
clearTimeout: timer => clearTimeout(timer),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
interface PublicProfile {
|
|
35
|
+
id: string;
|
|
36
|
+
label: string;
|
|
37
|
+
identityHint: string;
|
|
38
|
+
state: "active" | "inactive";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type NativeMainCodexLoginInvocationDeps =
|
|
42
|
+
& ResolveDeps
|
|
43
|
+
& Pick<ResolveCodexRuntimeDeps, "existsSync" | "execFileSync" | "configDir" | "readFileSync">;
|
|
44
|
+
|
|
45
|
+
function flag(args: string[], name: string): boolean {
|
|
46
|
+
const index = args.indexOf(name);
|
|
47
|
+
if (index < 0) return false;
|
|
48
|
+
args.splice(index, 1);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function reject(args: string[]): number {
|
|
53
|
+
if (args.length > 0) console.error(`Unexpected argument(s): ${args.join(", ")}`);
|
|
54
|
+
console.error(USAGE);
|
|
55
|
+
return 1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function effectiveCodexHome(result: Record<string, unknown>): string {
|
|
59
|
+
return typeof result.effectiveCodexHome === "string" && result.effectiveCodexHome.length > 0
|
|
60
|
+
? result.effectiveCodexHome
|
|
61
|
+
: "the effective CODEX_HOME";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function printProfiles(profiles: PublicProfile[]): void {
|
|
65
|
+
if (profiles.length === 0) { console.log("No native main login profiles registered."); return; }
|
|
66
|
+
const rows = profiles.map(profile => [profile.state === "active" ? "*" : " ", profile.label, profile.id, profile.identityHint]);
|
|
67
|
+
const header = ["", "LABEL", "PROFILE ID", "IDENTITY"];
|
|
68
|
+
const widths = header.map((value, index) => Math.max(value.length, ...rows.map(row => row[index]!.length)));
|
|
69
|
+
const line = (columns: string[]) => columns.map((value, index) => value.padEnd(widths[index]!)).join(" ").trimEnd();
|
|
70
|
+
console.log([line(header), ...rows.map(line)].join("\n"));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function nativeMainCodexLoginInvocation(
|
|
74
|
+
platform: NodeJS.Platform = process.platform,
|
|
75
|
+
deps: NativeMainCodexLoginInvocationDeps = {},
|
|
76
|
+
): SpawnInvocation {
|
|
77
|
+
const command = resolveAndPersistCodexRuntime({
|
|
78
|
+
env: deps.env ?? process.env,
|
|
79
|
+
platform,
|
|
80
|
+
existsSync: deps.existsSync,
|
|
81
|
+
execFileSync: deps.execFileSync,
|
|
82
|
+
configDir: deps.configDir,
|
|
83
|
+
readFileSync: deps.readFileSync,
|
|
84
|
+
discoverAlternatives: false,
|
|
85
|
+
}).runtime.command || "codex";
|
|
86
|
+
return codexExecInvocation(command, ["login"], platform, deps);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function spawnOfficialCodexLogin(codexHome: string): NativeMainLoginChild {
|
|
90
|
+
const invocation = nativeMainCodexLoginInvocation();
|
|
91
|
+
const child = Bun.spawn([invocation.file, ...invocation.args], {
|
|
92
|
+
env: { ...process.env, CODEX_HOME: codexHome },
|
|
93
|
+
stdin: "inherit",
|
|
94
|
+
stdout: "inherit",
|
|
95
|
+
stderr: "inherit",
|
|
96
|
+
...(invocation.options.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}),
|
|
97
|
+
});
|
|
98
|
+
return child;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function abortableDelay(ms: number, signal: AbortSignal, clock: StageLeaseClock): Promise<void> {
|
|
102
|
+
if (signal.aborted) return Promise.resolve();
|
|
103
|
+
return new Promise(resolve => {
|
|
104
|
+
const timer = clock.setTimeout(done, ms);
|
|
105
|
+
signal.addEventListener("abort", done, { once: true });
|
|
106
|
+
function done(): void {
|
|
107
|
+
clock.clearTimeout(timer);
|
|
108
|
+
signal.removeEventListener("abort", done);
|
|
109
|
+
resolve();
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function maintainStageLease(
|
|
115
|
+
deps: AccountDeps,
|
|
116
|
+
baseUrl: string,
|
|
117
|
+
stageId: string,
|
|
118
|
+
writerToken: string,
|
|
119
|
+
initialLeaseExpiresAt: number,
|
|
120
|
+
heartbeatIntervalMs: number,
|
|
121
|
+
child: NativeMainLoginChild,
|
|
122
|
+
signal: AbortSignal,
|
|
123
|
+
clock: StageLeaseClock,
|
|
124
|
+
): Promise<{ lost: boolean }> {
|
|
125
|
+
let leaseExpiresAt = initialLeaseExpiresAt;
|
|
126
|
+
for (;;) {
|
|
127
|
+
if (signal.aborted) return { lost: false };
|
|
128
|
+
const deadlineAt = leaseExpiresAt - STAGE_LEASE_SAFETY_MARGIN_MS;
|
|
129
|
+
if (clock.now() >= deadlineAt) {
|
|
130
|
+
try { child.kill(); } catch { /* child exit below is authoritative */ }
|
|
131
|
+
return { lost: true };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const heartbeatAbort = new AbortController();
|
|
135
|
+
const deadlineReached = Symbol("heartbeat-deadline");
|
|
136
|
+
const parentCancelled = Symbol("heartbeat-parent-cancelled");
|
|
137
|
+
let resolveInterruption!: (result: typeof deadlineReached | typeof parentCancelled) => void;
|
|
138
|
+
const interruption = new Promise<typeof deadlineReached | typeof parentCancelled>(resolve => {
|
|
139
|
+
resolveInterruption = resolve;
|
|
140
|
+
});
|
|
141
|
+
const cancelHeartbeat = () => {
|
|
142
|
+
heartbeatAbort.abort();
|
|
143
|
+
resolveInterruption(parentCancelled);
|
|
144
|
+
};
|
|
145
|
+
signal.addEventListener("abort", cancelHeartbeat, { once: true });
|
|
146
|
+
const deadlineTimer = clock.setTimeout(() => {
|
|
147
|
+
heartbeatAbort.abort();
|
|
148
|
+
resolveInterruption(deadlineReached);
|
|
149
|
+
}, Math.max(0, deadlineAt - clock.now()));
|
|
150
|
+
const heartbeatRequest = apiJson(
|
|
151
|
+
deps,
|
|
152
|
+
baseUrl,
|
|
153
|
+
"POST",
|
|
154
|
+
"/api/native-main-profiles/stage/heartbeat",
|
|
155
|
+
{ stageId, writerToken },
|
|
156
|
+
{ signal: heartbeatAbort.signal },
|
|
157
|
+
);
|
|
158
|
+
const heartbeat = await Promise.race([heartbeatRequest, interruption]);
|
|
159
|
+
clock.clearTimeout(deadlineTimer);
|
|
160
|
+
signal.removeEventListener("abort", cancelHeartbeat);
|
|
161
|
+
if (signal.aborted) return { lost: false };
|
|
162
|
+
if (heartbeat === parentCancelled) return { lost: false };
|
|
163
|
+
if (heartbeat === deadlineReached) {
|
|
164
|
+
try { child.kill(); } catch { /* child exit below is authoritative */ }
|
|
165
|
+
return { lost: true };
|
|
166
|
+
}
|
|
167
|
+
if (heartbeat.status === 200 && typeof heartbeat.json.leaseExpiresAt === "number") {
|
|
168
|
+
leaseExpiresAt = heartbeat.json.leaseExpiresAt;
|
|
169
|
+
await abortableDelay(Math.min(heartbeatIntervalMs, Math.max(0, leaseExpiresAt - STAGE_LEASE_SAFETY_MARGIN_MS - clock.now())), signal, clock);
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (heartbeat.status === 0 && clock.now() < leaseExpiresAt - STAGE_LEASE_SAFETY_MARGIN_MS) {
|
|
173
|
+
await abortableDelay(Math.min(5_000, heartbeatIntervalMs, leaseExpiresAt - STAGE_LEASE_SAFETY_MARGIN_MS - clock.now()), signal, clock);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
try { child.kill(); } catch { /* child exit below is authoritative */ }
|
|
177
|
+
return { lost: true };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export async function cmdNativeMainAccount(args: string[], deps: AccountDeps): Promise<number> {
|
|
182
|
+
const sub = args.shift();
|
|
183
|
+
const wantsJson = flag(args, "--json");
|
|
184
|
+
const confirmed = flag(args, "--yes");
|
|
185
|
+
const rollback = flag(args, "--rollback");
|
|
186
|
+
const baseUrl = await resolveBaseUrl(deps);
|
|
187
|
+
if (!baseUrl) return proxyUnreachable();
|
|
188
|
+
|
|
189
|
+
if (sub === "doctor" || sub === "list") {
|
|
190
|
+
if (args.length > 0 || confirmed || rollback) return reject(args);
|
|
191
|
+
const path = sub === "doctor" ? "/api/native-main-profiles/doctor" : "/api/native-main-profiles";
|
|
192
|
+
const result = await apiJson(deps, baseUrl, "GET", path);
|
|
193
|
+
if (result.status === 0) return proxyUnreachable();
|
|
194
|
+
if (result.status !== 200) return apiError(result.json, `failed to ${sub} native profiles`);
|
|
195
|
+
if (wantsJson || sub === "doctor") console.log(JSON.stringify(result.json, null, 2));
|
|
196
|
+
else printProfiles(Array.isArray(result.json.profiles) ? result.json.profiles as PublicProfile[] : []);
|
|
197
|
+
return 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (sub === "register") {
|
|
201
|
+
const label = args.shift();
|
|
202
|
+
if (!label || args.length > 0 || confirmed || rollback) return reject(args);
|
|
203
|
+
const result = await apiJson(deps, baseUrl, "POST", "/api/native-main-profiles/register", { label });
|
|
204
|
+
if (result.status === 0) return proxyUnreachable();
|
|
205
|
+
if (result.status !== 200) return apiError(result.json, "failed to register the current native login");
|
|
206
|
+
if (wantsJson) console.log(JSON.stringify(result.json, null, 2));
|
|
207
|
+
else console.log(`Registered '${label}' for ${effectiveCodexHome(result.json)}.`);
|
|
208
|
+
return 0;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (sub === "add") {
|
|
212
|
+
const label = args.shift();
|
|
213
|
+
if (!label || args.length > 0 || wantsJson || confirmed || rollback) return reject(args);
|
|
214
|
+
const stage = await apiJson(deps, baseUrl, "POST", "/api/native-main-profiles/stage", {});
|
|
215
|
+
if (stage.status === 0) return proxyUnreachable();
|
|
216
|
+
if (stage.status !== 200) return apiError(stage.json, "failed to prepare native login staging");
|
|
217
|
+
const stageId = typeof stage.json.stageId === "string" ? stage.json.stageId : "";
|
|
218
|
+
const writerToken = typeof stage.json.writerToken === "string" ? stage.json.writerToken : "";
|
|
219
|
+
const stagingHome = typeof stage.json.stagingCodexHome === "string" ? stage.json.stagingCodexHome : "";
|
|
220
|
+
const leaseExpiresAt = typeof stage.json.leaseExpiresAt === "number" ? stage.json.leaseExpiresAt : 0;
|
|
221
|
+
const heartbeatIntervalMs = typeof stage.json.heartbeatIntervalMs === "number"
|
|
222
|
+
? Math.min(5 * 60_000, Math.max(deps.stageHeartbeatIntervalMinMs ?? 5_000, stage.json.heartbeatIntervalMs))
|
|
223
|
+
: 60_000;
|
|
224
|
+
const stageLeaseClock = deps.stageLeaseClock ?? systemStageLeaseClock;
|
|
225
|
+
const stagedEffectiveHome = effectiveCodexHome(stage.json);
|
|
226
|
+
let exitCode = 1;
|
|
227
|
+
let finished = false;
|
|
228
|
+
let leaseLost = false;
|
|
229
|
+
try {
|
|
230
|
+
if (!stageId || !writerToken || !isAbsolute(stagingHome) || leaseExpiresAt <= stageLeaseClock.now()) {
|
|
231
|
+
throw new Error("The proxy returned an invalid staging session.");
|
|
232
|
+
}
|
|
233
|
+
console.error(`Effective CODEX_HOME: ${stagedEffectiveHome}`);
|
|
234
|
+
console.error(`Starting official Codex login in restricted staging home: ${stagingHome}`);
|
|
235
|
+
const child = deps.spawnCodexLoginImpl
|
|
236
|
+
? deps.spawnCodexLoginImpl(stagingHome)
|
|
237
|
+
: deps.runCodexLoginImpl
|
|
238
|
+
? { exited: deps.runCodexLoginImpl(stagingHome), kill: () => {} }
|
|
239
|
+
: spawnOfficialCodexLogin(stagingHome);
|
|
240
|
+
const heartbeatAbort = new AbortController();
|
|
241
|
+
const heartbeat = maintainStageLease(
|
|
242
|
+
deps,
|
|
243
|
+
baseUrl,
|
|
244
|
+
stageId,
|
|
245
|
+
writerToken,
|
|
246
|
+
leaseExpiresAt,
|
|
247
|
+
heartbeatIntervalMs,
|
|
248
|
+
child,
|
|
249
|
+
heartbeatAbort.signal,
|
|
250
|
+
stageLeaseClock,
|
|
251
|
+
);
|
|
252
|
+
try {
|
|
253
|
+
exitCode = await child.exited;
|
|
254
|
+
} finally {
|
|
255
|
+
heartbeatAbort.abort();
|
|
256
|
+
leaseLost = (await heartbeat).lost;
|
|
257
|
+
}
|
|
258
|
+
if (leaseLost) throw new Error("The native-login staging lease was lost before login completed.");
|
|
259
|
+
if (exitCode !== 0) throw new Error("Official Codex login did not complete successfully.");
|
|
260
|
+
const finish = await apiJson(deps, baseUrl, "POST", "/api/native-main-profiles/stage/finish", { stageId, writerToken, label });
|
|
261
|
+
if (finish.status === 0) return proxyUnreachable();
|
|
262
|
+
if (finish.status !== 200) return apiError(finish.json, "failed to encrypt the staged native login");
|
|
263
|
+
finished = true;
|
|
264
|
+
console.log(`Added encrypted native profile '${label}' for ${effectiveCodexHome(finish.json)}.`);
|
|
265
|
+
return 0;
|
|
266
|
+
} catch (error) {
|
|
267
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Official Codex login failed."}`);
|
|
268
|
+
return exitCode === 0 ? 1 : exitCode;
|
|
269
|
+
} finally {
|
|
270
|
+
if (stageId && !finished) {
|
|
271
|
+
const cleanup = await apiJson(deps, baseUrl, "POST", "/api/native-main-profiles/stage/cancel", { stageId, writerToken });
|
|
272
|
+
if (cleanup.status !== 200 || cleanup.json.plaintextMayRemain === true) {
|
|
273
|
+
console.error("Error: the proxy could not confirm native-login staging cleanup; run account main doctor.");
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (sub === "switch") {
|
|
280
|
+
const target = args.shift();
|
|
281
|
+
if (!target || args.length > 0 || rollback || !confirmed) {
|
|
282
|
+
if (!confirmed) console.error("Close Codex App/CLI, then pass --yes to confirm it is stopped.");
|
|
283
|
+
return reject(args);
|
|
284
|
+
}
|
|
285
|
+
const result = await apiJson(deps, baseUrl, "POST", "/api/native-main-profiles/switch", { target, confirmedStopped: true });
|
|
286
|
+
if (result.status === 0) return proxyUnreachable();
|
|
287
|
+
if (result.status !== 200) return apiError(result.json, "failed to switch the native login");
|
|
288
|
+
if (wantsJson) console.log(JSON.stringify(result.json, null, 2));
|
|
289
|
+
else {
|
|
290
|
+
const profile = result.json.activeProfile as PublicProfile | undefined;
|
|
291
|
+
console.log(`Native Codex login for ${effectiveCodexHome(result.json)} is now '${profile?.label ?? target}'. Restart Codex App/CLI before continuing.`);
|
|
292
|
+
}
|
|
293
|
+
return 0;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (sub === "recover") {
|
|
297
|
+
if (args.length > 0 || (rollback && !confirmed)) {
|
|
298
|
+
if (rollback && !confirmed) console.error("--rollback changes the native login and requires --yes.");
|
|
299
|
+
return reject(args);
|
|
300
|
+
}
|
|
301
|
+
const result = await apiJson(deps, baseUrl, "POST", "/api/native-main-profiles/recover", rollback
|
|
302
|
+
? { rollback: true, confirmedStopped: true }
|
|
303
|
+
: { rollback: false });
|
|
304
|
+
if (result.status === 0) return proxyUnreachable();
|
|
305
|
+
if (result.status !== 200) return apiError(result.json, "failed to recover the native-profile transaction");
|
|
306
|
+
if (wantsJson) console.log(JSON.stringify(result.json, null, 2));
|
|
307
|
+
else {
|
|
308
|
+
const home = effectiveCodexHome(result.json);
|
|
309
|
+
console.log(result.json.recovered === true
|
|
310
|
+
? `Recovery completed for ${home}: ${String(result.json.action ?? "converged")}.`
|
|
311
|
+
: `No recovery journal is pending for ${home}.`);
|
|
312
|
+
}
|
|
313
|
+
return 0;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return reject(args);
|
|
317
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/** `ocx account` — list and switch provider credentials (issue #180). */
|
|
2
|
+
import { loadConfig } from "../config";
|
|
3
|
+
import { providerCodexAccountMode } from "../providers/registry";
|
|
4
|
+
import type { OcxConfig } from "../types";
|
|
5
|
+
import { cmdAddKey, cmdAlias, cmdAutoSwitch, cmdClearCooldown, cmdImport, cmdPriority, cmdRefresh, cmdRemove } from "./account-extended";
|
|
6
|
+
import { apiError, apiJson, classifyAccount, fetchRows, proxyUnreachable, resolveBaseUrl, type AccountDeps, type AccountRow, type AccountType, type ApiResult }
|
|
7
|
+
from "./account-api";
|
|
8
|
+
|
|
9
|
+
export { classifyAccount } from "./account-api";
|
|
10
|
+
export type { AccountDeps, AccountRow, AccountType, ClassifyResult } from "./account-api";
|
|
11
|
+
type TargetProvenance = "live-oauth-list" | "config" | "codex";
|
|
12
|
+
|
|
13
|
+
const MAIN_ALIAS = "main";
|
|
14
|
+
const MAIN_CODEX_ID = "__main__";
|
|
15
|
+
/** Replacement-style single-slot OAuth (no stable identity; not HTTP-derivable). */
|
|
16
|
+
const REPLACEMENT_STYLE_OAUTH = new Set(["kiro"]);
|
|
17
|
+
|
|
18
|
+
const ACCOUNT_USAGE = `Usage:
|
|
19
|
+
ocx account list [provider] [--json] [--all]
|
|
20
|
+
ocx account current <provider> [--json]
|
|
21
|
+
ocx account use <provider> <account-or-key-id|main> [--json]
|
|
22
|
+
ocx account refresh <provider> [--json]
|
|
23
|
+
ocx account auto-switch <provider> <on|off|status|threshold <0-100>> [--json]
|
|
24
|
+
ocx account alias <provider> <account-or-key-id> <display-name|-> [--json]
|
|
25
|
+
ocx account priority <provider> <account-id|main> [<-100..100|first|earlier|normal|later|last|reset>] [--json]
|
|
26
|
+
ocx account remove <provider> <account-or-key-id|main> --yes [--json]
|
|
27
|
+
ocx account clear-cooldown <provider> <account-id|main> [--json]
|
|
28
|
+
ocx account add-key <provider> [--label <label>] [--json]
|
|
29
|
+
ocx account import <provider> --format <format> (--file <path>|--stdin) [--json]
|
|
30
|
+
ocx account login <provider> [--id <account-id>] [--reauth] [--code -] [--no-wait] [--json]
|
|
31
|
+
ocx account code <provider> [--flow <flow-id>] [--json] (reads the code from stdin)
|
|
32
|
+
ocx account cancel <provider> [--flow <flow-id>] [--json]
|
|
33
|
+
ocx account reset-credits <account-id|main> [--consume --yes] [--json]
|
|
34
|
+
ocx account main <doctor|list|register|add|switch|recover> ...
|
|
35
|
+
|
|
36
|
+
List and switch provider accounts and API-key pools (masked output only).
|
|
37
|
+
'main' selects the Codex App login for the openai account pool.`;
|
|
38
|
+
|
|
39
|
+
function consumeFlag(args: string[], flag: string): boolean {
|
|
40
|
+
const idx = args.indexOf(flag);
|
|
41
|
+
if (idx === -1) return false;
|
|
42
|
+
args.splice(idx, 1);
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Returns an error message for leftover args, or null when clean. */
|
|
47
|
+
function leftoverArgsError(args: string[]): string | null {
|
|
48
|
+
if (args.length === 0) return null;
|
|
49
|
+
const unknown = args.filter(a => a.startsWith("-"));
|
|
50
|
+
return unknown.length > 0
|
|
51
|
+
? `Unknown flag(s): ${unknown.join(", ")}`
|
|
52
|
+
: `Unexpected argument(s): ${args.join(", ")}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function candidateNames(config: OcxConfig): string {
|
|
56
|
+
const names = new Set<string>(["openai"]);
|
|
57
|
+
for (const n of Object.keys(config.providers ?? {})) names.add(n);
|
|
58
|
+
return [...names].join(", ");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function displayId(id: string): string {
|
|
62
|
+
return id === MAIN_CODEX_ID ? MAIN_ALIAS : id;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function statusText(row: AccountRow): string {
|
|
66
|
+
const parts: string[] = [];
|
|
67
|
+
if (row.active) parts.push(row.type === "codex" ? "selected" : "active");
|
|
68
|
+
if (row.needsReauth) parts.push("needs-reauth");
|
|
69
|
+
return parts.join(" ");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Signed so the sort direction reads off the column; "-" where ordering does not apply. */
|
|
73
|
+
function priorityText(row: AccountRow): string {
|
|
74
|
+
if (row.priority === undefined) return "-";
|
|
75
|
+
return row.priority > 0 ? `+${row.priority}` : String(row.priority);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function formatAccountTable(rows: AccountRow[]): string {
|
|
79
|
+
const header = ["PROVIDER", "TYPE", "ID", "PLAN/LABEL", "PRIORITY", "STATUS"];
|
|
80
|
+
const data = rows.map(r => {
|
|
81
|
+
const keyLabel = r.masked && r.label !== r.masked ? `${r.masked} (${r.label})` : r.masked;
|
|
82
|
+
return [
|
|
83
|
+
r.provider,
|
|
84
|
+
r.type,
|
|
85
|
+
displayId(r.id),
|
|
86
|
+
r.type === "api-key" ? keyLabel ?? "-" : r.label ?? "-",
|
|
87
|
+
priorityText(r),
|
|
88
|
+
statusText(r),
|
|
89
|
+
];
|
|
90
|
+
});
|
|
91
|
+
const widths = header.map((h, i) => Math.max(h.length, ...data.map(d => d[i]!.length)));
|
|
92
|
+
const line = (cols: string[]) => cols.map((c, i) => c.padEnd(widths[i]!)).join(" ").trimEnd();
|
|
93
|
+
return [line(header), ...data.map(line)].join("\n");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function cmdList(rest: string[], deps: AccountDeps): Promise<number> {
|
|
97
|
+
const wantsJson = consumeFlag(rest, "--json");
|
|
98
|
+
const showAll = consumeFlag(rest, "--all");
|
|
99
|
+
const name = rest.shift();
|
|
100
|
+
const leftover = leftoverArgsError(rest);
|
|
101
|
+
if (leftover) {
|
|
102
|
+
console.error(leftover);
|
|
103
|
+
console.error(ACCOUNT_USAGE);
|
|
104
|
+
return 1;
|
|
105
|
+
}
|
|
106
|
+
const config = deps.loadConfigImpl?.() ?? loadConfig();
|
|
107
|
+
const baseUrl = await resolveBaseUrl(deps);
|
|
108
|
+
if (!baseUrl) return proxyUnreachable();
|
|
109
|
+
|
|
110
|
+
const targets: { name: string; type: AccountType; provenance: TargetProvenance }[] = [];
|
|
111
|
+
if (name) {
|
|
112
|
+
const c = classifyAccount(config, name);
|
|
113
|
+
if ("error" in c) {
|
|
114
|
+
console.error(`Error: ${c.error}. Known candidates: ${candidateNames(config)}`);
|
|
115
|
+
return 1;
|
|
116
|
+
}
|
|
117
|
+
targets.push({ name, type: c.type, provenance: "config" });
|
|
118
|
+
} else {
|
|
119
|
+
const seen = new Set<string>();
|
|
120
|
+
const push = (n: string, provenance: TargetProvenance) => {
|
|
121
|
+
if (seen.has(n)) return;
|
|
122
|
+
seen.add(n);
|
|
123
|
+
const c = classifyAccount(config, n);
|
|
124
|
+
if ("error" in c) return; // fan-out silently skips no-credential providers
|
|
125
|
+
targets.push({ name: n, type: c.type, provenance });
|
|
126
|
+
};
|
|
127
|
+
push("openai", "codex");
|
|
128
|
+
const providersRes = await apiJson(deps, baseUrl, "GET", "/api/oauth/providers");
|
|
129
|
+
if (providersRes.status === 0) return proxyUnreachable();
|
|
130
|
+
if (providersRes.status !== 200) return apiError(providersRes.json, "failed to list OAuth providers");
|
|
131
|
+
if (Array.isArray(providersRes.json.providers)) {
|
|
132
|
+
for (const p of providersRes.json.providers) {
|
|
133
|
+
if (typeof p === "string") push(p, "live-oauth-list");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
for (const n of Object.keys(config.providers ?? {})) push(n, "config");
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const rows: AccountRow[] = [];
|
|
140
|
+
const notes: string[] = [];
|
|
141
|
+
for (const t of targets) {
|
|
142
|
+
const r = await fetchRows(deps, baseUrl, t.name, t.type);
|
|
143
|
+
if (r.networkDown) return proxyUnreachable();
|
|
144
|
+
if (r.errorJson) {
|
|
145
|
+
if (name) return apiError(r.errorJson, `failed to list ${t.name}`);
|
|
146
|
+
const errorText = typeof r.errorJson.error === "string" ? r.errorJson.error : "";
|
|
147
|
+
const skipUnknownKey = t.type === "api-key"
|
|
148
|
+
&& r.status === 404
|
|
149
|
+
&& errorText.includes("unknown provider");
|
|
150
|
+
const skipConfigOAuth = t.type === "oauth"
|
|
151
|
+
&& t.provenance === "config"
|
|
152
|
+
&& r.status === 400
|
|
153
|
+
&& errorText.includes("unknown oauth provider");
|
|
154
|
+
if (skipUnknownKey || skipConfigOAuth) continue;
|
|
155
|
+
return apiError(r.errorJson, `failed to list ${t.name}`);
|
|
156
|
+
}
|
|
157
|
+
if (r.rows.length === 0) {
|
|
158
|
+
if (showAll) notes.push(`${t.name}: no stored accounts or keys`);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
rows.push(...r.rows);
|
|
162
|
+
if (t.type === "codex") {
|
|
163
|
+
if (r.activeId === null) notes.push("openai: auto (no pin — lowest-usage account is selected per request)");
|
|
164
|
+
if (providerCodexAccountMode("openai", config.providers?.openai) === "direct") {
|
|
165
|
+
notes.push("openai is in direct mode — the selection takes effect when pool mode is enabled");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (t.type === "oauth" && REPLACEMENT_STYLE_OAUTH.has(t.name)) {
|
|
169
|
+
notes.push(`${t.name}: single login slot — re-login replaces the current account`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (wantsJson) {
|
|
174
|
+
console.log(JSON.stringify({ accounts: rows, notes }, null, 2));
|
|
175
|
+
return 0;
|
|
176
|
+
}
|
|
177
|
+
if (rows.length > 0) console.log(formatAccountTable(rows));
|
|
178
|
+
for (const n of notes) console.log(n);
|
|
179
|
+
if (rows.length === 0 && notes.length === 0) console.log("No stored accounts or keys.");
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function cmdCurrent(rest: string[], deps: AccountDeps): Promise<number> {
|
|
184
|
+
const wantsJson = consumeFlag(rest, "--json");
|
|
185
|
+
const name = rest.shift();
|
|
186
|
+
const leftover = leftoverArgsError(rest);
|
|
187
|
+
if (!name || leftover) {
|
|
188
|
+
if (leftover) console.error(leftover);
|
|
189
|
+
console.error(ACCOUNT_USAGE);
|
|
190
|
+
return 1;
|
|
191
|
+
}
|
|
192
|
+
const config = deps.loadConfigImpl?.() ?? loadConfig();
|
|
193
|
+
const c = classifyAccount(config, name);
|
|
194
|
+
if ("error" in c) {
|
|
195
|
+
console.error(`Error: ${c.error}. Known candidates: ${candidateNames(config)}`);
|
|
196
|
+
return 1;
|
|
197
|
+
}
|
|
198
|
+
const baseUrl = await resolveBaseUrl(deps);
|
|
199
|
+
if (!baseUrl) return proxyUnreachable();
|
|
200
|
+
const r = await fetchRows(deps, baseUrl, name, c.type);
|
|
201
|
+
if (r.networkDown) return proxyUnreachable();
|
|
202
|
+
if (r.errorJson) return apiError(r.errorJson, `failed to read ${name}`);
|
|
203
|
+
|
|
204
|
+
const activeRow = r.rows.find(row => row.active) ?? null;
|
|
205
|
+
if (wantsJson) {
|
|
206
|
+
console.log(JSON.stringify({
|
|
207
|
+
provider: name,
|
|
208
|
+
type: c.type,
|
|
209
|
+
activeId: r.activeId,
|
|
210
|
+
autoSwitchThreshold: r.autoSwitchThreshold,
|
|
211
|
+
account: activeRow,
|
|
212
|
+
}, null, 2));
|
|
213
|
+
return 0;
|
|
214
|
+
}
|
|
215
|
+
if (activeRow) {
|
|
216
|
+
console.log(formatAccountTable([activeRow]));
|
|
217
|
+
} else if (c.type === "codex" && r.activeId === null) {
|
|
218
|
+
console.log("openai: auto (no pin — lowest-usage account is selected per request)");
|
|
219
|
+
} else {
|
|
220
|
+
console.log(`${name}: no active account or key`);
|
|
221
|
+
}
|
|
222
|
+
return 0;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async function cmdUse(rest: string[], deps: AccountDeps): Promise<number> {
|
|
226
|
+
const wantsJson = consumeFlag(rest, "--json");
|
|
227
|
+
const name = rest.shift();
|
|
228
|
+
const id = rest.shift();
|
|
229
|
+
const leftover = leftoverArgsError(rest);
|
|
230
|
+
if (!name || !id || leftover) {
|
|
231
|
+
if (leftover) console.error(leftover);
|
|
232
|
+
console.error(ACCOUNT_USAGE);
|
|
233
|
+
return 1;
|
|
234
|
+
}
|
|
235
|
+
const config = deps.loadConfigImpl?.() ?? loadConfig();
|
|
236
|
+
const c = classifyAccount(config, name);
|
|
237
|
+
if ("error" in c) {
|
|
238
|
+
console.error(`Error: ${c.error}. Known candidates: ${candidateNames(config)}`);
|
|
239
|
+
return 1;
|
|
240
|
+
}
|
|
241
|
+
const baseUrl = await resolveBaseUrl(deps);
|
|
242
|
+
if (!baseUrl) return proxyUnreachable();
|
|
243
|
+
|
|
244
|
+
let res: ApiResult;
|
|
245
|
+
let activeId: string;
|
|
246
|
+
if (c.type === "codex") {
|
|
247
|
+
activeId = id === MAIN_ALIAS ? MAIN_CODEX_ID : id;
|
|
248
|
+
res = await apiJson(deps, baseUrl, "PUT", "/api/codex-auth/active", { accountId: activeId });
|
|
249
|
+
} else if (c.type === "oauth") {
|
|
250
|
+
activeId = id;
|
|
251
|
+
res = await apiJson(deps, baseUrl, "PUT", "/api/oauth/accounts/active", { provider: name, accountId: id });
|
|
252
|
+
} else {
|
|
253
|
+
activeId = id;
|
|
254
|
+
res = await apiJson(deps, baseUrl, "PUT", "/api/providers/keys/active", { name, id });
|
|
255
|
+
}
|
|
256
|
+
if (res.status === 0) return proxyUnreachable();
|
|
257
|
+
if (res.status !== 200) return apiError(res.json, `failed to switch ${name}`);
|
|
258
|
+
|
|
259
|
+
if (wantsJson) console.log(JSON.stringify({ ok: true, provider: name, type: c.type, activeId }, null, 2));
|
|
260
|
+
else console.log(`${name}: active ${c.type === "api-key" ? "key" : "account"} is now ${displayId(activeId)}`);
|
|
261
|
+
if (c.type === "codex") {
|
|
262
|
+
console.error("Takes effect immediately; running threads move on their next request, and in-flight requests keep the account they captured.");
|
|
263
|
+
const active = await apiJson(deps, baseUrl, "GET", "/api/codex-auth/active");
|
|
264
|
+
if (active.status === 200 && typeof active.json.autoSwitchThreshold === "number" && active.json.autoSwitchThreshold > 0) {
|
|
265
|
+
console.error(`Note: auto-switch (threshold ${active.json.autoSwitchThreshold}%) may override this pin.`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return 0;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export async function cmdAccount(args: string[], deps: AccountDeps = {}): Promise<number> {
|
|
272
|
+
const [sub, ...rest] = args;
|
|
273
|
+
try {
|
|
274
|
+
if (sub === "list") return await cmdList(rest, deps);
|
|
275
|
+
if (sub === "current") return await cmdCurrent(rest, deps);
|
|
276
|
+
if (sub === "use") return await cmdUse(rest, deps);
|
|
277
|
+
if (sub === "refresh") return await cmdRefresh(rest, deps);
|
|
278
|
+
if (sub === "auto-switch") return await cmdAutoSwitch(rest, deps);
|
|
279
|
+
if (sub === "alias" || sub === "rename") return await cmdAlias(rest, deps);
|
|
280
|
+
if (sub === "priority") return await cmdPriority(rest, deps);
|
|
281
|
+
if (sub === "remove") return await cmdRemove(rest, deps);
|
|
282
|
+
if (sub === "clear-cooldown") return await cmdClearCooldown(rest, deps);
|
|
283
|
+
if (sub === "add-key") return await cmdAddKey(rest, deps);
|
|
284
|
+
if (sub === "import") return await cmdImport(rest, deps);
|
|
285
|
+
if (sub === "main") {
|
|
286
|
+
const { cmdNativeMainAccount } = await import("./account-main");
|
|
287
|
+
return await cmdNativeMainAccount(rest, deps);
|
|
288
|
+
}
|
|
289
|
+
if (["login", "reauth", "code", "cancel", "reset-credits"].includes(sub ?? "")) {
|
|
290
|
+
const { handleAccountAuthCommand } = await import("./account-auth");
|
|
291
|
+
return await handleAccountAuthCommand(sub!, rest, deps) ?? 1;
|
|
292
|
+
}
|
|
293
|
+
console.error(ACCOUNT_USAGE);
|
|
294
|
+
return 1;
|
|
295
|
+
} catch (err) {
|
|
296
|
+
console.error(`account: ${err instanceof Error ? err.message : String(err)}`);
|
|
297
|
+
return 1;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects whether this process was started by a coding agent rather than typed
|
|
3
|
+
* by a person.
|
|
4
|
+
*
|
|
5
|
+
* Agent harnesses run `ocx` on the user's behalf and answer prompts from their
|
|
6
|
+
* own logic, which means a consent question would be decided by the agent
|
|
7
|
+
* instead of the account owner. Prompts that act on the user's identity check
|
|
8
|
+
* this and defer instead: they stay silent so the question reaches the human on
|
|
9
|
+
* a later hand-typed run.
|
|
10
|
+
*
|
|
11
|
+
* Detection is env-var based and deliberately conservative — a false positive
|
|
12
|
+
* only postpones a prompt, while a false negative would let an agent answer for
|
|
13
|
+
* the user.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Env vars set by agent harnesses and CI runners inside the shell they spawn.
|
|
18
|
+
*
|
|
19
|
+
* The list errs wide on purpose. A harness that is missed here is a harness
|
|
20
|
+
* whose model answers a consent question with the user's GitHub identity, which
|
|
21
|
+
* is the failure this module exists to prevent; a harness matched by mistake
|
|
22
|
+
* only postpones a prompt to the user's next hand-typed run.
|
|
23
|
+
*/
|
|
24
|
+
const AGENT_ENV_VARS = [
|
|
25
|
+
// Claude Code
|
|
26
|
+
"CLAUDECODE",
|
|
27
|
+
"CLAUDE_CODE_ENTRYPOINT",
|
|
28
|
+
"CLAUDE_CODE_SSE_PORT",
|
|
29
|
+
// Codex CLI / App / SDK. `CODEX_HOME` is deliberately NOT here: users export it
|
|
30
|
+
// from their own shell profile, so matching it would suppress the prompt for a
|
|
31
|
+
// person who is sitting right there.
|
|
32
|
+
"CODEX_THREAD_ID",
|
|
33
|
+
"CODEX_SHELL",
|
|
34
|
+
"CODEX_CI",
|
|
35
|
+
"CODEX_SANDBOX",
|
|
36
|
+
"CODEX_SANDBOX_NETWORK_DISABLED",
|
|
37
|
+
// Cursor
|
|
38
|
+
"CURSOR_TRACE_ID",
|
|
39
|
+
"CURSOR_SESSION_TOKEN",
|
|
40
|
+
"CURSOR_AGENT",
|
|
41
|
+
// Other coding agents
|
|
42
|
+
"AIDER_CHAT",
|
|
43
|
+
"OPENCODE_BIN_PATH",
|
|
44
|
+
"GEMINI_CLI",
|
|
45
|
+
// Generic runners and hosted environments that are never a person at a keyboard
|
|
46
|
+
"REPL_ID",
|
|
47
|
+
"CI",
|
|
48
|
+
"GITHUB_ACTIONS",
|
|
49
|
+
"GITLAB_CI",
|
|
50
|
+
"BUILDKITE",
|
|
51
|
+
"JENKINS_URL",
|
|
52
|
+
"TEAMCITY_VERSION",
|
|
53
|
+
"CODESPACES",
|
|
54
|
+
] as const;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* True when an agent or automated runner is driving this process. Reads the
|
|
58
|
+
* environment on every call so tests and long-lived processes see current state.
|
|
59
|
+
*/
|
|
60
|
+
export function isAgentDriven(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
61
|
+
return AGENT_ENV_VARS.some(name => (env[name] ?? "").trim() !== "");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The env-var names that mark this process as agent-driven. Empty for a real
|
|
66
|
+
* hand-typed run. Callers that refuse an action use it to name the reason.
|
|
67
|
+
*/
|
|
68
|
+
export function agentDrivenMarkers(env: NodeJS.ProcessEnv = process.env): string[] {
|
|
69
|
+
return AGENT_ENV_VARS.filter(name => (env[name] ?? "").trim() !== "");
|
|
70
|
+
}
|