@jeffusion/bungee-core 6.7.3 → 6.8.1
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 +1 -1
- package/dist/main.js +36 -28
- package/dist/plugins/codex-router/index.js +4 -4
- package/dist/plugins/codex-router/index.js.map +5 -5
- package/dist/plugins/llm-protocol-adapter/control.js +295 -47
- package/dist/plugins/llm-protocol-adapter/control.js.map +9 -8
- package/dist/plugins/llm-protocol-adapter/index.js +304 -48
- package/dist/plugins/llm-protocol-adapter/index.js.map +10 -9
- package/dist/plugins/llm-protocol-adapter/manifest.json +4 -0
- package/dist/plugins/token-metering/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -3379,7 +3379,7 @@ function definitionKey(value) {
|
|
|
3379
3379
|
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${definitionKey(value[key])}`).join(",")}}`;
|
|
3380
3380
|
return JSON.stringify(value);
|
|
3381
3381
|
}
|
|
3382
|
-
function decodeResponsesRequest(raw, protocol, capabilities = {}) {
|
|
3382
|
+
function decodeResponsesRequest(raw, protocol, capabilities = {}, options = {}) {
|
|
3383
3383
|
const body = record(raw, "Responses request");
|
|
3384
3384
|
if (capabilities.agentMessageDelivery !== undefined && capabilities.agentMessageDelivery !== "plaintext")
|
|
3385
3385
|
fail("invalid_payload", "Unknown agent message delivery policy", "agentMessageDelivery");
|
|
@@ -3646,12 +3646,16 @@ function decodeResponsesRequest(raw, protocol, capabilities = {}) {
|
|
|
3646
3646
|
if (item.content != null)
|
|
3647
3647
|
fail("unsupported_reasoning", "Reasoning content requires an explicit history mapping", `${messageParam}.content`);
|
|
3648
3648
|
const summary = list(item.summary, "reasoning summary");
|
|
3649
|
-
|
|
3649
|
+
const text = summary.map((part) => {
|
|
3650
3650
|
const p = record(part, "reasoning summary");
|
|
3651
3651
|
if (p.type !== "summary_text")
|
|
3652
3652
|
fail("unsupported_reasoning", "Unknown reasoning summary");
|
|
3653
3653
|
return string(p.text, "summary text");
|
|
3654
3654
|
}).join("");
|
|
3655
|
+
if (options.preserveContentOrder)
|
|
3656
|
+
addMessage({ role: "assistant", content: null, reasoning_content: text, ...item.id === undefined ? {} : { id: string(item.id, "item.id", true) } });
|
|
3657
|
+
else
|
|
3658
|
+
pendingReasoning += text;
|
|
3655
3659
|
return;
|
|
3656
3660
|
}
|
|
3657
3661
|
if (item.type === "function_call" || item.type === "custom_tool_call") {
|
|
@@ -3666,7 +3670,7 @@ function decodeResponsesRequest(raw, protocol, capabilities = {}) {
|
|
|
3666
3670
|
argumentObject(args);
|
|
3667
3671
|
const call = { id, type: "function", function: { name: resolve(item, custom), arguments: args } };
|
|
3668
3672
|
const previous = chat.at(-1);
|
|
3669
|
-
if (previous?.role === "assistant") {
|
|
3673
|
+
if (previous?.role === "assistant" && !options.preserveContentOrder) {
|
|
3670
3674
|
previous.tool_calls = [...previous.tool_calls ?? [], call];
|
|
3671
3675
|
if (pendingReasoning)
|
|
3672
3676
|
previous.reasoning_content = pendingReasoning;
|
|
@@ -3690,6 +3694,8 @@ function decodeResponsesRequest(raw, protocol, capabilities = {}) {
|
|
|
3690
3694
|
if (!["user", "assistant", "system", "developer"].includes(role))
|
|
3691
3695
|
fail("unsupported_content", "Unknown message role");
|
|
3692
3696
|
const message = { role, content: normalizeContent(item.content, role) };
|
|
3697
|
+
if (options.preserveContentOrder && item.id !== undefined)
|
|
3698
|
+
message.id = string(item.id, "item.id", true);
|
|
3693
3699
|
if (pendingReasoning) {
|
|
3694
3700
|
if (role !== "assistant")
|
|
3695
3701
|
fail("unsupported_reasoning", "Reasoning must precede an assistant item");
|
|
@@ -4230,6 +4236,9 @@ function encodeResponsesResult(raw, protocol, model, toolNames = new Map, config
|
|
|
4230
4236
|
fail("missing_terminal", "JSON response has no terminal result");
|
|
4231
4237
|
return record(end.response, "Responses result");
|
|
4232
4238
|
}
|
|
4239
|
+
// packages/llms/src/protocol-session/gemini.ts
|
|
4240
|
+
import { createHash } from "crypto";
|
|
4241
|
+
|
|
4233
4242
|
// packages/llms/src/protocol-session/validation.ts
|
|
4234
4243
|
function fields2(value, allowed, path, code = "unsupported_request") {
|
|
4235
4244
|
for (const key of Object.keys(value))
|
|
@@ -4274,6 +4283,145 @@ function textParts(raw, path, style, role) {
|
|
|
4274
4283
|
});
|
|
4275
4284
|
}
|
|
4276
4285
|
|
|
4286
|
+
// packages/llms/src/protocol-session/gemini.ts
|
|
4287
|
+
var signatureSeparator = "__thought__";
|
|
4288
|
+
function checkedSignature(value, maxBytes) {
|
|
4289
|
+
const signature = bounded(string(value, "thoughtSignature", true), maxBytes, "thoughtSignature");
|
|
4290
|
+
if (!/^[A-Za-z0-9+/]+={0,2}$/.test(signature) || signature.length % 4 === 1 || signature.includes("=") && signature.length % 4 !== 0 || Buffer.from(signature, "base64").toString("base64").replace(/=+$/, "") !== signature.replace(/=+$/, ""))
|
|
4291
|
+
fail("invalid_tool_arguments", "Invalid Gemini thought signature encoding", "thoughtSignature");
|
|
4292
|
+
return signature;
|
|
4293
|
+
}
|
|
4294
|
+
var envelopePrefix = "bungee_gemini:";
|
|
4295
|
+
var geminiEnvelopeBytes = (payloadBytes) => envelopePrefix.length + Math.ceil(payloadBytes * 4 / 3);
|
|
4296
|
+
var geminiTextHash = (text) => createHash("sha256").update(text).digest("base64url");
|
|
4297
|
+
function geminiSignatureItem(items, budget) {
|
|
4298
|
+
const payload = serialized({ version: 1, items }, budget.maxArgumentBytes, "Gemini signatures");
|
|
4299
|
+
return {
|
|
4300
|
+
type: "reasoning",
|
|
4301
|
+
id: `rs_gemini_${crypto.randomUUID().replaceAll("-", "")}`,
|
|
4302
|
+
summary: [],
|
|
4303
|
+
encrypted_content: bounded(envelopePrefix + Buffer.from(payload).toString("base64url"), budget.maxArgumentBytes, "Gemini signatures")
|
|
4304
|
+
};
|
|
4305
|
+
}
|
|
4306
|
+
function readGeminiSignatures(item, budget) {
|
|
4307
|
+
fields2(item, ["type", "id", "summary", "encrypted_content", "status"], "Gemini signatures", "unsupported_reasoning");
|
|
4308
|
+
if (item.type !== "reasoning" || list(item.summary, "summary").length)
|
|
4309
|
+
fail("unsupported_reasoning", "Invalid Gemini signature carrier");
|
|
4310
|
+
string(item.id, "signature item id", true);
|
|
4311
|
+
const opaque = bounded(string(item.encrypted_content, "encrypted_content", true), budget.maxArgumentBytes, "Gemini signatures");
|
|
4312
|
+
if (!opaque.startsWith(envelopePrefix))
|
|
4313
|
+
fail("unsupported_reasoning", "Native encrypted reasoning cannot be restored to Gemini");
|
|
4314
|
+
const encoded = opaque.slice(envelopePrefix.length), bytes = Buffer.from(encoded, "base64url");
|
|
4315
|
+
if (!encoded || bytes.toString("base64url") !== encoded)
|
|
4316
|
+
fail("unsupported_reasoning", "Invalid Gemini signature carrier encoding");
|
|
4317
|
+
let raw;
|
|
4318
|
+
try {
|
|
4319
|
+
raw = JSON.parse(bytes.toString("utf8"));
|
|
4320
|
+
} catch {
|
|
4321
|
+
fail("unsupported_reasoning", "Invalid Gemini signature carrier JSON");
|
|
4322
|
+
}
|
|
4323
|
+
const body = record(raw, "Gemini signatures");
|
|
4324
|
+
fields2(body, ["version", "items"], "Gemini signatures", "unsupported_reasoning");
|
|
4325
|
+
if (body.version !== 1)
|
|
4326
|
+
fail("unsupported_reasoning", "Unknown Gemini signature format");
|
|
4327
|
+
const ids = new Set;
|
|
4328
|
+
let partCount = 0;
|
|
4329
|
+
const result = list(body.items, "signature items").map((raw) => {
|
|
4330
|
+
const item = record(raw, "signature item");
|
|
4331
|
+
fields2(item, ["id", "thought", "parts"], "signature item", "unsupported_reasoning");
|
|
4332
|
+
const id = string(item.id, "signed item id", true);
|
|
4333
|
+
if (ids.has(id) || typeof item.thought !== "boolean")
|
|
4334
|
+
fail("unsupported_reasoning", "Invalid signed item identity");
|
|
4335
|
+
ids.add(id);
|
|
4336
|
+
const parts = list(item.parts, "signed parts").map((raw) => {
|
|
4337
|
+
if (++partCount > budget.maxItems)
|
|
4338
|
+
fail("resource_limit", "Too many signed Gemini parts");
|
|
4339
|
+
const part = record(raw, "signed part");
|
|
4340
|
+
fields2(part, ["length", "hash", "signature", "textAbsent"], "signed part", "unsupported_reasoning");
|
|
4341
|
+
const length = integer(part.length, "signed part length"), hash = string(part.hash, "signed part hash", true);
|
|
4342
|
+
if (!/^[A-Za-z0-9_-]{43}$/.test(hash))
|
|
4343
|
+
fail("unsupported_reasoning", "Invalid signed part hash");
|
|
4344
|
+
const signature = part.signature === undefined ? undefined : checkedSignature(part.signature, budget.maxArgumentBytes);
|
|
4345
|
+
if (part.textAbsent !== undefined && (part.textAbsent !== true || length !== 0 || signature === undefined))
|
|
4346
|
+
fail("unsupported_reasoning", "Invalid empty signed part");
|
|
4347
|
+
return { length, hash, ...signature === undefined ? {} : { signature }, ...part.textAbsent ? { textAbsent: true } : {} };
|
|
4348
|
+
});
|
|
4349
|
+
if (!parts.some((p) => p.signature !== undefined))
|
|
4350
|
+
fail("unsupported_reasoning", "Signature carrier has no signature");
|
|
4351
|
+
return { id, thought: item.thought, parts };
|
|
4352
|
+
});
|
|
4353
|
+
if (!result.length || result.length > budget.maxItems)
|
|
4354
|
+
fail("unsupported_reasoning", "Invalid signature item count");
|
|
4355
|
+
return result;
|
|
4356
|
+
}
|
|
4357
|
+
function restoreGeminiHistory(input, budget) {
|
|
4358
|
+
const original = typeof input === "string" ? [] : list(input, "input").map((raw) => record(raw, "input item"));
|
|
4359
|
+
const carriers = new Set, parts = new Map, ids = new Map;
|
|
4360
|
+
original.forEach((item, i) => {
|
|
4361
|
+
if (typeof item.id === "string") {
|
|
4362
|
+
if (ids.has(item.id))
|
|
4363
|
+
fail("invalid_tool_history", "Duplicate history item id", "input.id");
|
|
4364
|
+
ids.set(item.id, i);
|
|
4365
|
+
}
|
|
4366
|
+
});
|
|
4367
|
+
original.forEach((carrier, index) => {
|
|
4368
|
+
if (carrier.encrypted_content == null)
|
|
4369
|
+
return;
|
|
4370
|
+
const signed = readGeminiSignatures(carrier, budget);
|
|
4371
|
+
carriers.add(carrier);
|
|
4372
|
+
let previous = -1;
|
|
4373
|
+
for (const item of signed) {
|
|
4374
|
+
const at = ids.get(item.id);
|
|
4375
|
+
if (at === undefined || at >= index || at <= previous || parts.has(item.id))
|
|
4376
|
+
fail("unsupported_reasoning", "Signed history reference is missing or ambiguous");
|
|
4377
|
+
previous = at;
|
|
4378
|
+
const source = original[at];
|
|
4379
|
+
if (item.thought ? source.type !== "reasoning" || source.encrypted_content != null : source.role !== "assistant" || source.type !== undefined && source.type !== "message")
|
|
4380
|
+
fail("unsupported_reasoning", "Signed history item kind changed");
|
|
4381
|
+
const content = item.thought ? list(source.summary, "summary") : typeof source.content === "string" ? [{ type: "output_text", text: source.content }] : list(source.content, "content");
|
|
4382
|
+
const text = content.map((raw) => {
|
|
4383
|
+
const p = record(raw, "signed text");
|
|
4384
|
+
if (p.type !== (item.thought ? "summary_text" : "output_text") && !(p.type === "input_text" && !item.thought))
|
|
4385
|
+
fail("unsupported_reasoning", "Signed history content kind changed");
|
|
4386
|
+
return string(p.text, "signed text");
|
|
4387
|
+
}).join("");
|
|
4388
|
+
let offset = 0;
|
|
4389
|
+
const restored = item.parts.map((part) => {
|
|
4390
|
+
const value = text.slice(offset, offset + part.length);
|
|
4391
|
+
offset += part.length;
|
|
4392
|
+
if (value.length !== part.length || geminiTextHash(value) !== part.hash)
|
|
4393
|
+
fail("unsupported_reasoning", "Signed history text changed");
|
|
4394
|
+
return { ...part.textAbsent ? {} : { text: value }, ...item.thought ? { thought: true } : {}, ...part.signature === undefined ? {} : { thoughtSignature: part.signature } };
|
|
4395
|
+
});
|
|
4396
|
+
if (offset !== text.length)
|
|
4397
|
+
fail("unsupported_reasoning", "Signed history text was not fully consumed");
|
|
4398
|
+
parts.set(item.id, restored);
|
|
4399
|
+
}
|
|
4400
|
+
});
|
|
4401
|
+
return {
|
|
4402
|
+
input: typeof input === "string" ? input : original.filter((item) => !carriers.has(item)),
|
|
4403
|
+
parts,
|
|
4404
|
+
canonicalHistory(decoded) {
|
|
4405
|
+
if (!carriers.size)
|
|
4406
|
+
return decoded;
|
|
4407
|
+
let next = 0;
|
|
4408
|
+
return original.flatMap((item) => carriers.has(item) ? [item] : item.type === "additional_tools" ? [] : [decoded[next++]]);
|
|
4409
|
+
}
|
|
4410
|
+
};
|
|
4411
|
+
}
|
|
4412
|
+
function encodeGeminiCallId(id, signature, maxBytes) {
|
|
4413
|
+
if (id.includes(signatureSeparator))
|
|
4414
|
+
fail("invalid_tool_arguments", "Gemini call id contains the signature separator", "functionCall.id");
|
|
4415
|
+
return signature === undefined ? id : `${id}${signatureSeparator}${checkedSignature(signature, maxBytes)}`;
|
|
4416
|
+
}
|
|
4417
|
+
function decodeGeminiCallId(value, maxBytes) {
|
|
4418
|
+
const separator = value.indexOf(signatureSeparator);
|
|
4419
|
+
if (separator < 0)
|
|
4420
|
+
return { id: value };
|
|
4421
|
+
const id = string(value.slice(0, separator), "functionCall.id", true);
|
|
4422
|
+
return { id, thoughtSignature: checkedSignature(value.slice(separator + signatureSeparator.length), maxBytes) };
|
|
4423
|
+
}
|
|
4424
|
+
|
|
4277
4425
|
// packages/llms/src/protocol-session/schema.ts
|
|
4278
4426
|
function geminiSchemaToJson(raw, path, code = "unsupported_request", depth = 0) {
|
|
4279
4427
|
if (depth > 64)
|
|
@@ -4707,6 +4855,9 @@ function convertProtocolRequest(raw, context) {
|
|
|
4707
4855
|
b.stream = context.streaming;
|
|
4708
4856
|
}
|
|
4709
4857
|
validateCanonical(b, context);
|
|
4858
|
+
const geminiHistory = context.sourceProtocol === "responses" && context.targetProtocol === "gemini_generate_content" ? restoreGeminiHistory(b.input, limits(context.capabilities?.limits)) : undefined;
|
|
4859
|
+
if (geminiHistory)
|
|
4860
|
+
b.input = geminiHistory.input;
|
|
4710
4861
|
const cap = { ...context.capabilities, agentMessageDelivery: context.agentMessageDelivery ?? context.capabilities?.agentMessageDelivery, omitOptionalWebSearch: true, preserveToolIdentityDescription: true, preserveRefusalContent: true }, policy = context.reasoningPolicy;
|
|
4711
4862
|
const reasoning = b.reasoning === undefined ? undefined : record(b.reasoning, "reasoning");
|
|
4712
4863
|
const sourceThinking = b.sourceThinking;
|
|
@@ -4732,10 +4883,10 @@ function convertProtocolRequest(raw, context) {
|
|
|
4732
4883
|
if (sourceThinking !== undefined && reasoning?.effort === undefined && policy?.targetEffort !== undefined)
|
|
4733
4884
|
mappedEffort = string(policy.targetEffort, "reasoningPolicy.targetEffort", true);
|
|
4734
4885
|
const target = context.targetProtocol;
|
|
4735
|
-
if (target === "gemini_generate_content" && reasoning?.effort !== undefined && policy?.geminiThinkingBudget === undefined && policy?.geminiThinkingLevel === undefined)
|
|
4886
|
+
if (target === "gemini_generate_content" && reasoning?.effort !== undefined && mappedEffort === undefined && policy?.geminiThinkingBudget === undefined && policy?.geminiThinkingLevel === undefined)
|
|
4736
4887
|
fail("unsupported_reasoning", "Gemini requires an explicit thinking budget or level", "reasoning.effort");
|
|
4737
4888
|
if (sourceThinking !== undefined) {
|
|
4738
|
-
const represented = target === "responses" || target === "chat_completions" ? mappedEffort !== undefined : target === "anthropic_messages" ? mappedEffort !== undefined || policy?.anthropicThinkingMode !== undefined || policy?.anthropicThinkingBudget !== undefined : policy?.geminiThinkingBudget !== undefined || policy?.geminiThinkingLevel !== undefined;
|
|
4889
|
+
const represented = target === "responses" || target === "chat_completions" ? mappedEffort !== undefined : target === "anthropic_messages" ? mappedEffort !== undefined || policy?.anthropicThinkingMode !== undefined || policy?.anthropicThinkingBudget !== undefined : mappedEffort !== undefined || policy?.geminiThinkingBudget !== undefined || policy?.geminiThinkingLevel !== undefined;
|
|
4739
4890
|
if (!represented)
|
|
4740
4891
|
fail("unsupported_reasoning", "Source thinking mode needs an explicit target wire policy", "thinking");
|
|
4741
4892
|
}
|
|
@@ -4794,9 +4945,13 @@ function convertProtocolRequest(raw, context) {
|
|
|
4794
4945
|
const decodingTarget = target === "gemini_generate_content" ? "chat_completions" : target;
|
|
4795
4946
|
if (target === "gemini_generate_content" && reasoning)
|
|
4796
4947
|
b.reasoning = { ...reasoning, effort: undefined };
|
|
4797
|
-
const decoded = decodeResponsesRequest(b, decodingTarget, { ...cap, reasoningHistory: target !== "anthropic_messages" && cap.reasoningHistory === true, reasoningEffort: target === "chat_completions" && cap.reasoningEffort === true, anthropicThinkingBudget: undefined });
|
|
4948
|
+
const decoded = decodeResponsesRequest(b, decodingTarget, { ...cap, reasoningHistory: target !== "anthropic_messages" && cap.reasoningHistory === true, reasoningEffort: target === "chat_completions" && cap.reasoningEffort === true, anthropicThinkingBudget: undefined }, { preserveContentOrder: target === "gemini_generate_content" });
|
|
4798
4949
|
const diagnostics = decoded.diagnostics;
|
|
4799
|
-
|
|
4950
|
+
if (target === "gemini_generate_content" && decoded.body.parallel_tool_calls === true) {
|
|
4951
|
+
delete decoded.body.parallel_tool_calls;
|
|
4952
|
+
diagnostics.push({ param: "parallel_tool_calls", action: "omitted", reason: "gemini_parallel_tool_calls_allowed" });
|
|
4953
|
+
}
|
|
4954
|
+
const body = target === "gemini_generate_content" ? renderGemini(decoded.body, context, geminiHistory?.parts, diagnostics) : decoded.body;
|
|
4800
4955
|
if (stop !== undefined)
|
|
4801
4956
|
body[target === "chat_completions" ? "stop" : target === "anthropic_messages" ? "stop_sequences" : "generationConfig"] = target === "gemini_generate_content" ? { ...record(body.generationConfig ?? {}, "generationConfig"), stopSequences: typeof stop === "string" ? [stop] : stop } : typeof stop === "string" ? [stop] : stop;
|
|
4802
4957
|
if (target === "anthropic_messages") {
|
|
@@ -4818,18 +4973,24 @@ function convertProtocolRequest(raw, context) {
|
|
|
4818
4973
|
body.thinking = { type: "enabled", budget_tokens: budget };
|
|
4819
4974
|
}
|
|
4820
4975
|
}
|
|
4821
|
-
if (target === "gemini_generate_content" && (policy?.geminiThinkingBudget !== undefined || policy?.geminiThinkingLevel !== undefined)) {
|
|
4822
|
-
|
|
4976
|
+
if (target === "gemini_generate_content" && (mappedEffort !== undefined || policy?.geminiThinkingBudget !== undefined || policy?.geminiThinkingLevel !== undefined)) {
|
|
4977
|
+
const level = policy?.geminiThinkingLevel ?? mappedEffort;
|
|
4978
|
+
if (policy?.geminiThinkingBudget !== undefined && level !== undefined)
|
|
4823
4979
|
fail("unsupported_reasoning", "Choose one Gemini thinking policy", "reasoningPolicy");
|
|
4824
|
-
|
|
4980
|
+
if (level !== undefined && !["minimal", "low", "medium", "high"].includes(level))
|
|
4981
|
+
fail("unsupported_reasoning", "Unknown Gemini thinking level", "reasoning.effort");
|
|
4982
|
+
if (mappedEffort !== undefined && policy?.geminiThinkingLevel !== undefined && mappedEffort !== policy.geminiThinkingLevel)
|
|
4983
|
+
fail("unsupported_reasoning", "Conflicting Gemini thinking levels", "reasoning.effort");
|
|
4984
|
+
const thinkingConfig = policy?.geminiThinkingBudget !== undefined ? { thinkingBudget: integer(policy.geminiThinkingBudget, "reasoningPolicy.geminiThinkingBudget", -1) } : { thinkingLevel: string(level, "reasoningPolicy.geminiThinkingLevel", true) };
|
|
4825
4985
|
body.generationConfig = { ...record(body.generationConfig ?? {}, "generationConfig"), thinkingConfig };
|
|
4826
4986
|
}
|
|
4827
4987
|
if (mappedEffort !== undefined || sourceThinking !== undefined || policy?.anthropicThinkingBudget !== undefined)
|
|
4828
4988
|
diagnostics.push({ param: "reasoning", action: "mapped", reason: "explicit_verified_wire_policy" });
|
|
4829
|
-
return { body, canonicalHistory: decoded.canonicalInput, diagnostics, toolNames: decoded.toolNames, streaming: b.stream === true };
|
|
4989
|
+
return { body, canonicalHistory: geminiHistory?.canonicalHistory(decoded.canonicalInput) ?? decoded.canonicalInput, diagnostics, toolNames: decoded.toolNames, streaming: b.stream === true };
|
|
4830
4990
|
}
|
|
4831
|
-
function renderGemini(chat,
|
|
4991
|
+
function renderGemini(chat, context, signedParts, diagnostics) {
|
|
4832
4992
|
const result = { contents: [] }, contents = result.contents, system = [], calls = new Map;
|
|
4993
|
+
const nativeIds = new Set;
|
|
4833
4994
|
const append = (role, parts) => {
|
|
4834
4995
|
const prev = contents.at(-1);
|
|
4835
4996
|
if (prev?.role === role)
|
|
@@ -4838,14 +4999,22 @@ function renderGemini(chat, jsonSchema) {
|
|
|
4838
4999
|
contents.push({ role, parts });
|
|
4839
5000
|
};
|
|
4840
5001
|
for (const m of chat.messages) {
|
|
5002
|
+
const signed = signedParts?.get(m.id);
|
|
5003
|
+
if (signed) {
|
|
5004
|
+
append("model", signed);
|
|
5005
|
+
continue;
|
|
5006
|
+
}
|
|
4841
5007
|
const parts = m.content == null ? [] : typeof m.content === "string" ? [{ text: m.content }] : m.content.map((p) => {
|
|
4842
5008
|
if (p.type !== "text")
|
|
4843
5009
|
fail("unsupported_content", "This content cannot cross to Gemini", "input");
|
|
4844
5010
|
return { text: p.text };
|
|
4845
5011
|
});
|
|
4846
5012
|
if (m.role === "system" || m.role === "developer") {
|
|
4847
|
-
if (contents.length)
|
|
4848
|
-
|
|
5013
|
+
if (contents.length) {
|
|
5014
|
+
if (context.sourceProtocol !== "responses")
|
|
5015
|
+
fail("unsupported_content", "Mid-conversation instructions cannot be relocated", "input");
|
|
5016
|
+
diagnostics.push({ param: "input", action: "mapped", reason: "gemini_mid_conversation_instructions_consolidated" });
|
|
5017
|
+
}
|
|
4849
5018
|
system.push(...parts);
|
|
4850
5019
|
continue;
|
|
4851
5020
|
}
|
|
@@ -4855,7 +5024,8 @@ function renderGemini(chat, jsonSchema) {
|
|
|
4855
5024
|
fail("invalid_tool_history", "Unknown tool result", "input");
|
|
4856
5025
|
if (m.is_error === true)
|
|
4857
5026
|
fail("unsupported_content", "Tool error authority cannot be represented by Gemini", "input");
|
|
4858
|
-
|
|
5027
|
+
const { id } = context.sourceProtocol === "responses" ? decodeGeminiCallId(m.tool_call_id, limits(context.capabilities?.limits).maxArgumentBytes) : { id: m.tool_call_id };
|
|
5028
|
+
append("user", [{ functionResponse: { id, name, response: { output: m.content } } }]);
|
|
4859
5029
|
continue;
|
|
4860
5030
|
}
|
|
4861
5031
|
if (m.reasoning_content !== undefined)
|
|
@@ -4863,10 +5033,20 @@ function renderGemini(chat, jsonSchema) {
|
|
|
4863
5033
|
for (const c of m.tool_calls ?? []) {
|
|
4864
5034
|
const fn = record(c.function, "function");
|
|
4865
5035
|
calls.set(c.id, fn.name);
|
|
4866
|
-
|
|
5036
|
+
const { id, thoughtSignature } = context.sourceProtocol === "responses" ? decodeGeminiCallId(c.id, limits(context.capabilities?.limits).maxArgumentBytes) : { id: c.id, thoughtSignature: undefined };
|
|
5037
|
+
if (nativeIds.has(id))
|
|
5038
|
+
fail("invalid_tool_history", "Duplicate decoded Gemini call id", "call_id");
|
|
5039
|
+
nativeIds.add(id);
|
|
5040
|
+
parts.push({ functionCall: { id, name: fn.name, args: argumentObject(fn.arguments) }, ...thoughtSignature === undefined ? {} : { thoughtSignature } });
|
|
4867
5041
|
}
|
|
4868
5042
|
append(m.role === "assistant" ? "model" : "user", parts);
|
|
4869
5043
|
}
|
|
5044
|
+
if (chat.parallel_tool_calls !== undefined) {
|
|
5045
|
+
if (context.sourceProtocol !== "responses" || chat.parallel_tool_calls !== false)
|
|
5046
|
+
fail("unsupported_request", "Gemini cannot enforce parallel tool preference", "parallel_tool_calls");
|
|
5047
|
+
system.push({ text: "Call at most one tool per response." });
|
|
5048
|
+
diagnostics.push({ param: "parallel_tool_calls", action: "mapped", reason: "gemini_serial_tool_calls_prompt_only" });
|
|
5049
|
+
}
|
|
4870
5050
|
if (system.length)
|
|
4871
5051
|
result.systemInstruction = { parts: system };
|
|
4872
5052
|
const generation = {};
|
|
@@ -4875,12 +5055,10 @@ function renderGemini(chat, jsonSchema) {
|
|
|
4875
5055
|
generation[to] = chat[from];
|
|
4876
5056
|
if (chat.metadata !== undefined)
|
|
4877
5057
|
fail("unsupported_request", "Gemini has no compatible request metadata", "metadata");
|
|
4878
|
-
if (chat.parallel_tool_calls !== undefined)
|
|
4879
|
-
fail("unsupported_request", "Gemini cannot enforce parallel tool preference", "parallel_tool_calls");
|
|
4880
5058
|
if (chat.response_format !== undefined) {
|
|
4881
5059
|
const f = record(chat.response_format, "format");
|
|
4882
5060
|
if (f.type === "json_schema") {
|
|
4883
|
-
if (!
|
|
5061
|
+
if (!context.capabilities?.geminiJsonSchema)
|
|
4884
5062
|
fail("unsupported_request", "Target JSON schema capability is required", "text.format");
|
|
4885
5063
|
const s = record(f.json_schema, "schema");
|
|
4886
5064
|
if (s.strict === false)
|
|
@@ -5025,7 +5203,11 @@ function validateCanonicalResponse(raw, context, itemOnly = false) {
|
|
|
5025
5203
|
fail("unsupported_content", "Output annotations cannot cross protocols", path);
|
|
5026
5204
|
}
|
|
5027
5205
|
} else if (t.type === "reasoning") {
|
|
5028
|
-
if (t.encrypted_content != null
|
|
5206
|
+
if (t.encrypted_content != null && context.sourceProtocol === "responses" && context.targetProtocol === "gemini_generate_content")
|
|
5207
|
+
readGeminiSignatures(t, limits(context.capabilities?.limits));
|
|
5208
|
+
else if (t.encrypted_content != null)
|
|
5209
|
+
fail("unsupported_reasoning", "Opaque reasoning cannot cross protocols", path);
|
|
5210
|
+
if (t.content != null)
|
|
5029
5211
|
fail("unsupported_reasoning", "Opaque or raw reasoning output cannot cross protocols", path);
|
|
5030
5212
|
for (const rawPart of list(t.summary, "summary")) {
|
|
5031
5213
|
const p = record(rawPart, "summary");
|
|
@@ -5148,20 +5330,28 @@ function responseFromCanonical(raw, protocol, context) {
|
|
|
5148
5330
|
|
|
5149
5331
|
class GeminiCanonicalDecoder {
|
|
5150
5332
|
context;
|
|
5333
|
+
streaming;
|
|
5151
5334
|
encoder;
|
|
5152
5335
|
serial = 0;
|
|
5153
5336
|
ended = false;
|
|
5154
5337
|
tools = false;
|
|
5155
5338
|
ids = new Set;
|
|
5156
|
-
|
|
5339
|
+
sequence = 0;
|
|
5340
|
+
contentId;
|
|
5341
|
+
partCount = 0;
|
|
5342
|
+
replayBytes = Buffer.byteLength(JSON.stringify({ version: 1, items: [] }));
|
|
5343
|
+
signedItems = 0;
|
|
5344
|
+
signed = new Map;
|
|
5345
|
+
constructor(context, names, streaming = true) {
|
|
5157
5346
|
this.context = context;
|
|
5158
|
-
this.
|
|
5347
|
+
this.streaming = streaming;
|
|
5348
|
+
this.encoder = new ResponsesEventEncoder("chat_completions", context.responseModel ?? context.model, names, context.capabilities?.limits, { preserveContentOrder: true, agentMessageDelivery: context.capabilities?.agentMessageDelivery });
|
|
5159
5349
|
}
|
|
5160
5350
|
push(raw) {
|
|
5161
5351
|
const b = record(raw, "Gemini response");
|
|
5162
5352
|
fields2(b, ["candidates", "usageMetadata", "modelVersion", "responseId", "promptFeedback", "error"], "", "unsupported_response");
|
|
5163
5353
|
if (b.error !== undefined)
|
|
5164
|
-
return this.encoder.push({ error: safeProtocolError() });
|
|
5354
|
+
return this.decorate(this.encoder.push({ error: safeProtocolError() }));
|
|
5165
5355
|
const events = [];
|
|
5166
5356
|
if (b.promptFeedback !== undefined) {
|
|
5167
5357
|
const p = record(b.promptFeedback, "promptFeedback");
|
|
@@ -5179,34 +5369,69 @@ class GeminiCanonicalDecoder {
|
|
|
5179
5369
|
fields2(c, ["index", "content", "finishReason", "safetyRatings", "finishMessage"], "candidates", "unsupported_response");
|
|
5180
5370
|
if (c.index !== undefined && c.index !== 0)
|
|
5181
5371
|
fail("unsupported_response", "Only candidate index zero is supported", "candidates.index");
|
|
5182
|
-
if (c.content !== undefined) {
|
|
5372
|
+
if (c.content !== undefined && c.content !== null) {
|
|
5183
5373
|
const content = record(c.content, "content");
|
|
5184
5374
|
fields2(content, ["role", "parts"], "candidates.content", "unsupported_content");
|
|
5185
5375
|
if (content.role !== undefined && content.role !== "model")
|
|
5186
5376
|
fail("unsupported_response", "Response role must be model", "candidates.content.role");
|
|
5187
|
-
const parts = list(content.parts, "parts");
|
|
5377
|
+
const parts = list(content.parts ?? [], "parts");
|
|
5188
5378
|
if (this.ended && parts.length)
|
|
5189
5379
|
fail("invalid_stream", "Content arrived after Gemini terminal");
|
|
5190
5380
|
for (const [i, rawPart] of parts.entries()) {
|
|
5191
5381
|
const p = record(rawPart, "part");
|
|
5192
5382
|
fields2(p, ["text", "thought", "functionCall", "thoughtSignature"], "candidates.content.parts", "unsupported_content");
|
|
5193
|
-
if (p.thoughtSignature !== undefined)
|
|
5383
|
+
if (p.thoughtSignature !== undefined && this.context.sourceProtocol !== "responses")
|
|
5194
5384
|
fail("unsupported_reasoning", "Thought signatures cannot cross protocols", "candidates.content.parts.thoughtSignature");
|
|
5195
5385
|
if (p.functionCall !== undefined) {
|
|
5196
5386
|
if (p.text !== undefined || p.thought !== undefined)
|
|
5197
5387
|
fail("unsupported_content", "Mixed Gemini part kinds", "candidates.content.parts");
|
|
5198
5388
|
const f = record(p.functionCall, "functionCall");
|
|
5199
5389
|
fields2(f, ["id", "name", "args"], "functionCall", "unsupported_tool");
|
|
5200
|
-
const index = this.serial++,
|
|
5201
|
-
if (this.ids.has(
|
|
5390
|
+
const index = this.serial++, originalId = f.id === undefined ? `call_gemini_${crypto.randomUUID().replaceAll("-", "")}` : string(f.id, "functionCall.id", true);
|
|
5391
|
+
if (this.ids.has(originalId))
|
|
5202
5392
|
fail("invalid_tool_arguments", "Duplicate Gemini call id", "functionCall.id");
|
|
5203
|
-
this.ids.add(
|
|
5393
|
+
this.ids.add(originalId);
|
|
5394
|
+
const id = this.context.sourceProtocol === "responses" ? encodeGeminiCallId(originalId, p.thoughtSignature, limits(this.context.capabilities?.limits).maxArgumentBytes) : originalId;
|
|
5204
5395
|
this.tools = true;
|
|
5205
5396
|
events.push(...this.encoder.push({ choices: [{ delta: { tool_calls: [{ index, id, type: "function", function: { name: string(f.name, "functionCall.name", true), arguments: JSON.stringify(record(f.args ?? {}, "functionCall.args")) } }] } }] }));
|
|
5206
5397
|
} else {
|
|
5207
5398
|
if (p.thought !== undefined && typeof p.thought !== "boolean")
|
|
5208
5399
|
fail("invalid_payload", "Thought flag must be boolean", "thought");
|
|
5209
|
-
|
|
5400
|
+
const text = string(p.text ?? (p.thoughtSignature === undefined ? undefined : ""), `parts[${i}].text`);
|
|
5401
|
+
const output = this.encoder.push({ choices: [{ delta: { [p.thought === true ? "reasoning_content" : "content"]: text } }] });
|
|
5402
|
+
const added = output.find((e) => e.type === "response.output_item.added");
|
|
5403
|
+
if (added)
|
|
5404
|
+
this.contentId = record(added.item, "item").id;
|
|
5405
|
+
const id = this.contentId;
|
|
5406
|
+
let item = this.signed.get(id);
|
|
5407
|
+
if (!item) {
|
|
5408
|
+
item = { id, thought: p.thought === true, parts: [], hasSignature: false, metadataBytes: Buffer.byteLength(JSON.stringify({ id, thought: p.thought === true, parts: [] })) };
|
|
5409
|
+
this.signed.set(id, item);
|
|
5410
|
+
}
|
|
5411
|
+
const signature = p.thoughtSignature === undefined ? undefined : checkedSignature(p.thoughtSignature, limits(this.context.capabilities?.limits).maxArgumentBytes);
|
|
5412
|
+
const previous = item.parts.at(-1);
|
|
5413
|
+
const merge = this.streaming && signature === undefined && previous && previous.signature === undefined && !previous.textAbsent;
|
|
5414
|
+
const partBytes = Buffer.byteLength(JSON.stringify({ length: text.length + (merge ? previous.text.length : 0), hash: "x".repeat(43), ...signature === undefined ? {} : { signature }, ...p.text === undefined ? { textAbsent: true } : {} }));
|
|
5415
|
+
const metadataBytes = item.metadataBytes + partBytes - (merge ? previous.metadataBytes : 0) + (!merge && item.parts.length ? 1 : 0);
|
|
5416
|
+
const hasSignature = item.hasSignature || signature !== undefined;
|
|
5417
|
+
const replayBytes = this.replayBytes + (item.hasSignature ? metadataBytes - item.metadataBytes : hasSignature ? metadataBytes + (this.signedItems ? 1 : 0) : 0);
|
|
5418
|
+
const budget = limits(this.context.capabilities?.limits);
|
|
5419
|
+
if (hasSignature && geminiEnvelopeBytes(replayBytes) > Math.min(budget.maxArgumentBytes, budget.maxOutputBytes))
|
|
5420
|
+
fail("resource_limit", "Accumulated Gemini signatures exceed replay budget");
|
|
5421
|
+
if (hasSignature && !item.hasSignature)
|
|
5422
|
+
this.signedItems++;
|
|
5423
|
+
this.replayBytes = replayBytes;
|
|
5424
|
+
item.metadataBytes = metadataBytes;
|
|
5425
|
+
item.hasSignature = hasSignature;
|
|
5426
|
+
if (merge) {
|
|
5427
|
+
previous.text += text;
|
|
5428
|
+
previous.metadataBytes = partBytes;
|
|
5429
|
+
} else {
|
|
5430
|
+
if (++this.partCount > limits(this.context.capabilities?.limits).maxItems)
|
|
5431
|
+
fail("resource_limit", "Too many Gemini parts");
|
|
5432
|
+
item.parts.push({ text, metadataBytes: partBytes, ...signature === undefined ? {} : { signature }, ...p.text === undefined ? { textAbsent: true } : {} });
|
|
5433
|
+
}
|
|
5434
|
+
events.push(...output);
|
|
5210
5435
|
}
|
|
5211
5436
|
}
|
|
5212
5437
|
}
|
|
@@ -5223,25 +5448,47 @@ class GeminiCanonicalDecoder {
|
|
|
5223
5448
|
}
|
|
5224
5449
|
if (b.usageMetadata !== undefined) {
|
|
5225
5450
|
const u = record(b.usageMetadata, "usageMetadata");
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
const input = u.promptTokenCount ?? 0, thoughts = u.thoughtsTokenCount ?? 0, output = (u.candidatesTokenCount ?? 0) + thoughts;
|
|
5451
|
+
for (const k of ["promptTokenCount", "candidatesTokenCount", "totalTokenCount", "cachedContentTokenCount", "thoughtsTokenCount", "toolUsePromptTokenCount"])
|
|
5452
|
+
if (u[k] !== undefined && u[k] !== null)
|
|
5453
|
+
integer(u[k], `usageMetadata.${k}`);
|
|
5454
|
+
const input = (u.promptTokenCount ?? 0) + (u.toolUsePromptTokenCount ?? 0), thoughts = u.thoughtsTokenCount ?? 0, output = (u.candidatesTokenCount ?? 0) + thoughts;
|
|
5230
5455
|
if (u.totalTokenCount !== undefined && u.totalTokenCount !== input + output)
|
|
5231
5456
|
fail("invalid_usage", "Gemini total does not match reported components", "usageMetadata.totalTokenCount");
|
|
5232
5457
|
events.push(...this.encoder.push({ choices: [], usage: { prompt_tokens: input, completion_tokens: output, prompt_tokens_details: { cached_tokens: u.cachedContentTokenCount ?? 0 }, completion_tokens_details: { reasoning_tokens: thoughts } } }));
|
|
5233
5458
|
}
|
|
5234
|
-
return events;
|
|
5459
|
+
return this.decorate(events);
|
|
5460
|
+
}
|
|
5461
|
+
decorate(events) {
|
|
5462
|
+
const output = [];
|
|
5463
|
+
for (const event of events) {
|
|
5464
|
+
if (["response.completed", "response.incomplete", "response.failed"].includes(event.type)) {
|
|
5465
|
+
const signed = [...this.signed.values()].filter((item) => item.parts.some((p) => p.signature !== undefined));
|
|
5466
|
+
if (signed.length) {
|
|
5467
|
+
const budget = limits(this.context.capabilities?.limits), response = record(event.response, "response");
|
|
5468
|
+
const items = list(response.output, "output");
|
|
5469
|
+
if (items.length >= budget.maxItems)
|
|
5470
|
+
fail("resource_limit", "Too many Gemini output items");
|
|
5471
|
+
const item = geminiSignatureItem(signed.map((item) => ({ id: item.id, thought: item.thought, parts: item.parts.map((p) => ({ length: p.text.length, hash: geminiTextHash(p.text), ...p.signature === undefined ? {} : { signature: p.signature }, ...p.textAbsent ? { textAbsent: true } : {} })) })), budget);
|
|
5472
|
+
const body = { ...response, output: [...items, item] };
|
|
5473
|
+
serialized(body, budget.maxOutputBytes, "Gemini response");
|
|
5474
|
+
output.push({ type: "response.output_item.added", response_id: response.id, output_index: items.length, item }, { type: "response.output_item.done", response_id: response.id, output_index: items.length, item });
|
|
5475
|
+
output.push({ ...event, response: body });
|
|
5476
|
+
continue;
|
|
5477
|
+
}
|
|
5478
|
+
}
|
|
5479
|
+
output.push(event);
|
|
5480
|
+
}
|
|
5481
|
+
return output.map((event) => ({ ...event, sequence_number: this.sequence++ }));
|
|
5235
5482
|
}
|
|
5236
5483
|
finish() {
|
|
5237
|
-
return this.encoder.finish();
|
|
5484
|
+
return this.decorate(this.encoder.finish());
|
|
5238
5485
|
}
|
|
5239
5486
|
}
|
|
5240
5487
|
function canonicalResponse(raw, context, names) {
|
|
5241
5488
|
if (context.targetProtocol === "responses")
|
|
5242
5489
|
return validateCanonicalResponse(raw, context);
|
|
5243
5490
|
if (context.targetProtocol === "gemini_generate_content") {
|
|
5244
|
-
const decoder = new GeminiCanonicalDecoder(context, names);
|
|
5491
|
+
const decoder = new GeminiCanonicalDecoder(context, names, false);
|
|
5245
5492
|
const events = [...decoder.push(raw), ...decoder.finish()];
|
|
5246
5493
|
return record(events.at(-1)?.response, "response");
|
|
5247
5494
|
}
|
|
@@ -5623,7 +5870,7 @@ class CanonicalStreamRenderer {
|
|
|
5623
5870
|
var LLM_PROTOCOLS = ["responses", "chat_completions", "anthropic_messages", "gemini_generate_content"];
|
|
5624
5871
|
|
|
5625
5872
|
// packages/llms/src/protocol-session/index.ts
|
|
5626
|
-
var PROTOCOL_CONVERSION_RULES_VERSION = "1.0.
|
|
5873
|
+
var PROTOCOL_CONVERSION_RULES_VERSION = "1.0.4";
|
|
5627
5874
|
function describeProtocolConversion() {
|
|
5628
5875
|
return {
|
|
5629
5876
|
rulesVersion: PROTOCOL_CONVERSION_RULES_VERSION,
|
|
@@ -5631,7 +5878,7 @@ function describeProtocolConversion() {
|
|
|
5631
5878
|
matrix: LLM_PROTOCOLS.flatMap((sourceProtocol) => LLM_PROTOCOLS.map((targetProtocol) => ({
|
|
5632
5879
|
sourceProtocol,
|
|
5633
5880
|
targetProtocol,
|
|
5634
|
-
mode: sourceProtocol === targetProtocol ? "passthrough" : sourceProtocol === "
|
|
5881
|
+
mode: sourceProtocol === targetProtocol ? "passthrough" : sourceProtocol === "gemini_generate_content" && targetProtocol === "responses" ? "unsupported" : "convert"
|
|
5635
5882
|
})))
|
|
5636
5883
|
};
|
|
5637
5884
|
}
|
|
@@ -5649,9 +5896,9 @@ function createProtocolSession(context) {
|
|
|
5649
5896
|
fail("unsupported_protocol", "Unknown protocol");
|
|
5650
5897
|
if (typeof context.model !== "string" || !context.model)
|
|
5651
5898
|
fail("invalid_payload", "Target model is required", "model");
|
|
5652
|
-
const unsupported = context.sourceProtocol === "
|
|
5899
|
+
const unsupported = context.sourceProtocol === "gemini_generate_content" && context.targetProtocol === "responses";
|
|
5653
5900
|
if (unsupported)
|
|
5654
|
-
fail("unsupported_protocol_pair", "
|
|
5901
|
+
fail("unsupported_protocol_pair", "Gemini to Responses conversion is not supported");
|
|
5655
5902
|
const same = context.sourceProtocol === context.targetProtocol;
|
|
5656
5903
|
let disposed = false, poisoned = false, requested = false, mode, finished = false, passTerminal = false, passAnthropicStopped = false;
|
|
5657
5904
|
let names = new Map;
|
|
@@ -5890,7 +6137,7 @@ function protocolRequestModel(protocol, body, url) {
|
|
|
5890
6137
|
return model;
|
|
5891
6138
|
}
|
|
5892
6139
|
// plugins/llm-protocol-adapter/server/relay.ts
|
|
5893
|
-
import { createHash } from "crypto";
|
|
6140
|
+
import { createHash as createHash2 } from "crypto";
|
|
5894
6141
|
|
|
5895
6142
|
// plugins/llm-protocol-adapter/server/relay-response.ts
|
|
5896
6143
|
var RELAY_TOOL = "relay_external_agent_payload";
|
|
@@ -6054,7 +6301,7 @@ async function relayPayload(result, param, signal) {
|
|
|
6054
6301
|
}
|
|
6055
6302
|
|
|
6056
6303
|
// plugins/llm-protocol-adapter/server/relay.ts
|
|
6057
|
-
var hash = (value) =>
|
|
6304
|
+
var hash = (value) => createHash2("sha256").update(JSON.stringify(value)).digest("hex");
|
|
6058
6305
|
function rejection(param, code, status = 502) {
|
|
6059
6306
|
return new DataAdmissionError(status, code, undefined, { param, message: "Agent payload relay is unavailable" });
|
|
6060
6307
|
}
|
|
@@ -6260,9 +6507,10 @@ class AgentRelay {
|
|
|
6260
6507
|
}
|
|
6261
6508
|
|
|
6262
6509
|
// plugins/llm-protocol-adapter/server/service.ts
|
|
6263
|
-
var REASONING_RULES_VERSION = "2026-10-
|
|
6510
|
+
var REASONING_RULES_VERSION = "2026-10-27.1";
|
|
6264
6511
|
var concrete = new Set(["none", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
6265
|
-
var effortProtocols = new Set(["responses", "chat_completions", "anthropic_messages"]);
|
|
6512
|
+
var effortProtocols = new Set(["responses", "chat_completions", "anthropic_messages", "gemini_generate_content"]);
|
|
6513
|
+
var geminiEfforts = new Set(["minimal", "low", "medium", "high"]);
|
|
6266
6514
|
var anthropicEfforts = new Set(["low", "medium", "high", "xhigh", "max"]);
|
|
6267
6515
|
function identityError(code, message) {
|
|
6268
6516
|
throw new ResponsesCodecError(code, message, "modelIdentity");
|
|
@@ -6287,7 +6535,7 @@ function resolveCapabilities(catalog, context) {
|
|
|
6287
6535
|
if (!info)
|
|
6288
6536
|
return null;
|
|
6289
6537
|
const restrictions = context.restrictions, reasoningAllowed = info.reasoning && restrictions?.reasoning !== false;
|
|
6290
|
-
const allowed = context.targetProtocol === "anthropic_messages" ? anthropicEfforts : concrete;
|
|
6538
|
+
const allowed = context.targetProtocol === "anthropic_messages" ? anthropicEfforts : context.targetProtocol === "gemini_generate_content" ? geminiEfforts : concrete;
|
|
6291
6539
|
const candidates = reasoningAllowed && effortProtocols.has(context.targetProtocol) && info.reasoningOptionsStatus === "known" ? info.reasoningOptions?.flatMap((option) => option.type === "effort" ? option.values.filter((value) => typeof value === "string" && allowed.has(value)) : []) ?? [] : [];
|
|
6292
6540
|
const supportedEfforts = [...new Set(candidates)];
|
|
6293
6541
|
const wirePolicy = supportedEfforts.length ? { effortMap: Object.fromEntries(supportedEfforts.map((value) => [value, value])) } : null;
|
|
@@ -6484,4 +6732,4 @@ export {
|
|
|
6484
6732
|
control_default as default
|
|
6485
6733
|
};
|
|
6486
6734
|
|
|
6487
|
-
//# debugId=
|
|
6735
|
+
//# debugId=165F7F1DADB9687864756E2164756E21
|