@bitkyc08/opencodex 2.84.0 → 2.87.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/README.md +0 -4
- package/bin/ocx.mjs +61 -3
- package/gui/dist/assets/App-ZfYbLHkB.js +58 -0
- package/gui/dist/assets/App-wT3mXqFz.css +1 -0
- package/gui/dist/assets/{Tray-C9TGtwad.js → Tray-DCd-A1az.js} +1 -1
- package/gui/dist/assets/index-CfYDMj34.js +94 -0
- package/gui/dist/assets/index-DPeB9HpV.css +1 -0
- package/gui/dist/assets/quota-summary-ChvmKGOk.js +1 -0
- package/gui/dist/index.html +2 -2
- package/package.json +1 -2
- package/src/adapters/anthropic/beta-allowlist.ts +91 -11
- package/src/adapters/anthropic/beta-body-pairs.ts +93 -0
- package/src/adapters/anthropic/client-identity.ts +1 -1
- package/src/adapters/anthropic/passthrough.ts +16 -3
- package/src/adapters/anthropic-progress.ts +84 -0
- package/src/adapters/anthropic.ts +108 -21
- package/src/adapters/azure.ts +19 -1
- package/src/adapters/base.ts +2 -0
- package/src/adapters/claude-cli/adapter.ts +111 -23
- package/src/adapters/claude-cli/profiles.ts +2 -1
- package/src/adapters/claude-cli/stable-replay.ts +108 -0
- package/src/adapters/claude-cli/usage-admission.ts +230 -0
- package/src/adapters/client-fingerprint.ts +24 -0
- package/src/adapters/coding-agent/protocol.ts +1 -1
- package/src/adapters/coding-agent/turn.ts +40 -11
- package/src/adapters/cursor/arg-codec.ts +17 -5
- package/src/adapters/cursor/catalog.ts +8 -0
- package/src/adapters/cursor/effort-map.ts +3 -0
- package/src/adapters/cursor/freeform-args.ts +75 -0
- package/src/adapters/cursor/protobuf-events.ts +36 -23
- package/src/adapters/dsh-account.ts +97 -0
- package/src/adapters/google-antigravity-wire.ts +22 -1
- package/src/adapters/google.ts +37 -10
- package/src/adapters/openai-chat/messages.ts +4 -3
- package/src/adapters/openai-chat/passthrough.ts +8 -2
- package/src/adapters/openai-chat/reasoning-replay.ts +52 -0
- package/src/adapters/openai-chat/response-events.ts +59 -1
- package/src/adapters/openai-chat.ts +8 -5
- package/src/adapters/openai-responses/compaction-search-history.ts +14 -7
- package/src/adapters/openai-responses/passthrough.ts +57 -125
- package/src/adapters/openai-responses/request-strips.ts +25 -3
- package/src/adapters/openai-responses/transport.ts +81 -0
- package/src/adapters/qoder/adapter.ts +44 -3
- package/src/adapters/registry.ts +5 -0
- package/src/adapters/zed.ts +26 -1
- package/src/advisor/activity.ts +55 -0
- package/src/advisor/budget.ts +62 -0
- package/src/advisor/consult.ts +223 -0
- package/src/advisor/context.ts +238 -0
- package/src/advisor/disclosure.ts +20 -0
- package/src/advisor/evidence-tool.ts +21 -0
- package/src/advisor/evidence.ts +117 -0
- package/src/advisor/runtime.ts +353 -0
- package/src/advisor/settings.ts +144 -0
- package/src/advisor/state.ts +369 -0
- package/src/advisor/synthetic-tool.ts +33 -0
- package/src/bridge/errors.ts +24 -1
- package/src/bridge/internal.ts +3 -1
- package/src/bridge/response-json.ts +18 -3
- package/src/bridge/sse.ts +58 -8
- package/src/bridge/terminal-refusal.ts +59 -0
- package/src/chat/inbound.ts +30 -6
- package/src/chat/outbound.ts +5 -0
- package/src/claude/desktop-3p-library.ts +72 -7
- package/src/claude/desktop-3p.ts +75 -19
- package/src/claude/desktop-first-party.ts +1 -1
- package/src/claude/desktop-picker-platform.ts +4 -0
- package/src/claude/desktop-picker-profile.ts +11 -4
- package/src/claude/desktop-picker.ts +15 -8
- package/src/claude/desktop-profile.ts +10 -1
- package/src/claude/desktop-remote-store-io.ts +5 -3
- package/src/claude/desktop-system-proxy.ts +50 -4
- package/src/claude/inbound-content-options.ts +11 -0
- package/src/claude/inbound.ts +154 -50
- package/src/claude/intercept/local-ca.ts +8 -1
- package/src/claude/intercept/picker-ca-startup.ts +2 -1
- package/src/claude/intercept/picker-runtime.ts +6 -5
- package/src/claude/intercept/picker-trust-windows.ts +338 -0
- package/src/claude/intercept/picker-trust.ts +19 -0
- package/src/claude/intercept/port-policy.ts +30 -0
- package/src/claude/intercept/runtime.ts +97 -94
- package/src/claude/model-default-settings.ts +154 -0
- package/src/claude/model-info.ts +7 -7
- package/src/claude/outbound.ts +51 -19
- package/src/cli/account-api.ts +1 -0
- package/src/cli/account-policy-dto.ts +6 -0
- package/src/cli/account-policy.ts +34 -5
- package/src/cli/account-preservation.ts +44 -0
- package/src/cli/account.ts +8 -2
- package/src/cli/advisor.ts +165 -0
- package/src/cli/auxiliary-listener-preflight.ts +37 -0
- package/src/cli/capabilities-accounts.ts +20 -1
- package/src/cli/capabilities-agents-routing.ts +23 -2
- package/src/cli/capabilities-base.ts +39 -11
- package/src/cli/capabilities-observe-system.ts +63 -3
- package/src/cli/capabilities-provider-models.ts +11 -0
- package/src/cli/chatgpt-command.ts +35 -14
- package/src/cli/claude.ts +46 -6
- package/src/cli/codex-cli-update.ts +151 -41
- package/src/cli/codex-provider.ts +44 -0
- package/src/cli/combo-input.ts +10 -1
- package/src/cli/combo-result.ts +1 -1
- package/src/cli/combo.ts +2 -1
- package/src/cli/cross-home-owner.ts +17 -14
- package/src/cli/dispatch.ts +30 -5
- package/src/cli/doctor.ts +15 -1
- package/src/cli/ensure-desktop-cold-start.ts +382 -0
- package/src/cli/export-command.ts +1 -1
- package/src/cli/help.ts +4 -2
- package/src/cli/index.ts +14 -5
- package/src/cli/integration-plan-dto.ts +3 -0
- package/src/cli/log-history.ts +172 -0
- package/src/cli/models-runtime-subcommands.ts +1 -0
- package/src/cli/models-runtime.ts +72 -8
- package/src/cli/observe-stream.ts +2 -0
- package/src/cli/observe.ts +16 -4
- package/src/cli/provider.ts +27 -5
- package/src/cli/registry.ts +41 -9
- package/src/cli/restart-scope.ts +3 -1
- package/src/cli/runtime-api.ts +5 -3
- package/src/cli/system-command.ts +40 -8
- package/src/cli/uninstall-client-state.ts +32 -0
- package/src/cli/usage-compare.ts +309 -0
- package/src/cli/usage-model-search.ts +4 -4
- package/src/cli/usage-report.ts +2 -2
- package/src/cli/v2.ts +1 -1
- package/src/client/machine-listener.ts +1 -3
- package/src/client/runtime.ts +1 -0
- package/src/clients/client-path.ts +51 -0
- package/src/clients/config-export/contracts.ts +3 -1
- package/src/clients/config-export/model-metadata.ts +3 -2
- package/src/clients/config-export/qoder.ts +93 -0
- package/src/clients/config-export.ts +35 -48
- package/src/clients/gentle-shell-path.ts +87 -0
- package/src/codex/account-auto-switch.ts +2 -0
- package/src/codex/account-identity.ts +29 -0
- package/src/codex/account-label.ts +1 -1
- package/src/codex/account-lifecycle.ts +21 -5
- package/src/codex/account-preservation.ts +28 -0
- package/src/codex/account-use-remaining.ts +23 -0
- package/src/codex/app-server-processes.ts +97 -7
- package/src/codex/app-server-restart-service.ts +55 -4
- package/src/codex/auth-api/account-list.ts +4 -0
- package/src/codex/auth-api/account-pause-group.ts +6 -50
- package/src/codex/auth-api/account-preservation.ts +57 -0
- package/src/codex/auth-api/pool-mode-gate.ts +5 -2
- package/src/codex/auth-api/routes.ts +8 -0
- package/src/codex/auth-api/use-remaining-route.ts +36 -0
- package/src/codex/auth-api.ts +0 -1
- package/src/codex/auth-context.ts +81 -7
- package/src/codex/autostart-health.ts +4 -0
- package/src/codex/catalog/auto-review.ts +20 -3
- package/src/codex/catalog/build-entries.ts +19 -2
- package/src/codex/catalog/combo-member.ts +14 -5
- package/src/codex/catalog/configured-tiers.ts +50 -0
- package/src/codex/catalog/effort.ts +4 -1
- package/src/codex/catalog/gather-capture.ts +2 -0
- package/src/codex/catalog/metadata.ts +11 -9
- package/src/codex/catalog/model-hints.ts +42 -19
- package/src/codex/catalog/model-visibility.ts +3 -1
- package/src/codex/catalog/native-ultrafast.ts +106 -0
- package/src/codex/catalog/parsing.ts +35 -86
- package/src/codex/catalog/provider-models.ts +40 -34
- package/src/codex/catalog/retained-sync.ts +2 -0
- package/src/codex/catalog/routed-gather.ts +33 -16
- package/src/codex/catalog/vendor-context.ts +82 -0
- package/src/codex/cli-install-provenance.ts +105 -17
- package/src/codex/cli-update-plan.ts +545 -0
- package/src/codex/config-write-lock.ts +63 -4
- package/src/codex/convergence.ts +2 -0
- package/src/codex/desktop-app/picker-freshness.ts +96 -0
- package/src/codex/desktop-app/types.ts +2 -0
- package/src/codex/desktop-app/windows.ts +29 -16
- package/src/codex/desktop-app-restart.ts +25 -2
- package/src/codex/desktop-compatibility/certificate-service.ts +99 -0
- package/src/codex/desktop-compatibility/certificate-store.ts +193 -0
- package/src/codex/desktop-compatibility/connection-store.ts +87 -0
- package/src/codex/desktop-compatibility/installed-build.ts +73 -0
- package/src/codex/desktop-compatibility/json-body.ts +29 -0
- package/src/codex/desktop-compatibility/native-identity.ts +62 -0
- package/src/codex/desktop-compatibility/relay-listener.ts +93 -0
- package/src/codex/desktop-compatibility/routing-binding.ts +10 -0
- package/src/codex/desktop-compatibility/routing-preflight.ts +69 -0
- package/src/codex/desktop-compatibility/runtime-ownership.ts +28 -0
- package/src/codex/desktop-compatibility/runtime.ts +182 -0
- package/src/codex/desktop-compatibility/service.ts +30 -0
- package/src/codex/desktop-compatibility/startup-settings.ts +50 -0
- package/src/codex/desktop-compatibility/usage-activation.ts +86 -0
- package/src/codex/desktop-compatibility/usage-controlled-fetch.ts +59 -0
- package/src/codex/desktop-compatibility/usage-controller.ts +107 -0
- package/src/codex/desktop-compatibility/usage-policy.ts +59 -0
- package/src/codex/desktop-compatibility/usage-refresh.ts +33 -0
- package/src/codex/desktop-compatibility/usage-sse-controller.ts +86 -0
- package/src/codex/desktop-compatibility/windows-activation-source.ts +44 -0
- package/src/codex/desktop-compatibility/windows-certificate-trust.ts +81 -0
- package/src/codex/desktop-compatibility/windows-key-protection.ts +165 -0
- package/src/codex/desktop-compatibility/windows-package-command.ts +86 -0
- package/src/codex/desktop-compatibility/windows-package-launch.ts +28 -0
- package/src/codex/features.ts +85 -45
- package/src/codex/history-provider.ts +1 -1
- package/src/codex/inject/config-write-section.ts +4 -1
- package/src/codex/inject/history-failure.ts +27 -0
- package/src/codex/inject/remove.ts +18 -6
- package/src/codex/inject/restore.ts +24 -2
- package/src/codex/inject/routing-classify.ts +4 -3
- package/src/codex/inject.ts +18 -27
- package/src/codex/journal.ts +16 -1
- package/src/codex/main-account-hard-lock.ts +30 -1
- package/src/codex/main-account.ts +99 -15
- package/src/codex/native-main-refresh-mode.ts +217 -0
- package/src/codex/native-profile-startup.ts +1 -1
- package/src/codex/ocx-compaction-history.ts +12 -10
- package/src/codex/paths.ts +86 -1
- package/src/codex/provider-routing.ts +174 -0
- package/src/codex/refresh.ts +2 -2
- package/src/codex/routing/health-store.ts +2 -2
- package/src/codex/routing/pool-recovery.ts +79 -0
- package/src/codex/routing/selection.ts +4 -3
- package/src/codex/routing/thread-affinity.ts +1 -1
- package/src/codex/shim-diagnostics.ts +6 -0
- package/src/codex/shim-overlay.ts +7 -2
- package/src/codex/signed-in-identity.ts +43 -0
- package/src/codex/subagent-model-fallback.ts +1 -1
- package/src/codex/sync.ts +6 -1
- package/src/codex/user-identity.ts +16 -5
- package/src/codex/windows-local-appdata.ts +84 -0
- package/src/combos/failover.ts +6 -1
- package/src/combos/index.ts +1 -0
- package/src/combos/resolve.ts +46 -10
- package/src/combos/types.ts +15 -0
- package/src/config/diagnostics.ts +35 -7
- package/src/config/live-reconcile.ts +51 -2
- package/src/config/load-degrade.ts +23 -1
- package/src/config/opencode-wire-upgrade.ts +54 -0
- package/src/config/opencode-zen-upgrade.ts +52 -0
- package/src/config/owner-registry.ts +22 -17
- package/src/config/paths.ts +10 -3
- package/src/config/provider-validation.ts +45 -2
- package/src/config/schema/config-schema.ts +39 -0
- package/src/config/schema/desktop-compatibility.ts +9 -0
- package/src/config/schema/leaf-validators.ts +39 -9
- package/src/config/schema/main-account-hard-lock-fallback.ts +26 -0
- package/src/config/schema/native-reasoning-retention.ts +26 -0
- package/src/config.ts +2 -0
- package/src/generated/compatibility-version.json +962 -350
- package/src/generated/model-metadata.ts +1 -1
- package/src/grok/sync.ts +1 -1
- package/src/images/loop.ts +46 -8
- package/src/integrations/catalog-refresh.ts +1 -1
- package/src/integrations/config-io.ts +20 -2
- package/src/integrations/journal.ts +15 -1
- package/src/integrations/mutation-plan.ts +2 -0
- package/src/integrations/registry.ts +15 -0
- package/src/integrations/store.ts +3 -0
- package/src/integrations/writer.ts +10 -1
- package/src/lib/advisor-activation.ts +16 -0
- package/src/lib/background-work.ts +65 -0
- package/src/lib/bounded-file-read.ts +58 -0
- package/src/lib/bun-path-runtime.d.mts +10 -1
- package/src/lib/bun-path-runtime.mjs +62 -3
- package/src/lib/codex-restart-contract.ts +15 -0
- package/src/lib/desktop-proxy-route.ts +30 -0
- package/src/lib/desktop-upstream-tunnel.ts +72 -0
- package/src/lib/empty-tool-catalog.ts +62 -0
- package/src/lib/errors.ts +26 -3
- package/src/lib/gcp-adc.ts +96 -9
- package/src/lib/gcp-credential-input.ts +12 -0
- package/src/lib/lab-live-route-production.ts +5 -0
- package/src/lib/local-internal-call-capability.ts +55 -0
- package/src/lib/opaque-proxy-tunnel.ts +217 -0
- package/src/lib/package-tree-integrity.ts +2 -2
- package/src/lib/redact.ts +2 -2
- package/src/lib/socks5-fetch.ts +48 -71
- package/src/lib/socks5-handshake.ts +112 -0
- package/src/lib/translator-budget.ts +7 -1
- package/src/oauth/account-quota-rank.ts +69 -2
- package/src/oauth/anthropic-account-refusal.ts +20 -2
- package/src/oauth/anthropic-oauth-definitions.ts +3 -1
- package/src/oauth/anthropic-routing.ts +1 -21
- package/src/oauth/anthropic.ts +38 -7
- package/src/oauth/callback-server.ts +27 -1
- package/src/oauth/chatgpt-device.ts +1 -1
- package/src/oauth/chatgpt-shared.ts +83 -0
- package/src/oauth/chatgpt.ts +8 -72
- package/src/oauth/dsh.ts +203 -0
- package/src/oauth/generic-account-failover.ts +62 -12
- package/src/oauth/generic-session-affinity.ts +125 -0
- package/src/oauth/index.ts +188 -111
- package/src/oauth/kiro-device-login.ts +2 -1
- package/src/oauth/kiro.ts +7 -1
- package/src/oauth/local-token-detect.ts +21 -1
- package/src/oauth/login-cli-errors.ts +44 -0
- package/src/oauth/login-cli.ts +69 -7
- package/src/oauth/login-flow-state.ts +371 -23
- package/src/oauth/meta-muse-errors.ts +41 -0
- package/src/oauth/meta-muse-keychain.ts +52 -0
- package/src/oauth/meta-muse.ts +51 -84
- package/src/oauth/model-discovery-auth.ts +3 -0
- package/src/oauth/pool-settings-capability.ts +4 -2
- package/src/oauth/refresh-flight-retirement.ts +48 -0
- package/src/oauth/session-affinity-key.ts +23 -0
- package/src/oauth/store-anthropic-instance.ts +9 -2
- package/src/oauth/store.ts +12 -5
- package/src/protocols/codecs/chat-ir.ts +467 -0
- package/src/protocols/codecs/chat.ts +10 -1
- package/src/protocols/codecs/messages-ir.ts +500 -0
- package/src/protocols/encoders/adapter-events.ts +5 -4
- package/src/protocols/encoders/messages.ts +9 -6
- package/src/protocols/features.ts +10 -2
- package/src/protocols/path.ts +11 -1
- package/src/protocols/plan-snapshot.ts +39 -16
- package/src/protocols/plan.ts +9 -1
- package/src/protocols/provider-summary.ts +2 -1
- package/src/protocols/settings.ts +8 -0
- package/src/providers/antigravity-account-roster.ts +102 -0
- package/src/providers/antigravity-models.ts +85 -7
- package/src/providers/api-key-cooldowns.ts +49 -0
- package/src/providers/api-key-resolve.ts +11 -6
- package/src/providers/api-key-response-ownership.ts +57 -0
- package/src/providers/api-key-selection.ts +31 -6
- package/src/providers/api-keys.ts +214 -3
- package/src/providers/claude-cli-usage.ts +96 -0
- package/src/providers/dsh-account-destination.ts +31 -0
- package/src/providers/dsh-account-models.ts +41 -0
- package/src/providers/gcp-credential-cleanup.ts +59 -0
- package/src/providers/key-failover.ts +54 -50
- package/src/providers/key-store.ts +7 -2
- package/src/providers/model-rename-fields.ts +5 -0
- package/src/providers/model-rename-migration.ts +7 -5
- package/src/providers/openai-tiers-destination.ts +11 -2
- package/src/providers/openai-tiers.ts +5 -12
- package/src/providers/opencode-go-transport.ts +3 -1
- package/src/providers/quota/account-cache.ts +6 -5
- package/src/providers/quota/account-row.ts +34 -0
- package/src/providers/quota/antigravity.ts +28 -7
- package/src/providers/quota/dsh-account.ts +70 -0
- package/src/providers/quota/vendor-probes-oauth.ts +1 -93
- package/src/providers/quota-types.ts +2 -0
- package/src/providers/quota.ts +14 -20
- package/src/providers/registry/entries-core.ts +44 -14
- package/src/providers/registry/entries-extended.ts +19 -0
- package/src/providers/registry/types.ts +1 -1
- package/src/providers/request-pacing.ts +77 -19
- package/src/providers/routed-config.ts +339 -0
- package/src/providers/service-tier.ts +2 -1
- package/src/quota/window-mapping.ts +5 -2
- package/src/responses/anthropic-progress.ts +34 -0
- package/src/responses/assistant-replay.ts +35 -0
- package/src/responses/compaction-history-framing.ts +65 -0
- package/src/responses/compaction.ts +6 -1
- package/src/responses/incomplete-reason.ts +31 -0
- package/src/responses/parser.ts +78 -22
- package/src/responses/reasoning-envelope.ts +4 -0
- package/src/responses/reasoning-replay-cache.ts +24 -2
- package/src/responses/reasoning-retention.ts +173 -0
- package/src/responses/retained-compaction.ts +46 -0
- package/src/responses/schema.ts +23 -0
- package/src/responses/state.ts +32 -29
- package/src/router.ts +8 -321
- package/src/routing/health.ts +37 -22
- package/src/routing/history/build-file.ts +92 -0
- package/src/routing/history/indexer.ts +254 -221
- package/src/routing/history/ingest.ts +242 -0
- package/src/routing/history/rebuild-job.ts +111 -0
- package/src/routing/history/rebuild-protocol.ts +15 -0
- package/src/routing/history/rebuild-worker.ts +34 -0
- package/src/routing/profile.ts +1 -1
- package/src/server/admission-model-scope.ts +21 -1
- package/src/server/antigravity-direct-eligibility.ts +208 -0
- package/src/server/auth-cors.ts +15 -0
- package/src/server/chat-completions.ts +82 -10
- package/src/server/chat-native-reasoning.ts +123 -0
- package/src/server/chat-native-sse.ts +110 -7
- package/src/server/chat-native.ts +76 -17
- package/src/server/claude-messages.ts +164 -433
- package/src/server/effort-policy.ts +1 -1
- package/src/server/images.ts +15 -2
- package/src/server/index/desktop-compatibility-startup.ts +56 -0
- package/src/server/index/model-alias-id.ts +36 -0
- package/src/server/index/optional-listeners.ts +2 -0
- package/src/server/index/serve-options.ts +11 -3
- package/src/server/index/startup-warnings.ts +11 -0
- package/src/server/index/websocket-handler.ts +9 -0
- package/src/server/index.ts +14 -11
- package/src/server/inference/advisor-diagnostics.ts +31 -0
- package/src/server/inference/client-encoder-delivery.ts +6 -5
- package/src/server/login-shell-path.ts +146 -0
- package/src/server/management/advisor-routes.ts +202 -0
- package/src/server/management/agent-settings-routes.ts +22 -4
- package/src/server/management/claude-desktop-picker-routes.ts +1 -1
- package/src/server/management/combo-routes.ts +176 -50
- package/src/server/management/companion-routes.ts +4 -0
- package/src/server/management/config-routes.ts +77 -6
- package/src/server/management/context.ts +4 -0
- package/src/server/management/cursor-integration-routes.ts +1 -1
- package/src/server/management/desktop-compatibility-routes.ts +46 -0
- package/src/server/management/desktop-compatibility-runtime-routes.ts +46 -0
- package/src/server/management/desktop-compatibility-settings-routes.ts +27 -0
- package/src/server/management/model-routes.ts +13 -8
- package/src/server/management/model-rows.ts +14 -0
- package/src/server/management/native-integration-routes.ts +2 -7
- package/src/server/management/native-reasoning-retention-routes.ts +41 -0
- package/src/server/management/oauth-account-routes.ts +87 -14
- package/src/server/management/protocol-settings-patch.ts +1 -0
- package/src/server/management/provider-gcp-credential-routes.ts +29 -0
- package/src/server/management/provider-key-pacing-routes.ts +31 -0
- package/src/server/management/provider-overwrite-carry.ts +7 -0
- package/src/server/management/provider-routes.ts +25 -30
- package/src/server/management/route-registry.ts +21 -1
- package/src/server/management/sibling-guard.ts +1 -0
- package/src/server/management-api.ts +9 -1
- package/src/server/messages-antigravity-direct.ts +195 -0
- package/src/server/messages-native-tool-guard.ts +185 -0
- package/src/server/messages-native.ts +106 -22
- package/src/server/messages-shared.ts +431 -0
- package/src/server/relay.ts +1 -1
- package/src/server/request-log-terminal-status.ts +1 -1
- package/src/server/request-log.ts +13 -1
- package/src/server/responses/account-change-state.ts +8 -2
- package/src/server/responses/adapter-continuation.ts +48 -19
- package/src/server/responses/adapter-delivery.ts +43 -8
- package/src/server/responses/adapter-dispatch.ts +48 -4
- package/src/server/responses/advisor-plan-slot.ts +27 -0
- package/src/server/responses/advisor-retention.ts +117 -0
- package/src/server/responses/advisor-slot.ts +368 -0
- package/src/server/responses/code-mode-collab-surface.ts +116 -8
- package/src/server/responses/codex-ws-wire.ts +15 -8
- package/src/server/responses/compact.ts +303 -125
- package/src/server/responses/compaction-recovery.ts +18 -10
- package/src/server/responses/compaction-retention.ts +61 -0
- package/src/server/responses/context-overflow.ts +11 -6
- package/src/server/responses/core-auth.ts +6 -0
- package/src/server/responses/core-codex-account.ts +11 -1
- package/src/server/responses/core-combo-failure.ts +12 -1
- package/src/server/responses/core-combo.ts +141 -36
- package/src/server/responses/core-errors.ts +3 -3
- package/src/server/responses/core-lifetime.ts +7 -2
- package/src/server/responses/core-normalize.ts +11 -0
- package/src/server/responses/core-opaque-recovery.ts +35 -0
- package/src/server/responses/core-options.ts +51 -0
- package/src/server/responses/core-pipeline.ts +141 -0
- package/src/server/responses/core-replay.ts +25 -6
- package/src/server/responses/core.ts +3 -116
- package/src/server/responses/fetch-helpers.ts +73 -19
- package/src/server/responses/main-hard-lock-routing.ts +109 -0
- package/src/server/responses/native-response-control.ts +4 -2
- package/src/server/responses/passthrough-delivery.ts +19 -11
- package/src/server/responses/passthrough-dispatch.ts +29 -16
- package/src/server/responses/request-prepare.ts +144 -17
- package/src/server/responses/request-sidecar-auth.ts +2 -2
- package/src/server/responses/request-transport.ts +120 -27
- package/src/server/responses/response-effects.ts +1 -0
- package/src/server/responses/run-turn-execution.ts +166 -38
- package/src/server/responses/sidecar-execution.ts +98 -5
- package/src/server/responses/terminal-guard.ts +4 -17
- package/src/server/responses-undeclared-tool-guard.ts +30 -9
- package/src/server/startup-action-control.ts +16 -2
- package/src/server/startup-health-cache.ts +1 -0
- package/src/service/auth-preflight.ts +71 -0
- package/src/service/cli.ts +4 -2
- package/src/service/definition.ts +97 -0
- package/src/service/desktop-startup.ts +14 -0
- package/src/service/guards.ts +1 -61
- package/src/service/health-sentinel-linux.ts +112 -0
- package/src/service/health-sentinel-main.ts +99 -61
- package/src/service/health-sentinel-probe.ts +24 -7
- package/src/service/health.ts +5 -89
- package/src/service/launchd.ts +27 -7
- package/src/service/logging.ts +135 -0
- package/src/service/repair.ts +2 -1
- package/src/service/state.ts +7 -8
- package/src/service/systemd.ts +1 -1
- package/src/service/windows-guarded-manager.ts +2 -1
- package/src/service/windows-ops.ts +1 -1
- package/src/service/windows-scheduler.ts +2 -7
- package/src/service/windows-taskxml.ts +2 -2
- package/src/service/windows-wscript.ts +14 -0
- package/src/service.ts +4 -2
- package/src/sidecar/auth.ts +2 -0
- package/src/tray/windows-tray.ps1 +43 -24
- package/src/types/config.ts +124 -6
- package/src/types/opencode-go.ts +61 -0
- package/src/types/opencode-zen.ts +29 -0
- package/src/types/provider.ts +39 -6
- package/src/types/request.ts +38 -2
- package/src/types/tools.ts +2 -0
- package/src/types/wire.ts +29 -37
- package/src/types.ts +1 -0
- package/src/update/async-check.ts +1 -1
- package/src/update/badge.ts +2 -2
- package/src/update/index.ts +88 -15
- package/src/update/job-supervised-restart.ts +107 -0
- package/src/update/job.ts +32 -32
- package/src/update/notify.ts +1 -1
- package/src/update/npm-invocation.mjs +12 -2
- package/src/update/refresh-scheduler.ts +2 -2
- package/src/update/supervised-recovery.d.mts +27 -0
- package/src/update/supervised-recovery.mjs +157 -0
- package/src/usage/cache-diagnostic.ts +2 -0
- package/src/usage/cost.ts +48 -12
- package/src/usage/expected-prices.ts +15 -0
- package/src/usage/ledger-retention.ts +2 -1
- package/src/usage/ledger-scanner.ts +6 -5
- package/src/usage/log.ts +17 -8
- package/src/usage/summary.ts +22 -9
- package/src/usage/user-cost-overlays.ts +14 -19
- package/src/usage/user-cost-validation.ts +38 -0
- package/src/vision/eligibility.ts +13 -0
- package/src/web-search/gemini-executor.ts +2 -2
- package/src/web-search/loop.ts +55 -5
- package/src/web-search/progress-stream.ts +4 -1
- package/src/web-search/run-turn-loop.ts +9 -1
- package/assets/sponsors/packycode.png +0 -0
- package/gui/dist/assets/App-CSJvmjNs.css +0 -1
- package/gui/dist/assets/App-CZtqiGcw.js +0 -56
- package/gui/dist/assets/index-BB6uK6tU.css +0 -1
- package/gui/dist/assets/index-CTm4l-HQ.js +0 -94
- package/gui/dist/assets/quota-summary-BbEeRfPY.js +0 -1
|
@@ -25,6 +25,27 @@ export const AGENT_ROUTING_CAPABILITIES: readonly Capability[] = [
|
|
|
25
25
|
"queued means submitted, not processed. unknown must not be replayed; no automatic retry, daemon start or thread resume.",
|
|
26
26
|
"Exit 0: queued; 1: not sent; 3: unknown; 64: invalid usage. No remote/Claude transport or skill installation."],
|
|
27
27
|
},
|
|
28
|
+
{
|
|
29
|
+
command: ["advisor"],
|
|
30
|
+
summary: "Inspect and configure the advisor sidecar (expert consultation for routed workers).",
|
|
31
|
+
routes: [
|
|
32
|
+
{ method: "GET", path: "/api/advisor/settings" },
|
|
33
|
+
{ method: "GET", path: "/api/advisor/activity" },
|
|
34
|
+
{ method: "PUT", path: "/api/advisor/settings" },
|
|
35
|
+
],
|
|
36
|
+
flags: [{ name: "--json", value: "boolean", summary: "Emit advisor settings as JSON." }],
|
|
37
|
+
mutates: true,
|
|
38
|
+
json: "payload",
|
|
39
|
+
details: [
|
|
40
|
+
"`status` (the default) reads the resolved settings; `on`/`off` toggle the sidecar; `consent` records or revokes context-sharing consent; `set` updates model, effort, policy, or timeout.",
|
|
41
|
+
"`on` does not grant consent. Without current consent it refuses and prints the disclosure. `on --ack-context-sharing` records consent v1 and enables. `consent --revoke` removes consent and stops task-context transfer.",
|
|
42
|
+
"The advisor model may be any routable model string: a bare native model, an explicit `provider/model`, or an account-qualified native model.",
|
|
43
|
+
"`policy: preflight` makes OpenCodex attempt one automatic consultation per task with a stable conversation identity once the task shows orientation evidence (an assistant tool call or a tool result after the latest user message). Without a stable identity, each eligible request may trigger another consultation. `policy: manual` consults only when the worker calls the synthetic `advisor` tool. Neither path sends task context without current context-sharing consent.",
|
|
44
|
+
"`policy: adaptive` adds evidence-based failed-repair consultation after the same validation fails, a file edit completes, and validation fails again. Automatic calls require a stable conversation identity. `set --max-consultations <1-3>` caps adaptive task attempts, including manual calls, in a durable 24-hour budget. No semantic stuck detection is claimed.",
|
|
45
|
+
"`activity` reads up to 100 recent consultation metadata records (trigger, status, models, requested and mapped effort, duration, reported tokens); no task or advice content is retained. Records are process-local and expire after 24 hours. Missing mapped effort means unreported, not successful application.",
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
|
|
28
49
|
{
|
|
29
50
|
command: ["agent", "status"],
|
|
30
51
|
usage: "ocx agent status [--json]",
|
|
@@ -277,10 +298,10 @@ export const AGENT_ROUTING_CAPABILITIES: readonly Capability[] = [
|
|
|
277
298
|
},
|
|
278
299
|
{
|
|
279
300
|
command: ["combo","set"],
|
|
280
|
-
usage: "ocx combo set <id> [--targets <provider/model[:weight],...> | --targets-file <FILE|->] [--strategy <failover|round-robin|random|least-used|reset-window|jev>] [--sticky <1-100|->] [--effort <low|medium|high|xhigh|max|ultra|->] [--effort-mode <fallback|force|->] [--alias <name|->] [--native-alias [on|off]] [--display-name <label|->] [--decision-provider <provider|-> | --decision-model <route|->] [--decision-timeout <ms|->] [--rename-from <id>] [--image-input <auto|disabled>] [--reasoning-effort-mode <strict|adaptive>] [--json]",
|
|
301
|
+
usage: "ocx combo set <id> [--targets <provider/model[:weight],...> | --targets-file <FILE|->] [--strategy <failover|round-robin|random|least-used|reset-window|jev>] [--sticky <1-100|->] [--effort <low|medium|high|xhigh|max|ultra|->] [--effort-mode <fallback|force|->] [--alias <name|->] [--native-alias [on|off]] [--allow-metered-targets <on|off>] [--display-name <label|->] [--decision-provider <provider|-> | --decision-model <route|->] [--decision-timeout <ms|->] [--rename-from <id>] [--image-input <auto|disabled>] [--reasoning-effort-mode <strict|adaptive>] [--json]",
|
|
281
302
|
summary: "Create, update or rename a combo.",
|
|
282
303
|
routes: [{"method":"GET","path":"/api/combos"},{"method":"PUT","path":"/api/combos"}],
|
|
283
|
-
flags: [{"name":"--targets","value":"string","summary":"Ordered provider/model[:weight] list; required for creation."},{"name":"--strategy","value":"string","summary":"Routing strategy."},{"name":"--sticky","value":"string","summary":"Round-robin limit 1-100; - resets."},{"name":"--effort","value":"string","summary":"Default effort; - clears."},{"name":"--effort-mode","value":"string","summary":"fallback or force; - resets to fallback."},{"name":"--alias","value":"string","summary":"Alias; - clears."},{"name":"--display-name","value":"string","summary":"Label; - clears."},{"name":"--decision-provider","value":"string","summary":"JEV provider; - clears."},{"name":"--decision-model","value":"string","summary":"JEV route; - clears; exclusive with provider."},{"name":"--decision-timeout","value":"string","summary":"JEV deadline 1000-120000 ms; - clears."},{"name":"--rename-from","value":"string","summary":"Existing combo ID to rename."},{"name":"--json","value":"boolean","summary":"Emit structured JSON."},{"name":"--native-alias","value":"string","summary":"Bare legacy flag means on; explicit on/off preserves presence, including false."},{"name":"--targets-file","value":"string","summary":"Bounded ordered target JSON array, exclusive with --targets; preserves effort/profile/last-resort metadata."},{"name":"--image-input","value":"string","summary":"auto or disabled; explicit auto clears the previous disabled choice."},{"name":"--reasoning-effort-mode","value":"string","summary":"strict or adaptive, distinct from --effort-mode fallback/force."}],
|
|
304
|
+
flags: [{"name":"--allow-metered-targets","value":"string","summary":"on grants operator consent to metered targets only on a loopback-only proxy; off clears it."},{"name":"--targets","value":"string","summary":"Ordered provider/model[:weight] list; required for creation."},{"name":"--strategy","value":"string","summary":"Routing strategy."},{"name":"--sticky","value":"string","summary":"Round-robin limit 1-100; - resets."},{"name":"--effort","value":"string","summary":"Default effort; - clears."},{"name":"--effort-mode","value":"string","summary":"fallback or force; - resets to fallback."},{"name":"--alias","value":"string","summary":"Alias; - clears."},{"name":"--display-name","value":"string","summary":"Label; - clears."},{"name":"--decision-provider","value":"string","summary":"JEV provider; - clears."},{"name":"--decision-model","value":"string","summary":"JEV route; - clears; exclusive with provider."},{"name":"--decision-timeout","value":"string","summary":"JEV deadline 1000-120000 ms; - clears."},{"name":"--rename-from","value":"string","summary":"Existing combo ID to rename."},{"name":"--json","value":"boolean","summary":"Emit structured JSON."},{"name":"--native-alias","value":"string","summary":"Bare legacy flag means on; explicit on/off preserves presence, including false."},{"name":"--targets-file","value":"string","summary":"Bounded ordered target JSON array, exclusive with --targets; preserves effort/profile/last-resort metadata."},{"name":"--image-input","value":"string","summary":"auto or disabled; explicit auto clears the previous disabled choice."},{"name":"--reasoning-effort-mode","value":"string","summary":"strict or adaptive, distinct from --effort-mode fallback/force."}],
|
|
284
305
|
mutates: true,
|
|
285
306
|
json: "payload",
|
|
286
307
|
details: ["create and update are aliases of set. Existing fields are read before writing; --targets replaces targets.","force overrides valid client effort and may increase cost and latency.","Only the implemented target grammar is supported; full GUI target metadata and routing-profile writes are separate tasks.","New file/flag conflicts refuse before transport. Partial edits preserve target metadata; explicit false/default values override server carry. Turning a native alias off may also require clearing its incompatible alias.","Read/merge/write uses one target and remains an upsert without revision CAS. Saved-but-incomplete catalog outcomes return nonzero with their receipt."],
|
|
@@ -19,6 +19,15 @@ export const HEAD_CAPABILITIES: readonly HeadCapability[] = [
|
|
|
19
19
|
* A capability must not name a route the command does not actually fetch.
|
|
20
20
|
*/
|
|
21
21
|
export const CAPABILITIES: readonly Capability[] = [
|
|
22
|
+
{
|
|
23
|
+
command: ["codex-provider"],
|
|
24
|
+
bannerLines: ["ocx codex-provider <sub> Confirm custom Codex provider routing: status|allow|revoke"],
|
|
25
|
+
summary: "Inspect, allow or revoke custom Codex provider routing consent.",
|
|
26
|
+
routes: [], flags: [{ name: "--yes", value: "boolean", summary: "Explicitly approve the named provider without an interactive prompt." }],
|
|
27
|
+
mutates: true, json: "none",
|
|
28
|
+
usage: "ocx codex-provider <status|allow <id> [--yes]|revoke <id>>",
|
|
29
|
+
details: ["Only local loopback routing for Responses providers using OpenAI authentication is supported. No custom credentials/headers, authless mode or client compaction. Unapproved providers are never changed."],
|
|
30
|
+
},
|
|
22
31
|
{
|
|
23
32
|
command: ["chatgpt"],
|
|
24
33
|
summary: "Experimental ChatGPT app-server shim: launch, restore or status (macOS only).",
|
|
@@ -326,7 +335,7 @@ export const CAPABILITIES: readonly Capability[] = [
|
|
|
326
335
|
flags: [{"name":"--range","value":"string","summary":"today | 1d | 7d | 30d | all; default 30d."},{"name":"--surface","value":"string","summary":"all | codex | claude | grok; default all."},{"name":"--since","value":"string","summary":"Inclusive epoch milliseconds or ISO datetime with timezone; requires --until."},{"name":"--until","value":"string","summary":"Inclusive end; requires --since. Custom bounds override --range."},{"name":"--provider","value":"string","summary":"Filter provider."},{"name":"--model","value":"string","summary":"Filter model."},{"name":"--json","value":"boolean","summary":"Emit the result as JSON."},{"name":"--api-key-id","value":"string","summary":"Exact nonblank management key scope; connected clients refuse this before reading their enrolled key."},{"name":"--search","value":"string","summary":"Model-row substring view over model/provider/resolvedModel; top100 by tokens. Whole-report totals stay unchanged."}],
|
|
327
336
|
mutates: false,
|
|
328
337
|
json: "payload",
|
|
329
|
-
details: ["Alias of observe usage. Connected clients read only their enrolled-key Hub report through /v1/usage; caller --api-key-id is refused before key read/transport and never grants management authority.","Nonclient --api-key-id uses /api/usage and requires matching filter acknowledgment. An unknown acknowledged key is empty/matched:false, not404. Custom-window acknowledgment remains required.","--search filters only returned model rows after scope acknowledgment. Blank search selects the top100 model rows; modelView reports match/return counts without recomputing totals."],
|
|
338
|
+
details: ["Alias of observe usage. Connected clients read only their enrolled-key Hub report through /v1/usage; caller --api-key-id is refused before key read/transport and never grants management authority.","Nonclient --api-key-id uses /api/usage and requires matching filter acknowledgment. An unknown acknowledged key is empty/matched:false, not404. Custom-window acknowledgment remains required.","--search filters only returned model rows after scope acknowledgment. Blank search selects the top100 model rows; modelView reports match/return counts without recomputing totals.","Nested compare reads the named range and the previous equal window; --range all is refused."],
|
|
330
339
|
usage: "ocx usage [--range <today|1d|7d|30d|all>] [--surface <all|codex|claude|grok>] [--since <epoch-ms|ISO-datetime>] [--until <epoch-ms|ISO-datetime>] [--provider <name>] [--model <id>] [--api-key-id <id>] [--search <text>] [--json]",
|
|
331
340
|
},
|
|
332
341
|
{
|
|
@@ -406,7 +415,7 @@ export const CAPABILITIES: readonly Capability[] = [
|
|
|
406
415
|
flags: [{"name":"--provider","value":"string","summary":"Filter provider, including failover attempts."},{"name":"--model","value":"string","summary":"Filter model, including failover attempts."},{"name":"--status","value":"string","summary":"Filter status code."},{"name":"--conversation","value":"string","summary":"Filter conversation ID."},{"name":"--conversationId","value":"string","summary":"Alias of --conversation."},{"name":"--account","value":"string","summary":"Filter stable account log label."},{"name":"--limit","value":"number","summary":"Positive row limit; default 200."},{"name":"--follow","value":"boolean","summary":"Poll for new rows; add --jsonl to emit JSONL."},{"name":"-f","value":"boolean","summary":"Alias of --follow."},{"name":"--json","value":"boolean","summary":"Emit the result as JSON."},{"name":"--jsonl","value":"boolean","summary":"Emit one row per JSON line; exclusive with --json."},{"name":"--events","value":"boolean","summary":"Versioned snapshot/append JSONL; requires --follow, conflicts with --json. Redundant --jsonl is accepted."}],
|
|
407
416
|
mutates: false,
|
|
408
417
|
json: "payload",
|
|
409
|
-
details: ["Follow uses the server cursor and a bounded ordered window, preserving same-ID amendments and repeated row occurrences. It never enables logging.","--events emits version1 snapshots/appends with cursor and limit for observed-window reconstruction. Legacy row JSONL cannot express removals or resets exactly; neither mode promises lossless history between polls.","Follow limit is1–2000, default200. Polling is serial and cancellable; SIGINT exits130 and SIGTERM143. Malformed/oversized/unavailable responses stop without a fabricated empty snapshot or retry.","Nested explain reads recorded decisions; rebuild-index and index-status touch the local derived index and retain separate declarations."],
|
|
418
|
+
details: ["Follow uses the server cursor and a bounded ordered window, preserving same-ID amendments and repeated row occurrences. It never enables logging.","--events emits version1 snapshots/appends with cursor and limit for observed-window reconstruction. Legacy row JSONL cannot express removals or resets exactly; neither mode promises lossless history between polls.","Follow limit is1–2000, default200. Polling is serial and cancellable; SIGINT exits130 and SIGTERM143. Malformed/oversized/unavailable responses stop without a fabricated empty snapshot or retry.","Nested history pages the derived index and get reads one canonical row; explain reads recorded decisions; rebuild-index and index-status touch the local derived index and retain separate declarations."],
|
|
410
419
|
usage: "ocx logs [--provider <name>] [--model <id>] [--status <code>] [--conversation <id>] [--account <label>] [--limit <n>] [--follow] [--json|--jsonl]; ocx logs --follow --events [--limit <1-2000>]",
|
|
411
420
|
},
|
|
412
421
|
{
|
|
@@ -556,7 +565,7 @@ export const CAPABILITIES: readonly Capability[] = [
|
|
|
556
565
|
flags: [{"name":"--json","value":"boolean","summary":"Emit the redacted provenance report as JSON."}],
|
|
557
566
|
mutates: false,
|
|
558
567
|
json: "envelope",
|
|
559
|
-
details: ["Proof-bound published-launcher context authenticates the configured candidate snapshot, not successful Codex execution; this check
|
|
568
|
+
details: ["Proof-bound published-launcher context authenticates the configured candidate snapshot, not successful Codex execution; the selection is attested only when the runtime resolver picks the same canonical path, and even then this check reports rather than admits a runtime.","On Windows this first slice performs no candidate or configuration filesystem I/O: only a proof-captured absolute environment candidate can receive lexical app-bundle or version-manager labels; every other Windows candidate fails closed.","Makes no package-registry request.","Does not execute Codex or npm, install or repair software, control a process, or write configuration or cache state."],
|
|
560
569
|
usage: "ocx system codex-cli-update check [--json]",
|
|
561
570
|
},
|
|
562
571
|
{
|
|
@@ -569,14 +578,33 @@ export const CAPABILITIES: readonly Capability[] = [
|
|
|
569
578
|
details: ["Opt-in Windows x64 local-volume inspection using held native file handles; refuses reparse points, active writers and unsupported layouts.","Without explicit paths, the proof-bound launcher snapshot identifies the selected candidate: the configured CODEX_CLI_PATH or the first codex on the captured PATH, with an OpenCodex wrapper resolving to its codex.opencodex-real backing. Discovery only proposes paths; the held-handle observation remains the authority.","Success binds observed file identities and bytes, not selected-runtime admission or installer ownership.","selectionAttested, managed and applyAllowed remain false. The digest is an observation, not a durable update permit.","Does not run the named Codex/npm/Node files, query a registry, install software, control processes or persist state."],
|
|
570
579
|
usage: "ocx system codex-cli-update attest [--candidate <absolute-path> --npm-prefix <absolute-path> --npm-cli <absolute-path> --node <absolute-path>] [--json]",
|
|
571
580
|
},
|
|
581
|
+
{
|
|
582
|
+
command: ["system", "codex-cli-update", "plan"],
|
|
583
|
+
summary: "Dry-run a Codex CLI update and print the plan id binding the decision's evidence.",
|
|
584
|
+
routes: [],
|
|
585
|
+
flags: [
|
|
586
|
+
{ name: "--channel", value: "string", summary: "Registry channel to resolve. Only the stable latest channel is offered." },
|
|
587
|
+
{ name: "--json", value: "boolean", summary: "Emit the plan as JSON." },
|
|
588
|
+
],
|
|
589
|
+
mutates: false,
|
|
590
|
+
json: "envelope",
|
|
591
|
+
details: [
|
|
592
|
+
"Adds the three inputs check leaves out: an exact registry version with its sha512 integrity, a fail-closed process-table read, and a decision.",
|
|
593
|
+
"The registry evidence is pinned to the official npm registry with project/user npm configuration isolated, so a redirected .npmrc cannot supply the answer.",
|
|
594
|
+
"Installs nothing and mutates no application state; registry evidence is gathered under an isolated temporary npm root (npmrc, cwd, cache and logs) removed best-effort afterwards. A refusal is a normal dry-run answer and still exits 0.",
|
|
595
|
+
"The plan id is a digest of the evidence the decision rests on — ownership, the installed version, a digest of the canonical install root, the resolved target — not a stored job. There is no plan state on disk to expire, collide or clean up.",
|
|
596
|
+
"An unreadable process table refuses rather than reading as no live session.",
|
|
597
|
+
],
|
|
598
|
+
usage: "ocx system codex-cli-update plan [--channel latest] [--json]",
|
|
599
|
+
},
|
|
572
600
|
{
|
|
573
601
|
command: ["system","codex-restart"],
|
|
574
|
-
summary: "Restart the Codex desktop app
|
|
602
|
+
summary: "Restart the Codex app-servers, and the desktop app when its model picker predates the catalog.",
|
|
575
603
|
routes: [{"method":"POST","path":"/api/system/codex-restart"}],
|
|
576
|
-
flags: [{"name":"--yes","value":"boolean","summary":"Required: fully quits and relaunches the operator's Codex desktop app, which may discard unsaved composer drafts, model-picker selections, and pending approval prompts
|
|
604
|
+
flags: [{"name":"--yes","value":"boolean","summary":"Required: restarts the Codex app-servers, interrupting running turns, and fully quits and relaunches the operator's Codex desktop app when its model picker predates the current catalog or that cannot be determined, which may discard unsaved composer drafts, model-picker selections, and pending approval prompts."},{"name":"--json","value":"boolean","summary":"Emit the restart result as JSON."}],
|
|
577
605
|
mutates: true,
|
|
578
606
|
json: "payload",
|
|
579
|
-
details: ["`sync --restart-codex` is not a substitute: it restarts only as a side effect after a catalog or
|
|
607
|
+
details: ["`sync --restart-codex` is not a substitute: it restarts only as a side effect after a catalog, cache, or changed configuration write, so it cannot restart a healthy install on request.","Restarts the app-servers through the same module the CLI uses. The desktop app is quit and relaunched when its model picker predates the current catalog or this request changes the `model_catalog_json` binding, because the picker is built at launch; otherwise it is left running and respawns its own app-server, keeping unsaved client state. An unreadable desktop or catalog state falls back to the full restart. When the proxy itself runs inside the Codex app the desktop restart is refused, because restarting the app would kill the request.","--yes is mandatory because this interrupts a running editor session and may discard unsaved composer drafts, model-picker selections, and pending approval prompts; it must never happen because an agent guessed a subcommand."],
|
|
580
608
|
usage: "ocx system codex-restart --yes [--json]",
|
|
581
609
|
},
|
|
582
610
|
{
|
|
@@ -646,7 +674,7 @@ export const CAPABILITIES: readonly Capability[] = [
|
|
|
646
674
|
flags: [],
|
|
647
675
|
mutates: true,
|
|
648
676
|
json: "none",
|
|
649
|
-
details: ["Needs a running proxy, first-party mode and macOS. The first time,
|
|
677
|
+
details: ["Needs a running proxy, first-party mode and macOS or Windows. The first time, the OS asks to trust a local certificate authority limited to claude.ai; when the server cannot show that prompt the command runs the trust step in this terminal.","Claude Desktop then reaches the network through opencodex; fully quit and reopen Desktop afterwards."],
|
|
650
678
|
usage: "ocx claude desktop picker on",
|
|
651
679
|
},
|
|
652
680
|
{
|
|
@@ -661,7 +689,7 @@ export const CAPABILITIES: readonly Capability[] = [
|
|
|
661
689
|
},
|
|
662
690
|
{
|
|
663
691
|
command: ["claude","desktop","picker","trust"],
|
|
664
|
-
summary: "Run the
|
|
692
|
+
summary: "Run the OS certificate trust step for picker mode in this terminal, then ask the server to finish enabling it.",
|
|
665
693
|
routes: [{"method":"GET","path":"/api/claude-desktop/picker"},{"method":"PUT","path":"/api/claude-desktop/picker"}],
|
|
666
694
|
flags: [],
|
|
667
695
|
mutates: true,
|
|
@@ -683,7 +711,7 @@ export const CAPABILITIES: readonly Capability[] = [
|
|
|
683
711
|
command: ["integration","client"],
|
|
684
712
|
summary: "Inspect and toggle file integrations and Aside profiles, read journals, and restore selected operations.",
|
|
685
713
|
routes: [{"method":"GET","path":"/api/client-integrations"},{"method":"GET","path":"/api/client-integrations/{clientId}"},{"method":"GET","path":"/api/client-integrations/aside/profiles"},{"method":"GET","path":"/api/client-integrations/aside/profiles/{profileId}"},{"method":"GET","path":"/api/client-integrations/journal"},{"method":"GET","path":"/api/client-integrations/aside/profiles/journal"},{"method":"GET","path":"/api/client-integrations/aside/profiles/{profileId}/journal"},{"method":"PUT","path":"/api/client-integrations/{clientId}"},{"method":"PUT","path":"/api/client-integrations/aside/profiles"},{"method":"PUT","path":"/api/client-integrations/aside/profiles/{profileId}"},{"method":"POST","path":"/api/client-integrations/restore"},{"method":"POST","path":"/api/client-integrations/aside/profiles/{profileId}/restore"}],
|
|
686
|
-
flags: [{"name":"--client","value":"string","summary":"File integration ID; aside selects profiles."},{"name":"--profile","value":"number","summary":"Aside nonnegative integer account ID; requires --client aside."},{"name":"--json","value":"boolean","summary":"Emit the result as JSON."},{"name":"--overwrite-conflict","value":"boolean","summary":"Explicitly permit replacing a conflicting block."},{"name":"--op","value":"string","summary":"Operation ID; --op-id is an alias."},{"name":"--confirm-drift","value":"boolean","summary":"Explicitly allow replacing edits made after the snapshot."}],
|
|
714
|
+
flags: [{"name":"--client","value":"string","summary":"File integration ID, including gentle-shell; aside selects profiles."},{"name":"--profile","value":"number","summary":"Aside nonnegative integer account ID; requires --client aside."},{"name":"--json","value":"boolean","summary":"Emit the result as JSON."},{"name":"--overwrite-conflict","value":"boolean","summary":"Explicitly permit replacing a conflicting block."},{"name":"--op","value":"string","summary":"Operation ID; --op-id is an alias."},{"name":"--confirm-drift","value":"boolean","summary":"Explicitly allow replacing edits made after the snapshot."}],
|
|
687
715
|
mutates: true,
|
|
688
716
|
json: "payload",
|
|
689
717
|
details: ["status/show/list reads all clients, one client or Aside profiles. history/journal reads rollback records; expired snapshots stay visible.","enable/disable requires --client; an omitted Aside --profile toggles all profiles. --overwrite-conflict applies only to enable.","restore requires --op (alias --op-id); --client requires --profile and only Aside supports that profile selector. --confirm-drift is an explicit user waiver, never auto-retried. Use client preview or restore --preview to inspect a change, history remove --op ID --yes to retire a journal row, and sync --client aside to refresh managed profiles."],
|
|
@@ -694,7 +722,7 @@ export const CAPABILITIES: readonly Capability[] = [
|
|
|
694
722
|
summary: "Synchronize client catalogs, including Aside profiles through the running server's mutation owner.",
|
|
695
723
|
routes: [{ method: "POST", path: "/api/client-integrations/aside/sync" }],
|
|
696
724
|
flags: [
|
|
697
|
-
{ name: "--restart-codex", value: "boolean", summary: "Restart the Codex app-servers and fully quit and relaunch the Codex desktop app after a catalog or
|
|
725
|
+
{ name: "--restart-codex", value: "boolean", summary: "Restart the Codex app-servers and fully quit and relaunch the Codex desktop app after a catalog, cache, or changed configuration write, on macOS, Linux and Windows." },
|
|
698
726
|
{ name: "--restart-app-server-only", value: "boolean", summary: "Restart only the Codex app-servers and leave the desktop app running; wins over --restart-codex when both are given." },
|
|
699
727
|
{ name: "--restart-desktop-app", value: "boolean", summary: "Deprecated alias of --restart-codex." },
|
|
700
728
|
],
|
|
@@ -786,7 +814,7 @@ export const CAPABILITIES: readonly Capability[] = [
|
|
|
786
814
|
command: ["api","policy"],
|
|
787
815
|
summary: "Read the protocol policy, or change the Messages surface, unrepresentable policy and rollout switches.",
|
|
788
816
|
routes: [{"method":"GET","path":"/api/protocols"},{"method":"PATCH","path":"/api/protocols/settings"}],
|
|
789
|
-
flags: [{"name":"--messages","value":"string","summary":"Open or close the Messages API: on or off. Off also turns the Claude integration off."},{"name":"--unrepresentable","value":"string","summary":"legacy keeps today's behavior; reject refuses a request its path cannot carry."},{"name":"--rollout","value":"string","summary":"One switch as name=on or name=off; repeatable. Every switch defaults off."},{"name":"--json","value":"boolean","summary":"Emit the resulting GET /api/protocols body."}],
|
|
817
|
+
flags: [{"name":"--messages","value":"string","summary":"Open or close the Messages API: on or off. Off also turns the Claude integration off."},{"name":"--unrepresentable","value":"string","summary":"legacy keeps today's behavior; reject refuses a request its path cannot carry."},{"name":"--rollout","value":"string","summary":"One switch as name=on or name=off; repeatable. Every switch defaults off except antigravityDirect."},{"name":"--json","value":"boolean","summary":"Emit the resulting GET /api/protocols body."}],
|
|
790
818
|
mutates: true,
|
|
791
819
|
json: "payload",
|
|
792
820
|
details: ["A bare invocation reads and never writes.","A setting flag changes the operator's config; run it only when the operator asks for that change."],
|
|
@@ -16,6 +16,47 @@ export const OBSERVE_SYSTEM_CAPABILITIES: readonly Capability[] = [
|
|
|
16
16
|
json: "payload",
|
|
17
17
|
details: ["Follow uses the server cursor and a bounded ordered window, preserving same-ID amendments and repeated row occurrences. It never enables logging.","--events emits version1 snapshots/appends with cursor and limit for observed-window reconstruction. Legacy row JSONL cannot express removals or resets exactly; neither mode promises lossless history between polls.","Follow limit is1–2000, default200. Polling is serial and cancellable; SIGINT exits130 and SIGTERM143. Malformed/oversized/unavailable responses stop without a fabricated empty snapshot or retry."],
|
|
18
18
|
},
|
|
19
|
+
{
|
|
20
|
+
command: ["logs", "history"],
|
|
21
|
+
summary: "Page the indexed request-history ledger with filters and a resumable cursor.",
|
|
22
|
+
usage: "ocx logs history [--provider <name>] [--model <id>] [--requested-model <id>] [--status <code>] [--conversation <id>] [--surface <name>] [--protocol <responses|chat|messages>] [--api-key-id <id>] [--profile <id>] [--fallback <true|false>] [--from <epoch-ms|ISO-datetime>] [--to <epoch-ms|ISO-datetime>] [--cursor <token>] [--limit <1-100>] [--json|--jsonl]",
|
|
23
|
+
routes: [{"method": "GET", "path": "/api/request-history"}],
|
|
24
|
+
flags: [
|
|
25
|
+
{"name": "--provider", "value": "string", "summary": "Filter provider, including failover attempts."},
|
|
26
|
+
{"name": "--model", "value": "string", "summary": "Filter served model, including failover attempts."},
|
|
27
|
+
{"name": "--requested-model", "value": "string", "summary": "Filter the model the client asked for."},
|
|
28
|
+
{"name": "--status", "value": "number", "summary": "HTTP status 100-599."},
|
|
29
|
+
{"name": "--conversation", "value": "string", "summary": "Conversation ID or stored hash."},
|
|
30
|
+
{"name": "--conversationId", "value": "string", "summary": "Alias of --conversation."},
|
|
31
|
+
{"name": "--surface", "value": "string", "summary": "Calling client surface recorded on the row."},
|
|
32
|
+
{"name": "--protocol", "value": "string", "summary": "Inbound wire: responses, chat or messages."},
|
|
33
|
+
{"name": "--api-key-id", "value": "string", "summary": "Exact management key id recorded on the row."},
|
|
34
|
+
{"name": "--profile", "value": "string", "summary": "Routing profile id."},
|
|
35
|
+
{"name": "--fallback", "value": "string", "summary": "true selects rows that failed over; false selects rows that did not."},
|
|
36
|
+
{"name": "--from", "value": "string", "summary": "Inclusive start as epoch milliseconds or ISO datetime with timezone."},
|
|
37
|
+
{"name": "--to", "value": "string", "summary": "Inclusive end as epoch milliseconds or ISO datetime with timezone."},
|
|
38
|
+
{"name": "--cursor", "value": "string", "summary": "Opaque nextCursor from a previous page."},
|
|
39
|
+
{"name": "--limit", "value": "number", "summary": "1-100 rows; default 50."},
|
|
40
|
+
{"name": "--json", "value": "boolean", "summary": "Emit the management payload, including hasMore, nextCursor and index."},
|
|
41
|
+
{"name": "--jsonl", "value": "boolean", "summary": "Matching rows only; hasMore and nextCursor go to stderr."},
|
|
42
|
+
],
|
|
43
|
+
mutates: false, json: "payload",
|
|
44
|
+
details: [
|
|
45
|
+
"Pages the derived request-history index, not the recent /api/logs ring. Empty matches succeed. Also accepted after observe logs.",
|
|
46
|
+
"JSON is the management payload. JSONL emits entries only; resume with --cursor from stderr when hasMore is true.",
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
command: ["logs", "get"],
|
|
51
|
+
summary: "Read one canonical request-history row by request ID.",
|
|
52
|
+
usage: "ocx logs get <request-id> [--json]",
|
|
53
|
+
routes: [{"method": "GET", "path": "/api/request-history/{id}"}],
|
|
54
|
+
flags: [{"name": "--json", "value": "boolean", "summary": "Emit the canonical row as JSON."}],
|
|
55
|
+
mutates: false, json: "payload",
|
|
56
|
+
details: [
|
|
57
|
+
"The request ID is URI-encoded. This is the stored row, not the route-decision view from logs explain. A missing id is a 404. Also accepted after observe logs.",
|
|
58
|
+
],
|
|
59
|
+
},
|
|
19
60
|
{
|
|
20
61
|
command: ["logs", "explain"], summary: "Explain the recorded routing decision for one request.",
|
|
21
62
|
usage: "ocx logs explain <request-id> [--json]",
|
|
@@ -43,12 +84,31 @@ export const OBSERVE_SYSTEM_CAPABILITIES: readonly Capability[] = [
|
|
|
43
84
|
{
|
|
44
85
|
command: ["observe","usage"],
|
|
45
86
|
summary: "Read token and estimated-cost usage.",
|
|
46
|
-
usage: "ocx observe usage [--range <today|1d|7d|30d|all>] [--surface <all|codex|claude|grok>] [--since <epoch-ms|ISO-datetime>] [--until <epoch-ms|ISO-datetime>] [--provider <name>] [--model <id>] [--api-key-id <id>] [--search <text>] [--json]",
|
|
87
|
+
usage: "ocx observe usage [--range <today|1d|7d|30d|all>] [--surface <all|codex|claude|grok>] [--since <epoch-ms|ISO-datetime>] [--until <epoch-ms|ISO-datetime>] [--provider <name>] [--model <id>] [--api-key-id <id>] [--search <text>] [--top <1-1000>] [--json]",
|
|
47
88
|
routes: [{"method":"GET","path":"/api/usage"}],
|
|
48
|
-
flags: [{"name":"--range","value":"string","summary":"today | 1d | 7d | 30d | all; default 30d."},{"name":"--surface","value":"string","summary":"all | codex | claude | grok; default all."},{"name":"--since","value":"string","summary":"Inclusive epoch milliseconds or ISO datetime with timezone; requires --until."},{"name":"--until","value":"string","summary":"Inclusive end; requires --since. Custom bounds override --range."},{"name":"--provider","value":"string","summary":"Filter provider."},{"name":"--model","value":"string","summary":"Filter model."},{"name":"--json","value":"boolean","summary":"Emit the result as JSON."},{"name":"--api-key-id","value":"string","summary":"Exact nonblank management key scope; connected clients refuse this before reading their enrolled key."},{"name":"--search","value":"string","summary":"Model-row substring view over model/provider/resolvedModel; top100 by tokens. Whole-report totals stay unchanged."}],
|
|
89
|
+
flags: [{"name":"--range","value":"string","summary":"today | 1d | 7d | 30d | all; default 30d."},{"name":"--surface","value":"string","summary":"all | codex | claude | grok; default all."},{"name":"--since","value":"string","summary":"Inclusive epoch milliseconds or ISO datetime with timezone; requires --until."},{"name":"--until","value":"string","summary":"Inclusive end; requires --since. Custom bounds override --range."},{"name":"--provider","value":"string","summary":"Filter provider."},{"name":"--model","value":"string","summary":"Filter model."},{"name":"--json","value":"boolean","summary":"Emit the result as JSON."},{"name":"--api-key-id","value":"string","summary":"Exact nonblank management key scope; connected clients refuse this before reading their enrolled key."},{"name":"--top","value":"number","summary":"1-1000 human model rows; default 10, or 100 with --search. Applied after search; ignored with --json. Totals unchanged."},{"name":"--search","value":"string","summary":"Model-row substring view over model/provider/resolvedModel; default top100 by tokens. Whole-report totals stay unchanged."}],
|
|
49
90
|
mutates: false,
|
|
50
91
|
json: "payload",
|
|
51
|
-
details: ["Also available as ocx usage. Connected clients read only their enrolled-key Hub report through /v1/usage; caller --api-key-id is refused before key read/transport and never grants management authority.","Nonclient --api-key-id uses /api/usage and requires matching filter acknowledgment. An unknown acknowledged key is empty/matched:false, not404. Custom-window acknowledgment remains required.","--search filters only returned model rows after scope acknowledgment. Blank search selects the top100 model rows; modelView reports match/return counts without recomputing totals."],
|
|
92
|
+
details: ["Also available as ocx usage. Connected clients read only their enrolled-key Hub report through /v1/usage; caller --api-key-id is refused before key read/transport and never grants management authority.","Nonclient --api-key-id uses /api/usage and requires matching filter acknowledgment. An unknown acknowledged key is empty/matched:false, not404. Custom-window acknowledgment remains required.","--search filters only returned model rows after scope acknowledgment. Blank search selects the top100 model rows by default; modelView reports match/return counts without recomputing totals."],
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
command: ["usage", "compare"],
|
|
96
|
+
summary: "Compare a usage range with the previous equal window.",
|
|
97
|
+
usage: "ocx usage compare [--range <today|1d|7d|30d>] [--surface <all|codex|claude|grok>] [--provider <name>] [--model <id>] [--api-key-id <id>] [--json]",
|
|
98
|
+
routes: [{"method": "GET", "path": "/api/usage"}],
|
|
99
|
+
flags: [
|
|
100
|
+
{"name": "--range", "value": "string", "summary": "today | 1d | 7d | 30d; default 30d. all is refused."},
|
|
101
|
+
{"name": "--surface", "value": "string", "summary": "all | codex | claude | grok; default all."},
|
|
102
|
+
{"name": "--provider", "value": "string", "summary": "Filter provider."},
|
|
103
|
+
{"name": "--model", "value": "string", "summary": "Filter model."},
|
|
104
|
+
{"name": "--api-key-id", "value": "string", "summary": "Exact nonblank management key scope; connected clients refuse this."},
|
|
105
|
+
{"name": "--json", "value": "boolean", "summary": "Emit current, previous, delta and change percentages."},
|
|
106
|
+
],
|
|
107
|
+
mutates: false, json: "envelope",
|
|
108
|
+
details: [
|
|
109
|
+
"Two sequential GET /api/usage reads: the named range at now, then the same range shifted back one equal window. Custom since/until must be acknowledged on both. --range all is refused.",
|
|
110
|
+
"Also accepted after observe usage. Default range is 30d. This is not an atomic snapshot.",
|
|
111
|
+
],
|
|
52
112
|
},
|
|
53
113
|
{
|
|
54
114
|
command: ["observe", "storage"], summary: "Read storage diagnostics.",
|
|
@@ -207,6 +207,17 @@ export const PROVIDER_MODEL_CAPABILITIES: readonly Capability[] = [
|
|
|
207
207
|
flags: [{ name: "--enabled", value: "string", summary: "on or off; takes a value." }, { name: "--json", value: "boolean", summary: "Emit the settings receipt." }],
|
|
208
208
|
details: ["At least a model or --enabled is required; - clears the model with an empty string. Enabling shadow calls can cause subsequent inference calls."],
|
|
209
209
|
},
|
|
210
|
+
{
|
|
211
|
+
command: ["models", "auto-review", "status"], summary: "Read the global auto-review model and enabled state.",
|
|
212
|
+
usage: "ocx models auto-review status [--json]", routes: [{ method: "GET", path: "/api/auto-review-settings" }], mutates: false, json: "payload",
|
|
213
|
+
flags: [{ name: "--json", value: "boolean", summary: "Emit auto-review settings." }],
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
command: ["models", "auto-review", "set"], summary: "Set the global auto-review model or enabled state.",
|
|
217
|
+
usage: "ocx models auto-review set [model|-] [--enabled <on|off>] [--json]", routes: [{ method: "PUT", path: "/api/auto-review-settings" }], mutates: true, json: "payload",
|
|
218
|
+
flags: [{ name: "--enabled", value: "string", summary: "on or off; takes a value." }, { name: "--json", value: "boolean", summary: "Emit the settings receipt." }],
|
|
219
|
+
details: ["At least a model or --enabled is required; - clears the model with an empty string. Human output points to ocx sync when a catalog refresh can be retried and asks operators to resolve a failed refresh before syncing."],
|
|
220
|
+
},
|
|
210
221
|
{
|
|
211
222
|
command: ["alias", "list"], summary: "Read provider and model aliases.",
|
|
212
223
|
usage: "ocx alias list [--json]", routes: [{ method: "GET", path: "/api/aliases" }], mutates: false, json: "payload",
|
|
@@ -20,7 +20,7 @@ const USAGE = `Usage (experimental, macOS only):
|
|
|
20
20
|
|
|
21
21
|
function run(command: string, args: string[]) {
|
|
22
22
|
const result = spawnSync(command, args, { encoding: "utf8", timeout: 5000 });
|
|
23
|
-
return { ok: result.status === 0, output: `${result.stdout ?? ""}${result.stderr ?? ""}`.trim() };
|
|
23
|
+
return { ok: result.status === 0, status: result.status, output: `${result.stdout ?? ""}${result.stderr ?? ""}`.trim() };
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
@@ -42,11 +42,12 @@ function chatgptDesktopIssueInFile(): string | null {
|
|
|
42
42
|
* desktop restart adapter does. "ChatGPT" is a display name another app can share, so quitting,
|
|
43
43
|
* relaunching and the binary path all key on this verified bundle rather than on the name.
|
|
44
44
|
*/
|
|
45
|
-
function discoverApp(): DesktopAppInstall | null {
|
|
45
|
+
function discoverApp(): DesktopAppInstall | null | undefined {
|
|
46
46
|
try {
|
|
47
47
|
return darwinDesktopAppAdapter.discover(darwinDefaultExec);
|
|
48
48
|
} catch {
|
|
49
|
-
|
|
49
|
+
// An inspection error is not evidence that the app is uninstalled.
|
|
50
|
+
return undefined;
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
@@ -55,14 +56,20 @@ function discoverApp(): DesktopAppInstall | null {
|
|
|
55
56
|
* `-a` keeps ancestors in the match: when ocx runs inside a ChatGPT/Codex session the app is
|
|
56
57
|
* one of this process's ancestors, and plain `pgrep -x` would report it as not running.
|
|
57
58
|
*/
|
|
58
|
-
function appState(install: DesktopAppInstall, launcher: string): { running: boolean; shim: boolean } {
|
|
59
|
+
function appState(install: DesktopAppInstall, launcher: string): { running: boolean | null; shim: boolean | null } {
|
|
59
60
|
const shell = join(install.root, "Contents", "MacOS", "ChatGPT");
|
|
60
61
|
// Only this user's processes: another account's ChatGPT can neither be quit nor relaunched here.
|
|
61
62
|
const uid = typeof process.getuid === "function" ? process.getuid() : undefined;
|
|
62
63
|
const pids = run("pgrep", [...(uid === undefined ? [] : ["-U", String(uid)]), "-a", "-x", "ChatGPT"]);
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
// pgrep exit 1 means no match; timeout, signal, or command errors are unknown.
|
|
65
|
+
if (!pids.ok) return pids.status === 1
|
|
66
|
+
? { running: false, shim: false } : { running: null, shim: null };
|
|
67
|
+
const candidates = pids.output.split(/\s+/).filter(value => /^\d+$/.test(value));
|
|
68
|
+
if (candidates.length === 0) return { running: null, shim: null };
|
|
69
|
+
let unreadable = false;
|
|
70
|
+
for (const pid of candidates) {
|
|
65
71
|
const command = run("ps", ["eww", "-o", "command=", "-p", pid]);
|
|
72
|
+
if (!command.ok || !command.output) unreadable = true;
|
|
66
73
|
if (command.ok && (command.output === shell || command.output.startsWith(`${shell} `))) {
|
|
67
74
|
const marker = `CODEX_CLI_PATH=${launcher}`;
|
|
68
75
|
const start = command.output.indexOf(marker);
|
|
@@ -70,20 +77,24 @@ function appState(install: DesktopAppInstall, launcher: string): { running: bool
|
|
|
70
77
|
&& (start + marker.length === command.output.length || command.output[start + marker.length] === " ") };
|
|
71
78
|
}
|
|
72
79
|
}
|
|
73
|
-
return { running: false, shim: false };
|
|
80
|
+
return unreadable ? { running: null, shim: null } : { running: false, shim: false };
|
|
74
81
|
}
|
|
75
82
|
|
|
76
83
|
/** Adapted from #5947: open ignores new launch settings until the previous app exits. */
|
|
77
84
|
async function quitApp(install: DesktopAppInstall, launcher: string): Promise<boolean> {
|
|
78
|
-
|
|
85
|
+
const initial = appState(install, launcher).running;
|
|
86
|
+
if (initial === false) return true;
|
|
87
|
+
if (initial === null) return false;
|
|
79
88
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
80
89
|
run("/usr/bin/osascript", ["-e", `quit app id "${install.id}"`]);
|
|
81
90
|
for (let poll = 0; poll < 20; poll++) {
|
|
82
|
-
|
|
91
|
+
const running = appState(install, launcher).running;
|
|
92
|
+
if (running === false) return true;
|
|
93
|
+
if (running === null) return false;
|
|
83
94
|
await Bun.sleep(250);
|
|
84
95
|
}
|
|
85
96
|
}
|
|
86
|
-
return
|
|
97
|
+
return appState(install, launcher).running === false;
|
|
87
98
|
}
|
|
88
99
|
|
|
89
100
|
export async function handleChatgptCommand(args: string[], platform: NodeJS.Platform = process.platform): Promise<number> {
|
|
@@ -105,16 +116,21 @@ export async function handleChatgptCommand(args: string[], platform: NodeJS.Plat
|
|
|
105
116
|
const launcher = chatgptShimLauncherPath();
|
|
106
117
|
const install = discoverApp();
|
|
107
118
|
if (sub === "status") {
|
|
108
|
-
const app = install ? appState(install, launcher)
|
|
119
|
+
const app = install ? appState(install, launcher)
|
|
120
|
+
: install === undefined ? { running: null, shim: null } : { running: false, shim: false };
|
|
109
121
|
const configIssue = config.chatgptDesktop?.appServerShim === true ? null : chatgptDesktopIssueInFile();
|
|
110
122
|
const flag = config.chatgptDesktop?.appServerShim === true ? "on"
|
|
111
123
|
: configIssue ? `off (config.json ${configIssue}; the whole chatgptDesktop block is ignored)` : "off";
|
|
112
124
|
console.log(`app-server shim (experimental): ${flag}
|
|
113
125
|
launcher: ${existsSync(launcher) ? "present" : "absent"}
|
|
114
|
-
app: ${install ? (app.running ? "running" : "not running") : "not installed"}
|
|
115
|
-
CODEX_CLI_PATH launcher: ${app.shim ? "yes" : "no"}`);
|
|
126
|
+
app: ${install === undefined ? "unknown (app discovery failed)" : install ? (app.running === null ? "unknown (process inspection failed)" : app.running ? "running" : "not running") : "not installed"}
|
|
127
|
+
CODEX_CLI_PATH launcher: ${app.shim === null ? "unknown" : app.shim ? "yes" : "no"}`);
|
|
116
128
|
return 0;
|
|
117
129
|
}
|
|
130
|
+
if (install === undefined) {
|
|
131
|
+
console.error("ChatGPT app discovery failed; no launcher was changed and no app was opened. Retry after resolving discovery.");
|
|
132
|
+
return 1;
|
|
133
|
+
}
|
|
118
134
|
if (!install) {
|
|
119
135
|
if (sub === "restore") rmSync(launcher, { force: true });
|
|
120
136
|
console.error("ChatGPT (com.openai.codex) was not found; install or open it once, then retry.");
|
|
@@ -143,9 +159,14 @@ CODEX_CLI_PATH launcher: ${app.shim ? "yes" : "no"}`);
|
|
|
143
159
|
console.error(`Refusing to ${sub === "launch" ? "launch the shim" : "restore ChatGPT"}: ${untrusted}.`);
|
|
144
160
|
return 1;
|
|
145
161
|
}
|
|
162
|
+
// Preflight before changing the launcher. quitApp rechecks at the action boundary.
|
|
163
|
+
if (appState(install, launcher).running === null) {
|
|
164
|
+
console.error("ChatGPT process inspection failed; no launcher was changed and no app was opened. Retry after resolving inspection.");
|
|
165
|
+
return 1;
|
|
166
|
+
}
|
|
146
167
|
if (binary) writeChatgptShimLauncher(undefined, binary);
|
|
147
168
|
if (!(await quitApp(install, launcher))) {
|
|
148
|
-
console.error("ChatGPT
|
|
169
|
+
console.error("ChatGPT exit could not be confirmed; no new app was opened. Check the running app and retry.");
|
|
149
170
|
return 1;
|
|
150
171
|
}
|
|
151
172
|
// Remove an inherited override too: restore must launch without CODEX_CLI_PATH.
|
package/src/cli/claude.ts
CHANGED
|
@@ -32,7 +32,8 @@ import { DEFAULT_CATALOG_PATH } from "../codex/paths";
|
|
|
32
32
|
import { readFileSync } from "node:fs";
|
|
33
33
|
import { join } from "node:path";
|
|
34
34
|
import { aliasForNative, aliasForRoute, legacyAliasForNative, legacyAliasForRoute } from "../claude/alias";
|
|
35
|
-
import { desktop3pAlias } from "../claude/desktop-3p";
|
|
35
|
+
import { desktop3pAlias, isRealDesktop3pModelId, resolveDesktop3pAlias } from "../claude/desktop-3p";
|
|
36
|
+
import { desktopProfileWireAlias, legacyDesktopProfileWireAlias } from "../claude/desktop-profile";
|
|
36
37
|
import { inspectDesktopFirstParty } from "../claude/desktop-first-party";
|
|
37
38
|
import { isClaudeInterceptProxyUrl, type ClaudeInterceptSettingsState } from "../claude/intercept/settings";
|
|
38
39
|
import { withoutSiblingMarker } from "../codex/sibling-start";
|
|
@@ -618,11 +619,47 @@ const MODEL_ENV_SLOT_NAMES = [
|
|
|
618
619
|
"ANTHROPIC_SMALL_FAST_MODEL",
|
|
619
620
|
] as const;
|
|
620
621
|
|
|
621
|
-
const DESKTOP_3P_ALIAS = /^claude-opus-4(?:-8)?-[a-z][0-9a-z]{2}
|
|
622
|
+
const DESKTOP_3P_ALIAS = /^claude-(?:opus-4(?:-8)?-[a-z][0-9a-z]{2}|(?:opus-4-8|fable-5)-p[0-9a-z]{3})(?:--fast)?$/;
|
|
623
|
+
|
|
624
|
+
export function nativeClaudeModelIds(config: OcxConfig): string[] {
|
|
625
|
+
const assignments = config.claudeCode?.desktopProfile?.assignments ?? {};
|
|
626
|
+
const routes = Object.keys(assignments);
|
|
627
|
+
const realProfileIds = new Set(routes.filter(route => route.startsWith("anthropic/claude-"))
|
|
628
|
+
.map(route => route.slice("anthropic/".length)));
|
|
629
|
+
// A native CLI starts without the server registry. Persisted profile bindings still
|
|
630
|
+
// identify proxy selectors, even when an old provider declaration has the same spelling.
|
|
631
|
+
const proxyProfileIds = new Set(routes.filter(route => !route.startsWith("anthropic/claude-"))
|
|
632
|
+
.flatMap(route => {
|
|
633
|
+
const alias = assignments[route]!.alias;
|
|
634
|
+
const slash = route.indexOf("/");
|
|
635
|
+
return [alias, desktopProfileWireAlias(alias), legacyDesktopProfileWireAlias(alias),
|
|
636
|
+
desktop3pAlias(route.slice(0, slash), route.slice(slash + 1))];
|
|
637
|
+
}));
|
|
638
|
+
// The configured default is a genuine declaration too: the catalog seeds it for static
|
|
639
|
+
// providers, so it must be recognized here even without a server registry.
|
|
640
|
+
const anthropic = config.providers.anthropic;
|
|
641
|
+
const declaredIds = [
|
|
642
|
+
...(anthropic?.defaultModel ? [anthropic.defaultModel] : []),
|
|
643
|
+
...(anthropic?.models ?? []), ...(anthropic?.selectedModels ?? []), ...(anthropic?.retainModels ?? []),
|
|
644
|
+
];
|
|
645
|
+
return [...new Set([
|
|
646
|
+
...realProfileIds,
|
|
647
|
+
...declaredIds
|
|
648
|
+
.filter(id => {
|
|
649
|
+
const base = id.endsWith("--fast") ? id.slice(0, -"--fast".length) : id;
|
|
650
|
+
return id.startsWith("claude-") && (realProfileIds.has(id)
|
|
651
|
+
|| (!proxyProfileIds.has(id) && !proxyProfileIds.has(base)));
|
|
652
|
+
}),
|
|
653
|
+
])];
|
|
654
|
+
}
|
|
622
655
|
|
|
623
|
-
export function isProxyOnlyModelId(value: string, providerNames: readonly string[] = []): boolean {
|
|
656
|
+
export function isProxyOnlyModelId(value: string, providerNames: readonly string[] = [], realAnthropicIds: readonly string[] = []): boolean {
|
|
624
657
|
const id = value.trim().replace(/\[1m\]$/, "");
|
|
625
658
|
if (!id) return false;
|
|
659
|
+
if (isRealDesktop3pModelId(id)) return false;
|
|
660
|
+
const base = id.endsWith("--fast") ? id.slice(0, -"--fast".length) : id;
|
|
661
|
+
if (resolveDesktop3pAlias(id) || resolveDesktop3pAlias(base)) return true;
|
|
662
|
+
if (realAnthropicIds.includes(id)) return false;
|
|
626
663
|
const aliasPrefixes = [CLAUDE_ALIAS_PREFIX_CURRENT, CLAUDE_ALIAS_PREFIX_CURRENT_V2, CLAUDE_ALIAS_PREFIX_V1, CLAUDE_ALIAS_PREFIX_V2];
|
|
627
664
|
if (aliasPrefixes.some(prefix => id.startsWith(prefix)) || DESKTOP_3P_ALIAS.test(id)) {
|
|
628
665
|
return true;
|
|
@@ -684,9 +721,10 @@ export function buildNativeClaudeEnv(
|
|
|
684
721
|
// otherwise settings.env can replace the destination while retaining the credential.
|
|
685
722
|
if (hasOwnedAdmission) delete env.CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST;
|
|
686
723
|
const providerNames = Object.keys(config.providers);
|
|
724
|
+
const realAnthropicIds = nativeClaudeModelIds(config);
|
|
687
725
|
for (const name of MODEL_ENV_SLOT_NAMES) {
|
|
688
726
|
const value = env[name];
|
|
689
|
-
if (!value || !isProxyOnlyModelId(value, providerNames)) continue;
|
|
727
|
+
if (!value || !isProxyOnlyModelId(value, providerNames, realAnthropicIds)) continue;
|
|
690
728
|
delete env[name];
|
|
691
729
|
// The label opencodex paired with this slot names a proxy route the native session cannot use.
|
|
692
730
|
const labelName = `${name}_NAME`;
|
|
@@ -702,11 +740,12 @@ export function nativeModelOverride(
|
|
|
702
740
|
configuredModel: string | undefined,
|
|
703
741
|
args: readonly string[],
|
|
704
742
|
providerNames: readonly string[] = [],
|
|
743
|
+
realAnthropicIds: readonly string[] = [],
|
|
705
744
|
): { flag?: string[]; warning?: string } {
|
|
706
|
-
if (!pickedModel || !isProxyOnlyModelId(pickedModel, providerNames)) return {};
|
|
745
|
+
if (!pickedModel || !isProxyOnlyModelId(pickedModel, providerNames, realAnthropicIds)) return {};
|
|
707
746
|
if (args.some(arg => arg === "--model" || arg.startsWith("--model="))) return {};
|
|
708
747
|
const fallback = configuredModel?.trim();
|
|
709
|
-
if (fallback && !isProxyOnlyModelId(fallback, providerNames)) {
|
|
748
|
+
if (fallback && !isProxyOnlyModelId(fallback, providerNames, realAnthropicIds)) {
|
|
710
749
|
return {
|
|
711
750
|
flag: ["--model", fallback],
|
|
712
751
|
warning: `ℹ️ The saved model (${pickedModel}) requires the proxy. This native session will use ${fallback}.`,
|
|
@@ -867,6 +906,7 @@ async function launchNativeClaude(config: OcxConfig, args: string[], notice: str
|
|
|
867
906
|
config.claudeCode?.model,
|
|
868
907
|
args,
|
|
869
908
|
providerNames,
|
|
909
|
+
nativeClaudeModelIds(config),
|
|
870
910
|
);
|
|
871
911
|
if (override.warning) console.error(override.warning);
|
|
872
912
|
const allowRootSkipPermissions = shouldAllowRootSkipPermissions(args);
|