@sema-agent/core
Version:
Stateless, task-oriented AI agent core
39 lines (38 loc) • 2.39 kB
JavaScript
import { deliverEngineNotice } from "../engine-notice.js";
import { providerToolCallId, toolCallFoldReason } from "../../brain/tool-call-id.js";
function isCall(block) {
return typeof block === "object" && block !== null && block.type === "toolCall" && typeof block.id === "string";
}
const REASON_CLAUSE = {
charset: () => "named a tool call with an id outside the shape the engine keys calls under (a control byte, a space, a non-ASCII character or a `~`)",
length: (wireId) => `named a tool call with an id outside the shape the engine keys calls under (${wireId.length} characters, over 128)`,
duplicate: () => "gave two tool calls in one response the same id, and every provider requires a request's call ids to be unique",
};
export function createToolCallIdFoldSeat(onNotice, ids) {
let announced = false;
return {
observe(message) {
if (announced || !Array.isArray(message.content))
return;
for (const call of message.content.filter(isCall)) {
const reason = toolCallFoldReason(call);
if (reason === undefined)
continue;
announced = true;
const wireId = providerToolCallId(call);
deliverEngineNotice(onNotice, {
code: "route.tool_call_id_folded",
message: `The provider ${REASON_CLAUSE[reason](wireId)}. ` +
(reason === "duplicate"
? `The engine keys the later call as "${call.id}" on every face — frames, cards, transcript, park rows — and hands ` +
`the provider a distinct id for it and its result, so both calls run and both results reach the model. `
: `The engine keys it as "${call.id}" on every face — frames, cards, transcript, park rows — and hands the ` +
`provider its own id back for the call and its result, so the run is unchanged. `) +
`Once per run; later calls with such ids are folded the same way without another notice.`,
detail: { toolCallId: call.id, ...(reason === "duplicate" ? {} : { rawLength: wireId.length }), reason, sessionId: ids.sessionId, runId: ids.runId },
});
return;
}
},
};
}