import { type ClaudeCodeDriverOptions } from './driver/index.js';
import { type DriverName } from './driver-cli.js';
import type { ParsedPullRequest } from './turn-gate.js';
import { type FrameworkEvent } from './events.js';
import { type AgentKind } from './agent.js';
import { type AgentLocation } from './agent-location.js';
import { type HandoffLevel } from './handoff-level.js';
import { type AgentSpec } from './agent-spec.js';
import { type FrameworkFileConfig } from './config.js';
import { type ResolvedAgentConfig } from './config-layers.js';
import { type VersionFetcher } from './update-check.js';
import { AgentStore, type StoreFs } from './store/index.js';
import { type OnBeforeMergeableContext } from './on-before-mergeable-prompt.js';
/**
 * The default link shown for a live agent: the generic Claude Code entry point,
 * surfaced as "Open Claude Code" (not a per-agent live session). We drive Claude
 * Code headless, which is not Remote-Controlled, so there is no per-session deep
 * link to construct (#214); a cloud run reports its real link through its own
 * driver events instead.
 */
export declare const CLAUDE_CODE_SESSION_LIST = "https://claude.ai/code";
/**
 * The session link to show for an agent: the generic Claude Code entry point for
 * a live agent, nothing for a fake one (which has no real session). Pure, so the
 * default is unit-testable without a live agent.
 *
 * The default is Claude Code's *own* entry point, so it is only honest on a
 * Claude run: pointing a Codex session at claude.ai/code offers the user a link
 * to somewhere their run isn't. Codex keeps its sessions locally with nothing
 * equivalent to open, so another agent gets no default link at all (#542).
 */
export declare function chooseSessionLink(opts: Pick<AgentOptions, 'driver'>, fake: boolean): string | undefined;
/** Where the CLI writes. Injectable so tests capture output. */
export interface CliIO {
    out: (line: string) => void;
    err: (line: string) => void;
}
export declare function frameworkVersion(): string;
/**
 * One agent's resolved configuration, as it reads it itself (D4).
 *
 * These used to be command-line flags, which made every one of them a human surface as well as
 * the dashboard's process API. They arrive as a {@link AgentSpec} now — one JSON blob on a temp
 * file — so what is left here is a plain options object with no argv semantics: no tri-state
 * `--no-*` spellings, no mutual validation, no help text.
 */
export interface AgentOptions {
    /** The `FakeDriver` (`FRAMEWORK_FAKE=1`): an offline stand-in for the agent, for tests and e2e. */
    fake: boolean;
    /** What the session was asked to do. */
    intent: string;
    /** Which coding-agent CLI does the work (#542). Default `claude`. */
    driver: DriverName;
    /** `--run-on <local|actions|web>` (#1050/#610): where the agent executes. `actions` drives it on a
     * GitHub Actions runner via ActionsDriver (#934); `web` hands it to a Claude Code cloud session
     * via CloudDriver (#610); absent / `local` runs on this device as before. */
    target?: AgentLocation | undefined;
    cwd?: string | undefined;
    /**
     * `--run-id <id>` (#736): the id the daemon allocated for this agent before spawning it. Its
     * presence says the framework owns this agent's checkout — `--cwd` is a worktree the daemon
     * created on a `tf-agent-<id>` branch, which the agent renames once the agent names
     * the session. Absent for a plain `framework "..."`, which runs in the user's own checkout.
     */
    agentId?: string | undefined;
    /**
     * `--continue-run` (#762): this agent continues the agent `--run-id` names rather than starting a new
     * one. The store reopens that agent's log instead of truncating it, so messaging a stopped agent
     * stays one row in the history.
     */
    continueAgent?: boolean | undefined;
    model?: string | undefined;
    /** Continue a finished agent's agent session (#720) — the prompt resumes that conversation (full prior context). Set by the dashboard when you message an agent that has ended. */
    resumeSession?: string | undefined;
    /** The `tickets/<file>.md` this agent is implementing (#1117). Set by the daemon when it starts a drain agent, from the ticket its queue entry links to; recorded on the agent's meta. */
    ticket?: string | undefined;
    /** The {@link ticket} is being planned, not implemented (#1327), so the PR title must not inherit its issue as `(fix #42)` (#1334) — the plan's merge would close the issue with the work still undone. */
    planAgent?: boolean;
    /** No human is watching (#846), so choice gates take the recommended option. */
    unattended?: boolean;
    scope: 'prototype' | 'full';
    /**
     * The mode toggles are tri-state (#841): `undefined` is "this agent said nothing", so the repo's
     * the-framework.yml decides, while an explicit `--no-*` turns the mode off over the file.
     */
    /** Remove the built-in #326 system prompt entirely, keeping the session controls (#314). */
    vanilla?: boolean | undefined;
    /** Transparent mode (#625): run the wrapped agent fully raw — no framework system prompt, emit
     * protocols, consumption guard, dashboard, or TODO loop, so an agent is identical to `claude -p`. */
    transparent?: boolean | undefined;
    /** In-context directories, added as one `Context:` line (#439). */
    context: string[];
    /** Fire the built-in on-before-mergeable (#326) prompt when the agent signals setReadyForMerge(), queueing the quality follow-ups as TODO entries. */
    onBeforeMergeable: boolean;
    /** Give the agent a real browser via chrome-devtools-mcp (navigate, console, network, DOM, screenshot) during the agent (#452). */
    browser: boolean;
    /**
     * How far this session publishes itself when it finishes (#1102/#1216/B5). `undefined` is "this
     * session said nothing", so the repo's the-framework.yml decides, and nobody setting it resolves
     * to `pr` — which is what makes the handoff zero-config.
     */
    handoff?: HandoffLevel | undefined;
    todoLoop: boolean;
    /** Whether the session records itself to `.the-framework/`. Always true outside tests. */
    persist: boolean;
    /** {@link AgentSpec.kind} `research`: run the Research preset as a direct prompt (#331). */
    research: boolean;
    /** {@link AgentSpec.kind} `prompt`: run one prompt verbatim through the direct path (#353). */
    directPrompt: boolean;
}
/** What the CLI itself accepts: four options, no verbs (D4). */
export interface CliArgs {
    help: boolean;
    version: boolean;
    /** `--port <n>`: the port the dashboard binds. Default {@link DEFAULT_DAEMON_PORT}; `0` is ephemeral. */
    port?: number;
    /**
     * `--host <addr>` (#1051): the dashboard's bind address. Default loopback; a non-loopback
     * address exposes it to the network and gates every route behind the generated shared token.
     */
    host?: string;
    /**
     * `--agent <path>`: run the session described by the JSON spec at `path` (D4). The dashboard's
     * process API, not a human option — it is how one session is spawned, and the file is consumed.
     */
    session?: string;
    error?: string;
}
/**
 * Parse argv (without the node/script prefix). Pure and testable.
 *
 * Four options and nothing else. Everything a session needs used to be a flag here — sixty-seven
 * of them, twenty-seven with no human user at all, because the dashboard serialized
 * `StartAgentOptions` onto a command line. Those travel as a {@link AgentSpec} now. `--host` and
 * `--port` survive because they are the two things a browser cannot be asked and a dashboard
 * cannot serve about itself; `--help` and `--version` because a command with options owes the
 * user both.
 */
