export interface AsyncJob {
    id: string;
    type: "bash" | "task";
    status: "running" | "completed" | "failed" | "cancelled";
    startTime: number;
    label: string;
    abortController: AbortController;
    promise: Promise<void>;
    resultText?: string;
    errorText?: string;
    /**
     * Registry id of the agent that registered the job (e.g. "Main",
     * "AuthLoader"). Used by scoped cancel/list APIs so a subagent's teardown
     * does not cancel its parent's jobs. Undefined for callers that don't
     * supply an id (e.g. legacy tests, SDK consumers without an agent context).
     */
    ownerId?: string;
    /**
     * Job is registered but parked behind a caller-managed gate (e.g. a task
     * batch semaphore). Queued jobs do not count toward the running-job limit
     * until the caller invokes `markRunning()` from the run context.
     */
    queued?: boolean;
}
export interface AsyncJobManagerOptions {
    onJobComplete: (jobId: string, text: string, job?: AsyncJob) => void | Promise<void>;
    maxRunningJobs?: number;
    retentionMs?: number;
}
export interface AsyncJobDeliveryState {
    queued: number;
    delivering: boolean;
    nextRetryAt?: number;
    pendingJobIds: string[];
}
export interface AsyncJobRegisterOptions {
    id?: string;
    /** Registry id of the agent that owns this job; used to scope cancelAll. */
    ownerId?: string;
    onProgress?: (text: string, details?: Record<string, unknown>) => void | Promise<void>;
    /** Register the job in queued state; see {@link AsyncJob.queued}. */
    queued?: boolean;
}
/**
 * Filter applied to job query/cancel APIs. With `ownerId`, results are
 * restricted to jobs registered by that agent (registry id from
 * `AgentRegistry`, e.g. "Main", "AuthLoader").
 */
export interface AsyncJobFilter {
    ownerId?: string;
}
export declare class AsyncJobManager {
    #private;
    /** Process-global instance shared by internal URL protocol handlers and tools. */
    static instance(): AsyncJobManager | undefined;
    /** Install or clear the process-global instance. */
    static setInstance(value: AsyncJobManager | undefined): void;
    /** Reset the process-global instance. Test-only. */
    static resetForTests(): void;
    constructor(options: AsyncJobManagerOptions);
    /** True when the running-job count has reached the configured cap. */
    get atCapacity(): boolean;
    register(type: "bash" | "task", label: string, run: (ctx: {
        jobId: string;
        signal: AbortSignal;
        reportProgress: (text: string, details?: Record<string, unknown>) => Promise<void>;
        /** Clear the queued flag once the job actually starts executing. */
        markRunning: () => void;
    }) => Promise<string>, options?: AsyncJobRegisterOptions): string;
    /**
     * Cancel a single job by id. When `filter.ownerId` is set and does not
     * match the job's owner, the call is treated as not-found (returns false)
     * so cross-agent cancellation is rejected at the manager level.
     */
    cancel(id: string, filter?: AsyncJobFilter): boolean;
    getJob(id: string): AsyncJob | undefined;
    getRunningJobs(filter?: AsyncJobFilter): AsyncJob[];
    getRecentJobs(limit?: number, filter?: AsyncJobFilter): AsyncJob[];
    getAllJobs(filter?: AsyncJobFilter): AsyncJob[];
    getDeliveryState(filter?: AsyncJobFilter): AsyncJobDeliveryState;
    hasPendingDeliveries(filter?: AsyncJobFilter): boolean;
    watchJobs(jobIds: string[]): number;
    unwatchJobs(jobIds: string[]): number;
    /**
     * Compute the next adaptive ("smart") wait (ms) for a blocking `job` poll by
     * the given owner. Consecutive polls — those starting within
     * POLL_ESCALATION_RESET_MS of the previous poll returning — climb
     * POLL_WAIT_LADDER_MS so a tight wait loop backs off; a longer gap means the
     * agent left to do real work, so the wait resets to the floor. Pair each call
     * with `recordPollWaitEnd()` once the wait returns.
     */
    nextPollWaitMs(ownerId: string | undefined, now?: number): number;
    /**
     * Mark a blocking poll wait as finished so the idle-reset window is measured
     * from now. Polling again before POLL_ESCALATION_RESET_MS elapses keeps
     * climbing the ladder; waiting longer resets it to the floor.
     */
    recordPollWaitEnd(ownerId: string | undefined, now?: number): void;
    acknowledgeDeliveries(jobIds: string[]): number;
    /**
     * Lift a foreground-wait suppression set via `acknowledgeDeliveries`. If the
     * job already finished while suppressed (its delivery enqueue was skipped),
     * re-enqueue the completion so the result is still delivered exactly once.
     */
    resumeDeliveries(jobIds: string[]): void;
    /**
     * Cancel running jobs. With `filter.ownerId` set, cancels only jobs the
     * matching agent registered; with no filter, cancels every running job
     * (used by `dispose()` to nuke the manager's state).
     */
    cancelAll(filter?: AsyncJobFilter): void;
    waitForAll(): Promise<void>;
    drainDeliveries(options?: {
        timeoutMs?: number;
        filter?: AsyncJobFilter;
    }): Promise<boolean>;
    dispose(options?: {
        timeoutMs?: number;
    }): Promise<boolean>;
    isDeliverySuppressed(jobId: string): boolean;
}
