@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.
- package/dist/config-storage-worker.js +3 -1
- package/dist/main.js +2756 -295
- package/dist/plugins/chatgpt-oauth/index.js +92 -20
- package/dist/plugins/chatgpt-oauth/index.js.map +4 -4
- package/dist/plugins/codex-router/control.js +606 -2
- package/dist/plugins/codex-router/control.js.map +20 -5
- package/dist/plugins/codex-router/index.js +2459 -94
- package/dist/plugins/codex-router/index.js.map +20 -8
- package/dist/plugins/codex-router/manifest.json +14 -14
- package/dist/plugins/llm-protocol-adapter/control.js +96 -21
- package/dist/plugins/llm-protocol-adapter/control.js.map +8 -7
- package/dist/plugins/llm-protocol-adapter/index.js +134 -38
- package/dist/plugins/llm-protocol-adapter/index.js.map +11 -10
- package/dist/plugins/model-mapping/control.js +1 -1
- package/dist/plugins/model-mapping/control.js.map +3 -3
- package/dist/plugins/model-mapping/index.js +48 -17
- package/dist/plugins/model-mapping/index.js.map +6 -5
- package/dist/plugins/model-mapping/manifest.json +50 -6
- package/dist/plugins/models-dev/control.js +1 -1
- package/dist/plugins/models-dev/control.js.map +3 -3
- package/dist/plugins/models-dev/index.js +1 -1
- package/dist/plugins/models-dev/index.js.map +3 -3
- package/dist/plugins/token-metering/index.js +1 -1
- package/dist/plugins/token-metering/index.js.map +1 -1
- package/dist/plugins/token-stats/control.js +1 -1
- package/dist/plugins/token-stats/control.js.map +3 -3
- package/dist/plugins/token-stats/index.js +1 -1
- package/dist/plugins/token-stats/index.js.map +3 -3
- 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
|
-
|
|
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
|
|
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
|
|
1760
|
-
if (
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
2060
|
+
trackCompletion(streamCompletion);
|
|
1993
2061
|
return {
|
|
1994
|
-
response: mark(new Response(converted.body, {
|
|
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
|
|
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:
|
|
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=
|
|
2131
|
+
//# debugId=E48A263F3FBDCAF664756E2164756E21
|