@bitkyc08/opencodex 2.86.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/gui/dist/assets/App-ZfYbLHkB.js +58 -0
- package/gui/dist/assets/App-wT3mXqFz.css +1 -0
- package/gui/dist/assets/{Tray-DyR9yBee.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 -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.ts +108 -21
- 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.ts +35 -8
- 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 +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/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 +11 -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 +38 -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 +17 -14
- 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/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 +12 -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/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 +52 -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 +608 -284
- 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/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/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 +33 -7
- 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 +5 -4
- 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/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 +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/router.ts +8 -321
- 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 +55 -414
- package/src/server/effort-policy.ts +1 -1
- package/src/server/images.ts +15 -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 +9 -1
- package/src/server/index/startup-warnings.ts +2 -0
- package/src/server/index.ts +1 -1
- package/src/server/inference/advisor-diagnostics.ts +31 -0
- 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 +101 -21
- 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 +13 -1
- package/src/server/responses/adapter-delivery.ts +19 -6
- package/src/server/responses/adapter-dispatch.ts +19 -2
- package/src/server/responses/advisor-retention.ts +117 -0
- package/src/server/responses/advisor-slot.ts +73 -41
- 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 +2 -0
- package/src/server/responses/core-combo.ts +120 -36
- package/src/server/responses/core-errors.ts +3 -3
- package/src/server/responses/core-lifetime.ts +5 -2
- package/src/server/responses/core-opaque-recovery.ts +35 -0
- package/src/server/responses/core-options.ts +5 -0
- package/src/server/responses/core-pipeline.ts +141 -0
- package/src/server/responses/core-replay.ts +18 -2
- 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/request-prepare.ts +76 -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 +1 -0
- package/src/server/responses/run-turn-execution.ts +96 -30
- package/src/server/responses/sidecar-execution.ts +20 -2
- package/src/server/responses/terminal-guard.ts +2 -16
- 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 +29 -0
- package/src/types/provider.ts +32 -6
- package/src/types/request.ts +23 -2
- package/src/types/wire.ts +29 -37
- package/src/types.ts +1 -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 +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/loop.ts +55 -5
- package/src/web-search/progress-stream.ts +4 -1
- 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
package/src/web-search/loop.ts
CHANGED
|
@@ -6,6 +6,9 @@ import { cloneProviderOpaqueToolCallMetadata } from "../responses/provider-opaqu
|
|
|
6
6
|
import type { AttemptRecoveryKind } from "../usage/log";
|
|
7
7
|
import { isTruncatedStopReason } from "../responses/truncated-stop-reason";
|
|
8
8
|
import { bridgeToResponsesSSE } from "../bridge";
|
|
9
|
+
import { isTerminalRefusalIncomplete } from "../bridge/terminal-refusal";
|
|
10
|
+
import { guardEmptyToolCatalogStream, type ClientToolCatalogRestriction } from "../lib/empty-tool-catalog";
|
|
11
|
+
import { mergeUsage } from "../server/responses/empty-completion-guard";
|
|
9
12
|
import { runWebSearch, type SidecarOutcome, type SidecarOutcomeRecorder, type SidecarSettings } from "./executor";
|
|
10
13
|
import { runAnthropicWebSearch } from "./anthropic-executor";
|
|
11
14
|
import { runXaiWebSearch, type XaiSearchOptions } from "./xai-executor";
|
|
@@ -143,6 +146,18 @@ async function* replay(events: AdapterEvent[]): AsyncGenerator<AdapterEvent> {
|
|
|
143
146
|
for (const e of events) yield e;
|
|
144
147
|
}
|
|
145
148
|
|
|
149
|
+
function terminalUsage(events: AdapterEvent[]): OcxUsage | undefined {
|
|
150
|
+
for (const e of events) if (e.type === "done" || e.type === "incomplete") return e.usage;
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Hidden iterations add counters only: their checkpoint and raw wire usage are not the final terminal's. */
|
|
155
|
+
function countersOnly(usage: OcxUsage | undefined): OcxUsage | undefined {
|
|
156
|
+
if (!usage) return undefined;
|
|
157
|
+
const { contextTotalTokens: _context, rawUsage: _raw, ...counters } = usage;
|
|
158
|
+
return counters;
|
|
159
|
+
}
|
|
160
|
+
|
|
146
161
|
/**
|
|
147
162
|
* Collect the thinking block that preceded a web_search call in this iteration's events, so the
|
|
148
163
|
* replayed assistant turn can carry it. Anthropic extended thinking REQUIRES the assistant
|
|
@@ -189,7 +204,11 @@ function extractIterationThinking(events: AdapterEvent[]): OcxThinkingContent[]
|
|
|
189
204
|
};
|
|
190
205
|
|
|
191
206
|
for (const e of events) {
|
|
192
|
-
if (e.type === "
|
|
207
|
+
if (e.type === "text_delta" && e.anthropicThinkingSignature) {
|
|
208
|
+
flushVisible();
|
|
209
|
+
flushRaw();
|
|
210
|
+
parts.push({ type: "thinking", thinking: e.text, signature: e.anthropicThinkingSignature });
|
|
211
|
+
} else if (e.type === "thinking_delta") {
|
|
193
212
|
flushRaw();
|
|
194
213
|
thinking += e.thinking;
|
|
195
214
|
} else if (e.type === "reasoning_raw_delta") {
|
|
@@ -272,6 +291,7 @@ class LoopError extends Error {
|
|
|
272
291
|
*/
|
|
273
292
|
export interface WebSearchLoopDeps {
|
|
274
293
|
parsed: OcxParsedRequest;
|
|
294
|
+
clientToolCatalogRestriction?: ClientToolCatalogRestriction;
|
|
275
295
|
adapter: ProviderAdapter;
|
|
276
296
|
incomingMeta: IncomingMeta;
|
|
277
297
|
/**
|
|
@@ -297,6 +317,8 @@ export interface WebSearchLoopDeps {
|
|
|
297
317
|
settings: SidecarSettings;
|
|
298
318
|
maxSearches: number;
|
|
299
319
|
forceEmptyResponseId?: boolean;
|
|
320
|
+
/** Responses inbound only: deliver a non-retryable upstream refusal as `response.failed`. */
|
|
321
|
+
terminalRefusalAsFailed?: boolean;
|
|
300
322
|
abortSignal?: AbortSignal;
|
|
301
323
|
recordSidecarOutcome?: SidecarOutcomeRecorder;
|
|
302
324
|
beforeSidecarDispatch?: () => void;
|
|
@@ -320,6 +342,12 @@ export interface WebSearchLoopDeps {
|
|
|
320
342
|
onFirstOutput?: () => void;
|
|
321
343
|
/** Raw adapter usage at the terminal event, pre wire-normalization (see bridgeToResponsesSSE onUsage). */
|
|
322
344
|
onUsage?: (usage: OcxUsage | undefined) => void;
|
|
345
|
+
/**
|
|
346
|
+
* After an `on429` rotation, offered the usage of the hidden iterations the left credential
|
|
347
|
+
* served. Returning true means it was billed to that credential's attempt, so `onUsage` will not
|
|
348
|
+
* report it again.
|
|
349
|
+
*/
|
|
350
|
+
onRotatedUsage?: (usage: OcxUsage) => boolean;
|
|
323
351
|
/** Observe the exact adapter request selected for each routed-model iteration. */
|
|
324
352
|
onRequestBuilt?: (request: AdapterRequest) => void;
|
|
325
353
|
/** Request-scoped executor retains the core's selection binding across loop retries. */
|
|
@@ -407,6 +435,12 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
407
435
|
// One iteration beyond the forced answer is reserved for its empty-answer recovery below.
|
|
408
436
|
const HARD_CAP = maxSearches + 3;
|
|
409
437
|
let emptyAnswerRetries = 0;
|
|
438
|
+
// Every iteration re-sends the full context, but only the last one's terminal reaches the bridge.
|
|
439
|
+
// Search-calling passes and the discarded empty forced answer are summed here and added to what
|
|
440
|
+
// onUsage reports, so the request log meters what was actually sent. The client-facing terminal
|
|
441
|
+
// keeps the last iteration's usage: Codex and Claude Code size the context window from it, and
|
|
442
|
+
// a sum would read as a context several times larger and trigger early auto-compaction.
|
|
443
|
+
let hiddenUsage: OcxUsage | undefined;
|
|
410
444
|
let accountRefusalOutputStarted = false;
|
|
411
445
|
const connectTimeoutMs = deps.connectTimeoutMs ?? 200_000;
|
|
412
446
|
const routedModelStallTimeoutMs = deps.routedModelStallTimeoutMs ?? 200_000;
|
|
@@ -586,6 +620,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
586
620
|
const rotated = await deps.on429(prepared.response.headers.get("retry-after"), prepared.response.headers,
|
|
587
621
|
iterParsed, prepared.response);
|
|
588
622
|
if (!rotated) break;
|
|
623
|
+
if (hiddenUsage && deps.onRotatedUsage?.(hiddenUsage)) hiddenUsage = undefined;
|
|
589
624
|
const retainRefusal = prepared.response.status === 403
|
|
590
625
|
&& deps.incomingMeta?.providerName === "google-antigravity" && rotated.recoveryKind === "oauth-account-403";
|
|
591
626
|
// Keep the bounded refusal readable until the sibling actually returns headers.
|
|
@@ -681,6 +716,8 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
681
716
|
signal,
|
|
682
717
|
inactivityTimeoutMs: routedModelStallTimeoutMs,
|
|
683
718
|
translatorBudget,
|
|
719
|
+
// A pass that fails was still billed; the error path reports it with the hidden passes.
|
|
720
|
+
onErrorUsage: usage => { hiddenUsage = mergeUsage(hiddenUsage, usage); },
|
|
684
721
|
})) {
|
|
685
722
|
if (event.type === "heartbeat") yield event;
|
|
686
723
|
// Kiro's explicit-completion protocol marks ordinary assistant text as commentary while
|
|
@@ -689,7 +726,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
689
726
|
// Codex show only `Working` until both Kiro attempts had finished (often 30-40 seconds).
|
|
690
727
|
// Tool events remain buffered below, so the decision to invoke the hosted sidecar is still
|
|
691
728
|
// atomic and no search call can escape before its stream has validated successfully.
|
|
692
|
-
else if (event.type === "text_delta" && event.phase === "commentary") { accountRefusalOutputStarted = true; yield event; }
|
|
729
|
+
else if (event.type === "text_delta" && event.phase === "commentary" && !event.anthropicThinkingSignature) { accountRefusalOutputStarted = true; yield event; }
|
|
693
730
|
else if (liveWindowOpen && LIVE_STREAMABLE.has(event.type)) {
|
|
694
731
|
// Live events are ALSO buffered: the scanner still needs them for thinking extraction
|
|
695
732
|
// and the forced-answer output check; only the terminal replay skips them (by count).
|
|
@@ -914,7 +951,10 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
914
951
|
// limit-reached result instead of failing the turn (#6464: stripping
|
|
915
952
|
// the declaration makes some models emit the raw call as visible
|
|
916
953
|
// text).
|
|
917
|
-
|
|
954
|
+
// A refused iteration ends the turn even when it carried a search call: running the
|
|
955
|
+
// search would send the refused context back to the model (#7148).
|
|
956
|
+
const shouldLoop = split.calls.length > 0 && !split.hasRealToolCall
|
|
957
|
+
&& !split.passthrough.some(isTerminalRefusalIncomplete);
|
|
918
958
|
if (!shouldLoop) {
|
|
919
959
|
// #1001: a forced-answer pass that ends `done` must have produced
|
|
920
960
|
// usable output — never a malformed tool call, and never silence.
|
|
@@ -944,6 +984,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
944
984
|
stopReason: terminalEvent.stopReason,
|
|
945
985
|
eventTypes: [...new Set(split.passthrough.map(event => event.type))],
|
|
946
986
|
}));
|
|
987
|
+
hiddenUsage = mergeUsage(hiddenUsage, terminalEvent.usage);
|
|
947
988
|
if (!split.hasMalformedToolCall && !split.hasRealToolCall && emptyAnswerRetries === 0) {
|
|
948
989
|
emptyAnswerRetries++;
|
|
949
990
|
console.warn("[web-search-loop] empty forced answer — retrying once without tools");
|
|
@@ -966,13 +1007,19 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
966
1007
|
yield* replay(split.passthrough.slice(split.streamedPassthroughCount));
|
|
967
1008
|
return;
|
|
968
1009
|
}
|
|
1010
|
+
hiddenUsage = mergeUsage(hiddenUsage, terminalUsage(split.passthrough));
|
|
969
1011
|
// The thinking that led to the search belongs to the FIRST call's assistant replay turn.
|
|
1012
|
+
for (const event of split.passthrough.slice(split.streamedPassthroughCount)) {
|
|
1013
|
+
if (event.type === "text_delta" && event.anthropicThinkingSignature) yield event;
|
|
1014
|
+
}
|
|
970
1015
|
const iterationThinking = extractIterationThinking(split.passthrough);
|
|
971
1016
|
for (const [callIndex, call] of split.calls.entries()) {
|
|
972
1017
|
accountRefusalOutputStarted = true;
|
|
973
1018
|
yield* runSearchCall(call, callIndex === 0 ? iterationThinking : []);
|
|
974
1019
|
}
|
|
975
1020
|
} catch (e) {
|
|
1021
|
+
// The bridge reports no usage for either error; the iterations already sent still count.
|
|
1022
|
+
if (hiddenUsage) deps.onUsage?.(hiddenUsage);
|
|
976
1023
|
if (isTranslatorBudgetExceededError(e)) {
|
|
977
1024
|
yield {
|
|
978
1025
|
type: "error",
|
|
@@ -987,6 +1034,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
987
1034
|
return;
|
|
988
1035
|
}
|
|
989
1036
|
}
|
|
1037
|
+
if (hiddenUsage) deps.onUsage?.(hiddenUsage);
|
|
990
1038
|
yield { type: "error", message: "web-search loop exceeded its iteration cap" };
|
|
991
1039
|
} finally {
|
|
992
1040
|
if (abortSignal) abortSignal.removeEventListener("abort", linkAbort);
|
|
@@ -994,7 +1042,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
994
1042
|
}
|
|
995
1043
|
|
|
996
1044
|
const sse = bridgeToResponsesSSE(
|
|
997
|
-
produce(), parsed._responseModelId ?? parsed.modelId, toolNsMap, freeform, toolSearch, () => {
|
|
1045
|
+
guardEmptyToolCatalogStream(produce(), deps.clientToolCatalogRestriction, translatorBudget), parsed._responseModelId ?? parsed.modelId, toolNsMap, freeform, toolSearch, () => {
|
|
998
1046
|
const elapsed = Date.now() - loopT0;
|
|
999
1047
|
if (executedSearchCount > 0 || searchesExecuted > 0) {
|
|
1000
1048
|
console.warn(`[web-search-loop] cancelled — ${executedSearchCount} real searches, ${searchesExecuted - executedSearchCount} placeholders, ${elapsed}ms`);
|
|
@@ -1004,12 +1052,14 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
1004
1052
|
{
|
|
1005
1053
|
translatorBudget,
|
|
1006
1054
|
replayCacheScope: parsed._reasoningReplayScope,
|
|
1055
|
+
...(deps.clientToolCatalogRestriction ? { ...deps.clientToolCatalogRestriction, enforceDeclaredToolNames: false } : {}),
|
|
1007
1056
|
...(deps.forceEmptyResponseId ? { responseId: "" } : {}),
|
|
1057
|
+
...(deps.terminalRefusalAsFailed ? { terminalRefusalAsFailed: true } : {}),
|
|
1008
1058
|
hideThinkingSummary: parsed.options.hideThinkingSummary,
|
|
1009
1059
|
hideRawReasoning: parsed.options.hideRawReasoning,
|
|
1010
1060
|
...(deps.stallTimeoutSec !== undefined ? { stallTimeoutSec: deps.stallTimeoutSec } : {}),
|
|
1011
1061
|
...(deps.onFirstOutput ? { onFirstOutput: deps.onFirstOutput } : {}),
|
|
1012
|
-
...(deps.onUsage ? { onUsage: deps.onUsage } : {}),
|
|
1062
|
+
...(deps.onUsage ? { onUsage: (usage: OcxUsage | undefined) => deps.onUsage?.(mergeUsage(countersOnly(hiddenUsage), usage)) } : {}),
|
|
1013
1063
|
...(deps.onCompletedResponse ? { onCompletedResponse: deps.onCompletedResponse } : {}),
|
|
1014
1064
|
},
|
|
1015
1065
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ProviderAdapter } from "../adapters/base";
|
|
2
|
-
import type { AdapterEvent } from "../types";
|
|
2
|
+
import type { AdapterEvent, OcxUsage } from "../types";
|
|
3
3
|
import {
|
|
4
4
|
isTranslatorBudgetExceededError,
|
|
5
5
|
TRANSLATOR_MAX_TURN_BYTES,
|
|
@@ -32,6 +32,8 @@ export interface ParseStreamWithProgressOptions {
|
|
|
32
32
|
signal?: AbortSignal;
|
|
33
33
|
/** Kept configurable for focused tests; production callers should use the 5 second default. */
|
|
34
34
|
postTerminalDrainTimeoutMs?: number;
|
|
35
|
+
/** Receives the usage an adapter `error` event carries before the stream fails on it. */
|
|
36
|
+
onErrorUsage?: (usage: OcxUsage) => void;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
type ParseStream = ProviderAdapter["parseStream"];
|
|
@@ -296,6 +298,7 @@ export async function* parseStreamWithProgress(
|
|
|
296
298
|
);
|
|
297
299
|
}
|
|
298
300
|
if (event.type === "error") {
|
|
301
|
+
if (event.usage) options.onErrorUsage?.(event.usage);
|
|
299
302
|
fail(event.code === "translation_buffer_limit"
|
|
300
303
|
? new TranslatorBudgetExceededError("live_transient", TRANSLATOR_MAX_TURN_BYTES)
|
|
301
304
|
: new Error(event.message));
|
|
@@ -124,7 +124,12 @@ function extractIterationContent(events: AdapterEvent[]): OcxAssistantContentPar
|
|
|
124
124
|
rawReasoning = "";
|
|
125
125
|
};
|
|
126
126
|
for (const e of events) {
|
|
127
|
-
if (e.type === "
|
|
127
|
+
if (e.type === "text_delta" && e.anthropicThinkingSignature) {
|
|
128
|
+
flushText();
|
|
129
|
+
flushVisible();
|
|
130
|
+
flushRaw();
|
|
131
|
+
parts.push({ type: "thinking", thinking: e.text, signature: e.anthropicThinkingSignature });
|
|
132
|
+
} else if (e.type === "thinking_delta") {
|
|
128
133
|
flushText();
|
|
129
134
|
flushRaw();
|
|
130
135
|
thinking += e.thinking;
|
|
@@ -533,6 +538,9 @@ export async function* runTurnWebSearchLoop(
|
|
|
533
538
|
return;
|
|
534
539
|
}
|
|
535
540
|
|
|
541
|
+
for (const event of replayEvents) {
|
|
542
|
+
if (event.type === "text_delta" && event.anthropicThinkingSignature) yield event;
|
|
543
|
+
}
|
|
536
544
|
const iterationContent = extractIterationContent(split.passthrough);
|
|
537
545
|
for (const [callIndex, call] of split.calls.entries()) {
|
|
538
546
|
if (abortSignal?.aborted) { yield abortEvent(); return; }
|