UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

77 lines (76 loc) • 3.64 kB
import { isToolContentOrigin, TOOL_CONTENT_ORIGINS } from "./memory-engine/content-origin.js"; import { inlineUntrusted } from "./untrusted-text.js"; export const LOCKED_KEY_REGISTRY = { mcp: { specFields: ["mcp"] }, toolPolicy: { specFields: ["toolPolicy", "basePolicyForResumeEdit"] }, compliancePosture: { specFields: [] }, retentionPolicy: { specFields: [] }, }; function codedError(code, message) { const e = new Error(message); e.code = code; return e; } export function resolveLockedKeys(config) { if (config === undefined) return new Set(); const keys = new Set(); for (const key of config.keys) { if (!Object.prototype.hasOwnProperty.call(LOCKED_KEY_REGISTRY, key)) { throw codedError("config.locked_registry", `lockedConfig.keys contains "${String(key)}", which is not a member of the locked-key registry ` + `(${Object.keys(LOCKED_KEY_REGISTRY).join(", ")}). A lock that does not parse must not half-arm — ` + `fix the deployment's lock declaration.`); } keys.add(key); } return keys; } export function snapshotMcpEntries(entries) { return entries.map((entry) => Object.freeze({ ...entry })); } function describeDeclared(value) { try { return JSON.stringify(value) ?? String(value); } catch { try { return String(value); } catch { return `[unrepresentable ${typeof value}]`; } } } function snapshotAndValidateMcpEntries(entries) { const copies = snapshotMcpEntries(entries); for (const copy of copies) { const declared = copy.contentOrigin; if (declared !== undefined && !isToolContentOrigin(declared)) { throw codedError("config.mcp_content_class", `MCP server ${inlineUntrusted(typeof copy.name === "string" ? JSON.stringify(copy.name) : describeDeclared(copy.name), 80)} declares contentOrigin ` + `${inlineUntrusted(describeDeclared(declared), 80)}, which is not one of ` + `${TOOL_CONTENT_ORIGINS.map((v) => `"${v}"`).join(" | ")}. The declaration decides whether this server's tools ` + `mark the session's memory externally exposed — a value this engine cannot read is refused at the door rather ` + `than folded to a class, because folding it would let a deployment believe a declaration is in force while every ` + `call keeps writing a one-way durable mark.`); } } return copies; } export function preflightLockedConfig(spec, deps) { const lockedKeys = resolveLockedKeys(deps.lockedConfig); for (const key of lockedKeys) { for (const field of LOCKED_KEY_REGISTRY[key].specFields) { if (spec[field] !== undefined) { throw codedError("config.locked_key", `TaskSpec.${field} is administratively locked by this deployment (locked key "${key}") — ` + `the task-supplied value is refused wholesale (locks are config-time; there is no request-time ` + `unlock). Remove the field from the task, or change the deployment's lock configuration.`); } } } return { lockedKeys, mcp: lockedKeys.has("mcp") || spec.mcp === undefined ? undefined : snapshotAndValidateMcpEntries(spec.mcp), toolPolicy: lockedKeys.has("toolPolicy") ? deps.toolPolicy : (spec.toolPolicy ?? deps.toolPolicy), basePolicyForResumeEdit: lockedKeys.has("toolPolicy") ? deps.basePolicyForResumeEdit : (spec.basePolicyForResumeEdit ?? deps.basePolicyForResumeEdit), }; }