@jeffusion/bungee-core 6.11.1 → 6.11.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.
Files changed (29) hide show
  1. package/dist/main.js +64 -44
  2. package/dist/plugins/anthropic-request-sanitizer/index.js.map +1 -1
  3. package/dist/plugins/anthropic-tool-name-transformer/index.js.map +1 -1
  4. package/dist/plugins/chatgpt-oauth/control.js.map +1 -1
  5. package/dist/plugins/chatgpt-oauth/index.js.map +1 -1
  6. package/dist/plugins/codex-router/control.js.map +1 -1
  7. package/dist/plugins/codex-router/index.js +4 -4
  8. package/dist/plugins/codex-router/index.js.map +5 -5
  9. package/dist/plugins/deepseek-reasoning-fix/index.js.map +1 -1
  10. package/dist/plugins/key-access/control.js.map +1 -1
  11. package/dist/plugins/key-access/index.js.map +1 -1
  12. package/dist/plugins/key-access/ingress.js.map +1 -1
  13. package/dist/plugins/key-rate-limit/index.js.map +1 -1
  14. package/dist/plugins/llm-protocol-adapter/control.js +53 -28
  15. package/dist/plugins/llm-protocol-adapter/control.js.map +9 -9
  16. package/dist/plugins/llm-protocol-adapter/index.js +58 -33
  17. package/dist/plugins/llm-protocol-adapter/index.js.map +10 -10
  18. package/dist/plugins/llm-tps/index.js.map +1 -1
  19. package/dist/plugins/model-mapping/index.js.map +1 -1
  20. package/dist/plugins/models-dev/index.js.map +1 -1
  21. package/dist/plugins/signature-repair/index.js.map +1 -1
  22. package/dist/plugins/token-budget/control.js.map +1 -1
  23. package/dist/plugins/token-budget/index.js.map +1 -1
  24. package/dist/plugins/token-metering/index.js.map +2 -2
  25. package/dist/plugins/token-stats/control.js.map +1 -1
  26. package/dist/plugins/token-stats/index.js.map +1 -1
  27. package/dist/plugins/user-auth/control.js.map +1 -1
  28. package/dist/plugins/user-auth/index.js.map +1 -1
  29. package/package.json +2 -2
@@ -3631,6 +3631,8 @@ function decodeResponsesRequest(raw, protocol, capabilities = {}, options = {})
3631
3631
  const callIds = new Set;
3632
3632
  const callToolNames = new Map;
3633
3633
  const answered = new Set;
3634
+ const deferredInstructions = [];
3635
+ const normalizeChatHistory = protocol === "chat_completions" && !options.preserveContentOrder;
3634
3636
  const projectedToolImages = [];
3635
3637
  let pendingReasoning = "";
3636
3638
  const addMessage = (message) => {
@@ -3656,6 +3658,8 @@ function decodeResponsesRequest(raw, protocol, capabilities = {}, options = {})
3656
3658
  flushToolImages();
3657
3659
  if (item.type === "additional_tools")
3658
3660
  return;
3661
+ if (deferredInstructions.length && item.type !== "function_call_output" && item.type !== "custom_tool_call_output" && !((item.type === undefined || item.type === "message") && (item.role === "system" || item.role === "developer")))
3662
+ fail("invalid_tool_history", "Only instructions and tool results may follow a deferred instruction until all tool results arrive", messageParam);
3659
3663
  if (item.type === "agent_message") {
3660
3664
  validateAgentMessage(item, messageParam, capabilities.limits);
3661
3665
  if (capabilities.agentMessageDelivery !== "plaintext")
@@ -3734,6 +3738,13 @@ function decodeResponsesRequest(raw, protocol, capabilities = {}, options = {})
3734
3738
  }
3735
3739
  }
3736
3740
  addMessage({ role: "tool", tool_call_id: id, content: output, ...item.is_error === true ? { is_error: true } : {} });
3741
+ if (callIds.size === answered.size) {
3742
+ for (const instruction of deferredInstructions) {
3743
+ messageParam = instruction.param;
3744
+ addMessage(instruction.message);
3745
+ }
3746
+ deferredInstructions.length = 0;
3747
+ }
3737
3748
  return;
3738
3749
  }
3739
3750
  if (item.type !== undefined && item.type !== "message")
@@ -3750,6 +3761,11 @@ function decodeResponsesRequest(raw, protocol, capabilities = {}, options = {})
3750
3761
  message.reasoning_content = pendingReasoning;
3751
3762
  pendingReasoning = "";
3752
3763
  }
