UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

63 lines (62 loc) • 4.09 kB
export function parentSpecSeatOf(spec, frozenOnQuestion) { return Object.freeze({ ...(spec.principal !== undefined ? { principal: spec.principal } : {}), ...(spec.oneShot === true ? { oneShot: true } : {}), ...(spec.clientContext !== undefined ? { clientContext: spec.clientContext } : {}), ...(frozenOnQuestion !== undefined ? { onQuestion: frozenOnQuestion } : {}), ...(spec.hooks !== undefined ? { hooks: spec.hooks } : {}), ...(spec.additionalDirectories !== undefined ? { additionalDirectories: Object.freeze([...spec.additionalDirectories]) } : {}), ...(spec.additionalReadDirectories !== undefined ? { additionalReadDirectories: Object.freeze([...spec.additionalReadDirectories]) } : {}), ...(spec.envFacts !== undefined ? { envFacts: Object.freeze({ ...spec.envFacts }) } : {}), ...(spec.memoryPersistenceCapable !== undefined ? { memoryPersistenceCapable: spec.memoryPersistenceCapable } : {}), ...(spec.compaction !== undefined ? { compaction: Object.freeze({ ...spec.compaction }) } : {}), ...(spec.skillListingBudgetFraction !== undefined ? { skillListingBudgetFraction: spec.skillListingBudgetFraction } : {}), ...(spec.skillListingMaxDescChars !== undefined ? { skillListingMaxDescChars: spec.skillListingMaxDescChars } : {}), ...(spec.fileHistory !== undefined ? { fileHistory: spec.fileHistory } : {}), ...(spec.memory?.enabled === false ? { memoryOff: true } : {}), }); } export function applyParentSpecSeat(child, seat) { if (seat === undefined) return child; const fill = (key, value) => child[key] === undefined && value !== undefined ? { [key]: value } : {}; return { ...child, ...fill("principal", seat.principal), ...fill("clientContext", seat.clientContext), ...fill("onQuestion", seat.onQuestion), ...fill("hooks", seat.hooks), ...fill("additionalDirectories", (seat.additionalDirectories !== undefined ? [...seat.additionalDirectories] : undefined)), ...fill("additionalReadDirectories", (seat.additionalReadDirectories !== undefined ? [...seat.additionalReadDirectories] : undefined)), ...fill("envFacts", (seat.envFacts !== undefined ? { ...seat.envFacts } : undefined)), ...fill("compaction", (seat.compaction !== undefined ? { ...seat.compaction } : undefined)), ...fill("skillListingBudgetFraction", seat.skillListingBudgetFraction), ...fill("skillListingMaxDescChars", seat.skillListingMaxDescChars), ...fill("fileHistory", seat.fileHistory), ...(seat.oneShot === true ? { oneShot: true } : {}), ...(seat.memoryPersistenceCapable === false ? { memoryPersistenceCapable: false } : fill("memoryPersistenceCapable", seat.memoryPersistenceCapable)), ...(seat.memoryOff === true ? { memory: memoryTurnedOff(child.memory) } : {}), }; } export function memoryTurnedOff(memory) { return { ...(memory ?? {}), enabled: false }; } const SEAT_FACTS_ON_CTX = ["principal", "oneShot", "onQuestion", "memoryPersistenceCapable"]; export function parentSpecSeatOfCtx(ctx) { const seat = ctx.parentSpecSeat; const facts = SEAT_FACTS_ON_CTX.filter((k) => ctx[k] !== undefined); if (seat === undefined) { if (facts.length === 0) return undefined; throw seatRefusal(`the tool context carries ${facts.join(" / ")} but no \`parentSpecSeat\` — a delegating caller hands its children the seat it was minted (a Runner-filled ctx always carries it); spawning without it would silently drop the identity`); } const disagree = facts.filter((k) => (k === "oneShot" ? (ctx.oneShot === true) !== (seat.oneShot === true) : ctx[k] !== seat[k])); if (disagree.length > 0) throw seatRefusal(`the tool context's ${disagree.join(" / ")} disagree with its \`parentSpecSeat\` — one mint, one value`); return seat; } function seatRefusal(message) { const e = new Error(`parentSpecSeat: ${message}`); e.code = "config.parent_spec_seat_missing"; return e; }