/**
 * WorkflowRunner — parses relay.yaml, validates config, resolves templates,
 * executes steps (sequential/parallel/DAG), runs verification checks,
 * persists state to DB, and supports pause/resume/abort with retries.
 */
import type { AgentCli, DryRunReport, RelayYamlConfig, WorkflowRunRow, WorkflowStepRow } from './types.js';
import { AgentRelay } from '../relay.js';
import type { AgentRelayOptions } from '../relay.js';
/** Minimal DB adapter so the runner is not coupled to a specific driver. */
export interface WorkflowDb {
    insertRun(run: WorkflowRunRow): Promise<void>;
    updateRun(id: string, patch: Partial<WorkflowRunRow>): Promise<void>;
    getRun(id: string): Promise<WorkflowRunRow | null>;
    insertStep(step: WorkflowStepRow): Promise<void>;
    updateStep(id: string, patch: Partial<WorkflowStepRow>): Promise<void>;
    getStepsByRunId(runId: string): Promise<WorkflowStepRow[]>;
}
export type WorkflowEvent = {
    type: 'run:started';
    runId: string;
} | {
    type: 'run:completed';
    runId: string;
} | {
    type: 'run:failed';
    runId: string;
    error: string;
} | {
    type: 'run:cancelled';
    runId: string;
} | {
    type: 'step:started';
    runId: string;
    stepName: string;
} | {
    type: 'step:completed';
    runId: string;
    stepName: string;
    output?: string;
} | {
    type: 'step:failed';
    runId: string;
    stepName: string;
    error: string;
} | {
    type: 'step:skipped';
    runId: string;
    stepName: string;
} | {
    type: 'step:retrying';
    runId: string;
    stepName: string;
    attempt: number;
} | {
    type: 'step:nudged';
    runId: string;
    stepName: string;
    nudgeCount: number;
} | {
    type: 'step:force-released';
    runId: string;
    stepName: string;
};
export type WorkflowEventListener = (event: WorkflowEvent) => void;
export interface WorkflowRunnerOptions {
    db?: WorkflowDb;
    workspaceId?: string;
    relay?: AgentRelayOptions;
    cwd?: string;
    summaryDir?: string;
}
export interface VariableContext {
    [key: string]: string | number | boolean | undefined;
}
export declare class WorkflowRunner {
    private readonly db;
    private readonly workspaceId;
    private readonly relayOptions;
    private readonly cwd;
    private readonly summaryDir;
    /** @internal exposed for CLI signal-handler shutdown only */
    relay?: AgentRelay;
    private relaycast?;
    private relaycastAgent?;
    private relayApiKey?;
    private relayApiKeyAutoCreated;
    private channel?;
    private trajectory?;
    private abortController?;
    private paused;
    private pauseResolver?;
    private listeners;
    /** Current config for the active run, so spawnAndWait can access swarm config. */
    private currentConfig?;
    /** Current run ID for event emission from spawnAndWait context. */
    private currentRunId?;
    /** Live Agent handles keyed by name, for hub-mediated nudging. */
    private readonly activeAgentHandles;
    private readonly ptyOutputBuffers;
    private readonly ptyListeners;
    private readonly ptyLogStreams;
    /** Path to workers.json so `agents:kill` can find workflow-spawned agents */
    private readonly workersPath;
    /** In-memory tracking of active workers to avoid race conditions on workers.json */
    private readonly activeWorkers;
    /** Mutex for serializing workers.json file access */
    private workersFileLock;
    /** Timestamp when the current workflow run started, for elapsed-time logging. */
    private runStartTime?;
    /** Unsubscribe handle for broker stderr listener wired during a run. */
    private unsubBrokerStderr?;
    /** Tracks last idle log time per agent to debounce idle warnings (30s multiples). */
    private readonly lastIdleLog;
    /** Tracks last logged activity type per agent to avoid duplicate status lines. */
    private readonly lastActivity;
    constructor(options?: WorkflowRunnerOptions);
    /** Log a progress message with elapsed time since run start. */
    private log;
    /**
     * Ensure a Relaycast workspace API key is available for the broker.
     * Resolution order:
     *   1. RELAY_API_KEY environment variable (explicit override)
     *   2. Auto-create a fresh workspace via the Relaycast API
     *
     * Each workflow run gets its own isolated workspace — no caching, no sharing.
     */
    private ensureRelaycastApiKey;
    private getRelayEnv;
    private getRelaycastBaseUrl;
    private getRelaycastClient;
    private ensureRelaycastRunnerAgent;
    private createAndJoinRelaycastChannel;
    private registerRelaycastExternalAgent;
    private startRelaycastHeartbeat;
    on(listener: WorkflowEventListener): () => void;
    private emit;
    /** Parse a relay.yaml file from disk. */
    parseYamlFile(filePath: string): Promise<RelayYamlConfig>;
    /** Parse a relay.yaml string. */
    parseYamlString(raw: string, source?: string): RelayYamlConfig;
    /** Validate a config object against the RelayYamlConfig shape. */
    validateConfig(config: unknown, source?: string): asserts config is RelayYamlConfig;
    /**
     * Validate a workflow config and simulate execution waves without spawning agents.
     * Returns a DryRunReport with DAG analysis, agent summary, and wave breakdown.
     */
    dryRun(config: RelayYamlConfig, workflowName?: string, vars?: VariableContext): DryRunReport;
    private validateWorkflow;
    private detectCycles;
    private detectLeadWorkerDeadlock;
    /** Resolve {{variable}} placeholders in all task strings. */
    resolveVariables(config: RelayYamlConfig, vars: VariableContext): RelayYamlConfig;
    private interpolate;
    private resolveDotPath;
    /** Build a nested context from completed step outputs for {{steps.X.output}} resolution. */
    private buildStepOutputContext;
    /** Interpolate step-output variables, silently skipping unresolved ones (they may be user vars). */
    private interpolateStepTask;
    /** Execute a named workflow from a validated config. */
    execute(config: RelayYamlConfig, workflowName?: string, vars?: VariableContext): Promise<WorkflowRunRow>;
    /** Resume a previously paused or partially completed run. */
    resume(runId: string, vars?: VariableContext): Promise<WorkflowRunRow>;
    private runWorkflowCore;
    /** Pause execution. Currently-running steps will finish but no new steps start. */
    pause(): void;
    /** Resume after a pause(). */
    unpause(): void;
    /** Abort the current run. Running agents are released. */
    abort(): void;
    private executeSteps;
    private findReadySteps;
    /**
     * Execute preflight checks before any workflow steps.
     * All checks must pass or the workflow fails immediately.
     */
    private runPreflightChecks;
    /** Check if a step is deterministic (shell command) vs agent (LLM-powered). */
    private isDeterministicStep;
    /** Check if a step is a worktree (git worktree setup) step. */
    private isWorktreeStep;
    private executeStep;
    /**
     * Execute a deterministic step (shell command).
     * Fast, reliable, $0 LLM cost.
     */
    private executeDeterministicStep;
    /**
     * Execute a worktree step (git worktree setup).
     * Fast, reliable, $0 LLM cost.
     * Outputs the worktree path for downstream steps to use.
     */
    private executeWorktreeStep;
    /**
     * Execute an agent step (LLM-powered).
     */
    private executeAgentStep;
    /**
     * Build the CLI command and arguments for a non-interactive agent execution.
     * Each CLI has a specific flag for one-shot prompt mode.
     */
    static buildNonInteractiveCommand(cli: AgentCli, task: string, extraArgs?: string[]): {
        cmd: string;
        args: string[];
    };
    /**
     * Apply preset defaults to an agent definition.
     * Explicit fields on the definition always win over preset-inferred defaults.
     */
    private static resolveAgentDef;
    /**
     * Returns a preset-specific prefix that is prepended to the non-interactive
     * enforcement block in execNonInteractive.
     */
    /**
     * Returns a prefix injected into the task prompt for non-interactive agents.
     * Lead agents are always interactive (PTY), so they never reach execNonInteractive
     * and there is no 'lead' case here.
     */
    private buildPresetInjection;
    /**
     * Execute an agent as a non-interactive subprocess.
     * No PTY, no relay messaging, no /exit injection. The process receives its task
     * as a CLI argument and stdout is captured as the step output.
     */
    private execNonInteractive;
    private spawnAndWait;
    /** Patterns where a hub agent coordinates spoke agents. */
    private static readonly HUB_PATTERNS;
    /** Roles that indicate a coordinator/lead agent (eligible for delegation guidance). */
    private static readonly HUB_ROLES;
    /**
     * Wait for agent exit with idle detection and nudging.
     * If no idle nudge config is set, falls through to simple waitForExit.
     */
    private waitForExitWithIdleNudging;
    /**
     * Send a nudge to an idle agent. Uses hub-mediated nudge for hub patterns,
     * or direct system injection otherwise.
     */
    private nudgeIdleAgent;
    /**
     * Find the hub agent for hub-mediated nudging.
     * Returns the hub's live Agent handle if this is a hub pattern and the idle agent is not the hub.
     */
    private resolveHubForNudge;
    private runVerification;
    private updateRunStatus;
    private markStepFailed;
    private markDownstreamSkipped;
    private checkAborted;
    private waitIfPaused;
    private delay;
    /**
     * Build a metadata note about non-interactive workers for inclusion in interactive agent tasks.
     * Returns undefined if there are no non-interactive agents.
     */
    private buildNonInteractiveAwareness;
    /**
     * Build guidance that encourages agents to autonomously delegate subtasks
     * to helper agents when work is too complex for a single pass.
     */
    /**
     * Returns a relay registration preamble for CLIs that don't auto-call
     * `register` via the MCP system prompt (everyone except claude).
     *
     * Claude reads the Relaycast system prompt and registers on its own.
     * Codex, gemini, etc. have the MCP server configured with the workspace
     * key, but they won't call `register` unless explicitly told to.
     */
    private buildRelayRegistrationNote;
    private buildDelegationGuidance;
    /** Post a message to the workflow channel. Fire-and-forget — never throws or blocks. */
    private postToChannel;
    /** Post a rich completion report to the channel. */
    private postCompletionReport;
    /** Post a failure report to the channel. */
    private postFailureReport;
    /**
     * Log a human-readable run summary to the console after completion or failure.
     * Extracts the last meaningful lines from each step's raw PTY output.
     */
    private logRunSummary;
    /**
     * Extract a useful excerpt from raw PTY output.
     * Looks for the agent's final text output (ignoring ANSI, system prompts, tool calls).
     */
    private extractOutputExcerpt;
    /** Analyze DAG structure for trajectory context. */
    private analyzeDAG;
    /** Collect step outcomes for trajectory synthesis. */
    private collectOutcomes;
    private generateId;
    private generateShortId;
    /** Strip ANSI escape codes from terminal output — delegates to pty.ts canonical regex. */
    private static stripAnsi;
    /**
     * Strip TUI chrome from PTY-captured output before posting to a channel.
     * Removes: ANSI codes, unicode spinner/thinking characters, cursor-movement
     * artifacts, and collapses runs of blank lines to a single blank line.
     * The raw (ANSI-stripped) output is still written to disk for step chaining.
     */
    private static scrubForChannel;
    /** Sanitize a workflow name into a valid channel name. */
    private sanitizeChannelName;
    /** Directory for persisted step outputs: .agent-relay/step-outputs/{runId}/ */
    private getStepOutputDir;
    /** Persist step output to disk and post full output as a channel message. */
    private persistStepOutput;
    /** Load persisted step output from disk. */
    private loadStepOutput;
    /** Get or create the worker logs directory (.agent-relay/team/worker-logs) */
    private getWorkerLogsDir;
    /** Register a spawned agent in workers.json so `agents:kill` can find it. */
    private registerWorker;
    /** Remove a spawned agent from workers.json after it exits. */
    private unregisterWorker;
    private readWorkers;
    private writeWorkers;
}
//# sourceMappingURL=runner.d.ts.map