import { HealthCheckResult } from '../health/checkFns';
import { Trigger } from '../trigger';
import * as T from '../../../base/lib/types';
import { SubContainer } from '../util/SubContainer';
import * as CP from 'node:child_process';
export { Daemon } from './Daemon';
export { CommandController } from './CommandController';
import { HealthDaemon } from './HealthDaemon';
import { Daemon } from './Daemon';
import { CommandController } from './CommandController';
/** Promisified version of `child_process.exec` */
export declare const cpExec: typeof CP.exec.__promisify__;
/** Promisified version of `child_process.execFile` */
export declare const cpExecFile: typeof CP.execFile.__promisify__;
/**
 * Configuration for a daemon's health-check readiness probe.
 *
 * Determines how the system knows when a daemon is healthy and ready to serve.
 */
export type Ready = {
    /** A human-readable display name for the health check. If null, the health check itself will be from the UI */
    display: string | null;
    /**
     * @description The function to determine the health status of the daemon
     *
     *   The SDK provides some built-in health checks. To see them, type sdk.healthCheck.
     *
     * @example
     * ```
      fn: () =>
        sdk.healthCheck.checkPortListening(effects, 80, {
          successMessage: 'service listening on port 80',
          errorMessage: 'service is unreachable',
        })
    * ```
    */
    fn: () => Promise<HealthCheckResult> | HealthCheckResult;
    /**
     * A duration in milliseconds to treat a failing health check as "starting"
     *
     * defaults to 5000
     */
    gracePeriod?: number;
    trigger?: Trigger;
};
/**
 * Options for running a daemon as a shell command inside a subcontainer.
 * Includes the command to run, optional signal/timeout, environment, user, and stdio callbacks.
 */
export type ExecCommandOptions = {
    command: T.CommandType;
    sigtermTimeout?: number;
    runAsInit?: boolean;
    env?: {
        [variable in string]?: string;
    } | undefined;
    cwd?: string | undefined;
    user?: string | undefined;
    onStdout?: (chunk: Buffer | string | any) => void;
    onStderr?: (chunk: Buffer | string | any) => void;
};
/**
 * Options for running a daemon via an async function that may optionally return
 * a command to execute in the subcontainer. The function receives an `AbortSignal`
 * for cooperative cancellation.
 */
export type ExecFnOptions<Manifest extends T.SDKManifest, C extends SubContainer<Manifest> | null> = {
    fn: (subcontainer: C, abort: AbortSignal) => Promise<C extends null ? null : ExecCommandOptions | null>;
    sigtermTimeout?: number;
};
/**
 * The execution specification for a daemon: either an {@link ExecFnOptions} (async function)
 * or an {@link ExecCommandOptions} (shell command, only valid when a subcontainer is provided).
 */
export type DaemonCommandType<Manifest extends T.SDKManifest, C extends SubContainer<Manifest> | null> = ExecFnOptions<Manifest, C> | (C extends null ? never : ExecCommandOptions);
type NewDaemonParams<Manifest extends T.SDKManifest, C extends SubContainer<Manifest> | null> = {
    /** What to run as the daemon: either an async fn or a commandline command to run in the subcontainer */
    exec: DaemonCommandType<Manifest, C>;
    /** The subcontainer in which the daemon runs */
    subcontainer: C;
};
type OptionalParamSync<T> = T | (() => T | null);
type OptionalParamAsync<T> = () => Promise<T | null>;
type AddDaemonParams<Manifest extends T.SDKManifest, Ids extends string, Id extends string, C extends SubContainer<Manifest> | null> = (NewDaemonParams<Manifest, C> | {
    daemon: Daemon<Manifest>;
}) & {
    ready: Ready;
    /** An array of IDs of prior daemons whose successful initializations are required before this daemon will initialize */
    requires: Exclude<Ids, Id>[];
};
type AddOneshotParams<Manifest extends T.SDKManifest, Ids extends string, Id extends string, C extends SubContainer<Manifest> | null> = NewDaemonParams<Manifest, C> & {
    exec: DaemonCommandType<Manifest, C>;
    /** An array of IDs of prior daemons whose successful initializations are required before this daemon will initialize */
    requires: Exclude<Ids, Id>[];
};
type AddHealthCheckParams<Ids extends string, Id extends string> = {
    ready: Ready;
    /** An array of IDs of prior daemons whose successful initializations are required before this daemon will initialize */
    requires: Exclude<Ids, Id>[];
};
type ErrorDuplicateId<Id extends string> = `The id '${Id}' is already used`;
export declare const runCommand: <Manifest extends T.SDKManifest>() => (effects: T.Effects, subcontainer: SubContainer<Manifest, T.Effects>, exec: DaemonCommandType<Manifest, SubContainer<Manifest, T.Effects>>) => Promise<CommandController<Manifest, SubContainer<Manifest, T.Effects>>>;
/**
 * A class for defining and controlling the service daemons
```ts
Daemons.of({
  effects,
  started,
  interfaceReceipt, // Provide the interfaceReceipt to prove it was completed
  healthReceipts, // Provide the healthReceipts or [] to prove they were at least considered
}).addDaemon('webui', {
  command: 'hello-world', // The command to start the daemon
  ready: {
    display: 'Web Interface',
    // The function to run to determine the health status of the daemon
    fn: () =>
      checkPortListening(effects, 80, {
        successMessage: 'The web interface is ready',
        errorMessage: 'The web interface is not ready',
      }),
  },
  requires: [],
})
```
 */
