@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,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex-facing slug codec for routed models whose NATIVE ids contain "/".
|
|
3
|
+
*
|
|
4
|
+
* Codex's models-manager resolves per-model metadata (effort ladder, context window,
|
|
5
|
+
* capabilities — "tagging") with an exact one-slash rule: the namespaced-suffix lookup
|
|
6
|
+
* (codex-rs models-manager/src/manager.rs, `find_model_by_namespaced_suffix`) splits
|
|
7
|
+
* once on "/" and rejects the lookup when the remainder still contains "/". Providers
|
|
8
|
+
* whose native ids are themselves namespaced (zenmux `moonshotai/kimi-k3-free`,
|
|
9
|
+
* openrouter `anthropic/...`, nvidia `moonshotai/...`, together, fireworks, …) would
|
|
10
|
+
* otherwise produce two-slash Codex slugs that silently fall back to default metadata.
|
|
11
|
+
*
|
|
12
|
+
* Contract:
|
|
13
|
+
* - Codex-facing surfaces (catalog entries, picker lists, Codex-bound config picks)
|
|
14
|
+
* use `routedSlug(provider, id)` — inner slashes become "-".
|
|
15
|
+
* - Internal state (upstream requests, logs, usage, jawcode metadata, combo keys)
|
|
16
|
+
* keeps the native id. Decoding is an EXACT bijective lookup against the provider's
|
|
17
|
+
* known native ids — never a blind "-" → "/" replace — with three ordered rules:
|
|
18
|
+
* native exact match (back-compat with raw full-slash selectors) > unique alias
|
|
19
|
+
* match > pass-through unchanged (honest upstream error).
|
|
20
|
+
* - Config comparisons are tolerant via `slugEquals`/`slugsEquivalent` so legacy raw
|
|
21
|
+
* values keep working regardless of which form was stored.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** Separator standing in for "/" inside the model-id portion of a Codex-facing slug. */
|
|
25
|
+
export const SLUG_ALIAS_SEPARATOR = "-";
|
|
26
|
+
|
|
27
|
+
/** Native model id -> Codex-facing alias id. No-op for ids without "/". */
|
|
28
|
+
export function encodeRoutedModelId(id: string): string {
|
|
29
|
+
return id.includes("/") ? id.replaceAll("/", SLUG_ALIAS_SEPARATOR) : id;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Codex-facing routed slug: exactly one "/" — `<provider>/<encoded id>`. */
|
|
33
|
+
export function routedSlug(provider: string, id: string): string {
|
|
34
|
+
return `${provider}/${encodeRoutedModelId(id)}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Map a Codex-supplied model id back to the provider's native id.
|
|
39
|
+
* `knownIds` is the provider's known native ids (config ∪ registry ∪ live cache).
|
|
40
|
+
*/
|
|
41
|
+
export function decodeRoutedModelId(requested: string, knownIds: Iterable<string>): string {
|
|
42
|
+
let aliasMatch: string | undefined;
|
|
43
|
+
for (const id of knownIds) {
|
|
44
|
+
if (id === requested) return requested; // native exact (raw selector back-compat)
|
|
45
|
+
if (id.includes("/") && encodeRoutedModelId(id) === requested) {
|
|
46
|
+
// Ambiguous alias (e.g. both `a/b` and `a-b` exist): refuse to guess.
|
|
47
|
+
if (aliasMatch !== undefined && aliasMatch !== id) return requested;
|
|
48
|
+
aliasMatch = id;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return aliasMatch ?? requested;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Does a stored config slug name this routed model, in either raw or encoded form? */
|
|
55
|
+
export function slugEquals(stored: string, provider: string, id: string): boolean {
|
|
56
|
+
return stored === `${provider}/${id}` || stored === routedSlug(provider, id);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Equivalence between two routed slugs regardless of raw/encoded mix. */
|
|
60
|
+
export function slugsEquivalent(a: string, b: string): boolean {
|
|
61
|
+
if (a === b) return true;
|
|
62
|
+
const pa = a.indexOf("/");
|
|
63
|
+
const pb = b.indexOf("/");
|
|
64
|
+
if (pa <= 0 || pb <= 0) return false;
|
|
65
|
+
if (a.slice(0, pa) !== b.slice(0, pb)) return false;
|
|
66
|
+
return encodeRoutedModelId(a.slice(pa + 1)) === encodeRoutedModelId(b.slice(pb + 1));
|
|
67
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import type { OcxProviderConfig } from "../types";
|
|
3
|
+
import { resolveGithubCopilotTransport } from "./github-copilot-transport";
|
|
4
|
+
|
|
5
|
+
export const XAI_GROK_CLI_BASE_URL = "https://cli-chat-proxy.grok.com/v1";
|
|
6
|
+
|
|
7
|
+
export const XAI_GROK_COMPATIBILITY = {
|
|
8
|
+
version: "0.2.93",
|
|
9
|
+
userAgent: "opencodex-grok/0.2.93",
|
|
10
|
+
headers: {
|
|
11
|
+
clientIdentifier: "x-grok-client-identifier",
|
|
12
|
+
clientVersion: "x-grok-client-version",
|
|
13
|
+
tokenAuth: "x-xai-token-auth",
|
|
14
|
+
authenticateResponse: "x-authenticateresponse",
|
|
15
|
+
conversationId: "x-grok-conv-id",
|
|
16
|
+
requestId: "x-grok-req-id",
|
|
17
|
+
sessionId: "x-grok-session-id",
|
|
18
|
+
userAgent: "User-Agent",
|
|
19
|
+
},
|
|
20
|
+
} as const;
|
|
21
|
+
|
|
22
|
+
export const XAI_GROK_CLIENT_VERSION = XAI_GROK_COMPATIBILITY.version;
|
|
23
|
+
export const XAI_CONV_ID_HEADER = XAI_GROK_COMPATIBILITY.headers.conversationId;
|
|
24
|
+
|
|
25
|
+
export type OcxProviderTransport = OcxProviderConfig & {
|
|
26
|
+
/** Request executor used only at runtime; never persisted. */
|
|
27
|
+
fetch?: typeof globalThis.fetch;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const XAI_GROK_CLI_HEADERS: Readonly<Record<string, string>> = {
|
|
31
|
+
[XAI_GROK_COMPATIBILITY.headers.clientIdentifier]: "opencodex",
|
|
32
|
+
[XAI_GROK_COMPATIBILITY.headers.clientVersion]: XAI_GROK_CLIENT_VERSION,
|
|
33
|
+
[XAI_GROK_COMPATIBILITY.headers.tokenAuth]: "xai-grok-cli",
|
|
34
|
+
[XAI_GROK_COMPATIBILITY.headers.authenticateResponse]: "authenticate-response",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function hasHeaderCaseInsensitive(
|
|
38
|
+
headers: Record<string, string> | undefined,
|
|
39
|
+
name: string,
|
|
40
|
+
): boolean {
|
|
41
|
+
const target = name.toLowerCase();
|
|
42
|
+
return Object.keys(headers ?? {}).some(key => key.toLowerCase() === target);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function withoutUserOverridden(
|
|
46
|
+
defaults: Readonly<Record<string, string>>,
|
|
47
|
+
userHeaders: Record<string, string> | undefined,
|
|
48
|
+
): Record<string, string> {
|
|
49
|
+
return Object.fromEntries(
|
|
50
|
+
Object.entries(defaults).filter(([name]) => !hasHeaderCaseInsensitive(userHeaders, name)),
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function withGeneratedRequestId(
|
|
55
|
+
init: RequestInit | undefined,
|
|
56
|
+
configuredRequestId: string | undefined,
|
|
57
|
+
stableHeaders: Readonly<Record<string, string>>,
|
|
58
|
+
): RequestInit {
|
|
59
|
+
const headers = new Headers(init?.headers);
|
|
60
|
+
for (const [name, value] of Object.entries(stableHeaders)) {
|
|
61
|
+
if (!headers.has(name)) headers.set(name, value);
|
|
62
|
+
}
|
|
63
|
+
if (!headers.has(XAI_GROK_COMPATIBILITY.headers.requestId)) {
|
|
64
|
+
headers.set(
|
|
65
|
+
XAI_GROK_COMPATIBILITY.headers.requestId,
|
|
66
|
+
configuredRequestId ?? randomUUID(),
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return { ...init, headers };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function findHeaderCaseInsensitive(
|
|
73
|
+
headers: Record<string, string> | undefined,
|
|
74
|
+
name: string,
|
|
75
|
+
): string | undefined {
|
|
76
|
+
const target = name.toLowerCase();
|
|
77
|
+
return Object.entries(headers ?? {}).find(([key]) => key.toLowerCase() === target)?.[1];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function deriveXaiConvId(promptCacheKey: string): string {
|
|
81
|
+
return createHash("sha256").update(promptCacheKey).digest("hex").slice(0, 32);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Resolve xAI's runtime transport without mutating persisted config. Conversation/session
|
|
86
|
+
* affinity is stable for this resolved transport; request identity is generated per fetch.
|
|
87
|
+
* Agent, deployment, model-override, turn, mode, and user identity headers are intentionally
|
|
88
|
+
* omitted because opencodex has no truthful values for the official fields.
|
|
89
|
+
*/
|
|
90
|
+
export function resolveProviderTransport(
|
|
91
|
+
providerName: string,
|
|
92
|
+
provider: OcxProviderTransport,
|
|
93
|
+
promptCacheKey?: string,
|
|
94
|
+
apiBaseUrl?: string,
|
|
95
|
+
): OcxProviderTransport {
|
|
96
|
+
if (providerName === "github-copilot") {
|
|
97
|
+
return resolveGithubCopilotTransport(provider, apiBaseUrl);
|
|
98
|
+
}
|
|
99
|
+
if (providerName !== "xai") return provider;
|
|
100
|
+
|
|
101
|
+
const cacheKey = promptCacheKey?.trim();
|
|
102
|
+
const affinity = cacheKey ? deriveXaiConvId(cacheKey) : undefined;
|
|
103
|
+
const stableDefaults: Record<string, string> = {
|
|
104
|
+
[XAI_GROK_COMPATIBILITY.headers.userAgent]: XAI_GROK_COMPATIBILITY.userAgent,
|
|
105
|
+
...(affinity
|
|
106
|
+
? {
|
|
107
|
+
[XAI_GROK_COMPATIBILITY.headers.conversationId]: affinity,
|
|
108
|
+
[XAI_GROK_COMPATIBILITY.headers.sessionId]: affinity,
|
|
109
|
+
}
|
|
110
|
+
: {}),
|
|
111
|
+
...(provider.authMode === "oauth" ? XAI_GROK_CLI_HEADERS : {}),
|
|
112
|
+
};
|
|
113
|
+
const stableHeaders = {
|
|
114
|
+
...withoutUserOverridden(stableDefaults, provider.headers),
|
|
115
|
+
...(provider.headers ?? {}),
|
|
116
|
+
};
|
|
117
|
+
// Keep API-key provider metadata compatible with key-pool rotation; session/UA defaults
|
|
118
|
+
// remain transport-scoped and are applied by the wrapper immediately below.
|
|
119
|
+
const headers = provider.authMode === "oauth"
|
|
120
|
+
? stableHeaders
|
|
121
|
+
: {
|
|
122
|
+
...(affinity && !hasHeaderCaseInsensitive(provider.headers, XAI_GROK_COMPATIBILITY.headers.conversationId)
|
|
123
|
+
? { [XAI_GROK_COMPATIBILITY.headers.conversationId]: affinity }
|
|
124
|
+
: {}),
|
|
125
|
+
...(provider.headers ?? {}),
|
|
126
|
+
};
|
|
127
|
+
const configuredRequestId = findHeaderCaseInsensitive(
|
|
128
|
+
provider.headers,
|
|
129
|
+
XAI_GROK_COMPATIBILITY.headers.requestId,
|
|
130
|
+
);
|
|
131
|
+
const baseFetch = provider.fetch ?? globalThis.fetch;
|
|
132
|
+
const attemptFetch = ((input, init) =>
|
|
133
|
+
baseFetch(input, withGeneratedRequestId(init, configuredRequestId, stableHeaders))) as typeof globalThis.fetch;
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
...provider,
|
|
137
|
+
...(provider.authMode === "oauth" ? { baseUrl: XAI_GROK_CLI_BASE_URL } : {}),
|
|
138
|
+
headers,
|
|
139
|
+
fetch: attemptFetch,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { OcxProviderConfig } from "./types";
|
|
2
|
+
import { modelInList } from "./types";
|
|
3
|
+
|
|
4
|
+
// Descriptions mirror the upstream bundled models.json canonical wording (openai/codex PR #31684).
|
|
5
|
+
export const CODEX_REASONING_LEVELS: { effort: string; description: string }[] = [
|
|
6
|
+
{ effort: "low", description: "Fast responses with lighter reasoning" },
|
|
7
|
+
{ effort: "medium", description: "Balances speed and reasoning depth for everyday tasks" },
|
|
8
|
+
{ effort: "high", description: "Greater reasoning depth for complex problems" },
|
|
9
|
+
{ effort: "xhigh", description: "Extra high reasoning depth for complex problems" },
|
|
10
|
+
{ effort: "max", description: "Maximum reasoning depth for the hardest problems" },
|
|
11
|
+
{ effort: "ultra", description: "Maximum reasoning with automatic task delegation" },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const CODEX_REASONING_ORDER = CODEX_REASONING_LEVELS.map(l => l.effort);
|
|
15
|
+
const CODEX_REASONING_SET = new Set(CODEX_REASONING_ORDER);
|
|
16
|
+
|
|
17
|
+
/** True when `effort` is a member of the Codex reasoning ladder (low..ultra). */
|
|
18
|
+
export function isCodexReasoningEffort(effort: string): boolean {
|
|
19
|
+
return CODEX_REASONING_SET.has(effort);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Position of `effort` in the Codex ladder (low=0 .. ultra=5), or -1 when not a ladder member. */
|
|
23
|
+
export function codexEffortRank(effort: string): number {
|
|
24
|
+
return CODEX_REASONING_ORDER.indexOf(effort);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function modelRecordValue<T>(record: Record<string, T> | undefined, modelId: string): T | undefined {
|
|
28
|
+
if (!record) return undefined;
|
|
29
|
+
if (Object.prototype.hasOwnProperty.call(record, modelId)) return record[modelId];
|
|
30
|
+
const colon = modelId.indexOf(":");
|
|
31
|
+
if (colon > 0) {
|
|
32
|
+
const family = modelId.slice(0, colon);
|
|
33
|
+
if (Object.prototype.hasOwnProperty.call(record, family)) return record[family];
|
|
34
|
+
}
|
|
35
|
+
const folded = modelId.toLowerCase();
|
|
36
|
+
for (const [key, value] of Object.entries(record)) {
|
|
37
|
+
if (key.toLowerCase() === folded) return value;
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function sanitizeCodexReasoningEfforts(efforts: readonly string[] | undefined): string[] | undefined {
|
|
43
|
+
if (efforts === undefined) return undefined;
|
|
44
|
+
const seen = new Set<string>();
|
|
45
|
+
const out: string[] = [];
|
|
46
|
+
for (const effort of efforts) {
|
|
47
|
+
if (!CODEX_REASONING_SET.has(effort) || seen.has(effort)) continue;
|
|
48
|
+
seen.add(effort);
|
|
49
|
+
out.push(effort);
|
|
50
|
+
}
|
|
51
|
+
return out.sort((a, b) => CODEX_REASONING_ORDER.indexOf(a) - CODEX_REASONING_ORDER.indexOf(b));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Provider/model configured reasoning levels for the Codex catalog. `undefined` means “no override”,
|
|
56
|
+
* while an empty array means “intentionally expose no effort control for this model”.
|
|
57
|
+
*/
|
|
58
|
+
export function configuredReasoningEfforts(provider: OcxProviderConfig, modelId: string): string[] | undefined {
|
|
59
|
+
if (modelInList(provider.noReasoningModels, modelId)) return [];
|
|
60
|
+
const modelEfforts = modelRecordValue(provider.modelReasoningEfforts, modelId);
|
|
61
|
+
if (modelEfforts !== undefined) return healMappedTiers(provider, modelId, sanitizeCodexReasoningEfforts(modelEfforts) ?? []);
|
|
62
|
+
if (provider.reasoningEfforts !== undefined) return healMappedTiers(provider, modelId, sanitizeCodexReasoningEfforts(provider.reasoningEfforts) ?? []);
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Stale-ladder self-heal: a registry wire map is authoritative evidence of the upstream tiers
|
|
68
|
+
* it can emit. Merge Codex-native map values into an older persisted ladder so newly documented
|
|
69
|
+
* tiers appear without rewriting the user's config. Non-Codex values such as enabled/disabled
|
|
70
|
+
* and Kimi's none sentinel are ignored here; they remain request-only wire aliases.
|
|
71
|
+
*/
|
|
72
|
+
function healMappedTiers(provider: OcxProviderConfig, modelId: string, efforts: string[]): string[] {
|
|
73
|
+
if (efforts.length === 0) return efforts;
|
|
74
|
+
const wireMap = reasoningEffortMapFor(provider, modelId);
|
|
75
|
+
if (!wireMap) return efforts;
|
|
76
|
+
const mappedTiers = Object.values(wireMap).filter(isCodexReasoningEffort);
|
|
77
|
+
if (mappedTiers.length === 0) return efforts;
|
|
78
|
+
return sanitizeCodexReasoningEfforts([...efforts, ...mappedTiers]) ?? efforts;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function requestToCodexEffort(requested: string): string | undefined {
|
|
82
|
+
if (requested === "none") return undefined;
|
|
83
|
+
if (requested === "minimal") return "low";
|
|
84
|
+
return CODEX_REASONING_SET.has(requested) ? requested : undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function clampToSupportedCodexEffort(requested: string, supported: readonly string[]): string | undefined {
|
|
88
|
+
if (supported.length === 0) return undefined;
|
|
89
|
+
const codex = requestToCodexEffort(requested);
|
|
90
|
+
if (!codex) return undefined;
|
|
91
|
+
if (supported.includes(codex)) return codex;
|
|
92
|
+
|
|
93
|
+
const requestedRank = CODEX_REASONING_ORDER.indexOf(codex);
|
|
94
|
+
let best = supported[0];
|
|
95
|
+
let bestRank = CODEX_REASONING_ORDER.indexOf(best);
|
|
96
|
+
for (const effort of supported) {
|
|
97
|
+
const rank = CODEX_REASONING_ORDER.indexOf(effort);
|
|
98
|
+
if (rank <= requestedRank && rank >= bestRank) {
|
|
99
|
+
best = effort;
|
|
100
|
+
bestRank = rank;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// If every supported tier is above the requested tier, choose the lowest supported tier.
|
|
104
|
+
return best;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function reasoningEffortMapFor(provider: OcxProviderConfig, modelId: string): Record<string, string> | undefined {
|
|
108
|
+
return modelRecordValue(provider.modelReasoningEffortMap, modelId) ?? provider.reasoningEffortMap;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Translate Codex's reasoning label into the provider's real wire value. Prefer identity labels
|
|
113
|
+
* (`xhigh` stays `xhigh`, `max` stays `max`); provider maps are only for real upstream aliases.
|
|
114
|
+
*/
|
|
115
|
+
export function mapReasoningEffort(provider: OcxProviderConfig, modelId: string, requested: string | undefined): string | undefined {
|
|
116
|
+
if (!requested) return undefined;
|
|
117
|
+
if (modelInList(provider.noReasoningModels, modelId)) return undefined;
|
|
118
|
+
|
|
119
|
+
// Upstream codex-rs converts ultra -> max before ANY provider request (core/src/client.rs
|
|
120
|
+
// `reasoning_effort_for_request`), so "ultra" must never influence the provider wire — not even
|
|
121
|
+
// through a raw alias. Apply the boundary before alias/clamp resolution.
|
|
122
|
+
const boundary = requested === "ultra" ? "max" : requested;
|
|
123
|
+
|
|
124
|
+
const wireMap = reasoningEffortMapFor(provider, modelId);
|
|
125
|
+
if (wireMap && Object.prototype.hasOwnProperty.call(wireMap, boundary)) return wireMap[boundary];
|
|
126
|
+
|
|
127
|
+
const supported = configuredReasoningEfforts(provider, modelId);
|
|
128
|
+
const codexEffort = supported !== undefined ? clampToSupportedCodexEffort(boundary, supported) : requestToCodexEffort(boundary);
|
|
129
|
+
if (!codexEffort) return undefined;
|
|
130
|
+
|
|
131
|
+
// Belt for the odd config where the supported ladder is ultra-only and the clamp lands on it.
|
|
132
|
+
const wire = codexEffort === "ultra" ? "max" : codexEffort;
|
|
133
|
+
if (wireMap && Object.prototype.hasOwnProperty.call(wireMap, wire)) return wireMap[wire];
|
|
134
|
+
return wire;
|
|
135
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote compaction v2 support for ROUTED providers.
|
|
3
|
+
*
|
|
4
|
+
* Codex decides "this provider supports remote compaction" by provider name (built-in `OpenAI`),
|
|
5
|
+
* and Design B points that provider at this proxy — so Codex sends remote compaction v2 requests
|
|
6
|
+
* for EVERY routed model. The request is a normal /responses call whose input ends with
|
|
7
|
+
* `{"type":"compaction_trigger"}`; codex-rs `collect_compaction_output` then requires the stream
|
|
8
|
+
* to carry EXACTLY ONE `{"type":"compaction","encrypted_content":...}` output item
|
|
9
|
+
* (compact_remote_v2.rs) or it fatals with "expected exactly one compaction output item".
|
|
10
|
+
*
|
|
11
|
+
* Routed models cannot produce OpenAI's encrypted blob, so the proxy runs the model as a plain
|
|
12
|
+
* summarizer and wraps the summary text in a transparent envelope: `ocx1:` + base64(utf8 summary).
|
|
13
|
+
* Codex stores the item and replays it in later input; the parser decodes our envelope back into
|
|
14
|
+
* plain text for routed models. Real OpenAI-encrypted blobs (no `ocx1:` prefix) are opaque —
|
|
15
|
+
* routed models get a short "history was compacted" note instead.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export const OCX_COMPACTION_PREFIX = "ocx1:";
|
|
19
|
+
|
|
20
|
+
/** Mirrors codex-rs core/templates/compact/prompt.md (the local-compaction instruction). */
|
|
21
|
+
export const COMPACT_PROMPT = `You are performing a CONTEXT CHECKPOINT COMPACTION. Create a handoff summary for another LLM that will resume the task.
|
|
22
|
+
|
|
23
|
+
Include:
|
|
24
|
+
- Current progress and key decisions made
|
|
25
|
+
- Important context, constraints, or user preferences
|
|
26
|
+
- What remains to be done (clear next steps)
|
|
27
|
+
- Any critical data, examples, or references needed to continue
|
|
28
|
+
|
|
29
|
+
Be concise, structured, and focused on helping the next LLM seamlessly continue the work.`;
|
|
30
|
+
|
|
31
|
+
/** Mirrors codex-rs core/templates/compact/summary_prefix.md (framing for a replayed summary). */
|
|
32
|
+
export const SUMMARY_PREFIX = "Another language model started to solve this problem and produced a summary of its thinking process. You also have access to the state of the tools that were used by that language model. Use this to build on the work that has already been done and avoid duplicating work. Here is the summary produced by the other language model, use the information in this summary to assist with your own analysis:";
|
|
33
|
+
|
|
34
|
+
export const OPAQUE_COMPACTION_NOTE = "[earlier conversation was compacted; the summary is stored in a format this model cannot read]";
|
|
35
|
+
|
|
36
|
+
export function encodeCompactionSummary(summary: string): string {
|
|
37
|
+
return OCX_COMPACTION_PREFIX + Buffer.from(summary, "utf-8").toString("base64");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Decode an `ocx1:` envelope; returns null for real (OpenAI-encrypted) blobs or garbage. */
|
|
41
|
+
export function decodeCompactionSummary(encryptedContent: string): string | null {
|
|
42
|
+
if (!encryptedContent.startsWith(OCX_COMPACTION_PREFIX)) return null;
|
|
43
|
+
try {
|
|
44
|
+
return Buffer.from(encryptedContent.slice(OCX_COMPACTION_PREFIX.length), "base64").toString("utf-8");
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Render a replayed compaction item as plain user-visible text for a routed model. */
|
|
51
|
+
export function compactionItemToText(encryptedContent: string | undefined): string {
|
|
52
|
+
const decoded = typeof encryptedContent === "string" ? decodeCompactionSummary(encryptedContent) : null;
|
|
53
|
+
return decoded ? `${SUMMARY_PREFIX}\n\n${decoded}` : OPAQUE_COMPACTION_NOTE;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Remote compaction v1 (`POST /responses/compact`, unary) — codex-rs installs the returned
|
|
58
|
+
* `{"output":[ResponseItem...]}` as the REPLACEMENT history (compact_remote.rs
|
|
59
|
+
* process_compacted_history). Mirror codex-rs local `build_compacted_history`: recent real user
|
|
60
|
+
* messages within a token budget, then one user message `SUMMARY_PREFIX\n<summary>`. Plain user
|
|
61
|
+
* message items parse as real user messages on the codex side (event_mapping parse_user_message);
|
|
62
|
+
* contextual wrappers are filtered there, and v2-style `compaction` items are NOT expected here.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/** codex-rs compact.rs COMPACT_USER_MESSAGE_MAX_TOKENS = 20k tokens (~4 chars/token). */
|
|
66
|
+
const COMPACT_V1_RETAINED_CHAR_BUDGET = 20_000 * 4;
|
|
67
|
+
|
|
68
|
+
/** Extract plain-text user messages from a Responses `input` array (for v1 compact retention). */
|
|
69
|
+
export function extractCompactUserMessages(input: unknown): string[] {
|
|
70
|
+
if (!Array.isArray(input)) return [];
|
|
71
|
+
const out: string[] = [];
|
|
72
|
+
for (const item of input) {
|
|
73
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
|
|
74
|
+
const rec = item as { type?: string; role?: string; content?: unknown };
|
|
75
|
+
if (rec.type !== undefined && rec.type !== "message") continue;
|
|
76
|
+
if (rec.role !== "user") continue;
|
|
77
|
+
let text = "";
|
|
78
|
+
if (typeof rec.content === "string") text = rec.content;
|
|
79
|
+
else if (Array.isArray(rec.content)) {
|
|
80
|
+
text = rec.content
|
|
81
|
+
.map(b => {
|
|
82
|
+
if (!b || typeof b !== "object") return "";
|
|
83
|
+
const block = b as { type?: string; text?: string };
|
|
84
|
+
return (block.type === "input_text" || block.type === "text") && typeof block.text === "string" ? block.text : "";
|
|
85
|
+
})
|
|
86
|
+
.join("");
|
|
87
|
+
}
|
|
88
|
+
if (text.trim().length > 0) out.push(text);
|
|
89
|
+
}
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function compactUserMessageItem(text: string): Record<string, unknown> {
|
|
94
|
+
return { type: "message", role: "user", content: [{ type: "input_text", text }] };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Build the v1 compact `output` array: retained recent user messages + the summary message. */
|
|
98
|
+
export function buildCompactV1Output(userMessages: string[], summary: string): Record<string, unknown>[] {
|
|
99
|
+
const selected: string[] = [];
|
|
100
|
+
let remaining = COMPACT_V1_RETAINED_CHAR_BUDGET;
|
|
101
|
+
for (let i = userMessages.length - 1; i >= 0 && remaining > 0; i--) {
|
|
102
|
+
const msg = userMessages[i];
|
|
103
|
+
if (msg.length <= remaining) {
|
|
104
|
+
selected.push(msg);
|
|
105
|
+
remaining -= msg.length;
|
|
106
|
+
} else {
|
|
107
|
+
// Budget partially covers this older message: keep its tail (most recent context) and stop.
|
|
108
|
+
selected.push(msg.slice(msg.length - remaining));
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
selected.reverse();
|
|
113
|
+
// codex-rs compact.rs uses "{SUMMARY_PREFIX}\n{summary}" (single newline) and detects stored
|
|
114
|
+
// summaries by that exact prefix — keep the same shape.
|
|
115
|
+
const summaryText = summary.trim().length > 0 ? `${SUMMARY_PREFIX}\n${summary}` : "(no summary available)";
|
|
116
|
+
return [...selected.map(compactUserMessageItem), compactUserMessageItem(summaryText)];
|
|
117
|
+
}
|