@ljoukov/llm 3.0.0 → 3.0.2
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 +20 -5
- package/dist/index.cjs +748 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +747 -26
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
package/dist/index.cjs
CHANGED
|
@@ -34,6 +34,7 @@ __export(index_exports, {
|
|
|
34
34
|
CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION: () => CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION,
|
|
35
35
|
CODEX_APPLY_PATCH_LARK_GRAMMAR: () => CODEX_APPLY_PATCH_LARK_GRAMMAR,
|
|
36
36
|
FIREWORKS_DEFAULT_GLM_MODEL: () => FIREWORKS_DEFAULT_GLM_MODEL,
|
|
37
|
+
FIREWORKS_DEFAULT_GPT_OSS_120B_MODEL: () => FIREWORKS_DEFAULT_GPT_OSS_120B_MODEL,
|
|
37
38
|
FIREWORKS_DEFAULT_KIMI_MODEL: () => FIREWORKS_DEFAULT_KIMI_MODEL,
|
|
38
39
|
FIREWORKS_DEFAULT_MINIMAX_MODEL: () => FIREWORKS_DEFAULT_MINIMAX_MODEL,
|
|
39
40
|
FIREWORKS_MODEL_IDS: () => FIREWORKS_MODEL_IDS,
|
|
@@ -227,7 +228,7 @@ function getGeminiProPricing(modelId) {
|
|
|
227
228
|
if (modelId.includes("gemini-2.5-pro")) {
|
|
228
229
|
return GEMINI_2_5_PRO_PRICING;
|
|
229
230
|
}
|
|
230
|
-
if (modelId.includes("gemini-3-pro")) {
|
|
231
|
+
if (modelId.includes("gemini-3-pro") || modelId.includes("gemini-3.1-pro")) {
|
|
231
232
|
return GEMINI_3_PRO_PREVIEW_PRICING;
|
|
232
233
|
}
|
|
233
234
|
return void 0;
|
|
@@ -427,8 +428,6 @@ function parseEnvLine(line) {
|
|
|
427
428
|
// src/openai/chatgpt-auth.ts
|
|
428
429
|
var CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_URL";
|
|
429
430
|
var CHATGPT_AUTH_TOKEN_PROVIDER_STORE_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_STORE";
|
|
430
|
-
var CHATGPT_AUTH_SERVER_URL_ENV = "CHATGPT_AUTH_SERVER_URL";
|
|
431
|
-
var CHATGPT_AUTH_SERVER_STORE_ENV = "CHATGPT_AUTH_SERVER_STORE";
|
|
432
431
|
var CHATGPT_AUTH_API_KEY_ENV = "CHATGPT_AUTH_API_KEY";
|
|
433
432
|
var CHATGPT_AUTH_TOKEN_PROVIDER_API_KEY_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_API_KEY";
|
|
434
433
|
var CHATGPT_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
@@ -560,7 +559,7 @@ async function refreshChatGptOauthToken(refreshToken, fallback) {
|
|
|
560
559
|
}
|
|
561
560
|
async function getChatGptAuthProfile() {
|
|
562
561
|
loadLocalEnv();
|
|
563
|
-
const tokenProviderUrl = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV]
|
|
562
|
+
const tokenProviderUrl = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV];
|
|
564
563
|
const tokenProviderKey = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_API_KEY_ENV] ?? process.env[CHATGPT_AUTH_API_KEY_ENV];
|
|
565
564
|
if (tokenProviderUrl && tokenProviderUrl.trim().length > 0 && tokenProviderKey && tokenProviderKey.trim().length > 0) {
|
|
566
565
|
if (cachedProfile && !isExpired(cachedProfile)) {
|
|
@@ -571,7 +570,7 @@ async function getChatGptAuthProfile() {
|
|
|
571
570
|
}
|
|
572
571
|
refreshPromise = (async () => {
|
|
573
572
|
try {
|
|
574
|
-
const store = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_STORE_ENV]
|
|
573
|
+
const store = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_STORE_ENV];
|
|
575
574
|
const profile = await fetchChatGptAuthProfileFromTokenProvider({
|
|
576
575
|
baseUrl: tokenProviderUrl,
|
|
577
576
|
apiKey: tokenProviderKey,
|
|
@@ -774,22 +773,588 @@ function extractChatGptAccountId(token) {
|
|
|
774
773
|
return typeof namespaced === "string" && namespaced.length > 0 ? namespaced : void 0;
|
|
775
774
|
}
|
|
776
775
|
|
|
776
|
+
// src/openai/responses-websocket.ts
|
|
777
|
+
var import_ws = __toESM(require("ws"), 1);
|
|
778
|
+
var OPENAI_BETA_RESPONSES_WEBSOCKETS_V2 = "responses_websockets=2026-02-06";
|
|
779
|
+
var ResponsesWebSocketHttpError = class extends Error {
|
|
780
|
+
status;
|
|
781
|
+
body;
|
|
782
|
+
headers;
|
|
783
|
+
constructor(options) {
|
|
784
|
+
super(options.message);
|
|
785
|
+
this.name = "ResponsesWebSocketHttpError";
|
|
786
|
+
this.status = options.status;
|
|
787
|
+
this.body = options.body;
|
|
788
|
+
this.headers = options.headers;
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
function resolveResponsesWebSocketMode(raw, fallback = "auto") {
|
|
792
|
+
const value = raw?.trim().toLowerCase();
|
|
793
|
+
if (value === "auto" || value === "off" || value === "only") {
|
|
794
|
+
return value;
|
|
795
|
+
}
|
|
796
|
+
return fallback;
|
|
797
|
+
}
|
|
798
|
+
function mergeOpenAiBetaHeader(existing, required) {
|
|
799
|
+
const parts = /* @__PURE__ */ new Set();
|
|
800
|
+
for (const part of (existing ?? "").split(",")) {
|
|
801
|
+
const trimmed = part.trim();
|
|
802
|
+
if (trimmed.length > 0) {
|
|
803
|
+
parts.add(trimmed);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
const normalizedRequired = required.trim();
|
|
807
|
+
if (normalizedRequired.length > 0) {
|
|
808
|
+
parts.add(normalizedRequired);
|
|
809
|
+
}
|
|
810
|
+
return Array.from(parts).join(", ");
|
|
811
|
+
}
|
|
812
|
+
function toWebSocketUrl(httpOrHttpsUrl) {
|
|
813
|
+
const parsed = new URL(httpOrHttpsUrl);
|
|
814
|
+
if (parsed.protocol === "https:") {
|
|
815
|
+
parsed.protocol = "wss:";
|
|
816
|
+
} else if (parsed.protocol === "http:") {
|
|
817
|
+
parsed.protocol = "ws:";
|
|
818
|
+
} else if (parsed.protocol !== "ws:" && parsed.protocol !== "wss:") {
|
|
819
|
+
throw new Error(`Unsupported websocket URL protocol: ${parsed.protocol}`);
|
|
820
|
+
}
|
|
821
|
+
return parsed.toString();
|
|
822
|
+
}
|
|
823
|
+
function isResponsesWebSocketUnsupportedError(error) {
|
|
824
|
+
if (error instanceof ResponsesWebSocketHttpError) {
|
|
825
|
+
return [400, 404, 405, 406, 426, 501].includes(error.status);
|
|
826
|
+
}
|
|
827
|
+
const message = error instanceof Error ? error.message.toLowerCase() : "";
|
|
828
|
+
return message.includes("unexpected server response: 426");
|
|
829
|
+
}
|
|
830
|
+
function createAdaptiveResponsesStream(options) {
|
|
831
|
+
let resolved = null;
|
|
832
|
+
let websocketSelected = false;
|
|
833
|
+
let fallbackSelected = false;
|
|
834
|
+
const activateFallback = (error) => {
|
|
835
|
+
options.onWebSocketFallback?.(error);
|
|
836
|
+
fallbackSelected = true;
|
|
837
|
+
websocketSelected = false;
|
|
838
|
+
const fallback = options.createFallbackStream();
|
|
839
|
+
resolved = Promise.resolve(fallback);
|
|
840
|
+
return fallback;
|
|
841
|
+
};
|
|
842
|
+
const getStream = async () => {
|
|
843
|
+
if (resolved) {
|
|
844
|
+
return await resolved;
|
|
845
|
+
}
|
|
846
|
+
resolved = (async () => {
|
|
847
|
+
if (options.mode === "off") {
|
|
848
|
+
fallbackSelected = true;
|
|
849
|
+
return options.createFallbackStream();
|
|
850
|
+
}
|
|
851
|
+
try {
|
|
852
|
+
const stream = await options.createWebSocketStream();
|
|
853
|
+
websocketSelected = true;
|
|
854
|
+
return stream;
|
|
855
|
+
} catch (error) {
|
|
856
|
+
if (options.mode === "only") {
|
|
857
|
+
throw error;
|
|
858
|
+
}
|
|
859
|
+
return activateFallback(error);
|
|
860
|
+
}
|
|
861
|
+
})();
|
|
862
|
+
return await resolved;
|
|
863
|
+
};
|
|
864
|
+
return {
|
|
865
|
+
async *[Symbol.asyncIterator]() {
|
|
866
|
+
const stream = await getStream();
|
|
867
|
+
let yielded = 0;
|
|
868
|
+
try {
|
|
869
|
+
for await (const event of stream) {
|
|
870
|
+
yielded += 1;
|
|
871
|
+
yield event;
|
|
872
|
+
}
|
|
873
|
+
} catch (error) {
|
|
874
|
+
if (options.mode !== "only" && websocketSelected && !fallbackSelected && yielded === 0) {
|
|
875
|
+
const fallback = activateFallback(error);
|
|
876
|
+
for await (const event of fallback) {
|
|
877
|
+
yield event;
|
|
878
|
+
}
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
throw error;
|
|
882
|
+
}
|
|
883
|
+
},
|
|
884
|
+
async finalResponse() {
|
|
885
|
+
const stream = await getStream();
|
|
886
|
+
try {
|
|
887
|
+
return await stream.finalResponse();
|
|
888
|
+
} catch (error) {
|
|
889
|
+
if (options.mode === "only" || !websocketSelected || fallbackSelected) {
|
|
890
|
+
throw error;
|
|
891
|
+
}
|
|
892
|
+
const fallback = activateFallback(error);
|
|
893
|
+
return await fallback.finalResponse();
|
|
894
|
+
}
|
|
895
|
+
},
|
|
896
|
+
close() {
|
|
897
|
+
void getStream().then((stream) => stream.close()).catch(() => {
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
async function createResponsesWebSocketStream(options) {
|
|
903
|
+
const completionTypes = new Set(
|
|
904
|
+
options.completionEventTypes ?? ["response.completed", "response.failed", "response.done"]
|
|
905
|
+
);
|
|
906
|
+
const { socket, responseHeaders } = await connectWebSocket({
|
|
907
|
+
url: options.url,
|
|
908
|
+
headers: options.headers,
|
|
909
|
+
signal: options.signal
|
|
910
|
+
});
|
|
911
|
+
const queue = createAsyncQueue();
|
|
912
|
+
let settled = false;
|
|
913
|
+
let finalResponse = null;
|
|
914
|
+
let latestResponse = null;
|
|
915
|
+
let idleTimer = null;
|
|
916
|
+
let resolveFinal = null;
|
|
917
|
+
let rejectFinal = null;
|
|
918
|
+
const finalPromise = new Promise((resolve, reject) => {
|
|
919
|
+
resolveFinal = resolve;
|
|
920
|
+
rejectFinal = reject;
|
|
921
|
+
});
|
|
922
|
+
void finalPromise.catch(() => {
|
|
923
|
+
});
|
|
924
|
+
const clearIdleTimer = () => {
|
|
925
|
+
if (idleTimer) {
|
|
926
|
+
clearTimeout(idleTimer);
|
|
927
|
+
idleTimer = null;
|
|
928
|
+
}
|
|
929
|
+
};
|
|
930
|
+
const closeSocket = () => {
|
|
931
|
+
try {
|
|
932
|
+
if (socket.readyState === import_ws.default.OPEN || socket.readyState === import_ws.default.CONNECTING) {
|
|
933
|
+
socket.close();
|
|
934
|
+
}
|
|
935
|
+
} catch {
|
|
936
|
+
}
|
|
937
|
+
};
|
|
938
|
+
const complete = (response) => {
|
|
939
|
+
if (settled) {
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
settled = true;
|
|
943
|
+
clearIdleTimer();
|
|
944
|
+
finalResponse = response;
|
|
945
|
+
resolveFinal?.(response);
|
|
946
|
+
queue.close();
|
|
947
|
+
closeSocket();
|
|
948
|
+
};
|
|
949
|
+
const fail = (error) => {
|
|
950
|
+
if (settled) {
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
settled = true;
|
|
954
|
+
clearIdleTimer();
|
|
955
|
+
rejectFinal?.(error);
|
|
956
|
+
queue.fail(error);
|
|
957
|
+
closeSocket();
|
|
958
|
+
};
|
|
959
|
+
const restartIdleTimer = () => {
|
|
960
|
+
clearIdleTimer();
|
|
961
|
+
const idleTimeoutMs = options.idleTimeoutMs;
|
|
962
|
+
if (!idleTimeoutMs || idleTimeoutMs <= 0 || settled) {
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
idleTimer = setTimeout(() => {
|
|
966
|
+
fail(new Error(`Responses WebSocket idle timeout after ${idleTimeoutMs}ms.`));
|
|
967
|
+
}, idleTimeoutMs);
|
|
968
|
+
};
|
|
969
|
+
const onAbort = () => {
|
|
970
|
+
const error = createAbortError(options.signal?.reason);
|
|
971
|
+
fail(error);
|
|
972
|
+
};
|
|
973
|
+
if (options.signal) {
|
|
974
|
+
if (options.signal.aborted) {
|
|
975
|
+
socket.close();
|
|
976
|
+
throw createAbortError(options.signal.reason);
|
|
977
|
+
}
|
|
978
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
979
|
+
}
|
|
980
|
+
const cleanup = () => {
|
|
981
|
+
clearIdleTimer();
|
|
982
|
+
socket.removeAllListeners();
|
|
983
|
+
if (options.signal) {
|
|
984
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
985
|
+
}
|
|
986
|
+
};
|
|
987
|
+
socket.on("message", (raw) => {
|
|
988
|
+
restartIdleTimer();
|
|
989
|
+
const parsed = parseWebSocketPayload(raw);
|
|
990
|
+
if (!parsed) {
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
const error = mapWebSocketErrorEvent(parsed);
|
|
994
|
+
if (error) {
|
|
995
|
+
fail(error);
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
const event = parsed;
|
|
999
|
+
if (isObjectWithResponse(event)) {
|
|
1000
|
+
latestResponse = event.response;
|
|
1001
|
+
}
|
|
1002
|
+
queue.push(event);
|
|
1003
|
+
const type = typeof event.type === "string" ? event.type : "";
|
|
1004
|
+
if (completionTypes.has(type)) {
|
|
1005
|
+
const completedResponse = normalizeFinalResponse(
|
|
1006
|
+
type,
|
|
1007
|
+
event.response,
|
|
1008
|
+
latestResponse,
|
|
1009
|
+
responseHeaders
|
|
1010
|
+
);
|
|
1011
|
+
complete(completedResponse);
|
|
1012
|
+
}
|
|
1013
|
+
});
|
|
1014
|
+
socket.on("error", (error) => {
|
|
1015
|
+
fail(new Error(`Responses WebSocket error: ${error.message}`));
|
|
1016
|
+
});
|
|
1017
|
+
socket.on("close", (_code, _reason) => {
|
|
1018
|
+
if (settled) {
|
|
1019
|
+
cleanup();
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
fail(new Error("Responses WebSocket closed before completion."));
|
|
1023
|
+
cleanup();
|
|
1024
|
+
});
|
|
1025
|
+
restartIdleTimer();
|
|
1026
|
+
const payload = serializeRequestPayload(options.request);
|
|
1027
|
+
await new Promise((resolve, reject) => {
|
|
1028
|
+
socket.send(payload, (error) => {
|
|
1029
|
+
if (error) {
|
|
1030
|
+
reject(error);
|
|
1031
|
+
} else {
|
|
1032
|
+
resolve();
|
|
1033
|
+
}
|
|
1034
|
+
});
|
|
1035
|
+
}).catch((error) => {
|
|
1036
|
+
fail(new Error(`Failed to send Responses WebSocket request: ${errorToMessage(error)}`));
|
|
1037
|
+
throw error instanceof Error ? error : new Error(errorToMessage(error));
|
|
1038
|
+
});
|
|
1039
|
+
return {
|
|
1040
|
+
async *[Symbol.asyncIterator]() {
|
|
1041
|
+
try {
|
|
1042
|
+
for await (const event of queue.iterable) {
|
|
1043
|
+
yield event;
|
|
1044
|
+
}
|
|
1045
|
+
} finally {
|
|
1046
|
+
if (!settled) {
|
|
1047
|
+
closeSocket();
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
},
|
|
1051
|
+
async finalResponse() {
|
|
1052
|
+
return await finalPromise;
|
|
1053
|
+
},
|
|
1054
|
+
close() {
|
|
1055
|
+
if (settled) {
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
const response = finalResponse ?? latestResponse ?? { status: "cancelled" };
|
|
1059
|
+
complete(response);
|
|
1060
|
+
cleanup();
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
async function connectWebSocket(options) {
|
|
1065
|
+
return await new Promise((resolve, reject) => {
|
|
1066
|
+
const socket = new import_ws.default(options.url, {
|
|
1067
|
+
headers: options.headers,
|
|
1068
|
+
handshakeTimeout: 3e4
|
|
1069
|
+
});
|
|
1070
|
+
let settled = false;
|
|
1071
|
+
let responseBody = "";
|
|
1072
|
+
const rejectOnce = (error) => {
|
|
1073
|
+
if (settled) {
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
settled = true;
|
|
1077
|
+
cleanup();
|
|
1078
|
+
try {
|
|
1079
|
+
socket.terminate();
|
|
1080
|
+
} catch {
|
|
1081
|
+
}
|
|
1082
|
+
reject(error);
|
|
1083
|
+
};
|
|
1084
|
+
const resolveOnce = (result) => {
|
|
1085
|
+
if (settled) {
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
settled = true;
|
|
1089
|
+
cleanup(false);
|
|
1090
|
+
resolve(result);
|
|
1091
|
+
};
|
|
1092
|
+
const onAbort = () => {
|
|
1093
|
+
rejectOnce(createAbortError(options.signal?.reason));
|
|
1094
|
+
};
|
|
1095
|
+
const cleanup = (removeAbortListener = true) => {
|
|
1096
|
+
socket.removeListener("open", onOpen);
|
|
1097
|
+
socket.removeListener("error", onError);
|
|
1098
|
+
socket.removeListener("unexpected-response", onUnexpectedResponse);
|
|
1099
|
+
if (removeAbortListener && options.signal) {
|
|
1100
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
1101
|
+
}
|
|
1102
|
+
};
|
|
1103
|
+
const onOpen = () => {
|
|
1104
|
+
const headers = normalizeUpgradeHeaders(socket);
|
|
1105
|
+
resolveOnce({ socket, responseHeaders: headers });
|
|
1106
|
+
};
|
|
1107
|
+
const onError = (error) => {
|
|
1108
|
+
rejectOnce(new Error(`Responses WebSocket connection failed: ${error.message}`));
|
|
1109
|
+
};
|
|
1110
|
+
const onUnexpectedResponse = (_request, response) => {
|
|
1111
|
+
if (typeof response.setEncoding === "function") {
|
|
1112
|
+
response.setEncoding("utf8");
|
|
1113
|
+
}
|
|
1114
|
+
response.on("data", (chunk) => {
|
|
1115
|
+
responseBody += typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
1116
|
+
});
|
|
1117
|
+
response.on("end", () => {
|
|
1118
|
+
const status = Number(response.statusCode ?? 0);
|
|
1119
|
+
const headers = {};
|
|
1120
|
+
const rawHeaders = response.headers ?? {};
|
|
1121
|
+
for (const [key, value] of Object.entries(rawHeaders)) {
|
|
1122
|
+
if (typeof value === "string") {
|
|
1123
|
+
headers[key] = value;
|
|
1124
|
+
} else if (Array.isArray(value)) {
|
|
1125
|
+
headers[key] = value.join(", ");
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
rejectOnce(
|
|
1129
|
+
new ResponsesWebSocketHttpError({
|
|
1130
|
+
status: Number.isFinite(status) && status > 0 ? status : 500,
|
|
1131
|
+
message: `Responses WebSocket upgrade failed${status ? ` (${status})` : ""}.`,
|
|
1132
|
+
body: responseBody || void 0,
|
|
1133
|
+
headers
|
|
1134
|
+
})
|
|
1135
|
+
);
|
|
1136
|
+
});
|
|
1137
|
+
response.on("error", (error) => {
|
|
1138
|
+
rejectOnce(
|
|
1139
|
+
new ResponsesWebSocketHttpError({
|
|
1140
|
+
status: Number(response.statusCode ?? 500),
|
|
1141
|
+
message: `Responses WebSocket upgrade failed: ${error.message}`,
|
|
1142
|
+
body: responseBody || void 0
|
|
1143
|
+
})
|
|
1144
|
+
);
|
|
1145
|
+
});
|
|
1146
|
+
};
|
|
1147
|
+
socket.once("open", onOpen);
|
|
1148
|
+
socket.once("error", onError);
|
|
1149
|
+
socket.once("unexpected-response", onUnexpectedResponse);
|
|
1150
|
+
if (options.signal) {
|
|
1151
|
+
if (options.signal.aborted) {
|
|
1152
|
+
onAbort();
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
1156
|
+
}
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
function normalizeUpgradeHeaders(socket) {
|
|
1160
|
+
const maybeUpgradeResponse = socket._req?.res;
|
|
1161
|
+
const raw = maybeUpgradeResponse?.headers ?? {};
|
|
1162
|
+
const normalized = {};
|
|
1163
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
1164
|
+
if (typeof value === "string") {
|
|
1165
|
+
normalized[key.toLowerCase()] = value;
|
|
1166
|
+
} else if (Array.isArray(value)) {
|
|
1167
|
+
normalized[key.toLowerCase()] = value.join(", ");
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
return normalized;
|
|
1171
|
+
}
|
|
1172
|
+
function parseWebSocketPayload(raw) {
|
|
1173
|
+
const text = toUtf8(raw);
|
|
1174
|
+
if (!text) {
|
|
1175
|
+
return null;
|
|
1176
|
+
}
|
|
1177
|
+
try {
|
|
1178
|
+
const parsed = JSON.parse(text);
|
|
1179
|
+
if (parsed && typeof parsed === "object") {
|
|
1180
|
+
return parsed;
|
|
1181
|
+
}
|
|
1182
|
+
} catch {
|
|
1183
|
+
return null;
|
|
1184
|
+
}
|
|
1185
|
+
return null;
|
|
1186
|
+
}
|
|
1187
|
+
function toUtf8(raw) {
|
|
1188
|
+
if (typeof raw === "string") {
|
|
1189
|
+
return raw;
|
|
1190
|
+
}
|
|
1191
|
+
if (raw instanceof ArrayBuffer) {
|
|
1192
|
+
return Buffer.from(raw).toString("utf8");
|
|
1193
|
+
}
|
|
1194
|
+
if (Array.isArray(raw)) {
|
|
1195
|
+
const chunks = raw.map((chunk) => {
|
|
1196
|
+
if (typeof chunk === "string") {
|
|
1197
|
+
return Buffer.from(chunk, "utf8");
|
|
1198
|
+
}
|
|
1199
|
+
return Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
1200
|
+
});
|
|
1201
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
1202
|
+
}
|
|
1203
|
+
return Buffer.isBuffer(raw) ? raw.toString("utf8") : Buffer.from(raw).toString("utf8");
|
|
1204
|
+
}
|
|
1205
|
+
function mapWebSocketErrorEvent(payload) {
|
|
1206
|
+
if (payload.type !== "error") {
|
|
1207
|
+
return null;
|
|
1208
|
+
}
|
|
1209
|
+
const status = resolveNumericStatus(payload.status) ?? resolveNumericStatus(payload.status_code);
|
|
1210
|
+
if (!status || status < 400) {
|
|
1211
|
+
const message = errorToMessage(payload.error) || "Responses WebSocket returned an error event.";
|
|
1212
|
+
return new Error(message);
|
|
1213
|
+
}
|
|
1214
|
+
const headers = mapErrorHeaders(payload.headers);
|
|
1215
|
+
const body = payload.error && typeof payload.error === "object" ? JSON.stringify({ error: payload.error }, null, 2) : void 0;
|
|
1216
|
+
return new ResponsesWebSocketHttpError({
|
|
1217
|
+
status,
|
|
1218
|
+
message: `Responses WebSocket returned status ${status}.`,
|
|
1219
|
+
body,
|
|
1220
|
+
headers
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
function mapErrorHeaders(value) {
|
|
1224
|
+
if (!value || typeof value !== "object") {
|
|
1225
|
+
return void 0;
|
|
1226
|
+
}
|
|
1227
|
+
const headers = {};
|
|
1228
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
1229
|
+
if (typeof entry === "string" || typeof entry === "number" || typeof entry === "boolean") {
|
|
1230
|
+
headers[key.toLowerCase()] = String(entry);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
return Object.keys(headers).length > 0 ? headers : void 0;
|
|
1234
|
+
}
|
|
1235
|
+
function resolveNumericStatus(value) {
|
|
1236
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1237
|
+
return Math.floor(value);
|
|
1238
|
+
}
|
|
1239
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
1240
|
+
const parsed = Number(value);
|
|
1241
|
+
if (Number.isFinite(parsed)) {
|
|
1242
|
+
return Math.floor(parsed);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
return null;
|
|
1246
|
+
}
|
|
1247
|
+
function normalizeFinalResponse(eventType, eventResponse, latestResponse, responseHeaders) {
|
|
1248
|
+
const response = eventResponse && typeof eventResponse === "object" ? { ...eventResponse } : latestResponse ? { ...latestResponse } : {};
|
|
1249
|
+
if (typeof response.status !== "string") {
|
|
1250
|
+
if (eventType === "response.failed") {
|
|
1251
|
+
response.status = "failed";
|
|
1252
|
+
} else if (eventType === "response.done") {
|
|
1253
|
+
response.status = "completed";
|
|
1254
|
+
} else if (eventType === "response.completed") {
|
|
1255
|
+
response.status = "completed";
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
const upgradeModel = responseHeaders["openai-model"];
|
|
1259
|
+
if (typeof response.model !== "string" && upgradeModel) {
|
|
1260
|
+
response.model = upgradeModel;
|
|
1261
|
+
}
|
|
1262
|
+
return response;
|
|
1263
|
+
}
|
|
1264
|
+
function serializeRequestPayload(request) {
|
|
1265
|
+
if (!request || typeof request !== "object" || Array.isArray(request)) {
|
|
1266
|
+
throw new Error("Responses WebSocket request must be a JSON object.");
|
|
1267
|
+
}
|
|
1268
|
+
const body = request;
|
|
1269
|
+
const payload = typeof body.type === "string" ? body : { type: "response.create", ...body };
|
|
1270
|
+
return JSON.stringify(payload);
|
|
1271
|
+
}
|
|
1272
|
+
function isObjectWithResponse(event) {
|
|
1273
|
+
return Boolean(event.response && typeof event.response === "object");
|
|
1274
|
+
}
|
|
1275
|
+
function errorToMessage(error) {
|
|
1276
|
+
if (error instanceof Error) {
|
|
1277
|
+
return error.message;
|
|
1278
|
+
}
|
|
1279
|
+
if (typeof error === "string") {
|
|
1280
|
+
return error;
|
|
1281
|
+
}
|
|
1282
|
+
try {
|
|
1283
|
+
return JSON.stringify(error);
|
|
1284
|
+
} catch {
|
|
1285
|
+
return String(error);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
function createAbortError(reason) {
|
|
1289
|
+
const error = new Error(
|
|
1290
|
+
reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "Request aborted."
|
|
1291
|
+
);
|
|
1292
|
+
error.name = "AbortError";
|
|
1293
|
+
return error;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
777
1296
|
// src/openai/chatgpt-codex.ts
|
|
778
1297
|
var CHATGPT_CODEX_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
|
|
1298
|
+
var CHATGPT_RESPONSES_EXPERIMENTAL_HEADER = "responses=experimental";
|
|
1299
|
+
var cachedResponsesWebSocketMode = null;
|
|
1300
|
+
var chatGptResponsesWebSocketDisabled = false;
|
|
779
1301
|
async function streamChatGptCodexResponse(options) {
|
|
780
1302
|
const { access, accountId } = await getChatGptAuthProfile();
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1303
|
+
const mode = resolveChatGptResponsesWebSocketMode();
|
|
1304
|
+
const fallbackStreamFactory = () => {
|
|
1305
|
+
const streamPromise = streamChatGptCodexResponseSse({
|
|
1306
|
+
request: options.request,
|
|
1307
|
+
access,
|
|
1308
|
+
accountId,
|
|
1309
|
+
sessionId: options.sessionId,
|
|
1310
|
+
signal: options.signal
|
|
1311
|
+
});
|
|
1312
|
+
return {
|
|
1313
|
+
async *[Symbol.asyncIterator]() {
|
|
1314
|
+
const stream = await streamPromise;
|
|
1315
|
+
for await (const event of stream) {
|
|
1316
|
+
yield event;
|
|
1317
|
+
}
|
|
1318
|
+
},
|
|
1319
|
+
async finalResponse() {
|
|
1320
|
+
return {};
|
|
1321
|
+
},
|
|
1322
|
+
close() {
|
|
1323
|
+
}
|
|
1324
|
+
};
|
|
789
1325
|
};
|
|
790
|
-
if (
|
|
791
|
-
|
|
1326
|
+
if (mode === "off" || chatGptResponsesWebSocketDisabled) {
|
|
1327
|
+
return fallbackStreamFactory();
|
|
792
1328
|
}
|
|
1329
|
+
const websocketHeaders = buildChatGptCodexHeaders({
|
|
1330
|
+
access,
|
|
1331
|
+
accountId,
|
|
1332
|
+
sessionId: options.sessionId,
|
|
1333
|
+
useWebSocket: true
|
|
1334
|
+
});
|
|
1335
|
+
return createAdaptiveResponsesStream({
|
|
1336
|
+
mode,
|
|
1337
|
+
createWebSocketStream: async () => await createResponsesWebSocketStream({
|
|
1338
|
+
url: toWebSocketUrl(CHATGPT_CODEX_ENDPOINT),
|
|
1339
|
+
headers: websocketHeaders,
|
|
1340
|
+
request: options.request,
|
|
1341
|
+
signal: options.signal
|
|
1342
|
+
}),
|
|
1343
|
+
createFallbackStream: fallbackStreamFactory,
|
|
1344
|
+
onWebSocketFallback: () => {
|
|
1345
|
+
chatGptResponsesWebSocketDisabled = true;
|
|
1346
|
+
}
|
|
1347
|
+
});
|
|
1348
|
+
}
|
|
1349
|
+
async function streamChatGptCodexResponseSse(options) {
|
|
1350
|
+
const headers = buildChatGptCodexHeaders({
|
|
1351
|
+
access: options.access,
|
|
1352
|
+
accountId: options.accountId,
|
|
1353
|
+
sessionId: options.sessionId,
|
|
1354
|
+
useWebSocket: false
|
|
1355
|
+
});
|
|
1356
|
+
headers.Accept = "text/event-stream";
|
|
1357
|
+
headers["Content-Type"] = "application/json";
|
|
793
1358
|
const response = await fetch(CHATGPT_CODEX_ENDPOINT, {
|
|
794
1359
|
method: "POST",
|
|
795
1360
|
headers,
|
|
@@ -806,20 +1371,67 @@ async function streamChatGptCodexResponse(options) {
|
|
|
806
1371
|
}
|
|
807
1372
|
return parseEventStream(body);
|
|
808
1373
|
}
|
|
1374
|
+
function resolveChatGptResponsesWebSocketMode() {
|
|
1375
|
+
if (cachedResponsesWebSocketMode) {
|
|
1376
|
+
return cachedResponsesWebSocketMode;
|
|
1377
|
+
}
|
|
1378
|
+
cachedResponsesWebSocketMode = resolveResponsesWebSocketMode(
|
|
1379
|
+
process.env.CHATGPT_RESPONSES_WEBSOCKET_MODE ?? process.env.OPENAI_RESPONSES_WEBSOCKET_MODE,
|
|
1380
|
+
"auto"
|
|
1381
|
+
);
|
|
1382
|
+
return cachedResponsesWebSocketMode;
|
|
1383
|
+
}
|
|
1384
|
+
function buildChatGptCodexHeaders(options) {
|
|
1385
|
+
const openAiBeta = options.useWebSocket ? mergeOpenAiBetaHeader(
|
|
1386
|
+
CHATGPT_RESPONSES_EXPERIMENTAL_HEADER,
|
|
1387
|
+
OPENAI_BETA_RESPONSES_WEBSOCKETS_V2
|
|
1388
|
+
) : CHATGPT_RESPONSES_EXPERIMENTAL_HEADER;
|
|
1389
|
+
const headers = {
|
|
1390
|
+
Authorization: `Bearer ${options.access}`,
|
|
1391
|
+
"chatgpt-account-id": options.accountId,
|
|
1392
|
+
"OpenAI-Beta": openAiBeta,
|
|
1393
|
+
originator: "llm",
|
|
1394
|
+
"User-Agent": buildUserAgent()
|
|
1395
|
+
};
|
|
1396
|
+
if (options.sessionId) {
|
|
1397
|
+
headers.session_id = options.sessionId;
|
|
1398
|
+
}
|
|
1399
|
+
return headers;
|
|
1400
|
+
}
|
|
809
1401
|
async function collectChatGptCodexResponse(options) {
|
|
810
|
-
let
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
1402
|
+
let requestForAttempt = options.request;
|
|
1403
|
+
let retriedWithoutReasoningSummary = false;
|
|
1404
|
+
let retriedViaSseFallback = false;
|
|
1405
|
+
while (true) {
|
|
1406
|
+
let sawAnyDelta = false;
|
|
1407
|
+
try {
|
|
1408
|
+
const stream = await streamChatGptCodexResponse({
|
|
816
1409
|
...options,
|
|
817
|
-
request:
|
|
1410
|
+
request: requestForAttempt
|
|
818
1411
|
});
|
|
819
|
-
|
|
1412
|
+
return await collectChatGptCodexStream({
|
|
1413
|
+
stream,
|
|
1414
|
+
onDelta: (delta) => {
|
|
1415
|
+
sawAnyDelta = true;
|
|
1416
|
+
options.onDelta?.(delta);
|
|
1417
|
+
}
|
|
1418
|
+
});
|
|
1419
|
+
} catch (error) {
|
|
1420
|
+
if (!sawAnyDelta && !retriedViaSseFallback && shouldRetryViaSseFallback(error) && !chatGptResponsesWebSocketDisabled) {
|
|
1421
|
+
chatGptResponsesWebSocketDisabled = true;
|
|
1422
|
+
retriedViaSseFallback = true;
|
|
1423
|
+
continue;
|
|
1424
|
+
}
|
|
1425
|
+
if (!retriedWithoutReasoningSummary && shouldRetryWithoutReasoningSummary(requestForAttempt, error)) {
|
|
1426
|
+
requestForAttempt = removeReasoningSummary(requestForAttempt);
|
|
1427
|
+
retriedWithoutReasoningSummary = true;
|
|
1428
|
+
continue;
|
|
1429
|
+
}
|
|
820
1430
|
throw error;
|
|
821
1431
|
}
|
|
822
1432
|
}
|
|
1433
|
+
}
|
|
1434
|
+
async function collectChatGptCodexStream(options) {
|
|
823
1435
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
824
1436
|
const toolCallOrder = [];
|
|
825
1437
|
const webSearchCalls = /* @__PURE__ */ new Map();
|
|
@@ -832,7 +1444,7 @@ async function collectChatGptCodexResponse(options) {
|
|
|
832
1444
|
let model;
|
|
833
1445
|
let status;
|
|
834
1446
|
let blocked = false;
|
|
835
|
-
for await (const event of stream) {
|
|
1447
|
+
for await (const event of options.stream) {
|
|
836
1448
|
const type = typeof event.type === "string" ? event.type : void 0;
|
|
837
1449
|
if (type === "response.output_text.delta") {
|
|
838
1450
|
const delta = typeof event.delta === "string" ? event.delta : "";
|
|
@@ -956,6 +1568,16 @@ function shouldRetryWithoutReasoningSummary(request, error) {
|
|
|
956
1568
|
const message = error.message.toLowerCase();
|
|
957
1569
|
return message.includes("unsupported parameter") && message.includes("reasoning.summary");
|
|
958
1570
|
}
|
|
1571
|
+
function shouldRetryViaSseFallback(error) {
|
|
1572
|
+
if (!(error instanceof Error)) {
|
|
1573
|
+
return false;
|
|
1574
|
+
}
|
|
1575
|
+
if (error.name === "AbortError") {
|
|
1576
|
+
return false;
|
|
1577
|
+
}
|
|
1578
|
+
const message = error.message.toLowerCase();
|
|
1579
|
+
return message.includes("responses websocket");
|
|
1580
|
+
}
|
|
959
1581
|
function removeReasoningSummary(request) {
|
|
960
1582
|
const reasoning = request.reasoning;
|
|
961
1583
|
if (!reasoning?.summary) {
|
|
@@ -1203,14 +1825,16 @@ async function runFireworksCall(fn) {
|
|
|
1203
1825
|
}
|
|
1204
1826
|
|
|
1205
1827
|
// src/fireworks/models.ts
|
|
1206
|
-
var FIREWORKS_MODEL_IDS = ["kimi-k2.5", "glm-5", "minimax-m2.1"];
|
|
1828
|
+
var FIREWORKS_MODEL_IDS = ["kimi-k2.5", "glm-5", "minimax-m2.1", "gpt-oss-120b"];
|
|
1207
1829
|
var FIREWORKS_DEFAULT_KIMI_MODEL = "kimi-k2.5";
|
|
1208
1830
|
var FIREWORKS_DEFAULT_GLM_MODEL = "glm-5";
|
|
1209
1831
|
var FIREWORKS_DEFAULT_MINIMAX_MODEL = "minimax-m2.1";
|
|
1832
|
+
var FIREWORKS_DEFAULT_GPT_OSS_120B_MODEL = "gpt-oss-120b";
|
|
1210
1833
|
var FIREWORKS_CANONICAL_MODEL_IDS = {
|
|
1211
1834
|
"kimi-k2.5": "accounts/fireworks/models/kimi-k2p5",
|
|
1212
1835
|
"glm-5": "accounts/fireworks/models/glm-5",
|
|
1213
|
-
"minimax-m2.1": "accounts/fireworks/models/minimax-m2p1"
|
|
1836
|
+
"minimax-m2.1": "accounts/fireworks/models/minimax-m2p1",
|
|
1837
|
+
"gpt-oss-120b": "accounts/fireworks/models/gpt-oss-120b"
|
|
1214
1838
|
};
|
|
1215
1839
|
function isFireworksModelId(value) {
|
|
1216
1840
|
return FIREWORKS_MODEL_IDS.includes(value.trim());
|
|
@@ -1291,6 +1915,7 @@ function getGoogleAuthOptions(scopes) {
|
|
|
1291
1915
|
// src/google/client.ts
|
|
1292
1916
|
var GEMINI_MODEL_IDS = [
|
|
1293
1917
|
"gemini-3-pro-preview",
|
|
1918
|
+
"gemini-3.1-pro-preview",
|
|
1294
1919
|
"gemini-3-flash-preview",
|
|
1295
1920
|
"gemini-2.5-pro",
|
|
1296
1921
|
"gemini-flash-latest",
|
|
@@ -1557,6 +2182,8 @@ var cachedApiKey2 = null;
|
|
|
1557
2182
|
var cachedClient2 = null;
|
|
1558
2183
|
var cachedFetch2 = null;
|
|
1559
2184
|
var cachedTimeoutMs2 = null;
|
|
2185
|
+
var openAiResponsesWebSocketMode = null;
|
|
2186
|
+
var openAiResponsesWebSocketDisabled = false;
|
|
1560
2187
|
var DEFAULT_OPENAI_TIMEOUT_MS = 15 * 6e4;
|
|
1561
2188
|
function resolveOpenAiTimeoutMs() {
|
|
1562
2189
|
if (cachedTimeoutMs2 !== null) {
|
|
@@ -1584,6 +2211,97 @@ function getOpenAiFetch() {
|
|
|
1584
2211
|
});
|
|
1585
2212
|
return cachedFetch2;
|
|
1586
2213
|
}
|
|
2214
|
+
function resolveOpenAiBaseUrl() {
|
|
2215
|
+
loadLocalEnv();
|
|
2216
|
+
return process.env.OPENAI_BASE_URL?.trim() || "https://api.openai.com/v1";
|
|
2217
|
+
}
|
|
2218
|
+
function resolveOpenAiResponsesWebSocketMode() {
|
|
2219
|
+
if (openAiResponsesWebSocketMode) {
|
|
2220
|
+
return openAiResponsesWebSocketMode;
|
|
2221
|
+
}
|
|
2222
|
+
loadLocalEnv();
|
|
2223
|
+
openAiResponsesWebSocketMode = resolveResponsesWebSocketMode(
|
|
2224
|
+
process.env.OPENAI_RESPONSES_WEBSOCKET_MODE,
|
|
2225
|
+
"auto"
|
|
2226
|
+
);
|
|
2227
|
+
return openAiResponsesWebSocketMode;
|
|
2228
|
+
}
|
|
2229
|
+
function wrapFallbackStream(stream) {
|
|
2230
|
+
return {
|
|
2231
|
+
async *[Symbol.asyncIterator]() {
|
|
2232
|
+
for await (const event of stream) {
|
|
2233
|
+
yield event;
|
|
2234
|
+
}
|
|
2235
|
+
},
|
|
2236
|
+
async finalResponse() {
|
|
2237
|
+
return await stream.finalResponse();
|
|
2238
|
+
},
|
|
2239
|
+
close() {
|
|
2240
|
+
const maybeClose = stream;
|
|
2241
|
+
if (typeof maybeClose.close === "function") {
|
|
2242
|
+
maybeClose.close();
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
};
|
|
2246
|
+
}
|
|
2247
|
+
function buildOpenAiResponsesEndpointUrl() {
|
|
2248
|
+
const base = resolveOpenAiBaseUrl();
|
|
2249
|
+
const normalized = base.endsWith("/") ? base : `${base}/`;
|
|
2250
|
+
return new URL("responses", normalized).toString();
|
|
2251
|
+
}
|
|
2252
|
+
function buildOpenAiResponsesWebSocketHeaders(apiKey) {
|
|
2253
|
+
const headers = {
|
|
2254
|
+
Authorization: `Bearer ${apiKey}`,
|
|
2255
|
+
"OpenAI-Beta": mergeOpenAiBetaHeader(
|
|
2256
|
+
process.env.OPENAI_BETA,
|
|
2257
|
+
OPENAI_BETA_RESPONSES_WEBSOCKETS_V2
|
|
2258
|
+
)
|
|
2259
|
+
};
|
|
2260
|
+
const organization = process.env.OPENAI_ORGANIZATION?.trim();
|
|
2261
|
+
if (organization) {
|
|
2262
|
+
headers["OpenAI-Organization"] = organization;
|
|
2263
|
+
}
|
|
2264
|
+
const project = process.env.OPENAI_PROJECT?.trim();
|
|
2265
|
+
if (project) {
|
|
2266
|
+
headers["OpenAI-Project"] = project;
|
|
2267
|
+
}
|
|
2268
|
+
return headers;
|
|
2269
|
+
}
|
|
2270
|
+
function installResponsesWebSocketTransport(client, apiKey) {
|
|
2271
|
+
const responsesApi = client.responses;
|
|
2272
|
+
const streamMethod = responsesApi?.stream;
|
|
2273
|
+
if (typeof streamMethod !== "function") {
|
|
2274
|
+
return;
|
|
2275
|
+
}
|
|
2276
|
+
const originalStream = streamMethod.bind(client.responses);
|
|
2277
|
+
responsesApi.stream = (request, options) => {
|
|
2278
|
+
const mode = resolveOpenAiResponsesWebSocketMode();
|
|
2279
|
+
const fallbackStreamFactory = () => wrapFallbackStream(originalStream(request, options));
|
|
2280
|
+
if (mode === "off" || openAiResponsesWebSocketDisabled) {
|
|
2281
|
+
return fallbackStreamFactory();
|
|
2282
|
+
}
|
|
2283
|
+
const signal = options && typeof options === "object" ? options.signal ?? void 0 : void 0;
|
|
2284
|
+
const websocketUrl = toWebSocketUrl(buildOpenAiResponsesEndpointUrl());
|
|
2285
|
+
const headers = buildOpenAiResponsesWebSocketHeaders(apiKey);
|
|
2286
|
+
const timeoutMs = resolveOpenAiTimeoutMs();
|
|
2287
|
+
return createAdaptiveResponsesStream({
|
|
2288
|
+
mode,
|
|
2289
|
+
createWebSocketStream: async () => await createResponsesWebSocketStream({
|
|
2290
|
+
url: websocketUrl,
|
|
2291
|
+
headers,
|
|
2292
|
+
request,
|
|
2293
|
+
signal,
|
|
2294
|
+
idleTimeoutMs: timeoutMs
|
|
2295
|
+
}),
|
|
2296
|
+
createFallbackStream: fallbackStreamFactory,
|
|
2297
|
+
onWebSocketFallback: (error) => {
|
|
2298
|
+
if (isResponsesWebSocketUnsupportedError(error)) {
|
|
2299
|
+
openAiResponsesWebSocketDisabled = true;
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
});
|
|
2303
|
+
};
|
|
2304
|
+
}
|
|
1587
2305
|
function getOpenAiApiKey() {
|
|
1588
2306
|
if (cachedApiKey2 !== null) {
|
|
1589
2307
|
return cachedApiKey2;
|
|
@@ -1601,6 +2319,7 @@ function getOpenAiClient() {
|
|
|
1601
2319
|
if (cachedClient2) {
|
|
1602
2320
|
return cachedClient2;
|
|
1603
2321
|
}
|
|
2322
|
+
loadLocalEnv();
|
|
1604
2323
|
const apiKey = getOpenAiApiKey();
|
|
1605
2324
|
const timeoutMs = resolveOpenAiTimeoutMs();
|
|
1606
2325
|
cachedClient2 = new import_openai2.default({
|
|
@@ -1608,6 +2327,7 @@ function getOpenAiClient() {
|
|
|
1608
2327
|
fetch: getOpenAiFetch(),
|
|
1609
2328
|
timeout: timeoutMs
|
|
1610
2329
|
});
|
|
2330
|
+
installResponsesWebSocketTransport(cachedClient2, apiKey);
|
|
1611
2331
|
return cachedClient2;
|
|
1612
2332
|
}
|
|
1613
2333
|
|
|
@@ -3181,6 +3901,7 @@ function extractFireworksToolCalls(message) {
|
|
|
3181
3901
|
function resolveGeminiThinkingConfig(modelId) {
|
|
3182
3902
|
switch (modelId) {
|
|
3183
3903
|
case "gemini-3-pro-preview":
|
|
3904
|
+
case "gemini-3.1-pro-preview":
|
|
3184
3905
|
return { includeThoughts: true };
|
|
3185
3906
|
case "gemini-3-flash-preview":
|
|
3186
3907
|
return { includeThoughts: true, thinkingBudget: 16384 };
|
|
@@ -6581,6 +7302,7 @@ function mergeToolSets(base, extra) {
|
|
|
6581
7302
|
CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION,
|
|
6582
7303
|
CODEX_APPLY_PATCH_LARK_GRAMMAR,
|
|
6583
7304
|
FIREWORKS_DEFAULT_GLM_MODEL,
|
|
7305
|
+
FIREWORKS_DEFAULT_GPT_OSS_120B_MODEL,
|
|
6584
7306
|
FIREWORKS_DEFAULT_KIMI_MODEL,
|
|
6585
7307
|
FIREWORKS_DEFAULT_MINIMAX_MODEL,
|
|
6586
7308
|
FIREWORKS_MODEL_IDS,
|