@jeffusion/bungee-core 5.23.0 → 5.23.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.
Files changed (29) hide show
  1. package/dist/config-storage-worker.js +3 -1
  2. package/dist/main.js +2756 -295
  3. package/dist/plugins/chatgpt-oauth/index.js +92 -20
  4. package/dist/plugins/chatgpt-oauth/index.js.map +4 -4
  5. package/dist/plugins/codex-router/control.js +606 -2
  6. package/dist/plugins/codex-router/control.js.map +20 -5
  7. package/dist/plugins/codex-router/index.js +2459 -94
  8. package/dist/plugins/codex-router/index.js.map +20 -8
  9. package/dist/plugins/codex-router/manifest.json +14 -14
  10. package/dist/plugins/llm-protocol-adapter/control.js +96 -21
  11. package/dist/plugins/llm-protocol-adapter/control.js.map +8 -7
  12. package/dist/plugins/llm-protocol-adapter/index.js +134 -38
  13. package/dist/plugins/llm-protocol-adapter/index.js.map +11 -10
  14. package/dist/plugins/model-mapping/control.js +1 -1
  15. package/dist/plugins/model-mapping/control.js.map +3 -3
  16. package/dist/plugins/model-mapping/index.js +48 -17
  17. package/dist/plugins/model-mapping/index.js.map +6 -5
  18. package/dist/plugins/model-mapping/manifest.json +50 -6
  19. package/dist/plugins/models-dev/control.js +1 -1
  20. package/dist/plugins/models-dev/control.js.map +3 -3
  21. package/dist/plugins/models-dev/index.js +1 -1
  22. package/dist/plugins/models-dev/index.js.map +3 -3
  23. package/dist/plugins/token-metering/index.js +1 -1
  24. package/dist/plugins/token-metering/index.js.map +1 -1
  25. package/dist/plugins/token-stats/control.js +1 -1
  26. package/dist/plugins/token-stats/control.js.map +3 -3
  27. package/dist/plugins/token-stats/index.js +1 -1
  28. package/dist/plugins/token-stats/index.js.map +3 -3
  29. package/package.json +2 -2
@@ -1455,6 +1455,7 @@ var MAX_PROFILE_HEADER_VALUE_BYTES = 8192;
1455
1455
  var CHATGPT_ORIGIN = "https://chatgpt.com";
1456
1456
  var SIWC_ORIGIN = "https://api.openai.com";
1457
1457
  var CODEX_ROUTING_HINT_HEADER = "X-Codex-Routing-Hint";
