@bitkyc08/opencodex 2.86.0 → 2.88.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/gui/dist/assets/App-CHC89EXQ.js +58 -0
- package/gui/dist/assets/App-wT3mXqFz.css +1 -0
- package/gui/dist/assets/{Tray-DyR9yBee.js → Tray-B5bC7AWL.js} +1 -1
- package/gui/dist/assets/index-B5bsvxor.js +94 -0
- package/gui/dist/assets/index-DPeB9HpV.css +1 -0
- package/gui/dist/assets/quota-summary-D8y2wTsB.js +1 -0
- package/gui/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/adapters/anthropic/beta-allowlist.ts +9 -8
- package/src/adapters/anthropic/beta-body-pairs.ts +93 -0
- package/src/adapters/anthropic/passthrough.ts +7 -23
- package/src/adapters/anthropic-progress.ts +84 -0
- package/src/adapters/anthropic-rejection-memo.ts +71 -0
- package/src/adapters/anthropic-replay.ts +135 -0
- package/src/adapters/anthropic-tool-catalog.ts +11 -0
- package/src/adapters/anthropic.ts +151 -33
- 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/coding-agent/protocol.ts +1 -1
- package/src/adapters/coding-agent/turn.ts +18 -2
- package/src/adapters/dsh-account.ts +97 -0
- package/src/adapters/google-progress-history.ts +53 -0
- package/src/adapters/google.ts +52 -9
- 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-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 +4 -2
- 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 +4 -1
- package/src/advisor/context.ts +16 -4
- package/src/advisor/evidence-tool.ts +21 -0
- package/src/advisor/evidence.ts +117 -0
- package/src/advisor/runtime.ts +79 -31
- package/src/advisor/settings.ts +11 -2
- package/src/bridge/errors.ts +19 -1
- package/src/bridge/internal.ts +7 -1
- package/src/bridge/response-json.ts +18 -3
- package/src/bridge/sse.ts +59 -8
- package/src/bridge/terminal-refusal.ts +59 -0
- package/src/claude/desktop-3p-library.ts +32 -7
- package/src/claude/desktop-3p.ts +55 -13
- package/src/claude/desktop-first-party.ts +1 -1
- package/src/claude/desktop-picker-platform.ts +4 -0
- package/src/claude/desktop-picker.ts +15 -8
- package/src/claude/desktop-system-proxy.ts +50 -4
- package/src/claude/inbound-content-options.ts +77 -0
- package/src/claude/inbound.ts +33 -0
- 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/outbound.ts +46 -13
- 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 +17 -3
- package/src/cli/capabilities-accounts.ts +20 -1
- package/src/cli/capabilities-agents-routing.ts +5 -2
- package/src/cli/capabilities-base.ts +38 -10
- package/src/cli/capabilities-observe-system.ts +63 -3
- package/src/cli/capabilities-provider-models.ts +11 -0
- 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 +33 -16
- package/src/cli/dispatch.ts +25 -4
- package/src/cli/doctor.ts +6 -1
- package/src/cli/ensure-desktop-cold-start.ts +60 -7
- package/src/cli/help.ts +3 -2
- package/src/cli/index.ts +1 -1
- package/src/cli/integration-plan-dto.ts +1 -0
- package/src/cli/log-history.ts +172 -0
- package/src/cli/loopback-family.ts +31 -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 +28 -8
- 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 +2 -1
- package/src/clients/config-export.ts +18 -44
- 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/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 +2 -2
- package/src/codex/catalog/auto-review.ts +20 -3
- package/src/codex/catalog/build-entries.ts +9 -1
- package/src/codex/catalog/combo-member.ts +14 -5
- package/src/codex/catalog/configured-tiers.ts +1 -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 +21 -16
- package/src/codex/catalog/model-visibility.ts +3 -1
- package/src/codex/catalog/parsing.ts +30 -86
- package/src/codex/catalog/provider-models.ts +36 -34
- package/src/codex/catalog/routed-gather.ts +14 -13
- 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 +23 -2
- package/src/codex/desktop-app/picker-freshness.ts +96 -0
- package/src/codex/desktop-app-restart.ts +21 -0
- package/src/codex/desktop-compatibility/installed-build.ts +24 -6
- package/src/codex/desktop-compatibility/routing-preflight.ts +1 -1
- package/src/codex/desktop-compatibility/runtime.ts +12 -3
- package/src/codex/desktop-compatibility/windows-key-protection.ts +115 -9
- package/src/codex/features.ts +85 -45
- package/src/codex/inject/history-failure.ts +27 -0
- 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/main-account-hard-lock.ts +30 -1
- 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 +1 -1
- package/src/codex/routing/selection.ts +4 -3
- package/src/codex/routing/thread-affinity.ts +1 -1
- 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/websocket-activity.ts +161 -0
- package/src/codex/websocket-registry.ts +25 -1
- 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 +33 -6
- package/src/config/live-reconcile.ts +38 -2
- package/src/config/load-degrade.ts +17 -0
- package/src/config/opencode-wire-upgrade.ts +54 -0
- package/src/config/opencode-zen-upgrade.ts +53 -0
- package/src/config/owner-registry.ts +22 -17
- package/src/config/provider-validation.ts +45 -2
- package/src/config/schema/config-schema.ts +22 -0
- package/src/config/schema/leaf-validators.ts +38 -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 +657 -297
- package/src/grok/sync.ts +1 -1
- package/src/images/loop.ts +116 -27
- package/src/integrations/catalog-refresh.ts +1 -1
- package/src/integrations/mutation-plan.ts +1 -0
- package/src/integrations/registry.ts +8 -0
- package/src/lib/codex-restart-contract.ts +15 -0
- package/src/lib/desktop-upstream-tunnel.ts +18 -53
- package/src/lib/empty-tool-catalog.ts +62 -0
- package/src/lib/errors.ts +19 -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/opaque-proxy-tunnel.ts +217 -0
- package/src/lib/redact.ts +2 -2
- package/src/lib/request-failure-model.ts +2 -0
- 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 +40 -11
- package/src/oauth/generic-session-affinity.ts +125 -0
- package/src/oauth/index.ts +184 -109
- 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/encoders/adapter-events.ts +6 -5
- package/src/protocols/encoders/messages.ts +9 -6
- package/src/protocols/provider-summary.ts +2 -1
- 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 +3 -0
- package/src/providers/model-rename-migration.ts +2 -2
- 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/opencode-zen-rate-limit.ts +7 -2
- 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 +37 -8
- 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 +50 -5
- package/src/responses/reasoning-envelope.ts +4 -0
- package/src/responses/reasoning-replay-cache.ts +74 -6
- 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/router.ts +8 -321
- package/src/routing/analytics.ts +7 -15
- package/src/routing/health.ts +37 -22
- package/src/routing/history/indexer.ts +6 -5
- package/src/routing/history/ingest.ts +6 -2
- package/src/routing/profile.ts +1 -1
- package/src/server/admission-model-scope.ts +17 -0
- package/src/server/auth-cors.ts +11 -0
- package/src/server/chat-completions.ts +7 -1
- 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 +56 -414
- package/src/server/effort-policy.ts +1 -1
- package/src/server/images.ts +15 -2
- package/src/server/index/live-sideband.ts +3 -2
- 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 +20 -6
- package/src/server/index/startup-warnings.ts +2 -0
- package/src/server/index/websocket-handler.ts +18 -4
- package/src/server/index.ts +8 -8
- package/src/server/inference/advisor-diagnostics.ts +31 -0
- package/src/server/lifecycle.ts +13 -1
- package/src/server/management/advisor-routes.ts +15 -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 +1 -1
- package/src/server/management/config-routes.ts +75 -4
- package/src/server/management/cursor-integration-routes.ts +1 -1
- package/src/server/management/model-routes.ts +11 -6
- 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/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 +10 -1
- package/src/server/management-api.ts +3 -1
- package/src/server/messages-native-tool-guard.ts +185 -0
- package/src/server/messages-native.ts +117 -24
- 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 +6 -1
- package/src/server/responses/account-change-state.ts +8 -2
- package/src/server/responses/adapter-continuation.ts +47 -19
- package/src/server/responses/adapter-delivery.ts +72 -12
- package/src/server/responses/adapter-dispatch.ts +46 -3
- package/src/server/responses/advisor-retention.ts +117 -0
- package/src/server/responses/advisor-slot.ts +73 -41
- package/src/server/responses/anthropic-thinking-recovery.ts +153 -0
- package/src/server/responses/codex-ws-wire.ts +15 -8
- package/src/server/responses/combo-stream-preflight.ts +3 -2
- package/src/server/responses/compact.ts +303 -125
- package/src/server/responses/compaction-recovery.ts +20 -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 +2 -0
- package/src/server/responses/core-combo.ts +121 -36
- package/src/server/responses/core-errors.ts +3 -3
- package/src/server/responses/core-lifetime.ts +8 -4
- package/src/server/responses/core-opaque-recovery.ts +35 -0
- package/src/server/responses/core-options.ts +7 -0
- package/src/server/responses/core-pipeline.ts +141 -0
- package/src/server/responses/core-replay.ts +23 -3
- package/src/server/responses/core.ts +2 -115
- 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 +3 -1
- package/src/server/responses/passthrough-dispatch.ts +15 -13
- package/src/server/responses/passthrough-execution.ts +3 -2
- package/src/server/responses/request-prepare.ts +77 -12
- package/src/server/responses/request-sidecar-auth.ts +2 -2
- package/src/server/responses/request-transport.ts +104 -27
- package/src/server/responses/response-effects.ts +2 -0
- package/src/server/responses/response-tool-ownership.ts +21 -0
- package/src/server/responses/run-turn-execution.ts +96 -30
- package/src/server/responses/sidecar-execution.ts +63 -9
- package/src/server/responses/sidecar-send-budget.ts +2 -2
- package/src/server/responses/terminal-guard.ts +2 -16
- package/src/server/responses-undeclared-tool-guard.ts +1 -1
- package/src/server/ws-bridge.ts +2 -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/guards.ts +1 -61
- package/src/service/health-sentinel-linux.ts +112 -0
- package/src/service/health-sentinel-main.ts +76 -57
- package/src/service/health.ts +5 -89
- package/src/service/launchd.ts +27 -7
- package/src/service/logging.ts +72 -9
- 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/types/config.ts +64 -3
- package/src/types/opencode-go.ts +61 -0
- package/src/types/opencode-zen.ts +35 -0
- package/src/types/provider.ts +32 -6
- package/src/types/request.ts +31 -2
- package/src/types/wire.ts +31 -37
- package/src/types.ts +2 -0
- package/src/update/npm-invocation.mjs +12 -2
- package/src/usage/cost.ts +48 -12
- package/src/usage/expected-prices.ts +3 -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 +30 -11
- package/src/usage/telemetry-contract.ts +1 -0
- 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/anthropic-history.ts +59 -0
- package/src/web-search/loop.ts +236 -73
- package/src/web-search/progress-stream.ts +15 -2
- package/src/web-search/run-turn-loop.ts +9 -1
- package/gui/dist/assets/App-BjlttVLy.js +0 -58
- package/gui/dist/assets/App-CSJvmjNs.css +0 -1
- package/gui/dist/assets/index-BB6uK6tU.css +0 -1
- package/gui/dist/assets/index-BMssP4k3.js +0 -94
- package/gui/dist/assets/quota-summary-D8M1bc_R.js +0 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { fastRowBases } from "../fast-row";
|
|
2
|
+
import { previewRouteModel } from "../../router";
|
|
3
|
+
import type { OcxConfig } from "../../types";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Build the alias promoter for one model listing. The Fast-base inventory walks
|
|
7
|
+
* the configured catalog, so it is computed at most once per listing instead of
|
|
8
|
+
* once per aliased row.
|
|
9
|
+
*/
|
|
10
|
+
export function modelAliasIdPromoter(config: OcxConfig) {
|
|
11
|
+
let isFastBase: ((id: string) => boolean) | undefined;
|
|
12
|
+
const fastBases = () => (isFastBase ??= fastRowBases(config));
|
|
13
|
+
return (provider: string, model: string, alias: string, fastEligible: boolean) =>
|
|
14
|
+
preferredModelAliasId(config, provider, model, alias, fastEligible, fastBases);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Promote only a short alias whose ordinary route is this exact upstream model. */
|
|
18
|
+
export function preferredModelAliasId(
|
|
19
|
+
config: OcxConfig, provider: string, model: string, alias: string, fastEligible: boolean,
|
|
20
|
+
fastBases: () => (id: string) => boolean = () => fastRowBases(config),
|
|
21
|
+
): string | undefined {
|
|
22
|
+
if (config.preferModelAliasIds !== true) return undefined;
|
|
23
|
+
// Built-in bare aliases are not stable Fast bases. Preserve the qualified ID
|
|
24
|
+
// when promotion would publish a synthetic sibling that ingress cannot parse.
|
|
25
|
+
if (config.fastRows !== false && fastEligible && !fastBases()(alias)) return undefined;
|
|
26
|
+
try {
|
|
27
|
+
// Preview cannot consume a combo's round-robin selection state. A policy/combo,
|
|
28
|
+
// reserved native name or another provider's native id must keep its own meaning.
|
|
29
|
+
const route = previewRouteModel(config, alias);
|
|
30
|
+
return route.routeReason === "model-alias" && route.providerName === provider && route.modelId === model
|
|
31
|
+
? alias : undefined;
|
|
32
|
+
} catch {
|
|
33
|
+
// An ambiguous alias stays available through the existing qualified public id.
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -21,6 +21,7 @@ export { LINK_INGRESS_HOSTNAME } from "./link-listener";
|
|
|
21
21
|
import type { ServerIngress } from "./serve-options";
|
|
22
22
|
|
|
23
23
|
export interface OptionalListenerStartContext<T> {
|
|
24
|
+
startProxy?: typeof import("../../claude/intercept/connect-proxy").startConnectProxy;
|
|
24
25
|
config: OcxConfig;
|
|
25
26
|
publicPort: number;
|
|
26
27
|
requestedPort?: number;
|
|
@@ -106,6 +107,7 @@ export function createOptionalListenerSet<T>(linkDeps: LinkListenerDeps = {}): O
|
|
|
106
107
|
}
|
|
107
108
|
supervisorStop = () => supervisor.stop();
|
|
108
109
|
claudeIntercept.start({
|
|
110
|
+
startProxy: ctx.startProxy,
|
|
109
111
|
config: ctx.config,
|
|
110
112
|
publicPort: ctx.publicPort,
|
|
111
113
|
requestedPort: ctx.requestedPort,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Server, ServerWebSocket } from "bun";
|
|
2
|
+
import { modelAliasIdPromoter } from "./model-alias-id";
|
|
2
3
|
import type { StartServerDeps } from "./startup-warnings";
|
|
3
4
|
import { isLinkManagementPath } from "../../link/management-routes";
|
|
4
5
|
import {
|
|
@@ -1252,6 +1253,7 @@ export function createServeOptions(ctx: ServeOptionsContext) {
|
|
|
1252
1253
|
effortRowKnownIds,
|
|
1253
1254
|
));
|
|
1254
1255
|
};
|
|
1256
|
+
const promoteAliasId = modelAliasIdPromoter(config);
|
|
1255
1257
|
const routedRows = await Promise.all(uniqueCatalogModelsForRawPublicList(goOrdered)
|
|
1256
1258
|
.filter(m => listAllows(m.provider, m.id))
|
|
1257
1259
|
.map(async m => {
|
|
@@ -1269,8 +1271,11 @@ export function createServeOptions(ctx: ServeOptionsContext) {
|
|
|
1269
1271
|
knownModelIdsForProvider(m.provider, provider, config),
|
|
1270
1272
|
).get(m.id)
|
|
1271
1273
|
: undefined;
|
|
1274
|
+
const effectiveId = !isCombo && !fastModelId && effective
|
|
1275
|
+
? promoteAliasId(m.provider, m.id, effective.alias, catalogRowFastEligible(m)) ?? publicId
|
|
1276
|
+
: publicId;
|
|
1272
1277
|
const row = {
|
|
1273
|
-
id:
|
|
1278
|
+
id: effectiveId,
|
|
1274
1279
|
object: "model",
|
|
1275
1280
|
created: 0,
|
|
1276
1281
|
// This endpoint is an OpenAI-compatible inbound contract. Some clients use
|
|
@@ -1279,6 +1284,9 @@ export function createServeOptions(ctx: ServeOptionsContext) {
|
|
|
1279
1284
|
owned_by: isCombo ? "openai" : (m.owned_by ?? m.provider),
|
|
1280
1285
|
...(isCombo ? { is_combo: true } : {}),
|
|
1281
1286
|
...(effective ? { alias_of: `${provider?.alias || m.provider}/${effective.alias}` } : {}),
|
|
1287
|
+
// When preferModelAliasIds promotes the alias to `id`, retain the original
|
|
1288
|
+
// provider/nativeId so clients that need the upstream identity can read it.
|
|
1289
|
+
...(effectiveId !== publicId ? { native_id: publicId } : {}),
|
|
1282
1290
|
...grokEffortFields(m.reasoningEfforts ?? [], m.defaultReasoningEffort),
|
|
1283
1291
|
...modelCapabilityFields({
|
|
1284
1292
|
reasoningEfforts: m.reasoningEfforts,
|
|
@@ -1610,11 +1618,17 @@ export function createServeOptions(ctx: ServeOptionsContext) {
|
|
|
1610
1618
|
// Promote a caller `x-session-id` before admission, as Responses and Messages do (#6520):
|
|
1611
1619
|
// the ChatGPT bridge forwards only canonical session headers, so the raw marker is lost.
|
|
1612
1620
|
const sessionReq = withCallerSessionIdentity(req, admission);
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1621
|
+
// Only expose an id when the handler or a logged refusal owns its history row.
|
|
1622
|
+
let ownsRequestLog = false;
|
|
1623
|
+
const response = await runAdmittedHttpTurn(sessionReq, policy, async turnAdmissionLease => {
|
|
1624
|
+
ownsRequestLog = true;
|
|
1625
|
+
return withCors(
|
|
1626
|
+
await handleChatCompletions(sessionReq, config, logCtx, { requestId, start, turnAdmissionLease, admission }),
|
|
1627
|
+
req,
|
|
1628
|
+
policy,
|
|
1629
|
+
);
|
|
1630
|
+
}, { requestId, start, logCtx, onLogged: () => { ownsRequestLog = true; } });
|
|
1631
|
+
return ownsRequestLog ? withRequestLogId(response, requestId) : response;
|
|
1618
1632
|
}
|
|
1619
1633
|
|
|
1620
1634
|
if (url.pathname === "/v1/audio/transcriptions" && req.method === "POST") {
|
|
@@ -149,6 +149,8 @@ export function withRequestLogId(response: Response, requestId: string): Respons
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
export interface StartServerDeps {
|
|
152
|
+
/** Test-only CONNECT binder; permits kernel-assigned ports without probe-and-release races. */
|
|
153
|
+
startClaudeInterceptProxy?: typeof import("../../claude/intercept/connect-proxy").startConnectProxy;
|
|
152
154
|
/** Test-only seam; production always initializes its own management credential state. */
|
|
153
155
|
managementAuthState?: ManagementAuthState;
|
|
154
156
|
/** Test-only route dependencies, forwarded only after management admission succeeds. */
|
|
@@ -89,6 +89,7 @@ import {
|
|
|
89
89
|
import type { ServeOptionsContext } from "./serve-options";
|
|
90
90
|
import type { RequestMetricsRecorder } from "../request-metrics";
|
|
91
91
|
import { resolveInboundBodyLimitBytes } from "../request-decompress";
|
|
92
|
+
import { responseToolOwnership } from "../responses/response-tool-ownership";
|
|
92
93
|
|
|
93
94
|
/**
|
|
94
95
|
* The WebSocket half of the Bun.serve options, split out of serve-options.ts to keep that file
|
|
@@ -184,6 +185,8 @@ export function createWebsocketHandler(
|
|
|
184
185
|
}
|
|
185
186
|
return;
|
|
186
187
|
}
|
|
188
|
+
if (ws.data.responsesActivity?.closing) return;
|
|
189
|
+
ws.data.responsesActivity?.touch();
|
|
187
190
|
const rawBytes = typeof raw === "string" ? Buffer.byteLength(raw) : raw.byteLength;
|
|
188
191
|
if (rawBytes > MAX_WS_FRAME_BYTES) {
|
|
189
192
|
sendJsonFrame(ws, buildWsErrorFrame(413, {
|
|
@@ -223,6 +226,7 @@ export function createWebsocketHandler(
|
|
|
223
226
|
if (frame.type === "response.inject") {
|
|
224
227
|
if (!ws.data.nativeControl?.inject) throw new NativeSteeringError("injection_not_supported", "Native injection is disabled or unavailable on this route.");
|
|
225
228
|
ws.data.nativeControl.inject(frame);
|
|
229
|
+
ws.data.responsesActivity?.acceptResults(frame.input);
|
|
226
230
|
return;
|
|
227
231
|
}
|
|
228
232
|
if (frame.type === "response.steer") {
|
|
@@ -230,7 +234,10 @@ export function createWebsocketHandler(
|
|
|
230
234
|
ws.data.nativeControl.steer(frame);
|
|
231
235
|
return;
|
|
232
236
|
}
|
|
233
|
-
if (ws.data.nativeControl?.continue(frame))
|
|
237
|
+
if (ws.data.nativeControl?.continue(frame)) {
|
|
238
|
+
ws.data.responsesActivity?.acceptResults(frame.input);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
234
241
|
} catch (error) {
|
|
235
242
|
sendJsonFrame(ws, buildWsErrorFrame(400, {
|
|
236
243
|
type: "invalid_request_error",
|
|
@@ -294,6 +301,7 @@ export function createWebsocketHandler(
|
|
|
294
301
|
}
|
|
295
302
|
|
|
296
303
|
// Only a genuinely admitted turn may receive steering or continuations.
|
|
304
|
+
const finishActivity = ws.data.responsesActivity?.beginTurn(frame.input);
|
|
297
305
|
ws.data.nativeControl = nativeControl;
|
|
298
306
|
const payload: Record<string, unknown> = { ...frame };
|
|
299
307
|
delete payload.type;
|
|
@@ -346,11 +354,16 @@ export function createWebsocketHandler(
|
|
|
346
354
|
terminalRecorder = recorder;
|
|
347
355
|
},
|
|
348
356
|
});
|
|
357
|
+
const observeLog = nativeControl?.relayActive
|
|
358
|
+
? createNativeSteeringLogObserver(logCtx, () => recordFirstOutput(logCtx, start))
|
|
359
|
+
: (payload: string) => inspectResponseLogSsePayload(logCtx, payload);
|
|
360
|
+
const providerExecuted = responseToolOwnership(response);
|
|
349
361
|
await sendResponseToWebSocket(ws, response, isCurrent, {
|
|
350
362
|
untilEof: nativeControl?.relayActive === true,
|
|
351
|
-
onSsePayload:
|
|
352
|
-
|
|
353
|
-
|
|
363
|
+
onSsePayload: payload => {
|
|
364
|
+
ws.data.responsesActivity?.observePayload(payload, providerExecuted);
|
|
365
|
+
observeLog(payload);
|
|
366
|
+
},
|
|
354
367
|
onTerminal: status => {
|
|
355
368
|
terminalRecorder?.(status, logCtx.terminalHttpStatus);
|
|
356
369
|
finalizeLog(httpStatusForRequestLogTerminal(status, logCtx), {
|
|
@@ -392,6 +405,7 @@ export function createWebsocketHandler(
|
|
|
392
405
|
/* socket already gone or send dropped */
|
|
393
406
|
}
|
|
394
407
|
} finally {
|
|
408
|
+
finishActivity?.();
|
|
395
409
|
turnAdmissionLease.release();
|
|
396
410
|
if (ws.data.nativeControl === nativeControl) ws.data.nativeControl = undefined;
|
|
397
411
|
if (!logged && turnAbort.signal.aborted) finalizeLog(499);
|
package/src/server/index.ts
CHANGED
|
@@ -267,17 +267,17 @@ function startServerWithSpendLedgerOwner(port: number | undefined, deps: StartSe
|
|
|
267
267
|
startupOwnershipHomes = homes;
|
|
268
268
|
startupOwnershipStatePaths = statePaths;
|
|
269
269
|
} catch { /* inspection below stays unknown */ }
|
|
270
|
-
const startupCacheOwnership = inspectStartupOwnership(
|
|
270
|
+
const startupCacheOwnership = shouldSyncCodexOnStart(config) ? inspectStartupOwnership(
|
|
271
271
|
deps,
|
|
272
272
|
startupOwnershipHomes,
|
|
273
273
|
startupOwnershipStatePaths,
|
|
274
274
|
startupWindowsTaskListingCache,
|
|
275
|
-
);
|
|
275
|
+
) : null;
|
|
276
276
|
// Startup cache invalidation is best-effort and applies only when startup sync is enabled.
|
|
277
277
|
// Check OFF before taking K: on Windows K resolves SID + LocalAppData through PowerShell,
|
|
278
278
|
// and run 35093667426 exceeded healthy controls by 33.8 s against that 30 s child budget.
|
|
279
279
|
// The permit callback still re-reads intent under K to close a concurrent disable race.
|
|
280
|
-
if (
|
|
280
|
+
if (startupCacheOwnership?.ownership === "owned" && startupOwnershipHomes !== null) {
|
|
281
281
|
try {
|
|
282
282
|
const startupCodexHome = startupOwnershipHomes.codexHome;
|
|
283
283
|
// #1046: record whether this actually rewrote the cache. `handleStart` ORs this
|
|
@@ -549,12 +549,12 @@ function startServerWithSpendLedgerOwner(port: number | undefined, deps: StartSe
|
|
|
549
549
|
// clients; no Codex request can use this lifecycle in that state.
|
|
550
550
|
// Re-probe here instead of trusting the earlier cache decision: startup work
|
|
551
551
|
// between the two sites must not widen the service-install race.
|
|
552
|
-
const nativeOwnership = inspectStartupOwnership(
|
|
552
|
+
const nativeOwnership = shouldSyncCodexOnStart(config) ? inspectStartupOwnership(
|
|
553
553
|
deps,
|
|
554
554
|
startupOwnershipHomes,
|
|
555
555
|
startupOwnershipStatePaths,
|
|
556
|
-
);
|
|
557
|
-
const preparedNativeMainLifecycle = nativeOwnership.ownership !== "foreign"
|
|
556
|
+
) : null;
|
|
557
|
+
const preparedNativeMainLifecycle = nativeOwnership !== null && nativeOwnership.ownership !== "foreign"
|
|
558
558
|
&& startupOwnershipHomes !== null
|
|
559
559
|
? prepareNativeMainStartupLifecycle(
|
|
560
560
|
deps.nativeMainStartup,
|
|
@@ -600,7 +600,7 @@ function startServerWithSpendLedgerOwner(port: number | undefined, deps: StartSe
|
|
|
600
600
|
return retryPreparedNativeMainLifecycle.start();
|
|
601
601
|
},
|
|
602
602
|
};
|
|
603
|
-
const nativeMainLifecycle: NativeMainStartupLifecycle =
|
|
603
|
+
const nativeMainLifecycle: NativeMainStartupLifecycle = nativeOwnership !== null
|
|
604
604
|
? nativeOwnership.ownership === "owned"
|
|
605
605
|
? preparedNativeMainLifecycle
|
|
606
606
|
? preparedNativeMainLifecycle.start()
|
|
@@ -738,7 +738,7 @@ function startServerWithSpendLedgerOwner(port: number | undefined, deps: StartSe
|
|
|
738
738
|
throw new AuxiliaryListenerBindError("hub.managementIngress", managementIngressPort, "127.0.0.1", error);
|
|
739
739
|
}
|
|
740
740
|
}
|
|
741
|
-
optionalListeners.start({ config, publicPort: server.port ?? listenPort, requestedPort: listenPort,
|
|
741
|
+
optionalListeners.start({ config, publicPort: server.port ?? listenPort, requestedPort: listenPort, startProxy: deps.startClaudeInterceptProxy,
|
|
742
742
|
maxRequestBodySize: inboundBodyLimitBytes, dispatch: (req, requestServer) => serveOptions.fetch(req, requestServer) });
|
|
743
743
|
} catch (error) {
|
|
744
744
|
unregisterQuotaAutoRefresh?.();
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { RequestLogContext } from "../request-log";
|
|
2
|
+
import { ADVISOR_INTERNAL_CAPABILITY_HEADER, isInternalCallCapability } from "../../lib/local-internal-call-capability";
|
|
3
|
+
|
|
4
|
+
export const ADVISOR_REASONING_HEADER = "x-opencodex-advisor-reasoning";
|
|
5
|
+
const EFFORTS = new Set(["none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"]);
|
|
6
|
+
|
|
7
|
+
/** Native Chat sends the finalized body directly instead of the translating adapter builder. */
|
|
8
|
+
export function observeAdvisorNativeReasoning(headers: Headers, log: RequestLogContext, body: string): void {
|
|
9
|
+
if (!isInternalCallCapability(headers.get(ADVISOR_INTERNAL_CAPABILITY_HEADER))) return;
|
|
10
|
+
delete log.effectiveEffort;
|
|
11
|
+
try {
|
|
12
|
+
const effort = JSON.parse(body)?.reasoning_effort;
|
|
13
|
+
if (typeof effort === "string" && EFFORTS.has(effort)) log.effectiveEffort = effort;
|
|
14
|
+
} catch { /* absence of evidence stays unreported */ }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Only the authenticated internal caller receives adapter-owned serialization evidence. */
|
|
18
|
+
export function attachAdvisorReasoning(response: Response, log: RequestLogContext): Response {
|
|
19
|
+
const headers = new Headers(response.headers);
|
|
20
|
+
headers.set(ADVISOR_REASONING_HEADER, JSON.stringify({
|
|
21
|
+
effectiveEffort: log.effectiveEffort && EFFORTS.has(log.effectiveEffort) ? log.effectiveEffort : null,
|
|
22
|
+
}));
|
|
23
|
+
return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function readAdvisorReasoning(headers: Headers): string | null {
|
|
27
|
+
try {
|
|
28
|
+
const value = JSON.parse(headers.get(ADVISOR_REASONING_HEADER) ?? "null")?.effectiveEffort;
|
|
29
|
+
return typeof value === "string" && EFFORTS.has(value) ? value : null;
|
|
30
|
+
} catch { return null; }
|
|
31
|
+
}
|
package/src/server/lifecycle.ts
CHANGED
|
@@ -38,6 +38,7 @@ export interface ActiveTurnLease extends AdmissionLease {
|
|
|
38
38
|
attach(lease: AdmissionLease): void;
|
|
39
39
|
bindAbortSignal(signal: AbortSignal): () => void;
|
|
40
40
|
bindAbortController(ac: AbortController): void;
|
|
41
|
+
unbindAbortController(ac: AbortController): void;
|
|
41
42
|
beginCodexAccountSelection(): CodexAccountSelectionAdmission;
|
|
42
43
|
isTransferred(): boolean;
|
|
43
44
|
}
|
|
@@ -231,6 +232,17 @@ export function tryAdmitTurn(sessionLaneId?: string, clientSignal?: AbortSignal)
|
|
|
231
232
|
activeTurns.set(ac, lease);
|
|
232
233
|
lease.bindAbortSignal(ac.signal);
|
|
233
234
|
},
|
|
235
|
+
unbindAbortController(ac) {
|
|
236
|
+
if (!controllers.delete(ac)) return;
|
|
237
|
+
if (activeTurns.get(ac) === lease) activeTurns.delete(ac);
|
|
238
|
+
const listener = abortListeners.get(ac.signal);
|
|
239
|
+
if (listener) {
|
|
240
|
+
ac.signal.removeEventListener("abort", listener);
|
|
241
|
+
abortListeners.delete(ac.signal);
|
|
242
|
+
}
|
|
243
|
+
// A completed child relay cannot retire its still-running parent turn.
|
|
244
|
+
if (controllers.size === 0) lease.release();
|
|
245
|
+
},
|
|
234
246
|
beginCodexAccountSelection() {
|
|
235
247
|
const mainProfileDraining = nativeMainDrainOwners.size > 0;
|
|
236
248
|
let selectionActive = active && !mainProfileDraining;
|
|
@@ -327,7 +339,7 @@ export function unregisterTurn(ac: AbortController): void {
|
|
|
327
339
|
turnReleaseMisses += 1;
|
|
328
340
|
return;
|
|
329
341
|
}
|
|
330
|
-
lease.
|
|
342
|
+
lease.unbindAbortController(ac);
|
|
331
343
|
}
|
|
332
344
|
export function isDraining(): boolean { return shutdownDraining || temporaryDrainOwners.size > 0; }
|
|
333
345
|
export function getActiveTurnCount(): number { return turnGate.metrics().active; }
|
|
@@ -20,10 +20,12 @@ import {
|
|
|
20
20
|
isCurrentAdvisorContextSharingConsent,
|
|
21
21
|
isValidAdvisorEffort,
|
|
22
22
|
isValidAdvisorPolicy,
|
|
23
|
+
isValidAdvisorTaskLimit,
|
|
23
24
|
resolveAdvisorSettings,
|
|
24
25
|
type AdvisorEffort,
|
|
25
26
|
type AdvisorPolicy,
|
|
26
27
|
} from "../../advisor/settings";
|
|
28
|
+
import { advisorActivityStore } from "../../advisor/activity";
|
|
27
29
|
|
|
28
30
|
const INVALID_BODY = Symbol("invalid-body");
|
|
29
31
|
|
|
@@ -33,6 +35,7 @@ interface AdvisorPatch {
|
|
|
33
35
|
effort?: AdvisorEffort;
|
|
34
36
|
policy?: AdvisorPolicy;
|
|
35
37
|
timeoutMs?: number;
|
|
38
|
+
maxConsultationsPerTask?: number;
|
|
36
39
|
/** "v1" records current consent. null removes it. Enabling does not imply this field. */
|
|
37
40
|
contextSharingConsent?: typeof ADVISOR_CONTEXT_SHARING_CONSENT_VERSION | null;
|
|
38
41
|
reset?: boolean;
|
|
@@ -40,7 +43,7 @@ interface AdvisorPatch {
|
|
|
40
43
|
|
|
41
44
|
type ParsedPatch = { ok: true; patch: AdvisorPatch } | { ok: false; code: string; message: string };
|
|
42
45
|
|
|
43
|
-
const PATCH_KEYS = new Set(["enabled", "model", "effort", "policy", "timeoutMs", "contextSharingConsent", "reset"]);
|
|
46
|
+
const PATCH_KEYS = new Set(["enabled", "model", "effort", "policy", "timeoutMs", "maxConsultationsPerTask", "contextSharingConsent", "reset"]);
|
|
44
47
|
|
|
45
48
|
type Rec = Record<string, unknown>;
|
|
46
49
|
function isRec(value: unknown): value is Rec {
|
|
@@ -50,9 +53,9 @@ function isRec(value: unknown): value is Rec {
|
|
|
50
53
|
/** Strict: unknown keys and wrong types are refused; messages name the field, never the value. */
|
|
51
54
|
export function parseAdvisorSettingsPatch(body: unknown): ParsedPatch {
|
|
52
55
|
if (!isRec(body)) return { ok: false, code: "invalid_body", message: "body must be a JSON object" };
|
|
53
|
-
if (Object.keys(body).length === 0) return { ok: false, code: "empty_body", message: "body must set at least one
|
|
56
|
+
if (Object.keys(body).length === 0) return { ok: false, code: "empty_body", message: "body must set at least one supported advisor setting or reset" };
|
|
54
57
|
for (const key of Object.keys(body)) {
|
|
55
|
-
if (!PATCH_KEYS.has(key)) return { ok: false, code: "unknown_field", message: "body accepts only enabled, model, effort, policy, timeoutMs, contextSharingConsent and reset" };
|
|
58
|
+
if (!PATCH_KEYS.has(key)) return { ok: false, code: "unknown_field", message: "body accepts only enabled, model, effort, policy, timeoutMs, maxConsultationsPerTask, contextSharingConsent and reset" };
|
|
56
59
|
}
|
|
57
60
|
const patch: AdvisorPatch = {};
|
|
58
61
|
if (body.reset !== undefined) {
|
|
@@ -86,7 +89,7 @@ export function parseAdvisorSettingsPatch(body: unknown): ParsedPatch {
|
|
|
86
89
|
}
|
|
87
90
|
if (body.policy !== undefined) {
|
|
88
91
|
if (!isValidAdvisorPolicy(body.policy)) {
|
|
89
|
-
return { ok: false, code: "invalid_policy", message: 'policy must be "manual" or "
|
|
92
|
+
return { ok: false, code: "invalid_policy", message: 'policy must be "manual", "preflight" or "adaptive"' };
|
|
90
93
|
}
|
|
91
94
|
patch.policy = body.policy;
|
|
92
95
|
}
|
|
@@ -96,6 +99,10 @@ export function parseAdvisorSettingsPatch(body: unknown): ParsedPatch {
|
|
|
96
99
|
}
|
|
97
100
|
patch.timeoutMs = Math.floor(body.timeoutMs);
|
|
98
101
|
}
|
|
102
|
+
if (body.maxConsultationsPerTask !== undefined) {
|
|
103
|
+
if (!isValidAdvisorTaskLimit(body.maxConsultationsPerTask)) return { ok: false, code: "invalid_task_limit", message: "maxConsultationsPerTask must be an integer between 1 and 3" };
|
|
104
|
+
patch.maxConsultationsPerTask = body.maxConsultationsPerTask;
|
|
105
|
+
}
|
|
99
106
|
if (body.contextSharingConsent !== undefined) {
|
|
100
107
|
if (body.contextSharingConsent === null) {
|
|
101
108
|
patch.contextSharingConsent = null;
|
|
@@ -139,6 +146,7 @@ function applyPatchInMemory(config: ManagementContext["config"], patch: AdvisorP
|
|
|
139
146
|
if (patch.effort !== undefined) current.effort = patch.effort;
|
|
140
147
|
if (patch.policy !== undefined) current.policy = patch.policy;
|
|
141
148
|
if (patch.timeoutMs !== undefined) current.timeoutMs = patch.timeoutMs;
|
|
149
|
+
if (patch.maxConsultationsPerTask !== undefined) current.maxConsultationsPerTask = patch.maxConsultationsPerTask;
|
|
142
150
|
if (patch.contextSharingConsent === null) delete current.contextSharingConsent;
|
|
143
151
|
else if (patch.contextSharingConsent !== undefined) current.contextSharingConsent = patch.contextSharingConsent;
|
|
144
152
|
config.advisor = current as ManagementContext["config"]["advisor"];
|
|
@@ -152,6 +160,9 @@ function isConfigLockContention(error: unknown): boolean {
|
|
|
152
160
|
|
|
153
161
|
export async function handleAdvisorRoutes(ctx: ManagementContext): Promise<Response | null> {
|
|
154
162
|
const { url, req, config } = ctx;
|
|
163
|
+
if (url.pathname === "/api/advisor/activity" && req.method === "GET") {
|
|
164
|
+
return jsonResponse({ entries: advisorActivityStore(config).snapshot(), retention: "process", limit: 100 }, 200, req, config);
|
|
165
|
+
}
|
|
155
166
|
if (url.pathname !== "/api/advisor/settings") return null;
|
|
156
167
|
|
|
157
168
|
if (req.method === "GET") return jsonResponse(advisorInfo(config), 200, req, config);
|
|
@@ -44,7 +44,7 @@ export function pickerPreferenceOn(config: Pick<OcxConfig, "claudeCode">): boole
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
const PICKER_BODY_KEYS = new Set(["enabled", "persist", "trustedLocally", "callerAddedTrust"]);
|
|
47
|
-
/** Enable outcomes that are progress, not refusal: on, waiting for a Desktop restart, or for
|
|
47
|
+
/** Enable outcomes that are progress, not refusal: on, waiting for a Desktop restart, or for certificate trust. */
|
|
48
48
|
const ENABLE_ACCEPTED = new Set(["active", "restart_required", "trust_pending"]);
|
|
49
49
|
|
|
50
50
|
interface PickerRequestBody { enabled: boolean; persist: boolean; trustedLocally?: boolean; callerAddedTrust?: boolean }
|