UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

69 lines (68 loc) • 4.86 kB
import { readArtifactHostCapabilities } from "../artifact-host.js"; import { ARTIFACT_TOOL_NAME } from "../tool-catalog-entries.js"; import { deliverEngineNotice } from "../engine-notice.js"; import { RosterBuilder } from "../tool-roster.js"; import { defineTool } from "../tools.js"; import { inlineUntrusted } from "../untrusted-text.js"; import { physicalPathOfExisting } from "../physical-path.js"; import { resolveKey, rootAdmittingArtifactStore, violationDetails, violationText } from "../../tools/fs/safety.js"; import { createArtifactTool } from "../../tools/artifact/artifact-tool.js"; import { thrownText } from "../thrown-value.js"; export function prepareArtifact(input) { const { deps, runId, taskId, sessionId, agentName, onAsk: approver, toolOccurrences, permissionMode, executionEnv, rootCanonical, additionalRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, roster, firstPartyOffload, envHandToolNames, artifactStoreRef } = input; const host = deps.artifactHost; if (host === undefined) return { artifactPlane: undefined }; const refuse = (problem) => { deliverEngineNotice(deps.onNotice, { code: "config.artifact_host_invalid", message: `RunnerDeps.artifactHost is wired but unusable, so no Artifact tool is mounted for this task: ${problem}`, detail: { problem, sessionId, runId }, }); return { artifactPlane: undefined }; }; const verdict = readArtifactHostCapabilities(host); if (!verdict.ok) return refuse(verdict.problem); const storageDir = verdict.capabilities.storageDir; const storePhysical = storageDir !== undefined && rootCanonical !== undefined ? physicalPathOfExisting(storageDir) : undefined; if (artifactStoreRef !== undefined) artifactStoreRef.current = storePhysical; if (storePhysical !== undefined && rootCanonical !== undefined) { const overlapping = rootAdmittingArtifactStore(storePhysical, [rootCanonical, ...additionalRootsCanonical()]); if (overlapping !== undefined) return refuse(`the local artifact store ${storageDir} and a root this run may reach through its file tools (${overlapping}) overlap — the store lies inside a root, or the root inside the store; put the store outside every task root and additional directory`); } try { host.onMount?.(runId); } catch (err) { return refuse(`artifactHost.onMount threw: ${thrownText(err)}`); } const readLocalFile = async (path, maxBytes, signal) => { if (rootCanonical === undefined) return { ok: false, reason: "refused", text: "Error (Artifact): this task has no filesystem root, so a local file cannot be published." }; await additionalRootsCanonical.ready(signal); const rk = await resolveKey(executionEnv, rootCanonical, path, signal, handsCwdRef?.current, additionalRootsCanonical, undefined, readDenyMatcher, resolvedReadFace); if (!rk.ok) return { ok: false, reason: "refused", text: violationText("Artifact", rk.violation), details: violationDetails(rk.violation) }; const meta = await executionEnv.fileInfo(rk.key, signal); if (!meta.ok) return { ok: false, reason: "refused", text: `Error (Artifact): cannot stat ${inlineUntrusted(path, 200)} (${inlineUntrusted(meta.error.code, 40)}).` }; if (meta.value.kind !== "file") return { ok: false, reason: "not_a_file", kind: meta.value.kind }; if (meta.value.size > maxBytes) return { ok: false, reason: "too_large", size: meta.value.size, limit: maxBytes, judgedOn: "metadata" }; const r = await executionEnv.readBinaryFile(rk.key, signal); if (!r.ok) return { ok: false, reason: "refused", text: `Error (Artifact): cannot read ${inlineUntrusted(path, 200)} (${inlineUntrusted(r.error.code, 40)}).` }; if (r.value.byteLength > maxBytes) return { ok: false, reason: "too_large", size: r.value.byteLength, limit: maxBytes, judgedOn: "bytes" }; return { ok: true, key: rk.key, bytes: r.value }; }; const onAsk = typeof approver === "function" ? (req, signal) => toolOccurrences.whileAwaitingUser(req.toolCallId, () => approver(req, signal)) : approver; const artifactSpec = createArtifactTool({ host, capabilities: verdict.capabilities, runId, taskId, sessionId, ...(agentName !== undefined ? { agentName } : {}), readLocalFile, ...(onAsk !== undefined ? { onAsk } : {}), permissionMode: () => permissionMode.current, ...(deps.onNotice !== undefined ? { onNotice: deps.onNotice } : {}) }); roster.mount(firstPartyOffload(defineTool(artifactSpec)), { source: "builtin", mountedBy: "optional" }); envHandToolNames.add(ARTIFACT_TOOL_NAME); return { artifactPlane: verdict.capabilities.plane }; }