1458
+ var convertedCompletions = new WeakSet;
1458
1459
  var SIWC_FORBIDDEN_FIELDS = [
1459
1460
  "background",
1460
1461
  "conversation",
@@ -1629,6 +1630,13 @@ function responseHeaders(response, contentType) {
1629
1630
  headers.set("content-type", contentType);
1630
1631
  return headers;
1631
1632
  }
1633
+ function nativeResponseHeaders(response) {
1634
+ const headers = new Headers(response.headers);
1635
+ for (const name of ["content-encoding", "content-length", "transfer-encoding"])
1636
+ headers.delete(name);
1637
+ headers.set("content-type", "text/event-stream");
1638
+ return headers;
1639
+ }
1632
1640
  function errorBody2(error, fallbackCode = "upstream_error") {
1633
1641
  return { message: error?.message ?? "Upstream response could not be adapted", type: error?.type ?? "upstream_error", code: error?.code ?? fallbackCode };
1634
1642
  }
@@ -1725,14 +1733,34 @@ function serialize(event) {
1725
1733
  if (envelope?.retry !== undefined)
1726
1734
  lines.push(`retry: ${envelope.retry}`);
1727
1735
  const data = event.type === "done" ? "[DONE]" : envelope?.data ?? JSON.stringify(event.data);
1728
- lines.push(...data.split(`
1736
+ if (envelope?.hasData !== false)
1737
+ lines.push(...data.split(`
1729
1738
  `).map((line) => `data: ${line}`));
1730
1739
  return `${lines.join(`
1731
1740
  `)}
1732
1741
 
1733
1742
  `;
1734
1743
  }
1735
- function protocolStreamBody(handle, target, includeUsage, signal, redact, preserveCustomTools = false) {
1744
+ async function* nativeCodexEvents(handle, signal) {
1745
+ for await (const envelope of handle.events(bodyConsumer(signal))) {
1746
+ const data = envelope.json && typeof envelope.json === "object" && !Array.isArray(envelope.json) ? envelope.json : {};
1747
+ yield { type: typeof data.type === "string" ? data.type : undefined, data, envelope };
1748
+ }
1749
+ }
1750
+ function nativeTerminal(event) {
1751
+ if (event.envelope?.truncated || event.envelope?.hasData === false)
1752
+ return;
1753
+ if (event.type === "error")
1754
+ return { status: "failed", code: "upstream_error" };
1755
+ const status = event.type === "response.completed" ? "completed" : event.type === "response.incomplete" ? "incomplete" : event.type === "response.failed" ? "failed" : undefined;
1756
+ if (!status)
1757
+ return;
1758
+ const response = event.data.response;
1759
+ if (!response || typeof response !== "object" || Array.isArray(response) || response.status !== status || !Array.isArray(response.output) || status === "completed" && response.error != null)
1760
+ return { status: "failed", code: "invalid_response" };
1761
+ return status === "completed" ? { status } : { status, code: status === "failed" ? "upstream_error" : "incomplete" };
1762
+ }
1763
+ function protocolStreamBody(handle, target, includeUsage, signal, redact, preserveCustomTools = false, native = false) {
1736
1764
  const protocolController = new AbortController;
1737
1765
  const onAbort = () => protocolController.abort(signal.reason ?? "cancelled");
1738
1766
  if (signal.aborted)
@@ -1750,14 +1778,20 @@ function protocolStreamBody(handle, target, includeUsage, signal, redact, preser
1750
1778
  const completion = new Promise((resolve) => {
1751
1779
  resolveCompletion = resolve;
1752
1780
  });
1753
- const processor = new CodexResponseProcessor({ target, includeUsage, redactDiagnostic: redact, preserveCustomTools });
1781
+ const processor = native ? undefined : new CodexResponseProcessor({ target, includeUsage, redactDiagnostic: redact, preserveCustomTools });
1754
1782
  let terminalOutcome;
1755
- const events = parseCodexSSE(handle.events(bodyConsumer(protocolController.signal)), { signal: protocolController.signal });
1783
+ const events = native ? nativeCodexEvents(handle, protocolController.signal) : parseCodexSSE(handle.events(bodyConsumer(protocolController.signal)), { signal: protocolController.signal });
1756
1784
  const iterator = async function* () {
1757
1785
  try {
1758
1786
  for await (const event of events) {
1759
- const output = processor.process(event);
1760
- if (event.type === "response.completed" || event.type === "response.incomplete") {
1787
+ const output = processor?.process(event) ?? [];
1788
+ if (native) {
1789
+ const outcome = nativeTerminal(event);
1790
+ if (outcome) {
1791
+ terminalOutcome = outcome;
1792
+ settle(outcome);
1793
+ }
1794
+ } else if (event.type === "response.completed" || event.type === "response.incomplete") {
1761
1795
  const final = processor.finish();
1762
1796
  terminalOutcome = final.terminal === "completed" ? { status: "completed" } : { status: "incomplete", code: "incomplete" };
1763
1797
  settle(terminalOutcome);
@@ -1770,8 +1804,8 @@ function protocolStreamBody(handle, target, includeUsage, signal, redact, preser
1770
1804
 
1771
1805
  `;
1772
1806
  }
1773
- const final = processor.finish();
1774
- const outcome = final.terminal === "completed" ? { status: "completed" } : { status: "incomplete", code: "incomplete" };
1807
+ const final = processor?.finish();
1808
+ const outcome = native ? terminalOutcome ?? { status: "failed", code: "unexpected_eof" } : final.terminal === "completed" ? { status: "completed" } : { status: "incomplete", code: "incomplete" };
1775
1809
  if (target === "chat")
1776
1810
  yield `data: [DONE]
1777
1811
 
@@ -1780,7 +1814,7 @@ function protocolStreamBody(handle, target, includeUsage, signal, redact, preser
1780
1814
  } catch (error) {
1781
1815
  const outcome = completionFromError(error, redact);
1782
1816
  settle(outcome.status === "cancelled" ? terminalOutcome ?? outcome : outcome);
1783
- if (outcome.status === "failed" && outcome.error) {
1817
+ if (!native && outcome.status === "failed" && outcome.error) {
1784
1818
  const safe = errorBody2(outcome.error, outcome.code);
1785
1819
  yield target === "responses" ? `event: error
1786
1820
  data: ${JSON.stringify({ type: "error", code: safe.code, message: safe.message, param: null, error: safe })}
@@ -1814,12 +1848,13 @@ data: ${JSON.stringify({ type: "error", code: safe.code, message: safe.message,
1814
1848
  return;
1815
1849
  });
1816
1850
  }
1817
- });
1851
+ }, { highWaterMark: 0 });
1818
1852
  return { body, completion };
