@earendil-works/pi-ai 0.75.5 → 0.77.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/dist/models.generated.d.ts +269 -105
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.generated.js +332 -200
- package/dist/models.generated.js.map +1 -1
- package/dist/providers/amazon-bedrock.d.ts +1 -1
- package/dist/providers/amazon-bedrock.d.ts.map +1 -1
- package/dist/providers/amazon-bedrock.js +2 -2
- package/dist/providers/amazon-bedrock.js.map +1 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +16 -9
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/azure-openai-responses.d.ts.map +1 -1
- package/dist/providers/azure-openai-responses.js +1 -1
- package/dist/providers/azure-openai-responses.js.map +1 -1
- package/dist/providers/images/openrouter.d.ts.map +1 -1
- package/dist/providers/images/openrouter.js +1 -1
- package/dist/providers/images/openrouter.js.map +1 -1
- package/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/dist/providers/openai-codex-responses.js +148 -76
- package/dist/providers/openai-codex-responses.js.map +1 -1
- package/dist/providers/openai-completions.d.ts.map +1 -1
- package/dist/providers/openai-completions.js +10 -1
- package/dist/providers/openai-completions.js.map +1 -1
- package/dist/providers/openai-responses-shared.d.ts.map +1 -1
- package/dist/providers/openai-responses-shared.js +4 -1
- package/dist/providers/openai-responses-shared.js.map +1 -1
- package/dist/providers/openai-responses.d.ts.map +1 -1
- package/dist/providers/openai-responses.js +1 -1
- package/dist/providers/openai-responses.js.map +1 -1
- package/dist/providers/simple-options.d.ts.map +1 -1
- package/dist/providers/simple-options.js +1 -0
- package/dist/providers/simple-options.js.map +1 -1
- package/dist/types.d.ts +10 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/abort-signals.d.ts +6 -0
- package/dist/utils/abort-signals.d.ts.map +1 -0
- package/dist/utils/abort-signals.js +34 -0
- package/dist/utils/abort-signals.js.map +1 -0
- package/dist/utils/oauth/device-code.d.ts +9 -7
- package/dist/utils/oauth/device-code.d.ts.map +1 -1
- package/dist/utils/oauth/device-code.js +8 -7
- package/dist/utils/oauth/device-code.js.map +1 -1
- package/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/dist/utils/oauth/github-copilot.js +1 -1
- package/dist/utils/oauth/github-copilot.js.map +1 -1
- package/dist/utils/oauth/index.d.ts +1 -1
- package/dist/utils/oauth/index.d.ts.map +1 -1
- package/dist/utils/oauth/index.js +1 -1
- package/dist/utils/oauth/index.js.map +1 -1
- package/dist/utils/oauth/openai-codex.d.ts +10 -1
- package/dist/utils/oauth/openai-codex.d.ts.map +1 -1
- package/dist/utils/oauth/openai-codex.js +179 -79
- package/dist/utils/oauth/openai-codex.js.map +1 -1
- package/dist/utils/overflow.d.ts +2 -1
- package/dist/utils/overflow.d.ts.map +1 -1
- package/dist/utils/overflow.js +5 -2
- package/dist/utils/overflow.js.map +1 -1
- package/package.json +2 -2
|
@@ -18,6 +18,7 @@ if (typeof process !== "undefined" && (process.versions?.node || process.version
|
|
|
18
18
|
import { getEnvApiKey } from "../env-api-keys.js";
|
|
19
19
|
import { clampThinkingLevel } from "../models.js";
|
|
20
20
|
import { registerSessionResourceCleanup } from "../session-resources.js";
|
|
21
|
+
import { combineAbortSignals } from "../utils/abort-signals.js";
|
|
21
22
|
import { appendAssistantMessageDiagnostic, createAssistantMessageDiagnostic, formatThrownValue, } from "../utils/diagnostics.js";
|
|
22
23
|
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
|
23
24
|
import { headersToRecord } from "../utils/headers.js";
|
|
@@ -29,8 +30,11 @@ import { buildBaseOptions } from "./simple-options.js";
|
|
|
29
30
|
// ============================================================================
|
|
30
31
|
const DEFAULT_CODEX_BASE_URL = "https://chatgpt.com/backend-api";
|
|
31
32
|
const JWT_CLAIM_PATH = "https://api.openai.com/auth";
|
|
32
|
-
const
|
|
33
|
+
const DEFAULT_MAX_RETRIES = 0;
|
|
33
34
|
const BASE_DELAY_MS = 1000;
|
|
35
|
+
const DEFAULT_MAX_RETRY_DELAY_MS = 60_000;
|
|
36
|
+
const DEFAULT_SSE_HEADER_TIMEOUT_MS = 10_000;
|
|
37
|
+
const DEFAULT_WEBSOCKET_CONNECT_TIMEOUT_MS = 15_000;
|
|
34
38
|
const CODEX_TOOL_CALL_PROVIDERS = new Set(["openai", "openai-codex", "opencode"]);
|
|
35
39
|
const WEBSOCKET_MESSAGE_TOO_BIG_CLOSE_CODE = 1009;
|
|
36
40
|
const CODEX_RESPONSE_STATUSES = new Set([
|
|
@@ -44,12 +48,44 @@ const CODEX_RESPONSE_STATUSES = new Set([
|
|
|
44
48
|
// ============================================================================
|
|
45
49
|
// Retry Helpers
|
|
46
50
|
// ============================================================================
|
|
51
|
+
function isTerminalRateLimitError(errorText) {
|
|
52
|
+
return /GoUsageLimitError|FreeUsageLimitError|Monthly usage limit reached|available balance|insufficient_quota|out of budget|quota exceeded|billing/i.test(errorText);
|
|
53
|
+
}
|
|
47
54
|
function isRetryableError(status, errorText) {
|
|
55
|
+
if (status === 429 && isTerminalRateLimitError(errorText)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
48
58
|
if (status === 429 || status === 500 || status === 502 || status === 503 || status === 504) {
|
|
49
59
|
return true;
|
|
50
60
|
}
|
|
51
61
|
return /rate.?limit|overloaded|service.?unavailable|upstream.?connect|connection.?refused/i.test(errorText);
|
|
52
62
|
}
|
|
63
|
+
function getRetryAfterDelayMs(headers) {
|
|
64
|
+
const retryAfterMs = headers.get("retry-after-ms");
|
|
65
|
+
if (retryAfterMs !== null) {
|
|
66
|
+
const millis = Number(retryAfterMs);
|
|
67
|
+
if (Number.isFinite(millis)) {
|
|
68
|
+
return Math.max(0, millis);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const retryAfter = headers.get("retry-after");
|
|
72
|
+
if (!retryAfter) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
const seconds = Number(retryAfter);
|
|
76
|
+
if (Number.isFinite(seconds)) {
|
|
77
|
+
return Math.max(0, seconds * 1000);
|
|
78
|
+
}
|
|
79
|
+
const date = Date.parse(retryAfter);
|
|
80
|
+
if (!Number.isNaN(date)) {
|
|
81
|
+
return Math.max(0, date - Date.now());
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
function capRetryDelayMs(delayMs, options) {
|
|
86
|
+
const maxRetryDelayMs = options?.maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS;
|
|
87
|
+
return maxRetryDelayMs > 0 ? Math.min(delayMs, maxRetryDelayMs) : delayMs;
|
|
88
|
+
}
|
|
53
89
|
function sleep(ms, signal) {
|
|
54
90
|
return new Promise((resolve, reject) => {
|
|
55
91
|
if (signal?.aborted) {
|
|
@@ -63,6 +99,27 @@ function sleep(ms, signal) {
|
|
|
63
99
|
});
|
|
64
100
|
});
|
|
65
101
|
}
|
|
102
|
+
function normalizeTimeoutMs(value) {
|
|
103
|
+
if (value === undefined)
|
|
104
|
+
return undefined;
|
|
105
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
106
|
+
throw new Error(`Invalid timeoutMs: ${String(value)}`);
|
|
107
|
+
}
|
|
108
|
+
return Math.floor(value);
|
|
109
|
+
}
|
|
110
|
+
function createSSEHeaderTimeout() {
|
|
111
|
+
const controller = new AbortController();
|
|
112
|
+
let error;
|
|
113
|
+
const timeout = setTimeout(() => {
|
|
114
|
+
error = new Error(`Codex SSE response headers timed out after ${DEFAULT_SSE_HEADER_TIMEOUT_MS}ms`);
|
|
115
|
+
controller.abort(error);
|
|
116
|
+
}, DEFAULT_SSE_HEADER_TIMEOUT_MS);
|
|
117
|
+
return {
|
|
118
|
+
signal: controller.signal,
|
|
119
|
+
clear: () => clearTimeout(timeout),
|
|
120
|
+
error: () => error,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
66
123
|
// ============================================================================
|
|
67
124
|
// Main Stream Function
|
|
68
125
|
// ============================================================================
|
|
@@ -101,6 +158,8 @@ export const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
101
158
|
const sseHeaders = buildSSEHeaders(model.headers, options?.headers, accountId, apiKey, options?.sessionId);
|
|
102
159
|
const websocketHeaders = buildWebSocketHeaders(model.headers, options?.headers, accountId, apiKey, websocketRequestId);
|
|
103
160
|
const bodyJson = JSON.stringify(body);
|
|
161
|
+
const idleTimeoutMs = normalizeTimeoutMs(options?.timeoutMs);
|
|
162
|
+
const websocketConnectTimeoutMs = normalizeTimeoutMs(options?.websocketConnectTimeoutMs);
|
|
104
163
|
const transport = options?.transport || "auto";
|
|
105
164
|
const websocketDisabledForSession = transport !== "sse" && isWebSocketSseFallbackActive(options?.sessionId);
|
|
106
165
|
if (websocketDisabledForSession) {
|
|
@@ -111,7 +170,7 @@ export const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
111
170
|
try {
|
|
112
171
|
await processWebSocketStream(resolveCodexWebSocketUrl(model.baseUrl), body, websocketHeaders, output, stream, model, () => {
|
|
113
172
|
websocketStarted = true;
|
|
114
|
-
}, options);
|
|
173
|
+
}, idleTimeoutMs, websocketConnectTimeoutMs, options);
|
|
115
174
|
if (options?.signal?.aborted) {
|
|
116
175
|
throw new Error("Request was aborted");
|
|
117
176
|
}
|
|
@@ -145,46 +204,42 @@ export const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
145
204
|
// Fetch with retry logic for rate limits and transient errors
|
|
146
205
|
let response;
|
|
147
206
|
let lastError;
|
|
148
|
-
|
|
207
|
+
const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
208
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
149
209
|
if (options?.signal?.aborted) {
|
|
150
210
|
throw new Error("Request was aborted");
|
|
151
211
|
}
|
|
152
212
|
try {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
213
|
+
const headerTimeout = createSSEHeaderTimeout();
|
|
214
|
+
const combinedSignal = combineAbortSignals([options?.signal, headerTimeout.signal]);
|
|
215
|
+
try {
|
|
216
|
+
response = await fetch(resolveCodexUrl(model.baseUrl), {
|
|
217
|
+
method: "POST",
|
|
218
|
+
headers: sseHeaders,
|
|
219
|
+
body: bodyJson,
|
|
220
|
+
signal: combinedSignal.signal,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
const timeoutError = headerTimeout.error();
|
|
225
|
+
throw timeoutError && !options?.signal?.aborted ? timeoutError : error;
|
|
226
|
+
}
|
|
227
|
+
finally {
|
|
228
|
+
combinedSignal.cleanup();
|
|
229
|
+
headerTimeout.clear();
|
|
230
|
+
}
|
|
159
231
|
await options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);
|
|
160
232
|
if (response.ok) {
|
|
161
233
|
break;
|
|
162
234
|
}
|
|
163
235
|
const errorText = await response.text();
|
|
164
|
-
if (attempt <
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
const retryAfter = response.headers.get("retry-after");
|
|
175
|
-
if (retryAfter) {
|
|
176
|
-
const seconds = Number(retryAfter);
|
|
177
|
-
if (Number.isFinite(seconds)) {
|
|
178
|
-
delayMs = Math.max(0, seconds * 1000);
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
const date = Date.parse(retryAfter);
|
|
182
|
-
if (!Number.isNaN(date)) {
|
|
183
|
-
delayMs = Math.max(0, date - Date.now());
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
236
|
+
if (attempt < maxRetries && isRetryableError(response.status, errorText)) {
|
|
237
|
+
const retryAfterDelayMs = getRetryAfterDelayMs(response.headers);
|
|
238
|
+
const delayMs = retryAfterDelayMs === undefined
|
|
239
|
+
? BASE_DELAY_MS * 2 ** attempt
|
|
240
|
+
: response.status === 429
|
|
241
|
+
? capRetryDelayMs(retryAfterDelayMs, options)
|
|
242
|
+
: retryAfterDelayMs;
|
|
188
243
|
await sleep(delayMs, options?.signal);
|
|
189
244
|
continue;
|
|
190
245
|
}
|
|
@@ -204,7 +259,7 @@ export const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
204
259
|
}
|
|
205
260
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
206
261
|
// Network errors are retryable
|
|
207
|
-
if (attempt <
|
|
262
|
+
if (attempt < maxRetries && !lastError.message.includes("usage limit")) {
|
|
208
263
|
const delayMs = BASE_DELAY_MS * 2 ** attempt;
|
|
209
264
|
await sleep(delayMs, options?.signal);
|
|
210
265
|
continue;
|
|
@@ -602,7 +657,7 @@ function scheduleSessionWebSocketExpiry(sessionId, entry) {
|
|
|
602
657
|
websocketSessionCache.delete(sessionId);
|
|
603
658
|
}, SESSION_WEBSOCKET_CACHE_TTL_MS);
|
|
604
659
|
}
|
|
605
|
-
async function connectWebSocket(url, headers, signal) {
|
|
660
|
+
async function connectWebSocket(url, headers, signal, connectTimeoutMs = DEFAULT_WEBSOCKET_CONNECT_TIMEOUT_MS) {
|
|
606
661
|
const WebSocketCtor = await getWebSocketConstructor();
|
|
607
662
|
if (!WebSocketCtor) {
|
|
608
663
|
throw new Error("WebSocket transport is not available in this runtime");
|
|
@@ -611,6 +666,7 @@ async function connectWebSocket(url, headers, signal) {
|
|
|
611
666
|
delete wsHeaders["OpenAI-Beta"];
|
|
612
667
|
return new Promise((resolve, reject) => {
|
|
613
668
|
let settled = false;
|
|
669
|
+
let timeout;
|
|
614
670
|
let socket;
|
|
615
671
|
try {
|
|
616
672
|
socket = new WebSocketCtor(url, { headers: wsHeaders });
|
|
@@ -619,62 +675,63 @@ async function connectWebSocket(url, headers, signal) {
|
|
|
619
675
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
620
676
|
return;
|
|
621
677
|
}
|
|
622
|
-
const
|
|
623
|
-
if (
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
678
|
+
const cleanup = () => {
|
|
679
|
+
if (timeout) {
|
|
680
|
+
clearTimeout(timeout);
|
|
681
|
+
timeout = undefined;
|
|
682
|
+
}
|
|
683
|
+
socket.removeEventListener("open", onOpen);
|
|
684
|
+
socket.removeEventListener("error", onError);
|
|
685
|
+
socket.removeEventListener("close", onClose);
|
|
686
|
+
signal?.removeEventListener("abort", onAbort);
|
|
628
687
|
};
|
|
629
|
-
const
|
|
630
|
-
const error = extractWebSocketError(event);
|
|
688
|
+
const fail = (error, closeReason) => {
|
|
631
689
|
if (settled)
|
|
632
690
|
return;
|
|
633
691
|
settled = true;
|
|
634
692
|
cleanup();
|
|
693
|
+
if (closeReason) {
|
|
694
|
+
closeWebSocketSilently(socket, 1000, closeReason);
|
|
695
|
+
}
|
|
635
696
|
reject(error);
|
|
636
697
|
};
|
|
637
|
-
const
|
|
638
|
-
const error = extractWebSocketCloseError(event);
|
|
698
|
+
const onOpen = () => {
|
|
639
699
|
if (settled)
|
|
640
700
|
return;
|
|
641
701
|
settled = true;
|
|
642
702
|
cleanup();
|
|
643
|
-
|
|
703
|
+
resolve(socket);
|
|
644
704
|
};
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
return;
|
|
648
|
-
settled = true;
|
|
649
|
-
cleanup();
|
|
650
|
-
socket.close(1000, "aborted");
|
|
651
|
-
reject(new Error("Request was aborted"));
|
|
705
|
+
const onError = (event) => {
|
|
706
|
+
fail(extractWebSocketError(event));
|
|
652
707
|
};
|
|
653
|
-
const
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
708
|
+
const onClose = (event) => {
|
|
709
|
+
fail(extractWebSocketCloseError(event));
|
|
710
|
+
};
|
|
711
|
+
const onAbort = () => {
|
|
712
|
+
fail(new Error("Request was aborted"), "aborted");
|
|
658
713
|
};
|
|
659
714
|
socket.addEventListener("open", onOpen);
|
|
660
715
|
socket.addEventListener("error", onError);
|
|
661
716
|
socket.addEventListener("close", onClose);
|
|
662
717
|
signal?.addEventListener("abort", onAbort);
|
|
718
|
+
if (connectTimeoutMs > 0) {
|
|
719
|
+
timeout = setTimeout(() => {
|
|
720
|
+
fail(new Error(`WebSocket connect timeout after ${connectTimeoutMs}ms`), "connect_timeout");
|
|
721
|
+
}, connectTimeoutMs);
|
|
722
|
+
}
|
|
723
|
+
if (signal?.aborted) {
|
|
724
|
+
onAbort();
|
|
725
|
+
}
|
|
663
726
|
});
|
|
664
727
|
}
|
|
665
|
-
async function acquireWebSocket(url, headers, sessionId, signal) {
|
|
728
|
+
async function acquireWebSocket(url, headers, sessionId, signal, connectTimeoutMs) {
|
|
666
729
|
if (!sessionId) {
|
|
667
|
-
const socket = await connectWebSocket(url, headers, signal);
|
|
730
|
+
const socket = await connectWebSocket(url, headers, signal, connectTimeoutMs);
|
|
668
731
|
return {
|
|
669
732
|
socket,
|
|
670
733
|
reused: false,
|
|
671
|
-
release: (
|
|
672
|
-
if (keep === false) {
|
|
673
|
-
closeWebSocketSilently(socket);
|
|
674
|
-
return;
|
|
675
|
-
}
|
|
676
|
-
closeWebSocketSilently(socket);
|
|
677
|
-
},
|
|
734
|
+
release: () => closeWebSocketSilently(socket),
|
|
678
735
|
};
|
|
679
736
|
}
|
|
680
737
|
const cached = websocketSessionCache.get(sessionId);
|
|
@@ -701,7 +758,7 @@ async function acquireWebSocket(url, headers, sessionId, signal) {
|
|
|
701
758
|
};
|
|
702
759
|
}
|
|
703
760
|
if (cached.busy) {
|
|
704
|
-
const socket = await connectWebSocket(url, headers, signal);
|
|
761
|
+
const socket = await connectWebSocket(url, headers, signal, connectTimeoutMs);
|
|
705
762
|
return {
|
|
706
763
|
socket,
|
|
707
764
|
reused: false,
|
|
@@ -715,7 +772,7 @@ async function acquireWebSocket(url, headers, sessionId, signal) {
|
|
|
715
772
|
websocketSessionCache.delete(sessionId);
|
|
716
773
|
}
|
|
717
774
|
}
|
|
718
|
-
const socket = await connectWebSocket(url, headers, signal);
|
|
775
|
+
const socket = await connectWebSocket(url, headers, signal, connectTimeoutMs);
|
|
719
776
|
const entry = { socket, busy: true };
|
|
720
777
|
websocketSessionCache.set(sessionId, entry);
|
|
721
778
|
return {
|
|
@@ -791,7 +848,7 @@ async function decodeWebSocketData(data) {
|
|
|
791
848
|
}
|
|
792
849
|
return null;
|
|
793
850
|
}
|
|
794
|
-
async function* parseWebSocket(socket, signal) {
|
|
851
|
+
async function* parseWebSocket(socket, signal, idleTimeoutMs) {
|
|
795
852
|
const queue = [];
|
|
796
853
|
let pending = null;
|
|
797
854
|
let done = false;
|
|
@@ -869,8 +926,23 @@ async function* parseWebSocket(socket, signal) {
|
|
|
869
926
|
}
|
|
870
927
|
if (done)
|
|
871
928
|
break;
|
|
872
|
-
|
|
929
|
+
let timeout;
|
|
930
|
+
await new Promise((resolve, reject) => {
|
|
873
931
|
pending = resolve;
|
|
932
|
+
if (idleTimeoutMs !== undefined && idleTimeoutMs > 0) {
|
|
933
|
+
timeout = setTimeout(() => {
|
|
934
|
+
const error = new Error(`WebSocket idle timeout after ${idleTimeoutMs}ms`);
|
|
935
|
+
failed = error;
|
|
936
|
+
done = true;
|
|
937
|
+
pending = null;
|
|
938
|
+
closeWebSocketSilently(socket, 1000, "idle_timeout");
|
|
939
|
+
reject(error);
|
|
940
|
+
}, idleTimeoutMs);
|
|
941
|
+
}
|
|
942
|
+
}).finally(() => {
|
|
943
|
+
if (timeout) {
|
|
944
|
+
clearTimeout(timeout);
|
|
945
|
+
}
|
|
874
946
|
});
|
|
875
947
|
}
|
|
876
948
|
if (failed) {
|
|
@@ -939,8 +1011,8 @@ async function* startWebSocketOutputOnFirstEvent(events, output, stream, onStart
|
|
|
939
1011
|
yield event;
|
|
940
1012
|
}
|
|
941
1013
|
}
|
|
942
|
-
async function processWebSocketStream(url, body, headers, output, stream, model, onStart, options) {
|
|
943
|
-
const { socket, entry, reused, release } = await acquireWebSocket(url, headers, options?.sessionId, options?.signal);
|
|
1014
|
+
async function processWebSocketStream(url, body, headers, output, stream, model, onStart, idleTimeoutMs, websocketConnectTimeoutMs, options) {
|
|
1015
|
+
const { socket, entry, reused, release } = await acquireWebSocket(url, headers, options?.sessionId, options?.signal, websocketConnectTimeoutMs);
|
|
944
1016
|
let keepConnection = true;
|
|
945
1017
|
const useCachedContext = options?.transport === "websocket-cached" || options?.transport === "auto";
|
|
946
1018
|
// ChatGPT Codex Responses rejects `store: true` ("Store must be set to false").
|
|
@@ -972,7 +1044,7 @@ async function processWebSocketStream(url, body, headers, output, stream, model,
|
|
|
972
1044
|
}
|
|
973
1045
|
try {
|
|
974
1046
|
socket.send(JSON.stringify({ type: "response.create", ...requestBody }));
|
|
975
|
-
await processResponsesStream(startWebSocketOutputOnFirstEvent(mapCodexEvents(parseWebSocket(socket, options?.signal)), output, stream, onStart), output, stream, model, {
|
|
1047
|
+
await processResponsesStream(startWebSocketOutputOnFirstEvent(mapCodexEvents(parseWebSocket(socket, options?.signal, idleTimeoutMs)), output, stream, onStart), output, stream, model, {
|
|
976
1048
|
serviceTier: options?.serviceTier,
|
|
977
1049
|
resolveServiceTier: resolveCodexServiceTier,
|
|
978
1050
|
applyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),
|
|
@@ -1070,7 +1142,7 @@ function buildSSEHeaders(initHeaders, additionalHeaders, accountId, token, sessi
|
|
|
1070
1142
|
headers.set("accept", "text/event-stream");
|
|
1071
1143
|
headers.set("content-type", "application/json");
|
|
1072
1144
|
if (sessionId) {
|
|
1073
|
-
headers.set("
|
|
1145
|
+
headers.set("session-id", sessionId);
|
|
1074
1146
|
headers.set("x-client-request-id", sessionId);
|
|
1075
1147
|
}
|
|
1076
1148
|
return headers;
|
|
@@ -1083,7 +1155,7 @@ function buildWebSocketHeaders(initHeaders, additionalHeaders, accountId, token,
|
|
|
1083
1155
|
headers.delete("openai-beta");
|
|
1084
1156
|
headers.set("OpenAI-Beta", OPENAI_BETA_RESPONSES_WEBSOCKETS);
|
|
1085
1157
|
headers.set("x-client-request-id", requestId);
|
|
1086
|
-
headers.set("
|
|
1158
|
+
headers.set("session-id", requestId);
|
|
1087
1159
|
return headers;
|
|
1088
1160
|
}
|
|
1089
1161
|
//# sourceMappingURL=openai-codex-responses.js.map
|