export declare class Daemons<Manifest extends T.SDKManifest, Ids extends string> implements T.DaemonBuildable {
    readonly effects: T.Effects;
    readonly ids: Ids[];
    readonly healthDaemons: HealthDaemon<Manifest>[];
    private termPromise;
    private constructor();
    /**
     * Returns an empty new Daemons class with the provided inputSpec.
     *
     * Call .addDaemon() on the returned class to add a daemon.
     *
     * Daemons run in the order they are defined, with latter daemons being capable of
     * depending on prior daemons
     *
     * @param effects
     *
     * @param started
     * @returns
     */
    static of<Manifest extends T.SDKManifest>(options: {
        effects: T.Effects;
    }): Daemons<Manifest, never>;
    private addDaemonImpl;
    /**
     * Returns the complete list of daemons, including the one defined here
     * @param id
     * @param options
     * @returns a new Daemons object
     */
    addDaemon<Id extends string, C extends SubContainer<Manifest> | null>(id: "" extends Id ? never : ErrorDuplicateId<Id> extends Id ? never : Id extends Ids ? ErrorDuplicateId<Id> : Id, options: OptionalParamSync<AddDaemonParams<Manifest, Ids, Id, C>>): Daemons<Manifest, Ids | Id>;
    addDaemon<Id extends string, C extends SubContainer<Manifest> | null>(id: "" extends Id ? never : ErrorDuplicateId<Id> extends Id ? never : Id extends Ids ? ErrorDuplicateId<Id> : Id, options: OptionalParamAsync<AddDaemonParams<Manifest, Ids, Id, C>>): Promise<Daemons<Manifest, Ids | Id>>;
    /**
     * Returns the complete list of daemons, including a "oneshot" daemon one defined here
     * a oneshot daemon is a command that executes once when started, and is considered "running" once it exits successfully
     * @param id
     * @param options
     * @returns a new Daemons object
     */
    addOneshot<Id extends string, C extends SubContainer<Manifest> | null>(id: "" extends Id ? never : ErrorDuplicateId<Id> extends Id ? never : Id extends Ids ? ErrorDuplicateId<Id> : Id, options: OptionalParamSync<AddOneshotParams<Manifest, Ids, Id, C>>): Daemons<Manifest, Ids | Id>;
    addOneshot<Id extends string, C extends SubContainer<Manifest> | null>(id: "" extends Id ? never : ErrorDuplicateId<Id> extends Id ? never : Id extends Ids ? ErrorDuplicateId<Id> : Id, options: OptionalParamAsync<AddOneshotParams<Manifest, Ids, Id, C>>): Promise<Daemons<Manifest, Ids | Id>>;
    /**
     * Returns the complete list of daemons, including a new HealthCheck defined here
     * @param id
     * @param options
     * @returns a new Daemons object
     */
    addHealthCheck<Id extends string>(id: "" extends Id ? never : ErrorDuplicateId<Id> extends Id ? never : Id extends Ids ? ErrorDuplicateId<Id> : Id, options: OptionalParamSync<AddHealthCheckParams<Ids, Id>>): Daemons<Manifest, Ids | Id>;
    addHealthCheck<Id extends string>(id: "" extends Id ? never : ErrorDuplicateId<Id> extends Id ? never : Id extends Ids ? ErrorDuplicateId<Id> : Id, options: OptionalParamAsync<AddHealthCheckParams<Ids, Id>>): Promise<Daemons<Manifest, Ids | Id>>;
    /**
     * Runs the entire system until all daemons have returned `ready`.
     * @param id
     * @param options
     * @returns a new Daemons object
     */
    runUntilSuccess(timeout: number | null): Promise<null>;
    /**
     * Gracefully terminate all daemons in reverse dependency order.
     *
     * Daemons with no remaining dependents are shut down first, proceeding
     * until all daemons have been terminated. Falls back to a bulk shutdown
     * if a dependency cycle is detected.
     */
    term(): Promise<void>;
    private _term;
    /**
     * Start all registered daemons and their health checks.
     * @returns This `Daemons` instance, now running
     */
    build(): Promise<this>;
}