3764
+ if (normalizeChatHistory && (role === "system" || role === "developer") && callIds.size !== answered.size) {
3765
+ deferredInstructions.push({ message, param: messageParam });
3766
+ diagnostics.push({ param: messageParam, action: "mapped", reason: "chat_instruction_deferred_until_tool_results" });
3767
+ return;
3768
+ }
3753
3769
  if (protocol === "chat_completions" && !options.preserveContentOrder && role === "assistant") {
3754
3770
  const previous = chat.at(-1);
3755
3771
  if (previous?.role === "assistant") {
@@ -3763,6 +3779,8 @@ function decodeResponsesRequest(raw, protocol, capabilities = {}, options = {})
3763
3779
  });
3764
3780
  if (pendingReasoning)
3765
3781
  fail("unsupported_reasoning", "Orphan reasoning history cannot be represented");
3782
+ if (deferredInstructions.length)
3783
+ fail("invalid_tool_history", "Deferred instructions require all pending tool results", deferredInstructions[0].param);
3766
3784
  flushToolImages(true);
3767
3785
  const result = { model, messages: chat };
3768
3786
  const omittedAllTools = !tools.length && diagnostics.some((item) => item.reason === "optional_hosted_web_search_unavailable");
@@ -3866,6 +3884,28 @@ function decodeResponsesRequest(raw, protocol, capabilities = {}, options = {})
3866
3884
  return { body: result, toolNames, canonicalInput, diagnostics };
3867
3885
  }
3868
3886
  // packages/llms/src/responses-codec/events.ts