export declare function parseArgs(argv: string[]): CliArgs;
/**
 * Read a session's options off the spec the dashboard wrote (D4).
 *
 * The handoff pair and the mode toggles are left unset when the spec says nothing about them, on
 * purpose: that is what lets the repo's `the-framework.yml` decide, with nobody setting them
 * resolving to on (#1102/#841). JSON distinguishes "absent" from `false` without needing a
 * `--no-*` spelling for each, which is the whole reason this stopped being an argv.
 */
export declare function agentOptions(spec: AgentSpec, env?: NodeJS.ProcessEnv): AgentOptions;
/**
 * Resolve the Claude Code driver options for a live session. A session is a headless autonomous
 * builder: every turn is `claude -p`, which cannot answer an interactive approval. The driver's
 * library default (`acceptEdits`) silently denies installs/builds/tests, so the production-grade
 * checklist can never verify the app actually builds/runs (#225). `bypassPermissions`, so the full
 * loop runs unattended.
 *
 * There used to be a `--permission-mode` and a `--dangerously-skip-permissions` to override it.
 * Neither had a dashboard control, so with the flags gone (D4) nothing sets them and the mode is
 * simply what it always resolved to.
 */
export declare function claudeDriverOptions(): ClaudeCodeDriverOptions;
/**
 * The settings the picked driver cannot honor (#542), as lines to print at startup.
 *
 * A setting that silently does nothing is worse than one that errors. So the session says which
 * settings are not in force, rather than letting them imply they are.
 */
export declare function unguardedNotices(opts: Pick<AgentOptions, 'driver' | 'browser'>): string[];
/** Which flow an agent starts under (#1467), recorded on its meta: the direct paths are prompts, a
 * build agent is a build. Transparent (#625) routes a build-kind agent through the raw prompt path too,
 * so it records as a prompt. */
export declare function agentLogKind(opts: Pick<AgentOptions, 'directPrompt' | 'research'>, transparent?: boolean): AgentKind;
type AgentConfigFlags = Pick<AgentOptions, 'vanilla' | 'transparent' | 'handoff'>;
/**
 * Resolve an agent's config over its layers, nearest wins (#841): the agent's flags, then the repo's
 * `the-framework.yml`. #800 slots the project-user and global tiers in between and at the end.
 */
export declare function mergeAgentConfig(opts: AgentConfigFlags, file: FrameworkFileConfig): ResolvedAgentConfig;
/**
 * The `framework` command. Wires the parsed options into {@link runFramework}
 * over a live dashboard + terminal narration, and resolves with an exit code.
 * Returns 0 on success, 1 on an agent error, 2 on a usage error.
 */
