UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

211 lines (210 loc) • 8.86 kB
export const KERNEL_CONTRACT_VERSION = 2; export const MOD_TIERS = Object.freeze(["prepend", "user", "append", "builtin", "core"]); export const MOD_SEATS = Object.freeze(["deployment", "task"]); export const MOD_EVENT_SIDES = Object.freeze(["engine", "surface", "both"]); export const MOD_FAILURE_ANSWERS = Object.freeze(["refuse", "skip"]); export const MOD_ABORT_POSTURES = Object.freeze(["immediate", "grace", "caller"]); export const NEXT_TO_TABLE = Object.freeze({ prepend: Object.freeze(["append", "builtin", "core"]), user: Object.freeze([]), append: Object.freeze(["core"]), builtin: Object.freeze([]), core: Object.freeze([]), }); const CONTINUABLE = NEXT_TO_TABLE.prepend; export function nextToRefusal(from, to) { const allowed = NEXT_TO_TABLE[from]; const named = CONTINUABLE.find((t) => t === to); if (named === undefined) return `next.to names ${describe(to)}, which is not a tier a dispatch continues at (${CONTINUABLE.join(", ")})`; if (allowed.length === 0) return `next.to is available to prepend and append handlers only, not to a ${from} handler`; if (!allowed.includes(named)) return `next.to("${named}") skips nothing from ${from}; a ${from} handler may continue at ${allowed.join(", ")}`; return undefined; } export const SEAT_TIER_TABLE = Object.freeze({ deployment: Object.freeze({ declared: "required", tiers: Object.freeze(["prepend", "user", "append"]) }), task: Object.freeze({ declared: "optional", tiers: Object.freeze(["user"]) }), }); const station = (failure, abort, pinned = []) => Object.freeze({ failure, abort, pinned: Object.freeze([...pinned]) }); const method = (pausesCallerBudget) => Object.freeze({ failure: "skip", abort: "caller", pinned: Object.freeze([]), method: Object.freeze({ pausesCallerBudget }) }); const engine = (s) => Object.freeze(s === undefined ? { side: "engine" } : { side: "engine", station: s }); const surface = Object.freeze({ side: "surface" }); export const MOD_EVENT_TABLE = Object.freeze({ "classic.PreToolUse": engine(station("refuse", "immediate", ["tool", "tool_use_id", "agentId", "input"])), "classic.PostToolUse": engine(station("skip", "grace")), "classic.PostToolUseFailure": engine(station("skip", "grace")), "classic.PostToolBatch": engine(station("skip", "grace")), "classic.Notification": engine(), "classic.UserPromptSubmit": engine(station("refuse", "immediate", ["source", "inputId", "actor", "prompt"])), "classic.UserPromptExpansion": engine(), "classic.SessionStart": engine(), "classic.SessionEnd": engine(), "classic.Stop": engine(station("skip", "immediate")), "classic.StopFailure": engine(station("skip", "grace")), "classic.SubagentStart": engine(), "classic.SubagentStop": engine(station("skip", "immediate")), "classic.PreCompact": engine(station("skip", "grace")), "classic.PostCompact": engine(station("skip", "grace")), "classic.PreModelSwitch": engine(), "classic.PostModelSwitch": engine(), "classic.PermissionRequest": engine(), "classic.PermissionDenied": engine(station("skip", "grace")), "classic.Setup": engine(), "classic.TeammateIdle": engine(), "classic.TaskCreated": engine(), "classic.TaskCompleted": engine(), "classic.Elicitation": engine(), "classic.ElicitationResult": engine(), "classic.ConfigChange": engine(), "classic.WorktreeCreate": engine(), "classic.WorktreeRemove": engine(), "classic.InstructionsLoaded": engine(), "classic.CwdChanged": engine(), "classic.FileChanged": engine(), "classic.DirectoryAdded": engine(), "classic.MessageDisplay": engine(), "tool.call": engine(), "tool.check": engine(station("refuse", "immediate", ["tool", "input", "tool_use_id", "agentId", "ceiling"])), "ui.render": surface, "ui.resolve": surface, "ui.press": surface, "ui.input": surface, "ui.select": surface, "ui.message": surface, "ui.fault": surface, "ui.scroll": surface, "ui.focus": surface, "agent.offer": engine(), "agent.spawn": engine(), "prompt.submit": engine(), "prompt.fill": surface, "prompt.suggest": surface, "prompt.edit": surface, "prompt.autocomplete": surface, "prompt.section": engine(station("skip", "grace", ["name", "key", "mountedTools"])), "prompt.context": engine(), "prompt.attachment": engine(), "prompt.mention": surface, "prompt.compose": engine(station("skip", "grace", ["model", "catalog", "selectors"])), "tool.describe": engine(), "command.run": surface, "command.describe": surface, "config.set": surface, "config.describe": surface, "telemetry.log": engine(), "telemetry.mark": engine(), "skill.prompt": engine(), "attribution.text": engine(), "session.start": engine(), "session.receive": engine(), "session.append": engine(), "session.send": engine(), "session.compact": engine(), "session.attach": engine(), "session.detach": engine(), "session.measure": engine(), "session.end": engine(), "plugin.register": Object.freeze({ side: "both", station: station("skip", "immediate", ["name", "seat", "tier", "uses"]) }), "turn.start": engine(), "turn.step": engine(), "turn.complete": engine(), "engine.create": engine(), "model.complete": engine(method(true)), "model.classify": engine(), "model.fork": engine(), "audio.play": surface, "audio.speak": surface, "mcp.call": engine(), "mcp.connect": engine(), "session.cwd": engine(method(true)), "session.root": engine(method(true)), "session.model": engine(method(true)), "session.turns": engine(), "session.id": engine(method(true)), "session.messages": engine(method(true)), "session.repo": engine(), "session.surface": engine(), "session.surfaces": engine(), "session.authorize": engine(), "session.usage": engine(), "session.version": engine(), "turn.abort": engine(), "prompt.read": surface, "flag.value": engine(), "tool.list": engine(method(true)), "tool.register": engine(), "command.list": surface, "command.register": surface, "config.list": surface, "agent.list": engine(method(true)), "agent.register": engine(), "ui.toast": surface, "ui.status": surface, "ui.log": surface, "ui.notice": surface, "ui.invalidate": surface, "ui.open": surface, "ui.close": surface, "ui.panes": surface, "ui.selection": surface, "ui.copy": surface, "ui.notify": surface, "ui.blit": surface, "fs.read": engine(), "fs.write": engine(), "fs.list": engine(), "fs.exists": engine(), "fs.stat": engine(), "fs.ancestors": engine(), "store.get": engine(), "store.set": engine(), "store.delete": engine(), "store.keys": engine(), "state.get": engine(), "state.set": engine(), "clock.now": engine(method(false)), "clock.sleep": engine(method(false)), "clock.after": engine(), "clock.every": engine(), "http.fetch": engine(), "process.run": engine(method(true)), "process.spawn": engine(), "settings.read": engine(), "env.get": engine(), "env.set": engine(), }); const EVENT_NAMES = Object.freeze(Object.keys(MOD_EVENT_TABLE).filter(isModEventName)); export function isModEventName(name) { return typeof name === "string" && Object.prototype.hasOwnProperty.call(MOD_EVENT_TABLE, name); } export function stationOn(name, side) { const row = MOD_EVENT_TABLE[name]; return row.side === side || row.side === "both" ? row.station : undefined; } export function readOnSide(name, side) { const row = MOD_EVENT_TABLE[name]; return row.side === side || row.side === "both"; } export function expandModPattern(pattern) { if (typeof pattern !== "string" || pattern === "") return { refusal: `${describe(pattern)} is not an event name or a "<prefix>.*" pattern` }; if (pattern.endsWith(".*")) { const prefix = pattern.slice(0, -2); if (prefix === "" || prefix.includes("*")) return { refusal: `"${pattern}" is not an event name or a "<prefix>.*" pattern` }; const names = EVENT_NAMES.filter((n) => n.startsWith(`${prefix}.`)); return names.length > 0 ? { names } : { refusal: `"${pattern}" selects no event` }; } return isModEventName(pattern) ? { names: [pattern] } : { refusal: `"${pattern}" is not an event` }; } export function describe(value) { if (typeof value === "string") return `"${value}"`; if (typeof value === "number" || typeof value === "boolean") return String(value); if (value === null) return "null"; return typeof value === "object" ? (Array.isArray(value) ? "an array" : "an object") : typeof value; }