@bitkyc08/opencodex 2.36.0-preview.20260829 → 2.36.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/index-Cy7Z_pl0.css +1 -0
- package/gui/dist/assets/index-DO8liQVL.js +112 -0
- package/gui/dist/index.html +2 -2
- package/package.json +2 -1
- package/src/AGENTS.md +2 -1
- package/src/adapters/agentrouter.ts +50 -0
- package/src/adapters/anthropic.ts +1 -51
- package/src/adapters/cursor/call-id.ts +76 -8
- package/src/adapters/cursor/checkpoint-store.ts +6 -1
- package/src/adapters/cursor/cursor-errors.ts +44 -0
- package/src/adapters/cursor/native-exec.ts +13 -0
- package/src/adapters/cursor/protobuf-request.ts +651 -29
- package/src/adapters/cursor/tool-result-normalize.ts +3 -3
- package/src/adapters/cursor/transport-retry.ts +5 -1
- package/src/adapters/cursor.ts +15 -1
- package/src/adapters/empty-tool-output-annotation.ts +43 -0
- package/src/adapters/exec-tool-result-normalize.ts +70 -5
- package/src/adapters/google.ts +22 -2
- package/src/adapters/kiro.ts +26 -2
- package/src/adapters/ollama-native-url.ts +111 -0
- package/src/adapters/ollama-native.ts +1131 -0
- package/src/adapters/openai-chat.ts +30 -7
- package/src/adapters/openai-responses.ts +72 -4
- package/src/adapters/registry.ts +7 -0
- package/src/adapters/xai-web-search.ts +58 -0
- package/src/claude/desktop-3p.ts +21 -1
- package/src/claude/desktop-policy.ts +149 -0
- package/src/cli/account.ts +16 -2
- package/src/cli/claude-desktop.ts +13 -3
- package/src/cli/combo.ts +8 -5
- package/src/cli/doctor.ts +77 -11
- package/src/cli/help.ts +1 -1
- package/src/cli/index.ts +16 -0
- package/src/cli/models.ts +20 -3
- package/src/cli/registry.ts +2 -1
- package/src/cli/status.ts +140 -2
- package/src/cli/storage.ts +10 -1
- package/src/codex/account-runtime-state.ts +39 -5
- package/src/codex/account-store.ts +393 -13
- package/src/codex/account-usability.ts +11 -4
- package/src/codex/app-server-processes.ts +46 -5
- package/src/codex/auth-context.ts +160 -32
- package/src/codex/catalog/bundled.ts +7 -5
- package/src/codex/catalog/metadata.ts +1 -1
- package/src/codex/catalog/parsing.ts +57 -1
- package/src/codex/catalog/provider-fetch.ts +61 -4
- package/src/codex/catalog/sync.ts +4 -3
- package/src/codex/convergence.ts +3 -2
- package/src/codex/data/upstream-models.json +40 -8
- package/src/codex/inject-coordination.ts +111 -14
- package/src/codex/integration-record.ts +12 -2
- package/src/codex/main-account.ts +225 -1
- package/src/codex/model-entitlements.ts +339 -27
- package/src/codex/prompt-layers.ts +346 -7
- package/src/codex/prompt-text-probe.ts +272 -21
- package/src/codex/routing.ts +693 -132
- package/src/codex/runtime.ts +12 -0
- package/src/codex/subagent-model-fallback.ts +62 -24
- package/src/codex/user-identity.ts +33 -25
- package/src/combos/index.ts +1 -0
- package/src/combos/reset-window.ts +46 -0
- package/src/combos/resolve.ts +84 -2
- package/src/combos/types.ts +5 -2
- package/src/config/atomic-write.ts +104 -22
- package/src/config/provider-validation.ts +11 -0
- package/src/config.ts +75 -3
- package/src/generated/compatibility-version.json +207 -131
- package/src/generated/model-metadata.ts +1 -1
- package/src/grok/catalog.ts +71 -0
- package/src/grok/effort.ts +83 -0
- package/src/grok/inject.ts +952 -127
- package/src/grok/models.ts +56 -0
- package/src/grok/status.ts +21 -8
- package/src/grok/sync.ts +10 -18
- package/src/images/loop.ts +6 -3
- package/src/integrations/native/ownership-preflight.ts +4 -1
- package/src/lab/fabric/producer-isolate.ts +36 -3
- package/src/lib/destination-policy.ts +93 -7
- package/src/lib/redact.ts +6 -1
- package/src/lib/shadow-call.ts +38 -3
- package/src/lib/test-home-guard.ts +18 -3
- package/src/lib/upstream-retry.ts +43 -6
- package/src/lib/windows-secret-acl.ts +66 -0
- package/src/lib/windows-text.ts +28 -2
- package/src/lib/windows-user-principal.ts +35 -23
- package/src/oauth/account-quota-rank.ts +107 -0
- package/src/oauth/anthropic-routing.ts +125 -30
- package/src/oauth/chatgpt.ts +5 -1
- package/src/oauth/generic-account-failover.ts +114 -7
- package/src/oauth/index.ts +15 -8
- package/src/oauth/store.ts +16 -0
- package/src/providers/account-quota-disk.ts +79 -0
- package/src/providers/command-code-efforts.ts +24 -0
- package/src/providers/derive.ts +6 -0
- package/src/providers/key-failover.ts +33 -1
- package/src/providers/kiro-usage.ts +272 -0
- package/src/providers/ollama-show.ts +311 -0
- package/src/providers/openai-sidecar.ts +5 -0
- package/src/providers/quota-routing-cache.ts +32 -0
- package/src/providers/quota-types.ts +36 -0
- package/src/providers/quota-wire.ts +102 -0
- package/src/providers/quota.ts +208 -147
- package/src/providers/registry.ts +68 -8
- package/src/providers/slug-codec.ts +12 -4
- package/src/providers/vercel-gateway-routing.ts +108 -0
- package/src/router.ts +22 -12
- package/src/server/auth-cors.ts +26 -0
- package/src/server/catalog-download.ts +73 -0
- package/src/server/chat-native.ts +12 -2
- package/src/server/gui-static.ts +4 -1
- package/src/server/index.ts +132 -9
- package/src/server/management/agent-settings-routes.ts +38 -5
- package/src/server/management/codex-prompt-routes.ts +7 -1
- package/src/server/management/combo-routes.ts +10 -1
- package/src/server/management/config-routes.ts +9 -1
- package/src/server/management/context.ts +5 -0
- package/src/server/management/model-routes.ts +16 -6
- package/src/server/management/native-integration-routes.ts +12 -17
- package/src/server/management/oauth-account-routes.ts +13 -0
- package/src/server/management/provider-routes.ts +32 -5
- package/src/server/management/routing-profile-routes.ts +15 -0
- package/src/server/management/shadow-call-validation.ts +29 -0
- package/src/server/management-api.ts +7 -3
- package/src/server/request-log.ts +3 -5
- package/src/server/responses/agent-task-recovery-cache.ts +8 -0
- package/src/server/responses/agent-task-recovery.ts +52 -20
- package/src/server/responses/codex-auth-error.ts +26 -0
- package/src/server/responses/compact.ts +345 -10
- package/src/server/responses/core.ts +736 -108
- package/src/server/responses/empty-completion-guard.ts +16 -0
- package/src/server/responses/fetch-helpers.ts +42 -0
- package/src/server/responses/policy-fallback.ts +11 -6
- package/src/server/responses-undeclared-tool-guard.ts +16 -3
- package/src/server/startup-health-cache.ts +59 -13
- package/src/service-manager-probe.ts +115 -9
- package/src/service.ts +139 -40
- package/src/storage/cleanup.ts +10 -0
- package/src/storage/storage-mutation-coordinator.ts +14 -3
- package/src/tray/windows-tray.ps1 +10 -4
- package/src/tray/windows.ts +30 -2
- package/src/types/config.ts +27 -14
- package/src/types/provider.ts +54 -0
- package/src/types/tools.ts +13 -3
- package/src/types.ts +4 -0
- package/src/usage/summary.ts +421 -177
- package/src/vision/anthropic-describe.ts +3 -3
- package/src/vision/describe.ts +5 -3
- package/src/web-search/anthropic-executor.ts +9 -2
- package/src/web-search/exa-executor.ts +3 -3
- package/src/web-search/executor.ts +8 -3
- package/src/web-search/gemini-executor.ts +3 -3
- package/src/web-search/loop.ts +11 -3
- package/src/web-search/xai-executor.ts +3 -3
- package/gui/dist/assets/index-DQ-Ie18T.css +0 -1
- package/gui/dist/assets/index-DX0RGj3e.js +0 -112
|
@@ -2,7 +2,7 @@ import type { OcxProviderConfig } from "../types";
|
|
|
2
2
|
import { CLAUDE_CODE_HEADERS, claudeCodeSessionId } from "../adapters/client-fingerprint";
|
|
3
3
|
import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
|
|
4
4
|
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
5
|
-
import { fetchWithResetRetry } from "../lib/upstream-retry";
|
|
5
|
+
import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
|
|
6
6
|
import { getValidAccessToken, publicOAuthAuthenticationErrorMessage } from "../oauth";
|
|
7
7
|
import { ANTHROPIC_OAUTH_BETA, CLAUDE_CODE_SYSTEM_INSTRUCTION } from "../oauth/anthropic";
|
|
8
8
|
import type { DescribeOutcome, VisionSettings } from "./describe";
|
|
@@ -155,12 +155,12 @@ export async function describeImageAnthropic(
|
|
|
155
155
|
const startedAt = Date.now();
|
|
156
156
|
try {
|
|
157
157
|
const res = await fetchWithResetRetry(
|
|
158
|
-
|
|
158
|
+
recovery => fetch(`${base}/v1/messages`, applyUpstreamRecoveryInit({
|
|
159
159
|
method: "POST",
|
|
160
160
|
headers,
|
|
161
161
|
body: JSON.stringify(body),
|
|
162
162
|
signal: linkedSignal.signal,
|
|
163
|
-
}),
|
|
163
|
+
}, recovery)),
|
|
164
164
|
{ abortSignal: linkedSignal.signal, label: "vision-sidecar-anthropic" },
|
|
165
165
|
);
|
|
166
166
|
if (!res.ok) {
|
package/src/vision/describe.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { FORWARD_HEADERS } from "../adapters/openai-responses";
|
|
|
4
4
|
import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
|
|
5
5
|
import { redactSecretString } from "../lib/redact";
|
|
6
6
|
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
7
|
-
import { fetchWithResetRetry } from "../lib/upstream-retry";
|
|
7
|
+
import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
|
|
8
8
|
import { parseSidecarSSE } from "../web-search/parse";
|
|
9
9
|
import type { SidecarOutcomeRecorder } from "../web-search/executor";
|
|
10
10
|
|
|
@@ -90,7 +90,9 @@ export async function describeImage(
|
|
|
90
90
|
const t0 = Date.now();
|
|
91
91
|
try {
|
|
92
92
|
const res = await fetchWithResetRetry(
|
|
93
|
-
|
|
93
|
+
// The replay needs `keepalive: false` to abandon the half-closed pooled socket; Bun has
|
|
94
|
+
// ignored a bare `Connection: close` (oven-sh/bun#20492).
|
|
95
|
+
recovery => fetch(`${forwardProvider.baseUrl}/responses`, applyUpstreamRecoveryInit({
|
|
94
96
|
method: "POST",
|
|
95
97
|
headers,
|
|
96
98
|
body: JSON.stringify(body),
|
|
@@ -99,7 +101,7 @@ export async function describeImage(
|
|
|
99
101
|
// across origins but forwards nonstandard headers such as `chatgpt-account-id`,
|
|
100
102
|
// `session_id`, and `x-codex-turn-metadata` to the redirect target.
|
|
101
103
|
redirect: "manual",
|
|
102
|
-
}),
|
|
104
|
+
}, recovery)),
|
|
103
105
|
{ abortSignal: linkedSignal.signal, label: "vision-sidecar" },
|
|
104
106
|
);
|
|
105
107
|
const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
|
|
@@ -4,7 +4,7 @@ import { ANTHROPIC_OAUTH_BETA, CLAUDE_CODE_SYSTEM_INSTRUCTION } from "../oauth/a
|
|
|
4
4
|
import { CLAUDE_CODE_HEADERS, claudeCodeSessionId } from "../adapters/client-fingerprint";
|
|
5
5
|
import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
|
|
6
6
|
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
7
|
-
import { fetchWithResetRetry } from "../lib/upstream-retry";
|
|
7
|
+
import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
|
|
8
8
|
import type { WebSearchSource } from "./parse";
|
|
9
9
|
import { BASE_INSTRUCTION, IMAGE_INSTRUCTION, type SidecarOutcome, type SidecarSettings } from "./executor";
|
|
10
10
|
|
|
@@ -162,7 +162,14 @@ export async function runAnthropicWebSearch(
|
|
|
162
162
|
const t0 = Date.now();
|
|
163
163
|
try {
|
|
164
164
|
const res = await fetchWithResetRetry(
|
|
165
|
-
|
|
165
|
+
// The replay needs `keepalive: false` to leave the half-closed pooled socket; Bun has
|
|
166
|
+
// ignored a bare `Connection: close` (oven-sh/bun#20492).
|
|
167
|
+
recovery => fetch(url, applyUpstreamRecoveryInit({
|
|
168
|
+
method: "POST",
|
|
169
|
+
headers,
|
|
170
|
+
body: JSON.stringify(body),
|
|
171
|
+
signal: linkedSignal.signal,
|
|
172
|
+
}, recovery)),
|
|
166
173
|
{ abortSignal: linkedSignal.signal, label: "web-search-sidecar-anthropic" },
|
|
167
174
|
);
|
|
168
175
|
// Guard before any branch reads the body: the failure branch's `res.text()` ran ahead of
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* redirect: "manual" because Bun forwards custom headers across redirects.
|
|
9
9
|
* Never throws; every error string passes redactSecretString.
|
|
10
10
|
*/
|
|
11
|
-
import { fetchWithResetRetry } from "../lib/upstream-retry";
|
|
11
|
+
import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
|
|
12
12
|
import { cancelBodyOnAbort, signalWithTimeout } from "../lib/abort";
|
|
13
13
|
import { readBoundedResponseBytes } from "../lib/bounded-body";
|
|
14
14
|
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
@@ -39,13 +39,13 @@ export async function runExaWebSearch(
|
|
|
39
39
|
const t0 = Date.now();
|
|
40
40
|
try {
|
|
41
41
|
const res = await fetchWithResetRetry(
|
|
42
|
-
|
|
42
|
+
recovery => fetch(EXA_SEARCH_URL, applyUpstreamRecoveryInit({
|
|
43
43
|
method: "POST",
|
|
44
44
|
headers: { "Content-Type": "application/json", "x-api-key": apiKey },
|
|
45
45
|
body: JSON.stringify({ query, numResults: EXA_NUM_RESULTS, contents: { text: { maxCharacters: EXA_SNIPPET_CHARS } } }),
|
|
46
46
|
signal: linkedSignal.signal,
|
|
47
47
|
redirect: "manual",
|
|
48
|
-
}),
|
|
48
|
+
}, recovery)),
|
|
49
49
|
{ abortSignal: linkedSignal.signal, label: "exa-web-search-sidecar" },
|
|
50
50
|
);
|
|
51
51
|
const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
|
|
@@ -3,7 +3,8 @@ 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 { fetchWithResetRetry } from "../lib/upstream-retry";
|
|
6
|
+
import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
|
|
7
|
+
import { withUpstreamHttpVersion } from "../lib/upstream-http-version";
|
|
7
8
|
import { parseSidecarSSE, type WebSearchResult } from "./parse";
|
|
8
9
|
import type { CodexUpstreamOutcome } from "../codex/routing";
|
|
9
10
|
|
|
@@ -73,7 +74,11 @@ export async function runWebSearch(
|
|
|
73
74
|
const t0 = Date.now();
|
|
74
75
|
try {
|
|
75
76
|
const res = await fetchWithResetRetry(
|
|
76
|
-
|
|
77
|
+
// Recovery nests INSIDE the version helper: applyUpstreamRecoveryInit then always receives a
|
|
78
|
+
// defined init, and withUpstreamHttpVersion spreads the result, so `protocol` and the
|
|
79
|
+
// recovery fields (`connection: close` + Bun's transport-level `keepalive: false`) survive
|
|
80
|
+
// together. The reverse order needs a `?? init` fallback to type-check at all.
|
|
81
|
+
recovery => fetch(url, withUpstreamHttpVersion(url, applyUpstreamRecoveryInit({
|
|
77
82
|
method: "POST",
|
|
78
83
|
headers,
|
|
79
84
|
body: JSON.stringify(body),
|
|
@@ -82,7 +87,7 @@ export async function runWebSearch(
|
|
|
82
87
|
// across origins but forwards nonstandard headers such as `chatgpt-account-id`,
|
|
83
88
|
// `session_id`, and `x-codex-turn-metadata` to the redirect target.
|
|
84
89
|
redirect: "manual",
|
|
85
|
-
}),
|
|
90
|
+
}, recovery), forwardProvider)),
|
|
86
91
|
{ abortSignal: linkedSignal.signal, label: "web-search-sidecar" },
|
|
87
92
|
);
|
|
88
93
|
// Attach the body guard before ANY branch reads it. The success path guarded itself below,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { OcxProviderConfig } from "../types";
|
|
12
12
|
import { getValidAccessTokenSnapshot, publicOAuthAuthenticationErrorMessage } from "../oauth";
|
|
13
|
-
import { fetchWithResetRetry } from "../lib/upstream-retry";
|
|
13
|
+
import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
|
|
14
14
|
import { cancelBodyOnAbort, signalWithTimeout } from "../lib/abort";
|
|
15
15
|
import { readBoundedResponseBytes } from "../lib/bounded-body";
|
|
16
16
|
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
@@ -69,7 +69,7 @@ export async function runGeminiWebSearch(
|
|
|
69
69
|
const t0 = Date.now();
|
|
70
70
|
try {
|
|
71
71
|
const res = await fetchWithResetRetry(
|
|
72
|
-
|
|
72
|
+
recovery => fetch(`${base}/v1internal:generateContent`, applyUpstreamRecoveryInit({
|
|
73
73
|
method: "POST",
|
|
74
74
|
headers: {
|
|
75
75
|
"Content-Type": "application/json",
|
|
@@ -79,7 +79,7 @@ export async function runGeminiWebSearch(
|
|
|
79
79
|
body: JSON.stringify(envelope),
|
|
80
80
|
signal: linkedSignal.signal,
|
|
81
81
|
redirect: "manual",
|
|
82
|
-
}),
|
|
82
|
+
}, recovery)),
|
|
83
83
|
{ abortSignal: linkedSignal.signal, label: "gemini-web-search-sidecar" },
|
|
84
84
|
);
|
|
85
85
|
const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
|
package/src/web-search/loop.ts
CHANGED
|
@@ -13,7 +13,7 @@ import type { WebSearchBackendId } from "./index";
|
|
|
13
13
|
import { clearableDeadline } from "../lib/abort";
|
|
14
14
|
import { redactSecretString } from "../lib/redact";
|
|
15
15
|
import { readBoundedResponseBody } from "../lib/bounded-body";
|
|
16
|
-
import { fetchWithResetRetry, prepareSameTarget429Wait } from "../lib/upstream-retry";
|
|
16
|
+
import { applyUpstreamRecoveryInit, fetchWithResetRetry, prepareSameTarget429Wait } from "../lib/upstream-retry";
|
|
17
17
|
import { rateLimitRetryDelayMs } from "../providers/key-failover";
|
|
18
18
|
import {
|
|
19
19
|
isTranslatorBudgetExceededError,
|
|
@@ -323,6 +323,7 @@ export interface WebSearchLoopDeps {
|
|
|
323
323
|
*/
|
|
324
324
|
export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Response> {
|
|
325
325
|
const translatorBudget = deps.incomingMeta.translatorBudget;
|
|
326
|
+
const routedProviderFetch = deps.incomingMeta.providerFetch ?? globalThis.fetch;
|
|
326
327
|
const { parsed, selectedForwardHeaders, forwardProvider, hostedTool, settings, maxSearches, abortSignal, recordSidecarOutcome } = deps;
|
|
327
328
|
const backend = deps.backend ?? "openai";
|
|
328
329
|
const anthropicSidecar = deps.anthropicSidecar;
|
|
@@ -426,6 +427,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
426
427
|
request = cachedRequest;
|
|
427
428
|
} else {
|
|
428
429
|
request = await requestAdapter.buildRequest(iterParsed, {
|
|
430
|
+
...deps.incomingMeta,
|
|
429
431
|
headers: selectedForwardHeaders,
|
|
430
432
|
abortSignal: headerDeadline.signal,
|
|
431
433
|
translatorBudget,
|
|
@@ -447,6 +449,7 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
447
449
|
timeoutMs: connectTimeoutMs,
|
|
448
450
|
returnRawErrors: true,
|
|
449
451
|
stream: true,
|
|
452
|
+
executor: routedProviderFetch,
|
|
450
453
|
});
|
|
451
454
|
} else {
|
|
452
455
|
response = await fetchWithResetRetry(
|
|
@@ -457,12 +460,17 @@ export async function runWithWebSearch(deps: WebSearchLoopDeps): Promise<Respons
|
|
|
457
460
|
deps.onAttemptSend?.(retryRecovery ?? recovery);
|
|
458
461
|
const h = new Headers(request.headers);
|
|
459
462
|
if (!h.has("accept-encoding")) h.set("accept-encoding", "identity");
|
|
460
|
-
|
|
463
|
+
// A connection-reset replay must leave the half-closed pooled socket, not just
|
|
464
|
+
// ask politely: Bun has ignored a bare `Connection: close` (oven-sh/bun#20492),
|
|
465
|
+
// so the transport-level `keepalive: false` this helper adds is what actually
|
|
466
|
+
// opens a new connection. Spending `retryRecovery` on telemetry alone left every
|
|
467
|
+
// replay on this leg eligible for the same dead socket the reset came from.
|
|
468
|
+
return routedProviderFetch(request.url, applyUpstreamRecoveryInit({
|
|
461
469
|
method: request.method,
|
|
462
470
|
headers: h,
|
|
463
471
|
body: request.body,
|
|
464
472
|
signal: headerDeadline.signal,
|
|
465
|
-
});
|
|
473
|
+
}, retryRecovery));
|
|
466
474
|
},
|
|
467
475
|
{ abortSignal: headerDeadline.signal, label: "web-search-loop" },
|
|
468
476
|
);
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import type { OcxProviderConfig } from "../types";
|
|
14
14
|
import { getValidAccessToken, publicOAuthAuthenticationErrorMessage } from "../oauth";
|
|
15
|
-
import { fetchWithResetRetry } from "../lib/upstream-retry";
|
|
15
|
+
import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
|
|
16
16
|
import { cancelBodyOnAbort, signalWithTimeout } from "../lib/abort";
|
|
17
17
|
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
18
18
|
import { redactSecretString } from "../lib/redact";
|
|
@@ -102,14 +102,14 @@ export async function runXaiWebSearch(
|
|
|
102
102
|
const t0 = Date.now();
|
|
103
103
|
try {
|
|
104
104
|
const res = await fetchWithResetRetry(
|
|
105
|
-
|
|
105
|
+
recovery => fetch(url, applyUpstreamRecoveryInit({
|
|
106
106
|
method: "POST",
|
|
107
107
|
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
|
|
108
108
|
body: JSON.stringify(body),
|
|
109
109
|
signal: linkedSignal.signal,
|
|
110
110
|
// Credential-bearing: never follow a redirect off the pinned origin.
|
|
111
111
|
redirect: "manual",
|
|
112
|
-
}),
|
|
112
|
+
}, recovery)),
|
|
113
113
|
{ abortSignal: linkedSignal.signal, label: "xai-web-search-sidecar" },
|
|
114
114
|
);
|
|
115
115
|
const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
|