import { LoopEngine, type BootstrapResult, type BootstrapScope, type DeployTarget, type DomainPreset, type FrameworkDetection, type FrameworkSignals, type RunnerSession } from '@gemstack/ai-autopilot';
import type { Driver } from './driver/index.js';
import { type EcoOptions } from './system-prompt.js';
import { type BindProjectDeps, type RecordMessage } from './await-gate.js';
import { type TodoLoopResult } from './todo-loop.js';
import { type ChoicePick, type ChoiceRequest, type FrameworkEvent } from './events.js';
import type { RunMessages } from './run-messages.js';
/**
 * The framework's default full-fledged pass budget. Higher than ai-autopilot's
 * base of 3 because a from-scratch build spends its first pass or two just
 * bootstrapping an empty workspace before there is anything to polish (#182).
 */
export declare const DEFAULT_MAX_PASSES = 5;
/** The deploy decision to narrate at the end (plan-only in v1: it does not ship). */
export interface DeployDecision {
    render: 'ssr' | 'ssg' | 'spa';
    target: string;
    reason: string;
}
/**
 * How to actually boot and serve the generated app so the loop can gate on it
 * *running*, not just on an agent's review. When set, the run's checklist step
 * installs, (builds,) starts the app, and fetches it; a failure becomes a
 * blocker the loop hands back to the agent to fix.
 */