3887
+ function chatOutput(raw) {
3888
+ const keys = ["role", "content", "refusal", "reasoning_content", "reasoning", "tool_calls", "function_call", "annotations"];
3889
+ const delta = Object.fromEntries(keys.filter((key) => raw[key] != null).map((key) => [key, raw[key]]));
3890
+ const provider = raw.provider_specific_fields == null ? {} : record(raw.provider_specific_fields, "provider_specific_fields");
3891
+ for (const key of ["refusal", "reasoning_content", "reasoning"]) {
3892
+ if (provider[key] == null)
3893
+ continue;
3894
+ if (delta[key] != null && delta[key] !== provider[key])
3895
+ fail("unsupported_content", "Conflicting provider output fields", `provider_specific_fields.${key}`);
3896
+ delta[key] = provider[key];
3897
+ }
3898
+ for (const key of ["audio", "thinking_blocks", "reasoning_details", "signature", "thought_signature", "thoughtSignature", "encrypted_content", "encrypted_function_args"])
3899
+ if (raw[key] != null || provider[key] != null)
3900
+ fail("unsupported_content", "Provider output authority cannot cross protocols", key);
3901
+ for (const key of ["content", "tool_calls", "function_call", "annotations"])
3902
+ if (provider[key] != null)
3903
+ fail("unsupported_content", "Nested provider output cannot cross protocols", `provider_specific_fields.${key}`);
3904
+ if (delta.reasoning_content != null && delta.reasoning != null && delta.reasoning_content !== delta.reasoning)
3905
+ fail("unsupported_content", "Conflicting reasoning fields", "reasoning");
3906
+ return delta;
3907
+ }
3908
+
3869
3909
  class ResponsesEventEncoder {
3870
3910
  protocol;
3871
3911
  model;
@@ -4075,10 +4115,7 @@ class ResponsesEventEncoder {
4075
4115
  const choice = record(choices[0], "choice");
4076
4116
  if (choice.index !== undefined && choice.index !== 0)
4077
4117
  fail("unsupported_response", "Only choice index 0 is supported");
4078
- const delta = record(choice.delta ?? {}, "choice delta");
4079
- for (const key of Object.keys(delta))
4080
- if (!["role", "content", "refusal", "reasoning_content", "reasoning", "tool_calls", "function_call", "annotations"].includes(key))
4081
- fail("unsupported_content", `Unsupported Chat output field ${key}`);
4118
+ const delta = chatOutput(record(choice.delta ?? {}, "choice delta"));
4082
4119
  if (delta.annotations !== undefined && list(delta.annotations, "annotations").length)
4083
4120
  fail("unsupported_content", "Chat output annotations cannot be faithfully converted");
4084
4121
  if (delta.role !== undefined && delta.role !== "assistant")
@@ -4276,7 +4313,7 @@ function encodeResponsesResult(raw, protocol, model, toolNames = new Map, config
4276
4313
  const choice = record(choices[0], "choice");
4277
4314
  const message = record(choice.message, "message");
4278
4315
  const delta = { ...message };
4279
- if (message.tool_calls !== undefined)
4316
+ if (message.tool_calls != null)
4280
4317
  delta.tool_calls = list(message.tool_calls, "tool_calls").map((tool, index) => ({ ...record(tool, "tool call"), index }));
4281
4318
  encoder.push({ choices: [{ index: choice.index ?? 0, delta, finish_reason: choice.finish_reason }], usage: body.usage });
4282
4319
  } else {
@@ -5006,7 +5043,7 @@ function convertProtocolRequest(raw, context) {
5006
5043
  fail("unsupported_reasoning", "Source thinking mode needs an explicit target wire policy", "thinking");
5007
5044
  }
5008
5045
  if (target === "responses") {
5009
- const validation = decodeResponsesRequest({ ...b, reasoning: reasoning ? { ...reasoning, effort: undefined } : undefined }, "chat_completions", { ...cap, reasoningHistory: true });
5046
+ const validation = decodeResponsesRequest({ ...b, reasoning: reasoning ? { ...reasoning, effort: undefined } : undefined }, "chat_completions", { ...cap, reasoningHistory: true }, { preserveContentOrder: true, toolOutputImages: true });
5010
5047
  if (mappedEffort !== undefined)
5011
5048
  b.reasoning = { ...reasoning, effort: mappedEffort };
5012
5049
  else if (reasoning?.effort !== undefined)
@@ -5265,20 +5302,14 @@ function validateProviderResponse(raw, protocol) {
5265
5302
  if (b.error !== undefined || b.type === "error")
5266
5303
  return b;
5267
5304
  if (protocol === "chat_completions") {
5268
- fields2(b, ["id", "object", "created", "model", "choices", "usage", "system_fingerprint", "service_tier"], "", "unsupported_response");
5269
5305
  for (const rawChoice of list(b.choices, "choices")) {
5270
5306
  const c = record(rawChoice, "choice");
5271
- fields2(c, ["index", "message", "finish_reason", "logprobs", "provider_specific_fields"], "choices", "unsupported_response");
5272
- if (c.provider_specific_fields !== undefined) {
5273
- const providerFields = c.provider_specific_fields;
5274
- if (providerFields === null || typeof providerFields !== "object" || Array.isArray(providerFields) || Object.keys(providerFields).length)
5275
- fail("unsupported_response", "Only empty provider-specific choice fields are portable", "choices.provider_specific_fields");
5276
- }
5307
+ if (c.provider_specific_fields != null)
5308
+ record(c.provider_specific_fields, "choices.provider_specific_fields");
5277
5309
  if (c.logprobs != null)
5278
5310
  fail("unsupported_response", "Log probabilities cannot cross protocols", "choices.logprobs");
5279
5311
  const m = record(c.message, "message");
5280
- fields2(m, ["role", "content", "refusal", "reasoning_content", "reasoning", "tool_calls", "annotations"], "message", "unsupported_content");
5281
- for (const [callIndex, rawCall] of (m.tool_calls === undefined ? [] : list(m.tool_calls, "tool_calls")).entries()) {
5312
+ for (const [callIndex, rawCall] of (m.tool_calls == null ? [] : list(m.tool_calls, "tool_calls")).entries()) {
5282
5313
  const call = record(rawCall, "call");
5283
5314
  fields2(call, ["id", "type", "function", "index"], "tool_calls", "unsupported_tool");
5284
5315
  if (call.index !== undefined && integer(call.index, `tool_calls[${callIndex}].index`) !== callIndex)
@@ -5288,7 +5319,6 @@ function validateProviderResponse(raw, protocol) {
5288
5319
  }
5289
5320
  validateUsage(b.usage, protocol);
5290
5321
  } else if (protocol === "anthropic_messages") {
5291
- fields2(b, ["id", "type", "role", "model", "content", "stop_reason", "stop_sequence", "usage"], "", "unsupported_response");
5292
5322
  if (b.role !== undefined && b.role !== "assistant")
5293
5323
  fail("unsupported_response", "Response role must be assistant", "role");
5294
5324
  for (const rawPart of list(b.content, "content"))
@@ -5494,7 +5524,6 @@ class GeminiCanonicalDecoder {
5494
5524
  }
5495
5525
  push(raw) {
5496
5526
  const b = record(raw, "Gemini response");
5497
- fields2(b, ["candidates", "usageMetadata", "modelVersion", "responseId", "promptFeedback", "error"], "", "unsupported_response");
5498
5527
  if (b.error !== undefined)
5499
5528
  return this.decorate(this.encoder.push({ error: safeProtocolError() }));
5500
5529
  const events = [];
@@ -5511,7 +5540,6 @@ class GeminiCanonicalDecoder {
5511
5540
  fail("unsupported_response", "Multiple Gemini candidates cannot cross protocols", "candidates");
5512
5541
  if (candidates.length) {
5513
5542
  const c = record(candidates[0], "candidate");
5514
- fields2(c, ["index", "content", "finishReason", "safetyRatings", "finishMessage"], "candidates", "unsupported_response");
5515
5543
  if (c.index !== undefined && c.index !== 0)
5516
5544
  fail("unsupported_response", "Only candidate index zero is supported", "candidates.index");
5517
5545
  if (c.content !== undefined && c.content !== null) {
@@ -6117,9 +6145,9 @@ function createProtocolSession(context) {
6117
6145
  fail("invalid_session", "A session can convert one JSON response or one stream");
6118
6146
  mode = "json";
6119
6147
  finished = true;
6148
+ const body = record(raw, "response");
6149
+ serialized(body, limits(context.capabilities?.limits).maxOutputBytes, "response");
6120
6150
  if (same) {
6121
- const body = record(raw, "response");
6122
- serialized(body, limits(context.capabilities?.limits).maxOutputBytes, "response");
6123
6151
  return body;
6124
6152
  }
6125
6153
  const canonical = canonicalResponse(raw, context, names);
@@ -6133,9 +6161,9 @@ function createProtocolSession(context) {
6133
6161
  if (finished || mode === "json")
6134
6162
  fail("invalid_stream", "Event arrived after session completion");
6135
6163
  mode = "stream";
6164
+ const e = record(raw, "event");
6165
+ serialized(e, limits(context.capabilities?.limits).maxOutputBytes, "event");
6136
6166
  if (same) {
6137
- const e = record(raw, "event");
6138
- serialized(e, limits(context.capabilities?.limits).maxOutputBytes, "event");
6139
6167
  if (context.targetProtocol === "anthropic_messages") {
6140
6168
  if (passAnthropicStopped)
6141
6169
  fail("invalid_stream", "Event arrived after message_stop");
@@ -6213,11 +6241,11 @@ function validateStreamEnvelope(raw, protocol) {
6213
6241
  if (e.error !== undefined || e.type === "error")
6214
6242
  return;
6215
6243
  if (protocol === "chat_completions") {
6216
- fields2(e, ["id", "object", "created", "model", "choices", "usage", "system_fingerprint", "service_tier"], "", "unsupported_response");
6217
6244
  if (Array.isArray(e.choices))
6218
6245
  for (const rawChoice of e.choices) {
6219
6246
  const c = record(rawChoice, "choice");
6220
- fields2(c, ["index", "delta", "finish_reason", "logprobs"], "choices", "unsupported_response");
6247
+ if (c.provider_specific_fields != null)
6248
+ record(c.provider_specific_fields, "choices.provider_specific_fields");
6221
6249
  if (c.logprobs != null)
6222
6250
  fail("unsupported_response", "Log probabilities cannot cross protocols", "choices.logprobs");
6223
6251
  const d = record(c.delta ?? {}, "delta");
@@ -6231,8 +6259,6 @@ function validateStreamEnvelope(raw, protocol) {
6231
6259
  }
6232
6260
  validateUsage(e.usage, protocol);
6233
6261
  } else {
6234
- const allowed = e.type === "message_start" ? ["type", "message"] : e.type === "message_delta" ? ["type", "delta", "usage"] : e.type === "content_block_start" ? ["type", "index", "content_block"] : e.type === "content_block_delta" ? ["type", "index", "delta"] : e.type === "content_block_stop" ? ["type", "index"] : ["type"];
6235
- fields2(e, allowed, "", "unsupported_response");
6236
6262
  if (e.type === "content_block_start")
6237
6263
  validateAnthropicBlock(record(e.content_block, "block"), "content_block");
6238
6264
  if (e.type === "content_block_delta") {
@@ -6245,7 +6271,6 @@ function validateStreamEnvelope(raw, protocol) {
6245
6271
  fields2(record(e.delta, "delta"), ["stop_reason", "stop_sequence"], "delta", "unsupported_response");
6246
6272
  if (e.type === "message_start") {
6247
6273
  const m = record(e.message, "message");
6248
- fields2(m, ["id", "type", "role", "model", "content", "stop_reason", "stop_sequence", "usage"], "message", "unsupported_response");
6249
6274
  validateUsage(m.usage, protocol);
6250
6275
  if (m.content !== undefined && (!Array.isArray(m.content) || m.content.length))
6251
6276
  fail("unsupported_content", "Initial stream message content must be empty", "message.content");
@@ -6877,4 +6902,4 @@ export {
6877
6902
  control_default as default
6878
6903
  };
6879
6904
 
6880
- //# debugId=C05F1FFA2AD4DDAA64756E2164756E21
6905
+ //# debugId=6F3A86A34BE6620564756E2164756E21