UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

34 lines (33 loc) • 1.93 kB
export const PAUSE_REGISTRY = { human: { pending: "tool_approval", resume: "policy_ask", facet: "A", taskStatus: "suspended", terminal: false }, irreversible_ask: { pending: "tool_approval", resume: "policy_ask", facet: "A", taskStatus: "suspended", terminal: false }, resource_limit: { pending: "resource_limit", resume: "resource_limit", facet: "B", taskStatus: "suspended", terminal: false }, needs_review: { pending: "review", resume: "dry_run_review", facet: "B", taskStatus: "needs_review", terminal: false }, plan_review: { pending: "plan_review", resume: "plan_review", facet: "B", taskStatus: "needs_review", terminal: false }, task_done: { pending: "task_done", resume: "task_done", facet: "-", taskStatus: "suspended", terminal: true }, }; export function isGateKind(v) { return typeof v === "string" && Object.prototype.hasOwnProperty.call(PAUSE_REGISTRY, v); } export function facetOf(gate) { return isQuestionGate(gate) ? "B" : PAUSE_REGISTRY[gate.kind].facet; } export function isQuestionGate(gate) { return PAUSE_REGISTRY[gate.kind].pending === "tool_approval" && gate.approvalCard === "question"; } export function resumeGateMatches(gateKind, outcomeGate) { return outcomeGate === "wake" || PAUSE_REGISTRY[gateKind].resume === outcomeGate; } export function pauseOf(gate, pendingAction) { if (!isGateKind(gate.kind)) throw new Error(`checkpoint gate kind "${String(gate.kind)}" is not a registered pause`); const expected = PAUSE_REGISTRY[gate.kind].pending; if (pendingAction.kind !== expected) { throw new Error(`a "${gate.kind}" checkpoint carries a "${String(pendingAction.kind)}" pending action — the pause registry pairs it with "${expected}"`); } return { gate, pendingAction }; } export function checkpointFrom(fields) { const { gate, pendingAction, ...row } = fields; return { ...row, ...pauseOf(gate, pendingAction) }; }