/** * Execution storage adapter: where runs, attempts, transitions, and receipts * live. The interface is the contract; the memory and SQLite backends are the * shipped implementations. Every state change a dispatcher or state machine * makes is recorded here — nothing is held only in a process. */ import type { AttemptReceipt, AttemptRecord, ClaimResult, ExecutionRunRow, ExecutionRunStatus, FrozenAdmission, RunTransitionRecord, TerminalRunStatus } from "./types.js"; export type { AttemptReceipt, AttemptRecord, ClaimResult, ExecutionRunRow, ExecutionRunStatus, FrozenAdmission, RunTransitionRecord }; export interface CreateAttemptInput { runId: string; attemptNumber: number; } export interface ClaimAttemptInput { runId: string; attemptId: string; workerId: string; /** The generation the claimant believes is current. */ expectedLeaseGeneration: number; } /** Result of persisting an attempt launch intent. */ export type LaunchIntentResult = { ok: true; attempt: AttemptRecord; } | { ok: false; reason: "NO_SUCH_ATTEMPT" | "ATTEMPT_TERMINAL" | "RUN_TERMINAL" | "RUN_CANCELLED"; }; export interface RunExecutionStore { readonly durable: boolean; admit(admission: FrozenAdmission): Promise; getRun(runId: string): Promise; getRunByKey(tenantId: string, idempotencyKey: string): Promise; getRunByDigests(input: { tenantId: string; skillId: string; skillVersion: string; bundleDigest: string; inputDigest: string; }): Promise; listAttempts(runId: string): Promise; createAttempt(input: CreateAttemptInput): Promise; claimAttempt(input: ClaimAttemptInput): Promise; recordLaunchIntent(input: { runId: string; attemptId: string; clientToken: string; requestDigest: string; startedBy: string; }): Promise; recordLaunchState(input: { runId: string; attemptId: string; launchState: AttemptRecord["launchState"]; taskId?: string | null; }): Promise; recordTransition(transition: RunTransitionRecord): Promise; markAttemptTerminal(runId: string, attemptId: string): Promise; writeReceipt(receipt: AttemptReceipt): Promise; getReceipt(runId: string, attemptId: string): Promise; finalizeRun(runId: string, status: TerminalRunStatus, receiptId: string): Promise; setRunStatus(runId: string, status: ExecutionRunStatus): Promise; close?(): Promise; } declare function newRunId(): string; export { newRunId }; /** * In-memory implementation. Single-process only: the read-then-write claim * path is atomic only because the event loop cannot interleave two synchronous * turns. The SQLite backend is the durable twin; this one exists for tests and * for embedders that deliberately keep the queue in-process. */ export declare class MemoryRunExecutionStore implements RunExecutionStore { readonly durable = false; private runs; private byKey; private byDigests; private attempts; private transitions; private receipts; admit(admission: FrozenAdmission): Promise; getRun(runId: string): Promise; getRunByKey(tenantId: string, idempotencyKey: string): Promise; getRunByDigests(input: { tenantId: string; skillId: string; skillVersion: string; bundleDigest: string; inputDigest: string; }): Promise; listAttempts(runId: string): Promise; createAttempt(input: CreateAttemptInput): Promise; claimAttempt(input: ClaimAttemptInput): Promise; recordLaunchIntent(input: { runId: string; attemptId: string; clientToken: string; requestDigest: string; startedBy: string; }): Promise; recordLaunchState(input: { runId: string; attemptId: string; launchState: AttemptRecord["launchState"]; taskId?: string | null; }): Promise; recordTransition(transition: RunTransitionRecord): Promise; markAttemptTerminal(runId: string, attemptId: string): Promise; writeReceipt(receipt: AttemptReceipt): Promise; getReceipt(runId: string, attemptId: string): Promise; finalizeRun(runId: string, status: TerminalRunStatus, receiptId: string): Promise; setRunStatus(runId: string, status: ExecutionRunStatus): Promise; } /** * SQLite backend. `:memory:` is supported for tests; a path gives the durable * twin. All writes go through a single connection, so the CAS claim and the * launch-intent write are atomic by construction — the same property the * postgres backend must provide through row locking. */ export declare class SqliteRunExecutionStore implements RunExecutionStore { readonly durable = true; private db; constructor(path?: string); admit(admission: FrozenAdmission): Promise; getRun(runId: string): Promise; getRunByKey(tenantId: string, idempotencyKey: string): Promise; getRunByDigests(input: { tenantId: string; skillId: string; skillVersion: string; bundleDigest: string; inputDigest: string; }): Promise; listAttempts(runId: string): Promise; createAttempt(input: CreateAttemptInput): Promise; claimAttempt(input: ClaimAttemptInput): Promise; recordLaunchIntent(input: { runId: string; attemptId: string; clientToken: string; requestDigest: string; startedBy: string; }): Promise; recordLaunchState(input: { runId: string; attemptId: string; launchState: AttemptRecord["launchState"]; taskId?: string | null; }): Promise; recordTransition(transition: RunTransitionRecord): Promise; markAttemptTerminal(runId: string, attemptId: string): Promise; writeReceipt(receipt: AttemptReceipt): Promise; getReceipt(runId: string, attemptId: string): Promise; finalizeRun(runId: string, status: TerminalRunStatus, receiptId: string): Promise; setRunStatus(runId: string, status: ExecutionRunStatus): Promise; close(): Promise; private readRun; private readAttempt; }