@sema-agent/core
Version:
Stateless, task-oriented AI agent core
77 lines (76 loc) • 3.25 kB
JavaScript
import {} from "../../internal/harness.js";
import { readMember } from "../thrown-value.js";
import { MCP_DELIVERY_VERDICTS } from "../mcp-failure.js";
import { TOOL_SEARCH_NAME } from "./tool-disclosure.js";
import { toolOutputFrom } from "./tool-output-projection.js";
import { TASK_CREATE_TOOL_NAME, TASK_UPDATE_TOOL_NAME, TODO_WRITE_TOOL_NAME } from "../tool-catalog-entries.js";
const BATCH_RESPONSE_MAX_CHARS = 500;
export function batchResponseDigest(result) {
const content = result !== null && typeof result === "object" ? result.content : result;
if (content === undefined || content === null)
return undefined;
let text;
if (typeof content === "string") {
text = content;
}
else if (Array.isArray(content)) {
text = content
.map((c) => (c !== null && typeof c === "object" && typeof c.text === "string" ? c.text : ""))
.filter((t) => t.length > 0)
.join("\n");
}
else {
try {
text = JSON.stringify(content) ?? "";
}
catch {
return undefined;
}
}
if (text.length === 0)
return undefined;
return text.length > BATCH_RESPONSE_MAX_CHARS
? `${text.slice(0, BATCH_RESPONSE_MAX_CHARS)}…[+${text.length - BATCH_RESPONSE_MAX_CHARS} chars truncated]`
: text;
}
export function toolEndBodyFrom(result, isError, structured, gate, gatedCallIdOfRun) {
const o = toolOutputFrom(result);
const st = structured(result);
const det = isError ? readMember(result, "details") : undefined;
const codeRaw = readMember(det, "code");
const kindRaw = readMember(det, "errorKind");
const code = typeof codeRaw === "string" ? codeRaw : typeof kindRaw === "string" ? kindRaw : undefined;
const deliveredRaw = readMember(det, "delivered");
const delivered = typeof deliveredRaw === "string" && MCP_DELIVERY_VERDICTS.includes(deliveredRaw) ? deliveredRaw : undefined;
const gatedCallId = code === "gate.parked" ? gatedCallIdOfRun : undefined;
return {
...(o !== undefined ? { output: o.output, ...(o.truncated ? { truncated: true } : {}), ...(o.totalChars !== undefined ? { totalChars: o.totalChars } : {}) } : {}),
...(st !== undefined ? { structured: st } : {}),
...(typeof code === "string" ? { errorCode: code } : {}),
...(delivered !== undefined ? { delivered } : {}),
...(gatedCallId !== undefined ? { gatedCallId } : {}),
...(gate !== undefined ? { gate } : {}),
};
}
export function reconciledToolEndBody(orphan, structured) {
return toolEndBodyFrom({ content: orphan.text, details: { code: orphan.errorKind } }, true, structured);
}
export function writeFamilyOfCanonical(name) {
if (name === TASK_CREATE_TOOL_NAME || name === TASK_UPDATE_TOOL_NAME)
return "task";
if (name === TODO_WRITE_TOOL_NAME)
return "todo";
if (name === TOOL_SEARCH_NAME)
return "tool_search";
return undefined;
}
export function toolResultMsg(toolCallId, toolName, text, isError) {
return {
role: "toolResult",
toolCallId,
toolName,
content: [{ type: "text", text }],
isError,
timestamp: Date.now(),
};
}