@jeffusion/bungee-core 5.4.1 → 5.4.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.
@@ -14823,15 +14823,47 @@ function definePlugin(plugin) {
14823
14823
  return plugin;
14824
14824
  }
14825
14825
 
14826
+ // plugins/chatgpt-oauth/server/error-diagnostics.ts
14827
+ var MAX_MESSAGE_CHARS = 1024;
14828
+ function errorDiagnostic(value, source, fallback, redact) {
14829
+ const object = value !== null && typeof value === "object" ? value : {};
14830
+ const clean = (value) => {
14831
+ let text = value.slice(0, 16384);
14832
+ text = redact?.(text) ?? text;
14833
+ text = text.replace(/\bBearer\s+[^\s,;"'<>]+/gi, "Bearer [REDACTED]").replace(/\b(?:sk-[\w-]+|eyJ[\w-]+\.[\w-]+\.[\w-]+)/g, "[REDACTED]").replace(/((?:authorization|access_token|refresh_token|id_token|api[_-]?key|cookie)["']?\s*[=:]\s*["']?)[^\s,;&"'<>]+/gi, "$1[REDACTED]").replace(/[\x00-\x1f\x7f]+/g, " ");
14834
+ return text.slice(0, MAX_MESSAGE_CHARS).trim();
14835
+ };
14836
+ const identifier = (value) => {
14837
+ if (typeof value !== "string")
14838
+ return;
14839
+ const text = clean(value);
14840
+ return /^[a-zA-Z0-9_.-]{1,128}$/.test(text) ? text : undefined;
14841
+ };
14842
+ const cause = source === "transport" && object.cause !== null && typeof object.cause === "object" ? object.cause : {};
14843
+ const message = clean([
14844
+ typeof object.message === "string" ? object.message : "",
14845
+ typeof cause.message === "string" ? cause.message : ""
14846
+ ].filter(Boolean).join("; "));
14847
+ const code = identifier(object.code ?? cause.code);
14848
+ const type = identifier(source === "transport" ? object.name ?? object.type : object.type);
14849
+ return { source, message: message || fallback, ...code ? { code } : {}, ...type ? { type } : {} };
14850
+ }
14851
+ function upstreamErrorDiagnostic(value, fallback, redact) {
14852
+ const object = value !== null && typeof value === "object" ? value : {};
14853
+ return errorDiagnostic(object.response?.error ?? object.error ?? object, "upstream", fallback, redact);
14854
+ }
14855
+
14826
14856
  // plugins/chatgpt-oauth/server/codex-protocol.ts
14827
14857
  class CodexProtocolError extends Error {
14828
14858
  kind;
14829
14859
  reason;
14830
- constructor(kind, message, reason) {
14860
+ diagnostic;
14861
+ constructor(kind, message, reason, diagnostic) {
14831
14862
  super(message);
14832
14863
  this.name = "CodexProtocolError";
14833
14864
  this.kind = kind;
14834
14865
  this.reason = reason;
14866
+ this.diagnostic = diagnostic;
14835
14867
  }
14836
14868
  }
14837
14869
  var UNSUPPORTED_RESPONSES_FIELDS = [
@@ -15349,9 +15381,11 @@ class CodexResponseProcessor {
15349
15381
  toolIndex = 0;
15350
15382
  outputOrder = 0;
15351
15383
  sawDone = false;
15384
+ redactDiagnostic;
15352
15385
  constructor(options = {}) {
15353
15386
  this.includeUsage = options.includeUsage ?? (options.request ? streamIncludesUsage(options.request) : false);
15354
15387
  this.target = options.target ?? "chat";
15388
+ this.redactDiagnostic = options.redactDiagnostic;
15355
15389
  }
15356
15390
  validateOutputItem(item) {
15357
15391
  if (this.target === "responses")
@@ -15456,18 +15490,18 @@ class CodexResponseProcessor {
15456
15490
  return [];
15457
15491
  }
15458
15492
  if (type === "response.failed" || data.response?.status === "failed")
15459
- throw new CodexProtocolError("failed", "Codex response failed");
15493
+ throw new CodexProtocolError("failed", "Codex response failed", undefined, upstreamErrorDiagnostic(data, "Codex response failed", this.redactDiagnostic));
15460
15494
  if (this.sawDone && !this.terminal)
15461
15495
  throw new CodexProtocolError("incomplete", "Codex emitted an event after [DONE] without a terminal response");
15462
15496
  if (this.terminal) {
15463
15497
  if (type === "error" || type === "response.failed")
15464
- throw new CodexProtocolError("failed", "Codex response failed after terminal event");
15498
+ throw new CodexProtocolError("failed", "Codex response failed after terminal event", undefined, upstreamErrorDiagnostic(data, "Codex response failed after terminal event", this.redactDiagnostic));
15465
15499
  if (type === "response.completed" || type === "response.incomplete")
15466
15500
  return [];
15467
15501
  return [];
15468
15502
  }
15469
15503
  if (type === "error")
15470
- throw new CodexProtocolError("failed", "Codex response contained an error event");
15504
+ throw new CodexProtocolError("failed", "Codex response contained an error event", undefined, upstreamErrorDiagnostic(data, "Codex response contained an error event", this.redactDiagnostic));
15471
15505
  if (type === "response.created" || type === "response.in_progress") {
15472
15506
  const response = data.response ?? {};
15473
15507
  this.responseId ||= String(response.id ?? "");
@@ -15861,10 +15895,10 @@ function responseHeaders(response, contentType) {
15861
15895
  headers.set("content-type", contentType);
15862
15896
  return headers;
15863
15897
  }
15864
- function safeErrorBody() {
15865
- return JSON.stringify({ error: { message: "Upstream response could not be adapted", type: "upstream_error", code: "upstream_error" } });
15898
+ function errorBody(error, fallbackCode = "upstream_error") {
15899
+ return { message: error?.message ?? "Upstream response could not be adapted", type: error?.type ?? "upstream_error", code: error?.code ?? fallbackCode };
15866
15900
  }
15867
- function completionFromError(error) {
15901
+ function completionFromError(error, redact) {
15868
15902
  if (error instanceof CodexProtocolError) {
15869
15903
  if (error.kind === "cancelled")
15870
15904
  return { status: "cancelled" };
@@ -15872,12 +15906,54 @@ function completionFromError(error) {
15872
15906
  return { status: "incomplete", code: "incomplete" };
15873
15907
  if (error.kind === "unexpected_eof")
15874
15908
  return { status: "failed", code: "unexpected_eof" };
15875
- return { status: "failed", code: error.kind };
15909
+ return { status: "failed", code: error.kind, ...error.diagnostic ? {
15910
+ error: errorDiagnostic(error.diagnostic, error.diagnostic.source, error.message, redact)
15911
+ } : {} };
15876
15912
  }
15877
15913
  if (error instanceof CodexModelsError) {
15878
15914
  return error.kind === "aborted" ? { status: "cancelled" } : { status: "failed", code: error.kind };
15879
15915
  }
15880
- return { status: "failed", code: "body_error" };
15916
+ return { status: "failed", code: "body_error", error: errorDiagnostic(error, "transport", "Upstream response body could not be read", redact) };
15917
+ }
15918
+ async function readHttpError(response, context) {
15919
+ if (!response.body)
15920
+ return { status: "failed", code: "upstream_http_error" };
15921
+ const reader = response.body.getReader();
15922
+ const decoder = new TextDecoder;
15923
+ const signal = AbortSignal.any([context.signal, AbortSignal.timeout(1000)]);
15924
+ let text = "";
15925
+ let bytes = 0;
15926
+ try {
15927
+ for (;; ) {
15928
+ const next = await readWithSignal(reader, signal);
15929
+ if (next.done)
15930
+ break;
15931
+ bytes += next.value?.byteLength ?? 0;
15932
+ if (bytes > MAX_DISCARD_BYTES) {
15933
+ reader.cancel("body_limit").catch(() => {
15934
+ return;
15935
+ });
15936
+ return { status: "failed", code: "body_limit" };
15937
+ }
15938
+ text += decoder.decode(next.value, { stream: true });
15939
+ }
15940
+ const body = JSON.parse(text + decoder.decode());
15941
+ const error = body?.error;
15942
+ if (error && typeof error === "object" && !Array.isArray(error)) {
15943
+ return { status: "failed", code: "upstream_http_error", error: errorDiagnostic(error, "upstream", "Upstream returned an HTTP error", context.redactDiagnostic) };
15944
+ }
15945
+ } catch (error) {
15946
+ reader.cancel("error capture stopped").catch(() => {
15947
+ return;
15948
+ });
15949
+ if (context.signal.aborted)
15950
+ return { status: "cancelled" };
15951
+ } finally {
15952
+ try {
15953
+ reader.releaseLock();
15954
+ } catch {}
15955
+ }
15956
+ return { status: "failed", code: "upstream_http_error" };
15881
15957
  }
15882
15958
  function joinCompletion(upstream, body, signal) {
15883
15959
  const safe = (promise) => promise.catch(() => ({ status: "failed", code: "upstream_completion" }));
@@ -15995,7 +16071,7 @@ function serialize(event) {
15995
16071
 
15996
16072
  `;
15997
16073
  }
15998
- function protocolStreamBody(source, target, includeUsage, signal) {
16074
+ function protocolStreamBody(source, target, includeUsage, signal, redact) {
15999
16075
  const protocolController = new AbortController;
16000
16076
  const onAbort = () => protocolController.abort(signal.reason ?? "cancelled");
16001
16077
  if (signal.aborted)
@@ -16013,7 +16089,7 @@ function protocolStreamBody(source, target, includeUsage, signal) {
16013
16089
  const completion = new Promise((resolve) => {
16014
16090
  resolveCompletion = resolve;
16015
16091
  });
16016
- const processor = new CodexResponseProcessor({ target, includeUsage });
16092
+ const processor = new CodexResponseProcessor({ target, includeUsage, redactDiagnostic: redact });
16017
16093
  let terminalOutcome;
16018
16094
  const events = parseCodexSSE(source, { signal: protocolController.signal });
16019
16095
  const iterator = async function* () {
@@ -16040,8 +16116,18 @@ function protocolStreamBody(source, target, includeUsage, signal) {
16040
16116
  `;
16041
16117
  settle(outcome);
16042
16118
  } catch (error) {
16043
- const outcome = completionFromError(error);
16119
+ const outcome = completionFromError(error, redact);
16044
16120
  settle(outcome.status === "cancelled" ? terminalOutcome ?? outcome : outcome);
16121
+ if (outcome.status === "failed" && outcome.error) {
16122
+ const safe = errorBody(outcome.error, outcome.code);
16123
+ yield target === "responses" ? `event: error
16124
+ data: ${JSON.stringify({ type: "error", code: safe.code, message: safe.message, param: null, error: safe })}
16125
+
16126
+ ` : `data: ${JSON.stringify({ error: safe })}
16127
+
16128
+ `;
16129
+ return;
16130
+ }
16045
16131
  throw error;
16046
16132
  } finally {
16047
16133
  signal.removeEventListener("abort", onAbort);
@@ -16152,8 +16238,8 @@ class ChatgptOauthAdapter {
16152
16238
  current.adaptedResponses.add(response);
16153
16239
  return response;
16154
16240
  };
16155
- const errorResponse = (status, completion) => {
16156
- const response = mark(new Response(safeErrorBody(), {
16241
+ const errorResponse = (status, completion, error) => {
16242
+ const response = mark(new Response(JSON.stringify({ error: errorBody(error) }), {
16157
16243
  status,
16158
16244
  statusText: result.response.statusText,
16159
16245
  headers: responseHeaders(result.response, "application/json; charset=utf-8")
@@ -16162,8 +16248,8 @@ class ChatgptOauthAdapter {
16162
16248
  return { response, completion };
16163
16249
  };
16164
16250
  if (!result.response.ok) {
16165
- const bodyCompletion = discardBody(result.response, context.signal).then((outcome) => outcome.status === "completed" ? { status: "failed", code: "upstream_http_error" } : outcome);
16166
- return errorResponse(result.response.status, joinCompletion(result.completion, bodyCompletion, context.signal));
16251
+ const failure = await readHttpError(result.response, context);
16252
+ return errorResponse(result.response.status, joinCompletion(result.completion, Promise.resolve(failure), context.signal), "error" in failure ? failure.error : undefined);
16167
16253
  }
16168
16254
  if (state.target === "models") {
16169
16255
  if (!isJsonContentType(result.response)) {
@@ -16188,7 +16274,8 @@ class ChatgptOauthAdapter {
16188
16274
  completion.then(cleanup, cleanup);
16189
16275
  return { response, completion };
16190
16276
  } catch (error) {
16191
- return errorResponse(502, joinCompletion(result.completion, Promise.resolve(completionFromError(error)), context.signal));
16277
+ const failure = completionFromError(error, context.redactDiagnostic);
16278
+ return errorResponse(502, joinCompletion(result.completion, Promise.resolve(failure), context.signal), "error" in failure ? failure.error : undefined);
16192
16279
  }
16193
16280
  }
16194
16281
  const contentType = result.response.headers.get("content-type");
@@ -16199,7 +16286,7 @@ class ChatgptOauthAdapter {
16199
16286
  return errorResponse(502, joinCompletion(result.completion, bodyCompletion, context.signal));
16200
16287
  }
16201
16288
  if (state.stream) {
16202
- const converted = protocolStreamBody(result.response.body, state.target, state.includeUsage, context.signal);
16289
+ const converted = protocolStreamBody(result.response.body, state.target, state.includeUsage, context.signal, context.redactDiagnostic);
16203
16290
  const streamCompletion = joinCompletion(result.completion, converted.completion, context.signal);
16204
16291
  streamCompletion.then(cleanup, cleanup);
16205
16292
  return {
@@ -16211,7 +16298,8 @@ class ChatgptOauthAdapter {
16211
16298
  const stateResult = await consumeCodexResponse(result.response.body, {
16212
16299
  signal: context.signal,
16213
16300
  request: { stream_options: { include_usage: state.includeUsage } },
16214
- target: state.target
16301
+ target: state.target,
16302
+ redactDiagnostic: context.redactDiagnostic
16215
16303
  });
16216
16304
  const body = state.target === "chat" ? responsesToChatCompletion(stateResult.response) : stateResult.response;
16217
16305
  const protocolCompletion = Promise.resolve(stateResult.terminal === "completed" ? { status: "completed" } : { status: "incomplete", code: "incomplete" });
@@ -16219,9 +16307,9 @@ class ChatgptOauthAdapter {
16219
16307
  nonStreamCompletion.then(cleanup, cleanup);
16220
16308
  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 };
16221
16309
  } catch (error) {
16222
- const failure = completionFromError(error);
16310
+ const failure = completionFromError(error, context.redactDiagnostic);
16223
16311
  const failedCompletion = joinCompletion(result.completion, Promise.resolve(failure), context.signal);
16224
- return errorResponse(502, failedCompletion);
16312
+ return errorResponse(502, failedCompletion, "error" in failure ? failure.error : undefined);
16225
16313
  }
16226
16314
  }
16227
16315
  }
@@ -16252,4 +16340,4 @@ export {
16252
16340
  server_default as default
16253
16341
  };
16254
16342
 
16255
- //# debugId=A763904920EABC5C64756E2164756E21
16343
+ //# debugId=D19FB0DB9863C8D864756E2164756E21