@jeffusion/bungee-core 5.4.2 → 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.
package/dist/main.js CHANGED
@@ -12955,7 +12955,7 @@ var package_default;
12955
12955
  var init_package = __esm(() => {
12956
12956
  package_default = {
12957
12957
  name: "@jeffusion/bungee-core",
12958
- version: "5.4.2",
12958
+ version: "5.4.3",
12959
12959
  description: "Bungee reverse proxy core engine",
12960
12960
  main: "./dist/main.js",
12961
12961
  types: "./dist/main.d.ts",
@@ -30326,7 +30326,7 @@ class AccessLogWriter {
30326
30326
  entry.protocolOutcome = pendingOutcome.outcome;
30327
30327
  entry.protocolCode = pendingOutcome.code;
30328
30328
  entry.success = pendingOutcome.success;
30329
- entry.errorMessage ??= pendingOutcome.errorMessage;
30329
+ entry.errorMessage = pendingOutcome.detailed ? pendingOutcome.errorMessage : entry.errorMessage ?? pendingOutcome.errorMessage;
30330
30330
  }
30331
30331
  this.writeQueue.push(entry);
30332
30332
  if (this.writeQueue.length >= 100) {
@@ -30392,7 +30392,7 @@ class AccessLogWriter {
30392
30392
  entry.protocolOutcome = pendingOutcome.outcome;
30393
30393
  entry.protocolCode = pendingOutcome.code;
30394
30394
  entry.success = pendingOutcome.success;
30395
- entry.errorMessage ??= pendingOutcome.errorMessage;
30395
+ entry.errorMessage = pendingOutcome.detailed ? pendingOutcome.errorMessage : entry.errorMessage ?? pendingOutcome.errorMessage;
30396
30396
  }
30397
30397
  this.db.run("SAVEPOINT access_log_entry");
30398
30398
  try {
@@ -30479,7 +30479,7 @@ class AccessLogWriter {
30479
30479
  });
30480
30480
  }
30481
30481
  }
30482
- updateProtocolOutcome(requestId, outcome, success, code) {
30482
+ updateProtocolOutcome(requestId, outcome, success, code, diagnosticMessage) {
30483
30483
  if (!requestId)
30484
30484
  return;
30485
30485
  if (!this.pendingProtocolOutcomeUpdates.has(requestId) && this.pendingProtocolOutcomeUpdates.size >= AccessLogWriter.MAX_PENDING_UPDATES) {
@@ -30487,18 +30487,19 @@ class AccessLogWriter {
30487
30487
  if (oldest)
30488
30488
  this.pendingProtocolOutcomeUpdates.delete(oldest);
30489
30489
  }
30490
- const errorMessage = outcome === "failed" || outcome === "incomplete" ? `Response stream ${outcome}${code ? ` (${code})` : ""}` : undefined;
30491
- this.pendingProtocolOutcomeUpdates.set(requestId, { outcome, success, code, errorMessage });
30490
+ const errorMessage = diagnosticMessage ?? (outcome === "failed" || outcome === "incomplete" ? `Response stream ${outcome}${code ? ` (${code})` : ""}` : undefined);
30491
+ const detailed = diagnosticMessage !== undefined;
30492
+ this.pendingProtocolOutcomeUpdates.set(requestId, { outcome, success, code, errorMessage, detailed });
30492
30493
  for (const entry of this.writeQueue) {
30493
30494
  if (entry.requestId === requestId) {
30494
30495
  entry.protocolOutcome = outcome;
30495
30496
  entry.protocolCode = code;
30496
30497
  entry.success = success;
30497
- entry.errorMessage ??= errorMessage;
30498
+ entry.errorMessage = detailed ? errorMessage : entry.errorMessage ?? errorMessage;
30498
30499
  }
30499
30500
  }
30500
30501
  try {
30501
- const result = this.db.query("UPDATE access_logs SET protocol_outcome = ?, protocol_code = ?, success = ?, error_message = COALESCE(error_message, ?) WHERE request_id = ?").run(outcome, code || null, success ? 1 : 0, errorMessage ?? null, requestId);
30502
+ const result = this.db.query("UPDATE access_logs SET protocol_outcome = ?, protocol_code = ?, success = ?, error_message = CASE WHEN ? THEN ? ELSE COALESCE(error_message, ?) END WHERE request_id = ?").run(outcome, code || null, success ? 1 : 0, detailed ? 1 : 0, errorMessage ?? null, errorMessage ?? null, requestId);
30502
30503
  if (result.changes > 0)
30503
30504
  this.pendingProtocolOutcomeUpdates.delete(requestId);
30504
30505
  } catch (error) {
@@ -34917,6 +34918,13 @@ var init_plugin_manager = __esm(() => {
34917
34918
  });
34918
34919
 
34919
34920
  // src/logger/request-logger.ts
34921
+ function diagnosticMessage(error) {
34922
+ if (!error)
34923
+ return;
34924
+ const kind = [error.code, error.type].filter(Boolean).join(" / ");
34925
+ return `[${error.source}] ${kind ? `${kind}: ` : ""}${error.message}`;
34926
+ }
34927
+
34920
34928
  class RequestLogger {
34921
34929
  requestId;
34922
34930
  startTime;
@@ -34941,6 +34949,7 @@ class RequestLogger {
34941
34949
  completionPromise = null;
34942
34950
  fileLogEntry = null;
34943
34951
  fileLogWritten = false;
34952
+ protocolError;
34944
34953
  dependencies;
34945
34954
  constructor(req, failoverOptions, dependencies = {}) {
34946
34955
  this.dependencies = {
@@ -35062,6 +35071,10 @@ class RequestLogger {
35062
35071
  if (this.originalRequestBody && this.dependencies.bodyStorage) {
35063
35072
  originalReqBodyId = await this.saveBody(this.originalRequestBody, "original-request");
35064
35073
  }
35074
+ const protocolError = options?.protocolError ?? this.protocolError;
35075
+ const errorMessage = diagnosticMessage(protocolError) ?? options?.errorMessage;
35076
+ if (protocolError)
35077
+ this.addStep("response_error", protocolError);
35065
35078
  const logEntry = {
35066
35079
  requestId: this.requestId,
35067
35080
  timestamp: this.startTime,
@@ -35086,7 +35099,8 @@ class RequestLogger {
35086
35099
  protocolOutcome: options?.protocolOutcome,
35087
35100
  protocolCode: options?.protocolCode,
35088
35101
  success: options?.success,
35089
- ...options
35102
+ ...options,
35103
+ errorMessage
35090
35104
  };
35091
35105
  this.fileLogEntry = {
35092
35106
  requestId: this.requestId,
@@ -35102,7 +35116,7 @@ class RequestLogger {
35102
35116
  transformedPath: this.transformedPath || undefined,
35103
35117
  authSuccess: options?.authSuccess,
35104
35118
  authLevel: options?.authLevel,
35105
- errorMessage: options?.errorMessage,
35119
+ errorMessage,
35106
35120
  reqBodyId: reqBodyId || undefined,
35107
35121
  respBodyId: respBodyId || undefined,
35108
35122
  reqHeaderId: reqHeaderId || undefined,
@@ -35161,8 +35175,9 @@ class RequestLogger {
35161
35175
  updateStreamResponseBodyId(bodyId) {
35162
35176
  this.dependencies.accessLogWriter.updateResponseBodyId(this.requestId, bodyId);
35163
35177
  }
35164
- updateProtocolOutcome(outcome, success, code) {
35165
- this.dependencies.accessLogWriter.updateProtocolOutcome(this.requestId, outcome, success, code);
35178
+ updateProtocolOutcome(outcome, success, code, error) {
35179
+ this.protocolError = error;
35180
+ this.dependencies.accessLogWriter.updateProtocolOutcome(this.requestId, outcome, success, code, diagnosticMessage(error));
35166
35181
  }
35167
35182
  getRequestId() {
35168
35183
  return this.requestId;
@@ -37430,6 +37445,9 @@ function immutableSnapshot(value) {
37430
37445
  function isSafeUpstreamHttpError(originalResponse, originalStatus, rawResponse, finalResponse, completion) {
37431
37446
  return (originalStatus < 200 || originalStatus >= 300) && rawResponse.response !== originalResponse && rawResponse.response.status === originalStatus && finalResponse.status === originalStatus && (originalResponse.body === null || originalResponse.bodyUsed) && completion.status === "failed" && completion.code === "upstream_http_error";
37432
37447
  }
37448
+ function isSafeAdaptedErrorResponse(originalResponse, rawResponse, finalResponse, completion) {
37449
+ return completion.status === "failed" && completion.error !== undefined && rawResponse.response !== originalResponse && (originalResponse.body === null || originalResponse.bodyUsed) && rawResponse.response.status >= 400 && rawResponse.response.status < 600 && finalResponse.status === rawResponse.response.status && rawResponse.response.headers.get("content-type")?.split(";", 1)[0].trim().toLowerCase() === "application/json";
37450
+ }
37433
37451
  function inspectManagedCredential(upstream) {
37434
37452
  const endpoint = upstream;
37435
37453
  if (!isManagedBy(endpoint.managedBy))
@@ -37947,6 +37965,7 @@ async function proxyRequest(requestSnapshot, route, upstream, requestLog, config
37947
37965
  redirect: "manual",
37948
37966
  keepalive: true,
37949
37967
  verbose: false,
37968
+ timeout: false,
37950
37969
  signal: attemptSignal
37951
37970
  };
37952
37971
  try {
@@ -37983,6 +38002,7 @@ async function proxyRequest(requestSnapshot, route, upstream, requestLog, config
37983
38002
  redirect: fetchOptions.redirect,
37984
38003
  keepalive: fetchOptions.keepalive,
37985
38004
  verbose: fetchOptions.verbose,
38005
+ timeout: fetchOptions.timeout,
37986
38006
  hasBody: Boolean(fetchOptions.body),
37987
38007
  headerCount
37988
38008
  },
@@ -38149,7 +38169,8 @@ async function proxyRequest(requestSnapshot, route, upstream, requestLog, config
38149
38169
  routeId,
38150
38170
  upstreamId: upstream_id,
38151
38171
  attemptId: attemptOptions?.attemptId ?? requestId,
38152
- signal: attemptSignal
38172
+ signal: attemptSignal,
38173
+ redactDiagnostic: (message) => sanitizeMessage(message, credentialSecrets)
38153
38174
  }), attemptSignal, (lateResult) => {
38154
38175
  if (lateResult.response.body)
38155
38176
  lateResult.response.body.cancel("request aborted").catch(() => {
@@ -38246,7 +38267,7 @@ async function proxyRequest(requestSnapshot, route, upstream, requestLog, config
38246
38267
  transportCompletion.settle({ status: "completed" });
38247
38268
  const outcome = await abortable(strictCompletion, attemptSignal);
38248
38269
  logger.info({ request: requestLog, httpStatus: proxyRes.status, protocolOutcome: outcome.status }, "Upstream response protocol completed");
38249
- if (outcome.status !== "completed" && !isSafeUpstreamHttpError(originalResponse, originalStatus, rawResponse, proxyRes, outcome)) {
38270
+ if (outcome.status !== "completed" && !isSafeUpstreamHttpError(originalResponse, originalStatus, rawResponse, proxyRes, outcome) && !isSafeAdaptedErrorResponse(originalResponse, rawResponse, proxyRes, outcome)) {
38250
38271
  throw new Error(`raw response completed with ${outcome.status}:${"code" in outcome ? outcome.code : ""}`);
38251
38272
  }
38252
38273
  }
@@ -41049,7 +41070,7 @@ async function handleRequest(req, config, runtimeContextOrSelector = {}, selecto
41049
41070
  result.streamCompletionState.clientCancelled = outcome.status === "cancelled";
41050
41071
  result.streamCompletionState.interrupted = outcome.status === "failed" || outcome.status === "incomplete";
41051
41072
  }
41052
- attemptLogger.updateProtocolOutcome(outcome.status, persistedSuccess, "code" in outcome ? outcome.code : undefined);
41073
+ attemptLogger.updateProtocolOutcome(outcome.status, persistedSuccess, "code" in outcome ? outcome.code : undefined, "error" in outcome ? outcome.error : undefined);
41053
41074
  try {
41054
41075
  await onOutcome?.(outcome);
41055
41076
  } finally {
@@ -41595,6 +41616,7 @@ async function handleRequest(req, config, runtimeContextOrSelector = {}, selecto
41595
41616
  errorMessage: result.response.status >= 400 ? `Upstream returned error status: ${result.response.status}` : undefined,
41596
41617
  protocolOutcome: outcome.status,
41597
41618
  protocolCode: "code" in outcome ? outcome.code : undefined,
41619
+ protocolError: "error" in outcome ? outcome.error : undefined,
41598
41620
  success: outcome.status === "completed" && result.response.status < 400
41599
41621
  });
41600
41622
  } catch (logError) {
@@ -41610,6 +41632,7 @@ async function handleRequest(req, config, runtimeContextOrSelector = {}, selecto
41610
41632
  upstream: selectedUpstream.target,
41611
41633
  protocolOutcome: outcome.status,
41612
41634
  protocolCode: "code" in outcome ? outcome.code : undefined,
41635
+ protocolError: "error" in outcome ? outcome.error : undefined,
41613
41636
  success: outcome.status === "completed" && result.response.status < 400
41614
41637
  });
41615
41638
  } catch (logError) {
@@ -41810,6 +41833,7 @@ async function handleRequest(req, config, runtimeContextOrSelector = {}, selecto
41810
41833
  errorMessage: result.response.status >= 400 ? `Upstream returned error status: ${result.response.status}` : undefined,
41811
41834
  protocolOutcome: outcome.status,
41812
41835
  protocolCode: "code" in outcome ? outcome.code : undefined,
41836
+ protocolError: "error" in outcome ? outcome.error : undefined,
41813
41837
  success: outcome.status === "completed" && result.response.status < 400
41814
41838
  });
41815
41839
  } catch (logError) {
@@ -41837,6 +41861,7 @@ async function handleRequest(req, config, runtimeContextOrSelector = {}, selecto
41837
41861
  upstream: selectedUpstream.target,
41838
41862
  protocolOutcome: outcome.status,
41839
41863
  protocolCode: "code" in outcome ? outcome.code : undefined,
41864
+ protocolError: "error" in outcome ? outcome.error : undefined,
41840
41865
  success: outcome.status === "completed" && result.response.status < 400
41841
41866
  });
41842
41867
  } catch (logError) {
@@ -41864,6 +41889,7 @@ async function handleRequest(req, config, runtimeContextOrSelector = {}, selecto
41864
41889
  errorMessage: `Upstream returned retryable status code: ${result.response.status}`,
41865
41890
  protocolOutcome: outcome.status,
41866
41891
  protocolCode: "code" in outcome ? outcome.code : undefined,
41892
+ protocolError: "error" in outcome ? outcome.error : undefined,
41867
41893
  success: false
41868
41894
  });
41869
41895
  } catch (logError) {
@@ -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