/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import type { InjectionService } from '../config/injectionService.js';
import type { AnsiOutput } from '../utils/terminalSerializer.js';
export type ExecutionMethod = 'lydell-node-pty' | 'node-pty' | 'child_process' | 'remote_agent' | 'none';
export interface ExecutionResult {
    rawOutput: Buffer;
    output: string;
    exitCode: number | null;
    signal: number | null;
    error: Error | null;
    aborted: boolean;
    pid: number | undefined;
    executionMethod: ExecutionMethod;
    backgrounded?: boolean;
}
export interface ExecutionHandle {
    pid: number | undefined;
    result: Promise<ExecutionResult>;
}
export type ExecutionOutputEvent = {
    type: 'data';
    chunk: string | AnsiOutput;
} | {
    type: 'binary_detected';
} | {
    type: 'binary_progress';
    bytesReceived: number;
} | {
    type: 'exit';
    exitCode: number | null;
    signal: number | null;
};
export interface ExecutionCompletionOptions {
    exitCode?: number | null;
    signal?: number | null;
    error?: Error | null;
    aborted?: boolean;
}
export interface ExternalExecutionRegistration {
    executionMethod: ExecutionMethod;
    initialOutput?: string;
    getBackgroundOutput?: () => string;
    getSubscriptionSnapshot?: () => string | AnsiOutput | undefined;
    writeInput?: (input: string) => void;
    kill?: () => void;
    isActive?: () => boolean;
}
/**
 * Callback that an execution creator provides to control how its output
 * is formatted when reinjected into the model conversation after backgrounding.
 * Return `null` to skip injection entirely.
 */
export type FormatInjectionFn = (output: string, error: Error | null) => string | null;
/**
 * Payload emitted when a previously-backgrounded execution settles.
 */
export interface BackgroundCompletionInfo {
    executionId: number;
    executionMethod: ExecutionMethod;
    output: string;
    error: Error | null;
    /** Pre-formatted injection text from the execution creator, or `null` if skipped. */
    injectionText: string | null;
}
export type BackgroundCompletionListener = (info: BackgroundCompletionInfo) => void;
/**
 * Central owner for execution backgrounding lifecycle across shell and tools.
 */
export declare class ExecutionLifecycleService {
    private static readonly EXIT_INFO_TTL_MS;
    private static nextExecutionId;
    private static activeExecutions;
    private static activeResolvers;
    private static activeListeners;
    private static exitedExecutionInfo;
    private static backgroundCompletionListeners;
    private static injectionService;
    /**
     * Wires a singleton InjectionService so that backgrounded executions
     * can inject their output directly without routing through the UI layer.
     */
    static setInjectionService(service: InjectionService): void;
    /**
     * Registers a listener that fires when a previously-backgrounded
     * execution settles (completes or errors).
     */
    static onBackgroundComplete(listener: BackgroundCompletionListener): void;
    /**
     * Unregisters a background completion listener.
     */
    static offBackgroundComplete(listener: BackgroundCompletionListener): void;
    private static storeExitInfo;
    private static allocateExecutionId;
    private static createPendingResult;
    private static createAbortedResult;
    /**
     * Resets lifecycle state for isolated unit tests.
     */
    static resetForTest(): void;
    static attachExecution(executionId: number, registration: ExternalExecutionRegistration): ExecutionHandle;
    static createExecution(initialOutput?: string, onKill?: () => void, executionMethod?: ExecutionMethod, formatInjection?: FormatInjectionFn): ExecutionHandle;
    static appendOutput(executionId: number, chunk: string): void;
    static emitEvent(executionId: number, event: ExecutionOutputEvent): void;
    private static resolvePending;
    private static settleExecution;
    static completeExecution(executionId: number, options?: ExecutionCompletionOptions): void;
    static completeWithResult(executionId: number, result: ExecutionResult): void;
    static background(executionId: number): void;
    static subscribe(executionId: number, listener: (event: ExecutionOutputEvent) => void): () => void;
    static onExit(executionId: number, callback: (exitCode: number, signal?: number) => void): () => void;
    static kill(executionId: number): void;
    static isActive(executionId: number): boolean;
    static writeInput(executionId: number, input: string): void;
}
