/**
 * Cloudflare tunnel setup — deterministic orchestrator.
 *
 * the tunnel setup flow (login → create → enable → verify) has a
 * deterministic shape. Every branch is driven by a structured signal —
 * either `tunnel-status`'s `unhealthyReason` enum, or the operator's
 * literal input (domain name, subdomain names, "done").
 * the flow was driven by the LLM reading SKILL.md prose and picking the
 * next `tunnel-*` tool; that allowed a dozen+ recurrences where the LLM
 * forked, dispatched Playwright to the Cloudflare dashboard, or fabricated
 * a `cp cert.pem` workaround. None of those deviations are reachable here
 * because the LLM no longer chooses — this module does.
 *
 * Contract:
 *   - `runOrchestrator(input)` is the single entry point. One call advances
 *     one deterministic step. The LLM's only job is to pass the operator's
 *     literal input through (domain, "done", etc.) and relay the structured
 *     result verbatim.
 *   - Every transition emits a `[cloudflare:setup-run:phase-transition]` log
 *     line. Every internal sub-tool call emits
 *     `[cloudflare:setup-run:subtool-call]`. Every terminal state emits
 *     `[cloudflare:setup-run:terminal]`. These give a single grep path
 *     (`[cloudflare:setup-run:`) to the full transition chain post-hoc.
 *   - State is persisted at `~/{configDir}/cloudflared/setup.state.json`
 *     alongside `tunnel.state` and `login.state`. On corruption or absence
 *     the orchestrator reconciles from live `tunnel-status` + operator
 *     input (no "state file not found" crash).
 *   - The tool-surface gate in `platform/ui/app/lib/tool-surface-filter.ts`
 *     reads this state file every turn and removes the raw `tunnel-*`,
 *     Playwright, Bash, Write, Edit tools from the LLM's menu whenever
 *     `phase !== 'idle' && phase !== 'healthy'`. No LLM regression can
 *     re-enter the loop because the tools that enabled it are literally
 *     absent from the menu.
 */
export type OrchestratorPhase = "idle" | "awaiting-domain" | "awaiting-signin" | "awaiting-account-switch" | "awaiting-hostnames" | "enabling" | "healthy" | "unhealthy";
export interface OrchestratorState {
    phase: OrchestratorPhase;
    domain: string | null;
    adminSubdomain: string | null;
    publicSubdomain: string | null;
    /** The tunnelId once `tunnel-create` has run — used to short-circuit re-entry. */
    tunnelId: string | null;
    /** ISO 8601 — when the current phase was entered. Diagnostics only. */
    phaseEnteredAt: string;
    /** Set when phase is `unhealthy`; mirrors cloudflared.TunnelUnhealthyReason. */
    unhealthyReason: string | null;
}
/**
 * The orchestrator state file path. Consumers OUTSIDE this module (e.g. the
 * tool-surface filter in `platform/ui/app/lib/tool-surface-filter.ts`) also
 * need this path to read the phase. Exported so the two sides cannot drift.
 *
 * Brand-aware via loadBrand(); falls back to `.maxy` when PLATFORM_ROOT is
 * unset. The fallback matters only for the tool-surface filter running
 * outside the cloudflare MCP server's process — the MCP server always has
 * PLATFORM_ROOT set by the claude-agent spawn.
 */
export declare function setupStatePath(configDirOverride?: string): string;
export declare function readOrchestratorState(): OrchestratorState;
/**
 * Whether the tool-surface filter should treat this device as "setup in
 * progress". Matches the gate condition named in the task file: the filter
 * lifts whenever phase is idle or terminal (healthy / unhealthy).
 */
export declare function isSetupActive(state: OrchestratorState): boolean;
export interface OrchestratorInput {
    /** Bare domain, e.g. "maxy.bot". Required on the first call; ignored afterwards. */
    domain?: string;
    /** Admin subdomain label (no dots), e.g. "admin" → admin.{domain}. Required at `awaiting-hostnames`. */
    adminSubdomain?: string;
    /** Optional public subdomain label. */
    publicSubdomain?: string;
    /** Operator signalled "done" — only meaningful at `awaiting-signin` / `awaiting-account-switch`. */
    confirmed?: boolean;
}
export interface OrchestratorResult {
    /**
     * The agent-facing string. Includes a `maxy-device-url` fenced block when
     * a device-bound action is required; includes hostnames on terminal
     * success. The admin agent's only job is to relay this verbatim.
     */
    text: string;
    /** Phase at the end of this call. Diagnostic only — the agent never reads it. */
    phase: OrchestratorPhase;
    /** True at terminal success. */
    healthy: boolean;
}
export declare function runOrchestrator(input: OrchestratorInput): Promise<OrchestratorResult>;
export declare function resetOrchestrator(): void;
//# sourceMappingURL=setup-orchestrator.d.ts.map