/**
 * Spawner Service
 *
 * This service manages spawning and lifecycle of agent processes
 * for AI agents in the orchestration system.
 *
 * Key features:
 * - Spawn headless agents (ephemeral workers, stewards) via provider abstraction
 * - Spawn interactive agents (Director, persistent workers) via provider abstraction
 * - Resume existing sessions with provider session IDs
 * - Parse stream-json events (assistant, tool_use, tool_result, error)
 * - Track session metadata for cross-restart resumption
 * - Provider-agnostic: supports Claude Code, OpenCode, and future providers
 *
 * @module
 */
import { EventEmitter } from 'node:events';
import type { EntityId, Timestamp } from '@stoneforge/core';
import type { AgentRole, WorkerMode } from '../types/agent.js';
import type { AgentProvider } from '../providers/types.js';
/**
 * Shell-quotes a string for safe inclusion in a bash command.
 * Wraps in single quotes and escapes internal single quotes.
 */
export declare function shellQuote(s: string): string;
/**
 * Mode for spawning an agent process
 */
export type SpawnMode = 'headless' | 'interactive';
/**
 * Configuration for spawn behavior
 */
export interface SpawnConfig {
    /** Agent provider to use (defaults to Claude) */
    readonly provider?: AgentProvider;
    /** @deprecated Use provider instead. The Claude Code executable path. */
    readonly claudePath?: string;
    /** Working directory for the agent */
    readonly workingDirectory?: string;
    /** Environment variables to pass to the process */
    readonly environmentVariables?: Record<string, string>;
    /** Timeout for process operations in milliseconds */
    readonly timeout?: number;
    /** Root directory for stoneforge (passed as STONEFORGE_ROOT) */
    readonly stoneforgeRoot?: string;
}
/**
 * Options for spawning an agent session
 */
export interface SpawnOptions extends SpawnConfig {
    /** Provider session ID to resume (if any) */
    readonly resumeSessionId?: string;
    /** Initial prompt to send to the agent */
    readonly initialPrompt?: string;
    /** Spawn mode: headless (stream-json) or interactive (PTY) */
    readonly mode?: SpawnMode;
    /** Terminal columns (for interactive mode, default 120) */
    readonly cols?: number;
    /** Terminal rows (for interactive mode, default 30) */
    readonly rows?: number;
    /** Model identifier to use (e.g., 'claude-sonnet-4-20250514'). If not set, uses provider default. */
    readonly model?: string;
}
/**
 * Stream-json event types from Claude Code
 */
export type StreamJsonEventType = 'system' | 'assistant' | 'user' | 'tool_use' | 'tool_result' | 'result' | 'error';
/**
 * Stream-json event structure from Claude Code
 */
export interface StreamJsonEvent {
    /** Event type */
    readonly type: StreamJsonEventType;
    /** Event subtype (e.g., 'init', 'text', 'input_json_delta') */
    readonly subtype?: string;
    /** Session ID (from init event) */
    readonly session_id?: string;
    /** Tool information */
    readonly tool?: string;
    readonly tool_use_id?: string;
    readonly tool_input?: unknown;
    /** Content (for assistant/user messages) */
    readonly message?: string;
    readonly content?: string;
    /** Timestamp */
    readonly timestamp?: string;
    /** Error information */
    readonly error?: string;
    /** Result status */
    readonly result?: string;
    /** Raw event data */
    readonly [key: string]: unknown;
}
/**
 * Parsed event with typed data
 */
export interface SpawnedSessionEvent {
    /** Event type */
    readonly type: StreamJsonEventType;
    /** Event subtype */
    readonly subtype?: string;
    /** Timestamp when event was received */
    readonly receivedAt: Timestamp;
    /** Raw event data */
    readonly raw: StreamJsonEvent;
    /** Parsed message content (if any) */
    readonly message?: string;
    /** Tool information (if tool_use or tool_result) */
    readonly tool?: {
        readonly name?: string;
        readonly id?: string;
        readonly input?: unknown;
    };
}
/**
 * Status of a spawned session
 */
export type SessionStatus = 'starting' | 'running' | 'suspended' | 'terminating' | 'terminated';
/**
 * Session state machine transitions
 */
export declare const SessionStatusTransitions: Record<SessionStatus, SessionStatus[]>;
/**
 * Spawned session information
 */
