@jeffreycao/copilot-api 2.1.4 → 2.1.6
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 +12 -1
- package/README.zh-CN.md +12 -1
- package/dist/{auth-C0aeKq7k.js → auth-DYaGY4fS.js} +3 -3
- package/dist/{auth-C0aeKq7k.js.map → auth-DYaGY4fS.js.map} +1 -1
- package/dist/auth-t5Gi1JB9.js +2 -0
- package/dist/{config-CoMdcHDW.js → config-DMrKDHiF.js} +32 -4
- package/dist/config-DMrKDHiF.js.map +1 -0
- package/dist/{debug-D2giR-Kj.js → debug-2GkXJBt5.js} +2 -2
- package/dist/{debug-D2giR-Kj.js.map → debug-2GkXJBt5.js.map} +1 -1
- package/dist/main.js +3 -3
- package/dist/{models-DUdPhOBN.js → models-Do0TBzAz.js} +2 -2
- package/dist/{models-DUdPhOBN.js.map → models-Do0TBzAz.js.map} +1 -1
- package/dist/{server-BwT9agIL.js → server-GxC8BArQ.js} +221 -98
- package/dist/server-GxC8BArQ.js.map +1 -0
- package/dist/{start-B5CJA1Cx.js → start-B0MTWFyd.js} +6 -6
- package/dist/{start-B5CJA1Cx.js.map → start-B0MTWFyd.js.map} +1 -1
- package/dist/{token-_ZvkUtOA.js → token-DmNSTe37.js} +466 -86
- package/dist/token-DmNSTe37.js.map +1 -0
- package/package.json +1 -1
- package/dist/auth-DH-ThnhJ.js +0 -2
- package/dist/config-CoMdcHDW.js.map +0 -1
- package/dist/server-BwT9agIL.js.map +0 -1
- package/dist/token-_ZvkUtOA.js.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as isResponsesApiWebSocketEnabled, E as getResponsesTransportConfig, M as PATHS, c as setProviderConfig, n as getRawProviderConfig } from "./config-DMrKDHiF.js";
|
|
2
2
|
import consola from "consola";
|
|
3
3
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
4
4
|
import fs, { readFile } from "node:fs/promises";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { createServer } from "node:http";
|
|
7
|
-
import { events } from "fetch-event-stream";
|
|
8
7
|
import { getProxyForUrl } from "proxy-from-env";
|
|
9
8
|
import { WebSocket } from "undici";
|
|
9
|
+
import { events } from "fetch-event-stream";
|
|
10
10
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11
11
|
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
12
12
|
import { exec } from "node:child_process";
|
|
@@ -19,6 +19,10 @@ var HTTPError = class extends Error {
|
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
21
|
async function forwardError(c, error) {
|
|
22
|
+
if (c.req.raw.signal.aborted || isAbortError$1(error)) return new Response(null, {
|
|
23
|
+
status: 499,
|
|
24
|
+
statusText: "Client Closed Request"
|
|
25
|
+
});
|
|
22
26
|
consola.error("Error occurred:", error);
|
|
23
27
|
if (error instanceof HTTPError) {
|
|
24
28
|
if (error.response.status === 429) for (const [name, value] of error.response.headers) {
|
|
@@ -43,6 +47,7 @@ async function forwardError(c, error) {
|
|
|
43
47
|
type: "error"
|
|
44
48
|
} }, 500);
|
|
45
49
|
}
|
|
50
|
+
const isAbortError$1 = (error) => error instanceof Error && error.name === "AbortError";
|
|
46
51
|
//#endregion
|
|
47
52
|
//#region src/lib/state.ts
|
|
48
53
|
const state = {
|
|
@@ -53,9 +58,72 @@ const state = {
|
|
|
53
58
|
};
|
|
54
59
|
//#endregion
|
|
55
60
|
//#region src/services/responses-websocket.ts
|
|
56
|
-
const DEFAULT_WEBSOCKET_IDLE_TIMEOUT_MS = 6e4;
|
|
57
61
|
const websocketPool = /* @__PURE__ */ new Map();
|
|
58
62
|
const websocketActiveRequests = /* @__PURE__ */ new Map();
|
|
63
|
+
var ResponsesWebSocketOpenTimeoutError = class extends Error {
|
|
64
|
+
constructor(timeoutMs) {
|
|
65
|
+
super(`Responses websocket did not open within ${timeoutMs}ms`);
|
|
66
|
+
this.name = "ResponsesWebSocketOpenTimeoutError";
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
var ResponsesWebSocketInactivityTimeoutError = class extends Error {
|
|
70
|
+
constructor(timeoutMs) {
|
|
71
|
+
super(`Responses websocket stream was inactive for ${timeoutMs}ms`);
|
|
72
|
+
this.name = "ResponsesWebSocketInactivityTimeoutError";
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
var ResponsesWebSocketBufferOverflowError = class extends Error {
|
|
76
|
+
constructor(maxBufferedBytes, maxBufferedMessages) {
|
|
77
|
+
super(`Responses websocket buffer exceeded ${maxBufferedBytes} bytes or ${maxBufferedMessages} messages; downstream consumption is too slow`);
|
|
78
|
+
this.name = "ResponsesWebSocketBufferOverflowError";
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
var WebSocketMessageBuffer = class {
|
|
82
|
+
entries = [];
|
|
83
|
+
head = 0;
|
|
84
|
+
maxBufferedBytes;
|
|
85
|
+
maxBufferedMessages;
|
|
86
|
+
sizeBytes = 0;
|
|
87
|
+
constructor(maxBufferedBytes, maxBufferedMessages) {
|
|
88
|
+
this.maxBufferedBytes = maxBufferedBytes;
|
|
89
|
+
this.maxBufferedMessages = maxBufferedMessages;
|
|
90
|
+
}
|
|
91
|
+
get bufferedBytes() {
|
|
92
|
+
return this.sizeBytes;
|
|
93
|
+
}
|
|
94
|
+
get bufferedMessages() {
|
|
95
|
+
return this.entries.length - this.head;
|
|
96
|
+
}
|
|
97
|
+
enqueue(data) {
|
|
98
|
+
const size = getWebSocketMessageSize(data);
|
|
99
|
+
if (this.sizeBytes + size > this.maxBufferedBytes || this.bufferedMessages + 1 > this.maxBufferedMessages) return false;
|
|
100
|
+
this.entries.push({
|
|
101
|
+
data: normalizeWebSocketMessageData(data),
|
|
102
|
+
size
|
|
103
|
+
});
|
|
104
|
+
this.sizeBytes += size;
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
dequeue() {
|
|
108
|
+
const entry = this.entries[this.head];
|
|
109
|
+
if (!entry) return void 0;
|
|
110
|
+
this.entries[this.head] = void 0;
|
|
111
|
+
this.head += 1;
|
|
112
|
+
this.sizeBytes -= entry.size;
|
|
113
|
+
this.compactIfNeeded();
|
|
114
|
+
return entry.data;
|
|
115
|
+
}
|
|
116
|
+
clear() {
|
|
117
|
+
this.entries.length = 0;
|
|
118
|
+
this.head = 0;
|
|
119
|
+
this.sizeBytes = 0;
|
|
120
|
+
}
|
|
121
|
+
compactIfNeeded() {
|
|
122
|
+
if (this.head < 256 || this.head * 2 < this.entries.length) return;
|
|
123
|
+
this.entries.splice(0, this.head);
|
|
124
|
+
this.head = 0;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
59
127
|
const createWebSocketUrl = (url) => {
|
|
60
128
|
const websocketUrl = new URL(url);
|
|
61
129
|
if (websocketUrl.protocol === "https:") websocketUrl.protocol = "wss:";
|
|
@@ -64,23 +132,34 @@ const createWebSocketUrl = (url) => {
|
|
|
64
132
|
};
|
|
65
133
|
const createPooledWebSocketStream = (request, options) => runPooledWebSocketRequest(request, options);
|
|
66
134
|
const runPooledWebSocketRequest = async function* (request, options) {
|
|
135
|
+
throwIfAborted(request.signal);
|
|
67
136
|
const { entry, pooled } = getPooledWebSocketRequestTarget(request, options);
|
|
68
|
-
const release = acquirePooledWebSocketEntry(request.poolKey, entry, pooled
|
|
137
|
+
const release = acquirePooledWebSocketEntry(request.poolKey, entry, pooled);
|
|
138
|
+
let messageStream = null;
|
|
139
|
+
let reusable = false;
|
|
69
140
|
try {
|
|
70
141
|
const websocket = await getReadyPooledWebSocket(request.poolKey, entry, pooled, options);
|
|
142
|
+
throwIfAborted(request.signal);
|
|
143
|
+
messageStream = createWebSocketMessageStream(websocket, request.signal, options);
|
|
144
|
+
messageStream.start();
|
|
71
145
|
websocket.send(JSON.stringify(request.payload));
|
|
72
|
-
for await (const data of
|
|
146
|
+
for await (const data of messageStream.iterable) {
|
|
73
147
|
const chunk = options.createChunk(data);
|
|
148
|
+
const isTerminal = options.isTerminalChunk(chunk);
|
|
149
|
+
if (isTerminal) {
|
|
150
|
+
messageStream.complete();
|
|
151
|
+
reusable = true;
|
|
152
|
+
}
|
|
74
153
|
yield chunk;
|
|
75
|
-
if (
|
|
154
|
+
if (isTerminal) return;
|
|
76
155
|
}
|
|
77
|
-
removePooledWebSocketEntry(request.poolKey, entry);
|
|
78
156
|
throw new Error(options.terminalChunkMissingMessage);
|
|
79
157
|
} catch (error) {
|
|
80
|
-
|
|
81
|
-
throw toError(error);
|
|
158
|
+
throw toError$1(error);
|
|
82
159
|
} finally {
|
|
83
|
-
|
|
160
|
+
messageStream?.dispose();
|
|
161
|
+
if (!reusable) removePooledWebSocketEntry(request.poolKey, entry);
|
|
162
|
+
release(reusable);
|
|
84
163
|
}
|
|
85
164
|
};
|
|
86
165
|
const getPooledWebSocketRequestTarget = (request, options) => {
|
|
@@ -91,7 +170,7 @@ const getPooledWebSocketRequestTarget = (request, options) => {
|
|
|
91
170
|
const existing = websocketPool.get(request.poolKey);
|
|
92
171
|
if (existing && !existing.closed) {
|
|
93
172
|
consola.debug("websocket from pool");
|
|
94
|
-
|
|
173
|
+
clearPooledWebSocketIdleState(existing);
|
|
95
174
|
return {
|
|
96
175
|
entry: existing,
|
|
97
176
|
pooled: true
|
|
@@ -105,17 +184,24 @@ const getPooledWebSocketRequestTarget = (request, options) => {
|
|
|
105
184
|
};
|
|
106
185
|
};
|
|
107
186
|
const createPooledWebSocketEntry = (request, options) => {
|
|
187
|
+
const websocketPromise = openWebSocket({
|
|
188
|
+
headers: request.headers,
|
|
189
|
+
openErrorMessage: options.openErrorMessage,
|
|
190
|
+
openTimeoutMs: options.openTimeoutMs,
|
|
191
|
+
signal: request.signal,
|
|
192
|
+
url: request.url
|
|
193
|
+
});
|
|
108
194
|
const entry = {
|
|
109
195
|
closed: false,
|
|
196
|
+
idleMessageListener: null,
|
|
110
197
|
idleTimer: null,
|
|
198
|
+
poolIdleTimeoutMs: options.poolIdleTimeoutMs,
|
|
111
199
|
requestCount: 0,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
openErrorMessage: options.openErrorMessage,
|
|
115
|
-
url: request.url
|
|
116
|
-
})
|
|
200
|
+
websocket: null,
|
|
201
|
+
websocketPromise
|
|
117
202
|
};
|
|
118
203
|
entry.websocketPromise.then((websocket) => {
|
|
204
|
+
entry.websocket = websocket;
|
|
119
205
|
websocket.addEventListener("close", () => {
|
|
120
206
|
removePooledWebSocketEntry(request.poolKey, entry);
|
|
121
207
|
});
|
|
@@ -127,26 +213,30 @@ const createPooledWebSocketEntry = (request, options) => {
|
|
|
127
213
|
});
|
|
128
214
|
return entry;
|
|
129
215
|
};
|
|
130
|
-
const acquirePooledWebSocketEntry = (poolKey, entry, pooled
|
|
131
|
-
|
|
216
|
+
const acquirePooledWebSocketEntry = (poolKey, entry, pooled) => {
|
|
217
|
+
clearPooledWebSocketIdleState(entry);
|
|
132
218
|
incrementPooledWebSocketActiveRequestCount(poolKey);
|
|
133
219
|
entry.requestCount += 1;
|
|
134
220
|
let released = false;
|
|
135
|
-
return () => {
|
|
221
|
+
return (reusable) => {
|
|
136
222
|
if (released) return;
|
|
137
223
|
released = true;
|
|
138
224
|
entry.requestCount -= 1;
|
|
139
225
|
decrementPooledWebSocketActiveRequestCount(poolKey);
|
|
226
|
+
if (!reusable) {
|
|
227
|
+
removePooledWebSocketEntry(poolKey, entry);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
140
230
|
if (entry.closed || entry.requestCount > 0) return;
|
|
141
231
|
if (pooled && websocketPool.get(poolKey) === entry) {
|
|
142
|
-
schedulePooledWebSocketIdleClose(poolKey, entry
|
|
232
|
+
schedulePooledWebSocketIdleClose(poolKey, entry);
|
|
143
233
|
return;
|
|
144
234
|
}
|
|
145
235
|
removePooledWebSocketEntry(poolKey, entry);
|
|
146
236
|
};
|
|
147
237
|
};
|
|
148
238
|
const getReadyPooledWebSocket = async (poolKey, entry, pooled, options) => {
|
|
149
|
-
const unavailableErrorMessage = options
|
|
239
|
+
const unavailableErrorMessage = options.unavailableErrorMessage ?? "Websocket connection became unavailable before the request started";
|
|
150
240
|
if (entry.closed) throw new Error(unavailableErrorMessage);
|
|
151
241
|
const websocket = await entry.websocketPromise;
|
|
152
242
|
if (entry.closed || pooled && websocketPool.get(poolKey) !== entry) throw new Error(unavailableErrorMessage);
|
|
@@ -156,18 +246,31 @@ const getReadyPooledWebSocket = async (poolKey, entry, pooled, options) => {
|
|
|
156
246
|
}
|
|
157
247
|
return websocket;
|
|
158
248
|
};
|
|
159
|
-
const schedulePooledWebSocketIdleClose = (poolKey, entry
|
|
160
|
-
|
|
249
|
+
const schedulePooledWebSocketIdleClose = (poolKey, entry) => {
|
|
250
|
+
clearPooledWebSocketIdleState(entry);
|
|
251
|
+
const websocket = entry.websocket;
|
|
252
|
+
if (!websocket || websocket.readyState !== WebSocket.OPEN) {
|
|
253
|
+
removePooledWebSocketEntry(poolKey, entry);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
entry.idleMessageListener = () => {
|
|
257
|
+
removePooledWebSocketEntry(poolKey, entry);
|
|
258
|
+
};
|
|
259
|
+
websocket.addEventListener("message", entry.idleMessageListener);
|
|
161
260
|
entry.idleTimer = setTimeout(() => {
|
|
162
261
|
removePooledWebSocketEntry(poolKey, entry);
|
|
163
|
-
},
|
|
262
|
+
}, entry.poolIdleTimeoutMs);
|
|
164
263
|
unrefTimer(entry.idleTimer);
|
|
165
264
|
};
|
|
166
|
-
const
|
|
265
|
+
const clearPooledWebSocketIdleState = (entry) => {
|
|
167
266
|
if (entry.idleTimer) {
|
|
168
267
|
clearTimeout(entry.idleTimer);
|
|
169
268
|
entry.idleTimer = null;
|
|
170
269
|
}
|
|
270
|
+
if (entry.websocket && entry.idleMessageListener) {
|
|
271
|
+
entry.websocket.removeEventListener("message", entry.idleMessageListener);
|
|
272
|
+
entry.idleMessageListener = null;
|
|
273
|
+
}
|
|
171
274
|
};
|
|
172
275
|
const getPooledWebSocketActiveRequestCount = (poolKey) => websocketActiveRequests.get(poolKey) ?? 0;
|
|
173
276
|
const incrementPooledWebSocketActiveRequestCount = (poolKey) => {
|
|
@@ -175,117 +278,193 @@ const incrementPooledWebSocketActiveRequestCount = (poolKey) => {
|
|
|
175
278
|
};
|
|
176
279
|
const decrementPooledWebSocketActiveRequestCount = (poolKey) => {
|
|
177
280
|
const nextCount = getPooledWebSocketActiveRequestCount(poolKey) - 1;
|
|
178
|
-
if (nextCount <= 0)
|
|
179
|
-
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
websocketActiveRequests.set(poolKey, nextCount);
|
|
281
|
+
if (nextCount <= 0) websocketActiveRequests.delete(poolKey);
|
|
282
|
+
else websocketActiveRequests.set(poolKey, nextCount);
|
|
183
283
|
};
|
|
184
284
|
const removePooledWebSocketEntry = (poolKey, entry) => {
|
|
185
285
|
if (websocketPool.get(poolKey) === entry) websocketPool.delete(poolKey);
|
|
186
286
|
if (entry.closed) return;
|
|
187
287
|
entry.closed = true;
|
|
188
|
-
|
|
288
|
+
clearPooledWebSocketIdleState(entry);
|
|
189
289
|
entry.websocketPromise.then(closeWebSocket).catch(() => {});
|
|
190
290
|
};
|
|
191
|
-
const unrefTimer = (timer) => {
|
|
192
|
-
if (typeof timer === "object" && "unref" in timer && typeof timer.unref === "function") timer.unref();
|
|
193
|
-
};
|
|
194
291
|
const createWebSocketError = (message, event) => {
|
|
195
292
|
const reason = event?.error ?? event?.message;
|
|
196
293
|
if (reason === void 0 || reason === "") return new Error(message);
|
|
197
|
-
const cause = toError(reason);
|
|
294
|
+
const cause = toError$1(reason);
|
|
198
295
|
return new Error(`${message}: ${cause.message}`, { cause });
|
|
199
296
|
};
|
|
200
|
-
const openWebSocket = async ({ headers, openErrorMessage, url }) => await new Promise((resolve, reject) => {
|
|
297
|
+
const openWebSocket = async ({ headers, openErrorMessage, openTimeoutMs, signal, url }) => await new Promise((resolve, reject) => {
|
|
298
|
+
if (signal?.aborted) {
|
|
299
|
+
reject(toAbortReason$1(signal.reason));
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
201
302
|
const proxy = typeof Bun === "undefined" ? void 0 : getProxyUrl(url);
|
|
202
303
|
const websocket = new WebSocket(url, {
|
|
203
304
|
headers,
|
|
204
305
|
...proxy ? { proxy } : {}
|
|
205
306
|
});
|
|
307
|
+
let settled = false;
|
|
308
|
+
const timer = setTimeout(() => {
|
|
309
|
+
fail(new ResponsesWebSocketOpenTimeoutError(openTimeoutMs));
|
|
310
|
+
}, openTimeoutMs);
|
|
206
311
|
const cleanup = () => {
|
|
312
|
+
clearTimeout(timer);
|
|
313
|
+
signal?.removeEventListener("abort", onAbort);
|
|
207
314
|
websocket.removeEventListener("open", onOpen);
|
|
315
|
+
websocket.removeEventListener("close", onClose);
|
|
208
316
|
websocket.removeEventListener("error", onError);
|
|
209
317
|
};
|
|
318
|
+
const fail = (error) => {
|
|
319
|
+
if (settled) return;
|
|
320
|
+
settled = true;
|
|
321
|
+
cleanup();
|
|
322
|
+
closeWebSocket(websocket);
|
|
323
|
+
reject(error);
|
|
324
|
+
};
|
|
325
|
+
const onAbort = () => fail(toAbortReason$1(signal?.reason));
|
|
210
326
|
const onOpen = () => {
|
|
327
|
+
if (settled) return;
|
|
328
|
+
settled = true;
|
|
211
329
|
cleanup();
|
|
212
330
|
resolve(websocket);
|
|
213
331
|
};
|
|
332
|
+
const onClose = () => fail(new Error(openErrorMessage));
|
|
214
333
|
const onError = (event) => {
|
|
215
|
-
|
|
216
|
-
reject(createWebSocketError(openErrorMessage, event));
|
|
334
|
+
fail(createWebSocketError(openErrorMessage, event));
|
|
217
335
|
};
|
|
336
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
218
337
|
websocket.addEventListener("open", onOpen);
|
|
338
|
+
websocket.addEventListener("close", onClose);
|
|
219
339
|
websocket.addEventListener("error", onError);
|
|
220
340
|
});
|
|
221
|
-
const createWebSocketMessageStream =
|
|
222
|
-
const
|
|
341
|
+
const createWebSocketMessageStream = (websocket, signal, options) => {
|
|
342
|
+
const buffer = new WebSocketMessageBuffer(options.maxBufferedBytes, options.maxBufferedMessages);
|
|
223
343
|
let closed = false;
|
|
344
|
+
let disposed = false;
|
|
224
345
|
let error = null;
|
|
346
|
+
let inactivityTimer = null;
|
|
225
347
|
let notify = null;
|
|
226
348
|
const wake = () => {
|
|
227
349
|
notify?.();
|
|
228
350
|
notify = null;
|
|
229
351
|
};
|
|
352
|
+
const clearInactivityTimer = () => {
|
|
353
|
+
if (!inactivityTimer) return;
|
|
354
|
+
clearTimeout(inactivityTimer);
|
|
355
|
+
inactivityTimer = null;
|
|
356
|
+
};
|
|
357
|
+
const fail = (nextError, close = true) => {
|
|
358
|
+
if (error || disposed) return;
|
|
359
|
+
error = nextError;
|
|
360
|
+
clearInactivityTimer();
|
|
361
|
+
buffer.clear();
|
|
362
|
+
if (close) closeWebSocket(websocket);
|
|
363
|
+
wake();
|
|
364
|
+
};
|
|
365
|
+
const resetInactivityTimer = () => {
|
|
366
|
+
clearInactivityTimer();
|
|
367
|
+
if (disposed || closed || error) return;
|
|
368
|
+
inactivityTimer = setTimeout(() => {
|
|
369
|
+
fail(new ResponsesWebSocketInactivityTimeoutError(options.streamInactivityTimeoutMs));
|
|
370
|
+
}, options.streamInactivityTimeoutMs);
|
|
371
|
+
};
|
|
230
372
|
const onMessage = (event) => {
|
|
231
|
-
|
|
373
|
+
resetInactivityTimer();
|
|
374
|
+
if (!buffer.enqueue(event.data)) {
|
|
375
|
+
fail(new ResponsesWebSocketBufferOverflowError(options.maxBufferedBytes, options.maxBufferedMessages));
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
232
378
|
wake();
|
|
233
379
|
};
|
|
234
380
|
const onClose = () => {
|
|
235
381
|
consola.debug("WebSocket closed");
|
|
236
382
|
closed = true;
|
|
383
|
+
clearInactivityTimer();
|
|
237
384
|
wake();
|
|
238
385
|
};
|
|
239
386
|
const onError = (event) => {
|
|
240
387
|
consola.error("WebSocket error:", event, event.error);
|
|
241
|
-
|
|
242
|
-
wake();
|
|
388
|
+
fail(createWebSocketError(options.streamErrorMessage, event), false);
|
|
243
389
|
};
|
|
390
|
+
const onAbort = () => fail(toAbortReason$1(signal?.reason));
|
|
244
391
|
websocket.addEventListener("message", onMessage);
|
|
245
392
|
websocket.addEventListener("close", onClose);
|
|
246
393
|
websocket.addEventListener("error", onError);
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
if (error) throw toError(error);
|
|
255
|
-
if (closed) break;
|
|
256
|
-
await new Promise((resolve) => {
|
|
257
|
-
notify = resolve;
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
} finally {
|
|
394
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
395
|
+
const dispose = () => {
|
|
396
|
+
if (disposed) return;
|
|
397
|
+
disposed = true;
|
|
398
|
+
clearInactivityTimer();
|
|
399
|
+
buffer.clear();
|
|
261
400
|
websocket.removeEventListener("message", onMessage);
|
|
262
401
|
websocket.removeEventListener("close", onClose);
|
|
263
402
|
websocket.removeEventListener("error", onError);
|
|
264
|
-
|
|
403
|
+
signal?.removeEventListener("abort", onAbort);
|
|
404
|
+
wake();
|
|
405
|
+
};
|
|
406
|
+
return {
|
|
407
|
+
complete: clearInactivityTimer,
|
|
408
|
+
dispose,
|
|
409
|
+
iterable: (async function* () {
|
|
410
|
+
try {
|
|
411
|
+
while (true) {
|
|
412
|
+
const item = buffer.dequeue();
|
|
413
|
+
if (item) {
|
|
414
|
+
yield await item;
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
if (error) throw toError$1(error);
|
|
418
|
+
if (closed) return;
|
|
419
|
+
await new Promise((resolve) => {
|
|
420
|
+
notify = resolve;
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
} finally {
|
|
424
|
+
dispose();
|
|
425
|
+
}
|
|
426
|
+
})(),
|
|
427
|
+
start: resetInactivityTimer
|
|
428
|
+
};
|
|
265
429
|
};
|
|
266
430
|
const normalizeWebSocketMessageData = async (data) => {
|
|
267
431
|
if (typeof data === "string") return data;
|
|
268
432
|
if (data instanceof ArrayBuffer) return new TextDecoder().decode(data);
|
|
269
|
-
if (ArrayBuffer.isView(data))
|
|
270
|
-
const view = data;
|
|
271
|
-
return new TextDecoder().decode(new Uint8Array(view.buffer, view.byteOffset, view.byteLength));
|
|
272
|
-
}
|
|
433
|
+
if (ArrayBuffer.isView(data)) return new TextDecoder().decode(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
|
|
273
434
|
if (isTextReadable(data)) return await data.text();
|
|
274
435
|
return String(data);
|
|
275
436
|
};
|
|
276
|
-
const
|
|
277
|
-
if (
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
437
|
+
const getWebSocketMessageSize = (data) => {
|
|
438
|
+
if (typeof data === "string") return new TextEncoder().encode(data).byteLength;
|
|
439
|
+
if (data instanceof ArrayBuffer) return data.byteLength;
|
|
440
|
+
if (ArrayBuffer.isView(data)) return data.byteLength;
|
|
441
|
+
if (isSized(data)) return data.size;
|
|
442
|
+
return new TextEncoder().encode(String(data)).byteLength;
|
|
443
|
+
};
|
|
444
|
+
const isTextReadable = (value) => Boolean(value && typeof value === "object" && "text" in value && typeof value.text === "function");
|
|
445
|
+
const isSized = (value) => Boolean(value && typeof value === "object" && "size" in value && typeof value.size === "number");
|
|
446
|
+
const toAbortReason$1 = (reason) => {
|
|
447
|
+
if (reason instanceof Error) return reason;
|
|
448
|
+
const error = /* @__PURE__ */ new Error("The operation was aborted");
|
|
449
|
+
error.name = "AbortError";
|
|
450
|
+
return error;
|
|
451
|
+
};
|
|
452
|
+
const throwIfAborted = (signal) => {
|
|
453
|
+
if (signal?.aborted) throw toAbortReason$1(signal.reason);
|
|
454
|
+
};
|
|
455
|
+
const toError$1 = (value) => {
|
|
281
456
|
if (value instanceof Error) return value;
|
|
282
457
|
return new Error(String(value));
|
|
283
458
|
};
|
|
284
459
|
const closeWebSocket = (websocket) => {
|
|
285
|
-
if (websocket.readyState
|
|
460
|
+
if (websocket.readyState !== WebSocket.CONNECTING && websocket.readyState !== WebSocket.OPEN) return;
|
|
461
|
+
try {
|
|
462
|
+
websocket.close();
|
|
463
|
+
} catch {}
|
|
286
464
|
};
|
|
287
|
-
const getProxyUrl = (url) =>
|
|
288
|
-
|
|
465
|
+
const getProxyUrl = (url) => getProxyForUrl(url.replace(/^wss:/u, "https:").replace(/^ws:/u, "http:"));
|
|
466
|
+
const unrefTimer = (timer) => {
|
|
467
|
+
if (typeof timer === "object" && "unref" in timer && typeof timer.unref === "function") timer.unref();
|
|
289
468
|
};
|
|
290
469
|
//#endregion
|
|
291
470
|
//#region src/services/responses-websocket-helpers.ts
|
|
@@ -316,13 +495,200 @@ const isTerminalResponsesStreamChunk = (chunk) => {
|
|
|
316
495
|
return false;
|
|
317
496
|
}
|
|
318
497
|
};
|
|
319
|
-
const createResponsesSafeStream = async function* (source) {
|
|
498
|
+
const createResponsesSafeStream = async function* (source, options = {}) {
|
|
320
499
|
try {
|
|
321
500
|
yield* source;
|
|
322
501
|
} catch (error) {
|
|
502
|
+
if (options.signal?.aborted || isAbortError(error)) return;
|
|
323
503
|
yield createResponsesErrorServerSentEventChunk(getErrorMessage(error));
|
|
324
504
|
}
|
|
325
505
|
};
|
|
506
|
+
const isAbortError = (error) => error instanceof Error && error.name === "AbortError";
|
|
507
|
+
//#endregion
|
|
508
|
+
//#region src/services/responses-http.ts
|
|
509
|
+
var ResponsesHeadersTimeoutError = class extends Error {
|
|
510
|
+
constructor(timeoutMs) {
|
|
511
|
+
super(`Responses upstream did not return headers within ${timeoutMs}ms`);
|
|
512
|
+
this.name = "ResponsesHeadersTimeoutError";
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
var ResponsesStreamInactivityTimeoutError = class extends Error {
|
|
516
|
+
constructor(timeoutMs) {
|
|
517
|
+
super(`Responses upstream stream was inactive for ${timeoutMs}ms`);
|
|
518
|
+
this.name = "ResponsesStreamInactivityTimeoutError";
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
async function fetchResponsesWithLifecycle(input, init, options) {
|
|
522
|
+
const lifecycle = createRequestLifecycle(options);
|
|
523
|
+
try {
|
|
524
|
+
const response = await fetch(input, {
|
|
525
|
+
...init,
|
|
526
|
+
signal: lifecycle.signal
|
|
527
|
+
});
|
|
528
|
+
lifecycle.headersReceived();
|
|
529
|
+
return createManagedResponse(response, lifecycle, options);
|
|
530
|
+
} catch (error) {
|
|
531
|
+
throw lifecycle.finishWithError(error);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
const createRequestLifecycle = (options) => {
|
|
535
|
+
const controller = new AbortController();
|
|
536
|
+
const downstreamSignal = options.signal;
|
|
537
|
+
let finished = false;
|
|
538
|
+
let headersTimer = null;
|
|
539
|
+
const abortFromDownstream = () => {
|
|
540
|
+
controller.abort(toAbortReason(downstreamSignal?.reason));
|
|
541
|
+
};
|
|
542
|
+
if (downstreamSignal?.aborted) abortFromDownstream();
|
|
543
|
+
else downstreamSignal?.addEventListener("abort", abortFromDownstream, { once: true });
|
|
544
|
+
if (!controller.signal.aborted) headersTimer = setTimeout(() => {
|
|
545
|
+
controller.abort(new ResponsesHeadersTimeoutError(options.headersTimeoutMs));
|
|
546
|
+
}, options.headersTimeoutMs);
|
|
547
|
+
const clearHeadersTimer = () => {
|
|
548
|
+
if (headersTimer === null) return;
|
|
549
|
+
clearTimeout(headersTimer);
|
|
550
|
+
headersTimer = null;
|
|
551
|
+
};
|
|
552
|
+
const finish = () => {
|
|
553
|
+
if (finished) return;
|
|
554
|
+
finished = true;
|
|
555
|
+
clearHeadersTimer();
|
|
556
|
+
downstreamSignal?.removeEventListener("abort", abortFromDownstream);
|
|
557
|
+
};
|
|
558
|
+
return {
|
|
559
|
+
abort: (reason) => {
|
|
560
|
+
if (!controller.signal.aborted) controller.abort(reason);
|
|
561
|
+
},
|
|
562
|
+
finish,
|
|
563
|
+
finishWithError: (error) => {
|
|
564
|
+
clearHeadersTimer();
|
|
565
|
+
const reason = controller.signal.reason;
|
|
566
|
+
finish();
|
|
567
|
+
return reason instanceof Error ? reason : toError(error);
|
|
568
|
+
},
|
|
569
|
+
headersReceived: clearHeadersTimer,
|
|
570
|
+
signal: controller.signal
|
|
571
|
+
};
|
|
572
|
+
};
|
|
573
|
+
const createManagedResponse = (response, lifecycle, options) => {
|
|
574
|
+
if (!response.body) {
|
|
575
|
+
lifecycle.finish();
|
|
576
|
+
return response;
|
|
577
|
+
}
|
|
578
|
+
const body = createManagedResponseBody(response.body, lifecycle, options);
|
|
579
|
+
return new Response(body, {
|
|
580
|
+
headers: response.headers,
|
|
581
|
+
status: response.status,
|
|
582
|
+
statusText: response.statusText
|
|
583
|
+
});
|
|
584
|
+
};
|
|
585
|
+
const createManagedResponseBody = (body, lifecycle, options) => {
|
|
586
|
+
const reader = body.getReader();
|
|
587
|
+
let finished = false;
|
|
588
|
+
let readerReleased = false;
|
|
589
|
+
const finish = () => {
|
|
590
|
+
if (finished) return;
|
|
591
|
+
finished = true;
|
|
592
|
+
lifecycle.finish();
|
|
593
|
+
};
|
|
594
|
+
const releaseReader = () => {
|
|
595
|
+
if (readerReleased) return;
|
|
596
|
+
readerReleased = true;
|
|
597
|
+
reader.releaseLock();
|
|
598
|
+
};
|
|
599
|
+
return new ReadableStream({
|
|
600
|
+
async pull(controller) {
|
|
601
|
+
try {
|
|
602
|
+
const result = await readWithLifecycle(reader, lifecycle, options);
|
|
603
|
+
if (result.done) {
|
|
604
|
+
finish();
|
|
605
|
+
releaseReader();
|
|
606
|
+
controller.close();
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
controller.enqueue(result.value);
|
|
610
|
+
} catch (error) {
|
|
611
|
+
const reason = lifecycle.finishWithError(error);
|
|
612
|
+
finish();
|
|
613
|
+
await reader.cancel(reason).catch(() => {});
|
|
614
|
+
releaseReader();
|
|
615
|
+
controller.error(reason);
|
|
616
|
+
}
|
|
617
|
+
},
|
|
618
|
+
async cancel(reason) {
|
|
619
|
+
const error = toAbortReason(reason);
|
|
620
|
+
lifecycle.abort(error);
|
|
621
|
+
finish();
|
|
622
|
+
await reader.cancel(error).catch(() => {});
|
|
623
|
+
releaseReader();
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
};
|
|
627
|
+
const createResponsesHttpEventStream = async function* (response, signal) {
|
|
628
|
+
const responseBody = response.body;
|
|
629
|
+
if (!responseBody) return;
|
|
630
|
+
const reader = responseBody.getReader();
|
|
631
|
+
const readerBackedBody = new ReadableStream({
|
|
632
|
+
async pull(controller) {
|
|
633
|
+
const result = await reader.read();
|
|
634
|
+
if (result.done) {
|
|
635
|
+
controller.close();
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
controller.enqueue(result.value);
|
|
639
|
+
},
|
|
640
|
+
async cancel(reason) {
|
|
641
|
+
await reader.cancel(reason);
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
try {
|
|
645
|
+
yield* events(new Response(readerBackedBody), signal);
|
|
646
|
+
} finally {
|
|
647
|
+
try {
|
|
648
|
+
await reader.cancel();
|
|
649
|
+
} catch {} finally {
|
|
650
|
+
reader.releaseLock();
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
const readWithLifecycle = async (reader, lifecycle, options) => await new Promise((resolve, reject) => {
|
|
655
|
+
let settled = false;
|
|
656
|
+
const signal = lifecycle.signal;
|
|
657
|
+
const timer = setTimeout(() => {
|
|
658
|
+
const error = new ResponsesStreamInactivityTimeoutError(options.streamInactivityTimeoutMs);
|
|
659
|
+
lifecycle.abort(error);
|
|
660
|
+
settle(() => reject(error));
|
|
661
|
+
}, options.streamInactivityTimeoutMs);
|
|
662
|
+
const onAbort = () => {
|
|
663
|
+
settle(() => reject(toAbortReason(signal.reason)));
|
|
664
|
+
};
|
|
665
|
+
const cleanup = () => {
|
|
666
|
+
clearTimeout(timer);
|
|
667
|
+
signal.removeEventListener("abort", onAbort);
|
|
668
|
+
};
|
|
669
|
+
const settle = (action) => {
|
|
670
|
+
if (settled) return;
|
|
671
|
+
settled = true;
|
|
672
|
+
cleanup();
|
|
673
|
+
action();
|
|
674
|
+
};
|
|
675
|
+
if (signal.aborted) {
|
|
676
|
+
onAbort();
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
680
|
+
reader.read().then((result) => settle(() => resolve(result)), (error) => settle(() => reject(toError(error))));
|
|
681
|
+
});
|
|
682
|
+
const toAbortReason = (reason) => {
|
|
683
|
+
if (reason instanceof Error) return reason;
|
|
684
|
+
const error = /* @__PURE__ */ new Error("The operation was aborted");
|
|
685
|
+
error.name = "AbortError";
|
|
686
|
+
return error;
|
|
687
|
+
};
|
|
688
|
+
const toError = (value) => {
|
|
689
|
+
if (value instanceof Error) return value;
|
|
690
|
+
return new Error(String(value));
|
|
691
|
+
};
|
|
326
692
|
//#endregion
|
|
327
693
|
//#region src/lib/request-context.ts
|
|
328
694
|
const TRACE_ID_MAX_LENGTH = 64;
|
|
@@ -434,27 +800,33 @@ function buildCodexResponsesWebSocketPayload(payload) {
|
|
|
434
800
|
function buildCodexResponsesWebSocketUrl(baseUrl = CODEX_API_BASE_URL) {
|
|
435
801
|
return createWebSocketUrl(resolveCodexResponsesUrl(baseUrl));
|
|
436
802
|
}
|
|
437
|
-
function prepareCodexResponsesWebSocketRequest(payload, requestHeaders, baseUrl = CODEX_API_BASE_URL) {
|
|
803
|
+
function prepareCodexResponsesWebSocketRequest(payload, requestHeaders, baseUrl = CODEX_API_BASE_URL, signal) {
|
|
438
804
|
const headers = buildCodexResponsesWebSocketHeaders(requestHeaders);
|
|
439
805
|
return {
|
|
440
806
|
headers,
|
|
441
807
|
payload: buildCodexResponsesWebSocketPayload(payload),
|
|
442
808
|
poolKey: buildCodexResponsesWebSocketPoolKey(payload, headers, baseUrl),
|
|
809
|
+
signal,
|
|
443
810
|
url: buildCodexResponsesWebSocketUrl(baseUrl)
|
|
444
811
|
};
|
|
445
812
|
}
|
|
446
813
|
async function forwardCodexResponses(payload, requestHeaders, baseUrl = CODEX_API_BASE_URL, options = {}) {
|
|
447
814
|
consola.log(`<-- model: ${payload.model}`);
|
|
448
815
|
const transport = resolveCodexResponsesTransport(options.transport);
|
|
449
|
-
if (payload.stream && transport === "websocket") return forwardCodexResponsesOverWebSocket(payload, requestHeaders, baseUrl);
|
|
816
|
+
if (payload.stream && transport === "websocket") return forwardCodexResponsesOverWebSocket(payload, requestHeaders, baseUrl, options.signal);
|
|
450
817
|
const normalizedPayload = normalizeCodexResponsesPayload(payload);
|
|
451
|
-
const
|
|
818
|
+
const transportConfig = getResponsesTransportConfig();
|
|
819
|
+
const response = await fetchResponsesWithLifecycle(resolveCodexResponsesUrl(baseUrl), {
|
|
452
820
|
method: "POST",
|
|
453
821
|
headers: buildCodexResponsesHeaders(requestHeaders, { stream: normalizedPayload.stream }),
|
|
454
822
|
body: JSON.stringify(normalizedPayload)
|
|
823
|
+
}, {
|
|
824
|
+
headersTimeoutMs: transportConfig.headersTimeoutMs,
|
|
825
|
+
signal: options.signal,
|
|
826
|
+
streamInactivityTimeoutMs: transportConfig.streamInactivityTimeoutMs
|
|
455
827
|
});
|
|
456
828
|
if (!response.ok) throw new HTTPError("Failed to create codex responses", response);
|
|
457
|
-
if (normalizedPayload.stream) return
|
|
829
|
+
if (normalizedPayload.stream) return createResponsesSafeStream(createResponsesHttpEventStream(response, options.signal), { signal: options.signal });
|
|
458
830
|
return await response.json();
|
|
459
831
|
}
|
|
460
832
|
const normalizeCodexResponsesPayload = (payload) => {
|
|
@@ -520,16 +892,24 @@ const buildCodexResponsesWebSocketPoolKey = (payload, headers, baseUrl) => {
|
|
|
520
892
|
headerFingerprint
|
|
521
893
|
].map(encodePoolKeyPart).join("|");
|
|
522
894
|
};
|
|
523
|
-
const forwardCodexResponsesOverWebSocket = (payload, requestHeaders, baseUrl) => {
|
|
524
|
-
return createCodexResponsesWebSocketStream(prepareCodexResponsesWebSocketRequest(payload, requestHeaders, baseUrl));
|
|
895
|
+
const forwardCodexResponsesOverWebSocket = (payload, requestHeaders, baseUrl, signal) => {
|
|
896
|
+
return createCodexResponsesWebSocketStream(prepareCodexResponsesWebSocketRequest(payload, requestHeaders, baseUrl, signal));
|
|
897
|
+
};
|
|
898
|
+
const createCodexResponsesWebSocketStream = (request) => {
|
|
899
|
+
const transportConfig = getResponsesTransportConfig();
|
|
900
|
+
return createResponsesSafeStream(createPooledWebSocketStream(request, {
|
|
901
|
+
createChunk: createCodexResponsesWebSocketStreamChunk,
|
|
902
|
+
maxBufferedBytes: transportConfig.websocketMaxBufferedBytes,
|
|
903
|
+
maxBufferedMessages: transportConfig.websocketMaxBufferedMessages,
|
|
904
|
+
isTerminalChunk: isTerminalResponsesStreamChunk,
|
|
905
|
+
openErrorMessage: "Failed to create codex responses websocket",
|
|
906
|
+
openTimeoutMs: transportConfig.websocketOpenTimeoutMs,
|
|
907
|
+
poolIdleTimeoutMs: transportConfig.websocketPoolIdleTimeoutMs,
|
|
908
|
+
streamInactivityTimeoutMs: transportConfig.streamInactivityTimeoutMs,
|
|
909
|
+
streamErrorMessage: "Codex responses websocket stream error",
|
|
910
|
+
terminalChunkMissingMessage: "Codex responses websocket ended without a terminal response"
|
|
911
|
+
}), { signal: request.signal });
|
|
525
912
|
};
|
|
526
|
-
const createCodexResponsesWebSocketStream = (request) => createResponsesSafeStream(createPooledWebSocketStream(request, {
|
|
527
|
-
createChunk: createCodexResponsesWebSocketStreamChunk,
|
|
528
|
-
isTerminalChunk: isTerminalResponsesStreamChunk,
|
|
529
|
-
openErrorMessage: "Failed to create codex responses websocket",
|
|
530
|
-
streamErrorMessage: "Codex responses websocket stream error",
|
|
531
|
-
terminalChunkMissingMessage: "Codex responses websocket ended without a terminal response"
|
|
532
|
-
}));
|
|
533
913
|
const createCodexResponsesWebSocketStreamChunk = (data) => {
|
|
534
914
|
if (data === "[DONE]") return { data };
|
|
535
915
|
try {
|
|
@@ -1500,6 +1880,6 @@ async function logUser() {
|
|
|
1500
1880
|
state.tokenBasedBilling = copilotUser.token_based_billing;
|
|
1501
1881
|
}
|
|
1502
1882
|
//#endregion
|
|
1503
|
-
export { buildCodexRequestHeaders as A,
|
|
1883
|
+
export { buildCodexRequestHeaders as A, createPooledWebSocketStream as B, compactAutoContinuePromptStarts as C, compactTextOnlyGuard as D, compactSystemPromptStarts as E, createResponsesHttpEventStream as F, state as H, fetchResponsesWithLifecycle as I, createResponsesSafeStream as L, generateTraceId as M, requestContext as N, loginCodex as O, resolveTraceId as P, encodePoolKeyPart as R, initOpencodeVersion as S, compactSummaryPromptStart as T, HTTPError as U, createWebSocketUrl as V, forwardError as W, copilotModelsHeaders as _, setupGitHubToken as a, prepareInteractionHeaders as b, getUUID as c, isResponsesStream as d, parseUserIdMetadata as f, copilotHeaders as g, copilotBaseUrl as h, setupCopilotToken as i, forwardCodexResponses as j, CODEX_API_BASE_URL as k, isAsyncIterable as l, readGitHubToken as m, persistCodexCredentials as n, generateRequestIdFromPayload as o, getCopilotUsage as p, setupCodexToken as r, getRootSessionId as s, logUser as t, isNullish as u, copilotWebSocketHeaders as v, compactMessageSections as w, prepareMessageProxyHeaders as x, prepareForCompact as y, isTerminalResponsesStreamChunk as z };
|
|
1504
1884
|
|
|
1505
|
-
//# sourceMappingURL=token-
|
|
1885
|
+
//# sourceMappingURL=token-DmNSTe37.js.map
|