/**
 * Whether this agent can be steered over `.the-framework/control.jsonl` (#344): Stop, a choice pick,
 * a live message. True when its own dashboard is up (#427), or when whoever spawned it handed it a
 * agent id — the dashboard spawns each session with one in its spec, and steers it
 * from its own process.
 *
 * This used to have a third clause, "a daemon is alive somewhere on this machine", read from a
 * global state file. That file is gone with the background daemon (D4b), and it was never a fact
 * about *this* run in the first place: it went missing while the daemon was very much alive
 * (#922), and every Stop press then landed in control.jsonl and was read by nobody, in silence
 * (#905). An agent id holds when a file about another process does not.
 */
export declare function isSteerable(opts: {
    persist: boolean;
    agentId?: string | undefined;
}): boolean;
/**
 * Whether this session should stay open for the user's own messages once it settles (#714).
 *
 * The other half of #905. Being steerable only means someone *could* reach it; staying open means
 * a human is expected to keep talking to it. A headless agent is neither, but it used to inherit the
 * chat queue purely because a daemon happened to be alive elsewhere on the machine, and then
 * parked forever on a message nothing could send. #714 said as much: "headless / CI runs end when
 * done, exactly as today."
 *
 * So: the dashboard started it (an agent id) and therefore has a UI to carry on the conversation in.
 * Stop and gate picks keep working either way.
 */
export declare function isInteractive(opts: {
    agentId?: string | undefined;
}): boolean;
/** What the agent journal exposes to the epilogue. See {@link createAgentJournal}. */
export interface AgentJournal {
    onEvent: (event: FrameworkEvent) => void;
    /** The session name the agent chose via setSessionName() (#326), once it has. */
    sessionName: () => string | undefined;
    /** The agent signalled setReadyForMerge() this agent (#326). */
    sawReadyForMerge: () => boolean;
    /** The pull request the agent asked for via an `open-pr` block (#1567/#1618), if any. */
    pullRequest: () => ParsedPullRequest | undefined;
    /** The agent stopped cleanly (user interrupt / budget cap #322) rather than failed. */
    stoppedCleanly: () => boolean;
    /** Hold the browser preview's port until the session opens (#829/#813). */
    announceBrowserPort: (port: number) => void;
    /** The page the browser preview is on (#1455 item 6b): emitted as a `browser` event once a
     *  session is open, held until then, and re-said after every later `session` so the row
     *  survives the dashboard's last-session slice. */
    announceBrowserUrl: (url: string) => void;
}
/**
 * The agent's event sink and the state its epilogue reads. One event arrives and this prints it,
 * persists it, tracks the settle flags (#322/#326), renames the framework-owned branch once the
 * agent names its session (#736), and re-emits a held browser-stream port right after `session` so
 * it lands in the slice the dashboard renders (#829). These jobs sat inline in runCli across six
 * mutable locals; the journal is their one owner, and runCli reads the getters. Exported for the
 * rename-records-the-branch test (#1277).
 */
export declare function createAgentJournal(deps: {
    io: CliIO;
    cwd: string;
    store: AgentStore | undefined;
    agentId: string | undefined;
}): AgentJournal;
export declare function runCli(argv: string[], io?: CliIO): Promise<number>;
/**
 * The startup footer every dashboard path prints (#312): where prompts come from, the version,
 * and then — once npm answers — whether that version is the latest.
 *
 * The update line is deliberately not awaited before the static lines. #312 asks for the static
 * info first, and the foreground path (bare `framework`) blocks on the server forever, so a line
 * printed after the await would never appear there at all. `checkForUpdate` is already forgiving:
 * offline or slow (2.5s cap) resolves to 'unknown', which prints nothing.
 */
export declare function printStartupFooter(io: CliIO, opts?: {
    fetchLatest?: VersionFetcher;
}): Promise<void>;
/**
 * The session spec a spawned on-before-mergeable child runs with (D4). Pure so a test can assert
 * it: note it carries **no** `onBeforeMergeable`, which is the recursion guard — a quality pass
 * must not trigger its own suite.
 */
export declare function promptAgentSpec(prompt: string, cwd: string, vanilla?: boolean): AgentSpec;
/** How the on-before-mergeable prompt is spawned; injectable so tests observe it without spawning. */
export type PromptRunner = (prompt: string, cwd: string, binPath: string) => Promise<boolean>;
/**
 * Fire the built-in on-before-mergeable (#326) prompt after an agent signalled setReadyForMerge(): one
 * `framework prompt` child on the same workspace that appends the quality follow-ups to the
 * session's TODO file, for the backlog loop (#323/#538) to pick up.
 *
 * It used to run maintainability, readability and security-audit inline instead, as three
 * child runs back to back (#556). Queueing is both what the doc says and the cheaper thing:
 * one short turn that writes a few TODO lines, rather than three full preset passes serialized
 * on the same git index. Best-effort, like the suite was: a failure is logged, never thrown.
 *
 * Returns how it went so the caller can emit it as an event (#835); the `io` lines stay for
 * a terminal agent, which is the one surface that can still read them.
 */
export declare function runOnBeforeMergeable(cwd: string, binPath: string, io: CliIO, tf: OnBeforeMergeableContext, agent?: PromptRunner, fs?: StoreFs): Promise<'queued' | 'incomplete'>;
export {};
//# sourceMappingURL=cli.d.ts.map