@ljoukov/llm 3.0.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -11
- package/dist/index.cjs +875 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -8
- package/dist/index.d.ts +34 -8
- package/dist/index.js +859 -37
- package/dist/index.js.map +1 -1
- package/package.json +9 -7
package/dist/index.cjs
CHANGED
|
@@ -30,15 +30,24 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
CHATGPT_MODEL_IDS: () => CHATGPT_MODEL_IDS,
|
|
33
34
|
CODEX_APPLY_PATCH_FREEFORM_TOOL_DESCRIPTION: () => CODEX_APPLY_PATCH_FREEFORM_TOOL_DESCRIPTION,
|
|
34
35
|
CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION: () => CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION,
|
|
35
36
|
CODEX_APPLY_PATCH_LARK_GRAMMAR: () => CODEX_APPLY_PATCH_LARK_GRAMMAR,
|
|
36
37
|
FIREWORKS_DEFAULT_GLM_MODEL: () => FIREWORKS_DEFAULT_GLM_MODEL,
|
|
38
|
+
FIREWORKS_DEFAULT_GPT_OSS_120B_MODEL: () => FIREWORKS_DEFAULT_GPT_OSS_120B_MODEL,
|
|
37
39
|
FIREWORKS_DEFAULT_KIMI_MODEL: () => FIREWORKS_DEFAULT_KIMI_MODEL,
|
|
38
40
|
FIREWORKS_DEFAULT_MINIMAX_MODEL: () => FIREWORKS_DEFAULT_MINIMAX_MODEL,
|
|
39
41
|
FIREWORKS_MODEL_IDS: () => FIREWORKS_MODEL_IDS,
|
|
42
|
+
GEMINI_IMAGE_MODEL_IDS: () => GEMINI_IMAGE_MODEL_IDS,
|
|
43
|
+
GEMINI_MODEL_IDS: () => GEMINI_MODEL_IDS,
|
|
44
|
+
GEMINI_TEXT_MODEL_IDS: () => GEMINI_TEXT_MODEL_IDS,
|
|
40
45
|
InMemoryAgentFilesystem: () => InMemoryAgentFilesystem,
|
|
46
|
+
LLM_IMAGE_MODEL_IDS: () => LLM_IMAGE_MODEL_IDS,
|
|
47
|
+
LLM_MODEL_IDS: () => LLM_MODEL_IDS,
|
|
48
|
+
LLM_TEXT_MODEL_IDS: () => LLM_TEXT_MODEL_IDS,
|
|
41
49
|
LlmJsonCallError: () => LlmJsonCallError,
|
|
50
|
+
OPENAI_MODEL_IDS: () => OPENAI_MODEL_IDS,
|
|
42
51
|
appendMarkdownSourcesSection: () => appendMarkdownSourcesSection,
|
|
43
52
|
applyPatch: () => applyPatch,
|
|
44
53
|
configureGemini: () => configureGemini,
|
|
@@ -73,8 +82,15 @@ __export(index_exports, {
|
|
|
73
82
|
generateText: () => generateText,
|
|
74
83
|
getChatGptAuthProfile: () => getChatGptAuthProfile,
|
|
75
84
|
getCurrentToolCallContext: () => getCurrentToolCallContext,
|
|
85
|
+
isChatGptModelId: () => isChatGptModelId,
|
|
76
86
|
isFireworksModelId: () => isFireworksModelId,
|
|
87
|
+
isGeminiImageModelId: () => isGeminiImageModelId,
|
|
77
88
|
isGeminiModelId: () => isGeminiModelId,
|
|
89
|
+
isGeminiTextModelId: () => isGeminiTextModelId,
|
|
90
|
+
isLlmImageModelId: () => isLlmImageModelId,
|
|
91
|
+
isLlmModelId: () => isLlmModelId,
|
|
92
|
+
isLlmTextModelId: () => isLlmTextModelId,
|
|
93
|
+
isOpenAiModelId: () => isOpenAiModelId,
|
|
78
94
|
loadEnvFromFile: () => loadEnvFromFile,
|
|
79
95
|
loadLocalEnv: () => loadLocalEnv,
|
|
80
96
|
parseJsonFromLlmText: () => parseJsonFromLlmText,
|
|
@@ -227,7 +243,7 @@ function getGeminiProPricing(modelId) {
|
|
|
227
243
|
if (modelId.includes("gemini-2.5-pro")) {
|
|
228
244
|
return GEMINI_2_5_PRO_PRICING;
|
|
229
245
|
}
|
|
230
|
-
if (modelId.includes("gemini-3-pro")) {
|
|
246
|
+
if (modelId.includes("gemini-3-pro") || modelId.includes("gemini-3.1-pro")) {
|
|
231
247
|
return GEMINI_3_PRO_PREVIEW_PRICING;
|
|
232
248
|
}
|
|
233
249
|
return void 0;
|
|
@@ -262,9 +278,6 @@ function getOpenAiPricing(modelId) {
|
|
|
262
278
|
if (modelId.includes("gpt-5.3-codex")) {
|
|
263
279
|
return OPENAI_GPT_53_CODEX_PRICING;
|
|
264
280
|
}
|
|
265
|
-
if (modelId.includes("gpt-5-codex")) {
|
|
266
|
-
return OPENAI_GPT_53_CODEX_PRICING;
|
|
267
|
-
}
|
|
268
281
|
if (modelId.includes("gpt-5.2")) {
|
|
269
282
|
return OPENAI_GPT_52_PRICING;
|
|
270
283
|
}
|
|
@@ -427,8 +440,6 @@ function parseEnvLine(line) {
|
|
|
427
440
|
// src/openai/chatgpt-auth.ts
|
|
428
441
|
var CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_URL";
|
|
429
442
|
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
443
|
var CHATGPT_AUTH_API_KEY_ENV = "CHATGPT_AUTH_API_KEY";
|
|
433
444
|
var CHATGPT_AUTH_TOKEN_PROVIDER_API_KEY_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_API_KEY";
|
|
434
445
|
var CHATGPT_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
@@ -560,7 +571,7 @@ async function refreshChatGptOauthToken(refreshToken, fallback) {
|
|
|
560
571
|
}
|
|
561
572
|
async function getChatGptAuthProfile() {
|
|
562
573
|
loadLocalEnv();
|
|
563
|
-
const tokenProviderUrl = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV]
|
|
574
|
+
const tokenProviderUrl = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV];
|
|
564
575
|
const tokenProviderKey = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_API_KEY_ENV] ?? process.env[CHATGPT_AUTH_API_KEY_ENV];
|
|
565
576
|
if (tokenProviderUrl && tokenProviderUrl.trim().length > 0 && tokenProviderKey && tokenProviderKey.trim().length > 0) {
|
|
566
577
|
if (cachedProfile && !isExpired(cachedProfile)) {
|
|
@@ -571,7 +582,7 @@ async function getChatGptAuthProfile() {
|
|
|
571
582
|
}
|
|
572
583
|
refreshPromise = (async () => {
|
|
573
584
|
try {
|
|
574
|
-
const store = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_STORE_ENV]
|
|
585
|
+
const store = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_STORE_ENV];
|
|
575
586
|
const profile = await fetchChatGptAuthProfileFromTokenProvider({
|
|
576
587
|
baseUrl: tokenProviderUrl,
|
|
577
588
|
apiKey: tokenProviderKey,
|
|
@@ -774,22 +785,624 @@ function extractChatGptAccountId(token) {
|
|
|
774
785
|
return typeof namespaced === "string" && namespaced.length > 0 ? namespaced : void 0;
|
|
775
786
|
}
|
|
776
787
|
|
|
788
|
+
// src/openai/responses-websocket.ts
|
|
789
|
+
var import_ws = __toESM(require("ws"), 1);
|
|
790
|
+
var OPENAI_BETA_RESPONSES_WEBSOCKETS_V2 = "responses_websockets=2026-02-06";
|
|
791
|
+
var ResponsesWebSocketHttpError = class extends Error {
|
|
792
|
+
status;
|
|
793
|
+
body;
|
|
794
|
+
headers;
|
|
795
|
+
constructor(options) {
|
|
796
|
+
super(options.message);
|
|
797
|
+
this.name = "ResponsesWebSocketHttpError";
|
|
798
|
+
this.status = options.status;
|
|
799
|
+
this.body = options.body;
|
|
800
|
+
this.headers = options.headers;
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
var UNSUPPORTED_WEBSOCKET_STATUS_CODES = /* @__PURE__ */ new Set([400, 404, 405, 406, 426, 501]);
|
|
804
|
+
var WEBSOCKET_CONNECT_TIMEOUT_MS = 3e4;
|
|
805
|
+
function parseUnexpectedServerResponseStatus(message) {
|
|
806
|
+
const match = /unexpected server response:\s*(\d+)/i.exec(message);
|
|
807
|
+
if (!match) {
|
|
808
|
+
return null;
|
|
809
|
+
}
|
|
810
|
+
const status = Number(match[1]);
|
|
811
|
+
if (!Number.isFinite(status) || status <= 0) {
|
|
812
|
+
return null;
|
|
813
|
+
}
|
|
814
|
+
return status;
|
|
815
|
+
}
|
|
816
|
+
function supportsUnexpectedResponseEvent() {
|
|
817
|
+
return !("bun" in process.versions);
|
|
818
|
+
}
|
|
819
|
+
function resolveResponsesWebSocketMode(raw, fallback = "auto") {
|
|
820
|
+
const value = raw?.trim().toLowerCase();
|
|
821
|
+
if (value === "auto" || value === "off" || value === "only") {
|
|
822
|
+
return value;
|
|
823
|
+
}
|
|
824
|
+
return fallback;
|
|
825
|
+
}
|
|
826
|
+
function mergeOpenAiBetaHeader(existing, required) {
|
|
827
|
+
const parts = /* @__PURE__ */ new Set();
|
|
828
|
+
for (const part of (existing ?? "").split(",")) {
|
|
829
|
+
const trimmed = part.trim();
|
|
830
|
+
if (trimmed.length > 0) {
|
|
831
|
+
parts.add(trimmed);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
const normalizedRequired = required.trim();
|
|
835
|
+
if (normalizedRequired.length > 0) {
|
|
836
|
+
parts.add(normalizedRequired);
|
|
837
|
+
}
|
|
838
|
+
return Array.from(parts).join(", ");
|
|
839
|
+
}
|
|
840
|
+
function toWebSocketUrl(httpOrHttpsUrl) {
|
|
841
|
+
const parsed = new URL(httpOrHttpsUrl);
|
|
842
|
+
if (parsed.protocol === "https:") {
|
|
843
|
+
parsed.protocol = "wss:";
|
|
844
|
+
} else if (parsed.protocol === "http:") {
|
|
845
|
+
parsed.protocol = "ws:";
|
|
846
|
+
} else if (parsed.protocol !== "ws:" && parsed.protocol !== "wss:") {
|
|
847
|
+
throw new Error(`Unsupported websocket URL protocol: ${parsed.protocol}`);
|
|
848
|
+
}
|
|
849
|
+
return parsed.toString();
|
|
850
|
+
}
|
|
851
|
+
function isResponsesWebSocketUnsupportedError(error) {
|
|
852
|
+
if (error instanceof ResponsesWebSocketHttpError) {
|
|
853
|
+
return UNSUPPORTED_WEBSOCKET_STATUS_CODES.has(error.status);
|
|
854
|
+
}
|
|
855
|
+
const message = error instanceof Error ? error.message.toLowerCase() : "";
|
|
856
|
+
const status = parseUnexpectedServerResponseStatus(message);
|
|
857
|
+
if (status !== null) {
|
|
858
|
+
return UNSUPPORTED_WEBSOCKET_STATUS_CODES.has(status);
|
|
859
|
+
}
|
|
860
|
+
return message.includes("unexpected server response: 426");
|
|
861
|
+
}
|
|
862
|
+
function createAdaptiveResponsesStream(options) {
|
|
863
|
+
let resolved = null;
|
|
864
|
+
let websocketSelected = false;
|
|
865
|
+
let fallbackSelected = false;
|
|
866
|
+
const activateFallback = (error) => {
|
|
867
|
+
options.onWebSocketFallback?.(error);
|
|
868
|
+
fallbackSelected = true;
|
|
869
|
+
websocketSelected = false;
|
|
870
|
+
const fallback = options.createFallbackStream();
|
|
871
|
+
resolved = Promise.resolve(fallback);
|
|
872
|
+
return fallback;
|
|
873
|
+
};
|
|
874
|
+
const getStream = async () => {
|
|
875
|
+
if (resolved) {
|
|
876
|
+
return await resolved;
|
|
877
|
+
}
|
|
878
|
+
resolved = (async () => {
|
|
879
|
+
if (options.mode === "off") {
|
|
880
|
+
fallbackSelected = true;
|
|
881
|
+
return options.createFallbackStream();
|
|
882
|
+
}
|
|
883
|
+
try {
|
|
884
|
+
const stream = await options.createWebSocketStream();
|
|
885
|
+
websocketSelected = true;
|
|
886
|
+
return stream;
|
|
887
|
+
} catch (error) {
|
|
888
|
+
if (options.mode === "only") {
|
|
889
|
+
throw error;
|
|
890
|
+
}
|
|
891
|
+
return activateFallback(error);
|
|
892
|
+
}
|
|
893
|
+
})();
|
|
894
|
+
return await resolved;
|
|
895
|
+
};
|
|
896
|
+
return {
|
|
897
|
+
async *[Symbol.asyncIterator]() {
|
|
898
|
+
const stream = await getStream();
|
|
899
|
+
let yielded = 0;
|
|
900
|
+
try {
|
|
901
|
+
for await (const event of stream) {
|
|
902
|
+
yielded += 1;
|
|
903
|
+
yield event;
|
|
904
|
+
}
|
|
905
|
+
} catch (error) {
|
|
906
|
+
if (options.mode !== "only" && websocketSelected && !fallbackSelected && yielded === 0) {
|
|
907
|
+
const fallback = activateFallback(error);
|
|
908
|
+
for await (const event of fallback) {
|
|
909
|
+
yield event;
|
|
910
|
+
}
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
throw error;
|
|
914
|
+
}
|
|
915
|
+
},
|
|
916
|
+
async finalResponse() {
|
|
917
|
+
const stream = await getStream();
|
|
918
|
+
try {
|
|
919
|
+
return await stream.finalResponse();
|
|
920
|
+
} catch (error) {
|
|
921
|
+
if (options.mode === "only" || !websocketSelected || fallbackSelected) {
|
|
922
|
+
throw error;
|
|
923
|
+
}
|
|
924
|
+
const fallback = activateFallback(error);
|
|
925
|
+
return await fallback.finalResponse();
|
|
926
|
+
}
|
|
927
|
+
},
|
|
928
|
+
close() {
|
|
929
|
+
void getStream().then((stream) => stream.close()).catch(() => {
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
async function createResponsesWebSocketStream(options) {
|
|
935
|
+
const completionTypes = new Set(
|
|
936
|
+
options.completionEventTypes ?? ["response.completed", "response.failed", "response.done"]
|
|
937
|
+
);
|
|
938
|
+
const { socket, responseHeaders } = await connectWebSocket({
|
|
939
|
+
url: options.url,
|
|
940
|
+
headers: options.headers,
|
|
941
|
+
signal: options.signal
|
|
942
|
+
});
|
|
943
|
+
const queue = createAsyncQueue();
|
|
944
|
+
let settled = false;
|
|
945
|
+
let finalResponse = null;
|
|
946
|
+
let latestResponse = null;
|
|
947
|
+
let idleTimer = null;
|
|
948
|
+
let resolveFinal = null;
|
|
949
|
+
let rejectFinal = null;
|
|
950
|
+
const finalPromise = new Promise((resolve, reject) => {
|
|
951
|
+
resolveFinal = resolve;
|
|
952
|
+
rejectFinal = reject;
|
|
953
|
+
});
|
|
954
|
+
void finalPromise.catch(() => {
|
|
955
|
+
});
|
|
956
|
+
const clearIdleTimer = () => {
|
|
957
|
+
if (idleTimer) {
|
|
958
|
+
clearTimeout(idleTimer);
|
|
959
|
+
idleTimer = null;
|
|
960
|
+
}
|
|
961
|
+
};
|
|
962
|
+
const closeSocket = () => {
|
|
963
|
+
try {
|
|
964
|
+
if (socket.readyState === import_ws.default.OPEN || socket.readyState === import_ws.default.CONNECTING) {
|
|
965
|
+
socket.close();
|
|
966
|
+
}
|
|
967
|
+
} catch {
|
|
968
|
+
}
|
|
969
|
+
};
|
|
970
|
+
const complete = (response) => {
|
|
971
|
+
if (settled) {
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
settled = true;
|
|
975
|
+
clearIdleTimer();
|
|
976
|
+
finalResponse = response;
|
|
977
|
+
resolveFinal?.(response);
|
|
978
|
+
queue.close();
|
|
979
|
+
closeSocket();
|
|
980
|
+
};
|
|
981
|
+
const fail = (error) => {
|
|
982
|
+
if (settled) {
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
settled = true;
|
|
986
|
+
clearIdleTimer();
|
|
987
|
+
rejectFinal?.(error);
|
|
988
|
+
queue.fail(error);
|
|
989
|
+
closeSocket();
|
|
990
|
+
};
|
|
991
|
+
const restartIdleTimer = () => {
|
|
992
|
+
clearIdleTimer();
|
|
993
|
+
const idleTimeoutMs = options.idleTimeoutMs;
|
|
994
|
+
if (!idleTimeoutMs || idleTimeoutMs <= 0 || settled) {
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
idleTimer = setTimeout(() => {
|
|
998
|
+
fail(new Error(`Responses WebSocket idle timeout after ${idleTimeoutMs}ms.`));
|
|
999
|
+
}, idleTimeoutMs);
|
|
1000
|
+
};
|
|
1001
|
+
const onAbort = () => {
|
|
1002
|
+
const error = createAbortError(options.signal?.reason);
|
|
1003
|
+
fail(error);
|
|
1004
|
+
};
|
|
1005
|
+
if (options.signal) {
|
|
1006
|
+
if (options.signal.aborted) {
|
|
1007
|
+
socket.close();
|
|
1008
|
+
throw createAbortError(options.signal.reason);
|
|
1009
|
+
}
|
|
1010
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
1011
|
+
}
|
|
1012
|
+
const cleanup = () => {
|
|
1013
|
+
clearIdleTimer();
|
|
1014
|
+
socket.removeAllListeners();
|
|
1015
|
+
if (options.signal) {
|
|
1016
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
1017
|
+
}
|
|
1018
|
+
};
|
|
1019
|
+
socket.on("message", (raw) => {
|
|
1020
|
+
restartIdleTimer();
|
|
1021
|
+
const parsed = parseWebSocketPayload(raw);
|
|
1022
|
+
if (!parsed) {
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
const error = mapWebSocketErrorEvent(parsed);
|
|
1026
|
+
if (error) {
|
|
1027
|
+
fail(error);
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
const event = parsed;
|
|
1031
|
+
if (isObjectWithResponse(event)) {
|
|
1032
|
+
latestResponse = event.response;
|
|
1033
|
+
}
|
|
1034
|
+
queue.push(event);
|
|
1035
|
+
const type = typeof event.type === "string" ? event.type : "";
|
|
1036
|
+
if (completionTypes.has(type)) {
|
|
1037
|
+
const completedResponse = normalizeFinalResponse(
|
|
1038
|
+
type,
|
|
1039
|
+
event.response,
|
|
1040
|
+
latestResponse,
|
|
1041
|
+
responseHeaders
|
|
1042
|
+
);
|
|
1043
|
+
complete(completedResponse);
|
|
1044
|
+
}
|
|
1045
|
+
});
|
|
1046
|
+
socket.on("error", (error) => {
|
|
1047
|
+
fail(new Error(`Responses WebSocket error: ${error.message}`));
|
|
1048
|
+
});
|
|
1049
|
+
socket.on("close", (_code, _reason) => {
|
|
1050
|
+
if (settled) {
|
|
1051
|
+
cleanup();
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
fail(new Error("Responses WebSocket closed before completion."));
|
|
1055
|
+
cleanup();
|
|
1056
|
+
});
|
|
1057
|
+
restartIdleTimer();
|
|
1058
|
+
const payload = serializeRequestPayload(options.request);
|
|
1059
|
+
await new Promise((resolve, reject) => {
|
|
1060
|
+
socket.send(payload, (error) => {
|
|
1061
|
+
if (error) {
|
|
1062
|
+
reject(error);
|
|
1063
|
+
} else {
|
|
1064
|
+
resolve();
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1067
|
+
}).catch((error) => {
|
|
1068
|
+
fail(new Error(`Failed to send Responses WebSocket request: ${errorToMessage(error)}`));
|
|
1069
|
+
throw error instanceof Error ? error : new Error(errorToMessage(error));
|
|
1070
|
+
});
|
|
1071
|
+
return {
|
|
1072
|
+
async *[Symbol.asyncIterator]() {
|
|
1073
|
+
try {
|
|
1074
|
+
for await (const event of queue.iterable) {
|
|
1075
|
+
yield event;
|
|
1076
|
+
}
|
|
1077
|
+
} finally {
|
|
1078
|
+
if (!settled) {
|
|
1079
|
+
closeSocket();
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
},
|
|
1083
|
+
async finalResponse() {
|
|
1084
|
+
return await finalPromise;
|
|
1085
|
+
},
|
|
1086
|
+
close() {
|
|
1087
|
+
if (settled) {
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1090
|
+
const response = finalResponse ?? latestResponse ?? { status: "cancelled" };
|
|
1091
|
+
complete(response);
|
|
1092
|
+
cleanup();
|
|
1093
|
+
}
|
|
1094
|
+
};
|
|
1095
|
+
}
|
|
1096
|
+
async function connectWebSocket(options) {
|
|
1097
|
+
return await new Promise((resolve, reject) => {
|
|
1098
|
+
const shouldListenForUnexpectedResponse = supportsUnexpectedResponseEvent();
|
|
1099
|
+
const socket = new import_ws.default(options.url, {
|
|
1100
|
+
headers: options.headers,
|
|
1101
|
+
handshakeTimeout: WEBSOCKET_CONNECT_TIMEOUT_MS
|
|
1102
|
+
});
|
|
1103
|
+
let settled = false;
|
|
1104
|
+
let responseBody = "";
|
|
1105
|
+
let connectTimeout = setTimeout(() => {
|
|
1106
|
+
rejectOnce(
|
|
1107
|
+
new Error(
|
|
1108
|
+
`Responses WebSocket connection timed out after ${WEBSOCKET_CONNECT_TIMEOUT_MS}ms.`
|
|
1109
|
+
)
|
|
1110
|
+
);
|
|
1111
|
+
}, WEBSOCKET_CONNECT_TIMEOUT_MS);
|
|
1112
|
+
const rejectOnce = (error) => {
|
|
1113
|
+
if (settled) {
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
settled = true;
|
|
1117
|
+
cleanup();
|
|
1118
|
+
try {
|
|
1119
|
+
socket.terminate();
|
|
1120
|
+
} catch {
|
|
1121
|
+
}
|
|
1122
|
+
reject(error);
|
|
1123
|
+
};
|
|
1124
|
+
const resolveOnce = (result) => {
|
|
1125
|
+
if (settled) {
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
settled = true;
|
|
1129
|
+
cleanup(false);
|
|
1130
|
+
resolve(result);
|
|
1131
|
+
};
|
|
1132
|
+
const onAbort = () => {
|
|
1133
|
+
rejectOnce(createAbortError(options.signal?.reason));
|
|
1134
|
+
};
|
|
1135
|
+
const cleanup = (removeAbortListener = true) => {
|
|
1136
|
+
if (connectTimeout) {
|
|
1137
|
+
clearTimeout(connectTimeout);
|
|
1138
|
+
connectTimeout = null;
|
|
1139
|
+
}
|
|
1140
|
+
socket.removeListener("open", onOpen);
|
|
1141
|
+
socket.removeListener("error", onError);
|
|
1142
|
+
if (shouldListenForUnexpectedResponse) {
|
|
1143
|
+
socket.removeListener("unexpected-response", onUnexpectedResponse);
|
|
1144
|
+
}
|
|
1145
|
+
if (removeAbortListener && options.signal) {
|
|
1146
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
1147
|
+
}
|
|
1148
|
+
};
|
|
1149
|
+
const onOpen = () => {
|
|
1150
|
+
const headers = normalizeUpgradeHeaders(socket);
|
|
1151
|
+
resolveOnce({ socket, responseHeaders: headers });
|
|
1152
|
+
};
|
|
1153
|
+
const onError = (error) => {
|
|
1154
|
+
rejectOnce(new Error(`Responses WebSocket connection failed: ${error.message}`));
|
|
1155
|
+
};
|
|
1156
|
+
const onUnexpectedResponse = (_request, response) => {
|
|
1157
|
+
if (typeof response.setEncoding === "function") {
|
|
1158
|
+
response.setEncoding("utf8");
|
|
1159
|
+
}
|
|
1160
|
+
response.on("data", (chunk) => {
|
|
1161
|
+
responseBody += typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
1162
|
+
});
|
|
1163
|
+
response.on("end", () => {
|
|
1164
|
+
const status = Number(response.statusCode ?? 0);
|
|
1165
|
+
const headers = {};
|
|
1166
|
+
const rawHeaders = response.headers ?? {};
|
|
1167
|
+
for (const [key, value] of Object.entries(rawHeaders)) {
|
|
1168
|
+
if (typeof value === "string") {
|
|
1169
|
+
headers[key] = value;
|
|
1170
|
+
} else if (Array.isArray(value)) {
|
|
1171
|
+
headers[key] = value.join(", ");
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
rejectOnce(
|
|
1175
|
+
new ResponsesWebSocketHttpError({
|
|
1176
|
+
status: Number.isFinite(status) && status > 0 ? status : 500,
|
|
1177
|
+
message: `Responses WebSocket upgrade failed${status ? ` (${status})` : ""}.`,
|
|
1178
|
+
body: responseBody || void 0,
|
|
1179
|
+
headers
|
|
1180
|
+
})
|
|
1181
|
+
);
|
|
1182
|
+
});
|
|
1183
|
+
response.on("error", (error) => {
|
|
1184
|
+
rejectOnce(
|
|
1185
|
+
new ResponsesWebSocketHttpError({
|
|
1186
|
+
status: Number(response.statusCode ?? 500),
|
|
1187
|
+
message: `Responses WebSocket upgrade failed: ${error.message}`,
|
|
1188
|
+
body: responseBody || void 0
|
|
1189
|
+
})
|
|
1190
|
+
);
|
|
1191
|
+
});
|
|
1192
|
+
};
|
|
1193
|
+
socket.once("open", onOpen);
|
|
1194
|
+
socket.once("error", onError);
|
|
1195
|
+
if (shouldListenForUnexpectedResponse) {
|
|
1196
|
+
socket.once("unexpected-response", onUnexpectedResponse);
|
|
1197
|
+
}
|
|
1198
|
+
if (options.signal) {
|
|
1199
|
+
if (options.signal.aborted) {
|
|
1200
|
+
onAbort();
|
|
1201
|
+
return;
|
|
1202
|
+
}
|
|
1203
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
1204
|
+
}
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
function normalizeUpgradeHeaders(socket) {
|
|
1208
|
+
const maybeUpgradeResponse = socket._req?.res;
|
|
1209
|
+
const raw = maybeUpgradeResponse?.headers ?? {};
|
|
1210
|
+
const normalized = {};
|
|
1211
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
1212
|
+
if (typeof value === "string") {
|
|
1213
|
+
normalized[key.toLowerCase()] = value;
|
|
1214
|
+
} else if (Array.isArray(value)) {
|
|
1215
|
+
normalized[key.toLowerCase()] = value.join(", ");
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
return normalized;
|
|
1219
|
+
}
|
|
1220
|
+
function parseWebSocketPayload(raw) {
|
|
1221
|
+
const text = toUtf8(raw);
|
|
1222
|
+
if (!text) {
|
|
1223
|
+
return null;
|
|
1224
|
+
}
|
|
1225
|
+
try {
|
|
1226
|
+
const parsed = JSON.parse(text);
|
|
1227
|
+
if (parsed && typeof parsed === "object") {
|
|
1228
|
+
return parsed;
|
|
1229
|
+
}
|
|
1230
|
+
} catch {
|
|
1231
|
+
return null;
|
|
1232
|
+
}
|
|
1233
|
+
return null;
|
|
1234
|
+
}
|
|
1235
|
+
function toUtf8(raw) {
|
|
1236
|
+
if (typeof raw === "string") {
|
|
1237
|
+
return raw;
|
|
1238
|
+
}
|
|
1239
|
+
if (raw instanceof ArrayBuffer) {
|
|
1240
|
+
return Buffer.from(raw).toString("utf8");
|
|
1241
|
+
}
|
|
1242
|
+
if (Array.isArray(raw)) {
|
|
1243
|
+
const chunks = raw.map((chunk) => {
|
|
1244
|
+
if (typeof chunk === "string") {
|
|
1245
|
+
return Buffer.from(chunk, "utf8");
|
|
1246
|
+
}
|
|
1247
|
+
return Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
1248
|
+
});
|
|
1249
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
1250
|
+
}
|
|
1251
|
+
return Buffer.isBuffer(raw) ? raw.toString("utf8") : Buffer.from(raw).toString("utf8");
|
|
1252
|
+
}
|
|
1253
|
+
function mapWebSocketErrorEvent(payload) {
|
|
1254
|
+
if (payload.type !== "error") {
|
|
1255
|
+
return null;
|
|
1256
|
+
}
|
|
1257
|
+
const status = resolveNumericStatus(payload.status) ?? resolveNumericStatus(payload.status_code);
|
|
1258
|
+
if (!status || status < 400) {
|
|
1259
|
+
const message = errorToMessage(payload.error) || "Responses WebSocket returned an error event.";
|
|
1260
|
+
return new Error(message);
|
|
1261
|
+
}
|
|
1262
|
+
const headers = mapErrorHeaders(payload.headers);
|
|
1263
|
+
const body = payload.error && typeof payload.error === "object" ? JSON.stringify({ error: payload.error }, null, 2) : void 0;
|
|
1264
|
+
return new ResponsesWebSocketHttpError({
|
|
1265
|
+
status,
|
|
1266
|
+
message: `Responses WebSocket returned status ${status}.`,
|
|
1267
|
+
body,
|
|
1268
|
+
headers
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
function mapErrorHeaders(value) {
|
|
1272
|
+
if (!value || typeof value !== "object") {
|
|
1273
|
+
return void 0;
|
|
1274
|
+
}
|
|
1275
|
+
const headers = {};
|
|
1276
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
1277
|
+
if (typeof entry === "string" || typeof entry === "number" || typeof entry === "boolean") {
|
|
1278
|
+
headers[key.toLowerCase()] = String(entry);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
return Object.keys(headers).length > 0 ? headers : void 0;
|
|
1282
|
+
}
|
|
1283
|
+
function resolveNumericStatus(value) {
|
|
1284
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1285
|
+
return Math.floor(value);
|
|
1286
|
+
}
|
|
1287
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
1288
|
+
const parsed = Number(value);
|
|
1289
|
+
if (Number.isFinite(parsed)) {
|
|
1290
|
+
return Math.floor(parsed);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
return null;
|
|
1294
|
+
}
|
|
1295
|
+
function normalizeFinalResponse(eventType, eventResponse, latestResponse, responseHeaders) {
|
|
1296
|
+
const response = eventResponse && typeof eventResponse === "object" ? { ...eventResponse } : latestResponse ? { ...latestResponse } : {};
|
|
1297
|
+
if (typeof response.status !== "string") {
|
|
1298
|
+
if (eventType === "response.failed") {
|
|
1299
|
+
response.status = "failed";
|
|
1300
|
+
} else if (eventType === "response.done") {
|
|
1301
|
+
response.status = "completed";
|
|
1302
|
+
} else if (eventType === "response.completed") {
|
|
1303
|
+
response.status = "completed";
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
const upgradeModel = responseHeaders["openai-model"];
|
|
1307
|
+
if (typeof response.model !== "string" && upgradeModel) {
|
|
1308
|
+
response.model = upgradeModel;
|
|
1309
|
+
}
|
|
1310
|
+
return response;
|
|
1311
|
+
}
|
|
1312
|
+
function serializeRequestPayload(request) {
|
|
1313
|
+
if (!request || typeof request !== "object" || Array.isArray(request)) {
|
|
1314
|
+
throw new Error("Responses WebSocket request must be a JSON object.");
|
|
1315
|
+
}
|
|
1316
|
+
const body = request;
|
|
1317
|
+
const payload = typeof body.type === "string" ? body : { type: "response.create", ...body };
|
|
1318
|
+
return JSON.stringify(payload);
|
|
1319
|
+
}
|
|
1320
|
+
function isObjectWithResponse(event) {
|
|
1321
|
+
return Boolean(event.response && typeof event.response === "object");
|
|
1322
|
+
}
|
|
1323
|
+
function errorToMessage(error) {
|
|
1324
|
+
if (error instanceof Error) {
|
|
1325
|
+
return error.message;
|
|
1326
|
+
}
|
|
1327
|
+
if (typeof error === "string") {
|
|
1328
|
+
return error;
|
|
1329
|
+
}
|
|
1330
|
+
try {
|
|
1331
|
+
return JSON.stringify(error);
|
|
1332
|
+
} catch {
|
|
1333
|
+
return String(error);
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
function createAbortError(reason) {
|
|
1337
|
+
const error = new Error(
|
|
1338
|
+
reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "Request aborted."
|
|
1339
|
+
);
|
|
1340
|
+
error.name = "AbortError";
|
|
1341
|
+
return error;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
777
1344
|
// src/openai/chatgpt-codex.ts
|
|
778
1345
|
var CHATGPT_CODEX_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
|
|
1346
|
+
var CHATGPT_RESPONSES_EXPERIMENTAL_HEADER = "responses=experimental";
|
|
1347
|
+
var cachedResponsesWebSocketMode = null;
|
|
1348
|
+
var chatGptResponsesWebSocketDisabled = false;
|
|
779
1349
|
async function streamChatGptCodexResponse(options) {
|
|
780
1350
|
const { access, accountId } = await getChatGptAuthProfile();
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1351
|
+
const mode = resolveChatGptResponsesWebSocketMode();
|
|
1352
|
+
const fallbackStreamFactory = () => {
|
|
1353
|
+
const streamPromise = streamChatGptCodexResponseSse({
|
|
1354
|
+
request: options.request,
|
|
1355
|
+
access,
|
|
1356
|
+
accountId,
|
|
1357
|
+
sessionId: options.sessionId,
|
|
1358
|
+
signal: options.signal
|
|
1359
|
+
});
|
|
1360
|
+
return {
|
|
1361
|
+
async *[Symbol.asyncIterator]() {
|
|
1362
|
+
const stream = await streamPromise;
|
|
1363
|
+
for await (const event of stream) {
|
|
1364
|
+
yield event;
|
|
1365
|
+
}
|
|
1366
|
+
},
|
|
1367
|
+
async finalResponse() {
|
|
1368
|
+
return {};
|
|
1369
|
+
},
|
|
1370
|
+
close() {
|
|
1371
|
+
}
|
|
1372
|
+
};
|
|
789
1373
|
};
|
|
790
|
-
if (
|
|
791
|
-
|
|
1374
|
+
if (mode === "off" || chatGptResponsesWebSocketDisabled) {
|
|
1375
|
+
return fallbackStreamFactory();
|
|
792
1376
|
}
|
|
1377
|
+
const websocketHeaders = buildChatGptCodexHeaders({
|
|
1378
|
+
access,
|
|
1379
|
+
accountId,
|
|
1380
|
+
sessionId: options.sessionId,
|
|
1381
|
+
useWebSocket: true
|
|
1382
|
+
});
|
|
1383
|
+
return createAdaptiveResponsesStream({
|
|
1384
|
+
mode,
|
|
1385
|
+
createWebSocketStream: async () => await createResponsesWebSocketStream({
|
|
1386
|
+
url: toWebSocketUrl(CHATGPT_CODEX_ENDPOINT),
|
|
1387
|
+
headers: websocketHeaders,
|
|
1388
|
+
request: options.request,
|
|
1389
|
+
signal: options.signal
|
|
1390
|
+
}),
|
|
1391
|
+
createFallbackStream: fallbackStreamFactory,
|
|
1392
|
+
onWebSocketFallback: () => {
|
|
1393
|
+
chatGptResponsesWebSocketDisabled = true;
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1396
|
+
}
|
|
1397
|
+
async function streamChatGptCodexResponseSse(options) {
|
|
1398
|
+
const headers = buildChatGptCodexHeaders({
|
|
1399
|
+
access: options.access,
|
|
1400
|
+
accountId: options.accountId,
|
|
1401
|
+
sessionId: options.sessionId,
|
|
1402
|
+
useWebSocket: false
|
|
1403
|
+
});
|
|
1404
|
+
headers.Accept = "text/event-stream";
|
|
1405
|
+
headers["Content-Type"] = "application/json";
|
|
793
1406
|
const response = await fetch(CHATGPT_CODEX_ENDPOINT, {
|
|
794
1407
|
method: "POST",
|
|
795
1408
|
headers,
|
|
@@ -806,20 +1419,67 @@ async function streamChatGptCodexResponse(options) {
|
|
|
806
1419
|
}
|
|
807
1420
|
return parseEventStream(body);
|
|
808
1421
|
}
|
|
1422
|
+
function resolveChatGptResponsesWebSocketMode() {
|
|
1423
|
+
if (cachedResponsesWebSocketMode) {
|
|
1424
|
+
return cachedResponsesWebSocketMode;
|
|
1425
|
+
}
|
|
1426
|
+
cachedResponsesWebSocketMode = resolveResponsesWebSocketMode(
|
|
1427
|
+
process.env.CHATGPT_RESPONSES_WEBSOCKET_MODE ?? process.env.OPENAI_RESPONSES_WEBSOCKET_MODE,
|
|
1428
|
+
"auto"
|
|
1429
|
+
);
|
|
1430
|
+
return cachedResponsesWebSocketMode;
|
|
1431
|
+
}
|
|
1432
|
+
function buildChatGptCodexHeaders(options) {
|
|
1433
|
+
const openAiBeta = options.useWebSocket ? mergeOpenAiBetaHeader(
|
|
1434
|
+
CHATGPT_RESPONSES_EXPERIMENTAL_HEADER,
|
|
1435
|
+
OPENAI_BETA_RESPONSES_WEBSOCKETS_V2
|
|
1436
|
+
) : CHATGPT_RESPONSES_EXPERIMENTAL_HEADER;
|
|
1437
|
+
const headers = {
|
|
1438
|
+
Authorization: `Bearer ${options.access}`,
|
|
1439
|
+
"chatgpt-account-id": options.accountId,
|
|
1440
|
+
"OpenAI-Beta": openAiBeta,
|
|
1441
|
+
originator: "llm",
|
|
1442
|
+
"User-Agent": buildUserAgent()
|
|
1443
|
+
};
|
|
1444
|
+
if (options.sessionId) {
|
|
1445
|
+
headers.session_id = options.sessionId;
|
|
1446
|
+
}
|
|
1447
|
+
return headers;
|
|
1448
|
+
}
|
|
809
1449
|
async function collectChatGptCodexResponse(options) {
|
|
810
|
-
let
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
1450
|
+
let requestForAttempt = options.request;
|
|
1451
|
+
let retriedWithoutReasoningSummary = false;
|
|
1452
|
+
let retriedViaSseFallback = false;
|
|
1453
|
+
while (true) {
|
|
1454
|
+
let sawAnyDelta = false;
|
|
1455
|
+
try {
|
|
1456
|
+
const stream = await streamChatGptCodexResponse({
|
|
816
1457
|
...options,
|
|
817
|
-
request:
|
|
1458
|
+
request: requestForAttempt
|
|
818
1459
|
});
|
|
819
|
-
|
|
1460
|
+
return await collectChatGptCodexStream({
|
|
1461
|
+
stream,
|
|
1462
|
+
onDelta: (delta) => {
|
|
1463
|
+
sawAnyDelta = true;
|
|
1464
|
+
options.onDelta?.(delta);
|
|
1465
|
+
}
|
|
1466
|
+
});
|
|
1467
|
+
} catch (error) {
|
|
1468
|
+
if (!sawAnyDelta && !retriedViaSseFallback && shouldRetryViaSseFallback(error) && !chatGptResponsesWebSocketDisabled) {
|
|
1469
|
+
chatGptResponsesWebSocketDisabled = true;
|
|
1470
|
+
retriedViaSseFallback = true;
|
|
1471
|
+
continue;
|
|
1472
|
+
}
|
|
1473
|
+
if (!retriedWithoutReasoningSummary && shouldRetryWithoutReasoningSummary(requestForAttempt, error)) {
|
|
1474
|
+
requestForAttempt = removeReasoningSummary(requestForAttempt);
|
|
1475
|
+
retriedWithoutReasoningSummary = true;
|
|
1476
|
+
continue;
|
|
1477
|
+
}
|
|
820
1478
|
throw error;
|
|
821
1479
|
}
|
|
822
1480
|
}
|
|
1481
|
+
}
|
|
1482
|
+
async function collectChatGptCodexStream(options) {
|
|
823
1483
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
824
1484
|
const toolCallOrder = [];
|
|
825
1485
|
const webSearchCalls = /* @__PURE__ */ new Map();
|
|
@@ -832,7 +1492,7 @@ async function collectChatGptCodexResponse(options) {
|
|
|
832
1492
|
let model;
|
|
833
1493
|
let status;
|
|
834
1494
|
let blocked = false;
|
|
835
|
-
for await (const event of stream) {
|
|
1495
|
+
for await (const event of options.stream) {
|
|
836
1496
|
const type = typeof event.type === "string" ? event.type : void 0;
|
|
837
1497
|
if (type === "response.output_text.delta") {
|
|
838
1498
|
const delta = typeof event.delta === "string" ? event.delta : "";
|
|
@@ -956,6 +1616,16 @@ function shouldRetryWithoutReasoningSummary(request, error) {
|
|
|
956
1616
|
const message = error.message.toLowerCase();
|
|
957
1617
|
return message.includes("unsupported parameter") && message.includes("reasoning.summary");
|
|
958
1618
|
}
|
|
1619
|
+
function shouldRetryViaSseFallback(error) {
|
|
1620
|
+
if (!(error instanceof Error)) {
|
|
1621
|
+
return false;
|
|
1622
|
+
}
|
|
1623
|
+
if (error.name === "AbortError") {
|
|
1624
|
+
return false;
|
|
1625
|
+
}
|
|
1626
|
+
const message = error.message.toLowerCase();
|
|
1627
|
+
return message.includes("responses websocket");
|
|
1628
|
+
}
|
|
959
1629
|
function removeReasoningSummary(request) {
|
|
960
1630
|
const reasoning = request.reasoning;
|
|
961
1631
|
if (!reasoning?.summary) {
|
|
@@ -1203,14 +1873,16 @@ async function runFireworksCall(fn) {
|
|
|
1203
1873
|
}
|
|
1204
1874
|
|
|
1205
1875
|
// src/fireworks/models.ts
|
|
1206
|
-
var FIREWORKS_MODEL_IDS = ["kimi-k2.5", "glm-5", "minimax-m2.1"];
|
|
1876
|
+
var FIREWORKS_MODEL_IDS = ["kimi-k2.5", "glm-5", "minimax-m2.1", "gpt-oss-120b"];
|
|
1207
1877
|
var FIREWORKS_DEFAULT_KIMI_MODEL = "kimi-k2.5";
|
|
1208
1878
|
var FIREWORKS_DEFAULT_GLM_MODEL = "glm-5";
|
|
1209
1879
|
var FIREWORKS_DEFAULT_MINIMAX_MODEL = "minimax-m2.1";
|
|
1880
|
+
var FIREWORKS_DEFAULT_GPT_OSS_120B_MODEL = "gpt-oss-120b";
|
|
1210
1881
|
var FIREWORKS_CANONICAL_MODEL_IDS = {
|
|
1211
1882
|
"kimi-k2.5": "accounts/fireworks/models/kimi-k2p5",
|
|
1212
1883
|
"glm-5": "accounts/fireworks/models/glm-5",
|
|
1213
|
-
"minimax-m2.1": "accounts/fireworks/models/minimax-m2p1"
|
|
1884
|
+
"minimax-m2.1": "accounts/fireworks/models/minimax-m2p1",
|
|
1885
|
+
"gpt-oss-120b": "accounts/fireworks/models/gpt-oss-120b"
|
|
1214
1886
|
};
|
|
1215
1887
|
function isFireworksModelId(value) {
|
|
1216
1888
|
return FIREWORKS_MODEL_IDS.includes(value.trim());
|
|
@@ -1289,16 +1961,25 @@ function getGoogleAuthOptions(scopes) {
|
|
|
1289
1961
|
}
|
|
1290
1962
|
|
|
1291
1963
|
// src/google/client.ts
|
|
1292
|
-
var
|
|
1964
|
+
var GEMINI_TEXT_MODEL_IDS = [
|
|
1293
1965
|
"gemini-3-pro-preview",
|
|
1966
|
+
"gemini-3.1-pro-preview",
|
|
1294
1967
|
"gemini-3-flash-preview",
|
|
1295
1968
|
"gemini-2.5-pro",
|
|
1296
1969
|
"gemini-flash-latest",
|
|
1297
1970
|
"gemini-flash-lite-latest"
|
|
1298
1971
|
];
|
|
1972
|
+
var GEMINI_IMAGE_MODEL_IDS = ["gemini-3-pro-image-preview"];
|
|
1973
|
+
var GEMINI_MODEL_IDS = [...GEMINI_TEXT_MODEL_IDS, ...GEMINI_IMAGE_MODEL_IDS];
|
|
1299
1974
|
function isGeminiModelId(value) {
|
|
1300
1975
|
return GEMINI_MODEL_IDS.includes(value);
|
|
1301
1976
|
}
|
|
1977
|
+
function isGeminiTextModelId(value) {
|
|
1978
|
+
return GEMINI_TEXT_MODEL_IDS.includes(value);
|
|
1979
|
+
}
|
|
1980
|
+
function isGeminiImageModelId(value) {
|
|
1981
|
+
return GEMINI_IMAGE_MODEL_IDS.includes(value);
|
|
1982
|
+
}
|
|
1302
1983
|
var CLOUD_PLATFORM_SCOPE = "https://www.googleapis.com/auth/cloud-platform";
|
|
1303
1984
|
var DEFAULT_VERTEX_LOCATION = "global";
|
|
1304
1985
|
var geminiConfiguration = {};
|
|
@@ -1557,6 +2238,8 @@ var cachedApiKey2 = null;
|
|
|
1557
2238
|
var cachedClient2 = null;
|
|
1558
2239
|
var cachedFetch2 = null;
|
|
1559
2240
|
var cachedTimeoutMs2 = null;
|
|
2241
|
+
var openAiResponsesWebSocketMode = null;
|
|
2242
|
+
var openAiResponsesWebSocketDisabled = false;
|
|
1560
2243
|
var DEFAULT_OPENAI_TIMEOUT_MS = 15 * 6e4;
|
|
1561
2244
|
function resolveOpenAiTimeoutMs() {
|
|
1562
2245
|
if (cachedTimeoutMs2 !== null) {
|
|
@@ -1584,6 +2267,97 @@ function getOpenAiFetch() {
|
|
|
1584
2267
|
});
|
|
1585
2268
|
return cachedFetch2;
|
|
1586
2269
|
}
|
|
2270
|
+
function resolveOpenAiBaseUrl() {
|
|
2271
|
+
loadLocalEnv();
|
|
2272
|
+
return process.env.OPENAI_BASE_URL?.trim() || "https://api.openai.com/v1";
|
|
2273
|
+
}
|
|
2274
|
+
function resolveOpenAiResponsesWebSocketMode() {
|
|
2275
|
+
if (openAiResponsesWebSocketMode) {
|
|
2276
|
+
return openAiResponsesWebSocketMode;
|
|
2277
|
+
}
|
|
2278
|
+
loadLocalEnv();
|
|
2279
|
+
openAiResponsesWebSocketMode = resolveResponsesWebSocketMode(
|
|
2280
|
+
process.env.OPENAI_RESPONSES_WEBSOCKET_MODE,
|
|
2281
|
+
"auto"
|
|
2282
|
+
);
|
|
2283
|
+
return openAiResponsesWebSocketMode;
|
|
2284
|
+
}
|
|
2285
|
+
function wrapFallbackStream(stream) {
|
|
2286
|
+
return {
|
|
2287
|
+
async *[Symbol.asyncIterator]() {
|
|
2288
|
+
for await (const event of stream) {
|
|
2289
|
+
yield event;
|
|
2290
|
+
}
|
|
2291
|
+
},
|
|
2292
|
+
async finalResponse() {
|
|
2293
|
+
return await stream.finalResponse();
|
|
2294
|
+
},
|
|
2295
|
+
close() {
|
|
2296
|
+
const maybeClose = stream;
|
|
2297
|
+
if (typeof maybeClose.close === "function") {
|
|
2298
|
+
maybeClose.close();
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
};
|
|
2302
|
+
}
|
|
2303
|
+
function buildOpenAiResponsesEndpointUrl() {
|
|
2304
|
+
const base = resolveOpenAiBaseUrl();
|
|
2305
|
+
const normalized = base.endsWith("/") ? base : `${base}/`;
|
|
2306
|
+
return new URL("responses", normalized).toString();
|
|
2307
|
+
}
|
|
2308
|
+
function buildOpenAiResponsesWebSocketHeaders(apiKey) {
|
|
2309
|
+
const headers = {
|
|
2310
|
+
Authorization: `Bearer ${apiKey}`,
|
|
2311
|
+
"OpenAI-Beta": mergeOpenAiBetaHeader(
|
|
2312
|
+
process.env.OPENAI_BETA,
|
|
2313
|
+
OPENAI_BETA_RESPONSES_WEBSOCKETS_V2
|
|
2314
|
+
)
|
|
2315
|
+
};
|
|
2316
|
+
const organization = process.env.OPENAI_ORGANIZATION?.trim();
|
|
2317
|
+
if (organization) {
|
|
2318
|
+
headers["OpenAI-Organization"] = organization;
|
|
2319
|
+
}
|
|
2320
|
+
const project = process.env.OPENAI_PROJECT?.trim();
|
|
2321
|
+
if (project) {
|
|
2322
|
+
headers["OpenAI-Project"] = project;
|
|
2323
|
+
}
|
|
2324
|
+
return headers;
|
|
2325
|
+
}
|
|
2326
|
+
function installResponsesWebSocketTransport(client, apiKey) {
|
|
2327
|
+
const responsesApi = client.responses;
|
|
2328
|
+
const streamMethod = responsesApi?.stream;
|
|
2329
|
+
if (typeof streamMethod !== "function") {
|
|
2330
|
+
return;
|
|
2331
|
+
}
|
|
2332
|
+
const originalStream = streamMethod.bind(client.responses);
|
|
2333
|
+
responsesApi.stream = (request, options) => {
|
|
2334
|
+
const mode = resolveOpenAiResponsesWebSocketMode();
|
|
2335
|
+
const fallbackStreamFactory = () => wrapFallbackStream(originalStream(request, options));
|
|
2336
|
+
if (mode === "off" || openAiResponsesWebSocketDisabled) {
|
|
2337
|
+
return fallbackStreamFactory();
|
|
2338
|
+
}
|
|
2339
|
+
const signal = options && typeof options === "object" ? options.signal ?? void 0 : void 0;
|
|
2340
|
+
const websocketUrl = toWebSocketUrl(buildOpenAiResponsesEndpointUrl());
|
|
2341
|
+
const headers = buildOpenAiResponsesWebSocketHeaders(apiKey);
|
|
2342
|
+
const timeoutMs = resolveOpenAiTimeoutMs();
|
|
2343
|
+
return createAdaptiveResponsesStream({
|
|
2344
|
+
mode,
|
|
2345
|
+
createWebSocketStream: async () => await createResponsesWebSocketStream({
|
|
2346
|
+
url: websocketUrl,
|
|
2347
|
+
headers,
|
|
2348
|
+
request,
|
|
2349
|
+
signal,
|
|
2350
|
+
idleTimeoutMs: timeoutMs
|
|
2351
|
+
}),
|
|
2352
|
+
createFallbackStream: fallbackStreamFactory,
|
|
2353
|
+
onWebSocketFallback: (error) => {
|
|
2354
|
+
if (isResponsesWebSocketUnsupportedError(error)) {
|
|
2355
|
+
openAiResponsesWebSocketDisabled = true;
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
});
|
|
2359
|
+
};
|
|
2360
|
+
}
|
|
1587
2361
|
function getOpenAiApiKey() {
|
|
1588
2362
|
if (cachedApiKey2 !== null) {
|
|
1589
2363
|
return cachedApiKey2;
|
|
@@ -1601,6 +2375,7 @@ function getOpenAiClient() {
|
|
|
1601
2375
|
if (cachedClient2) {
|
|
1602
2376
|
return cachedClient2;
|
|
1603
2377
|
}
|
|
2378
|
+
loadLocalEnv();
|
|
1604
2379
|
const apiKey = getOpenAiApiKey();
|
|
1605
2380
|
const timeoutMs = resolveOpenAiTimeoutMs();
|
|
1606
2381
|
cachedClient2 = new import_openai2.default({
|
|
@@ -1608,6 +2383,7 @@ function getOpenAiClient() {
|
|
|
1608
2383
|
fetch: getOpenAiFetch(),
|
|
1609
2384
|
timeout: timeoutMs
|
|
1610
2385
|
});
|
|
2386
|
+
installResponsesWebSocketTransport(cachedClient2, apiKey);
|
|
1611
2387
|
return cachedClient2;
|
|
1612
2388
|
}
|
|
1613
2389
|
|
|
@@ -1622,11 +2398,51 @@ async function runOpenAiCall(fn) {
|
|
|
1622
2398
|
return scheduler3.run(async () => fn(getOpenAiClient()));
|
|
1623
2399
|
}
|
|
1624
2400
|
|
|
2401
|
+
// src/openai/models.ts
|
|
2402
|
+
var OPENAI_MODEL_IDS = [
|
|
2403
|
+
"gpt-5.3-codex",
|
|
2404
|
+
"gpt-5.3-codex-spark",
|
|
2405
|
+
"gpt-5.2",
|
|
2406
|
+
"gpt-5.1-codex-mini"
|
|
2407
|
+
];
|
|
2408
|
+
function isOpenAiModelId(value) {
|
|
2409
|
+
return OPENAI_MODEL_IDS.includes(value);
|
|
2410
|
+
}
|
|
2411
|
+
var CHATGPT_MODEL_IDS = [
|
|
2412
|
+
"chatgpt-gpt-5.3-codex",
|
|
2413
|
+
"chatgpt-gpt-5.3-codex-spark",
|
|
2414
|
+
"chatgpt-gpt-5.2",
|
|
2415
|
+
"chatgpt-gpt-5.1-codex-mini"
|
|
2416
|
+
];
|
|
2417
|
+
function isChatGptModelId(value) {
|
|
2418
|
+
return CHATGPT_MODEL_IDS.includes(value);
|
|
2419
|
+
}
|
|
2420
|
+
function stripChatGptPrefix(model) {
|
|
2421
|
+
return model.slice("chatgpt-".length);
|
|
2422
|
+
}
|
|
2423
|
+
|
|
1625
2424
|
// src/llm.ts
|
|
1626
2425
|
var toolCallContextStorage = new import_node_async_hooks.AsyncLocalStorage();
|
|
1627
2426
|
function getCurrentToolCallContext() {
|
|
1628
2427
|
return toolCallContextStorage.getStore() ?? null;
|
|
1629
2428
|
}
|
|
2429
|
+
var LLM_TEXT_MODEL_IDS = [
|
|
2430
|
+
...OPENAI_MODEL_IDS,
|
|
2431
|
+
...CHATGPT_MODEL_IDS,
|
|
2432
|
+
...FIREWORKS_MODEL_IDS,
|
|
2433
|
+
...GEMINI_TEXT_MODEL_IDS
|
|
2434
|
+
];
|
|
2435
|
+
var LLM_IMAGE_MODEL_IDS = [...GEMINI_IMAGE_MODEL_IDS];
|
|
2436
|
+
var LLM_MODEL_IDS = [...LLM_TEXT_MODEL_IDS, ...LLM_IMAGE_MODEL_IDS];
|
|
2437
|
+
function isLlmTextModelId(value) {
|
|
2438
|
+
return isOpenAiModelId(value) || isChatGptModelId(value) || isFireworksModelId(value) || isGeminiTextModelId(value);
|
|
2439
|
+
}
|
|
2440
|
+
function isLlmImageModelId(value) {
|
|
2441
|
+
return isGeminiImageModelId(value);
|
|
2442
|
+
}
|
|
2443
|
+
function isLlmModelId(value) {
|
|
2444
|
+
return isLlmTextModelId(value) || isLlmImageModelId(value);
|
|
2445
|
+
}
|
|
1630
2446
|
var LlmJsonCallError = class extends Error {
|
|
1631
2447
|
constructor(message, attempts) {
|
|
1632
2448
|
super(message);
|
|
@@ -1984,17 +2800,22 @@ function convertLlmContentToGeminiContent(content) {
|
|
|
1984
2800
|
};
|
|
1985
2801
|
}
|
|
1986
2802
|
function resolveProvider(model) {
|
|
1987
|
-
if (model
|
|
1988
|
-
return { provider: "chatgpt", model: model
|
|
2803
|
+
if (isChatGptModelId(model)) {
|
|
2804
|
+
return { provider: "chatgpt", model: stripChatGptPrefix(model) };
|
|
1989
2805
|
}
|
|
1990
|
-
if (model
|
|
2806
|
+
if (isGeminiTextModelId(model) || isGeminiImageModelId(model)) {
|
|
1991
2807
|
return { provider: "gemini", model };
|
|
1992
2808
|
}
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
2809
|
+
if (isFireworksModelId(model)) {
|
|
2810
|
+
const fireworksModel = resolveFireworksModelId(model);
|
|
2811
|
+
if (fireworksModel) {
|
|
2812
|
+
return { provider: "fireworks", model: fireworksModel };
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
if (isOpenAiModelId(model)) {
|
|
2816
|
+
return { provider: "openai", model };
|
|
1996
2817
|
}
|
|
1997
|
-
|
|
2818
|
+
throw new Error(`Unsupported text model: ${model}`);
|
|
1998
2819
|
}
|
|
1999
2820
|
function isOpenAiCodexModel(modelId) {
|
|
2000
2821
|
return modelId.includes("codex");
|
|
@@ -3181,6 +4002,7 @@ function extractFireworksToolCalls(message) {
|
|
|
3181
4002
|
function resolveGeminiThinkingConfig(modelId) {
|
|
3182
4003
|
switch (modelId) {
|
|
3183
4004
|
case "gemini-3-pro-preview":
|
|
4005
|
+
case "gemini-3.1-pro-preview":
|
|
3184
4006
|
return { includeThoughts: true };
|
|
3185
4007
|
case "gemini-3-flash-preview":
|
|
3186
4008
|
return { includeThoughts: true, thinkingBudget: 16384 };
|
|
@@ -6577,15 +7399,24 @@ function mergeToolSets(base, extra) {
|
|
|
6577
7399
|
}
|
|
6578
7400
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6579
7401
|
0 && (module.exports = {
|
|
7402
|
+
CHATGPT_MODEL_IDS,
|
|
6580
7403
|
CODEX_APPLY_PATCH_FREEFORM_TOOL_DESCRIPTION,
|
|
6581
7404
|
CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION,
|
|
6582
7405
|
CODEX_APPLY_PATCH_LARK_GRAMMAR,
|
|
6583
7406
|
FIREWORKS_DEFAULT_GLM_MODEL,
|
|
7407
|
+
FIREWORKS_DEFAULT_GPT_OSS_120B_MODEL,
|
|
6584
7408
|
FIREWORKS_DEFAULT_KIMI_MODEL,
|
|
6585
7409
|
FIREWORKS_DEFAULT_MINIMAX_MODEL,
|
|
6586
7410
|
FIREWORKS_MODEL_IDS,
|
|
7411
|
+
GEMINI_IMAGE_MODEL_IDS,
|
|
7412
|
+
GEMINI_MODEL_IDS,
|
|
7413
|
+
GEMINI_TEXT_MODEL_IDS,
|
|
6587
7414
|
InMemoryAgentFilesystem,
|
|
7415
|
+
LLM_IMAGE_MODEL_IDS,
|
|
7416
|
+
LLM_MODEL_IDS,
|
|
7417
|
+
LLM_TEXT_MODEL_IDS,
|
|
6588
7418
|
LlmJsonCallError,
|
|
7419
|
+
OPENAI_MODEL_IDS,
|
|
6589
7420
|
appendMarkdownSourcesSection,
|
|
6590
7421
|
applyPatch,
|
|
6591
7422
|
configureGemini,
|
|
@@ -6620,8 +7451,15 @@ function mergeToolSets(base, extra) {
|
|
|
6620
7451
|
generateText,
|
|
6621
7452
|
getChatGptAuthProfile,
|
|
6622
7453
|
getCurrentToolCallContext,
|
|
7454
|
+
isChatGptModelId,
|
|
6623
7455
|
isFireworksModelId,
|
|
7456
|
+
isGeminiImageModelId,
|
|
6624
7457
|
isGeminiModelId,
|
|
7458
|
+
isGeminiTextModelId,
|
|
7459
|
+
isLlmImageModelId,
|
|
7460
|
+
isLlmModelId,
|
|
7461
|
+
isLlmTextModelId,
|
|
7462
|
+
isOpenAiModelId,
|
|
6625
7463
|
loadEnvFromFile,
|
|
6626
7464
|
loadLocalEnv,
|
|
6627
7465
|
parseJsonFromLlmText,
|