export interface SpawnedSession {
    /** Internal session ID (unique per spawn) */
    readonly id: string;
    /** Provider session ID (for resume) */
    readonly providerSessionId?: string;
    /** Agent entity ID this session belongs to */
    readonly agentId: EntityId;
    /** Agent role */
    readonly agentRole: AgentRole;
    /** Worker mode (for workers) */
    readonly workerMode?: WorkerMode;
    /** Spawn mode used */
    readonly mode: SpawnMode;
    /** Process ID */
    readonly pid?: number;
    /** Current status */
    status: SessionStatus;
    /** Working directory */
    readonly workingDirectory: string;
    /** Session created timestamp */
    readonly createdAt: Timestamp;
    /** Last activity timestamp */
    lastActivityAt: Timestamp;
    /** Session started timestamp (when running state entered) */
    startedAt?: Timestamp;
    /** Session ended timestamp (when terminated) */
    endedAt?: Timestamp;
}
/**
 * Result of spawning an agent
 */
export interface SpawnResult {
    /** The spawned session */
    session: SpawnedSession;
    /** Event emitter for session events */
    events: EventEmitter;
}
/**
 * Options for sending input to a headless agent
 */
export interface SendInputOptions {
    /** Whether this is a user message (vs system command) */
    readonly isUserMessage?: boolean;
}
/**
 * Result of the UWP (Universal Work Principle) check
 */
export interface UWPCheckResult {
    /** Whether a ready task was found */
    hasReadyTask: boolean;
    /** The ready task ID if found */
    taskId?: string;
    /** The task title if found */
    taskTitle?: string;
    /** The task priority if found */
    taskPriority?: number;
    /** Whether the task was automatically started */
    autoStarted: boolean;
    /** Session ID if a task was auto-started */
    sessionId?: string;
}
/**
 * Spawner Service interface for agent process management.
 *
 * The service provides methods for:
 * - Spawning new agent sessions (headless or interactive)
 * - Resuming previous sessions
 * - Managing session lifecycle
 * - Sending input to headless agents
 */
export interface SpawnerService {
    /**
     * Spawns a new agent session.
     *
     * @param agentId - The agent entity ID
     * @param agentRole - The agent's role
     * @param options - Spawn options
     * @returns The spawn result with session info and event emitter
     */
    spawn(agentId: EntityId, agentRole: AgentRole, options?: SpawnOptions): Promise<SpawnResult>;
    /**
     * Terminates a running session.
     *
     * @param sessionId - The internal session ID
     * @param graceful - Whether to attempt graceful shutdown (default: true)
     */
    terminate(sessionId: string, graceful?: boolean): Promise<void>;
    /**
     * Suspends a session (marks it for later resume).
     *
     * @param sessionId - The internal session ID
     */
    suspend(sessionId: string): Promise<void>;
    /**
     * Interrupts a running session.
     * For headless sessions, this sends an interrupt signal.
     * For interactive sessions, this sends Escape key.
     *
     * @param sessionId - The internal session ID
     */
    interrupt(sessionId: string): Promise<void>;
    /**
     * Gets a session by internal ID.
     *
     * @param sessionId - The internal session ID
     * @returns The session or undefined if not found
     */
    getSession(sessionId: string): SpawnedSession | undefined;
    /**
     * Lists all active sessions.
     *
     * @param agentId - Optional filter by agent ID
     * @returns Array of active sessions
     */
    listActiveSessions(agentId?: EntityId): SpawnedSession[];
    /**
     * Lists all sessions (including terminated).
     *
     * @param agentId - Optional filter by agent ID
     * @returns Array of all sessions
     */
    listAllSessions(agentId?: EntityId): SpawnedSession[];
    /**
     * Gets the most recent session for an agent.
     *
     * @param agentId - The agent entity ID
     * @returns The most recent session or undefined
     */
    getMostRecentSession(agentId: EntityId): SpawnedSession | undefined;
    /**
     * Sends input to a headless agent's stdin.
     *
     * @param sessionId - The internal session ID
     * @param input - The input to send (will be formatted as stream-json)
     * @param options - Send options
     */
    sendInput(sessionId: string, input: string, options?: SendInputOptions): Promise<void>;
    /**
     * Writes data directly to an interactive PTY session.
     * This is for interactive sessions where input is sent character-by-character.
     *
     * @param sessionId - The internal session ID
     * @param data - The data to write to the PTY
     */
    writeToPty(sessionId: string, data: string): Promise<void>;
    /**
     * Resizes an interactive PTY session.
     *
     * @param sessionId - The internal session ID
     * @param cols - Number of columns
     * @param rows - Number of rows
     */
    resize(sessionId: string, cols: number, rows: number): Promise<void>;
    /**
     * Gets the event emitter for a session.
     *
     * Events emitted:
     * - 'event' (SpawnedSessionEvent) - Parsed stream-json event
     * - 'error' (Error) - Process error
     * - 'exit' (code: number | null, signal: string | null) - Process exit
     *
     * @param sessionId - The internal session ID
     * @returns The event emitter or undefined if session not found
     */
    getEventEmitter(sessionId: string): EventEmitter | undefined;
    /**
     * Checks the ready queue for an agent and optionally auto-starts the first task.
     *
     * This implements the Universal Work Principle (UWP):
     * "If there is work on your anchor, YOU MUST RUN IT"
     *
     * On agent startup:
     * 1. Query tasks ready for this agent (assigned to them, status open/in_progress)
     * 2. If task exists → Optionally set task status to IN_PROGRESS, return task info
     * 3. If no task → Return empty result, agent should enter idle/polling mode
     *
     * @param agentId - The agent entity ID to check tasks for
     * @param options - Options for the check
     * @returns UWP check result with task info if found
     */
    checkReadyQueue(agentId: EntityId, options?: UWPCheckOptions): Promise<UWPCheckResult>;
}
/**
 * Options for UWP ready queue check
 */
