@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,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects whether this process was started by a coding agent rather than typed
|
|
3
|
+
* by a person.
|
|
4
|
+
*
|
|
5
|
+
* Agent harnesses run `ocx` on the user's behalf and answer prompts from their
|
|
6
|
+
* own logic, which means a consent question would be decided by the agent
|
|
7
|
+
* instead of the account owner. Prompts that act on the user's identity check
|
|
8
|
+
* this and defer instead: they stay silent so the question reaches the human on
|
|
9
|
+
* a later hand-typed run.
|
|
10
|
+
*
|
|
11
|
+
* Detection is env-var based and deliberately conservative — a false positive
|
|
12
|
+
* only postpones a prompt, while a false negative would let an agent answer for
|
|
13
|
+
* the user.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Env vars set by agent harnesses and CI runners inside the shell they spawn.
|
|
18
|
+
*
|
|
19
|
+
* The list errs wide on purpose. A harness that is missed here is a harness
|
|
20
|
+
* whose model answers a consent question with the user's GitHub identity, which
|
|
21
|
+
* is the failure this module exists to prevent; a harness matched by mistake
|
|
22
|
+
* only postpones a prompt to the user's next hand-typed run.
|
|
23
|
+
*/
|
|
24
|
+
const AGENT_ENV_VARS = [
|
|
25
|
+
// Claude Code
|
|
26
|
+
"CLAUDECODE",
|
|
27
|
+
"CLAUDE_CODE_ENTRYPOINT",
|
|
28
|
+
"CLAUDE_CODE_SSE_PORT",
|
|
29
|
+
// Codex CLI / App / SDK. `CODEX_HOME` is deliberately NOT here: users export it
|
|
30
|
+
// from their own shell profile, so matching it would suppress the prompt for a
|
|
31
|
+
// person who is sitting right there.
|
|
32
|
+
"CODEX_THREAD_ID",
|
|
33
|
+
"CODEX_SHELL",
|
|
34
|
+
"CODEX_CI",
|
|
35
|
+
"CODEX_SANDBOX",
|
|
36
|
+
"CODEX_SANDBOX_NETWORK_DISABLED",
|
|
37
|
+
// Cursor
|
|
38
|
+
"CURSOR_TRACE_ID",
|
|
39
|
+
"CURSOR_SESSION_TOKEN",
|
|
40
|
+
"CURSOR_AGENT",
|
|
41
|
+
// Other coding agents
|
|
42
|
+
"AIDER_CHAT",
|
|
43
|
+
"OPENCODE_BIN_PATH",
|
|
44
|
+
"GEMINI_CLI",
|
|
45
|
+
// Generic runners and hosted environments that are never a person at a keyboard
|
|
46
|
+
"REPL_ID",
|
|
47
|
+
"CI",
|
|
48
|
+
"GITHUB_ACTIONS",
|
|
49
|
+
"GITLAB_CI",
|
|
50
|
+
"BUILDKITE",
|
|
51
|
+
"JENKINS_URL",
|
|
52
|
+
"TEAMCITY_VERSION",
|
|
53
|
+
"CODESPACES",
|
|
54
|
+
] as const;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* True when an agent or automated runner is driving this process. Reads the
|
|
58
|
+
* environment on every call so tests and long-lived processes see current state.
|
|
59
|
+
*/
|
|
60
|
+
export function isAgentDriven(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
61
|
+
return AGENT_ENV_VARS.some(name => (env[name] ?? "").trim() !== "");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The env-var names that mark this process as agent-driven. Empty for a real
|
|
66
|
+
* hand-typed run. Callers that refuse an action use it to name the reason.
|
|
67
|
+
*/
|
|
68
|
+
export function agentDrivenMarkers(env: NodeJS.ProcessEnv = process.env): string[] {
|
|
69
|
+
return AGENT_ENV_VARS.filter(name => (env[name] ?? "").trim() !== "");
|
|
70
|
+
}
|
package/src/cli/agent.ts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CliUsageError,
|
|
3
|
+
csv,
|
|
4
|
+
printData,
|
|
5
|
+
rejectArgs,
|
|
6
|
+
runCliAction,
|
|
7
|
+
runtimeRequest,
|
|
8
|
+
summaryLines,
|
|
9
|
+
takeBooleanOption,
|
|
10
|
+
takeFlag,
|
|
11
|
+
takeIntegerOption,
|
|
12
|
+
takeOption,
|
|
13
|
+
type RuntimeApiDeps,
|
|
14
|
+
} from "./runtime-api";
|
|
15
|
+
|
|
16
|
+
const USAGE = `Usage:
|
|
17
|
+
ocx agent [status] [--json]
|
|
18
|
+
ocx agent injection <status|set> [--model <id|->] [--effort <level|->]
|
|
19
|
+
[--prompt <text|->] [--guidance <on|off>] [--json]
|
|
20
|
+
ocx agent effort <status|set> [--main <level|->] [--subagent <level|->] [--json]
|
|
21
|
+
ocx agent subagents <status|set|clear> [model,model...] [--json]
|
|
22
|
+
ocx agent fallback <status|set|clear> [model,model...] [--poll-ms <5000-600000>] [--json]
|
|
23
|
+
ocx agent sidecar <status|web|vision> [--model <id|->] [--backend <openai|anthropic|->]
|
|
24
|
+
[--reasoning <level>] [--max-descriptions <n>] [--json]`;
|
|
25
|
+
|
|
26
|
+
function clearable(value: string | undefined): string | null | undefined {
|
|
27
|
+
return value === "-" ? null : value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function status(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
31
|
+
const args = [...argv];
|
|
32
|
+
const wantsJson = takeFlag(args, "--json");
|
|
33
|
+
rejectArgs(args, USAGE);
|
|
34
|
+
const [v2, injection, caps, subagents, fallback, sidecars] = await Promise.all([
|
|
35
|
+
runtimeRequest("/api/v2", {}, deps),
|
|
36
|
+
runtimeRequest("/api/injection-model", {}, deps),
|
|
37
|
+
runtimeRequest("/api/effort-caps", {}, deps),
|
|
38
|
+
runtimeRequest("/api/subagent-models", {}, deps),
|
|
39
|
+
runtimeRequest("/api/subagent-model-fallback", {}, deps),
|
|
40
|
+
runtimeRequest("/api/sidecar-settings", {}, deps),
|
|
41
|
+
]);
|
|
42
|
+
const result = { v2, injection, caps, subagents, fallback, sidecars };
|
|
43
|
+
printData(result, wantsJson, summaryLines(result));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function injection(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
47
|
+
const args = [...argv];
|
|
48
|
+
const action = (args.shift() ?? "status").toLowerCase();
|
|
49
|
+
const wantsJson = takeFlag(args, "--json");
|
|
50
|
+
if (action === "status") {
|
|
51
|
+
rejectArgs(args, USAGE);
|
|
52
|
+
const result = await runtimeRequest("/api/injection-model", {}, deps);
|
|
53
|
+
printData(result, wantsJson, summaryLines(result));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (action !== "set") throw new CliUsageError(`unknown injection action ${action}`, USAGE);
|
|
57
|
+
const model = clearable(takeOption(args, "--model"));
|
|
58
|
+
const effort = clearable(takeOption(args, "--effort"));
|
|
59
|
+
const prompt = clearable(takeOption(args, "--prompt"));
|
|
60
|
+
const guidance = takeBooleanOption(args, "--guidance");
|
|
61
|
+
rejectArgs(args, USAGE);
|
|
62
|
+
const body: Record<string, unknown> = {};
|
|
63
|
+
if (model !== undefined) body.model = model;
|
|
64
|
+
if (effort !== undefined) body.effort = effort;
|
|
65
|
+
if (prompt !== undefined) body.prompt = prompt;
|
|
66
|
+
if (guidance !== undefined) body.multiAgentGuidanceEnabled = guidance;
|
|
67
|
+
if (Object.keys(body).length === 0) throw new CliUsageError("at least one injection option is required", USAGE);
|
|
68
|
+
const result = await runtimeRequest("/api/injection-model", { method: "PUT", body: JSON.stringify(body) }, deps);
|
|
69
|
+
printData(result, wantsJson, ["Agent injection settings updated."]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function effort(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
73
|
+
const args = [...argv];
|
|
74
|
+
const action = (args.shift() ?? "status").toLowerCase();
|
|
75
|
+
const wantsJson = takeFlag(args, "--json");
|
|
76
|
+
if (action === "status") {
|
|
77
|
+
rejectArgs(args, USAGE);
|
|
78
|
+
const result = await runtimeRequest("/api/effort-caps", {}, deps);
|
|
79
|
+
printData(result, wantsJson, summaryLines(result));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (action !== "set") throw new CliUsageError(`unknown effort action ${action}`, USAGE);
|
|
83
|
+
const main = clearable(takeOption(args, "--main"));
|
|
84
|
+
const subagent = clearable(takeOption(args, "--subagent"));
|
|
85
|
+
rejectArgs(args, USAGE);
|
|
86
|
+
const body: Record<string, unknown> = {};
|
|
87
|
+
if (main !== undefined) body.effortCap = main;
|
|
88
|
+
if (subagent !== undefined) body.subagentEffortCap = subagent;
|
|
89
|
+
if (Object.keys(body).length === 0) throw new CliUsageError("--main and/or --subagent is required", USAGE);
|
|
90
|
+
const result = await runtimeRequest("/api/effort-caps", { method: "PUT", body: JSON.stringify(body) }, deps);
|
|
91
|
+
printData(result, wantsJson, ["Agent effort caps updated."]);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function subagents(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
95
|
+
const args = [...argv];
|
|
96
|
+
const action = (args.shift() ?? "status").toLowerCase();
|
|
97
|
+
const wantsJson = takeFlag(args, "--json");
|
|
98
|
+
if (action === "status") {
|
|
99
|
+
rejectArgs(args, USAGE);
|
|
100
|
+
const result = await runtimeRequest("/api/subagent-models", {}, deps);
|
|
101
|
+
printData(result, wantsJson, summaryLines(result));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
let models: string[];
|
|
105
|
+
if (action === "clear") models = [];
|
|
106
|
+
else if (action === "set") {
|
|
107
|
+
const raw = args.shift();
|
|
108
|
+
if (!raw) throw new CliUsageError("comma-separated subagent models are required", USAGE);
|
|
109
|
+
models = csv(raw) ?? [];
|
|
110
|
+
} else throw new CliUsageError(`unknown subagents action ${action}`, USAGE);
|
|
111
|
+
rejectArgs(args, USAGE);
|
|
112
|
+
if (models.length > 5) throw new CliUsageError("at most 5 subagent models are allowed", USAGE);
|
|
113
|
+
const result = await runtimeRequest("/api/subagent-models", { method: "PUT", body: JSON.stringify({ models }) }, deps);
|
|
114
|
+
printData(result, wantsJson, [`Subagent roster: ${models.join(", ") || "cleared"}`]);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function fallback(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
118
|
+
const args = [...argv];
|
|
119
|
+
const action = (args.shift() ?? "status").toLowerCase();
|
|
120
|
+
const wantsJson = takeFlag(args, "--json");
|
|
121
|
+
if (action === "status") {
|
|
122
|
+
rejectArgs(args, USAGE);
|
|
123
|
+
const result = await runtimeRequest("/api/subagent-model-fallback", {}, deps);
|
|
124
|
+
printData(result, wantsJson, summaryLines(result));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const body: Record<string, unknown> = {};
|
|
128
|
+
if (action === "clear") body.models = [];
|
|
129
|
+
else if (action === "set") {
|
|
130
|
+
const raw = args[0] && !args[0].startsWith("--") ? args.shift() : undefined;
|
|
131
|
+
if (raw) body.models = csv(raw) ?? [];
|
|
132
|
+
} else throw new CliUsageError(`unknown fallback action ${action}`, USAGE);
|
|
133
|
+
const pollMs = takeIntegerOption(args, "--poll-ms", { min: 5_000 });
|
|
134
|
+
if (pollMs !== undefined) {
|
|
135
|
+
if (pollMs > 600_000) throw new CliUsageError("--poll-ms must be <= 600000", USAGE);
|
|
136
|
+
body.pollMs = pollMs;
|
|
137
|
+
}
|
|
138
|
+
rejectArgs(args, USAGE);
|
|
139
|
+
if (Object.keys(body).length === 0) throw new CliUsageError("models and/or --poll-ms is required", USAGE);
|
|
140
|
+
const result = await runtimeRequest("/api/subagent-model-fallback", { method: "PUT", body: JSON.stringify(body) }, deps);
|
|
141
|
+
printData(result, wantsJson, ["Subagent fallback settings updated."]);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function sidecar(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
145
|
+
const args = [...argv];
|
|
146
|
+
const section = (args.shift() ?? "status").toLowerCase();
|
|
147
|
+
const wantsJson = takeFlag(args, "--json");
|
|
148
|
+
if (section === "status") {
|
|
149
|
+
rejectArgs(args, USAGE);
|
|
150
|
+
const result = await runtimeRequest("/api/sidecar-settings", {}, deps);
|
|
151
|
+
printData(result, wantsJson, summaryLines(result));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (section !== "web" && section !== "vision") throw new CliUsageError("sidecar must be web, vision, or status", USAGE);
|
|
155
|
+
const model = takeOption(args, "--model");
|
|
156
|
+
const backend = takeOption(args, "--backend");
|
|
157
|
+
const reasoning = takeOption(args, "--reasoning");
|
|
158
|
+
const maxDescriptionsPerTurn = takeIntegerOption(args, "--max-descriptions", { min: 1 });
|
|
159
|
+
rejectArgs(args, USAGE);
|
|
160
|
+
const settings: Record<string, unknown> = {};
|
|
161
|
+
if (model !== undefined) settings.model = model === "-" ? "" : model;
|
|
162
|
+
if (backend !== undefined) settings.backend = backend === "-" ? null : backend;
|
|
163
|
+
if (reasoning !== undefined) settings.reasoning = reasoning;
|
|
164
|
+
if (maxDescriptionsPerTurn !== undefined) settings.maxDescriptionsPerTurn = maxDescriptionsPerTurn;
|
|
165
|
+
if (Object.keys(settings).length === 0) throw new CliUsageError("at least one sidecar option is required", USAGE);
|
|
166
|
+
const body = section === "web" ? { webSearch: settings } : { vision: settings };
|
|
167
|
+
const result = await runtimeRequest("/api/sidecar-settings", { method: "PUT", body: JSON.stringify(body) }, deps);
|
|
168
|
+
printData(result, wantsJson, [`${section} sidecar settings updated.`]);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export async function handleAgentCommand(argv: string[], deps: RuntimeApiDeps = {}): Promise<number> {
|
|
172
|
+
return runCliAction(async () => {
|
|
173
|
+
const [sub = "status", ...rest] = argv;
|
|
174
|
+
if (sub === "status") await status(rest, deps);
|
|
175
|
+
else if (sub === "injection" || sub === "guidance") await injection(rest, deps);
|
|
176
|
+
else if (sub === "effort") await effort(rest, deps);
|
|
177
|
+
else if (sub === "subagents" || sub === "roster") await subagents(rest, deps);
|
|
178
|
+
else if (sub === "fallback") await fallback(rest, deps);
|
|
179
|
+
else if (sub === "sidecar") await sidecar(rest, deps);
|
|
180
|
+
else throw new CliUsageError(`unknown agent command ${sub}`, USAGE);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export const AGENT_USAGE = USAGE;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { OcxConfig } from "../types";
|
|
2
|
+
|
|
3
|
+
type GatherRoutedModels = (config: OcxConfig) => Promise<unknown>;
|
|
4
|
+
|
|
5
|
+
export type CatalogPrewarmDeps = {
|
|
6
|
+
loadConfig?: () => OcxConfig;
|
|
7
|
+
importCatalog?: () => Promise<{ gatherRoutedModels: GatherRoutedModels }>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* After the listen port is bound, kick off live provider discovery so the first
|
|
12
|
+
* GUI /v1/models and syncModelsToCodex share one gather flight instead of racing
|
|
13
|
+
* duplicate upstream /models fetches.
|
|
14
|
+
*/
|
|
15
|
+
export function scheduleCatalogPrewarm(deps: CatalogPrewarmDeps = {}): void {
|
|
16
|
+
void Promise.resolve()
|
|
17
|
+
.then(async () => {
|
|
18
|
+
const load = deps.loadConfig ?? (await import("../config")).loadConfig;
|
|
19
|
+
const { gatherRoutedModels } = await (deps.importCatalog?.() ?? import("../codex/catalog"));
|
|
20
|
+
return gatherRoutedModels(load());
|
|
21
|
+
})
|
|
22
|
+
.catch(error => {
|
|
23
|
+
if (error && typeof error === "object" && (error as { code?: unknown }).code === "catalog_busy") {
|
|
24
|
+
console.warn("[catalog] startup discovery skipped: catalog gather is busy");
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { loadConfig, saveConfigPreservingClaudeCode } from "../config";
|
|
4
|
+
import {
|
|
5
|
+
DESKTOP_FAMILIES,
|
|
6
|
+
moveDesktopRoute,
|
|
7
|
+
parseDesktopProfile,
|
|
8
|
+
setDesktopFamilyDefault,
|
|
9
|
+
type DesktopFamily,
|
|
10
|
+
type DesktopProfile,
|
|
11
|
+
} from "../claude/desktop-profile";
|
|
12
|
+
import { writeDesktop3pConfig, type Desktop3pConfigMode, parseDesktop3pModeArgs } from "../claude/desktop-3p";
|
|
13
|
+
import { filterCatalogVisibleModels, desktopVisibleNativeSlugs } from "../codex/catalog";
|
|
14
|
+
import { buildClaudeDesktopState, fetchAllModels } from "../server/management-api";
|
|
15
|
+
import { findLiveProxy } from "../server/proxy-liveness";
|
|
16
|
+
import { runtimeRequest } from "./runtime-api";
|
|
17
|
+
|
|
18
|
+
function isFamily(value: string | undefined): value is DesktopFamily {
|
|
19
|
+
return !!value && (DESKTOP_FAMILIES as readonly string[]).includes(value);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function printDesktopHelp(): void {
|
|
23
|
+
console.log(`Usage:
|
|
24
|
+
ocx claude desktop [apply] [--static|--hybrid|--discovery-only]
|
|
25
|
+
ocx claude desktop show [--json]
|
|
26
|
+
ocx claude desktop move <provider/model> <opus|fable|sonnet|haiku> [--default]
|
|
27
|
+
ocx claude desktop default <family> <provider/model|none>
|
|
28
|
+
ocx claude desktop export <path|->
|
|
29
|
+
ocx claude desktop import <path> [--apply]`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ApplyProfileDeps {
|
|
33
|
+
findLiveProxyImpl?: typeof findLiveProxy;
|
|
34
|
+
postApplyImpl?: (
|
|
35
|
+
mode: Desktop3pConfigMode,
|
|
36
|
+
profile: DesktopProfile,
|
|
37
|
+
) => Promise<{ ok?: boolean; path?: string; error?: string }>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function applyProfile(
|
|
41
|
+
profile: DesktopProfile,
|
|
42
|
+
mode: Desktop3pConfigMode,
|
|
43
|
+
deps: ApplyProfileDeps = {},
|
|
44
|
+
): Promise<{ ok: boolean; path: string; reason?: string }> {
|
|
45
|
+
const config = loadConfig();
|
|
46
|
+
const state = await buildClaudeDesktopState(config, profile);
|
|
47
|
+
config.claudeCode = { ...(config.claudeCode ?? {}), desktopProfile: state.profile };
|
|
48
|
+
saveConfigPreservingClaudeCode(config);
|
|
49
|
+
const live = await (deps.findLiveProxyImpl ?? findLiveProxy)();
|
|
50
|
+
if (live) {
|
|
51
|
+
// #859: the Desktop alias reverse-map is process-local. Applying through the
|
|
52
|
+
// serving process installs the map there; a local-only write leaves the
|
|
53
|
+
// daemon unable to decode aliases, and the provider rejects them (400).
|
|
54
|
+
const post = deps.postApplyImpl ?? (async (m: Desktop3pConfigMode, p: DesktopProfile) =>
|
|
55
|
+
runtimeRequest<{ ok?: boolean; path?: string; error?: string }>(
|
|
56
|
+
"/api/claude-desktop/apply",
|
|
57
|
+
// The daemon's config may be older than what we just saved, so the
|
|
58
|
+
// profile travels with the request instead of being re-read there.
|
|
59
|
+
{ method: "POST", body: JSON.stringify({ mode: m, profile: p }) },
|
|
60
|
+
));
|
|
61
|
+
try {
|
|
62
|
+
const applied = await post(mode, state.profile);
|
|
63
|
+
if (applied.ok === false) return { ok: false, path: applied.path ?? "", reason: applied.error ?? "daemon apply failed" };
|
|
64
|
+
return { ok: true, path: applied.path ?? "" };
|
|
65
|
+
} catch (error) {
|
|
66
|
+
return { ok: false, path: "", reason: error instanceof Error ? error.message : String(error) };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const allModels = await fetchAllModels(config);
|
|
70
|
+
const routed = filterCatalogVisibleModels(allModels, config).map(model => ({
|
|
71
|
+
provider: model.provider,
|
|
72
|
+
id: model.id,
|
|
73
|
+
contextWindow: model.contextWindow,
|
|
74
|
+
}));
|
|
75
|
+
const result = writeDesktop3pConfig(
|
|
76
|
+
config.port ?? 10100,
|
|
77
|
+
[...desktopVisibleNativeSlugs(config)],
|
|
78
|
+
routed,
|
|
79
|
+
config.apiKeys?.[0]?.key,
|
|
80
|
+
mode,
|
|
81
|
+
state.profile,
|
|
82
|
+
);
|
|
83
|
+
return { ok: result.written, path: result.path, reason: result.reason };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function handleClaudeDesktopCommand(argv: string[], deps: ApplyProfileDeps = {}): Promise<number> {
|
|
87
|
+
const command = argv[0];
|
|
88
|
+
if (command === "help" || command === "--help" || command === "-h") {
|
|
89
|
+
printDesktopHelp();
|
|
90
|
+
return 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Legacy mode flags remain apply aliases and are parsed before subcommands.
|
|
94
|
+
const legacyFlags = argv.filter(arg => ["--static", "--hybrid", "--discovery-only"].includes(arg));
|
|
95
|
+
const applyInvocation = argv.length === 0 || command === "apply" || legacyFlags.length > 0;
|
|
96
|
+
if (applyInvocation) {
|
|
97
|
+
const nonMode = argv.filter(arg => !["apply", "--static", "--hybrid", "--discovery-only"].includes(arg));
|
|
98
|
+
if (nonMode.length > 0) {
|
|
99
|
+
console.error(`알 수 없는 인자: ${nonMode.join(" ")}`);
|
|
100
|
+
return 1;
|
|
101
|
+
}
|
|
102
|
+
const parsedMode = parseDesktop3pModeArgs(legacyFlags);
|
|
103
|
+
if ("error" in parsedMode) { console.error(parsedMode.error); return 1; }
|
|
104
|
+
try {
|
|
105
|
+
const config = loadConfig();
|
|
106
|
+
const state = await buildClaudeDesktopState(config);
|
|
107
|
+
const result = await applyProfile(state.profile, parsedMode.mode, deps);
|
|
108
|
+
if (!result.ok) {
|
|
109
|
+
console.error(`설정 적용 실패: ${result.reason ?? "unknown error"}`);
|
|
110
|
+
console.error("프로필은 저장되었지만 Claude Desktop 설정 파일에는 반영되지 않았습니다. 프록시 상태를 확인한 뒤 다시 적용해 주세요.");
|
|
111
|
+
return 1;
|
|
112
|
+
}
|
|
113
|
+
console.log(`Claude Desktop 설정을 적용했습니다: ${result.path}`);
|
|
114
|
+
console.log("Claude Desktop을 완전히 종료한 뒤 다시 열어 주세요.");
|
|
115
|
+
return 0;
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
118
|
+
return 1;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const config = loadConfig();
|
|
124
|
+
const state = await buildClaudeDesktopState(config);
|
|
125
|
+
if (command === "show") {
|
|
126
|
+
if (argv.length > 2 || (argv[1] && argv[1] !== "--json")) throw new Error("Usage: ocx claude desktop show [--json]");
|
|
127
|
+
if (argv[1] === "--json") console.log(JSON.stringify(state));
|
|
128
|
+
else {
|
|
129
|
+
for (const family of DESKTOP_FAMILIES) {
|
|
130
|
+
console.log(`${family.toUpperCase()}${state.profile.defaults[family] ? ` (default: ${state.profile.defaults[family]})` : ""}`);
|
|
131
|
+
for (const model of state.models.filter(item => item.assignment.family === family)) {
|
|
132
|
+
console.log(` ${model.available ? "•" : "○"} ${model.route} -> ${model.assignment.alias}${model.available ? "" : " (unavailable)"}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
138
|
+
if (command === "move") {
|
|
139
|
+
const [, route, familyRaw, ...flags] = argv;
|
|
140
|
+
if (!route || !isFamily(familyRaw) || flags.some(flag => flag !== "--default")) throw new Error("Usage: ocx claude desktop move <route> <family> [--default]");
|
|
141
|
+
if (!state.models.some(model => model.route === route && model.available)) throw new Error(`현재 사용할 수 없는 모델입니다: ${route}`);
|
|
142
|
+
const profile = moveDesktopRoute(state.profile, route, familyRaw, flags.includes("--default"));
|
|
143
|
+
config.claudeCode = { ...(config.claudeCode ?? {}), desktopProfile: profile };
|
|
144
|
+
saveConfigPreservingClaudeCode(config);
|
|
145
|
+
console.log(`${route} 모델을 ${familyRaw} 그룹으로 옮겼습니다.`);
|
|
146
|
+
return 0;
|
|
147
|
+
}
|
|
148
|
+
if (command === "default") {
|
|
149
|
+
const [, familyRaw, routeRaw] = argv;
|
|
150
|
+
if (!isFamily(familyRaw) || !routeRaw || argv.length !== 3) throw new Error("Usage: ocx claude desktop default <family> <route|none>");
|
|
151
|
+
const route = routeRaw === "none" ? null : routeRaw;
|
|
152
|
+
if (route && !state.models.some(model => model.route === route && model.available)) throw new Error(`현재 사용할 수 없는 모델입니다: ${route}`);
|
|
153
|
+
const profile = setDesktopFamilyDefault(state.profile, familyRaw, route);
|
|
154
|
+
config.claudeCode = { ...(config.claudeCode ?? {}), desktopProfile: profile };
|
|
155
|
+
saveConfigPreservingClaudeCode(config);
|
|
156
|
+
console.log(`${familyRaw} 기본 모델을 ${route ?? "없음"}으로 지정했습니다.`);
|
|
157
|
+
return 0;
|
|
158
|
+
}
|
|
159
|
+
if (command === "export") {
|
|
160
|
+
const target = argv[1];
|
|
161
|
+
if (!target || argv.length !== 2) throw new Error("Usage: ocx claude desktop export <path|->");
|
|
162
|
+
const json = JSON.stringify(state.profile, null, 2) + "\n";
|
|
163
|
+
if (target === "-") process.stdout.write(json);
|
|
164
|
+
else writeFileSync(resolve(target), json, { encoding: "utf8", mode: 0o600 });
|
|
165
|
+
return 0;
|
|
166
|
+
}
|
|
167
|
+
if (command === "import") {
|
|
168
|
+
const source = argv[1];
|
|
169
|
+
const flags = argv.slice(2);
|
|
170
|
+
if (!source || flags.some(flag => flag !== "--apply")) throw new Error("Usage: ocx claude desktop import <path> [--apply]");
|
|
171
|
+
const profile = parseDesktopProfile(JSON.parse(readFileSync(resolve(source), "utf8")));
|
|
172
|
+
const reconciled = (await buildClaudeDesktopState(config, profile)).profile;
|
|
173
|
+
config.claudeCode = { ...(config.claudeCode ?? {}), desktopProfile: reconciled };
|
|
174
|
+
saveConfigPreservingClaudeCode(config);
|
|
175
|
+
if (flags.includes("--apply")) {
|
|
176
|
+
const result = await applyProfile(reconciled, "static", deps);
|
|
177
|
+
if (!result.ok) { console.error(`프로필은 저장했지만 Desktop 적용에 실패했습니다: ${result.reason ?? "unknown error"}`); return 1; }
|
|
178
|
+
}
|
|
179
|
+
console.log("Claude Desktop 프로필을 가져왔습니다.");
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
printDesktopHelp();
|
|
183
|
+
return 1;
|
|
184
|
+
} catch (error) {
|
|
185
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
186
|
+
return 1;
|
|
187
|
+
}
|
|
188
|
+
}
|