/** * sub-dispatcher.ts — Self-contained nested sub-dispatcher for DAG sub-graphs. * * A SubDispatcherNode manages an independent sub-graph of PlanSteps with its * own dispatch loop, retry logic, timeout handling, failure propagation, and * deadlock detection. It mirrors the core dispatch logic of the parent * Dispatcher without plan parsing, artifact directory, watchdog timer, or * tasks-file-update overhead. * * Events from the sub-dispatcher are relayed to the parent via the * parentMetrics callback in SubDispatcherConfig. The parent can then aggregate * metrics from all sub-dispatchers. * * Integration with the main Dispatcher: * - The parent creates SubDispatcherNode instances via createSubDispatcher(). * - Sub-dispatchers are tracked in the parent's subDispatchers map. * - Sub-dispatcher metrics are included in the parent's overall getMetrics(). */ import type { Model, ThinkingLevel } from "@earendil-works/pi-ai"; import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; import type { PlanStep, StepMetrics, DispatchStatus, SubDispatcherConfig } from "./types.ts"; /** * Sub-agent spawn function signature matching the parent Dispatcher's type. * * This is used internally to spawn nested sub-agents for each step in the * sub-graph. The default delegates to runAgent from the nested-subagents * package. */ type SubSpawnAgentFn = (ctx: ExtensionContext, type: string, prompt: string, options: { pi: ExtensionAPI; inheritContext: boolean; isolated: boolean; depth: number; /** Parent session model object — passed explicitly so children inherit it. */ model?: Model; /** Thinking level override. Omit to inherit agent type's default. */ thinkingLevel?: ThinkingLevel; /** Maximum agentic turns before forced wrap-up. */ maxTurns?: number; }) => Promise<{ responseText: string; aborted: boolean; }>; /** * Self-contained nested sub-dispatcher for DAG sub-graphs. * * Manages an independent set of PlanSteps with its own dispatch loop, retry * logic, timeout handling, failure propagation, and deadlock detection. Events * are relayed to the parent dispatcher via the parentMetrics callback. * * Typical usage: * * const sub = new SubDispatcherNode(config, ctx, pi); * const finalStatus = await sub.run(); * const metrics = sub.getMetrics(); * * The parent Dispatcher can create SubDispatcherNodes for independent sub-graphs * and aggregate their metrics into its own reporting. */ export declare class SubDispatcherNode { private steps; private config; private spawnAgent; private ctx; private pi; private cpMap; private predecessorResults; private stepTimeouts; private metrics; private stopped; private dispatching; private lastDeadlockedCount; private completionPromise; private resolveCompletion; constructor(config: SubDispatcherConfig, ctx: ExtensionContext, pi: ExtensionAPI, spawnAgent?: SubSpawnAgentFn); /** * Start executing the sub-graph. Returns a promise that resolves when all * steps have reached a terminal state (done or failed). * * The resolved DispatchStatus reflects the final state of the sub-graph. */ run(): Promise; /** * Stop execution immediately. Prevents further dispatch and clears all * pending step timeouts. */ stop(): void; /** * Return a snapshot of all collected step metrics for this sub-graph. */ getMetrics(): StepMetrics[]; /** * Return the current execution status snapshot of the sub-graph. */ getStatus(): DispatchStatus; /** * Access the managed steps (for parent to inspect sub-graph state). */ getSteps(): PlanStep[]; /** * True if all steps in the sub-graph have reached a terminal state. */ get isComplete(): boolean; /** * Emit a lifecycle event via the parentMetrics callback. * Each event is tagged with `subDispatcher: true` so the parent can * distinguish sub-dispatcher events from its own. */ private emitEvent; /** * Dispatch all ready steps, respecting the concurrency limit. * Serialized via a promise chain so overlapping calls queue rather than race. */ private dispatchReady; /** * Execute a single step by spawning a sub-agent, with retry and timeout. * * Implements the same T-SEDR 3-strike re-mutation loop as the parent * Dispatcher: * - Promise.race between the spawnAgent and a timeout rejection. * - Retry loop with exponential backoff (retryDelayMs * retryCount). * - Metrics tracking for each attempt. * - Emits step_started / step_timed_out / step_failed events. */ private executeStep; /** * Clear and remove any pending timeout for the given step. */ private clearStepTimeout; /** * Handle successful step completion: update status, record metrics, persist * result, check for deadlocks, and re-invoke dispatch for newly-ready steps. */ private onStepComplete; /** * Handle step failure: update status, record metrics, propagate failure * downstream, and re-evaluate completion. */ private onStepFail; /** * Propagate failure downstream through the sub-graph DAG using iterative * (stack-based) traversal instead of recursion, preventing stack overflow * on deep dependency chains. */ private propagateFailure; /** * Check for deadlocked steps within the sub-graph. Pending steps whose * transitive predecessors are all failed are marked as failed so they * don't block execution indefinitely. * * Only emits notifications when the deadlock count changes, preventing * repeated noise. */ private checkDeadlock; /** * Check if all steps in the sub-graph have reached a terminal state. * When they have, stop the sub-dispatcher and resolve the completion promise. */ private checkCompletion; } export {}; //# sourceMappingURL=sub-dispatcher.d.ts.map