export interface ServeConfig {
    /** The command that starts the app (e.g. `npm run dev`). */
    command: string;
    /** Install command run first (e.g. `npm install`). */
    install?: string;
    /** Build command run after install (e.g. `npm run build`). */
    build?: string;
    /** Port the app listens on. Default 3000. */
    port?: number;
    /** How long to wait for it to accept connections. Default 15000ms. */
    waitMs?: number;
    /** Path to fetch once it is up. Default `/`. */
    healthPath?: string;
    /**
     * Keep the app serving after a successful run and hand back an
     * {@link AppPreview} the caller must {@link AppPreview.stop}. Default `false`:
     * the serve gate boots the app only to check it, then tears it down. The CLI
     * sets this so the dashboard can show a live preview link until Ctrl+C.
     */
    keepAlive?: boolean;
}
/** Options for {@link runFramework}. */
export interface RunFrameworkOptions {
    /** What the user wants built (the one scope question's answer). */
    intent: string;
    /** How much app: a quick prototype (no full-fledged loop) or the full thing. Default `"full"`. */
    scope?: BootstrapScope;
    /** The wrapped coding agent. */
    driver: Driver;
    /** Absolute workspace path the agent builds in. */
    cwd: string;
    /** Model id to pass through to the driver. */
    model?: string;
    /** Signals for preset detection (deps/files). Default: none, so the flagship preset wins. */
    signals?: FrameworkSignals;
    /**
     * A user-authored system prompt (from `SYSTEM.md`) injected into every prompt
     * (#301). Load with `loadUserSystemPrompt(cwd)`. Composed after the built-in
     * #326 system prompt, so a repo can add its own instructions on top of the default.
     */
    systemPrompt?: string;
    /**
     * Inject the built-in #326 system prompt into every prompt (#301). Default
     * `true`; pass `false` (e.g. from `the-framework.yml`) to remove it. The name
     * is the historical config key: #326 is the anti-lazy-pill's (#297) successor.
     */
    antiLazyPill?: boolean;
    /** This run has a real browser (#824), so the system channel says so. */
    browser?: boolean;
    /**
     * This is a project-less "topic" run (#1120): advertise the bind gate (#1121) in the system
     * channel and wire {@link bind} so an `await-bind-project` / `await-create-project` gate resolves.
     */
    topic?: boolean;
    /** The bind seams (#1121) a topic run's gate resolves against. Only meaningful with {@link topic}. */
    bind?: BindProjectDeps;
    /** Transparent mode (#625): empty the system channel entirely (raw `claude -p`); overrides antiLazyPill/eco. */
    transparent?: boolean;
    /** Eco fine-grained control (#314): drop the enabled #326 sections to save tokens. */
    eco?: EcoOptions;
    /** In-context directories (#439): added as one `Context:` line to the system prompt. */
    context?: readonly string[];
    /**
     * A user-picked Open Loop domain preset ({loops, prompts}) to run the build
     * under (#251). Its loops + prompts are materialized into a driver-backed {@link LoopEngine}
     * exposed as {@link RunFrameworkResult.loop}. Load it with `loadDomainPreset` /
     * `softwareDevelopmentPreset` (pass `modes` there to activate variants). Omit
     * for the framework-only run.
     */
    preset?: DomainPreset;
    /**
     * The active modes for the run (e.g. `['autopilot']`). Narrated with the
     * {@link preset}, which is expected to be loaded with them already applied.
     * (`autopilot` no longer steers the system prompt: #556 moved the maintenance
     * section out, leaving the choice-gate countdown as its whole effect. See #801.)
     */
    modes?: readonly string[];
    /**
     * The loop event kind the review phase dispatches (#265) — this is what makes a
     * run a bug fix vs a feature: `bug-fix` fires the preset's bug-fix loop, the
     * default `major-change` fires its major-change loop. Overrides the preset's own
     * `defaultEvent`. A kind the preset has no loop for reviews nothing (#1372).
     * No-op without a preset.
     */
    buildEvent?: string;
    /** Max full-fledged passes. Default {@link DEFAULT_MAX_PASSES} (5). */
    maxPasses?: number;
    /** A deploy decision to narrate at the end. Omit to skip the deploy phase. */
    deploy?: DeployDecision;
    /**
     * A real {@link DeployTarget} to *execute* the decided plan (e.g.
     * `cloudflareTarget` / `dokployTarget`). Requires {@link deploy}. Omit to only
     * narrate a plan-only decision.
     */
    deployTarget?: DeployTarget;
    /**
     * Boot-and-serve verification for the full-fledged loop: when set, the
     * checklist gates on the app actually running, not just an agent review.
     */
    serve?: ServeConfig;
    /**
     * Where the {@link serve} verification runs (#229). `"local"` (default) boots the
     * app on the host, adopting the agent's cwd in place. `"docker"` sandboxes it: a
     * throwaway container is booted, the source is copied in fresh before each check
     * (the build still runs on the host in this slice), deps install inside the
     * container, and the app serves on a mapped port — so agent-authored code never
     * installs or runs on the host. Requires a reachable Docker daemon; no-op without
     * {@link serve}.
     */
    sandbox?: 'local' | 'docker';
    /**
     * A pre-provisioned {@link RunnerSession} to run the serve check in, bypassing
     * {@link sandbox} provisioning. Advanced / testing seam — the caller owns its
     * lifecycle is handed to the run (it is disposed with the run). Omit to let
     * {@link sandbox} provision one.
     */
    runner?: RunnerSession;
    /**
     * A link to the live agent session, shown on the dashboard. Either a literal
     * URL, or a template with `{sessionId}` (see {@link SESSION_ID_PLACEHOLDER})
     * that resolves once the wrapped agent reports its real id via `session-update`.
     */
    sessionLink?: string;
    /** Interrupt the run between phases. */
    signal?: AbortSignal;
    /**
     * Pause the run on an interactive choice and await a pick (#304). Called when a
     * build turn stops to ask (#337/#358): the run emits a `choice` event, calls
     * this, and resumes on the returned option. Omit for a headless run: the gate
     * then auto-accepts the recommended option without pausing. The CLI wires this
     * to the dashboard's Accept button + autopilot countdown.
     */
    requestChoice?: (req: ChoiceRequest) => Promise<ChoicePick>;
    /**
     * Stop the run once cumulative agent cost reaches this many USD (budget cap,
     * #322). Checked after each turn that reports usage: the turn that crosses the
     * cap finishes, then the run stops itself (a clean stop, not a failure). Omit
     * for no cap. This gates on what *this run* spent, which is a separate question
     * from where the account's quota stands (readable via #517 / #521, and gated on
     * by #519's consumption limits).
     */
    budgetUsd?: number;
    /**
     * Consult the consumption limits between turns (#529): return the limit that
     * has been reached to pause the run, or `null` to carry on.
     *
     * Must answer from a cached reading — a live quota read spawns the whole agent
     * CLI (~5s). Compose one from a `QuotaPoller` and `consumptionStatus`. Omit to
     * leave the run ungated, which is also what a gate that throws resolves to:
     * an unreadable quota must never stop the user's work (Rom's call on #519).
     */
    consumptionGate?: () => string | null;
    /**
     * Run the backlog loop (#323) after the build settles: consume the agent's own
     * `TODO_AGENTS.md` one entry per turn until empty, gating
     * before each entry when {@link requestChoice} is wired. Default: on for real
     * drivers, off for the fake one (its scripted demo writes no backlog and must
     * stay deterministic). Set explicitly to force either way.
     */
    todoLoop?: boolean;
    /** Per-run cap on backlog entries worked (#323). Default 25. */
    todoMaxItems?: number;
    /**
     * Continue a stopped build run's conversation (#1467): the captured agent session id to
     * `--resume`. When set, the build turn sends {@link RunFrameworkOptions.intent} verbatim as a
     * continuation message instead of rendering the build/extend prompt — the resumed transcript
     * already carries the scope→build framing, which is exactly why #782 refused to bolt
     * `--resume-session` onto a fresh build run. Everything around the turn still runs: the
     * bootstrap narration with its synthesize framing, the review checklist where configured, the
     * backlog loop and live chat — the flow resumes, not just the conversation.
     */
    resumeSessionId?: string;
    /**
     * Live chat (#714): once the build settles, take the user's own messages, each
     * resuming the build session for full context. The session then ends itself when
     * the queue is idle (#1390) unless {@link stayOpenChat} parks it. Wired only for
     * an interactive run — a headless run leaves it unset and ends when the build is
     * done, exactly as before.
     */
    messages?: RunMessages;
    /**
     * Keep the chat parked for the next message instead of ending on an idle queue (#1390).
     * Only for a run whose own terminal dashboard is the single surface — it has no daemon
     * to resume the session through, so ending would leave its composer a dead end.
     */
    stayOpenChat?: boolean;
    /** Record each chat turn to the committed conversation (#908). Best-effort; unset = not recorded. */
    recordMessage?: RecordMessage;
    /** Observe the unified event stream. */
    onEvent?: (event: FrameworkEvent) => void;
}
/**
 * A running instance of the generated app, handed back so the caller can show a
 * live preview link and keep it up until the user is done (then {@link stop}).
 */
