@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.
- package/dist/main.js +64 -44
- package/dist/plugins/anthropic-request-sanitizer/index.js.map +1 -1
- package/dist/plugins/anthropic-tool-name-transformer/index.js.map +1 -1
- package/dist/plugins/chatgpt-oauth/control.js.map +1 -1
- package/dist/plugins/chatgpt-oauth/index.js.map +1 -1
- package/dist/plugins/codex-router/control.js.map +1 -1
- package/dist/plugins/codex-router/index.js +4 -4
- package/dist/plugins/codex-router/index.js.map +5 -5
- package/dist/plugins/deepseek-reasoning-fix/index.js.map +1 -1
- package/dist/plugins/key-access/control.js.map +1 -1
- package/dist/plugins/key-access/index.js.map +1 -1
- package/dist/plugins/key-access/ingress.js.map +1 -1
- package/dist/plugins/key-rate-limit/index.js.map +1 -1
- package/dist/plugins/llm-protocol-adapter/control.js +53 -28
- package/dist/plugins/llm-protocol-adapter/control.js.map +9 -9
- package/dist/plugins/llm-protocol-adapter/index.js +58 -33
- package/dist/plugins/llm-protocol-adapter/index.js.map +10 -10
- package/dist/plugins/llm-tps/index.js.map +1 -1
- package/dist/plugins/model-mapping/index.js.map +1 -1
- package/dist/plugins/models-dev/index.js.map +1 -1
- package/dist/plugins/signature-repair/index.js.map +1 -1
- package/dist/plugins/token-budget/control.js.map +1 -1
- package/dist/plugins/token-budget/index.js.map +1 -1
- package/dist/plugins/token-metering/index.js.map +2 -2
- package/dist/plugins/token-stats/control.js.map +1 -1
- package/dist/plugins/token-stats/index.js.map +1 -1
- package/dist/plugins/user-auth/control.js.map +1 -1
- package/dist/plugins/user-auth/index.js.map +1 -1
- 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
|
|
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
|
-
|
|
5272
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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=
|
|
6905
|
+
//# debugId=6F3A86A34BE6620564756E2164756E21
|