UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

125 lines (124 loc) • 4.83 kB
import { TOOL_MOUNT_TAGS, pathTargetSlotOnly } from "./tool-face.js"; import { ENGINE_CARDS, TOOL_CATALOG_ENTRIES } from "./tool-catalog-entries.js"; import { seatOf } from "./tool-name-readings.js"; export function describeToolCatalog() { return TOOL_CATALOG_ENTRIES; } export function catalogEntriesNamed(name) { return TOOL_CATALOG_ENTRIES.filter((e) => e.name === name); } export function catalogToolNames() { const out = new Set(); for (const e of TOOL_CATALOG_ENTRIES) { out.add(e.name); for (const a of e.face.aliases ?? []) out.add(a); } return out; } const names = (pred) => { const out = new Set(); for (const e of TOOL_CATALOG_ENTRIES) if (pred(e)) out.add(e.name); return out; }; export function pathConfinableWriteToolNames() { return names((e) => e.face.pathTarget !== undefined && e.face.pathTarget.access !== "read"); } export function pathTargetingToolNames() { return names((e) => e.face.pathTarget !== undefined); } export function readTargetToolNames() { return names((e) => e.face.pathTarget?.access === "read"); } export function compactableToolNames() { return names((e) => e.face.compactable === true); } export function budgetExemptToolNames() { return names((e) => e.face.budgetExempt === true); } export function pathTargetValue(args, pt) { if (args === null || typeof args !== "object") return undefined; const a = args; for (const k of [pt.param, ...(pt.aliases ?? [])]) { const v = a[k]; if (typeof v === "string" && v.length > 0) return v; } return undefined; } export function protectivePathTargetOf(call) { if (call.face?.pathTarget !== undefined) return call.face.pathTarget; const floor = seatOf("floor.protectivePathTarget", { get: pathTargetOf }, call)?.value; return floor === undefined || call.face === undefined ? floor : pathTargetSlotOnly(floor); } export const BARE_REQUEST_CODE = "policy.bare_request"; export function declaredPathTargetOf(call) { if (call.face === undefined) { const e = new Error(`tool call ${JSON.stringify(call.toolName)} carries no face: a containment fence admits a write only by the tool's OWN declared path target, which a prepared leg's roster stamps on every gated request — a policy invoked outside a Runner must stamp \`face\` itself (toolCallFaceOf) rather than expect the catalog's declaration for the name`); e.code = BARE_REQUEST_CODE; throw e; } return call.face.pathTarget; } export function isProtectedWrite(call) { const pt = protectivePathTargetOf(call); return pt !== undefined && pt.access !== "read"; } export function isDeclaredWrite(call) { const pt = declaredPathTargetOf(call); return pt !== undefined && pt.access !== "read"; } export function fileOpAccessOf(name) { for (const e of TOOL_CATALOG_ENTRIES) { if (e.name === name && (e.face.family === "file-read" || e.face.family === "file-write") && e.face.pathTarget !== undefined) return e.face.pathTarget.access; } return undefined; } export function pathTargetOf(name) { for (const e of TOOL_CATALOG_ENTRIES) if (e.name === name && e.face.pathTarget !== undefined) return e.face.pathTarget; return undefined; } export function catalogRuleFaceOf(name) { for (const e of TOOL_CATALOG_ENTRIES) { if (e.name !== name) continue; const pt = e.face.pathTarget; const primary = e.face.ruleFace?.primaryParams ?? (pt !== undefined ? [pt.param, ...(pt.aliases ?? [])] : []); const params = e.face.ruleFace?.params ?? (pt !== undefined ? [pt.param, ...(pt.aliases ?? [])] : undefined); if (params === undefined && primary.length === 0) continue; return { primaryParams: [...primary], ...(params !== undefined ? { params: [...new Set([...params, ...primary])] } : {}) }; } return undefined; } export function handBandEffects() { const out = new Map(); for (const e of TOOL_CATALOG_ENTRIES) { if (!e.mountedBy.includes("hands")) continue; const eff = e.face.effect ?? "write"; const prior = out.get(e.name); if (prior === undefined || prior === "read") out.set(e.name, eff); } return out; } export function engineCardTypes() { const out = new Set(Object.keys(ENGINE_CARDS)); for (const e of TOOL_CATALOG_ENTRIES) for (const card of e.cards) out.add(card); return out; } export function predictMountedToolNames(active) { return names((e) => e.mountedBy.some((t) => active.has(t))); } export const TOOL_MOUNT_TAG_SET = new Set(TOOL_MOUNT_TAGS); export { HANDS_BAND_TAGS, MOUNT_TAG_IN_HANDS_BAND } from "./tool-face.js";