/** * Concurrency scheduler for the local-model workflow runtime. * * Mirrors the execution model of Claude Code's dynamic-workflow runtime: * - `parallel(thunks)` — barrier; runs all thunks with bounded concurrency * and awaits them all (order-preserving). Use for lens panels / N skeptics. * - `pipeline(items, ...stages)` — per-item, NO barrier between stages; each * item flows through every stage independently, so item A can be in stage 3 * while item B is still in stage 1. Total concurrent stage executions are * bounded by the same cap. * * Concurrency is enforced by a hand-off semaphore (true bounded concurrency, * unlike chunk-batching which idles fast tasks waiting on a slow one). A live * agent counter caps total executions over the scheduler's lifetime (the * runaway guard — Claude Code uses 1000/run). */ /** Raised when a scheduler exceeds its lifetime agent-execution cap. */ export declare class AgentCapError extends Error { /** The cap that was hit. */ readonly cap: number; constructor(message: string, /** The cap that was hit. */ cap: number); } /** * The default concurrency cap: `min(16, cores - 2)`, floored at 1. Matches the * Claude Code dynamic-workflow runtime. For local model servers the real bound * is usually the server's slot count (e.g. Ollama's OLLAMA_NUM_PARALLEL), so * callers should override `maxConcurrent` to match their backend. */ export declare function defaultConcurrency(): number; /** * A counting semaphore with FIFO hand-off: when a holder releases and a waiter * is queued, the slot transfers directly to that waiter (the active count never * dips), giving true peak-concurrency === cap regardless of task duration. */ export declare class Semaphore { private readonly cap; private active; private readonly waiters; constructor(cap: number); acquire(): Promise; release(): void; /** Number of currently-held slots (for tests / introspection). */ get inFlight(): number; } export interface SchedulerOptions { /** Max concurrent task executions. Default {@link defaultConcurrency}. */ maxConcurrent?: number; /** Hard ceiling on total executions over this scheduler's lifetime. Default 1000. */ maxAgents?: number; } /** A pipeline stage: receives the previous stage's output, the original item, and its index. */ export type Stage = (prev: unknown, item: I, index: number) => Promise; export declare class Scheduler { readonly maxConcurrent: number; readonly maxAgents: number; private readonly sem; private agentsStarted; constructor(opts?: SchedulerOptions); /** Total task executions started over this scheduler's lifetime. */ get agentsRun(): number; /** Acquire a slot, run, release — counting the execution against the cap. */ private run; /** * Run all thunks concurrently (bounded by the cap) and await them all. * Results are index-aligned with `thunks`. A thunk that throws rejects the * whole call (use try/catch inside the thunk for {@link Promise.allSettled}-style * tolerance). */ parallel(thunks: ReadonlyArray<() => Promise>): Promise; /** * Run each item through every stage independently — no barrier between * stages. Returns an array index-aligned with `items`. A stage that throws * (other than {@link AgentCapError}) drops that item to `null` and skips its * remaining stages; the runaway-cap error propagates. */ pipeline(items: ReadonlyArray, ...stages: Array>): Promise; } /** * Map over `items` applying `fn` with at most `cap` concurrent calls, preserving * input order. Backed by a hand-off {@link Semaphore} (true bounded concurrency, * superseding the chunk-batching copies previously duplicated in the evaluator * and architect agents). */ export declare function mapBounded(items: ReadonlyArray, cap: number, fn: (x: T) => Promise): Promise; //# sourceMappingURL=scheduler.d.ts.map