1819
1853
  }
1820
1854
 
1821
1855
  class ChatgptOauthAdapter {
1822
1856
  requests = new Map;
1857
+ nativeResponses = new WeakSet;
1823
1858
  constructor() {}
1824
1859
  beforeRequest(context) {
1825
1860
  assertResponsesEntryPath(context.url.pathname);
@@ -1915,10 +1950,31 @@ class ChatgptOauthAdapter {
1915
1950
  return context;
1916
1951
  }
1917
1952
  async rawResponse(result, context) {
1918
- const current = this.requests.get(context.requestId);
1953
+ if (convertedCompletions.has(result.completion)) {
1954
+ const pending = this.requests.get(context.requestId);
1955
+ const cleanup = () => {
1956
+ if (this.requests.get(context.requestId) === pending)
1957
+ this.requests.delete(context.requestId);
1958
+ };
1959
+ result.completion.then(cleanup, cleanup);
1960
+ return result;
1961
+ }
1962
+ if (this.nativeResponses.has(result.response))
1963
+ return result;
1964
+ const upstreamUrl = context.upstreamUrl ? new URL(context.upstreamUrl) : undefined;
1965
+ const current = this.requests.get(context.requestId) ?? (upstreamUrl?.origin === CHATGPT_ORIGIN && upstreamUrl.pathname === CODEX_RESPONSES_PATH && context.method.toUpperCase() === "POST" ? Object.freeze({
1966
+ target: "responses",
1967
+ stream: true,
1968
+ includeUsage: false,
1969
+ allowMissingContentType: true,
1970
+ native: true,
1971
+ adaptedResponses: new WeakSet
1972
+ }) : undefined);
1919
1973
  if (current === undefined || current.adaptedResponses.has(result.response))
1920
1974
  return result;
1921
1975
  current.adaptedResponses.add(result.response);
1976
+ if (current.native)
1977
+ this.nativeResponses.add(result.response);
1922
1978
  const state = current.attemptId === undefined ? Object.freeze({ ...current, attemptId: context.attemptId }) : current;
1923
1979
  if (state !== current && this.requests.get(context.requestId) === current)
1924
1980
  this.requests.set(context.requestId, state);
@@ -1926,8 +1982,15 @@ class ChatgptOauthAdapter {
1926
1982
  if (this.requests.get(context.requestId) === state)
1927
1983
  this.requests.delete(context.requestId);
1928
1984
  };
1985
+ const trackCompletion = (completion) => {
1986
+ if (!state.native)
1987
+ convertedCompletions.add(completion);
1988
+ completion.then(cleanup, cleanup);
1989
+ };
1929
1990
  const mark = (response) => {
1930
1991
  current.adaptedResponses.add(response);
1992
+ if (current.native)
1993
+ this.nativeResponses.add(response);
1931
1994
  return response;
1932
1995
  };
1933
1996
  const errorResponse = (status, completion, error) => {
@@ -1936,9 +1999,13 @@ class ChatgptOauthAdapter {
1936
1999
  statusText: result.response.statusText,
1937
2000
  headers: responseHeaders(result.response, "application/json; charset=utf-8")
1938
2001
  }));
1939
- completion.then(cleanup, cleanup);
2002
+ trackCompletion(completion);
1940
2003
  return { response, completion };
1941
2004
  };
2005
+ if (state.native && !result.response.ok) {
2006
+ result.completion.then(cleanup, cleanup);
2007
+ return result;
2008
+ }
1942
2009
  if (!context.bodyHandle) {
1943
2010
  return errorResponse(502, Promise.resolve({ status: "failed", code: "body_view_missing" }));
1944
2011
  }
@@ -1969,7 +2036,7 @@ class ChatgptOauthAdapter {
1969
2036
  statusText: result.response.statusText,
1970
2037
  headers: responseHeaders(result.response, "application/json; charset=utf-8")
1971
2038
  }));
1972
- completion.then(cleanup, cleanup);
2039
+ trackCompletion(completion);
1973
2040
  return { response, completion };
1974
2041
  } catch (error) {
1975
2042
  const failure = completionFromError(error, context.redactDiagnostic);
@@ -1977,21 +2044,26 @@ class ChatgptOauthAdapter {
1977
2044
  }
1978
2045
  }
1979
2046
  const contentType = result.response.headers.get("content-type");
