UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

33 lines (32 loc) • 2.25 kB
/** * The prepare-FAILURE rollback stack — the implementation of {@link RollbackStack} (declared beside the * other prepare contracts in ./contracts.ts, whose JSDoc carries the contract this file keeps). * * Why a stack and not a `finally`: prepare acquires resources in sequence (an execution env, MCP * clients, A2A peers) and every one of them belongs to the RUN once prepare succeeds — the Runner's * finish/teardown releases them. Only a prepare that THROWS must release what it already took, in * reverse acquisition order. Today the orchestrator sees those handles because they are hoisted * `let`s at function scope; a phase module that acquires a handle inside its own body has no such * hoist, so it registers the cleanup HERE, immediately after the acquisition, and the driver unwinds * the whole stack from its one catch. * * Posture (identical to the teardown leg the catch already uses — {@link settleTeardownLeg}): * · reverse order, each cleanup exactly once — the entry is removed before it runs, so a second * `unwindAll` (or a re-entrant one) finds nothing; * · no cleanup can stop another — a throw is routed to `report`, a hang is BOUNDED and reported as a * `TeardownLegTimeoutError` naming the leg; the unwind proceeds either way; * · `unwindAll` NEVER throws — it runs inside the driver's catch, where a throw would replace the * prepare error the caller is owed. * * States: `armed` (accepting pushes) → `committed` (prepare succeeded; the stack is emptied and * ownership has passed to `Prepared`) or → `unwinding`/`unwound` (the failure path ran). A `push` * outside `armed` is a PROGRAMMING error and is refused loudly: a resource acquired after commit * would have no owner on the failure path, and one pushed during an unwind would never run. */ import type { RollbackStack } from "./contracts.js"; /** * Mint one stack per prepare. `report` is the incident channel for a cleanup that throws or times out * (wire it to `deps.onError`); with none, failures of the failure path are dropped — the same * contract `settleTeardownLeg` states for its own `report`. */ export declare function createRollbackStack(report?: (err: Error) => void): RollbackStack;