@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,550 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure, ownership-aware edits for Codex's native `[agents]` defaults.
|
|
3
|
+
*
|
|
4
|
+
* This intentionally does not parse and re-serialize the whole TOML document:
|
|
5
|
+
* callers can write the returned content atomically while comments, ordering,
|
|
6
|
+
* unknown keys, and line endings remain untouched. Every value and table that
|
|
7
|
+
* this transform may later remove has its own immediately preceding marker.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const MANAGED_SUBAGENT_DEFAULT_MARKER = "# Managed by opencodex: native subagent default";
|
|
11
|
+
export const MANAGED_AGENTS_TABLE_MARKER = "# Managed by opencodex: native subagent defaults table";
|
|
12
|
+
|
|
13
|
+
export type ManagedSubagentDefaultKey =
|
|
14
|
+
| "default_subagent_model"
|
|
15
|
+
| "default_subagent_reasoning_effort";
|
|
16
|
+
|
|
17
|
+
export interface ManagedSubagentDefaults {
|
|
18
|
+
model: string;
|
|
19
|
+
reasoningEffort?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ManagedSubagentDefaultsConflict {
|
|
23
|
+
key: ManagedSubagentDefaultKey;
|
|
24
|
+
line: number;
|
|
25
|
+
reason: "user-owned";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type ManagedSubagentDefaultsTransformResult =
|
|
29
|
+
| {
|
|
30
|
+
ok: true;
|
|
31
|
+
changed: boolean;
|
|
32
|
+
content: string;
|
|
33
|
+
conflicts: ManagedSubagentDefaultsConflict[];
|
|
34
|
+
}
|
|
35
|
+
| {
|
|
36
|
+
ok: false;
|
|
37
|
+
changed: false;
|
|
38
|
+
content: string;
|
|
39
|
+
conflicts: [];
|
|
40
|
+
error: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
interface SourceLine {
|
|
44
|
+
text: string;
|
|
45
|
+
eol: "\r\n" | "\n" | "";
|
|
46
|
+
/** False when this physical line began inside a TOML multiline string. */
|
|
47
|
+
structural: boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface TargetDefinition {
|
|
51
|
+
key: ManagedSubagentDefaultKey;
|
|
52
|
+
index: number;
|
|
53
|
+
owned: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface TomlShape {
|
|
57
|
+
agentsHeader: number | null;
|
|
58
|
+
agentsEnd: number | null;
|
|
59
|
+
tableOwned: boolean;
|
|
60
|
+
definitions: Map<ManagedSubagentDefaultKey, TargetDefinition>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const TARGET_KEYS: readonly ManagedSubagentDefaultKey[] = [
|
|
64
|
+
"default_subagent_model",
|
|
65
|
+
"default_subagent_reasoning_effort",
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
function splitSourceLines(content: string): SourceLine[] {
|
|
69
|
+
const lines: SourceLine[] = [];
|
|
70
|
+
let offset = 0;
|
|
71
|
+
while (offset < content.length) {
|
|
72
|
+
const lf = content.indexOf("\n", offset);
|
|
73
|
+
if (lf === -1) {
|
|
74
|
+
lines.push({ text: content.slice(offset), eol: "", structural: true });
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
const crlf = lf > offset && content[lf - 1] === "\r";
|
|
78
|
+
lines.push({
|
|
79
|
+
text: content.slice(offset, crlf ? lf - 1 : lf),
|
|
80
|
+
eol: crlf ? "\r\n" : "\n",
|
|
81
|
+
structural: true,
|
|
82
|
+
});
|
|
83
|
+
offset = lf + 1;
|
|
84
|
+
}
|
|
85
|
+
markStructuralLines(lines);
|
|
86
|
+
return lines;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
type MultilineStringKind = "basic" | "literal" | null;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* TOML table-looking text inside a multiline string is data, not syntax. Keep
|
|
93
|
+
* a deliberately small lexical state machine so the format-preserving editor
|
|
94
|
+
* never treats those physical lines as headers, keys, or ownership markers.
|
|
95
|
+
*/
|
|
96
|
+
function markStructuralLines(lines: SourceLine[]): void {
|
|
97
|
+
let multiline: MultilineStringKind = null;
|
|
98
|
+
let squareDepth = 0;
|
|
99
|
+
let curlyDepth = 0;
|
|
100
|
+
|
|
101
|
+
for (const line of lines) {
|
|
102
|
+
line.structural = multiline === null && squareDepth === 0 && curlyDepth === 0;
|
|
103
|
+
let single: "basic" | "literal" | null = null;
|
|
104
|
+
|
|
105
|
+
for (let index = 0; index < line.text.length;) {
|
|
106
|
+
if (multiline === "basic") {
|
|
107
|
+
if (line.text.startsWith('"""', index)) {
|
|
108
|
+
multiline = null;
|
|
109
|
+
index += 3;
|
|
110
|
+
} else if (line.text[index] === "\\") {
|
|
111
|
+
index += 2;
|
|
112
|
+
} else {
|
|
113
|
+
index += 1;
|
|
114
|
+
}
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (multiline === "literal") {
|
|
118
|
+
if (line.text.startsWith("'''", index)) {
|
|
119
|
+
multiline = null;
|
|
120
|
+
index += 3;
|
|
121
|
+
} else {
|
|
122
|
+
index += 1;
|
|
123
|
+
}
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (single === "basic") {
|
|
127
|
+
if (line.text[index] === "\\") index += 2;
|
|
128
|
+
else if (line.text[index] === '"') {
|
|
129
|
+
single = null;
|
|
130
|
+
index += 1;
|
|
131
|
+
} else index += 1;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (single === "literal") {
|
|
135
|
+
if (line.text[index] === "'") single = null;
|
|
136
|
+
index += 1;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (line.text[index] === "#") break;
|
|
141
|
+
if (line.text.startsWith('"""', index)) {
|
|
142
|
+
multiline = "basic";
|
|
143
|
+
index += 3;
|
|
144
|
+
} else if (line.text.startsWith("'''", index)) {
|
|
145
|
+
multiline = "literal";
|
|
146
|
+
index += 3;
|
|
147
|
+
} else if (line.text[index] === '"') {
|
|
148
|
+
single = "basic";
|
|
149
|
+
index += 1;
|
|
150
|
+
} else if (line.text[index] === "'") {
|
|
151
|
+
single = "literal";
|
|
152
|
+
index += 1;
|
|
153
|
+
} else if (line.text[index] === "[") {
|
|
154
|
+
squareDepth += 1;
|
|
155
|
+
index += 1;
|
|
156
|
+
} else if (line.text[index] === "]") {
|
|
157
|
+
squareDepth = Math.max(0, squareDepth - 1);
|
|
158
|
+
index += 1;
|
|
159
|
+
} else if (line.text[index] === "{") {
|
|
160
|
+
curlyDepth += 1;
|
|
161
|
+
index += 1;
|
|
162
|
+
} else if (line.text[index] === "}") {
|
|
163
|
+
curlyDepth = Math.max(0, curlyDepth - 1);
|
|
164
|
+
index += 1;
|
|
165
|
+
} else {
|
|
166
|
+
index += 1;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function joinSourceLines(lines: readonly SourceLine[]): string {
|
|
173
|
+
return lines.map(line => `${line.text}${line.eol}`).join("");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function dominantEol(lines: readonly SourceLine[]): "\r\n" | "\n" {
|
|
177
|
+
let crlf = 0;
|
|
178
|
+
let lf = 0;
|
|
179
|
+
for (const line of lines) {
|
|
180
|
+
if (line.eol === "\r\n") crlf += 1;
|
|
181
|
+
else if (line.eol === "\n") lf += 1;
|
|
182
|
+
}
|
|
183
|
+
return crlf > 0 && crlf >= lf ? "\r\n" : "\n";
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Decode a TOML basic-string key body, including Unicode escapes. */
|
|
187
|
+
function decodeTomlBasicKey(body: string): string {
|
|
188
|
+
return body.replace(
|
|
189
|
+
/\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8}|.)/g,
|
|
190
|
+
(whole, escape: string) => {
|
|
191
|
+
if (escape[0] === "x") return String.fromCharCode(Number.parseInt(escape.slice(1), 16));
|
|
192
|
+
if (escape[0] === "u") return String.fromCharCode(Number.parseInt(escape.slice(1), 16));
|
|
193
|
+
if (escape[0] === "U") {
|
|
194
|
+
const codePoint = Number.parseInt(escape.slice(1), 16);
|
|
195
|
+
return codePoint <= 0x10ffff ? String.fromCodePoint(codePoint) : whole;
|
|
196
|
+
}
|
|
197
|
+
switch (escape) {
|
|
198
|
+
case "b": return "\b";
|
|
199
|
+
case "t": return "\t";
|
|
200
|
+
case "n": return "\n";
|
|
201
|
+
case "f": return "\f";
|
|
202
|
+
case "r": return "\r";
|
|
203
|
+
case '"': return '"';
|
|
204
|
+
case "\\": return "\\";
|
|
205
|
+
default: return whole;
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function canonicalKeySegment(raw: string): string {
|
|
212
|
+
if (raw.startsWith('"')) return decodeTomlBasicKey(raw.slice(1, -1));
|
|
213
|
+
if (raw.startsWith("'")) return raw.slice(1, -1);
|
|
214
|
+
return raw;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const KEY_SEGMENT = String.raw`(?:[A-Za-z0-9_-]+|"(?:[^"\\]|\\.)*"|'[^']*')`;
|
|
218
|
+
const EXACT_TABLE_HEADER = new RegExp(`^\\s*\\[\\s*(${KEY_SEGMENT})\\s*\\]\\s*(?:#.*)?$`);
|
|
219
|
+
const ARRAY_TABLE_HEADER = new RegExp(`^\\s*\\[\\[\\s*(${KEY_SEGMENT})\\s*\\]\\]\\s*(?:#.*)?$`);
|
|
220
|
+
const DOTTED_TABLE_HEADER = new RegExp(`^\\s*\\[\\[?\\s*(${KEY_SEGMENT})\\s*\\.\\s*(${KEY_SEGMENT})(?:\\s*\\.|\\s*\\]\\]?)`);
|
|
221
|
+
const KEY_ASSIGNMENT = new RegExp(`^\\s*(${KEY_SEGMENT})\\s*=`);
|
|
222
|
+
const DOTTED_ASSIGNMENT = new RegExp(`^\\s*(${KEY_SEGMENT})\\s*\\.\\s*(${KEY_SEGMENT})(?:\\s*\\.|\\s*=)`);
|
|
223
|
+
const ANY_TABLE_HEADER = /^\s*\[{1,2}/;
|
|
224
|
+
|
|
225
|
+
function exactAgentsHeader(line: SourceLine | undefined): boolean {
|
|
226
|
+
if (!line?.structural) return false;
|
|
227
|
+
const match = line.text.match(EXACT_TABLE_HEADER);
|
|
228
|
+
return match !== null && canonicalKeySegment(match[1]!) === "agents";
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function arrayAgentsHeader(line: SourceLine): boolean {
|
|
232
|
+
if (!line.structural) return false;
|
|
233
|
+
const match = line.text.match(ARRAY_TABLE_HEADER);
|
|
234
|
+
return match !== null && canonicalKeySegment(match[1]!) === "agents";
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function dottedAgentsHeader(line: SourceLine): { second: string } | null {
|
|
238
|
+
if (!line.structural) return null;
|
|
239
|
+
const match = line.text.match(DOTTED_TABLE_HEADER);
|
|
240
|
+
if (!match || canonicalKeySegment(match[1]!) !== "agents") return null;
|
|
241
|
+
return { second: canonicalKeySegment(match[2]!) };
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function isAnyTableHeader(line: SourceLine): boolean {
|
|
245
|
+
return line.structural && ANY_TABLE_HEADER.test(line.text);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function assignmentKeyAt(line: SourceLine): string | null {
|
|
249
|
+
if (!line.structural) return null;
|
|
250
|
+
const match = line.text.match(KEY_ASSIGNMENT);
|
|
251
|
+
return match ? canonicalKeySegment(match[1]!) : null;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function markerLine(line: SourceLine | undefined, marker: string): boolean {
|
|
255
|
+
return line?.structural === true && line.text.trim() === marker;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function targetKeyAt(line: SourceLine | undefined): ManagedSubagentDefaultKey | null {
|
|
259
|
+
if (!line) return null;
|
|
260
|
+
const key = assignmentKeyAt(line);
|
|
261
|
+
return TARGET_KEYS.includes(key as ManagedSubagentDefaultKey)
|
|
262
|
+
? key as ManagedSubagentDefaultKey
|
|
263
|
+
: null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function dottedAssignmentAt(line: SourceLine): { first: string; second: string } | null {
|
|
267
|
+
if (!line.structural) return null;
|
|
268
|
+
const match = line.text.match(DOTTED_ASSIGNMENT);
|
|
269
|
+
if (!match) return null;
|
|
270
|
+
return {
|
|
271
|
+
first: canonicalKeySegment(match[1]!),
|
|
272
|
+
second: canonicalKeySegment(match[2]!),
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function dottedTargetAt(line: SourceLine): ManagedSubagentDefaultKey | null {
|
|
277
|
+
const dotted = dottedAssignmentAt(line);
|
|
278
|
+
if (!dotted) return null;
|
|
279
|
+
return TARGET_KEYS.includes(dotted.first as ManagedSubagentDefaultKey)
|
|
280
|
+
? dotted.first as ManagedSubagentDefaultKey
|
|
281
|
+
: null;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function analyzeToml(lines: readonly SourceLine[]): { shape: TomlShape } | { error: string } {
|
|
285
|
+
const exactHeaders: number[] = [];
|
|
286
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
287
|
+
const line = lines[index]!;
|
|
288
|
+
if (exactAgentsHeader(line)) exactHeaders.push(index);
|
|
289
|
+
else if (arrayAgentsHeader(line)) {
|
|
290
|
+
return { error: "array [[agents]] tables are not supported for managed subagent defaults" };
|
|
291
|
+
} else if (TARGET_KEYS.includes(dottedAgentsHeader(line)?.second as ManagedSubagentDefaultKey)) {
|
|
292
|
+
return { error: "agents default keys cannot be represented as nested tables" };
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (exactHeaders.length > 1) {
|
|
296
|
+
return { error: "duplicate [agents] tables cannot be updated safely" };
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const firstTable = lines.findIndex(isAnyTableHeader);
|
|
300
|
+
const rootEnd = firstTable === -1 ? lines.length : firstTable;
|
|
301
|
+
for (let index = 0; index < rootEnd; index += 1) {
|
|
302
|
+
const line = lines[index]!;
|
|
303
|
+
const dotted = dottedAssignmentAt(line);
|
|
304
|
+
if (dotted?.first === "agents"
|
|
305
|
+
&& TARGET_KEYS.includes(dotted.second as ManagedSubagentDefaultKey)) {
|
|
306
|
+
return { error: "dotted agents default keys are not supported for managed subagent defaults" };
|
|
307
|
+
}
|
|
308
|
+
if (assignmentKeyAt(line) === "agents") {
|
|
309
|
+
return { error: "inline agents definitions cannot be updated safely" };
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const agentsHeader = exactHeaders[0] ?? null;
|
|
314
|
+
let agentsEnd: number | null = null;
|
|
315
|
+
const definitions = new Map<ManagedSubagentDefaultKey, TargetDefinition>();
|
|
316
|
+
if (agentsHeader !== null) {
|
|
317
|
+
agentsEnd = lines.length;
|
|
318
|
+
for (let index = agentsHeader + 1; index < lines.length; index += 1) {
|
|
319
|
+
if (isAnyTableHeader(lines[index]!)) {
|
|
320
|
+
agentsEnd = index;
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
const dotted = dottedTargetAt(lines[index]!);
|
|
324
|
+
if (dotted) {
|
|
325
|
+
return { error: `dotted agents.${dotted} fields are not supported` };
|
|
326
|
+
}
|
|
327
|
+
const key = targetKeyAt(lines[index]);
|
|
328
|
+
if (!key) continue;
|
|
329
|
+
if (definitions.has(key)) {
|
|
330
|
+
return { error: `duplicate agents.${key} definitions cannot be updated safely` };
|
|
331
|
+
}
|
|
332
|
+
definitions.set(key, {
|
|
333
|
+
key,
|
|
334
|
+
index,
|
|
335
|
+
owned: markerLine(lines[index - 1], MANAGED_SUBAGENT_DEFAULT_MARKER),
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
341
|
+
if (markerLine(lines[index], MANAGED_SUBAGENT_DEFAULT_MARKER)) {
|
|
342
|
+
const nextKey = targetKeyAt(lines[index + 1]);
|
|
343
|
+
const insideAgents = agentsHeader !== null
|
|
344
|
+
&& agentsEnd !== null
|
|
345
|
+
&& index > agentsHeader
|
|
346
|
+
&& index + 1 < agentsEnd;
|
|
347
|
+
if (!nextKey || !insideAgents) {
|
|
348
|
+
return { error: "orphaned managed subagent default marker cannot be updated safely" };
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (markerLine(lines[index], MANAGED_AGENTS_TABLE_MARKER)) {
|
|
352
|
+
if (index + 1 !== agentsHeader) {
|
|
353
|
+
return { error: "orphaned managed agents table marker cannot be updated safely" };
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return {
|
|
359
|
+
shape: {
|
|
360
|
+
agentsHeader,
|
|
361
|
+
agentsEnd,
|
|
362
|
+
tableOwned: agentsHeader !== null && markerLine(lines[agentsHeader - 1], MANAGED_AGENTS_TABLE_MARKER),
|
|
363
|
+
definitions,
|
|
364
|
+
},
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function quotedTomlString(value: string): string {
|
|
369
|
+
// JSON basic strings are valid TOML basic strings and cover quotes,
|
|
370
|
+
// backslashes, control characters, and newlines. JSON leaves DEL literal,
|
|
371
|
+
// while TOML requires it escaped.
|
|
372
|
+
return JSON.stringify(value).replace(/\u007f/g, "\\u007F");
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function containsLoneSurrogate(value: string): boolean {
|
|
376
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
377
|
+
const unit = value.charCodeAt(index);
|
|
378
|
+
if (unit >= 0xd800 && unit <= 0xdbff) {
|
|
379
|
+
const next = value.charCodeAt(index + 1);
|
|
380
|
+
if (!(next >= 0xdc00 && next <= 0xdfff)) return true;
|
|
381
|
+
index += 1;
|
|
382
|
+
} else if (unit >= 0xdc00 && unit <= 0xdfff) {
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return false;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function replaceManagedString(line: string, key: ManagedSubagentDefaultKey, value: string): string | null {
|
|
390
|
+
const stringValue = `(?:"(?:\\\\.|[^"\\\\])*"|'[^']*')`;
|
|
391
|
+
const match = line.match(new RegExp(`^(\\s*)(${KEY_SEGMENT})(\\s*=\\s*)(${stringValue})(\\s*(?:#.*)?)$`));
|
|
392
|
+
if (!match || canonicalKeySegment(match[2]!) !== key) return null;
|
|
393
|
+
const quoted = quotedTomlString(value);
|
|
394
|
+
if (match[4] === quoted) return line;
|
|
395
|
+
return `${match[1]}${match[2]}${match[3]}${quoted}${match[5]}`;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function insertedLines(
|
|
399
|
+
key: ManagedSubagentDefaultKey,
|
|
400
|
+
value: string,
|
|
401
|
+
eol: "\r\n" | "\n",
|
|
402
|
+
): SourceLine[] {
|
|
403
|
+
return [
|
|
404
|
+
{ text: MANAGED_SUBAGENT_DEFAULT_MARKER, eol, structural: true },
|
|
405
|
+
{ text: `${key} = ${quotedTomlString(value)}`, eol, structural: true },
|
|
406
|
+
];
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function invalidInput(content: string, error: string): ManagedSubagentDefaultsTransformResult {
|
|
410
|
+
return { ok: false, changed: false, content, conflicts: [], error };
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Add/update opencodex-owned native subagent defaults, or remove them with
|
|
415
|
+
* `defaults = null`. Unmarked target keys are user-owned: they are retained and
|
|
416
|
+
* returned as conflicts rather than overwritten. Ambiguous TOML is rejected
|
|
417
|
+
* byte-for-byte so callers never have to guess what was changed.
|
|
418
|
+
*/
|
|
419
|
+
export function transformManagedSubagentDefaults(
|
|
420
|
+
content: string,
|
|
421
|
+
defaults: ManagedSubagentDefaults | null,
|
|
422
|
+
): ManagedSubagentDefaultsTransformResult {
|
|
423
|
+
if (defaults !== null) {
|
|
424
|
+
if (typeof defaults.model !== "string" || defaults.model.length === 0) {
|
|
425
|
+
return invalidInput(content, "managed subagent model must be a non-empty string");
|
|
426
|
+
}
|
|
427
|
+
if (containsLoneSurrogate(defaults.model)) {
|
|
428
|
+
return invalidInput(content, "managed subagent model must contain valid Unicode scalar values");
|
|
429
|
+
}
|
|
430
|
+
if (defaults.reasoningEffort !== undefined
|
|
431
|
+
&& (typeof defaults.reasoningEffort !== "string" || defaults.reasoningEffort.length === 0)) {
|
|
432
|
+
return invalidInput(content, "managed subagent reasoning effort must be a non-empty string when supplied");
|
|
433
|
+
}
|
|
434
|
+
if (defaults.reasoningEffort !== undefined && containsLoneSurrogate(defaults.reasoningEffort)) {
|
|
435
|
+
return invalidInput(content, "managed subagent reasoning effort must contain valid Unicode scalar values");
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const lines = splitSourceLines(content);
|
|
440
|
+
if (defaults === null && !lines.some(line =>
|
|
441
|
+
markerLine(line, MANAGED_SUBAGENT_DEFAULT_MARKER)
|
|
442
|
+
|| markerLine(line, MANAGED_AGENTS_TABLE_MARKER))) {
|
|
443
|
+
return { ok: true, changed: false, content, conflicts: [] };
|
|
444
|
+
}
|
|
445
|
+
const analysis = analyzeToml(lines);
|
|
446
|
+
if ("error" in analysis) return invalidInput(content, analysis.error);
|
|
447
|
+
const { shape } = analysis;
|
|
448
|
+
const eol = dominantEol(lines);
|
|
449
|
+
const desired = new Map<ManagedSubagentDefaultKey, string>();
|
|
450
|
+
if (defaults !== null) {
|
|
451
|
+
desired.set("default_subagent_model", defaults.model);
|
|
452
|
+
if (defaults.reasoningEffort !== undefined) {
|
|
453
|
+
desired.set("default_subagent_reasoning_effort", defaults.reasoningEffort);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const conflicts: ManagedSubagentDefaultsConflict[] = [];
|
|
458
|
+
const missing: Array<[ManagedSubagentDefaultKey, string]> = [];
|
|
459
|
+
const removals: number[] = [];
|
|
460
|
+
|
|
461
|
+
if (defaults !== null) {
|
|
462
|
+
for (const key of TARGET_KEYS) {
|
|
463
|
+
const definition = shape.definitions.get(key);
|
|
464
|
+
if (definition && !definition.owned) {
|
|
465
|
+
conflicts.push({ key, line: definition.index + 1, reason: "user-owned" });
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
// Model and effort are one effective native-default pair. A partial write
|
|
469
|
+
// could apply a newly managed effort to a user's model (or vice versa), so
|
|
470
|
+
// any desired-key ownership conflict makes the whole enable/update a no-op.
|
|
471
|
+
if (conflicts.length > 0) {
|
|
472
|
+
return { ok: true, changed: false, content, conflicts };
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
for (const key of TARGET_KEYS) {
|
|
477
|
+
const definition = shape.definitions.get(key);
|
|
478
|
+
const value = desired.get(key);
|
|
479
|
+
if (!definition) {
|
|
480
|
+
if (value !== undefined) missing.push([key, value]);
|
|
481
|
+
continue;
|
|
482
|
+
}
|
|
483
|
+
if (!definition.owned) {
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
if (replaceManagedString(lines[definition.index]!.text, key, value ?? "__opencodex_validation__") === null) {
|
|
487
|
+
return invalidInput(content, `managed agents.${key} is not a supported single-line TOML string`);
|
|
488
|
+
}
|
|
489
|
+
if (value === undefined) {
|
|
490
|
+
removals.push(definition.index - 1, definition.index);
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
493
|
+
const replacement = replaceManagedString(lines[definition.index]!.text, key, value);
|
|
494
|
+
if (replacement === null) {
|
|
495
|
+
return invalidInput(content, `managed agents.${key} is not a supported single-line TOML string`);
|
|
496
|
+
}
|
|
497
|
+
lines[definition.index]!.text = replacement;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
removals.sort((a, b) => b - a);
|
|
501
|
+
for (const index of removals) lines.splice(index, 1);
|
|
502
|
+
|
|
503
|
+
if (missing.length > 0) {
|
|
504
|
+
const pairs = missing.flatMap(([key, value]) => insertedLines(key, value, eol));
|
|
505
|
+
const currentHeader = lines.findIndex(exactAgentsHeader);
|
|
506
|
+
if (currentHeader !== -1) {
|
|
507
|
+
if (lines[currentHeader]!.eol === "") lines[currentHeader]!.eol = eol;
|
|
508
|
+
lines.splice(currentHeader + 1, 0, ...pairs);
|
|
509
|
+
} else {
|
|
510
|
+
const table = [
|
|
511
|
+
{ text: MANAGED_AGENTS_TABLE_MARKER, eol, structural: true },
|
|
512
|
+
{ text: "[agents]", eol, structural: true },
|
|
513
|
+
...pairs,
|
|
514
|
+
];
|
|
515
|
+
const nestedHeader = lines.findIndex(line => dottedAgentsHeader(line) !== null);
|
|
516
|
+
if (nestedHeader !== -1) {
|
|
517
|
+
lines.splice(nestedHeader, 0, ...table);
|
|
518
|
+
} else {
|
|
519
|
+
if (lines.length > 0 && lines[lines.length - 1]!.eol === "") lines[lines.length - 1]!.eol = eol;
|
|
520
|
+
lines.push(...table);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// A table created by this transform is removable only after every body line
|
|
526
|
+
// is blank. Comments or unknown keys make it user-extended and preserve it.
|
|
527
|
+
if (shape.tableOwned) {
|
|
528
|
+
const currentHeader = lines.findIndex(exactAgentsHeader);
|
|
529
|
+
if (currentHeader !== -1 && markerLine(lines[currentHeader - 1], MANAGED_AGENTS_TABLE_MARKER)) {
|
|
530
|
+
let currentEnd = lines.length;
|
|
531
|
+
for (let index = currentHeader + 1; index < lines.length; index += 1) {
|
|
532
|
+
if (isAnyTableHeader(lines[index]!)) {
|
|
533
|
+
currentEnd = index;
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
if (lines.slice(currentHeader + 1, currentEnd).every(line => line.text.trim() === "")) {
|
|
538
|
+
lines.splice(currentHeader - 1, currentEnd - currentHeader + 1);
|
|
539
|
+
} else if (defaults === null) {
|
|
540
|
+
// The table outlived the defaults because a user added content. Drop
|
|
541
|
+
// only our ownership claim; the surviving table and extensions are now
|
|
542
|
+
// wholly user-owned.
|
|
543
|
+
lines.splice(currentHeader - 1, 1);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const output = joinSourceLines(lines);
|
|
549
|
+
return { ok: true, changed: output !== content, content: output, conflicts };
|
|
550
|
+
}
|