@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.js
CHANGED
|
@@ -136,7 +136,7 @@ function getGeminiProPricing(modelId) {
|
|
|
136
136
|
if (modelId.includes("gemini-2.5-pro")) {
|
|
137
137
|
return GEMINI_2_5_PRO_PRICING;
|
|
138
138
|
}
|
|
139
|
-
if (modelId.includes("gemini-3-pro")) {
|
|
139
|
+
if (modelId.includes("gemini-3-pro") || modelId.includes("gemini-3.1-pro")) {
|
|
140
140
|
return GEMINI_3_PRO_PREVIEW_PRICING;
|
|
141
141
|
}
|
|
142
142
|
return void 0;
|
|
@@ -336,8 +336,6 @@ function parseEnvLine(line) {
|
|
|
336
336
|
// src/openai/chatgpt-auth.ts
|
|
337
337
|
var CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_URL";
|
|
338
338
|
var CHATGPT_AUTH_TOKEN_PROVIDER_STORE_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_STORE";
|
|
339
|
-
var CHATGPT_AUTH_SERVER_URL_ENV = "CHATGPT_AUTH_SERVER_URL";
|
|
340
|
-
var CHATGPT_AUTH_SERVER_STORE_ENV = "CHATGPT_AUTH_SERVER_STORE";
|
|
341
339
|
var CHATGPT_AUTH_API_KEY_ENV = "CHATGPT_AUTH_API_KEY";
|
|
342
340
|
var CHATGPT_AUTH_TOKEN_PROVIDER_API_KEY_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_API_KEY";
|
|
343
341
|
var CHATGPT_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
@@ -469,7 +467,7 @@ async function refreshChatGptOauthToken(refreshToken, fallback) {
|
|
|
469
467
|
}
|
|
470
468
|
async function getChatGptAuthProfile() {
|
|
471
469
|
loadLocalEnv();
|
|
472
|
-
const tokenProviderUrl = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV]
|
|
470
|
+
const tokenProviderUrl = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV];
|
|
473
471
|
const tokenProviderKey = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_API_KEY_ENV] ?? process.env[CHATGPT_AUTH_API_KEY_ENV];
|
|
474
472
|
if (tokenProviderUrl && tokenProviderUrl.trim().length > 0 && tokenProviderKey && tokenProviderKey.trim().length > 0) {
|
|
475
473
|
if (cachedProfile && !isExpired(cachedProfile)) {
|
|
@@ -480,7 +478,7 @@ async function getChatGptAuthProfile() {
|
|
|
480
478
|
}
|
|
481
479
|
refreshPromise = (async () => {
|
|
482
480
|
try {
|
|
483
|
-
const store = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_STORE_ENV]
|
|
481
|
+
const store = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_STORE_ENV];
|
|
484
482
|
const profile = await fetchChatGptAuthProfileFromTokenProvider({
|
|
485
483
|
baseUrl: tokenProviderUrl,
|
|
486
484
|
apiKey: tokenProviderKey,
|
|
@@ -683,22 +681,588 @@ function extractChatGptAccountId(token) {
|
|
|
683
681
|
return typeof namespaced === "string" && namespaced.length > 0 ? namespaced : void 0;
|
|
684
682
|
}
|
|
685
683
|
|
|
684
|
+
// src/openai/responses-websocket.ts
|
|
685
|
+
import WebSocket from "ws";
|
|
686
|
+
var OPENAI_BETA_RESPONSES_WEBSOCKETS_V2 = "responses_websockets=2026-02-06";
|
|
687
|
+
var ResponsesWebSocketHttpError = class extends Error {
|
|
688
|
+
status;
|
|
689
|
+
body;
|
|
690
|
+
headers;
|
|
691
|
+
constructor(options) {
|
|
692
|
+
super(options.message);
|
|
693
|
+
this.name = "ResponsesWebSocketHttpError";
|
|
694
|
+
this.status = options.status;
|
|
695
|
+
this.body = options.body;
|
|
696
|
+
this.headers = options.headers;
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
function resolveResponsesWebSocketMode(raw, fallback = "auto") {
|
|
700
|
+
const value = raw?.trim().toLowerCase();
|
|
701
|
+
if (value === "auto" || value === "off" || value === "only") {
|
|
702
|
+
return value;
|
|
703
|
+
}
|
|
704
|
+
return fallback;
|
|
705
|
+
}
|
|
706
|
+
function mergeOpenAiBetaHeader(existing, required) {
|
|
707
|
+
const parts = /* @__PURE__ */ new Set();
|
|
708
|
+
for (const part of (existing ?? "").split(",")) {
|
|
709
|
+
const trimmed = part.trim();
|
|
710
|
+
if (trimmed.length > 0) {
|
|
711
|
+
parts.add(trimmed);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
const normalizedRequired = required.trim();
|
|
715
|
+
if (normalizedRequired.length > 0) {
|
|
716
|
+
parts.add(normalizedRequired);
|
|
717
|
+
}
|
|
718
|
+
return Array.from(parts).join(", ");
|
|
719
|
+
}
|
|
720
|
+
function toWebSocketUrl(httpOrHttpsUrl) {
|
|
721
|
+
const parsed = new URL(httpOrHttpsUrl);
|
|
722
|
+
if (parsed.protocol === "https:") {
|
|
723
|
+
parsed.protocol = "wss:";
|
|
724
|
+
} else if (parsed.protocol === "http:") {
|
|
725
|
+
parsed.protocol = "ws:";
|
|
726
|
+
} else if (parsed.protocol !== "ws:" && parsed.protocol !== "wss:") {
|
|
727
|
+
throw new Error(`Unsupported websocket URL protocol: ${parsed.protocol}`);
|
|
728
|
+
}
|
|
729
|
+
return parsed.toString();
|
|
730
|
+
}
|
|
731
|
+
function isResponsesWebSocketUnsupportedError(error) {
|
|
732
|
+
if (error instanceof ResponsesWebSocketHttpError) {
|
|
733
|
+
return [400, 404, 405, 406, 426, 501].includes(error.status);
|
|
734
|
+
}
|
|
735
|
+
const message = error instanceof Error ? error.message.toLowerCase() : "";
|
|
736
|
+
return message.includes("unexpected server response: 426");
|
|
737
|
+
}
|
|
738
|
+
function createAdaptiveResponsesStream(options) {
|
|
739
|
+
let resolved = null;
|
|
740
|
+
let websocketSelected = false;
|
|
741
|
+
let fallbackSelected = false;
|
|
742
|
+
const activateFallback = (error) => {
|
|
743
|
+
options.onWebSocketFallback?.(error);
|
|
744
|
+
fallbackSelected = true;
|
|
745
|
+
websocketSelected = false;
|
|
746
|
+
const fallback = options.createFallbackStream();
|
|
747
|
+
resolved = Promise.resolve(fallback);
|
|
748
|
+
return fallback;
|
|
749
|
+
};
|
|
750
|
+
const getStream = async () => {
|
|
751
|
+
if (resolved) {
|
|
752
|
+
return await resolved;
|
|
753
|
+
}
|
|
754
|
+
resolved = (async () => {
|
|
755
|
+
if (options.mode === "off") {
|
|
756
|
+
fallbackSelected = true;
|
|
757
|
+
return options.createFallbackStream();
|
|
758
|
+
}
|
|
759
|
+
try {
|
|
760
|
+
const stream = await options.createWebSocketStream();
|
|
761
|
+
websocketSelected = true;
|
|
762
|
+
return stream;
|
|
763
|
+
} catch (error) {
|
|
764
|
+
if (options.mode === "only") {
|
|
765
|
+
throw error;
|
|
766
|
+
}
|
|
767
|
+
return activateFallback(error);
|
|
768
|
+
}
|
|
769
|
+
})();
|
|
770
|
+
return await resolved;
|
|
771
|
+
};
|
|
772
|
+
return {
|
|
773
|
+
async *[Symbol.asyncIterator]() {
|
|
774
|
+
const stream = await getStream();
|
|
775
|
+
let yielded = 0;
|
|
776
|
+
try {
|
|
777
|
+
for await (const event of stream) {
|
|
778
|
+
yielded += 1;
|
|
779
|
+
yield event;
|
|
780
|
+
}
|
|
781
|
+
} catch (error) {
|
|
782
|
+
if (options.mode !== "only" && websocketSelected && !fallbackSelected && yielded === 0) {
|
|
783
|
+
const fallback = activateFallback(error);
|
|
784
|
+
for await (const event of fallback) {
|
|
785
|
+
yield event;
|
|
786
|
+
}
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
throw error;
|
|
790
|
+
}
|
|
791
|
+
},
|
|
792
|
+
async finalResponse() {
|
|
793
|
+
const stream = await getStream();
|
|
794
|
+
try {
|
|
795
|
+
return await stream.finalResponse();
|
|
796
|
+
} catch (error) {
|
|
797
|
+
if (options.mode === "only" || !websocketSelected || fallbackSelected) {
|
|
798
|
+
throw error;
|
|
799
|
+
}
|
|
800
|
+
const fallback = activateFallback(error);
|
|
801
|
+
return await fallback.finalResponse();
|
|
802
|
+
}
|
|
803
|
+
},
|
|
804
|
+
close() {
|
|
805
|
+
void getStream().then((stream) => stream.close()).catch(() => {
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
async function createResponsesWebSocketStream(options) {
|
|
811
|
+
const completionTypes = new Set(
|
|
812
|
+
options.completionEventTypes ?? ["response.completed", "response.failed", "response.done"]
|
|
813
|
+
);
|
|
814
|
+
const { socket, responseHeaders } = await connectWebSocket({
|
|
815
|
+
url: options.url,
|
|
816
|
+
headers: options.headers,
|
|
817
|
+
signal: options.signal
|
|
818
|
+
});
|
|
819
|
+
const queue = createAsyncQueue();
|
|
820
|
+
let settled = false;
|
|
821
|
+
let finalResponse = null;
|
|
822
|
+
let latestResponse = null;
|
|
823
|
+
let idleTimer = null;
|
|
824
|
+
let resolveFinal = null;
|
|
825
|
+
let rejectFinal = null;
|
|
826
|
+
const finalPromise = new Promise((resolve, reject) => {
|
|
827
|
+
resolveFinal = resolve;
|
|
828
|
+
rejectFinal = reject;
|
|
829
|
+
});
|
|
830
|
+
void finalPromise.catch(() => {
|
|
831
|
+
});
|
|
832
|
+
const clearIdleTimer = () => {
|
|
833
|
+
if (idleTimer) {
|
|
834
|
+
clearTimeout(idleTimer);
|
|
835
|
+
idleTimer = null;
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
const closeSocket = () => {
|
|
839
|
+
try {
|
|
840
|
+
if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
|
|
841
|
+
socket.close();
|
|
842
|
+
}
|
|
843
|
+
} catch {
|
|
844
|
+
}
|
|
845
|
+
};
|
|
846
|
+
const complete = (response) => {
|
|
847
|
+
if (settled) {
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
settled = true;
|
|
851
|
+
clearIdleTimer();
|
|
852
|
+
finalResponse = response;
|
|
853
|
+
resolveFinal?.(response);
|
|
854
|
+
queue.close();
|
|
855
|
+
closeSocket();
|
|
856
|
+
};
|
|
857
|
+
const fail = (error) => {
|
|
858
|
+
if (settled) {
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
settled = true;
|
|
862
|
+
clearIdleTimer();
|
|
863
|
+
rejectFinal?.(error);
|
|
864
|
+
queue.fail(error);
|
|
865
|
+
closeSocket();
|
|
866
|
+
};
|
|
867
|
+
const restartIdleTimer = () => {
|
|
868
|
+
clearIdleTimer();
|
|
869
|
+
const idleTimeoutMs = options.idleTimeoutMs;
|
|
870
|
+
if (!idleTimeoutMs || idleTimeoutMs <= 0 || settled) {
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
idleTimer = setTimeout(() => {
|
|
874
|
+
fail(new Error(`Responses WebSocket idle timeout after ${idleTimeoutMs}ms.`));
|
|
875
|
+
}, idleTimeoutMs);
|
|
876
|
+
};
|
|
877
|
+
const onAbort = () => {
|
|
878
|
+
const error = createAbortError(options.signal?.reason);
|
|
879
|
+
fail(error);
|
|
880
|
+
};
|
|
881
|
+
if (options.signal) {
|
|
882
|
+
if (options.signal.aborted) {
|
|
883
|
+
socket.close();
|
|
884
|
+
throw createAbortError(options.signal.reason);
|
|
885
|
+
}
|
|
886
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
887
|
+
}
|
|
888
|
+
const cleanup = () => {
|
|
889
|
+
clearIdleTimer();
|
|
890
|
+
socket.removeAllListeners();
|
|
891
|
+
if (options.signal) {
|
|
892
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
socket.on("message", (raw) => {
|
|
896
|
+
restartIdleTimer();
|
|
897
|
+
const parsed = parseWebSocketPayload(raw);
|
|
898
|
+
if (!parsed) {
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
const error = mapWebSocketErrorEvent(parsed);
|
|
902
|
+
if (error) {
|
|
903
|
+
fail(error);
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
const event = parsed;
|
|
907
|
+
if (isObjectWithResponse(event)) {
|
|
908
|
+
latestResponse = event.response;
|
|
909
|
+
}
|
|
910
|
+
queue.push(event);
|
|
911
|
+
const type = typeof event.type === "string" ? event.type : "";
|
|
912
|
+
if (completionTypes.has(type)) {
|
|
913
|
+
const completedResponse = normalizeFinalResponse(
|
|
914
|
+
type,
|
|
915
|
+
event.response,
|
|
916
|
+
latestResponse,
|
|
917
|
+
responseHeaders
|
|
918
|
+
);
|
|
919
|
+
complete(completedResponse);
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
socket.on("error", (error) => {
|
|
923
|
+
fail(new Error(`Responses WebSocket error: ${error.message}`));
|
|
924
|
+
});
|
|
925
|
+
socket.on("close", (_code, _reason) => {
|
|
926
|
+
if (settled) {
|
|
927
|
+
cleanup();
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
fail(new Error("Responses WebSocket closed before completion."));
|
|
931
|
+
cleanup();
|
|
932
|
+
});
|
|
933
|
+
restartIdleTimer();
|
|
934
|
+
const payload = serializeRequestPayload(options.request);
|
|
935
|
+
await new Promise((resolve, reject) => {
|
|
936
|
+
socket.send(payload, (error) => {
|
|
937
|
+
if (error) {
|
|
938
|
+
reject(error);
|
|
939
|
+
} else {
|
|
940
|
+
resolve();
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
}).catch((error) => {
|
|
944
|
+
fail(new Error(`Failed to send Responses WebSocket request: ${errorToMessage(error)}`));
|
|
945
|
+
throw error instanceof Error ? error : new Error(errorToMessage(error));
|
|
946
|
+
});
|
|
947
|
+
return {
|
|
948
|
+
async *[Symbol.asyncIterator]() {
|
|
949
|
+
try {
|
|
950
|
+
for await (const event of queue.iterable) {
|
|
951
|
+
yield event;
|
|
952
|
+
}
|
|
953
|
+
} finally {
|
|
954
|
+
if (!settled) {
|
|
955
|
+
closeSocket();
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
},
|
|
959
|
+
async finalResponse() {
|
|
960
|
+
return await finalPromise;
|
|
961
|
+
},
|
|
962
|
+
close() {
|
|
963
|
+
if (settled) {
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
const response = finalResponse ?? latestResponse ?? { status: "cancelled" };
|
|
967
|
+
complete(response);
|
|
968
|
+
cleanup();
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
async function connectWebSocket(options) {
|
|
973
|
+
return await new Promise((resolve, reject) => {
|
|
974
|
+
const socket = new WebSocket(options.url, {
|
|
975
|
+
headers: options.headers,
|
|
976
|
+
handshakeTimeout: 3e4
|
|
977
|
+
});
|
|
978
|
+
let settled = false;
|
|
979
|
+
let responseBody = "";
|
|
980
|
+
const rejectOnce = (error) => {
|
|
981
|
+
if (settled) {
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
settled = true;
|
|
985
|
+
cleanup();
|
|
986
|
+
try {
|
|
987
|
+
socket.terminate();
|
|
988
|
+
} catch {
|
|
989
|
+
}
|
|
990
|
+
reject(error);
|
|
991
|
+
};
|
|
992
|
+
const resolveOnce = (result) => {
|
|
993
|
+
if (settled) {
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
settled = true;
|
|
997
|
+
cleanup(false);
|
|
998
|
+
resolve(result);
|
|
999
|
+
};
|
|
1000
|
+
const onAbort = () => {
|
|
1001
|
+
rejectOnce(createAbortError(options.signal?.reason));
|
|
1002
|
+
};
|
|
1003
|
+
const cleanup = (removeAbortListener = true) => {
|
|
1004
|
+
socket.removeListener("open", onOpen);
|
|
1005
|
+
socket.removeListener("error", onError);
|
|
1006
|
+
socket.removeListener("unexpected-response", onUnexpectedResponse);
|
|
1007
|
+
if (removeAbortListener && options.signal) {
|
|
1008
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
const onOpen = () => {
|
|
1012
|
+
const headers = normalizeUpgradeHeaders(socket);
|
|
1013
|
+
resolveOnce({ socket, responseHeaders: headers });
|
|
1014
|
+
};
|
|
1015
|
+
const onError = (error) => {
|
|
1016
|
+
rejectOnce(new Error(`Responses WebSocket connection failed: ${error.message}`));
|
|
1017
|
+
};
|
|
1018
|
+
const onUnexpectedResponse = (_request, response) => {
|
|
1019
|
+
if (typeof response.setEncoding === "function") {
|
|
1020
|
+
response.setEncoding("utf8");
|
|
1021
|
+
}
|
|
1022
|
+
response.on("data", (chunk) => {
|
|
1023
|
+
responseBody += typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
1024
|
+
});
|
|
1025
|
+
response.on("end", () => {
|
|
1026
|
+
const status = Number(response.statusCode ?? 0);
|
|
1027
|
+
const headers = {};
|
|
1028
|
+
const rawHeaders = response.headers ?? {};
|
|
1029
|
+
for (const [key, value] of Object.entries(rawHeaders)) {
|
|
1030
|
+
if (typeof value === "string") {
|
|
1031
|
+
headers[key] = value;
|
|
1032
|
+
} else if (Array.isArray(value)) {
|
|
1033
|
+
headers[key] = value.join(", ");
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
rejectOnce(
|
|
1037
|
+
new ResponsesWebSocketHttpError({
|
|
1038
|
+
status: Number.isFinite(status) && status > 0 ? status : 500,
|
|
1039
|
+
message: `Responses WebSocket upgrade failed${status ? ` (${status})` : ""}.`,
|
|
1040
|
+
body: responseBody || void 0,
|
|
1041
|
+
headers
|
|
1042
|
+
})
|
|
1043
|
+
);
|
|
1044
|
+
});
|
|
1045
|
+
response.on("error", (error) => {
|
|
1046
|
+
rejectOnce(
|
|
1047
|
+
new ResponsesWebSocketHttpError({
|
|
1048
|
+
status: Number(response.statusCode ?? 500),
|
|
1049
|
+
message: `Responses WebSocket upgrade failed: ${error.message}`,
|
|
1050
|
+
body: responseBody || void 0
|
|
1051
|
+
})
|
|
1052
|
+
);
|
|
1053
|
+
});
|
|
1054
|
+
};
|
|
1055
|
+
socket.once("open", onOpen);
|
|
1056
|
+
socket.once("error", onError);
|
|
1057
|
+
socket.once("unexpected-response", onUnexpectedResponse);
|
|
1058
|
+
if (options.signal) {
|
|
1059
|
+
if (options.signal.aborted) {
|
|
1060
|
+
onAbort();
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1066
|
+
}
|
|
1067
|
+
function normalizeUpgradeHeaders(socket) {
|
|
1068
|
+
const maybeUpgradeResponse = socket._req?.res;
|
|
1069
|
+
const raw = maybeUpgradeResponse?.headers ?? {};
|
|
1070
|
+
const normalized = {};
|
|
1071
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
1072
|
+
if (typeof value === "string") {
|
|
1073
|
+
normalized[key.toLowerCase()] = value;
|
|
1074
|
+
} else if (Array.isArray(value)) {
|
|
1075
|
+
normalized[key.toLowerCase()] = value.join(", ");
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
return normalized;
|
|
1079
|
+
}
|
|
1080
|
+
function parseWebSocketPayload(raw) {
|
|
1081
|
+
const text = toUtf8(raw);
|
|
1082
|
+
if (!text) {
|
|
1083
|
+
return null;
|
|
1084
|
+
}
|
|
1085
|
+
try {
|
|
1086
|
+
const parsed = JSON.parse(text);
|
|
1087
|
+
if (parsed && typeof parsed === "object") {
|
|
1088
|
+
return parsed;
|
|
1089
|
+
}
|
|
1090
|
+
} catch {
|
|
1091
|
+
return null;
|
|
1092
|
+
}
|
|
1093
|
+
return null;
|
|
1094
|
+
}
|
|
1095
|
+
function toUtf8(raw) {
|
|
1096
|
+
if (typeof raw === "string") {
|
|
1097
|
+
return raw;
|
|
1098
|
+
}
|
|
1099
|
+
if (raw instanceof ArrayBuffer) {
|
|
1100
|
+
return Buffer.from(raw).toString("utf8");
|
|
1101
|
+
}
|
|
1102
|
+
if (Array.isArray(raw)) {
|
|
1103
|
+
const chunks = raw.map((chunk) => {
|
|
1104
|
+
if (typeof chunk === "string") {
|
|
1105
|
+
return Buffer.from(chunk, "utf8");
|
|
1106
|
+
}
|
|
1107
|
+
return Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
1108
|
+
});
|
|
1109
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
1110
|
+
}
|
|
1111
|
+
return Buffer.isBuffer(raw) ? raw.toString("utf8") : Buffer.from(raw).toString("utf8");
|
|
1112
|
+
}
|
|
1113
|
+
function mapWebSocketErrorEvent(payload) {
|
|
1114
|
+
if (payload.type !== "error") {
|
|
1115
|
+
return null;
|
|
1116
|
+
}
|
|
1117
|
+
const status = resolveNumericStatus(payload.status) ?? resolveNumericStatus(payload.status_code);
|
|
1118
|
+
if (!status || status < 400) {
|
|
1119
|
+
const message = errorToMessage(payload.error) || "Responses WebSocket returned an error event.";
|
|
1120
|
+
return new Error(message);
|
|
1121
|
+
}
|
|
1122
|
+
const headers = mapErrorHeaders(payload.headers);
|
|
1123
|
+
const body = payload.error && typeof payload.error === "object" ? JSON.stringify({ error: payload.error }, null, 2) : void 0;
|
|
1124
|
+
return new ResponsesWebSocketHttpError({
|
|
1125
|
+
status,
|
|
1126
|
+
message: `Responses WebSocket returned status ${status}.`,
|
|
1127
|
+
body,
|
|
1128
|
+
headers
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
function mapErrorHeaders(value) {
|
|
1132
|
+
if (!value || typeof value !== "object") {
|
|
1133
|
+
return void 0;
|
|
1134
|
+
}
|
|
1135
|
+
const headers = {};
|
|
1136
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
1137
|
+
if (typeof entry === "string" || typeof entry === "number" || typeof entry === "boolean") {
|
|
1138
|
+
headers[key.toLowerCase()] = String(entry);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
return Object.keys(headers).length > 0 ? headers : void 0;
|
|
1142
|
+
}
|
|
1143
|
+
function resolveNumericStatus(value) {
|
|
1144
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1145
|
+
return Math.floor(value);
|
|
1146
|
+
}
|
|
1147
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
1148
|
+
const parsed = Number(value);
|
|
1149
|
+
if (Number.isFinite(parsed)) {
|
|
1150
|
+
return Math.floor(parsed);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
return null;
|
|
1154
|
+
}
|
|
1155
|
+
function normalizeFinalResponse(eventType, eventResponse, latestResponse, responseHeaders) {
|
|
1156
|
+
const response = eventResponse && typeof eventResponse === "object" ? { ...eventResponse } : latestResponse ? { ...latestResponse } : {};
|
|
1157
|
+
if (typeof response.status !== "string") {
|
|
1158
|
+
if (eventType === "response.failed") {
|
|
1159
|
+
response.status = "failed";
|
|
1160
|
+
} else if (eventType === "response.done") {
|
|
1161
|
+
response.status = "completed";
|
|
1162
|
+
} else if (eventType === "response.completed") {
|
|
1163
|
+
response.status = "completed";
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
const upgradeModel = responseHeaders["openai-model"];
|
|
1167
|
+
if (typeof response.model !== "string" && upgradeModel) {
|
|
1168
|
+
response.model = upgradeModel;
|
|
1169
|
+
}
|
|
1170
|
+
return response;
|
|
1171
|
+
}
|
|
1172
|
+
function serializeRequestPayload(request) {
|
|
1173
|
+
if (!request || typeof request !== "object" || Array.isArray(request)) {
|
|
1174
|
+
throw new Error("Responses WebSocket request must be a JSON object.");
|
|
1175
|
+
}
|
|
1176
|
+
const body = request;
|
|
1177
|
+
const payload = typeof body.type === "string" ? body : { type: "response.create", ...body };
|
|
1178
|
+
return JSON.stringify(payload);
|
|
1179
|
+
}
|
|
1180
|
+
function isObjectWithResponse(event) {
|
|
1181
|
+
return Boolean(event.response && typeof event.response === "object");
|
|
1182
|
+
}
|
|
1183
|
+
function errorToMessage(error) {
|
|
1184
|
+
if (error instanceof Error) {
|
|
1185
|
+
return error.message;
|
|
1186
|
+
}
|
|
1187
|
+
if (typeof error === "string") {
|
|
1188
|
+
return error;
|
|
1189
|
+
}
|
|
1190
|
+
try {
|
|
1191
|
+
return JSON.stringify(error);
|
|
1192
|
+
} catch {
|
|
1193
|
+
return String(error);
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
function createAbortError(reason) {
|
|
1197
|
+
const error = new Error(
|
|
1198
|
+
reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "Request aborted."
|
|
1199
|
+
);
|
|
1200
|
+
error.name = "AbortError";
|
|
1201
|
+
return error;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
686
1204
|
// src/openai/chatgpt-codex.ts
|
|
687
1205
|
var CHATGPT_CODEX_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
|
|
1206
|
+
var CHATGPT_RESPONSES_EXPERIMENTAL_HEADER = "responses=experimental";
|
|
1207
|
+
var cachedResponsesWebSocketMode = null;
|
|
1208
|
+
var chatGptResponsesWebSocketDisabled = false;
|
|
688
1209
|
async function streamChatGptCodexResponse(options) {
|
|
689
1210
|
const { access, accountId } = await getChatGptAuthProfile();
|
|
690
|
-
const
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
1211
|
+
const mode = resolveChatGptResponsesWebSocketMode();
|
|
1212
|
+
const fallbackStreamFactory = () => {
|
|
1213
|
+
const streamPromise = streamChatGptCodexResponseSse({
|
|
1214
|
+
request: options.request,
|
|
1215
|
+
access,
|
|
1216
|
+
accountId,
|
|
1217
|
+
sessionId: options.sessionId,
|
|
1218
|
+
signal: options.signal
|
|
1219
|
+
});
|
|
1220
|
+
return {
|
|
1221
|
+
async *[Symbol.asyncIterator]() {
|
|
1222
|
+
const stream = await streamPromise;
|
|
1223
|
+
for await (const event of stream) {
|
|
1224
|
+
yield event;
|
|
1225
|
+
}
|
|
1226
|
+
},
|
|
1227
|
+
async finalResponse() {
|
|
1228
|
+
return {};
|
|
1229
|
+
},
|
|
1230
|
+
close() {
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
698
1233
|
};
|
|
699
|
-
if (
|
|
700
|
-
|
|
1234
|
+
if (mode === "off" || chatGptResponsesWebSocketDisabled) {
|
|
1235
|
+
return fallbackStreamFactory();
|
|
701
1236
|
}
|
|
1237
|
+
const websocketHeaders = buildChatGptCodexHeaders({
|
|
1238
|
+
access,
|
|
1239
|
+
accountId,
|
|
1240
|
+
sessionId: options.sessionId,
|
|
1241
|
+
useWebSocket: true
|
|
1242
|
+
});
|
|
1243
|
+
return createAdaptiveResponsesStream({
|
|
1244
|
+
mode,
|
|
1245
|
+
createWebSocketStream: async () => await createResponsesWebSocketStream({
|
|
1246
|
+
url: toWebSocketUrl(CHATGPT_CODEX_ENDPOINT),
|
|
1247
|
+
headers: websocketHeaders,
|
|
1248
|
+
request: options.request,
|
|
1249
|
+
signal: options.signal
|
|
1250
|
+
}),
|
|
1251
|
+
createFallbackStream: fallbackStreamFactory,
|
|
1252
|
+
onWebSocketFallback: () => {
|
|
1253
|
+
chatGptResponsesWebSocketDisabled = true;
|
|
1254
|
+
}
|
|
1255
|
+
});
|
|
1256
|
+
}
|
|
1257
|
+
async function streamChatGptCodexResponseSse(options) {
|
|
1258
|
+
const headers = buildChatGptCodexHeaders({
|
|
1259
|
+
access: options.access,
|
|
1260
|
+
accountId: options.accountId,
|
|
1261
|
+
sessionId: options.sessionId,
|
|
1262
|
+
useWebSocket: false
|
|
1263
|
+
});
|
|
1264
|
+
headers.Accept = "text/event-stream";
|
|
1265
|
+
headers["Content-Type"] = "application/json";
|
|
702
1266
|
const response = await fetch(CHATGPT_CODEX_ENDPOINT, {
|
|
703
1267
|
method: "POST",
|
|
704
1268
|
headers,
|
|
@@ -715,20 +1279,67 @@ async function streamChatGptCodexResponse(options) {
|
|
|
715
1279
|
}
|
|
716
1280
|
return parseEventStream(body);
|
|
717
1281
|
}
|
|
1282
|
+
function resolveChatGptResponsesWebSocketMode() {
|
|
1283
|
+
if (cachedResponsesWebSocketMode) {
|
|
1284
|
+
return cachedResponsesWebSocketMode;
|
|
1285
|
+
}
|
|
1286
|
+
cachedResponsesWebSocketMode = resolveResponsesWebSocketMode(
|
|
1287
|
+
process.env.CHATGPT_RESPONSES_WEBSOCKET_MODE ?? process.env.OPENAI_RESPONSES_WEBSOCKET_MODE,
|
|
1288
|
+
"auto"
|
|
1289
|
+
);
|
|
1290
|
+
return cachedResponsesWebSocketMode;
|
|
1291
|
+
}
|
|
1292
|
+
function buildChatGptCodexHeaders(options) {
|
|
1293
|
+
const openAiBeta = options.useWebSocket ? mergeOpenAiBetaHeader(
|
|
1294
|
+
CHATGPT_RESPONSES_EXPERIMENTAL_HEADER,
|
|
1295
|
+
OPENAI_BETA_RESPONSES_WEBSOCKETS_V2
|
|
1296
|
+
) : CHATGPT_RESPONSES_EXPERIMENTAL_HEADER;
|
|
1297
|
+
const headers = {
|
|
1298
|
+
Authorization: `Bearer ${options.access}`,
|
|
1299
|
+
"chatgpt-account-id": options.accountId,
|
|
1300
|
+
"OpenAI-Beta": openAiBeta,
|
|
1301
|
+
originator: "llm",
|
|
1302
|
+
"User-Agent": buildUserAgent()
|
|
1303
|
+
};
|
|
1304
|
+
if (options.sessionId) {
|
|
1305
|
+
headers.session_id = options.sessionId;
|
|
1306
|
+
}
|
|
1307
|
+
return headers;
|
|
1308
|
+
}
|
|
718
1309
|
async function collectChatGptCodexResponse(options) {
|
|
719
|
-
let
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
1310
|
+
let requestForAttempt = options.request;
|
|
1311
|
+
let retriedWithoutReasoningSummary = false;
|
|
1312
|
+
let retriedViaSseFallback = false;
|
|
1313
|
+
while (true) {
|
|
1314
|
+
let sawAnyDelta = false;
|
|
1315
|
+
try {
|
|
1316
|
+
const stream = await streamChatGptCodexResponse({
|
|
725
1317
|
...options,
|
|
726
|
-
request:
|
|
1318
|
+
request: requestForAttempt
|
|
727
1319
|
});
|
|
728
|
-
|
|
1320
|
+
return await collectChatGptCodexStream({
|
|
1321
|
+
stream,
|
|
1322
|
+
onDelta: (delta) => {
|
|
1323
|
+
sawAnyDelta = true;
|
|
1324
|
+
options.onDelta?.(delta);
|
|
1325
|
+
}
|
|
1326
|
+
});
|
|
1327
|
+
} catch (error) {
|
|
1328
|
+
if (!sawAnyDelta && !retriedViaSseFallback && shouldRetryViaSseFallback(error) && !chatGptResponsesWebSocketDisabled) {
|
|
1329
|
+
chatGptResponsesWebSocketDisabled = true;
|
|
1330
|
+
retriedViaSseFallback = true;
|
|
1331
|
+
continue;
|
|
1332
|
+
}
|
|
1333
|
+
if (!retriedWithoutReasoningSummary && shouldRetryWithoutReasoningSummary(requestForAttempt, error)) {
|
|
1334
|
+
requestForAttempt = removeReasoningSummary(requestForAttempt);
|
|
1335
|
+
retriedWithoutReasoningSummary = true;
|
|
1336
|
+
continue;
|
|
1337
|
+
}
|
|
729
1338
|
throw error;
|
|
730
1339
|
}
|
|
731
1340
|
}
|
|
1341
|
+
}
|
|
1342
|
+
async function collectChatGptCodexStream(options) {
|
|
732
1343
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
733
1344
|
const toolCallOrder = [];
|
|
734
1345
|
const webSearchCalls = /* @__PURE__ */ new Map();
|
|
@@ -741,7 +1352,7 @@ async function collectChatGptCodexResponse(options) {
|
|
|
741
1352
|
let model;
|
|
742
1353
|
let status;
|
|
743
1354
|
let blocked = false;
|
|
744
|
-
for await (const event of stream) {
|
|
1355
|
+
for await (const event of options.stream) {
|
|
745
1356
|
const type = typeof event.type === "string" ? event.type : void 0;
|
|
746
1357
|
if (type === "response.output_text.delta") {
|
|
747
1358
|
const delta = typeof event.delta === "string" ? event.delta : "";
|
|
@@ -865,6 +1476,16 @@ function shouldRetryWithoutReasoningSummary(request, error) {
|
|
|
865
1476
|
const message = error.message.toLowerCase();
|
|
866
1477
|
return message.includes("unsupported parameter") && message.includes("reasoning.summary");
|
|
867
1478
|
}
|
|
1479
|
+
function shouldRetryViaSseFallback(error) {
|
|
1480
|
+
if (!(error instanceof Error)) {
|
|
1481
|
+
return false;
|
|
1482
|
+
}
|
|
1483
|
+
if (error.name === "AbortError") {
|
|
1484
|
+
return false;
|
|
1485
|
+
}
|
|
1486
|
+
const message = error.message.toLowerCase();
|
|
1487
|
+
return message.includes("responses websocket");
|
|
1488
|
+
}
|
|
868
1489
|
function removeReasoningSummary(request) {
|
|
869
1490
|
const reasoning = request.reasoning;
|
|
870
1491
|
if (!reasoning?.summary) {
|
|
@@ -1112,14 +1733,16 @@ async function runFireworksCall(fn) {
|
|
|
1112
1733
|
}
|
|
1113
1734
|
|
|
1114
1735
|
// src/fireworks/models.ts
|
|
1115
|
-
var FIREWORKS_MODEL_IDS = ["kimi-k2.5", "glm-5", "minimax-m2.1"];
|
|
1736
|
+
var FIREWORKS_MODEL_IDS = ["kimi-k2.5", "glm-5", "minimax-m2.1", "gpt-oss-120b"];
|
|
1116
1737
|
var FIREWORKS_DEFAULT_KIMI_MODEL = "kimi-k2.5";
|
|
1117
1738
|
var FIREWORKS_DEFAULT_GLM_MODEL = "glm-5";
|
|
1118
1739
|
var FIREWORKS_DEFAULT_MINIMAX_MODEL = "minimax-m2.1";
|
|
1740
|
+
var FIREWORKS_DEFAULT_GPT_OSS_120B_MODEL = "gpt-oss-120b";
|
|
1119
1741
|
var FIREWORKS_CANONICAL_MODEL_IDS = {
|
|
1120
1742
|
"kimi-k2.5": "accounts/fireworks/models/kimi-k2p5",
|
|
1121
1743
|
"glm-5": "accounts/fireworks/models/glm-5",
|
|
1122
|
-
"minimax-m2.1": "accounts/fireworks/models/minimax-m2p1"
|
|
1744
|
+
"minimax-m2.1": "accounts/fireworks/models/minimax-m2p1",
|
|
1745
|
+
"gpt-oss-120b": "accounts/fireworks/models/gpt-oss-120b"
|
|
1123
1746
|
};
|
|
1124
1747
|
function isFireworksModelId(value) {
|
|
1125
1748
|
return FIREWORKS_MODEL_IDS.includes(value.trim());
|
|
@@ -1200,6 +1823,7 @@ function getGoogleAuthOptions(scopes) {
|
|
|
1200
1823
|
// src/google/client.ts
|
|
1201
1824
|
var GEMINI_MODEL_IDS = [
|
|
1202
1825
|
"gemini-3-pro-preview",
|
|
1826
|
+
"gemini-3.1-pro-preview",
|
|
1203
1827
|
"gemini-3-flash-preview",
|
|
1204
1828
|
"gemini-2.5-pro",
|
|
1205
1829
|
"gemini-flash-latest",
|
|
@@ -1466,6 +2090,8 @@ var cachedApiKey2 = null;
|
|
|
1466
2090
|
var cachedClient2 = null;
|
|
1467
2091
|
var cachedFetch2 = null;
|
|
1468
2092
|
var cachedTimeoutMs2 = null;
|
|
2093
|
+
var openAiResponsesWebSocketMode = null;
|
|
2094
|
+
var openAiResponsesWebSocketDisabled = false;
|
|
1469
2095
|
var DEFAULT_OPENAI_TIMEOUT_MS = 15 * 6e4;
|
|
1470
2096
|
function resolveOpenAiTimeoutMs() {
|
|
1471
2097
|
if (cachedTimeoutMs2 !== null) {
|
|
@@ -1493,6 +2119,97 @@ function getOpenAiFetch() {
|
|
|
1493
2119
|
});
|
|
1494
2120
|
return cachedFetch2;
|
|
1495
2121
|
}
|
|
2122
|
+
function resolveOpenAiBaseUrl() {
|
|
2123
|
+
loadLocalEnv();
|
|
2124
|
+
return process.env.OPENAI_BASE_URL?.trim() || "https://api.openai.com/v1";
|
|
2125
|
+
}
|
|
2126
|
+
function resolveOpenAiResponsesWebSocketMode() {
|
|
2127
|
+
if (openAiResponsesWebSocketMode) {
|
|
2128
|
+
return openAiResponsesWebSocketMode;
|
|
2129
|
+
}
|
|
2130
|
+
loadLocalEnv();
|
|
2131
|
+
openAiResponsesWebSocketMode = resolveResponsesWebSocketMode(
|
|
2132
|
+
process.env.OPENAI_RESPONSES_WEBSOCKET_MODE,
|
|
2133
|
+
"auto"
|
|
2134
|
+
);
|
|
2135
|
+
return openAiResponsesWebSocketMode;
|
|
2136
|
+
}
|
|
2137
|
+
function wrapFallbackStream(stream) {
|
|
2138
|
+
return {
|
|
2139
|
+
async *[Symbol.asyncIterator]() {
|
|
2140
|
+
for await (const event of stream) {
|
|
2141
|
+
yield event;
|
|
2142
|
+
}
|
|
2143
|
+
},
|
|
2144
|
+
async finalResponse() {
|
|
2145
|
+
return await stream.finalResponse();
|
|
2146
|
+
},
|
|
2147
|
+
close() {
|
|
2148
|
+
const maybeClose = stream;
|
|
2149
|
+
if (typeof maybeClose.close === "function") {
|
|
2150
|
+
maybeClose.close();
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
};
|
|
2154
|
+
}
|
|
2155
|
+
function buildOpenAiResponsesEndpointUrl() {
|
|
2156
|
+
const base = resolveOpenAiBaseUrl();
|
|
2157
|
+
const normalized = base.endsWith("/") ? base : `${base}/`;
|
|
2158
|
+
return new URL("responses", normalized).toString();
|
|
2159
|
+
}
|
|
2160
|
+
function buildOpenAiResponsesWebSocketHeaders(apiKey) {
|
|
2161
|
+
const headers = {
|
|
2162
|
+
Authorization: `Bearer ${apiKey}`,
|
|
2163
|
+
"OpenAI-Beta": mergeOpenAiBetaHeader(
|
|
2164
|
+
process.env.OPENAI_BETA,
|
|
2165
|
+
OPENAI_BETA_RESPONSES_WEBSOCKETS_V2
|
|
2166
|
+
)
|
|
2167
|
+
};
|
|
2168
|
+
const organization = process.env.OPENAI_ORGANIZATION?.trim();
|
|
2169
|
+
if (organization) {
|
|
2170
|
+
headers["OpenAI-Organization"] = organization;
|
|
2171
|
+
}
|
|
2172
|
+
const project = process.env.OPENAI_PROJECT?.trim();
|
|
2173
|
+
if (project) {
|
|
2174
|
+
headers["OpenAI-Project"] = project;
|
|
2175
|
+
}
|
|
2176
|
+
return headers;
|
|
2177
|
+
}
|
|
2178
|
+
function installResponsesWebSocketTransport(client, apiKey) {
|
|
2179
|
+
const responsesApi = client.responses;
|
|
2180
|
+
const streamMethod = responsesApi?.stream;
|
|
2181
|
+
if (typeof streamMethod !== "function") {
|
|
2182
|
+
return;
|
|
2183
|
+
}
|
|
2184
|
+
const originalStream = streamMethod.bind(client.responses);
|
|
2185
|
+
responsesApi.stream = (request, options) => {
|
|
2186
|
+
const mode = resolveOpenAiResponsesWebSocketMode();
|
|
2187
|
+
const fallbackStreamFactory = () => wrapFallbackStream(originalStream(request, options));
|
|
2188
|
+
if (mode === "off" || openAiResponsesWebSocketDisabled) {
|
|
2189
|
+
return fallbackStreamFactory();
|
|
2190
|
+
}
|
|
2191
|
+
const signal = options && typeof options === "object" ? options.signal ?? void 0 : void 0;
|
|
2192
|
+
const websocketUrl = toWebSocketUrl(buildOpenAiResponsesEndpointUrl());
|
|
2193
|
+
const headers = buildOpenAiResponsesWebSocketHeaders(apiKey);
|
|
2194
|
+
const timeoutMs = resolveOpenAiTimeoutMs();
|
|
2195
|
+
return createAdaptiveResponsesStream({
|
|
2196
|
+
mode,
|
|
2197
|
+
createWebSocketStream: async () => await createResponsesWebSocketStream({
|
|
2198
|
+
url: websocketUrl,
|
|
2199
|
+
headers,
|
|
2200
|
+
request,
|
|
2201
|
+
signal,
|
|
2202
|
+
idleTimeoutMs: timeoutMs
|
|
2203
|
+
}),
|
|
2204
|
+
createFallbackStream: fallbackStreamFactory,
|
|
2205
|
+
onWebSocketFallback: (error) => {
|
|
2206
|
+
if (isResponsesWebSocketUnsupportedError(error)) {
|
|
2207
|
+
openAiResponsesWebSocketDisabled = true;
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
});
|
|
2211
|
+
};
|
|
2212
|
+
}
|
|
1496
2213
|
function getOpenAiApiKey() {
|
|
1497
2214
|
if (cachedApiKey2 !== null) {
|
|
1498
2215
|
return cachedApiKey2;
|
|
@@ -1510,6 +2227,7 @@ function getOpenAiClient() {
|
|
|
1510
2227
|
if (cachedClient2) {
|
|
1511
2228
|
return cachedClient2;
|
|
1512
2229
|
}
|
|
2230
|
+
loadLocalEnv();
|
|
1513
2231
|
const apiKey = getOpenAiApiKey();
|
|
1514
2232
|
const timeoutMs = resolveOpenAiTimeoutMs();
|
|
1515
2233
|
cachedClient2 = new OpenAI2({
|
|
@@ -1517,6 +2235,7 @@ function getOpenAiClient() {
|
|
|
1517
2235
|
fetch: getOpenAiFetch(),
|
|
1518
2236
|
timeout: timeoutMs
|
|
1519
2237
|
});
|
|
2238
|
+
installResponsesWebSocketTransport(cachedClient2, apiKey);
|
|
1520
2239
|
return cachedClient2;
|
|
1521
2240
|
}
|
|
1522
2241
|
|
|
@@ -3090,6 +3809,7 @@ function extractFireworksToolCalls(message) {
|
|
|
3090
3809
|
function resolveGeminiThinkingConfig(modelId) {
|
|
3091
3810
|
switch (modelId) {
|
|
3092
3811
|
case "gemini-3-pro-preview":
|
|
3812
|
+
case "gemini-3.1-pro-preview":
|
|
3093
3813
|
return { includeThoughts: true };
|
|
3094
3814
|
case "gemini-3-flash-preview":
|
|
3095
3815
|
return { includeThoughts: true, thinkingBudget: 16384 };
|
|
@@ -6489,6 +7209,7 @@ export {
|
|
|
6489
7209
|
CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION,
|
|
6490
7210
|
CODEX_APPLY_PATCH_LARK_GRAMMAR,
|
|
6491
7211
|
FIREWORKS_DEFAULT_GLM_MODEL,
|
|
7212
|
+
FIREWORKS_DEFAULT_GPT_OSS_120B_MODEL,
|
|
6492
7213
|
FIREWORKS_DEFAULT_KIMI_MODEL,
|
|
6493
7214
|
FIREWORKS_DEFAULT_MINIMAX_MODEL,
|
|
6494
7215
|
FIREWORKS_MODEL_IDS,
|