/**
 * Webhook handler config layer.
 *
 * Handlers are one-off triggers stored in `~/.agents/webhooks/*.yml` (plus
 * project/system layers). They complement routine triggers: a matching webhook
 * can run an agent, workflow, shell command, or delegate to a routine.
 */
import type { JobConfig, RunMeta, WebhookContext } from '../scheduling/routines.js';
import type { AgentId } from '../types.js';
import type { IncomingWebhook, SlackPayload, WebhookSource } from './webhook.js';
export interface WebhookHandler {
    name: string;
    enabled?: boolean;
    devices?: string[];
    source: WebhookSource;
    event?: string;
    action?: string;
    stateTo?: string;
    stateFrom?: string;
    teamKey?: string;
    label?: string;
    repo?: string;
    branch?: string;
    /** Slack (source: slack) only — match one slash command, e.g. `/agents`. */
    command?: string;
    /** Slack (source: slack) only — restrict to one channel id (`C0…`). Lets a
     *  channel imply a project via a per-channel handler. */
    channel?: string;
    /**
     * Where to run the action. A device name (`yosemite-s0`) runs there over SSH;
     * `fleet` picks any eligible online worker; `fleet/<platform>` (or
     * `<platform>/fleet`, or a bare `linux`/`macos`/`windows`) restricts that pick
     * to one platform. Omitted runs locally.
     */
    host?: string;
    /**
     * Named project (`agents projects`) whose base directory the dispatched
     * agent/workflow run lands in — the execution anchor, mirroring a routine's
     * `project`. Without it an agent handler runs at the target's `$HOME` with no
     * repo checkout to edit. Applies to `run.agent`/`run.workflow` and the
     * `routine:` delegate; ignored by `run.command` (put a `cd` in the command).
     */
    project?: string;
    /**
     * Portable execution directory for the dispatched run. A relative value
     * resolves under `project` when set, otherwise the target's `$HOME`. Mirrors
     * a routine's `cwd`.
     */
    cwd?: string;
    /**
     * Permission mode for a dispatched agent/workflow run. Defaults to `auto`
     * (write with the classifier). Set `skip`/`full` for fully unattended edits,
     * or `plan` for a read-only run.
     */
    mode?: JobConfig['mode'];
    run?: {
        agent?: AgentId;
        workflow?: string;
        command?: string;
        prompt?: string;
        /** Environment variables injected into the spawned process. */
        env?: Record<string, string>;
    };
    routine?: string;
}
export interface FiredHandler {
    handlerName: string;
    runId?: string;
    exitCode?: number;
    output?: string;
}
export interface HandlerHostResolution {
    /** Resolved execution host, or undefined to run locally. */
    host?: string;
    /** Strategy that should be set on the JobConfig. */
    hostStrategy?: 'host' | 'fleet';
}
/**
 * Resolve a handler `host` expression to a concrete host or local execution.
 *
 * - Specific device name (e.g. `yosemite-s0`) → run there over SSH, or locally
 *   if it names this machine.
 * - `fleet` → pick any online worker device.
 * - `fleet/<platform>` or `<platform>/fleet` (e.g. `fleet/linux`, `linux/fleet`)
 *   → pick any online worker on that platform. `linux` alone is accepted as a
 *   shorthand for `fleet/linux`.
 *
 * Throws when a fleet expression matches no eligible device, rather than
 * silently falling back to this machine — `fleet/linux` must never land on a
 * macOS box.
 */
export declare function resolveHandlerHost(host: string | undefined): HandlerHostResolution;
/**
 * List all webhook handlers, scanning project > user > system webhook dirs.
 * Higher layers shadow lower ones of the same name (first-seen wins).
 */
export declare function listHandlers(cwd?: string): WebhookHandler[];
/** Pure matcher: does this handler match the incoming webhook? */
export declare function handlerMatchesWebhook(handler: WebhookHandler, webhook: IncomingWebhook): boolean;
/**
 * The `{{slack.*}}` substitution namespace: a Slack message split into an
 * agent-actionable project + prompt, plus the coordinates a reply threads into.
 */
export interface SlackMessageContext {
    /** The message with a leading bot mention stripped. */
    text: string;
    /** The `PROJECT:` token at the head of the message, or '' when absent. */
    project: string;
    /** The request — the text after `PROJECT:`, or the whole message. */
    prompt: string;
    /** Channel id to reply into (`C0…`). */
    channel: string;
    /** Thread ts to reply into (empty for a slash command → reply to the channel). */
    thread_ts: string;
    /** Invoking user id (`U0…`). */
    user: string;
    /** Slash command name (`/agents`), or '' for an event delivery. */
    command: string;
    /**
     * Slash-command reply URL (`https://hooks.slack.com/commands/…`), or '' for an
     * event delivery. Slack accepts a POST here for 30 minutes with no token and no
     * channel membership, so it is the only reply path that works before the app has
     * been invited to a channel.
     */
    response_url: string;
}
/**
 * Split a Slack message into a `{{slack.*}}` context. Strips a leading bot
 * mention (`<@U0BOT> …`), then reads an optional `PROJECT:` prefix — a single
 * bare token followed by a colon and a space — as the project, with the
 * remainder the prompt. `AGI: rebase my PR` → project `AGI`, prompt
 * `rebase my PR`; a message with no such prefix leaves `project` empty and the
 * whole text as the prompt. The token pattern forbids slashes, so a project
 * value can never carry a path into a `cwd`/`project` substitution.
 */
export declare function parseSlackMessage(payload: SlackPayload): SlackMessageContext;
/**
 * Build the variable-substitution context for a webhook. Linear events expose
 * `issue` and `updatedFrom`; GitHub events expose `repository`, `pull_request`,
 * and `issue`; Slack events expose the `{{slack.*}}` namespace above.
 */
export declare function buildWebhookContext(webhook: IncomingWebhook): WebhookContext;
export interface ExecuteHandlerOptions {
    dispatchAgent?: (config: JobConfig) => Promise<RunMeta>;
    dispatchWorkflow?: (config: JobConfig) => Promise<RunMeta>;
    execCommand?: (command: string) => Promise<{
        exitCode: number;
        output: string;
    }>;
    dispatchRoutine?: (config: JobConfig) => Promise<RunMeta>;
}
/**
 * Execute a handler's action. Runs the configured agent/workflow/command or
 * delegates to a routine, substituting `{{...}}` placeholders from the webhook
 * context.
 */
export declare function executeHandler(handler: WebhookHandler, webhook: IncomingWebhook, opts?: ExecuteHandlerOptions): Promise<FiredHandler>;
