@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,185 @@
|
|
|
1
|
+
import type { OcxProviderConfig } from "../types";
|
|
2
|
+
import { CLAUDE_CODE_HEADERS, claudeCodeSessionId } from "../adapters/client-fingerprint";
|
|
3
|
+
import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
|
|
4
|
+
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
5
|
+
import { fetchWithResetRetry } from "../lib/upstream-retry";
|
|
6
|
+
import { getValidAccessToken } from "../oauth";
|
|
7
|
+
import { ANTHROPIC_OAUTH_BETA, CLAUDE_CODE_SYSTEM_INSTRUCTION } from "../oauth/anthropic";
|
|
8
|
+
import type { DescribeOutcome, VisionSettings } from "./describe";
|
|
9
|
+
|
|
10
|
+
const ANTHROPIC_VISION_MAX_TOKENS = 1024;
|
|
11
|
+
const ALLOWED_IMAGE_MIME = new Set(["image/png", "image/jpeg", "image/jpg", "image/webp", "image/gif"]);
|
|
12
|
+
const MAX_IMAGE_BYTES = 20 * 1024 * 1024;
|
|
13
|
+
const DESCRIBE_INSTRUCTION =
|
|
14
|
+
"You are a vision describer for a text-only model that cannot see the image. Describe the image " +
|
|
15
|
+
"thoroughly and factually so that model can fully reason about it: transcribe any visible text " +
|
|
16
|
+
"verbatim, and note UI/layout, colors, branding/logos, charts, and notable details. Focus on " +
|
|
17
|
+
"what's relevant to the user's request. Output only the description.";
|
|
18
|
+
|
|
19
|
+
type AnthropicImageBlock =
|
|
20
|
+
| { type: "image"; source: { type: "base64"; media_type: string; data: string } }
|
|
21
|
+
| { type: "image"; source: { type: "url"; url: string } };
|
|
22
|
+
|
|
23
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
24
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function buildImageBlock(imageUrl: string): { block?: AnthropicImageBlock; error?: string } {
|
|
28
|
+
if (imageUrl.startsWith("data:")) {
|
|
29
|
+
// Anthropic's base64 image source requires actual base64 bytes, so a non-base64 data URL
|
|
30
|
+
// (e.g. `data:image/png,raw`) is rejected here. This is intentionally stricter than the OpenAI
|
|
31
|
+
// vision executor, which forwards the raw data URL to `image_url` (review F3, documented delta).
|
|
32
|
+
const match = /^data:([^;,]+?)(;base64)?,(.*)$/s.exec(imageUrl);
|
|
33
|
+
if (!match || !match[2]) return { error: "malformed data URL" };
|
|
34
|
+
const mime = match[1].toLowerCase();
|
|
35
|
+
if (!ALLOWED_IMAGE_MIME.has(mime)) return { error: `unsupported image type "${mime}"` };
|
|
36
|
+
const bytes = Math.floor((match[3].length * 3) / 4);
|
|
37
|
+
if (bytes > MAX_IMAGE_BYTES) return { error: `image too large (~${Math.round(bytes / 1024 / 1024)}MB)` };
|
|
38
|
+
return { block: { type: "image", source: { type: "base64", media_type: mime, data: match[3] } } };
|
|
39
|
+
}
|
|
40
|
+
if (imageUrl.startsWith("https://")) {
|
|
41
|
+
return { block: { type: "image", source: { type: "url", url: imageUrl } } };
|
|
42
|
+
}
|
|
43
|
+
return { error: "unsupported image URL scheme (expected data: or https:)" };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Fold Anthropic Messages text deltas into one description. Malformed frames are ignored. */
|
|
47
|
+
export async function parseAnthropicVisionSSE(res: Response): Promise<DescribeOutcome> {
|
|
48
|
+
if (!res.body) return { text: "", error: "anthropic vision sidecar returned no response body" };
|
|
49
|
+
|
|
50
|
+
let text = "";
|
|
51
|
+
let terminalError = "";
|
|
52
|
+
const decoder = new TextDecoder();
|
|
53
|
+
const reader = res.body.getReader();
|
|
54
|
+
let buffer = "";
|
|
55
|
+
|
|
56
|
+
const processFrame = (rawFrame: string): void => {
|
|
57
|
+
let dataLine = "";
|
|
58
|
+
for (const line of rawFrame.split("\n")) {
|
|
59
|
+
if (line.startsWith("data:")) dataLine += line.slice(line.startsWith("data: ") ? 6 : 5);
|
|
60
|
+
}
|
|
61
|
+
if (!dataLine || dataLine === "[DONE]") return;
|
|
62
|
+
let data: unknown;
|
|
63
|
+
try { data = JSON.parse(dataLine); } catch { return; }
|
|
64
|
+
if (!isRecord(data)) return;
|
|
65
|
+
|
|
66
|
+
if (data.type === "content_block_delta") {
|
|
67
|
+
const delta = isRecord(data.delta) ? data.delta : {};
|
|
68
|
+
if (delta.type === "text_delta" && typeof delta.text === "string") text += delta.text;
|
|
69
|
+
} else if (data.type === "error") {
|
|
70
|
+
const error = isRecord(data.error) ? data.error : {};
|
|
71
|
+
terminalError = typeof error.message === "string" ? error.message : "anthropic vision sidecar stream error";
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
for (;;) {
|
|
77
|
+
const { done, value } = await reader.read();
|
|
78
|
+
if (done) break;
|
|
79
|
+
buffer = (buffer + decoder.decode(value, { stream: true })).replace(/\r\n/g, "\n");
|
|
80
|
+
let separator: number;
|
|
81
|
+
while ((separator = buffer.indexOf("\n\n")) !== -1) {
|
|
82
|
+
processFrame(buffer.slice(0, separator));
|
|
83
|
+
buffer = buffer.slice(separator + 2);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
buffer = (buffer + decoder.decode()).replace(/\r\n/g, "\n");
|
|
87
|
+
if (buffer.trim()) processFrame(buffer);
|
|
88
|
+
} catch {
|
|
89
|
+
// A mid-stream read/decode failure after partial text is NOT a usable description. Mark it
|
|
90
|
+
// terminal so the caller returns an error and never caches an incomplete result (review F1).
|
|
91
|
+
if (!terminalError) terminalError = "anthropic vision sidecar stream ended abnormally";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const trimmed = text.trim();
|
|
95
|
+
// A terminal error (an in-stream `error` frame OR an abnormal body failure) invalidates any partial
|
|
96
|
+
// text: return an error outcome so vision/index.ts never caches an incomplete description (review F1).
|
|
97
|
+
if (terminalError) return { text: "", error: terminalError };
|
|
98
|
+
if (!trimmed) return { text: "", error: "anthropic vision sidecar produced no description" };
|
|
99
|
+
return { text: trimmed };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Describe one image through a stored Anthropic OAuth credential. Never throws. */
|
|
103
|
+
export async function describeImageAnthropic(
|
|
104
|
+
imageUrl: string,
|
|
105
|
+
detail: string | undefined,
|
|
106
|
+
contextText: string,
|
|
107
|
+
providerName: string,
|
|
108
|
+
provider: OcxProviderConfig,
|
|
109
|
+
settings: VisionSettings,
|
|
110
|
+
abortSignal?: AbortSignal,
|
|
111
|
+
): Promise<DescribeOutcome> {
|
|
112
|
+
const image = buildImageBlock(imageUrl);
|
|
113
|
+
if (!image.block) return { text: "", error: image.error ?? "invalid image" };
|
|
114
|
+
|
|
115
|
+
let token: string;
|
|
116
|
+
try {
|
|
117
|
+
token = await getValidAccessToken(providerName);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
return { text: "", error: `anthropic vision sidecar auth failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const headers: Record<string, string> = {
|
|
123
|
+
"Content-Type": "application/json",
|
|
124
|
+
"anthropic-version": "2023-06-01",
|
|
125
|
+
"Accept": "text/event-stream",
|
|
126
|
+
"User-Agent": "@anthropic-ai/sdk/0.74.0",
|
|
127
|
+
"Authorization": `Bearer ${token}`,
|
|
128
|
+
"anthropic-beta": ANTHROPIC_OAUTH_BETA,
|
|
129
|
+
...CLAUDE_CODE_HEADERS,
|
|
130
|
+
"X-Claude-Code-Session-Id": claudeCodeSessionId(token),
|
|
131
|
+
"x-client-request-id": crypto.randomUUID(),
|
|
132
|
+
};
|
|
133
|
+
if (provider.headers) Object.assign(headers, provider.headers);
|
|
134
|
+
|
|
135
|
+
const content: unknown[] = [];
|
|
136
|
+
if (contextText) content.push({ type: "text", text: `The user's request about this image: ${contextText}` });
|
|
137
|
+
content.push(image.block);
|
|
138
|
+
const body = {
|
|
139
|
+
model: settings.model,
|
|
140
|
+
max_tokens: ANTHROPIC_VISION_MAX_TOKENS,
|
|
141
|
+
thinking: { type: "disabled" },
|
|
142
|
+
system: [
|
|
143
|
+
{ type: "text", text: CLAUDE_CODE_SYSTEM_INSTRUCTION },
|
|
144
|
+
{ type: "text", text: DESCRIBE_INSTRUCTION },
|
|
145
|
+
],
|
|
146
|
+
messages: [{ role: "user", content }],
|
|
147
|
+
stream: true,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// Anthropic image blocks have no detail field, but detail remains part of the cache identity.
|
|
151
|
+
void detail;
|
|
152
|
+
const base = provider.baseUrl.replace(/\/v1\/?$/, "");
|
|
153
|
+
const linkedSignal = signalWithTimeout(settings.timeoutMs, abortSignal);
|
|
154
|
+
const sidecarExit = sidecarEnter("vision");
|
|
155
|
+
const startedAt = Date.now();
|
|
156
|
+
try {
|
|
157
|
+
const res = await fetchWithResetRetry(
|
|
158
|
+
() => fetch(`${base}/v1/messages`, {
|
|
159
|
+
method: "POST",
|
|
160
|
+
headers,
|
|
161
|
+
body: JSON.stringify(body),
|
|
162
|
+
signal: linkedSignal.signal,
|
|
163
|
+
}),
|
|
164
|
+
{ abortSignal: linkedSignal.signal, label: "vision-sidecar-anthropic" },
|
|
165
|
+
);
|
|
166
|
+
if (!res.ok) {
|
|
167
|
+
const responseText = await res.text().catch(() => "");
|
|
168
|
+
console.warn(`[vision] anthropic sidecar HTTP ${res.status} (${Date.now() - startedAt}ms)`);
|
|
169
|
+
return { text: "", error: `anthropic vision sidecar HTTP ${res.status}: ${responseText.slice(0, 200)}` };
|
|
170
|
+
}
|
|
171
|
+
const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
|
|
172
|
+
try {
|
|
173
|
+
return await parseAnthropicVisionSSE(res);
|
|
174
|
+
} finally {
|
|
175
|
+
detachBodyGuard();
|
|
176
|
+
}
|
|
177
|
+
} catch (error) {
|
|
178
|
+
const kind = error instanceof Error && error.name === "TimeoutError" ? "timeout" : "connect_error";
|
|
179
|
+
console.warn(`[vision] anthropic sidecar ${kind} (${Date.now() - startedAt}ms)`);
|
|
180
|
+
return { text: "", error: error instanceof Error ? error.message : String(error) };
|
|
181
|
+
} finally {
|
|
182
|
+
sidecarExit();
|
|
183
|
+
linkedSignal.cleanup();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { OcxProviderConfig } from "../types";
|
|
2
|
+
import { FORWARD_HEADERS } from "../adapters/openai-responses";
|
|
3
|
+
import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
|
|
4
|
+
import { redactSecretString } from "../lib/redact";
|
|
5
|
+
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
6
|
+
import { fetchWithResetRetry } from "../lib/upstream-retry";
|
|
7
|
+
import { parseSidecarSSE } from "../web-search/parse";
|
|
8
|
+
import type { SidecarOutcomeRecorder } from "../web-search/executor";
|
|
9
|
+
|
|
10
|
+
export interface VisionSettings {
|
|
11
|
+
model: string;
|
|
12
|
+
timeoutMs: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** A description, or an `error` string when it couldn't run (caller injects a graceful marker). */
|
|
16
|
+
export type DescribeOutcome = { text: string; error?: string };
|
|
17
|
+
|
|
18
|
+
const ALLOWED_IMAGE_MIME = new Set(["image/png", "image/jpeg", "image/jpg", "image/webp", "image/gif"]);
|
|
19
|
+
/** ~20 MB — generous enough for screenshots; rejects pathological payloads before forwarding. */
|
|
20
|
+
const MAX_IMAGE_BYTES = 20 * 1024 * 1024;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Validate an image URL before forwarding. Data URLs are checked for an allowed media type and a sane
|
|
24
|
+
* decoded size (a malformed/huge/unsupported one would otherwise 400 at the backend or waste tokens).
|
|
25
|
+
* Remote https URLs are passed through — the ChatGPT backend fetches them, not this proxy (so there's
|
|
26
|
+
* no SSRF surface here). Returns an error string when the URL must be rejected, else null.
|
|
27
|
+
*/
|
|
28
|
+
function validateImageUrl(url: string): string | null {
|
|
29
|
+
if (url.startsWith("data:")) {
|
|
30
|
+
const m = /^data:([^;,]+?)(;base64)?,(.*)$/s.exec(url);
|
|
31
|
+
if (!m) return "malformed data URL";
|
|
32
|
+
const mime = m[1].toLowerCase();
|
|
33
|
+
if (!ALLOWED_IMAGE_MIME.has(mime)) return `unsupported image type "${mime}"`;
|
|
34
|
+
if (m[2]) {
|
|
35
|
+
const bytes = Math.floor((m[3].length * 3) / 4);
|
|
36
|
+
if (bytes > MAX_IMAGE_BYTES) return `image too large (~${Math.round(bytes / 1024 / 1024)}MB)`;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
if (url.startsWith("https://")) return null;
|
|
41
|
+
return "unsupported image URL scheme (expected data: or https:)";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Describe ONE image via a gpt vision model through the ChatGPT forward backend — the path that has
|
|
46
|
+
* native image input. Reuses selected forwarded OAuth headers. The user's own request text is
|
|
47
|
+
* passed as context so the description is focused. Never throws — returns `{error}` on failure.
|
|
48
|
+
*/
|
|
49
|
+
export async function describeImage(
|
|
50
|
+
imageUrl: string,
|
|
51
|
+
detail: string | undefined,
|
|
52
|
+
contextText: string,
|
|
53
|
+
forwardProvider: OcxProviderConfig,
|
|
54
|
+
selectedForwardHeaders: Headers,
|
|
55
|
+
settings: VisionSettings,
|
|
56
|
+
abortSignal?: AbortSignal,
|
|
57
|
+
recordOutcome?: SidecarOutcomeRecorder,
|
|
58
|
+
): Promise<DescribeOutcome> {
|
|
59
|
+
const invalid = validateImageUrl(imageUrl);
|
|
60
|
+
if (invalid) return { text: "", error: invalid };
|
|
61
|
+
|
|
62
|
+
const headers: Record<string, string> = { "Content-Type": "application/json" };
|
|
63
|
+
if (forwardProvider.headers) Object.assign(headers, forwardProvider.headers);
|
|
64
|
+
for (const h of FORWARD_HEADERS) {
|
|
65
|
+
const v = selectedForwardHeaders.get(h);
|
|
66
|
+
if (v) headers[h] = v;
|
|
67
|
+
}
|
|
68
|
+
const content: unknown[] = [];
|
|
69
|
+
if (contextText) content.push({ type: "input_text", text: `The user's request about this image: ${contextText}` });
|
|
70
|
+
content.push({ type: "input_image", image_url: imageUrl, detail: detail ?? "high" });
|
|
71
|
+
|
|
72
|
+
const body = {
|
|
73
|
+
model: settings.model,
|
|
74
|
+
instructions:
|
|
75
|
+
"You are a vision describer for a text-only model that cannot see the image. Describe the image " +
|
|
76
|
+
"thoroughly and factually so that model can fully reason about it: transcribe any visible text " +
|
|
77
|
+
"verbatim, and note UI/layout, colors, branding/logos, charts, and notable details. Focus on " +
|
|
78
|
+
"what's relevant to the user's request. Output only the description.",
|
|
79
|
+
input: [{ type: "message", role: "user", content }],
|
|
80
|
+
reasoning: { effort: "low" },
|
|
81
|
+
// The ChatGPT (codex) backend rejects `max_output_tokens` ("Unsupported parameter"); the
|
|
82
|
+
// description is clamped downstream (DESC_MAX_CHARS) instead.
|
|
83
|
+
store: false,
|
|
84
|
+
stream: true,
|
|
85
|
+
};
|
|
86
|
+
const linkedSignal = signalWithTimeout(settings.timeoutMs, abortSignal);
|
|
87
|
+
const sidecarExit = sidecarEnter("vision");
|
|
88
|
+
const t0 = Date.now();
|
|
89
|
+
try {
|
|
90
|
+
const res = await fetchWithResetRetry(
|
|
91
|
+
() => fetch(`${forwardProvider.baseUrl}/responses`, {
|
|
92
|
+
method: "POST",
|
|
93
|
+
headers,
|
|
94
|
+
body: JSON.stringify(body),
|
|
95
|
+
signal: linkedSignal.signal,
|
|
96
|
+
}),
|
|
97
|
+
{ abortSignal: linkedSignal.signal, label: "vision-sidecar" },
|
|
98
|
+
);
|
|
99
|
+
recordOutcome?.(res.status);
|
|
100
|
+
if (!res.ok) {
|
|
101
|
+
const t = await res.text().catch(() => "");
|
|
102
|
+
console.warn(`[vision] sidecar HTTP ${res.status} (${Date.now() - t0}ms)`);
|
|
103
|
+
return { text: "", error: `vision sidecar HTTP ${res.status}: ${redactSecretString(t.slice(0, 200))}` };
|
|
104
|
+
}
|
|
105
|
+
const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
|
|
106
|
+
let parsed;
|
|
107
|
+
try {
|
|
108
|
+
parsed = await parseSidecarSSE(res);
|
|
109
|
+
} finally {
|
|
110
|
+
detachBodyGuard();
|
|
111
|
+
}
|
|
112
|
+
// The backend can return HTTP 200 then stream a `response.failed`/`error` event with no text;
|
|
113
|
+
// surface that as a describe error instead of an empty (silently-blank) description.
|
|
114
|
+
if (!parsed.text.trim() && parsed.error) return { text: "", error: parsed.error };
|
|
115
|
+
return { text: parsed.text };
|
|
116
|
+
} catch (e) {
|
|
117
|
+
recordOutcome?.(e instanceof Error && e.name === "TimeoutError" ? "timeout" : "connect_error");
|
|
118
|
+
const kind = e instanceof Error && e.name === "TimeoutError" ? "timeout" : "connect_error";
|
|
119
|
+
console.warn(`[vision] sidecar ${kind} (${Date.now() - t0}ms)`);
|
|
120
|
+
return { text: "", error: e instanceof Error ? e.message : String(e) };
|
|
121
|
+
} finally {
|
|
122
|
+
sidecarExit();
|
|
123
|
+
linkedSignal.cleanup();
|
|
124
|
+
}
|
|
125
|
+
}
|