UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

77 lines (76 loc) • 3.25 kB
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(), }; }