@xiaoso/dsh-tool-plus 0.1.0-beta.2 → 0.1.0-beta.3
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.en.md +122 -0
- package/README.md +3 -2
- package/THIRD_PARTY_NOTICES.md +4 -35
- package/lib/abort-B7izMMna.mjs +51 -0
- package/lib/amazon-bedrock-D-shAr1X.mjs +917 -0
- package/lib/anthropic-BWsZFzU8.mjs +262 -0
- package/lib/anthropic-CMT1Qj1t.mjs +3115 -0
- package/lib/api-key-login-CpzSezsi.mjs +157 -0
- package/lib/aws-credentials-8Mgn5MAy.mjs +867 -0
- package/lib/azure-openai-responses-CNkHiLUh.mjs +274 -0
- package/lib/bun-shim.mjs +172 -7
- package/lib/bundled-references-CSuBco5p.mjs +55 -0
- package/lib/callback-server-BEFNf-jf.mjs +398 -0
- package/lib/client.js +110 -40
- package/lib/cursor-BIQfBC6V.mjs +135 -0
- package/lib/cursor-DNk6eXDd.mjs +5470 -0
- package/lib/cursor-MjSm74IJ.mjs +273 -0
- package/lib/device-code-OI_tQcmc.mjs +51 -0
- package/lib/devin-CldyPD8K.mjs +95 -0
- package/lib/devin-CzRpTUOA.mjs +114 -0
- package/lib/devin-DXOeNyU7.mjs +542 -0
- package/lib/error-B3bevhrs.mjs +1449 -0
- package/lib/event-stream-BDPi64mK.mjs +151 -0
- package/lib/github-copilot-4GaMtQmg.mjs +208 -0
- package/lib/github-copilot-B2HGSIJK.mjs +104 -0
- package/lib/gitlab-duo-akICyfeD.mjs +155 -0
- package/lib/gitlab-duo-workflow-CSEgYk3N.mjs +91 -0
- package/lib/google-antigravity-Dlkdhahq.mjs +198 -0
- package/lib/google-auth-DhqpOYrX.mjs +232 -0
- package/lib/google-gemini-cli-BG_LRdIV.mjs +850 -0
- package/lib/google-gemini-cli-zJhiOcND.mjs +211 -0
- package/lib/google-oauth-shared-CwNWYdmR.mjs +147 -0
- package/lib/google-shared-DzhCb9b0.mjs +760 -0
- package/lib/google-vertex-kscbkyRb.mjs +99 -0
- package/lib/google-zyDOG9x7.mjs +30 -0
- package/lib/identity-DnB63pS7.mjs +219 -0
- package/lib/idle-iterator-C6XbWcuB.mjs +366 -0
- package/lib/index.mjs +2865 -2745
- package/lib/kimi-DMVI-zrZ.mjs +236 -0
- package/lib/markit-M0jhziqU.mjs +1417 -0
- package/lib/minimax-code-BK-3eBbz.mjs +53 -0
- package/lib/models-CfT4coYT.mjs +104660 -0
- package/lib/ollama-BQMGPxtV.mjs +589 -0
- package/lib/openai-codex-CQL_kvYL.mjs +255 -0
- package/lib/openai-codex-responses-Cz-2qpC7.mjs +3144 -0
- package/lib/openai-completions-i8doczAk.mjs +1360 -0
- package/lib/openai-reasoning-fallback-DGVVLgd1.mjs +286 -0
- package/lib/openai-responses-DTkBiiy-.mjs +867 -0
- package/lib/opencode-DaJjcUbf.mjs +38 -0
- package/lib/perplexity-9b-RQ0mV.mjs +194 -0
- package/lib/proxy-ZtUcl6r5.mjs +190 -0
- package/lib/scrapers-CL-WgdU1.mjs +9198 -0
- package/lib/scrapers-CipyKyCH.mjs +9198 -0
- package/lib/scrapers-DGfrYhtw.mjs +9198 -0
- package/lib/scrapers-DSUPYoUF.mjs +9198 -0
- package/lib/scrapers-DZ2GXmp7.mjs +9198 -0
- package/lib/src-DTid0g4K.mjs +5001 -0
- package/lib/stream-C_RAoxJC.mjs +10236 -0
- package/lib/stream-markup-healing-2toHXWXM.mjs +491 -0
- package/lib/types/client/locales.d.ts +1 -1
- package/lib/types/config/fields.d.ts +1 -1
- package/lib/types/config/settings.d.ts +16 -2
- package/lib/types/tools/omp/sdk.d.ts +6 -0
- package/lib/types/tools/omp/tools/fetch.d.ts +2 -0
- package/lib/types/tools/omp/tools/read.d.ts +2 -8
- package/lib/types/tools/omp/utils/image-loading.d.ts +10 -36
- package/lib/types/tools/read/adapter/index.d.ts +4 -1
- package/lib/types/tools/read-image/index.d.ts +4 -0
- package/lib/types/tools/shared/bun-shim.d.ts +35 -3
- package/lib/types/tools/shared/image-bridge.d.ts +98 -0
- package/lib/types/tools/shared/omp-prompt.d.ts +4 -2
- package/lib/utils-2Wq2eATG.mjs +8119 -0
- package/lib/utils-BnX8O3vi.mjs +12303 -0
- package/lib/utils-CE8N8P4Q.mjs +12315 -0
- package/lib/utils-C_MrQ_0z.mjs +12301 -0
- package/lib/utils-D0Z1fyoO.mjs +12299 -0
- package/lib/utils-DppGHXQB.mjs +51 -0
- package/lib/utils-W8WdSBpX.mjs +12315 -0
- package/lib/vision-guard-BDD4OrKo.mjs +92 -0
- package/lib/wafer-DRU0EjZX.mjs +17 -0
- package/lib/xai-oauth-DPHDXKD7.mjs +446 -0
- package/lib/xiaomi-Dd87KSg5.mjs +157 -0
- package/lib/zai-CFeOt-53.mjs +203 -0
- package/lib/zip-D6QXpvaJ.mjs +1316 -0
- package/package.json +14 -10
- package/presets/package.json +1 -1
- package/presets/tool-plus-ptc/preset.yml +1 -1
- package/presets/tool-plus-standard/preset.yml +1 -1
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { P as $env } from "./src-DTid0g4K.mjs";
|
|
4
|
+
import { n as StreamTimeoutError, v as AbortError } from "./error-B3bevhrs.mjs";
|
|
5
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/utils/idle-iterator.ts
|
|
6
|
+
const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 3e5;
|
|
7
|
+
const DEFAULT_STREAM_FIRST_EVENT_TIMEOUT_MS = 3e5;
|
|
8
|
+
/** Re-mint persistent race promises every N iterations (see hoisted-racer comment). */
|
|
9
|
+
const RACER_REMINT_INTERVAL = 1024;
|
|
10
|
+
function normalizeIdleTimeoutMs(value, fallback) {
|
|
11
|
+
if (value === void 0) return fallback;
|
|
12
|
+
const parsed = Number(value);
|
|
13
|
+
if (!Number.isFinite(parsed)) return fallback;
|
|
14
|
+
if (parsed <= 0) return void 0;
|
|
15
|
+
return Math.trunc(parsed);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Returns the idle timeout used for provider streaming transports.
|
|
19
|
+
*
|
|
20
|
+
* `PI_OPENAI_STREAM_IDLE_TIMEOUT_MS` is accepted as a backward-compatible alias.
|
|
21
|
+
* Set `PI_STREAM_IDLE_TIMEOUT_MS=0` to disable the watchdog.
|
|
22
|
+
*
|
|
23
|
+
* Providers that legitimately stream much slower than the global default can pass
|
|
24
|
+
* `fallbackMs` to widen the floor used when neither env var nor caller option is set.
|
|
25
|
+
* Caller options still take precedence; env overrides still trump the fallback.
|
|
26
|
+
*/
|
|
27
|
+
function getStreamIdleTimeoutMs(fallbackMs = DEFAULT_STREAM_IDLE_TIMEOUT_MS) {
|
|
28
|
+
return normalizeIdleTimeoutMs($env.PI_STREAM_IDLE_TIMEOUT_MS ?? $env.PI_OPENAI_STREAM_IDLE_TIMEOUT_MS, fallbackMs);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Returns the idle timeout used for OpenAI-family streaming transports.
|
|
32
|
+
*
|
|
33
|
+
* `PI_OPENAI_STREAM_IDLE_TIMEOUT_MS` takes precedence over the generic
|
|
34
|
+
* `PI_STREAM_IDLE_TIMEOUT_MS` because some deployments tune OpenAI-compatible
|
|
35
|
+
* backends separately from Anthropic/Gemini-style transports.
|
|
36
|
+
*
|
|
37
|
+
* Set `PI_OPENAI_STREAM_IDLE_TIMEOUT_MS=0` to disable the watchdog.
|
|
38
|
+
*/
|
|
39
|
+
function getOpenAIStreamIdleTimeoutMs(fallbackMs = DEFAULT_STREAM_IDLE_TIMEOUT_MS) {
|
|
40
|
+
return normalizeIdleTimeoutMs($env.PI_OPENAI_STREAM_IDLE_TIMEOUT_MS ?? $env.PI_STREAM_IDLE_TIMEOUT_MS, fallbackMs);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Returns the timeout used while waiting for the first stream event.
|
|
44
|
+
* The first token can legitimately take longer than later inter-event gaps,
|
|
45
|
+
* so the default never undershoots the steady-state idle timeout.
|
|
46
|
+
*
|
|
47
|
+
* Set `PI_STREAM_FIRST_EVENT_TIMEOUT_MS=0` to disable the watchdog.
|
|
48
|
+
*
|
|
49
|
+
* Providers whose first response can legitimately take longer (heavy reasoning,
|
|
50
|
+
* slow cold-start proxies) can pass `fallbackMs` to widen the floor used when
|
|
51
|
+
* neither env var nor caller option is set. Caller options still take precedence;
|
|
52
|
+
* env overrides still trump the fallback.
|
|
53
|
+
*/
|
|
54
|
+
function getStreamFirstEventTimeoutMs(idleTimeoutMs, fallbackMs = DEFAULT_STREAM_FIRST_EVENT_TIMEOUT_MS) {
|
|
55
|
+
const fallback = idleTimeoutMs === void 0 ? fallbackMs : Math.max(fallbackMs, idleTimeoutMs);
|
|
56
|
+
return normalizeIdleTimeoutMs($env.PI_STREAM_FIRST_EVENT_TIMEOUT_MS, fallback);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Returns the first-event timeout used for OpenAI-family streaming transports.
|
|
60
|
+
*
|
|
61
|
+
* Precedence: explicit `PI_OPENAI_STREAM_FIRST_EVENT_TIMEOUT_MS` (including a
|
|
62
|
+
* `"0"` disable) wins outright. Otherwise the resolved idle (caller-supplied
|
|
63
|
+
* `idleTimeoutMs` — which itself already encompasses per-call
|
|
64
|
+
* `streamIdleTimeoutMs` or `PI_OPENAI_STREAM_IDLE_TIMEOUT_MS` resolved
|
|
65
|
+
* upstream) floors the first-event budget so slow OpenAI-compatible servers
|
|
66
|
+
* are not undercut by a shorter `PI_STREAM_FIRST_EVENT_TIMEOUT_MS` or the
|
|
67
|
+
* global default during prompt processing. A zero per-provider fallback
|
|
68
|
+
* disables the first-event watchdog unless an environment override is set.
|
|
69
|
+
*
|
|
70
|
+
* Returns `0` when an explicit env knob or per-provider fallback disables the
|
|
71
|
+
* watchdog, preserving the sentinel through iterator timeout resolution.
|
|
72
|
+
*/
|
|
73
|
+
function getOpenAIStreamFirstEventTimeoutMs(idleTimeoutMs, fallbackMs = DEFAULT_STREAM_FIRST_EVENT_TIMEOUT_MS) {
|
|
74
|
+
const openAIFirstEventRaw = $env.PI_OPENAI_STREAM_FIRST_EVENT_TIMEOUT_MS;
|
|
75
|
+
if (openAIFirstEventRaw !== void 0) return normalizeIdleTimeoutMs(openAIFirstEventRaw, fallbackMs) ?? 0;
|
|
76
|
+
const base = normalizeIdleTimeoutMs($env.PI_STREAM_FIRST_EVENT_TIMEOUT_MS, fallbackMs);
|
|
77
|
+
if (base === void 0 || base <= 0) return 0;
|
|
78
|
+
if (idleTimeoutMs === void 0 || idleTimeoutMs <= 0) return base;
|
|
79
|
+
return Math.max(base, idleTimeoutMs);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Arms a clearable pre-response (time-to-first-byte) abort guard for a streaming
|
|
83
|
+
* fetch, combined with the caller's signal.
|
|
84
|
+
*
|
|
85
|
+
* `AbortSignal.timeout(ms)` is an *absolute* wall-clock deadline: once handed to
|
|
86
|
+
* `fetch` it keeps governing the request after the response headers arrive, so
|
|
87
|
+
* it aborts an actively-streaming body the moment it fires — not just a stalled
|
|
88
|
+
* pre-response request (issue #2422 regression: large `write` tool-call streams
|
|
89
|
+
* died at the budget with `TimeoutError: The operation timed out.` despite
|
|
90
|
+
* deltas actively flowing). This arms a `clearTimeout`-able timer instead;
|
|
91
|
+
* callers MUST `clear()` as soon as the guarded transport attempt settles so
|
|
92
|
+
* the body stream is left to the iterator-level idle watchdog.
|
|
93
|
+
*
|
|
94
|
+
* Retrying callers MUST arm a fresh guard for each transport attempt and keep
|
|
95
|
+
* the retry loop's base signal reserved for caller cancellation. Reusing the
|
|
96
|
+
* guard as the loop signal makes its timeout indistinguishable from cancellation.
|
|
97
|
+
*
|
|
98
|
+
* Returns the caller signal unchanged (and a no-op `clear`) when no positive
|
|
99
|
+
* timeout is configured.
|
|
100
|
+
*/
|
|
101
|
+
function armPreResponseTimeout(callerSignal, timeoutMs) {
|
|
102
|
+
if (timeoutMs === void 0 || timeoutMs <= 0) return {
|
|
103
|
+
signal: callerSignal,
|
|
104
|
+
clear: () => {}
|
|
105
|
+
};
|
|
106
|
+
const controller = new AbortController();
|
|
107
|
+
const timer = setTimeout(() => {
|
|
108
|
+
controller.abort(new DOMException("The operation timed out.", "TimeoutError"));
|
|
109
|
+
}, timeoutMs);
|
|
110
|
+
timer.unref?.();
|
|
111
|
+
return {
|
|
112
|
+
signal: callerSignal ? AbortSignal.any([callerSignal, controller.signal]) : controller.signal,
|
|
113
|
+
clear: () => clearTimeout(timer)
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Yields items from an async iterable while enforcing a maximum idle gap between items.
|
|
118
|
+
*
|
|
119
|
+
* The first item may use a shorter timeout so stuck requests can be aborted and retried
|
|
120
|
+
* before any user-visible content has streamed.
|
|
121
|
+
*/
|
|
122
|
+
async function* iterateWithIdleTimeout(iterable, options) {
|
|
123
|
+
const firstItemTimeoutMs = options.firstItemTimeoutMs ?? options.idleTimeoutMs;
|
|
124
|
+
let firstItemDeadlineMs = firstItemTimeoutMs !== void 0 && firstItemTimeoutMs > 0 ? Date.now() + firstItemTimeoutMs : void 0;
|
|
125
|
+
const abortSignal = options.abortSignal;
|
|
126
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
127
|
+
let iteratorClosed = false;
|
|
128
|
+
const closeIterator = () => {
|
|
129
|
+
if (iteratorClosed) return;
|
|
130
|
+
iteratorClosed = true;
|
|
131
|
+
const returnPromise = iterator.return?.();
|
|
132
|
+
if (returnPromise) returnPromise.catch(() => {});
|
|
133
|
+
};
|
|
134
|
+
if (abortSignal?.aborted) {
|
|
135
|
+
closeIterator();
|
|
136
|
+
throw abortReason(abortSignal);
|
|
137
|
+
}
|
|
138
|
+
const withRacy = (promise) => promise.then((result) => ({
|
|
139
|
+
kind: "next",
|
|
140
|
+
result
|
|
141
|
+
}), (error) => ({
|
|
142
|
+
kind: "error",
|
|
143
|
+
error
|
|
144
|
+
}));
|
|
145
|
+
let awaitingFirstItem = true;
|
|
146
|
+
const markFirstItemReceived = () => {
|
|
147
|
+
awaitingFirstItem = false;
|
|
148
|
+
};
|
|
149
|
+
const isProgressItem = (item) => {
|
|
150
|
+
if (!options.isProgressItem) return true;
|
|
151
|
+
try {
|
|
152
|
+
return options.isProgressItem(item);
|
|
153
|
+
} catch {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
let lastProgressAt = Date.now();
|
|
158
|
+
const hasPendingLocalWork = () => {
|
|
159
|
+
if (!options.hasPendingLocalWork) return false;
|
|
160
|
+
try {
|
|
161
|
+
return options.hasPendingLocalWork();
|
|
162
|
+
} catch {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const extendDeadlineForLocalWork = () => {
|
|
167
|
+
if (awaitingFirstItem) {
|
|
168
|
+
if (firstItemDeadlineMs !== void 0 && firstItemTimeoutMs !== void 0) firstItemDeadlineMs = Date.now() + firstItemTimeoutMs;
|
|
169
|
+
} else lastProgressAt = Date.now();
|
|
170
|
+
};
|
|
171
|
+
const noTimeoutEnforced = (firstItemTimeoutMs === void 0 || firstItemTimeoutMs <= 0) && (options.idleTimeoutMs === void 0 || options.idleTimeoutMs <= 0);
|
|
172
|
+
let abortPromise;
|
|
173
|
+
let abortListener;
|
|
174
|
+
let resolveAbort;
|
|
175
|
+
if (abortSignal) {
|
|
176
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
177
|
+
resolveAbort = resolve;
|
|
178
|
+
abortListener = () => resolveAbort?.({ kind: "abort" });
|
|
179
|
+
abortSignal.addEventListener("abort", abortListener, { once: true });
|
|
180
|
+
abortPromise = promise;
|
|
181
|
+
}
|
|
182
|
+
let timeoutPromise;
|
|
183
|
+
let resolveTimeout;
|
|
184
|
+
let timeoutFired = false;
|
|
185
|
+
let timer;
|
|
186
|
+
let timerFireAtMs = Infinity;
|
|
187
|
+
const currentDeadlineMs = () => {
|
|
188
|
+
if (awaitingFirstItem) return firstItemDeadlineMs;
|
|
189
|
+
if (options.idleTimeoutMs !== void 0 && options.idleTimeoutMs > 0) return lastProgressAt + options.idleTimeoutMs;
|
|
190
|
+
};
|
|
191
|
+
const onTimerFire = () => {
|
|
192
|
+
timer = void 0;
|
|
193
|
+
timerFireAtMs = Infinity;
|
|
194
|
+
const deadlineMs = currentDeadlineMs();
|
|
195
|
+
if (deadlineMs === void 0) return;
|
|
196
|
+
const remainingMs = deadlineMs - Date.now();
|
|
197
|
+
if (remainingMs > 0) {
|
|
198
|
+
timerFireAtMs = deadlineMs;
|
|
199
|
+
timer = setTimeout(onTimerFire, remainingMs);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
timeoutFired = true;
|
|
203
|
+
resolveTimeout?.({ kind: "timeout" });
|
|
204
|
+
};
|
|
205
|
+
const armTimer = (deadlineMs) => {
|
|
206
|
+
if (timeoutPromise === void 0 || timeoutFired) {
|
|
207
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
208
|
+
timeoutPromise = promise;
|
|
209
|
+
resolveTimeout = resolve;
|
|
210
|
+
timeoutFired = false;
|
|
211
|
+
}
|
|
212
|
+
if (timer !== void 0) {
|
|
213
|
+
if (timerFireAtMs <= deadlineMs) return;
|
|
214
|
+
clearTimeout(timer);
|
|
215
|
+
}
|
|
216
|
+
timerFireAtMs = deadlineMs;
|
|
217
|
+
timer = setTimeout(onTimerFire, Math.max(0, deadlineMs - Date.now()));
|
|
218
|
+
};
|
|
219
|
+
let pendingNext;
|
|
220
|
+
try {
|
|
221
|
+
let raceCount = 0;
|
|
222
|
+
while (true) {
|
|
223
|
+
if (++raceCount % RACER_REMINT_INTERVAL === 0) {
|
|
224
|
+
if (abortPromise !== void 0 && !abortSignal.aborted) {
|
|
225
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
226
|
+
resolveAbort = resolve;
|
|
227
|
+
abortPromise = promise;
|
|
228
|
+
}
|
|
229
|
+
if (timeoutPromise !== void 0 && !timeoutFired) {
|
|
230
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
231
|
+
resolveTimeout = resolve;
|
|
232
|
+
timeoutPromise = promise;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
let activeTimeoutMs;
|
|
236
|
+
if (awaitingFirstItem) {
|
|
237
|
+
if (firstItemDeadlineMs !== void 0) {
|
|
238
|
+
activeTimeoutMs = firstItemDeadlineMs - Date.now();
|
|
239
|
+
if (activeTimeoutMs <= 0) {
|
|
240
|
+
if (!hasPendingLocalWork()) {
|
|
241
|
+
options.onFirstItemTimeout?.();
|
|
242
|
+
closeIterator();
|
|
243
|
+
throw new StreamTimeoutError(options.firstItemErrorMessage ?? options.errorMessage);
|
|
244
|
+
}
|
|
245
|
+
extendDeadlineForLocalWork();
|
|
246
|
+
activeTimeoutMs = firstItemDeadlineMs - Date.now();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
} else if (options.idleTimeoutMs !== void 0 && options.idleTimeoutMs > 0) {
|
|
250
|
+
activeTimeoutMs = options.idleTimeoutMs - (Date.now() - lastProgressAt);
|
|
251
|
+
if (activeTimeoutMs <= 0) {
|
|
252
|
+
if (!hasPendingLocalWork()) {
|
|
253
|
+
options.onIdle?.();
|
|
254
|
+
closeIterator();
|
|
255
|
+
throw new StreamTimeoutError(options.errorMessage);
|
|
256
|
+
}
|
|
257
|
+
extendDeadlineForLocalWork();
|
|
258
|
+
activeTimeoutMs = options.idleTimeoutMs;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
pendingNext ??= withRacy(iterator.next());
|
|
262
|
+
const racers = [pendingNext];
|
|
263
|
+
if (!noTimeoutEnforced && activeTimeoutMs !== void 0 && activeTimeoutMs > 0) {
|
|
264
|
+
armTimer(Date.now() + activeTimeoutMs);
|
|
265
|
+
racers.push(timeoutPromise);
|
|
266
|
+
}
|
|
267
|
+
if (abortPromise) racers.push(abortPromise);
|
|
268
|
+
let continuing = false;
|
|
269
|
+
try {
|
|
270
|
+
const outcome = await Promise.race(racers);
|
|
271
|
+
if (outcome.kind === "next" || outcome.kind === "error") pendingNext = void 0;
|
|
272
|
+
if (outcome.kind === "abort") {
|
|
273
|
+
closeIterator();
|
|
274
|
+
throw abortReason(abortSignal);
|
|
275
|
+
}
|
|
276
|
+
if (outcome.kind === "timeout") {
|
|
277
|
+
if (hasPendingLocalWork()) {
|
|
278
|
+
extendDeadlineForLocalWork();
|
|
279
|
+
continuing = true;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (!awaitingFirstItem) options.onIdle?.();
|
|
283
|
+
else options.onFirstItemTimeout?.();
|
|
284
|
+
closeIterator();
|
|
285
|
+
throw new StreamTimeoutError(!awaitingFirstItem ? options.errorMessage : options.firstItemErrorMessage ?? options.errorMessage);
|
|
286
|
+
}
|
|
287
|
+
if (outcome.kind === "error") throw outcome.error;
|
|
288
|
+
if (outcome.result.done) {
|
|
289
|
+
markFirstItemReceived();
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
const item = outcome.result.value;
|
|
293
|
+
if (isProgressItem(item)) {
|
|
294
|
+
markFirstItemReceived();
|
|
295
|
+
lastProgressAt = Date.now();
|
|
296
|
+
}
|
|
297
|
+
yield item;
|
|
298
|
+
continuing = true;
|
|
299
|
+
} finally {
|
|
300
|
+
if (!continuing) closeIterator();
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
} finally {
|
|
304
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
305
|
+
resolveTimeout?.({ kind: "timeout" });
|
|
306
|
+
if (abortListener && abortSignal) abortSignal.removeEventListener("abort", abortListener);
|
|
307
|
+
resolveAbort?.({ kind: "abort" });
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Yields items from an async iterable until the consumer marks the stream
|
|
312
|
+
* logically finished AND the source stays silent past a short grace window.
|
|
313
|
+
*
|
|
314
|
+
* Misbehaving OpenAI-compatible servers deliver the terminal chunk but never
|
|
315
|
+
* send `[DONE]` nor close the connection; without this guard the consumer
|
|
316
|
+
* hangs on `iterator.next()` until the idle watchdog converts an
|
|
317
|
+
* already-successful turn into a timeout error. Grace expiry is a clean end
|
|
318
|
+
* of iteration, never an error.
|
|
319
|
+
*/
|
|
320
|
+
async function* iterateWithTerminalGrace(iterable, options) {
|
|
321
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
322
|
+
try {
|
|
323
|
+
while (true) {
|
|
324
|
+
const finishedAtMs = options.finishedAtMs();
|
|
325
|
+
if (finishedAtMs === void 0) {
|
|
326
|
+
const result = await iterator.next();
|
|
327
|
+
if (result.done) return;
|
|
328
|
+
yield result.value;
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
const remainingMs = finishedAtMs + options.graceMs - Date.now();
|
|
332
|
+
if (remainingMs <= 0) {
|
|
333
|
+
options.onGraceEnd?.();
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
const nextPromise = iterator.next();
|
|
337
|
+
let timer;
|
|
338
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
339
|
+
timer = setTimeout(() => resolve("timeout"), remainingMs);
|
|
340
|
+
});
|
|
341
|
+
try {
|
|
342
|
+
const outcome = await Promise.race([nextPromise, timeoutPromise]);
|
|
343
|
+
if (outcome === "timeout") {
|
|
344
|
+
nextPromise.catch(() => {});
|
|
345
|
+
options.onGraceEnd?.();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
if (outcome.done) return;
|
|
349
|
+
yield outcome.value;
|
|
350
|
+
} finally {
|
|
351
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
} finally {
|
|
355
|
+
const returnPromise = iterator.return?.();
|
|
356
|
+
if (returnPromise) Promise.resolve(returnPromise).catch(() => {});
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
function abortReason(signal) {
|
|
360
|
+
const reason = signal.reason;
|
|
361
|
+
if (reason instanceof Error) return reason;
|
|
362
|
+
if (typeof reason === "string") return new AbortError(reason);
|
|
363
|
+
return new AbortError();
|
|
364
|
+
}
|
|
365
|
+
//#endregion
|
|
366
|
+
export { getStreamIdleTimeoutMs as a, getStreamFirstEventTimeoutMs as i, getOpenAIStreamFirstEventTimeoutMs as n, iterateWithIdleTimeout as o, getOpenAIStreamIdleTimeoutMs as r, iterateWithTerminalGrace as s, armPreResponseTimeout as t };
|