@ljoukov/llm 7.0.18 → 7.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -575,6 +575,10 @@ function resolveOpenAiImagePriceResolution(imageSize) {
575
575
  import os2 from "os";
576
576
  import { TextDecoder as TextDecoder2 } from "util";
577
577
 
578
+ // src/utils/env.ts
579
+ import fs from "fs";
580
+ import path from "path";
581
+
578
582
  // src/utils/runtimeSingleton.ts
579
583
  var runtimeSingletonStoreKey = /* @__PURE__ */ Symbol.for("@ljoukov/llm.runtimeSingletonStore");
580
584
  function getRuntimeSingletonStore() {
@@ -603,16 +607,7 @@ function getRuntimeSingleton(key, create) {
603
607
  return createdValue;
604
608
  }
605
609
 
606
- // src/openai/chatgpt-auth.ts
607
- import { Buffer as Buffer2 } from "buffer";
608
- import fs2 from "fs";
609
- import os from "os";
610
- import path2 from "path";
611
- import { z } from "zod";
612
-
613
610
  // src/utils/env.ts
614
- import fs from "fs";
615
- import path from "path";
616
611
  var envState = getRuntimeSingleton(/* @__PURE__ */ Symbol.for("@ljoukov/llm.envState"), () => ({
617
612
  envLoaded: false
618
613
  }));
@@ -674,6 +669,11 @@ function parseEnvLine(line) {
674
669
  }
675
670
 
676
671
  // src/openai/chatgpt-auth.ts
672
+ import { Buffer as Buffer2 } from "buffer";
673
+ import fs2 from "fs";
674
+ import os from "os";
675
+ import path2 from "path";
676
+ import { z } from "zod";
677
677
  var CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_URL";
678
678
  var CHATGPT_AUTH_TOKEN_PROVIDER_STORE_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_STORE";
679
679
  var CHATGPT_AUTH_API_KEY_ENV = "CHATGPT_AUTH_API_KEY";
@@ -1581,19 +1581,21 @@ function createAbortError(reason) {
1581
1581
 
1582
1582
  // src/openai/chatgpt-codex.ts
1583
1583
  var CHATGPT_CODEX_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
1584
+ var CHATGPT_CODEX_ENDPOINT_ENV = "CHATGPT_CODEX_ENDPOINT";
1585
+ var CHATGPT_CODEX_PROXY_URL_ENV = "CHATGPT_CODEX_PROXY_URL";
1586
+ var CHATGPT_CODEX_PROXY_API_KEY_ENV = "CHATGPT_CODEX_PROXY_API_KEY";
1584
1587
  var CHATGPT_RESPONSES_EXPERIMENTAL_HEADER = "responses=experimental";
1585
1588
  var chatGptCodexState = getRuntimeSingleton(/* @__PURE__ */ Symbol.for("@ljoukov/llm.chatGptCodexState"), () => ({
1586
1589
  cachedResponsesWebSocketMode: null,
1587
1590
  chatGptResponsesWebSocketDisabled: false
1588
1591
  }));
1589
1592
  async function streamChatGptCodexResponse(options) {
1590
- const { access, accountId } = await getChatGptAuthProfile();
1593
+ const endpointConfig = await resolveChatGptCodexEndpointConfig();
1591
1594
  const mode = resolveChatGptResponsesWebSocketMode();
1592
1595
  const fallbackStreamFactory = () => {
1593
1596
  const streamPromise = streamChatGptCodexResponseSse({
1594
1597
  request: options.request,
1595
- access,
1596
- accountId,
1598
+ endpointConfig,
1597
1599
  sessionId: options.sessionId,
1598
1600
  signal: options.signal
1599
1601
  });
@@ -1615,15 +1617,14 @@ async function streamChatGptCodexResponse(options) {
1615
1617
  return fallbackStreamFactory();
1616
1618
  }
1617
1619
  const websocketHeaders = buildChatGptCodexHeaders({
1618
- access,
1619
- accountId,
1620
+ endpointConfig,
1620
1621
  sessionId: options.sessionId,
1621
1622
  useWebSocket: true
1622
1623
  });
1623
1624
  return createAdaptiveResponsesStream({
1624
1625
  mode,
1625
1626
  createWebSocketStream: async () => await createResponsesWebSocketStream({
1626
- url: toWebSocketUrl(CHATGPT_CODEX_ENDPOINT),
1627
+ url: toWebSocketUrl(endpointConfig.url),
1627
1628
  headers: websocketHeaders,
1628
1629
  request: options.request,
1629
1630
  signal: options.signal
@@ -1636,14 +1637,13 @@ async function streamChatGptCodexResponse(options) {
1636
1637
  }
1637
1638
  async function streamChatGptCodexResponseSse(options) {
1638
1639
  const headers = buildChatGptCodexHeaders({
1639
- access: options.access,
1640
- accountId: options.accountId,
1640
+ endpointConfig: options.endpointConfig,
1641
1641
  sessionId: options.sessionId,
1642
1642
  useWebSocket: false
1643
1643
  });
1644
1644
  headers.Accept = "text/event-stream";
1645
1645
  headers["Content-Type"] = "application/json";
1646
- const response = await fetch(CHATGPT_CODEX_ENDPOINT, {
1646
+ const response = await fetch(options.endpointConfig.url, {
1647
1647
  method: "POST",
1648
1648
  headers,
1649
1649
  body: JSON.stringify(options.request),
@@ -1663,24 +1663,77 @@ function resolveChatGptResponsesWebSocketMode() {
1663
1663
  if (chatGptCodexState.cachedResponsesWebSocketMode) {
1664
1664
  return chatGptCodexState.cachedResponsesWebSocketMode;
1665
1665
  }
1666
+ const explicitMode = process.env.CHATGPT_RESPONSES_WEBSOCKET_MODE ?? process.env.OPENAI_RESPONSES_WEBSOCKET_MODE;
1667
+ const defaultMode = resolveChatGptCodexProxyConfig() ? "off" : "auto";
1666
1668
  chatGptCodexState.cachedResponsesWebSocketMode = resolveResponsesWebSocketMode(
1667
- process.env.CHATGPT_RESPONSES_WEBSOCKET_MODE ?? process.env.OPENAI_RESPONSES_WEBSOCKET_MODE,
1668
- "auto"
1669
+ explicitMode,
1670
+ defaultMode
1669
1671
  );
1670
1672
  return chatGptCodexState.cachedResponsesWebSocketMode;
1671
1673
  }
1674
+ async function resolveChatGptCodexEndpointConfig() {
1675
+ const proxy = resolveChatGptCodexProxyConfig();
1676
+ if (proxy) {
1677
+ return proxy;
1678
+ }
1679
+ const { access, accountId } = await getChatGptAuthProfile();
1680
+ return {
1681
+ kind: "direct",
1682
+ url: resolveChatGptCodexEndpoint(),
1683
+ access,
1684
+ accountId
1685
+ };
1686
+ }
1687
+ function resolveChatGptCodexEndpoint() {
1688
+ loadLocalEnv();
1689
+ return process.env[CHATGPT_CODEX_ENDPOINT_ENV]?.trim() || CHATGPT_CODEX_ENDPOINT;
1690
+ }
1691
+ function resolveChatGptCodexProxyConfig() {
1692
+ loadLocalEnv();
1693
+ const rawUrl = process.env[CHATGPT_CODEX_PROXY_URL_ENV]?.trim();
1694
+ if (!rawUrl) {
1695
+ return null;
1696
+ }
1697
+ const apiKey = process.env[CHATGPT_CODEX_PROXY_API_KEY_ENV]?.trim();
1698
+ if (!apiKey) {
1699
+ throw new Error(
1700
+ `${CHATGPT_CODEX_PROXY_API_KEY_ENV} must be provided when ${CHATGPT_CODEX_PROXY_URL_ENV} is set.`
1701
+ );
1702
+ }
1703
+ return {
1704
+ kind: "proxy",
1705
+ url: normalizeChatGptCodexProxyUrl(rawUrl),
1706
+ apiKey
1707
+ };
1708
+ }
1709
+ function normalizeChatGptCodexProxyUrl(rawUrl) {
1710
+ try {
1711
+ const url = new URL(rawUrl);
1712
+ if (url.pathname === "" || url.pathname === "/") {
1713
+ url.pathname = "/api/codex/responses";
1714
+ }
1715
+ return url.toString();
1716
+ } catch {
1717
+ return rawUrl;
1718
+ }
1719
+ }
1672
1720
  function buildChatGptCodexHeaders(options) {
1673
1721
  const openAiBeta = options.useWebSocket ? mergeOpenAiBetaHeader(
1674
1722
  CHATGPT_RESPONSES_EXPERIMENTAL_HEADER,
1675
1723
  OPENAI_BETA_RESPONSES_WEBSOCKETS_V2
1676
1724
  ) : CHATGPT_RESPONSES_EXPERIMENTAL_HEADER;
1677
1725
  const headers = {
1678
- Authorization: `Bearer ${options.access}`,
1679
- "chatgpt-account-id": options.accountId,
1680
1726
  "OpenAI-Beta": openAiBeta,
1681
1727
  originator: "llm",
1682
1728
  "User-Agent": buildUserAgent()
1683
1729
  };
1730
+ if (options.endpointConfig.kind === "proxy") {
1731
+ headers.Authorization = `Bearer ${options.endpointConfig.apiKey}`;
1732
+ headers["x-codex-proxy-auth"] = options.endpointConfig.apiKey;
1733
+ } else {
1734
+ headers.Authorization = `Bearer ${options.endpointConfig.access}`;
1735
+ headers["chatgpt-account-id"] = options.endpointConfig.accountId;
1736
+ }
1684
1737
  if (options.sessionId) {
1685
1738
  headers.session_id = options.sessionId;
1686
1739
  }