@iislee/opencodex 2.11.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/LICENSE +21 -0
- package/README.md +225 -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 +451 -0
- package/bin/package-main.mjs +9 -0
- package/gui/dist/assets/index-DTpMHS4F.js +67 -0
- package/gui/dist/assets/index-ZNVDE3C7.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/antigravity.svg +1 -0
- package/gui/dist/provider-icons/claude-color.svg +1 -0
- package/gui/dist/provider-icons/claude.svg +1 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -0
- package/gui/dist/provider-icons/copilot.svg +1 -0
- package/gui/dist/provider-icons/cursor-color.svg +2 -0
- package/gui/dist/provider-icons/cursor.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/gemini.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-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/kiro.svg +14 -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 +1 -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 +102 -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.ts +1003 -0
- package/src/adapters/azure.ts +36 -0
- package/src/adapters/base.ts +72 -0
- package/src/adapters/client-fingerprint.ts +59 -0
- package/src/adapters/cursor/arg-codec.ts +38 -0
- package/src/adapters/cursor/arg-normalize.ts +104 -0
- package/src/adapters/cursor/cursor-errors.ts +165 -0
- package/src/adapters/cursor/discovery.ts +276 -0
- package/src/adapters/cursor/effort-map.ts +127 -0
- package/src/adapters/cursor/exec-policy.ts +88 -0
- package/src/adapters/cursor/framing.ts +211 -0
- package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
- package/src/adapters/cursor/kv-store.ts +52 -0
- package/src/adapters/cursor/live-models.ts +153 -0
- package/src/adapters/cursor/live-smoke-gate.ts +41 -0
- package/src/adapters/cursor/live-transport.ts +1214 -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 +55 -0
- package/src/adapters/cursor/native-exec-desktop.ts +184 -0
- package/src/adapters/cursor/native-exec-fs.ts +329 -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 +548 -0
- package/src/adapters/cursor/native-exec-tools.ts +118 -0
- package/src/adapters/cursor/native-exec.ts +576 -0
- package/src/adapters/cursor/protobuf-events.ts +563 -0
- package/src/adapters/cursor/protobuf-request.ts +714 -0
- package/src/adapters/cursor/request-builder.ts +255 -0
- package/src/adapters/cursor/thread-continuity.ts +67 -0
- package/src/adapters/cursor/tool-definitions.ts +505 -0
- package/src/adapters/cursor/transport-retry.ts +132 -0
- package/src/adapters/cursor/transport.ts +57 -0
- package/src/adapters/cursor/types.ts +52 -0
- package/src/adapters/cursor.ts +196 -0
- package/src/adapters/google-antigravity-replay.ts +303 -0
- package/src/adapters/google-antigravity-wire.ts +108 -0
- package/src/adapters/google-errors.ts +85 -0
- package/src/adapters/google-http.ts +100 -0
- package/src/adapters/google-tool-schema.ts +173 -0
- package/src/adapters/google-truncation.ts +13 -0
- package/src/adapters/google-wire-compiler.ts +232 -0
- package/src/adapters/google.ts +758 -0
- package/src/adapters/identity.ts +44 -0
- package/src/adapters/image.ts +23 -0
- package/src/adapters/kiro-constants.ts +16 -0
- package/src/adapters/kiro-errors.ts +197 -0
- package/src/adapters/kiro-events.ts +179 -0
- package/src/adapters/kiro-images.ts +129 -0
- package/src/adapters/kiro-retry.ts +312 -0
- package/src/adapters/kiro-thinking.ts +96 -0
- package/src/adapters/kiro-tool-fallback.ts +36 -0
- package/src/adapters/kiro-tools.ts +215 -0
- package/src/adapters/kiro-truncation.ts +33 -0
- package/src/adapters/kiro-wire.ts +129 -0
- package/src/adapters/kiro.ts +1898 -0
- package/src/adapters/mimo-free.ts +263 -0
- package/src/adapters/openai-chat.ts +1005 -0
- package/src/adapters/openai-responses.ts +1137 -0
- package/src/adapters/run-turn-queue.ts +114 -0
- package/src/adapters/tool-catalog-nudge.ts +71 -0
- package/src/adapters/upstream-http-error.ts +48 -0
- package/src/bridge.ts +1619 -0
- package/src/chat/inbound.ts +295 -0
- package/src/chat/outbound.ts +765 -0
- package/src/claude/agents-inject.ts +243 -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 +189 -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 +381 -0
- package/src/claude/desktop-health.ts +26 -0
- package/src/claude/desktop-profile.ts +263 -0
- package/src/claude/gateway-cache.ts +70 -0
- package/src/claude/inbound-debug.ts +163 -0
- package/src/claude/inbound.ts +509 -0
- package/src/claude/model-info.ts +151 -0
- package/src/claude/outbound.ts +872 -0
- package/src/cli/access.ts +108 -0
- package/src/cli/account-api.ts +268 -0
- package/src/cli/account-auth.ts +223 -0
- package/src/cli/account-extended.ts +350 -0
- package/src/cli/account.ts +275 -0
- package/src/cli/agent-driven.ts +70 -0
- package/src/cli/agent.ts +184 -0
- package/src/cli/catalog-prewarm.ts +27 -0
- package/src/cli/claude-desktop.ts +188 -0
- package/src/cli/claude.ts +286 -0
- package/src/cli/codex-shim-autorestore.ts +45 -0
- package/src/cli/combo.ts +119 -0
- package/src/cli/config-command.ts +145 -0
- package/src/cli/debug.ts +228 -0
- package/src/cli/doctor.ts +930 -0
- package/src/cli/export-command.ts +187 -0
- package/src/cli/help.ts +354 -0
- package/src/cli/index.ts +1113 -0
- package/src/cli/init.ts +224 -0
- package/src/cli/integrations.ts +142 -0
- package/src/cli/interactive-confirm.ts +133 -0
- package/src/cli/internal-dispatch.ts +20 -0
- package/src/cli/models-runtime.ts +212 -0
- package/src/cli/models.ts +336 -0
- package/src/cli/observe.ts +117 -0
- package/src/cli/opencode.ts +586 -0
- package/src/cli/pi.ts +188 -0
- package/src/cli/provider-runtime.ts +162 -0
- package/src/cli/provider.ts +463 -0
- package/src/cli/runtime-api.ts +325 -0
- package/src/cli/star-prompt.ts +155 -0
- package/src/cli/status-oauth.ts +78 -0
- package/src/cli/status.ts +321 -0
- package/src/cli/sync-cloud.ts +283 -0
- package/src/cli/system-command.ts +112 -0
- package/src/cli/tray-proxy.ts +52 -0
- package/src/cli/v2.ts +173 -0
- package/src/cli.ts +10 -0
- package/src/clients/config-export.ts +377 -0
- package/src/clients/effective-status.ts +385 -0
- package/src/clients/probes/agy.ts +55 -0
- package/src/clients/probes/cc-switch.ts +110 -0
- package/src/clients/probes/claude.ts +90 -0
- package/src/clients/probes/codex.ts +125 -0
- package/src/clients/probes/grok.ts +29 -0
- package/src/clients/probes/opencode.ts +109 -0
- package/src/clients/probes/paseo.ts +55 -0
- package/src/clients/probes/pi.ts +55 -0
- package/src/cloud/onedrive-auth.ts +666 -0
- package/src/cloud/onedrive-graph.ts +108 -0
- package/src/cloud/settings.ts +75 -0
- package/src/cloud/sync.ts +212 -0
- package/src/cloud/types.ts +56 -0
- package/src/cloud/vault.ts +89 -0
- package/src/codex/account-id.ts +34 -0
- package/src/codex/account-label.ts +34 -0
- package/src/codex/account-lifecycle.ts +55 -0
- package/src/codex/account-namespace-match.ts +63 -0
- package/src/codex/account-namespaces.ts +149 -0
- package/src/codex/account-pause.ts +20 -0
- package/src/codex/account-runtime-state.ts +31 -0
- package/src/codex/account-store.ts +517 -0
- package/src/codex/account-usability.ts +20 -0
- package/src/codex/app-server-processes.ts +756 -0
- package/src/codex/auth-api.ts +1540 -0
- package/src/codex/auth-collision.ts +107 -0
- package/src/codex/auth-context.ts +352 -0
- package/src/codex/autostart-health.ts +149 -0
- package/src/codex/catalog/aggregation.ts +378 -0
- package/src/codex/catalog/bundled.ts +251 -0
- package/src/codex/catalog/effort.ts +355 -0
- package/src/codex/catalog/metadata.ts +180 -0
- package/src/codex/catalog/parsing.ts +456 -0
- package/src/codex/catalog/provider-fetch.ts +902 -0
- package/src/codex/catalog/sync.ts +620 -0
- package/src/codex/catalog.ts +12 -0
- package/src/codex/data/upstream-models.json +830 -0
- package/src/codex/exec-invocation.ts +22 -0
- package/src/codex/features.ts +969 -0
- package/src/codex/history-migration-guardian.ts +102 -0
- package/src/codex/history-provider.ts +776 -0
- package/src/codex/home.ts +206 -0
- package/src/codex/inject.ts +799 -0
- package/src/codex/injected-marker.ts +72 -0
- package/src/codex/journal.ts +163 -0
- package/src/codex/main-account-cache.ts +32 -0
- package/src/codex/main-account.ts +40 -0
- package/src/codex/model-cache.ts +227 -0
- package/src/codex/paths.ts +65 -0
- package/src/codex/plugins-doctor.ts +242 -0
- package/src/codex/pool-rotation.ts +225 -0
- package/src/codex/project-config-warnings.ts +411 -0
- package/src/codex/quota.ts +411 -0
- package/src/codex/refresh.ts +53 -0
- package/src/codex/routing.ts +1477 -0
- package/src/codex/runtime.ts +538 -0
- package/src/codex/shim.ts +1189 -0
- package/src/codex/subagent-defaults.ts +550 -0
- package/src/codex/subagent-model-fallback.ts +469 -0
- package/src/codex/sync.ts +130 -0
- package/src/codex/warmup.ts +192 -0
- package/src/codex/websocket-registry.ts +100 -0
- package/src/combos/failover.ts +140 -0
- package/src/combos/index.ts +41 -0
- package/src/combos/request.ts +62 -0
- package/src/combos/resolve.ts +232 -0
- package/src/combos/types.ts +326 -0
- package/src/config.ts +2356 -0
- package/src/generated/jawcode-model-metadata.ts +104 -0
- package/src/github/star-state.ts +203 -0
- package/src/grok/inject.ts +545 -0
- package/src/grok/status.ts +121 -0
- package/src/grok/sync.ts +103 -0
- package/src/grok/usage-hook/report.mjs +348 -0
- package/src/grok/usage-hook.ts +278 -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 +829 -0
- package/src/images/plan.ts +133 -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/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 +173 -0
- package/src/lib/app-owned-memory.ts +265 -0
- package/src/lib/bounded-body.ts +202 -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 +71 -0
- package/src/lib/bun-stream-caps.ts +126 -0
- package/src/lib/config-ownership.ts +360 -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 +316 -0
- package/src/lib/errors.ts +364 -0
- package/src/lib/eventstream-decoder.ts +253 -0
- package/src/lib/gcp-adc.ts +341 -0
- package/src/lib/injection-debug-log.ts +58 -0
- package/src/lib/open-url.ts +25 -0
- package/src/lib/pinned-http.ts +151 -0
- package/src/lib/privacy.ts +20 -0
- package/src/lib/process-control.ts +165 -0
- package/src/lib/provider-outbound.ts +170 -0
- package/src/lib/provider-url.ts +14 -0
- package/src/lib/proxy-env.ts +18 -0
- package/src/lib/redact.ts +105 -0
- package/src/lib/retry-after.ts +55 -0
- package/src/lib/service-secrets.ts +25 -0
- package/src/lib/shadow-call.ts +30 -0
- package/src/lib/sidecar-tracker.ts +52 -0
- package/src/lib/sse-decoder.ts +323 -0
- package/src/lib/state-store-registrations.ts +109 -0
- package/src/lib/state-store-sweeper.ts +184 -0
- package/src/lib/test-home-guard.ts +90 -0
- package/src/lib/token-estimate.ts +69 -0
- package/src/lib/translator-budget.ts +356 -0
- package/src/lib/upstream-retry.ts +239 -0
- package/src/lib/win-exec.ts +115 -0
- package/src/lib/win-paths.ts +68 -0
- package/src/lib/windows-elevation.ts +705 -0
- package/src/lib/windows-secret-acl.ts +514 -0
- package/src/lib/winsw.ts +375 -0
- package/src/oauth/anthropic-routing.ts +594 -0
- package/src/oauth/anthropic.ts +177 -0
- package/src/oauth/callback-server.ts +294 -0
- package/src/oauth/chatgpt.ts +150 -0
- package/src/oauth/cursor.ts +211 -0
- package/src/oauth/github-copilot.ts +428 -0
- package/src/oauth/google-antigravity.ts +230 -0
- package/src/oauth/health.ts +399 -0
- package/src/oauth/index.ts +1174 -0
- package/src/oauth/key-providers.ts +108 -0
- package/src/oauth/kimi.ts +213 -0
- package/src/oauth/kiro-credentials.ts +726 -0
- package/src/oauth/kiro.ts +577 -0
- package/src/oauth/local-token-detect.ts +121 -0
- package/src/oauth/log.ts +48 -0
- package/src/oauth/login-cli.ts +163 -0
- package/src/oauth/pkce.ts +15 -0
- package/src/oauth/store.ts +630 -0
- package/src/oauth/token-guardian.ts +303 -0
- package/src/oauth/types.ts +62 -0
- package/src/oauth/xai.ts +241 -0
- package/src/pi/extensions.ts +72 -0
- package/src/pi/home.ts +42 -0
- package/src/pi/index.ts +40 -0
- package/src/pi/models.ts +278 -0
- package/src/pi/packages.ts +219 -0
- package/src/pi/settings.ts +365 -0
- package/src/pi/status.ts +68 -0
- package/src/pi/sync.ts +75 -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 +205 -0
- package/src/providers/api-keys.ts +140 -0
- package/src/providers/base-url-choices.ts +64 -0
- package/src/providers/context-cap.ts +65 -0
- package/src/providers/derive.ts +339 -0
- package/src/providers/free-directory.ts +184 -0
- package/src/providers/github-copilot-transport.ts +56 -0
- package/src/providers/key-failover.ts +203 -0
- package/src/providers/kiro-models.ts +67 -0
- package/src/providers/label.ts +19 -0
- package/src/providers/model-discovery.ts +356 -0
- package/src/providers/openai-sidecar.ts +175 -0
- package/src/providers/openai-tier-startup.ts +27 -0
- package/src/providers/openai-tiers.ts +301 -0
- package/src/providers/openai-virtual-models.ts +82 -0
- package/src/providers/openrouter-routing.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +150 -0
- package/src/providers/quota.ts +1260 -0
- package/src/providers/registry.ts +1600 -0
- package/src/providers/slug-codec.ts +67 -0
- package/src/providers/xai-transport.ts +141 -0
- package/src/reasoning-effort.ts +135 -0
- package/src/responses/compaction.ts +117 -0
- package/src/responses/parser.ts +656 -0
- package/src/responses/reasoning-envelope.ts +52 -0
- package/src/responses/schema.ts +159 -0
- package/src/responses/spill-store.ts +394 -0
- package/src/responses/state.ts +895 -0
- package/src/responses/tool-groups.ts +19 -0
- package/src/router.ts +425 -0
- package/src/server/adapter-resolve.ts +80 -0
- package/src/server/auth-cors.ts +530 -0
- package/src/server/chat-completions.ts +368 -0
- package/src/server/claude-messages.ts +914 -0
- package/src/server/effort-policy.ts +172 -0
- package/src/server/gui-static.ts +123 -0
- package/src/server/image-retry.ts +42 -0
- package/src/server/images.ts +476 -0
- package/src/server/index.ts +1126 -0
- package/src/server/lifecycle.ts +227 -0
- package/src/server/live.ts +598 -0
- package/src/server/management/agent-settings-routes.ts +1169 -0
- package/src/server/management/api-access.ts +141 -0
- package/src/server/management/api-key-usage.ts +167 -0
- package/src/server/management/body.ts +35 -0
- package/src/server/management/clients-routes.ts +63 -0
- package/src/server/management/cloud-sync-routes.ts +266 -0
- package/src/server/management/combo-routes.ts +220 -0
- package/src/server/management/config-routes.ts +422 -0
- package/src/server/management/context.ts +31 -0
- package/src/server/management/logs-usage-routes.ts +707 -0
- package/src/server/management/model-routes.ts +525 -0
- package/src/server/management/oauth-account-routes.ts +563 -0
- package/src/server/management/provider-routes.ts +556 -0
- package/src/server/management/shared.ts +277 -0
- package/src/server/management/sidebar-routes.ts +90 -0
- package/src/server/management/system-restart.ts +179 -0
- package/src/server/management/system-routes.ts +117 -0
- package/src/server/management/usage-summary-cache.ts +86 -0
- package/src/server/management-api.ts +215 -0
- package/src/server/management-auth.ts +267 -0
- package/src/server/memory-watchdog.ts +156 -0
- package/src/server/port-reclaim.ts +307 -0
- package/src/server/ports.ts +116 -0
- package/src/server/proxy-liveness.ts +201 -0
- package/src/server/relay-eager.ts +313 -0
- package/src/server/relay.ts +1049 -0
- package/src/server/request-decompress.ts +132 -0
- package/src/server/request-log-conversation.ts +168 -0
- package/src/server/request-log.ts +1046 -0
- package/src/server/responses/collaboration.ts +354 -0
- package/src/server/responses/compact.ts +384 -0
- package/src/server/responses/core.ts +2758 -0
- package/src/server/responses/encrypted-payload.ts +308 -0
- package/src/server/responses/fetch-helpers.ts +157 -0
- package/src/server/responses/passthrough-error.ts +78 -0
- package/src/server/responses/terminal-guard.ts +230 -0
- package/src/server/responses/upstream-error.ts +48 -0
- package/src/server/responses-image-gen-repair.ts +132 -0
- package/src/server/responses-item-id-repair.ts +224 -0
- package/src/server/responses.ts +9 -0
- package/src/server/search.ts +136 -0
- package/src/server/sse-payload-rewrite.ts +175 -0
- package/src/server/startup-action-control.ts +308 -0
- package/src/server/startup-health-cache.ts +113 -0
- package/src/server/system-env.ts +413 -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 +471 -0
- package/src/service.ts +2554 -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 +290 -0
- package/src/tray/windows.ts +730 -0
- package/src/types.ts +1237 -0
- package/src/update/badge.ts +72 -0
- package/src/update/index.ts +407 -0
- package/src/update/job.ts +1520 -0
- package/src/update/notify.ts +257 -0
- package/src/update/npm-invocation.d.mts +23 -0
- package/src/update/npm-invocation.mjs +94 -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 +0 -0
- package/src/usage/debug.ts +97 -0
- package/src/usage/expected-prices.ts +164 -0
- package/src/usage/log.ts +658 -0
- package/src/usage/summary.ts +585 -0
- package/src/usage/totals.ts +14 -0
- package/src/vision/anthropic-describe.ts +185 -0
- package/src/vision/describe.ts +125 -0
- package/src/vision/index.ts +467 -0
- package/src/web-search/anthropic-executor.ts +189 -0
- package/src/web-search/executor.ts +105 -0
- package/src/web-search/format-result.ts +89 -0
- package/src/web-search/index.ts +196 -0
- package/src/web-search/loop.ts +664 -0
- package/src/web-search/parse.ts +220 -0
- package/src/web-search/progress-stream.ts +342 -0
- package/src/web-search/synthetic-tool.ts +47 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, realpathSync } from "node:fs";
|
|
4
|
+
import { delimiter, dirname, join, resolve } from "node:path";
|
|
5
|
+
import { atomicWriteFile, expandUserPath, getConfigDir, websocketsEnabled } from "../../config";
|
|
6
|
+
import { CODEX_CONFIG_PATH, CODEX_MODELS_CACHE_PATH, DEFAULT_CATALOG_PATH, readRootTomlString, resolveCodexConfigPath } from "../paths";
|
|
7
|
+
import { clearModelCache, DEFAULT_MODEL_CACHE_TTL_MS, getFreshCached, getStaleCached, isModelsFetchCoolingDown, markModelsFetchFailure, setCached } from "../model-cache";
|
|
8
|
+
import { buildModelsRequest, resolveModelsAuthToken } from "../../oauth";
|
|
9
|
+
import type { OcxConfig, OcxProviderConfig } from "../../types";
|
|
10
|
+
import { modelInList } from "../../types";
|
|
11
|
+
import { CODEX_REASONING_LEVELS, codexEffortRank, configuredReasoningEfforts, modelRecordValue, sanitizeCodexReasoningEfforts } from "../../reasoning-effort";
|
|
12
|
+
import { getJawcodeModelMetadata, getJawcodeModelMetadataCaseInsensitive, listJawcodeModelMetadata, resolveJawcodeProvider } from "../../generated/jawcode-model-metadata";
|
|
13
|
+
import { enrichProviderFromRegistry, shouldCaseFoldMetadataModelId } from "../../providers/derive";
|
|
14
|
+
import { getProviderRegistryEntry } from "../../providers/registry";
|
|
15
|
+
import { applyProviderContextCap, providerContextCap } from "../../providers/context-cap";
|
|
16
|
+
import { routedSlug, slugEquals, slugsEquivalent } from "../../providers/slug-codec";
|
|
17
|
+
import { CODEX_GPT5_IDENTITY_LINE } from "../../adapters/identity";
|
|
18
|
+
import { filterCursorConfiguredModelsByLiveDiscovery } from "../../adapters/cursor/discovery";
|
|
19
|
+
import { fetchCursorUsableModels } from "../../adapters/cursor/live-models";
|
|
20
|
+
import { isCanonicalOpenAiForwardProvider, OPENAI_API_PROVIDER_ID, OPENAI_CODEX_PROVIDER_ID } from "../../providers/openai-tiers";
|
|
21
|
+
import {
|
|
22
|
+
COMBO_NAMESPACE,
|
|
23
|
+
comboModelId,
|
|
24
|
+
getCombo,
|
|
25
|
+
listComboIds,
|
|
26
|
+
targetKey,
|
|
27
|
+
} from "../../combos";
|
|
28
|
+
import type { NormalizedComboConfig } from "../../combos/types";
|
|
29
|
+
import { providerDestinationResolvedError } from "../../lib/destination-policy";
|
|
30
|
+
import { redactSecretString, redactUserPath } from "../../lib/redact";
|
|
31
|
+
import upstreamModelsSnapshot from "../data/upstream-models.json";
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
import { readCatalog, readCodexCatalogPath } from "./parsing";
|
|
35
|
+
import type { CatalogModel, RawEntry } from "./parsing";
|
|
36
|
+
import { UPSTREAM_NATIVE_ENTRIES } from "./metadata";
|
|
37
|
+
import { loadBundledCodexCatalog } from "./bundled";
|
|
38
|
+
import type { BundledCatalogDeps } from "./bundled";
|
|
39
|
+
import { deriveEntry } from "./sync";
|
|
40
|
+
import {
|
|
41
|
+
formatClampLogLines,
|
|
42
|
+
formatRuntimeLogLine,
|
|
43
|
+
displayCodexRuntimePath,
|
|
44
|
+
persistEffortClamp,
|
|
45
|
+
resolveAndPersistCodexRuntime,
|
|
46
|
+
type EffortClampDiagnostic,
|
|
47
|
+
} from "../runtime";
|
|
48
|
+
|
|
49
|
+
export function nativeEffortClamp(slug: string, effort: string | undefined): string | null {
|
|
50
|
+
if (!effort || (effort !== "max" && effort !== "ultra")) return null;
|
|
51
|
+
if (slug.includes("/")) return null; // routed models map efforts in their adapters
|
|
52
|
+
const entry = UPSTREAM_NATIVE_ENTRIES.get(slug);
|
|
53
|
+
const levels = Array.isArray(entry?.supported_reasoning_levels)
|
|
54
|
+
? entry.supported_reasoning_levels as Array<{ effort?: string }>
|
|
55
|
+
: [];
|
|
56
|
+
if (levels.length === 0) {
|
|
57
|
+
// Not snapshot-covered. gpt-5.6 natives have a REAL max rung (ensureGpt56ReasoningLevels
|
|
58
|
+
// restores it even off-snapshot) -> never clamp. Every other bare native (gpt-5.5/5.4/
|
|
59
|
+
// 5.4-mini/5.3-codex-spark and future old-ladder slugs) really stops at xhigh — the
|
|
60
|
+
// ChatGPT backend error names exactly none..xhigh — so clamp the synthetic top tier.
|
|
61
|
+
return isGpt56NativeSlug(slug) ? null : "xhigh";
|
|
62
|
+
}
|
|
63
|
+
const supported = levels.flatMap(l => typeof l.effort === "string" ? [l.effort] : []);
|
|
64
|
+
if (supported.includes(effort)) return null;
|
|
65
|
+
const rank = ["minimal", "low", "medium", "high", "xhigh", "max"];
|
|
66
|
+
const highest = supported
|
|
67
|
+
.filter(e => rank.includes(e))
|
|
68
|
+
.sort((a, b) => rank.indexOf(a) - rank.indexOf(b))
|
|
69
|
+
.at(-1);
|
|
70
|
+
return highest ?? null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function shouldApplyNativeEffortClamp(
|
|
74
|
+
providerName: string,
|
|
75
|
+
provider: OcxProviderConfig,
|
|
76
|
+
requestedModelId: string,
|
|
77
|
+
): boolean {
|
|
78
|
+
return !requestedModelId.includes("/")
|
|
79
|
+
&& providerName === OPENAI_CODEX_PROVIDER_ID
|
|
80
|
+
&& isCanonicalOpenAiForwardProvider(provider);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function catalogModelEfforts(slugs: readonly string[]): Map<string, string[]> {
|
|
84
|
+
const out = new Map<string, string[]>();
|
|
85
|
+
if (slugs.length === 0) return out;
|
|
86
|
+
const catalog = readCatalog(readCodexCatalogPath());
|
|
87
|
+
if (!catalog) return out;
|
|
88
|
+
for (const entry of catalog.models ?? []) {
|
|
89
|
+
if (typeof entry.slug !== "string") continue;
|
|
90
|
+
// Tolerate raw legacy config slugs (`provider/vendor/model`) against the
|
|
91
|
+
// Codex-facing encoded catalog slug (`provider/vendor-model`).
|
|
92
|
+
const callerSlug = slugs.find(s => slugsEquivalent(s, entry.slug as string));
|
|
93
|
+
if (callerSlug === undefined) continue;
|
|
94
|
+
const levels = Array.isArray(entry.supported_reasoning_levels)
|
|
95
|
+
? entry.supported_reasoning_levels as Array<{ effort?: string }>
|
|
96
|
+
: [];
|
|
97
|
+
const efforts = levels.flatMap(l => typeof l.effort === "string" ? [l.effort] : []);
|
|
98
|
+
if (efforts.length > 0) out.set(callerSlug, efforts);
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function catalogEntryEfforts(entry: RawEntry): string[] {
|
|
104
|
+
const levels = Array.isArray(entry.supported_reasoning_levels)
|
|
105
|
+
? entry.supported_reasoning_levels as Array<{ effort?: string }>
|
|
106
|
+
: [];
|
|
107
|
+
return levels.flatMap(level => typeof level.effort === "string" ? [level.effort] : []);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const ROUTED_REASONING_LEVELS = [...CODEX_REASONING_LEVELS];
|
|
111
|
+
|
|
112
|
+
export function applyCatalogModelMetadata(entry: RawEntry, model?: CatalogModel): void {
|
|
113
|
+
if (!model) return;
|
|
114
|
+
// This marker survives strict catalog normalization and lets sync distinguish a stale
|
|
115
|
+
// bare combo alias from a genuine native model row.
|
|
116
|
+
if (model.provider === COMBO_NAMESPACE) entry.owned_by = model.owned_by ?? COMBO_NAMESPACE;
|
|
117
|
+
// displayName is DISPLAY-ONLY: it relabels the picker row but never touches the routing
|
|
118
|
+
// slug, alias, or provider. deriveEntry already stamped the slug as display_name; a
|
|
119
|
+
// configured displayName overrides just the label. The `/` separator is rejected at every
|
|
120
|
+
// input boundary (CLI `ocx models add`, management API), so the catalog trusts its source.
|
|
121
|
+
// Combos carry no displayName, and natives never reach here (no CatalogModel), so genuine
|
|
122
|
+
// upstream marketing names and combo alias labels are preserved untouched.
|
|
123
|
+
const displayName = typeof model.displayName === "string" ? model.displayName.trim() : "";
|
|
124
|
+
if (displayName) entry.display_name = displayName;
|
|
125
|
+
if (typeof model.contextWindow === "number" && model.contextWindow > 0) {
|
|
126
|
+
entry.context_window = model.contextWindow;
|
|
127
|
+
entry.max_context_window = model.contextWindow;
|
|
128
|
+
entry.auto_compact_token_limit = Math.min(
|
|
129
|
+
Math.floor(model.contextWindow * 0.9),
|
|
130
|
+
model.maxInputTokens ?? Number.POSITIVE_INFINITY,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
if (Array.isArray(model.inputModalities) && model.inputModalities.length > 0) {
|
|
134
|
+
entry.input_modalities = model.inputModalities;
|
|
135
|
+
}
|
|
136
|
+
if (typeof model.supportsVerbosity === "boolean") {
|
|
137
|
+
entry.support_verbosity = model.supportsVerbosity;
|
|
138
|
+
}
|
|
139
|
+
if (typeof model.supportsReasoningSummaries === "boolean") {
|
|
140
|
+
entry.supports_reasoning_summaries = model.supportsReasoningSummaries;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function applyReasoningLevels(
|
|
145
|
+
entry: RawEntry,
|
|
146
|
+
effortsOverride?: string[],
|
|
147
|
+
defaultOverride?: string,
|
|
148
|
+
preserveExact = false,
|
|
149
|
+
): void {
|
|
150
|
+
let efforts = sanitizeCodexReasoningEfforts(effortsOverride) ?? ROUTED_REASONING_LEVELS.map(l => l.effort);
|
|
151
|
+
// Mock top tiers (user decision 260709): every reasoning-capable model advertises `max`
|
|
152
|
+
// even when the provider ladder stops lower — subagent spawns pass `max` DIRECTLY
|
|
153
|
+
// (no ultra->max client conversion) and codex-rs validates it by catalog membership,
|
|
154
|
+
// so a missing max rung hard-fails spawn_agent effort overrides. The wire stays honest:
|
|
155
|
+
// routed adapters clamp via clampToSupportedCodexEffort and natives via
|
|
156
|
+
// nativeEffortClamp (max -> the model's real top rung).
|
|
157
|
+
if (!preserveExact && efforts.length > 0) {
|
|
158
|
+
const additions: string[] = [];
|
|
159
|
+
if (!efforts.includes("max")) additions.push("max");
|
|
160
|
+
if (!efforts.includes("ultra")) additions.push("ultra");
|
|
161
|
+
if (additions.length > 0) efforts = sanitizeCodexReasoningEfforts([...efforts, ...additions]) ?? efforts;
|
|
162
|
+
}
|
|
163
|
+
const byEffort = new Map(
|
|
164
|
+
(Array.isArray(entry.supported_reasoning_levels) ? entry.supported_reasoning_levels : [])
|
|
165
|
+
.map((l: { effort?: string }) => [l.effort, l]),
|
|
166
|
+
);
|
|
167
|
+
entry.supported_reasoning_levels = efforts.map(effort => {
|
|
168
|
+
const native = byEffort.get(effort);
|
|
169
|
+
if (native) return native;
|
|
170
|
+
// Description lookup uses the FULL ladder so an opt-in effort outside the routed default
|
|
171
|
+
// (e.g. "ultra") still renders its canonical description.
|
|
172
|
+
return CODEX_REASONING_LEVELS.find(l => l.effort === effort) ?? { effort, description: `${effort} reasoning` };
|
|
173
|
+
});
|
|
174
|
+
if (efforts.length === 0) {
|
|
175
|
+
delete entry.default_reasoning_level;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
entry.default_reasoning_level = defaultOverride && efforts.includes(defaultOverride)
|
|
179
|
+
? defaultOverride
|
|
180
|
+
: efforts.includes("medium") ? "medium" : efforts.includes("high") ? "high" : efforts[0];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function isGpt56NativeSlug(slug: string): boolean {
|
|
184
|
+
return !slug.includes("/") && slug.startsWith("gpt-5.6-");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function ensureGpt56ReasoningLevels(entry: RawEntry): void {
|
|
188
|
+
const levels = Array.isArray(entry.supported_reasoning_levels)
|
|
189
|
+
? entry.supported_reasoning_levels as Array<{ effort?: string }>
|
|
190
|
+
: [];
|
|
191
|
+
const out = [...levels];
|
|
192
|
+
// max is a real native rung on the 5.6 family — always restored; ultra always advertised.
|
|
193
|
+
for (const effort of ["max", "ultra"]) {
|
|
194
|
+
if (out.some(level => level.effort === effort)) continue;
|
|
195
|
+
out.push(CODEX_REASONING_LEVELS.find(level => level.effort === effort)
|
|
196
|
+
?? { effort, description: `${effort} reasoning` });
|
|
197
|
+
}
|
|
198
|
+
entry.supported_reasoning_levels = out;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function ensureUltraReasoningLevel(entry: RawEntry): void {
|
|
202
|
+
const levels = Array.isArray(entry.supported_reasoning_levels)
|
|
203
|
+
? entry.supported_reasoning_levels as Array<{ effort?: string }>
|
|
204
|
+
: [];
|
|
205
|
+
if (levels.length === 0) return;
|
|
206
|
+
const wanted = ["max", "ultra"];
|
|
207
|
+
for (const effort of wanted) {
|
|
208
|
+
if (levels.some(level => level.effort === effort)) continue;
|
|
209
|
+
levels.push(
|
|
210
|
+
CODEX_REASONING_LEVELS.find(level => level.effort === effort)
|
|
211
|
+
?? { effort, description: `${effort} reasoning` },
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
entry.supported_reasoning_levels = levels;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function codexSupportedReasoningEfforts(deps: BundledCatalogDeps = {}): Set<string> | null {
|
|
218
|
+
const bundled = loadBundledCodexCatalog(deps);
|
|
219
|
+
if (!bundled) return null;
|
|
220
|
+
const efforts = new Set<string>();
|
|
221
|
+
for (const model of bundled.models ?? []) {
|
|
222
|
+
if (typeof model.slug !== "string" || model.slug.includes("/")) continue;
|
|
223
|
+
const levels = Array.isArray(model.supported_reasoning_levels) ? model.supported_reasoning_levels : [];
|
|
224
|
+
for (const level of levels) {
|
|
225
|
+
const effort = (level as { effort?: unknown })?.effort;
|
|
226
|
+
if (typeof effort === "string") efforts.add(effort);
|
|
227
|
+
}
|
|
228
|
+
if (typeof model.default_reasoning_level === "string") efforts.add(model.default_reasoning_level);
|
|
229
|
+
}
|
|
230
|
+
return efforts.size > 0 ? efforts : null;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function clampedDefaultEffort(original: string, surviving: readonly string[]): string {
|
|
234
|
+
if (surviving.length === 0) return "medium";
|
|
235
|
+
const ranked = [...surviving]
|
|
236
|
+
.map(effort => ({ effort, rank: codexEffortRank(effort) }))
|
|
237
|
+
.sort((a, b) => a.rank - b.rank);
|
|
238
|
+
const originalRank = codexEffortRank(original);
|
|
239
|
+
const atOrBelow = ranked.filter(item => item.rank >= 0 && item.rank <= originalRank);
|
|
240
|
+
return (atOrBelow.at(-1) ?? ranked[0]!).effort;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export function clampEntryToCodexSupportedEfforts(entry: RawEntry, supported: Set<string> | null): void {
|
|
244
|
+
if (!supported) return;
|
|
245
|
+
const levels = Array.isArray(entry.supported_reasoning_levels)
|
|
246
|
+
? entry.supported_reasoning_levels as Array<{ effort?: string }>
|
|
247
|
+
: null;
|
|
248
|
+
if (levels && levels.length > 0) {
|
|
249
|
+
const kept = levels.filter(level => typeof level?.effort === "string" && supported.has(level.effort));
|
|
250
|
+
entry.supported_reasoning_levels = kept.length > 0
|
|
251
|
+
? kept
|
|
252
|
+
: CODEX_REASONING_LEVELS
|
|
253
|
+
.filter(level => level.effort === "low" || level.effort === "medium" || level.effort === "high")
|
|
254
|
+
.map(level => ({ ...level }));
|
|
255
|
+
}
|
|
256
|
+
const currentDefault = entry.default_reasoning_level;
|
|
257
|
+
if (typeof currentDefault === "string" && !supported.has(currentDefault)) {
|
|
258
|
+
const surviving = (Array.isArray(entry.supported_reasoning_levels) ? entry.supported_reasoning_levels : [])
|
|
259
|
+
.flatMap(level => typeof (level as { effort?: string })?.effort === "string"
|
|
260
|
+
? [(level as { effort: string }).effort]
|
|
261
|
+
: []);
|
|
262
|
+
entry.default_reasoning_level = clampedDefaultEffort(currentDefault, surviving);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function clampCatalogModelsToCodexSupport(models: RawEntry[], deps: BundledCatalogDeps = {}): RawEntry[] {
|
|
267
|
+
const supported = codexSupportedReasoningEfforts(deps);
|
|
268
|
+
if (!supported) {
|
|
269
|
+
if (!deps.commandCandidates) persistEffortClamp(null, { configDir: deps.configDir });
|
|
270
|
+
return models;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const removed = new Set<string>();
|
|
274
|
+
const affected: string[] = [];
|
|
275
|
+
for (const entry of models) {
|
|
276
|
+
const before = new Set(
|
|
277
|
+
(Array.isArray(entry.supported_reasoning_levels) ? entry.supported_reasoning_levels : [])
|
|
278
|
+
.flatMap(level => typeof (level as { effort?: string })?.effort === "string"
|
|
279
|
+
? [(level as { effort: string }).effort]
|
|
280
|
+
: []),
|
|
281
|
+
);
|
|
282
|
+
const beforeDefault = typeof entry.default_reasoning_level === "string"
|
|
283
|
+
? entry.default_reasoning_level
|
|
284
|
+
: null;
|
|
285
|
+
clampEntryToCodexSupportedEfforts(entry, supported);
|
|
286
|
+
const after = new Set(
|
|
287
|
+
(Array.isArray(entry.supported_reasoning_levels) ? entry.supported_reasoning_levels : [])
|
|
288
|
+
.flatMap(level => typeof (level as { effort?: string })?.effort === "string"
|
|
289
|
+
? [(level as { effort: string }).effort]
|
|
290
|
+
: []),
|
|
291
|
+
);
|
|
292
|
+
const afterDefault = typeof entry.default_reasoning_level === "string"
|
|
293
|
+
? entry.default_reasoning_level
|
|
294
|
+
: null;
|
|
295
|
+
const lost = [...before].filter(effort => !after.has(effort));
|
|
296
|
+
const defaultClamped = Boolean(beforeDefault && beforeDefault !== afterDefault);
|
|
297
|
+
if (lost.length > 0 || defaultClamped) {
|
|
298
|
+
for (const effort of lost) removed.add(effort);
|
|
299
|
+
if (defaultClamped && beforeDefault) removed.add(beforeDefault);
|
|
300
|
+
if (typeof entry.slug === "string") affected.push(entry.slug);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
let runtimePath = "codex";
|
|
305
|
+
let runtimeVersion: string | null = null;
|
|
306
|
+
if (!deps.commandCandidates) {
|
|
307
|
+
try {
|
|
308
|
+
const resolved = resolveAndPersistCodexRuntime({
|
|
309
|
+
execFileSync: deps.execFileSync,
|
|
310
|
+
configDir: deps.configDir,
|
|
311
|
+
env: deps.env,
|
|
312
|
+
platform: deps.platform,
|
|
313
|
+
existsSync: deps.existsSync,
|
|
314
|
+
readFileSync: deps.readFileSync,
|
|
315
|
+
now: deps.now,
|
|
316
|
+
discoverAlternatives: deps.discoverAlternatives,
|
|
317
|
+
});
|
|
318
|
+
runtimePath = resolved.runtime.command;
|
|
319
|
+
runtimeVersion = resolved.runtime.version;
|
|
320
|
+
process.stderr.write(`${formatRuntimeLogLine(resolved.runtime)}\n`);
|
|
321
|
+
if (resolved.persistError) {
|
|
322
|
+
console.warn(`[opencodex] Codex runtime selection could not be persisted; a later sync may pick a different binary.`);
|
|
323
|
+
}
|
|
324
|
+
if (
|
|
325
|
+
resolved.replacedConfigured
|
|
326
|
+
&& resolved.replacedConfigured.from.command !== resolved.runtime.command
|
|
327
|
+
) {
|
|
328
|
+
console.warn(`[opencodex] Preferred Codex runtime is unavailable.`);
|
|
329
|
+
console.warn(
|
|
330
|
+
`[opencodex] Falling back from ${displayCodexRuntimePath(resolved.replacedConfigured.from.command)} to ${displayCodexRuntimePath(runtimePath)}.`,
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
} catch (error) {
|
|
334
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
335
|
+
const redacted = redactUserPath(redactSecretString(message)).slice(0, 200);
|
|
336
|
+
console.warn(`[opencodex] Codex runtime resolve failed during catalog clamp: ${redacted}`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (removed.size > 0) {
|
|
341
|
+
const diagnostic: EffortClampDiagnostic = {
|
|
342
|
+
runtimePath,
|
|
343
|
+
runtimeVersion,
|
|
344
|
+
removedEfforts: [...removed].sort(),
|
|
345
|
+
affectedModels: affected,
|
|
346
|
+
};
|
|
347
|
+
for (const line of formatClampLogLines(diagnostic)) console.warn(line);
|
|
348
|
+
if (!deps.commandCandidates) persistEffortClamp(diagnostic, { configDir: deps.configDir });
|
|
349
|
+
deps.onEffortClamp?.(diagnostic);
|
|
350
|
+
} else if (!deps.commandCandidates) {
|
|
351
|
+
persistEffortClamp(null, { configDir: deps.configDir });
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return models;
|
|
355
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, realpathSync } from "node:fs";
|
|
4
|
+
import { delimiter, dirname, join, resolve } from "node:path";
|
|
5
|
+
import { atomicWriteFile, expandUserPath, getConfigDir, websocketsEnabled } from "../../config";
|
|
6
|
+
import { CODEX_CONFIG_PATH, CODEX_MODELS_CACHE_PATH, DEFAULT_CATALOG_PATH, readRootTomlString, resolveCodexConfigPath } from "../paths";
|
|
7
|
+
import { clearModelCache, DEFAULT_MODEL_CACHE_TTL_MS, getFreshCached, getStaleCached, isModelsFetchCoolingDown, markModelsFetchFailure, setCached } from "../model-cache";
|
|
8
|
+
import { buildModelsRequest, resolveModelsAuthToken } from "../../oauth";
|
|
9
|
+
import type { OcxConfig, OcxProviderConfig } from "../../types";
|
|
10
|
+
import { modelInList } from "../../types";
|
|
11
|
+
import { CODEX_REASONING_LEVELS, codexEffortRank, configuredReasoningEfforts, modelRecordValue, sanitizeCodexReasoningEfforts } from "../../reasoning-effort";
|
|
12
|
+
import { getJawcodeModelMetadata, getJawcodeModelMetadataCaseInsensitive, listJawcodeModelMetadata, resolveJawcodeProvider } from "../../generated/jawcode-model-metadata";
|
|
13
|
+
import { enrichProviderFromRegistry, shouldCaseFoldMetadataModelId } from "../../providers/derive";
|
|
14
|
+
import { getProviderRegistryEntry } from "../../providers/registry";
|
|
15
|
+
import { applyProviderContextCap, providerContextCap } from "../../providers/context-cap";
|
|
16
|
+
import { routedSlug, slugEquals, slugsEquivalent } from "../../providers/slug-codec";
|
|
17
|
+
import { CODEX_GPT5_IDENTITY_LINE } from "../../adapters/identity";
|
|
18
|
+
import { filterCursorConfiguredModelsByLiveDiscovery } from "../../adapters/cursor/discovery";
|
|
19
|
+
import { fetchCursorUsableModels } from "../../adapters/cursor/live-models";
|
|
20
|
+
import { isCanonicalOpenAiForwardProvider, OPENAI_API_PROVIDER_ID, OPENAI_CODEX_PROVIDER_ID } from "../../providers/openai-tiers";
|
|
21
|
+
import {
|
|
22
|
+
COMBO_NAMESPACE,
|
|
23
|
+
comboModelId,
|
|
24
|
+
getCombo,
|
|
25
|
+
listComboIds,
|
|
26
|
+
targetKey,
|
|
27
|
+
} from "../../combos";
|
|
28
|
+
import type { NormalizedComboConfig } from "../../combos/types";
|
|
29
|
+
import { providerDestinationResolvedError } from "../../lib/destination-policy";
|
|
30
|
+
import { redactSecretString } from "../../lib/redact";
|
|
31
|
+
import upstreamModelsSnapshot from "../data/upstream-models.json";
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
import { filterSupportedNativeSlugs } from "./parsing";
|
|
35
|
+
import type { RawEntry } from "./parsing";
|
|
36
|
+
import { readCurrentCatalogOrCache, unique } from "./bundled";
|
|
37
|
+
|
|
38
|
+
export const NATIVE_OPENAI_MODELS = [
|
|
39
|
+
"gpt-5.5", "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex-spark",
|
|
40
|
+
"gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna",
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
export const DOCUMENTED_NATIVE_OPENAI_ADDITIONS = [
|
|
44
|
+
"gpt-5.3-codex-spark",
|
|
45
|
+
"gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna",
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
export const SUPPORTED_NATIVE_OPENAI_SLUGS = new Set(NATIVE_OPENAI_MODELS);
|
|
49
|
+
|
|
50
|
+
export function isUnsupportedOpenAiNativeSlug(slug: string): boolean {
|
|
51
|
+
if (slug.includes("/")) return false;
|
|
52
|
+
if (SUPPORTED_NATIVE_OPENAI_SLUGS.has(slug)) return false;
|
|
53
|
+
return /^(?:gpt|codex)-/.test(slug);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const NATIVE_GPT56_CONTEXT_WINDOW = 372_000;
|
|
57
|
+
|
|
58
|
+
export const NATIVE_OPENAI_CONTEXT_OVERRIDES: Record<string, { contextWindow?: number; maxContextWindow?: number }> = {
|
|
59
|
+
"gpt-5.5": { contextWindow: 272_000, maxContextWindow: 272_000 },
|
|
60
|
+
"gpt-5.4": { contextWindow: 1_000_000, maxContextWindow: 1_000_000 },
|
|
61
|
+
"gpt-5.3-codex-spark": { contextWindow: 100_000, maxContextWindow: 100_000 },
|
|
62
|
+
"gpt-5.6-sol": { contextWindow: NATIVE_GPT56_CONTEXT_WINDOW, maxContextWindow: NATIVE_GPT56_CONTEXT_WINDOW },
|
|
63
|
+
"gpt-5.6-terra": { contextWindow: NATIVE_GPT56_CONTEXT_WINDOW, maxContextWindow: NATIVE_GPT56_CONTEXT_WINDOW },
|
|
64
|
+
"gpt-5.6-luna": { contextWindow: NATIVE_GPT56_CONTEXT_WINDOW, maxContextWindow: NATIVE_GPT56_CONTEXT_WINDOW },
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export function nativeOpenAiContextWindow(slug: string): number | undefined {
|
|
68
|
+
return NATIVE_OPENAI_CONTEXT_OVERRIDES[slug]?.contextWindow
|
|
69
|
+
?? (typeof UPSTREAM_NATIVE_ENTRIES.get(slug)?.context_window === "number"
|
|
70
|
+
? UPSTREAM_NATIVE_ENTRIES.get(slug)!.context_window as number
|
|
71
|
+
: undefined);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function nativeInputModalities(slug: string): string[] {
|
|
75
|
+
const upstream = UPSTREAM_NATIVE_ENTRIES.get(slug);
|
|
76
|
+
if (Array.isArray(upstream?.input_modalities) && upstream!.input_modalities!.length > 0) {
|
|
77
|
+
return [...upstream!.input_modalities as string[]];
|
|
78
|
+
}
|
|
79
|
+
// gpt-5.3-codex-spark is not in the upstream snapshot; all supported natives are
|
|
80
|
+
// text+image capable, so default to the family baseline rather than text-only.
|
|
81
|
+
return ["text", "image"];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function nativeReasoningEfforts(slug: string): string[] {
|
|
85
|
+
const upstream = UPSTREAM_NATIVE_ENTRIES.get(slug);
|
|
86
|
+
const levels = Array.isArray(upstream?.supported_reasoning_levels)
|
|
87
|
+
? upstream!.supported_reasoning_levels as Array<{ effort?: string }>
|
|
88
|
+
: [];
|
|
89
|
+
if (levels.length > 0) {
|
|
90
|
+
// Preserve the exact pinned per-model ladder. In particular, GPT-5.6 Sol and Terra
|
|
91
|
+
// include ultra while Luna intentionally ends at max.
|
|
92
|
+
return levels.flatMap(l => typeof l.effort === "string" ? [l.effort] : []);
|
|
93
|
+
}
|
|
94
|
+
// gpt-5.3-codex-spark is not in upstream snapshot — use the standard old-ladder default.
|
|
95
|
+
return ["low", "medium", "high", "xhigh"];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Upstream-pinned default for a native slug, when present and non-empty. */
|
|
99
|
+
export function nativeDefaultReasoningEffort(slug: string): string | undefined {
|
|
100
|
+
const level = UPSTREAM_NATIVE_ENTRIES.get(slug)?.default_reasoning_level;
|
|
101
|
+
return typeof level === "string" && level.length > 0 ? level : undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function nativeParallelToolCalls(slug: string): boolean {
|
|
105
|
+
return UPSTREAM_NATIVE_ENTRIES.get(slug)?.supports_parallel_tool_calls === true
|
|
106
|
+
|| false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function hasComboTargets(config: { combos?: Record<string, { targets?: unknown[] }> }): boolean {
|
|
110
|
+
const combos = config.combos;
|
|
111
|
+
if (!combos) return false;
|
|
112
|
+
return Object.values(combos).some(c => Array.isArray(c?.targets) && c!.targets!.length > 0);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function disabledNativeSlugs(config: Pick<OcxConfig, "disabledModels">): Set<string> {
|
|
116
|
+
return new Set((config.disabledModels ?? []).filter(id => !id.includes("/")));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function visibleNativeSlugs(config: Pick<OcxConfig, "disabledModels">): string[] {
|
|
120
|
+
const disabled = disabledNativeSlugs(config);
|
|
121
|
+
return nativeOpenAiSlugs().filter(slug => !disabled.has(slug));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Native slugs exposed to Claude Desktop show/export/apply (opt-out via claudeCode.desktopNativeModels). */
|
|
125
|
+
export function desktopVisibleNativeSlugs(config: Pick<OcxConfig, "claudeCode" | "disabledModels">): string[] {
|
|
126
|
+
if (config.claudeCode?.desktopNativeModels === false) return [];
|
|
127
|
+
return visibleNativeSlugs(config);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function nativeModelRows(config: Pick<OcxConfig, "disabledModels">): Array<{ slug: string; disabled: boolean; contextWindow?: number }> {
|
|
131
|
+
const disabled = disabledNativeSlugs(config);
|
|
132
|
+
return NATIVE_OPENAI_MODELS.map(slug => {
|
|
133
|
+
const contextWindow = nativeOpenAiContextWindow(slug);
|
|
134
|
+
return { slug, disabled: disabled.has(slug), ...(contextWindow !== undefined ? { contextWindow } : {}) };
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function applyNativeVisibility(entries: RawEntry[], disabledNative: Set<string>): RawEntry[] {
|
|
139
|
+
for (const entry of entries) {
|
|
140
|
+
const slug = typeof entry.slug === "string" ? entry.slug : "";
|
|
141
|
+
if (!slug || slug.includes("/") || !SUPPORTED_NATIVE_OPENAI_SLUGS.has(slug)) continue;
|
|
142
|
+
entry.visibility = disabledNative.has(slug) ? "hide" : "list";
|
|
143
|
+
}
|
|
144
|
+
return entries;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export const UPSTREAM_NATIVE_ENTRIES: Map<string, RawEntry> = new Map(
|
|
148
|
+
((upstreamModelsSnapshot as unknown as { models?: RawEntry[] }).models ?? [])
|
|
149
|
+
.filter(m => typeof m.slug === "string"
|
|
150
|
+
&& SUPPORTED_NATIVE_OPENAI_SLUGS.has(m.slug as string)
|
|
151
|
+
&& (m.slug as string).startsWith("gpt-5.6-"))
|
|
152
|
+
.map(m => [m.slug as string, m]),
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
export function upstreamNativeEntry(slug: string): RawEntry | null {
|
|
156
|
+
const entry = UPSTREAM_NATIVE_ENTRIES.get(slug);
|
|
157
|
+
if (!entry) return null;
|
|
158
|
+
const clone = JSON.parse(JSON.stringify(entry)) as RawEntry;
|
|
159
|
+
delete clone.minimal_client_version;
|
|
160
|
+
return clone;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function shouldUpgradeToUpstreamEntry(entry: RawEntry): boolean {
|
|
164
|
+
return typeof entry.slug === "string"
|
|
165
|
+
&& UPSTREAM_NATIVE_ENTRIES.has(entry.slug)
|
|
166
|
+
&& entry.display_name === entry.slug;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function nativeOpenAiSlugs(): string[] {
|
|
170
|
+
const live = listCatalogNativeSlugs();
|
|
171
|
+
return live.length > 0 ? unique([...live, ...DOCUMENTED_NATIVE_OPENAI_ADDITIONS]) : NATIVE_OPENAI_MODELS;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function listCatalogNativeSlugs(): string[] {
|
|
175
|
+
const cat = readCurrentCatalogOrCache();
|
|
176
|
+
const live = filterSupportedNativeSlugs(cat?.models ?? []);
|
|
177
|
+
// Ensure documented additions (e.g. gpt-5.3-codex-spark) appear even when the bundled catalog
|
|
178
|
+
// predates the slug — mirrors nativeOpenAiSlugs() which already merges them for /v1/models.
|
|
179
|
+
return unique([...live, ...DOCUMENTED_NATIVE_OPENAI_ADDITIONS]);
|
|
180
|
+
}
|