1980
- const hasEventStream = contentType?.split(";", 1)[0].trim().toLowerCase() === "text/event-stream";
2047
+ const media = contentType?.split(";", 1)[0].trim().toLowerCase();
2048
+ const hasEventStream = media === "text/event-stream" || state.native === true && media === "application/octet-stream";
1981
2049
  const allowMissingContentType = state.allowMissingContentType && contentType === null;
1982
2050
  if (!hasEventStream && !allowMissingContentType || !result.response.body) {
1983
2051
  const bodyCompletion = !hasEventStream && !allowMissingContentType ? discardBody(context.bodyHandle, context.signal).then((outcome) => outcome.status === "completed" ? { status: "failed", code: "invalid_content_type" } : outcome) : Promise.resolve({ status: "failed", code: "invalid_response" });
1984
2052
  return errorResponse(502, joinCompletion(result.completion, bodyCompletion, context.signal));
1985
2053
  }
1986
2054
  if (state.stream) {
1987
- const converted = protocolStreamBody(context.bodyHandle, state.target, state.includeUsage, context.signal, context.redactDiagnostic, state.siwc);
2055
+ const converted = protocolStreamBody(context.bodyHandle, state.target, state.includeUsage, context.signal, context.redactDiagnostic, state.siwc, state.native);
1988
2056
  const streamCompletion = Promise.race([
1989
2057
  converted.completion,
1990
2058
  result.completion.then((upstream) => upstream.status === "failed" ? upstream : converted.completion, () => ({ status: "failed", code: "upstream_completion" }))
1991
2059
  ]);
1992
- streamCompletion.then(cleanup, cleanup);
2060
+ trackCompletion(streamCompletion);
1993
2061
  return {
1994
- response: mark(new Response(converted.body, { status: result.response.status, statusText: result.response.statusText, headers: responseHeaders(result.response, "text/event-stream") })),
2062
+ response: mark(new Response(converted.body, {
2063
+ status: result.response.status,
2064
+ statusText: result.response.statusText,
2065
+ headers: state.native ? nativeResponseHeaders(result.response) : responseHeaders(result.response, "text/event-stream")
2066
+ })),
1995
2067
  completion: streamCompletion
1996
2068
  };
1997
2069
  }
@@ -2005,7 +2077,7 @@ class ChatgptOauthAdapter {
2005
2077
  const body = state.target === "chat" ? responsesToChatCompletion(stateResult.response, state.siwc) : stateResult.response;
2006
2078
  const protocolCompletion = Promise.resolve(stateResult.terminal === "completed" ? { status: "completed" } : { status: "incomplete", code: "incomplete" });
2007
2079
  const nonStreamCompletion = joinCompletion(result.completion, protocolCompletion, context.signal);
2008
- nonStreamCompletion.then(cleanup, cleanup);
2080
+ trackCompletion(nonStreamCompletion);
2009
2081
  return { response: mark(new Response(JSON.stringify(body), { status: result.response.status, statusText: result.response.statusText, headers: responseHeaders(result.response, "application/json; charset=utf-8") })), completion: nonStreamCompletion };
2010
2082
  } catch (error) {
2011
2083
  const failure = completionFromError(error, context.redactDiagnostic);
@@ -2034,7 +2106,7 @@ var ChatgptOauthPlugin = definePlugin(class {
2034
2106
  const path = context.url.pathname;
2035
2107
  if (path === "/v1/models" && context.method.toUpperCase() === "GET")
2036
2108
  return { request: "none", response: ["json"] };
2037
- return context.method.toUpperCase() === "POST" && (isResponsesRequest(context.url) || ["/v1/chat/completions", "/backend-api/codex/responses"].includes(path)) ? { request: "json-write", response: path === "/backend-api/codex/responses" ? [] : ["json", "sse-json"] } : { request: "none" };
2109
+ return context.method.toUpperCase() === "POST" && (isResponsesRequest(context.url) || ["/v1/chat/completions", "/backend-api/codex/responses"].includes(path)) ? { request: "json-write", response: ["json", "sse-json"] } : { request: "none" };
2038
2110
  }
2039
2111
  register(hooks) {
2040
2112
  hooks.onWebSocketHandshake.tap("chatgpt-oauth", (context) => {
@@ -2056,4 +2128,4 @@ export {
2056
2128
  server_default as default
2057
2129
  };
2058
2130
 
2059
- //# debugId=F44D362B53E644C964756E2164756E21
2131
+ //# debugId=E48A263F3FBDCAF664756E2164756E21