@bitkyc08/opencodex 2.58.0 → 2.60.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 +28 -10
- package/gui/dist/assets/index-BTuCbqQd.css +1 -0
- package/gui/dist/assets/index-DoBVdPHP.js +134 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/crusoe.svg +1 -0
- package/gui/dist/provider-icons/opper.svg +3 -0
- package/package.json +4 -1
- package/src/adapters/anthropic-image-codec.ts +16 -2
- package/src/adapters/anthropic-image-normalize.ts +49 -2
- package/src/adapters/anthropic.ts +4 -1
- package/src/adapters/base.ts +34 -1
- package/src/adapters/coding-agent/turn.ts +22 -2
- package/src/adapters/command-code.ts +50 -3
- package/src/adapters/cursor/catalog.ts +11 -0
- package/src/adapters/cursor/checkpoint-store.ts +3 -0
- package/src/adapters/cursor/discovery.ts +11 -8
- package/src/adapters/cursor/effort-map.ts +16 -2
- package/src/adapters/cursor/envelope-echo.ts +55 -2
- package/src/adapters/cursor/live-transport.ts +26 -9
- package/src/adapters/cursor/message-mapper.ts +3 -2
- package/src/adapters/cursor/protobuf-request.ts +8 -5
- package/src/adapters/cursor/request-builder.ts +21 -4
- package/src/adapters/cursor/thread-continuity.ts +105 -31
- package/src/adapters/cursor/tool-guidance.ts +5 -4
- package/src/adapters/cursor/transport.ts +19 -0
- package/src/adapters/cursor.ts +45 -2
- package/src/adapters/devin/cloud-direct/chat.ts +14 -3
- package/src/adapters/devin/cloud-direct/index.ts +7 -0
- package/src/adapters/devin/cloud-direct/stated-reset-retry.ts +140 -0
- package/src/adapters/devin.ts +125 -26
- package/src/adapters/google-antigravity-replay.ts +1 -1
- package/src/adapters/google-antigravity-wire.ts +55 -4
- package/src/adapters/google-http.ts +57 -11
- package/src/adapters/google-tool-schema.ts +595 -31
- package/src/adapters/google-wire-compiler.ts +93 -10
- package/src/adapters/google-wire-shape.ts +461 -0
- package/src/adapters/google.ts +60 -10
- package/src/adapters/openai-chat/response-events.ts +61 -0
- package/src/adapters/openai-chat-images.ts +3 -1
- package/src/adapters/openai-chat.ts +10 -11
- package/src/adapters/openai-responses/image-gen.ts +8 -6
- package/src/adapters/openai-responses/passthrough.ts +25 -4
- package/src/adapters/openai-responses/reasoning.ts +7 -0
- package/src/adapters/openai-responses/tool-output-recovery.ts +75 -0
- package/src/adapters/openai-responses/tool-schema.ts +19 -7
- package/src/adapters/opencode-go-additional-tools.ts +12 -2
- package/src/adapters/responses-tool-schema.ts +76 -46
- package/src/adapters/run-turn-queue.ts +17 -4
- package/src/bridge/response-json.ts +1 -1
- package/src/bridge/sse.ts +28 -35
- package/src/claude/context-windows.ts +22 -0
- package/src/claude/outbound.ts +35 -4
- package/src/cli/account-api.ts +4 -3
- package/src/cli/account-extended.ts +26 -6
- package/src/cli/account-orca-import.ts +63 -0
- package/src/cli/account.ts +32 -4
- package/src/cli/capabilities.ts +40 -0
- package/src/cli/claude.ts +29 -1
- package/src/cli/codex-cli-update.ts +97 -2
- package/src/cli/dispatch.ts +57 -3
- package/src/cli/doctor.ts +218 -4
- package/src/cli/help.ts +4 -1
- package/src/cli/hub.ts +3 -2
- package/src/cli/index.ts +95 -22
- package/src/cli/models-runtime.ts +33 -4
- package/src/cli/opencode.ts +2 -2
- package/src/cli/provider.ts +13 -1
- package/src/cli/registry.ts +11 -1
- package/src/cli/runtime-api.ts +44 -0
- package/src/cli/start-args.ts +94 -0
- package/src/cli/system-command.ts +2 -0
- package/src/client/machine-api.ts +6 -5
- package/src/client/machine-listener.ts +16 -3
- package/src/client/runtime.ts +26 -2
- package/src/clients/config-export/constants.ts +2 -3
- package/src/clients/config-export.ts +5 -5
- package/src/codex/account-store.ts +146 -5
- package/src/codex/auth-api/account-list.ts +19 -11
- package/src/codex/auth-api/pool-quota-probe.ts +44 -10
- package/src/codex/auth-api/routes.ts +17 -2
- package/src/codex/auth-context.ts +16 -12
- package/src/codex/catalog/build-entries.ts +25 -4
- package/src/codex/catalog/derive-entry.ts +8 -1
- package/src/codex/catalog/effort.ts +10 -6
- package/src/codex/catalog/gather-capture.ts +22 -2
- package/src/codex/catalog/model-hints.ts +66 -33
- package/src/codex/catalog/parsing.ts +90 -5
- package/src/codex/catalog/provider-models.ts +19 -2
- package/src/codex/catalog/reserve-warn.ts +96 -0
- package/src/codex/catalog/retained-sync.ts +41 -26
- package/src/codex/catalog/routed-gather.ts +61 -3
- package/src/codex/cli-installation-identity.ts +210 -0
- package/src/codex/cli-installation-targets.ts +158 -0
- package/src/codex/context-compat.ts +5 -2
- package/src/codex/convergence.ts +5 -0
- package/src/codex/desired-state.ts +4 -1
- package/src/codex/history-job.ts +6 -6
- package/src/codex/history-provider.ts +24 -167
- package/src/codex/history-rollout-read.ts +174 -0
- package/src/codex/history-state-open.ts +105 -0
- package/src/codex/inject/config-toml.ts +44 -2
- package/src/codex/inject.ts +3 -2
- package/src/codex/internal/catalog-writer.ts +33 -1
- package/src/codex/lineage.ts +83 -32
- package/src/codex/loopback-target.ts +31 -0
- package/src/codex/main-account-hard-lock.ts +2 -1
- package/src/codex/main-account.ts +10 -3
- package/src/codex/main-device-reauth.ts +17 -9
- package/src/codex/model-cache.ts +47 -0
- package/src/codex/model-entitlements.ts +80 -2
- package/src/codex/observed-model-denials.ts +230 -0
- package/src/codex/orca-auth-source.ts +94 -0
- package/src/codex/orca-import.ts +219 -0
- package/src/codex/prompt-text-probe.ts +289 -16
- package/src/codex/quota-401-recovery.ts +12 -0
- package/src/codex/quota-types.ts +65 -0
- package/src/codex/quota.ts +24 -19
- package/src/codex/routing/cooldown-math.ts +8 -47
- package/src/codex/routing/pin-drain.ts +57 -0
- package/src/codex/routing.ts +20 -16
- package/src/codex/shim.ts +1 -1
- package/src/codex/subagent-model-fallback.ts +114 -2
- package/src/codex/windows-installation-files.ts +224 -0
- package/src/combos/failover.ts +125 -5
- package/src/config/admitted-identity.ts +222 -0
- package/src/config/diagnostics.ts +43 -1
- package/src/config/feature-flags.ts +5 -0
- package/src/config/load-degrade.ts +33 -0
- package/src/config/pending-teardown.ts +8 -0
- package/src/config/process-state.ts +36 -3
- package/src/config/provider-relative-send-path.ts +16 -0
- package/src/config/proxy-env.ts +31 -7
- package/src/config/schema/compaction-triggers.ts +11 -0
- package/src/config/schema/config-schema.ts +25 -0
- package/src/config/schema/leaf-validators.ts +76 -17
- package/src/config.ts +2 -2
- package/src/generated/compatibility-version.json +410 -258
- package/src/generated/model-metadata.ts +1 -1
- package/src/grok/reset-coupons.ts +38 -19
- package/src/images/loop.ts +6 -1
- package/src/integrations/aside-profile-context.ts +37 -3
- package/src/integrations/aside-profile-journal.ts +68 -3
- package/src/integrations/aside-profiles.ts +128 -3
- package/src/integrations/mutation-plan.ts +815 -0
- package/src/integrations/writer.ts +85 -99
- package/src/lab/live/transport.ts +4 -0
- package/src/lab/live/types.ts +5 -0
- package/src/lab/subject/behavior-fingerprint.ts +1 -1
- package/src/lib/admin-secrets.ts +9 -1
- package/src/lib/bounded-body.ts +4 -2
- package/src/lib/debug-log-buffer.ts +6 -1
- package/src/lib/debug.ts +23 -0
- package/src/lib/destination-policy.ts +48 -6
- package/src/lib/errors.ts +82 -15
- package/src/lib/http-response-semantics.ts +57 -0
- package/src/lib/lab-live-pinned-sender.ts +26 -12
- package/src/lib/local-destinations.ts +32 -5
- package/src/lib/pinned-http.ts +142 -2
- package/src/lib/plain-data.ts +103 -0
- package/src/lib/process-control.ts +13 -5
- package/src/lib/provider-outbound.ts +53 -5
- package/src/lib/proxy-env.ts +70 -3
- package/src/lib/request-execution-budget.ts +11 -3
- package/src/lib/response-body-inactivity.ts +193 -0
- package/src/lib/retry-delay.ts +69 -0
- package/src/lib/socks5-fetch.ts +741 -0
- package/src/lib/spend-ledger-owner.ts +364 -0
- package/src/lib/spend-reservation-ledger.ts +332 -35
- package/src/lib/windows-system-proxy.ts +16 -11
- package/src/lib/workflow-budget.ts +145 -8
- package/src/oauth/account-quota-rank.ts +72 -15
- package/src/oauth/callback-server.ts +4 -3
- package/src/oauth/generic-account-failover.ts +41 -27
- package/src/oauth/health.ts +12 -1
- package/src/oauth/index.ts +3 -107
- package/src/oauth/login-flow-state.ts +127 -0
- package/src/oauth/orcarouter.ts +15 -2
- package/src/oauth/store.ts +8 -0
- package/src/providers/codex-capacity.ts +9 -0
- package/src/providers/derive.ts +34 -17
- package/src/providers/devin-cli-authmode-migration.ts +14 -10
- package/src/providers/devin-provider-merge-migration.ts +33 -12
- package/src/providers/free-directory.ts +20 -2
- package/src/providers/key-failover.ts +327 -25
- package/src/providers/model-rename-migration.ts +56 -1
- package/src/providers/model-rename-startup.ts +7 -5
- package/src/providers/openai-sidecar.ts +4 -0
- package/src/providers/openai-virtual-models.ts +42 -2
- package/src/providers/opencode-go-transport.ts +14 -5
- package/src/providers/quota/antigravity.ts +22 -2
- package/src/providers/quota/report-cache.ts +3 -0
- package/src/providers/quota/vendor-probes-key.ts +1 -1
- package/src/providers/registry/entries-core.ts +39 -17
- package/src/providers/registry/entries-extended.ts +131 -1
- package/src/providers/registry/model-ids.ts +168 -0
- package/src/providers/registry/model-seeds.ts +87 -21
- package/src/providers/registry/types.ts +2 -0
- package/src/providers/resolved-model-policy-merge.ts +167 -0
- package/src/providers/resolved-model-policy.ts +406 -0
- package/src/providers/stale-vision-classification-migration.ts +137 -0
- package/src/responses/apply-patch-envelope.ts +32 -11
- package/src/responses/bridge-search-replay-cache.ts +152 -0
- package/src/responses/code-mode-helper-compat.ts +26 -16
- package/src/responses/custom-tool-compat.ts +1 -1
- package/src/responses/freeform-wrapper-scan.ts +279 -0
- package/src/responses/hosted-tool-policy.ts +85 -2
- package/src/responses/legacy-dotted-tool-name-repair.ts +134 -0
- package/src/responses/progressive-freeform-input.ts +130 -0
- package/src/responses/reasoning-envelope.ts +30 -0
- package/src/responses/schema.ts +9 -2
- package/src/responses/state.ts +5 -12
- package/src/responses/tool-name-aliases.ts +15 -1
- package/src/router.ts +91 -115
- package/src/routing/compatibility/behavior.ts +9 -0
- package/src/routing/compatibility/subject.ts +16 -1
- package/src/server/adapter-resolve.ts +9 -0
- package/src/server/auth-cors.ts +29 -0
- package/src/server/chat-completions.ts +13 -5
- package/src/server/chat-native-sse.ts +26 -9
- package/src/server/chat-native.ts +10 -4
- package/src/server/claude-messages.ts +30 -5
- package/src/server/effort-row.ts +11 -3
- package/src/server/grok-responses-control-frame.ts +160 -1
- package/src/server/gui-static.ts +36 -2
- package/src/server/inbound-body-admission.ts +187 -0
- package/src/server/index/serve-options.ts +86 -29
- package/src/server/index/spend-ledger-lifecycle.ts +66 -0
- package/src/server/index/websocket-handler.ts +6 -1
- package/src/server/index.ts +24 -25
- package/src/server/management/api-access.ts +3 -4
- package/src/server/management/aside-profile-routes.ts +266 -7
- package/src/server/management/config-routes.ts +48 -7
- package/src/server/management/context.ts +3 -0
- package/src/server/management/integration-routes.ts +287 -5
- package/src/server/management/metrics-routes.ts +20 -0
- package/src/server/management/model-rows.ts +224 -12
- package/src/server/management/provider-capability-config.ts +35 -7
- package/src/server/management/provider-routes.ts +70 -18
- package/src/server/management/route-registry.ts +14 -0
- package/src/server/management/shared.ts +10 -3
- package/src/server/management/system-restart.ts +7 -2
- package/src/server/management/system-routes.ts +2 -0
- package/src/server/management/usage-aggregate-cache.ts +4 -0
- package/src/server/management-api.ts +2 -0
- package/src/server/management-auth.ts +15 -1
- package/src/server/proxy-liveness.ts +97 -2
- package/src/server/readiness.ts +29 -10
- package/src/server/relay-eager.ts +24 -2
- package/src/server/relay.ts +136 -34
- package/src/server/request-log.ts +80 -3
- package/src/server/request-metrics.ts +236 -0
- package/src/server/responses/adapter-continuation.ts +74 -30
- package/src/server/responses/adapter-delivery.ts +39 -8
- package/src/server/responses/adapter-dispatch.ts +63 -30
- package/src/server/responses/compact.ts +89 -18
- package/src/server/responses/compaction-routing.ts +111 -0
- package/src/server/responses/core-codex-account.ts +90 -24
- package/src/server/responses/core-combo.ts +7 -7
- package/src/server/responses/core-normalize.ts +16 -15
- package/src/server/responses/core-opaque-recovery.ts +1 -0
- package/src/server/responses/core-options.ts +4 -0
- package/src/server/responses/encrypted-payload.ts +20 -2
- package/src/server/responses/fetch-helpers.ts +68 -2
- package/src/server/responses/passthrough-delivery.ts +41 -15
- package/src/server/responses/passthrough-dispatch.ts +145 -53
- package/src/server/responses/passthrough-execution.ts +11 -1
- package/src/server/responses/policy-fallback.ts +5 -13
- package/src/server/responses/request-prepare.ts +96 -17
- package/src/server/responses/request-send-budget.ts +89 -8
- package/src/server/responses/request-sidecar-auth.ts +17 -9
- package/src/server/responses/request-spend.ts +38 -9
- package/src/server/responses/request-transport.ts +15 -12
- package/src/server/responses/run-turn-execution.ts +45 -8
- package/src/server/responses/sidecar-execution.ts +19 -2
- package/src/server/responses/ws-upstream.ts +16 -28
- package/src/server/responses-custom-tool-repair.ts +29 -56
- package/src/server/responses-undeclared-tool-guard.ts +31 -1
- package/src/server/sse-frame-buffer.ts +12 -10
- package/src/server/sse-payload-rewrite.ts +37 -10
- package/src/server/system-env-shell.ts +5 -1
- package/src/server/system-env.ts +7 -1
- package/src/server/workflow-refusal.ts +56 -2
- package/src/service/cli.ts +16 -6
- package/src/service/guards.ts +10 -0
- package/src/service/health.ts +43 -0
- package/src/service/state.ts +7 -2
- package/src/tray/windows-tray.ps1 +155 -3
- package/src/types/accounts.ts +4 -0
- package/src/types/config.ts +111 -6
- package/src/types/provider.ts +37 -0
- package/src/types/request.ts +9 -1
- package/src/types/tools.ts +14 -0
- package/src/types/wire.ts +9 -1
- package/src/types.ts +1 -0
- package/src/usage/expected-prices.ts +28 -0
- package/src/usage/log.ts +87 -4
- package/src/vision/eligibility.ts +88 -9
- package/src/vision/plan.ts +34 -10
- package/src/web-search/executor.ts +41 -2
- package/src/web-search/loop.ts +6 -1
- package/src/web-search/passthrough-bridge.ts +39 -5
- package/gui/dist/assets/index-BbrHOIY0.js +0 -128
- package/gui/dist/assets/index-C5-RdDmD.css +0 -1
|
@@ -3,7 +3,14 @@ import { FORWARD_HEADERS } from "../adapters/openai-responses";
|
|
|
3
3
|
import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
|
|
4
4
|
import { redactSecretString } from "../lib/redact";
|
|
5
5
|
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
applyUpstreamRecoveryInit,
|
|
8
|
+
fetchWithResetRetry,
|
|
9
|
+
releaseResponseBodyBestEffort,
|
|
10
|
+
retryBackoffDelayMs,
|
|
11
|
+
sleepWithAbort,
|
|
12
|
+
RETRY_AFTER_CEILING_MS,
|
|
13
|
+
} from "../lib/upstream-retry";
|
|
7
14
|
import { withUpstreamHttpVersion } from "../lib/upstream-http-version";
|
|
8
15
|
import { parseSidecarSSE, type WebSearchResult } from "./parse";
|
|
9
16
|
import type { CodexUpstreamOutcome } from "../codex/routing";
|
|
@@ -35,6 +42,22 @@ export const IMAGE_INSTRUCTION =
|
|
|
35
42
|
|
|
36
43
|
/** A search result, or an `error` string when the search couldn't run (surfaced as a tool result). */
|
|
37
44
|
export type SidecarOutcome = WebSearchResult & { error?: string };
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Bounded same-search 429 replays for the sidecar POST.
|
|
48
|
+
*
|
|
49
|
+
* The forward backend throttles burst sidecar traffic, and without a replay the 429 becomes a
|
|
50
|
+
* failed tool result that poisons the query for the whole turn (see failedQueries in loop.ts).
|
|
51
|
+
* 1 initial send + 2 replays; Retry-After is honored as a lower bound and capped by
|
|
52
|
+
* RETRY_AFTER_CEILING_MS (an instruction past the ceiling ends with the 429 instead of
|
|
53
|
+
* parking the search). Each wait releases the unread 429 body first so sockets do not
|
|
54
|
+
* accumulate under a rate-limit storm. Abort or timeout ends the wait through the existing
|
|
55
|
+
* catch, exactly like an abort during the SSE parse.
|
|
56
|
+
*/
|
|
57
|
+
const SIDECAR_429_MAX_ATTEMPTS = 3;
|
|
58
|
+
const SIDECAR_429_BASE_DELAY_MS = 1_000;
|
|
59
|
+
const SIDECAR_429_MAX_DELAY_MS = 10_000;
|
|
60
|
+
|
|
38
61
|
export type SidecarOutcomeRecorder = (outcome: CodexUpstreamOutcome) => void;
|
|
39
62
|
|
|
40
63
|
/**
|
|
@@ -79,7 +102,7 @@ export async function runWebSearch(
|
|
|
79
102
|
const sidecarExit = sidecarEnter("web-search");
|
|
80
103
|
const t0 = Date.now();
|
|
81
104
|
try {
|
|
82
|
-
const
|
|
105
|
+
const sendOnce = () => fetchWithResetRetry(
|
|
83
106
|
// Recovery nests INSIDE the version helper: applyUpstreamRecoveryInit then always receives a
|
|
84
107
|
// defined init, and withUpstreamHttpVersion spreads the result, so `protocol` and the
|
|
85
108
|
// recovery fields (`connection: close` + Bun's transport-level `keepalive: false`) survive
|
|
@@ -96,6 +119,22 @@ export async function runWebSearch(
|
|
|
96
119
|
}, recovery), forwardProvider)),
|
|
97
120
|
{ replaySafe: true, abortSignal: linkedSignal.signal, label: "web-search-sidecar" },
|
|
98
121
|
);
|
|
122
|
+
let res = await sendOnce();
|
|
123
|
+
for (let attempt = 0; res.status === 429 && attempt + 1 < SIDECAR_429_MAX_ATTEMPTS; attempt++) {
|
|
124
|
+
const delay = retryBackoffDelayMs(attempt, {
|
|
125
|
+
baseDelayMs: SIDECAR_429_BASE_DELAY_MS,
|
|
126
|
+
maxDelayMs: SIDECAR_429_MAX_DELAY_MS,
|
|
127
|
+
headers: res.headers,
|
|
128
|
+
retryAfterIsLowerBound: true,
|
|
129
|
+
});
|
|
130
|
+
// A deadline, not a clamp: an instruction past the ceiling ends the search with the
|
|
131
|
+
// 429 instead of parking it at a provider that already said it would refuse.
|
|
132
|
+
if (delay > RETRY_AFTER_CEILING_MS) break;
|
|
133
|
+
console.warn(`[web-search] sidecar HTTP 429 — retrying (${attempt + 2}/${SIDECAR_429_MAX_ATTEMPTS}) after ${delay}ms`);
|
|
134
|
+
await releaseResponseBodyBestEffort(res.body, linkedSignal.signal);
|
|
135
|
+
await sleepWithAbort(delay, linkedSignal.signal);
|
|
136
|
+
res = await sendOnce();
|
|
137
|
+
}
|
|
99
138
|
// Attach the body guard before ANY branch reads it. The success path guarded itself below,
|
|
100
139
|
// but the failure branch's `res.text()` runs first, so a cancel landing between fetch
|
|
101
140
|
// resolution and reader attach orphaned the internal rejection (found investigating #1419).
|
package/src/web-search/loop.ts
CHANGED
|
@@ -333,10 +333,15 @@ export interface WebSearchLoopDeps {
|
|
|
333
333
|
* 429 states the window's reset epoch even when it omits Retry-After -- and a rotation that
|
|
334
334
|
* cannot see it cools the drained account for the short default instead of until the window
|
|
335
335
|
* actually reopens. Optional so existing callers keep compiling.
|
|
336
|
+
*
|
|
337
|
+
* `retryParsed` is the exact iteration-local request the retry will be built from. The loop
|
|
338
|
+
* sends a shallow copy of the outer parsed request, so a rotation that rebinds only the outer
|
|
339
|
+
* object never reaches the wire. Optional so existing callers keep compiling.
|
|
336
340
|
*/
|
|
337
341
|
on429?: (
|
|
338
342
|
retryAfterHeader: string | null,
|
|
339
343
|
responseHeaders?: Headers,
|
|
344
|
+
retryParsed?: OcxParsedRequest,
|
|
340
345
|
) => ProviderAdapter | null | Promise<ProviderAdapter | null>;
|
|
341
346
|
/** Opt-in same-target 429 policy (key-auth providers). When present, 429 replays on the SAME key before on429 rotation. */
|
|
342
347
|
retryOn429Policy?: Required<RateLimitRetryPolicy> | null;
|
|
@@ -558,7 +563,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
558
563
|
// 429 key-failover parity with the normal routed path: rotate pool keys until one responds
|
|
559
564
|
// or the pool is exhausted (deps.on429 returns null — cooldown map guarantees termination).
|
|
560
565
|
while (prepared.response.status === 429 && deps.on429) {
|
|
561
|
-
const rotated = await deps.on429(prepared.response.headers.get("retry-after"), prepared.response.headers);
|
|
566
|
+
const rotated = await deps.on429(prepared.response.headers.get("retry-after"), prepared.response.headers, iterParsed);
|
|
562
567
|
if (!rotated) break;
|
|
563
568
|
// Never let a broken body's cancel promise outlive the cumulative header deadline. Observe
|
|
564
569
|
// it, but proceed immediately to the rotated fetch under the SAME deadline signal.
|
|
@@ -75,6 +75,7 @@ import {
|
|
|
75
75
|
} from "./sidecar-providers";
|
|
76
76
|
import { providerDestinationConfigError } from "../lib/destination-policy";
|
|
77
77
|
import { redactSecretString } from "../lib/redact";
|
|
78
|
+
import { rememberBridgeSearchReplay } from "../responses/bridge-search-replay-cache";
|
|
78
79
|
|
|
79
80
|
/** Canonical Ollama Cloud origin. The only origin the "ollama" backend derives on its own. */
|
|
80
81
|
export const OLLAMA_CLOUD_ORIGIN = "https://ollama.com";
|
|
@@ -377,11 +378,18 @@ export interface PassthroughWebSearchBridgeStreamOptions {
|
|
|
377
378
|
/** Sends one continuation leg and resolves with its response. */
|
|
378
379
|
send: (body: string) => Promise<Response>;
|
|
379
380
|
execute: PassthroughWebSearchBridgeExecutor;
|
|
381
|
+
/**
|
|
382
|
+
* Destination identity for the executed-search memo (#4587). When absent nothing is recorded,
|
|
383
|
+
* and the next turn replays the hosted cell exactly as it does today.
|
|
384
|
+
*/
|
|
385
|
+
destinationScope?: string;
|
|
380
386
|
/**
|
|
381
387
|
* Re-applies the caller's outbound body ceiling to a continuation body. Returns a refusal
|
|
382
388
|
* message when the extended body may not be sent, or undefined when it is admitted.
|
|
383
389
|
*/
|
|
384
390
|
checkOutboundBody?: (body: string) => string | undefined;
|
|
391
|
+
/** Releases request-scoped resources when the stream completes, fails, or is cancelled. */
|
|
392
|
+
onFinalize?: () => void;
|
|
385
393
|
signal?: AbortSignal;
|
|
386
394
|
}
|
|
387
395
|
|
|
@@ -1094,11 +1102,22 @@ async function* bridgeStreamBlocks(
|
|
|
1094
1102
|
outcome = await options.execute(queries, options.signal);
|
|
1095
1103
|
}
|
|
1096
1104
|
yield* emit(state.searchEndFrames(call, queries, outcome));
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1105
|
+
// The model needs a readable result either way; an executor error is reported as the
|
|
1106
|
+
// tool result rather than as a turn failure, so it can still answer without the search.
|
|
1107
|
+
const output = outcome.error ? "Web search failed: " + outcome.error : outcome.text;
|
|
1108
|
+
turns.push({ call, output });
|
|
1109
|
+
// Record what a continuation leg WOULD put on the wire, whether or not this leg sends one
|
|
1110
|
+
// (#4587). The caller keeps the hosted cell and replays it next turn; the pre-dispatch
|
|
1111
|
+
// rewrite in the Responses adapter uses this to hand the destination back its own call and
|
|
1112
|
+
// result instead of an item type it never produced. Recording the same text that
|
|
1113
|
+
// appendBridgeSearchTurn would append is what keeps a replayed turn and a continued turn
|
|
1114
|
+
// showing the destination one consistent conversation.
|
|
1115
|
+
rememberBridgeSearchReplay(options.destinationScope, call.cellItemId, {
|
|
1116
|
+
callId: call.callId,
|
|
1117
|
+
sourceItemId: call.sourceItemId,
|
|
1118
|
+
name: WEB_SEARCH_TOOL_NAME,
|
|
1119
|
+
argumentsText: call.argumentsText,
|
|
1120
|
+
output,
|
|
1102
1121
|
});
|
|
1103
1122
|
}
|
|
1104
1123
|
|
|
@@ -1170,21 +1189,36 @@ export function createPassthroughWebSearchBridgeStream(
|
|
|
1170
1189
|
const aborted = (): boolean => cancelled || options.signal?.aborted === true;
|
|
1171
1190
|
const iterator = bridgeStreamBlocks(options, aborted)[Symbol.asyncIterator]();
|
|
1172
1191
|
const encoder = new TextEncoder();
|
|
1192
|
+
let finalized = false;
|
|
1193
|
+
const finalize = (): void => {
|
|
1194
|
+
if (finalized) return;
|
|
1195
|
+
finalized = true;
|
|
1196
|
+
options.onFinalize?.();
|
|
1197
|
+
};
|
|
1173
1198
|
return new ReadableStream<Uint8Array>({
|
|
1174
1199
|
async pull(controller) {
|
|
1175
1200
|
try {
|
|
1176
1201
|
const next = await iterator.next();
|
|
1177
1202
|
if (next.done) {
|
|
1203
|
+
finalize();
|
|
1178
1204
|
controller.close();
|
|
1179
1205
|
return;
|
|
1180
1206
|
}
|
|
1181
1207
|
controller.enqueue(encoder.encode(next.value));
|
|
1182
1208
|
} catch (error) {
|
|
1209
|
+
finalize();
|
|
1183
1210
|
controller.error(error);
|
|
1184
1211
|
}
|
|
1185
1212
|
},
|
|
1186
1213
|
cancel(reason) {
|
|
1187
1214
|
cancelled = true;
|
|
1215
|
+
// Release request-scoped authority immediately. An async generator cannot
|
|
1216
|
+
// process a queued return() while its active next() is blocked on an
|
|
1217
|
+
// upstream read, so deferring finalize until that settles would hold the
|
|
1218
|
+
// sidecar probe lease for as long as the abandoned upstream leg does.
|
|
1219
|
+
// Optional chaining would also skip finalize entirely for an iterator
|
|
1220
|
+
// with no return method.
|
|
1221
|
+
finalize();
|
|
1188
1222
|
void iterator.return?.(reason);
|
|
1189
1223
|
},
|
|
1190
1224
|
});
|