export interface AppPreview {
    /** The localhost URL the app is served at. */
    url: string;
    /** The command that started it (e.g. `npm run dev`). */
    command: string;
    /** Stop the app and free its runner. Idempotent. */
    stop(): Promise<void>;
}
/** What a run returns. */
export interface RunFrameworkResult {
    result: BootstrapResult;
    detection: FrameworkDetection;
    events: FrameworkEvent[];
    /**
     * The generated app, left running when a {@link ServeConfig} was supplied and
     * the run finished. The caller owns its lifecycle: show {@link AppPreview.url},
     * then call {@link AppPreview.stop} (e.g. on Ctrl+C). Absent when no serve
     * config was set or the app could not be booted.
     */
    preview?: AppPreview;
    /**
     * The domain preset's review policy, materialized against this run's driver:
     * its loops plus its prompts as driver-backed passes. Present only when a
     * {@link RunFrameworkOptions.preset} was supplied. It also drives the run's
     * review phase (#252): each checklist pass dispatches a `major-change` event
     * through it.
     */
    loop?: LoopEngine;
    /** How the backlog loop (#323) ended, when it ran. */
    todo?: TodoLoopResult;
}
/**
 * Run the whole turnkey flow: detect the framework preset, frame the wrapped
 * agent with its framework skill (page builder + docs), then drive ai-autopilot's `Bootstrap`
 * (scope → build → full-fledged loop → deploy) entirely *through*
 * the driver (option A). Every phase, plus the agent's own progress, streams as
 * a {@link FrameworkEvent}. Reversible: swap in a real deploy target, or a
 * different `Driver`, without touching this wiring.
 */
export declare function runFramework(opts: RunFrameworkOptions): Promise<RunFrameworkResult>;
//# sourceMappingURL=run.d.ts.map