export interface UWPCheckOptions {
    /** Whether to automatically mark the task as started (default: false) */
    autoStart?: boolean;
    /** Maximum number of tasks to check (default: 1) */
    limit?: number;
    /** Callback to get task info - allows integration without circular deps */
    getReadyTasks?: (agentId: EntityId, limit: number) => Promise<UWPTaskInfo[]>;
}
/**
 * Task information for UWP check
 */
export interface UWPTaskInfo {
    id: string;
    title: string;
    priority: number;
    status: string;
}
/**
 * Options for building headless CLI arguments
 */
export interface HeadlessArgsOptions {
    /** Provider session ID to resume */
    resumeSessionId?: string;
    /** Initial prompt to send */
    initialPrompt?: string;
}
/**
 * Builds the CLI arguments for headless (non-interactive) Claude Code spawning.
 *
 * This function is exported to allow unit testing of the argument construction,
 * which is critical for ensuring Claude Code is invoked correctly.
 *
 * @param options - Options affecting argument construction
 * @returns Array of CLI arguments
 */
export declare function buildHeadlessArgs(options?: HeadlessArgsOptions): string[];
/**
 * Implementation of the Spawner Service.
 * Uses the provider abstraction to spawn and manage agent processes.
 */
export declare class SpawnerServiceImpl implements SpawnerService {
    private readonly sessions;
    private readonly defaultConfig;
    private readonly provider;
    private sessionCounter;
    constructor(config?: SpawnConfig);
    spawn(agentId: EntityId, agentRole: AgentRole, options?: SpawnOptions): Promise<SpawnResult>;
    terminate(sessionId: string, graceful?: boolean): Promise<void>;
    suspend(sessionId: string): Promise<void>;
    interrupt(sessionId: string): Promise<void>;
    getSession(sessionId: string): SpawnedSession | undefined;
    listActiveSessions(agentId?: EntityId): SpawnedSession[];
    listAllSessions(agentId?: EntityId): SpawnedSession[];
    getMostRecentSession(agentId: EntityId): SpawnedSession | undefined;
    sendInput(sessionId: string, input: string, _options?: SendInputOptions): Promise<void>;
    writeToPty(sessionId: string, data: string): Promise<void>;
    resize(sessionId: string, cols: number, rows: number): Promise<void>;
    getEventEmitter(sessionId: string): EventEmitter | undefined;
    checkReadyQueue(agentId: EntityId, options?: UWPCheckOptions): Promise<UWPCheckResult>;
    private spawnHeadless;
    /**
     * Process provider messages and emit them as session events.
     */
    private processProviderMessages;
    /**
     * Convert a provider AgentMessage to a SpawnedSessionEvent.
     */
    private convertAgentMessageToEvent;
    private spawnInteractive;
    private waitForInit;
    private handleHeadlessOutput;
    private parseAndEmitEvent;
    private generateSessionId;
    private determineSpawnMode;
    private getWorkerMode;
    private scheduleTerminatedSessionCleanup;
    private transitionStatus;
    private filterAndMapSessions;
    private toPublicSession;
}
/**
 * Creates a SpawnerService instance
 */
export declare function createSpawnerService(config?: SpawnConfig): SpawnerService;
/**
 * Checks if a status allows the session to receive input
 */
export declare function canReceiveInput(status: SessionStatus): boolean;
/**
 * Checks if a status is a terminal state
 */
export declare function isTerminalStatus(status: SessionStatus): boolean;
/**
 * Gets human-readable description of a session status
 */
export declare function getStatusDescription(status: SessionStatus): string;
//# sourceMappingURL=spawner.d.ts.map