import type { LabListResult } from "./labs.js"; import type { LabSummary, ReadLabSummaryOptions } from "./lab-summary.js"; import type { RunDetail } from "./run-detail.js"; import type { ReclaimResult } from "./reclaim.js"; import type { TuiActionResult } from "./tui-actions.js"; import type { TuiProjectState } from "./tui-project.js"; import type { ReadRunIndexOptions, RunIndexResult } from "./run-index.js"; import type { LaunchRunOptions, LaunchRunResult } from "./tui-launch.js"; import type { CommsSetupResult, CommsSetupStatus } from "./comms-connections.js"; import type { CommsCheckResult, CommsConfigureResult } from "./comms-setup.js"; import type { CommsRecoveryEntry } from "./comms-receiving.js"; /** The humanish version string shown in the frame, so a screenshot in a bug report is datable. */ export interface TuiVersionInfo { cli: string; } /** * What the surface may do to the project. Deliberately a small, explicit list rather than a handle * to the whole library: the set of verbs a stakeholder surface can perform should be readable in * one place, and anything absent here is something the TUI simply cannot do. */ export interface TuiCapabilities { /** Optional for older embedders. Credentials are never returned to the view. */ comms?: { read(): Promise; save(): Promise; check?(): Promise; labs?(): Promise<{ title: string; path: string; }[]>; configure?(lab: string, apply: boolean, planToken?: string): Promise; recovery?(): Promise; recover?(runId: string, connectionName: string): Promise<{ ok: boolean; message: string; }>; }; /** Read every run in the project, cheapest source first. */ readRunIndex(cwd: string, options?: ReadRunIndexOptions): Promise; /** * The labs DECLARED in this project. Listed separately from run history because neither side is * the whole truth: a fresh project has manifests and no runs, and a long-lived one has runs from * manifests since renamed or deleted. */ listLabs(cwd: string): Promise; /** * Start a run and return once it is running. The run is DETACHED: it outlives this surface, so * quitting the TUI — or losing the connection it runs over — does not kill a study that costs * real money. The surface then follows it through `status.json` like any other reader. */ startRun(options: Omit): Promise; /** The tail of a launch log: the only account of a run that died before writing evidence. */ readLaunchLog(logPath: string): Promise; /** * Who is in ONE run and what they are thinking. Opens that run's bundle, which the index * deliberately does not — affordable because it is asked only for the run being watched. * `null` when the run has not written a bundle yet. */ readRunDetail(cwd: string, runId: string): Promise; /** * What a lab IS — subject, participants, model, spend caps, and whether the keys a live run needs * resolve right now. Read for the lab being looked at, because it is what someone reads before * deciding to spend money. */ readLabSummary(cwd: string, lab: string, options?: ReadLabSummaryOptions): Promise; /** Whether this directory is a humanish project — an empty project and a wrong directory are * different problems and must not share a screen. */ readProjectState(cwd: string): TuiProjectState; /** Open the selected run in the session-owned local evidence server; closes when the TUI exits. */ openObserver(cwd: string, observerPath: string): Promise; /** Stop the sandboxes an interrupted run left behind, keeping its evidence. */ reclaimRun(cwd: string, runId: string): Promise; /** End a run that is still going. "analysis" is marker-only regardless of the current status; * it MUST NOT probe or signal a process. The default "run" intent stops the participant process. */ stopRun(cwd: string, runId: string, intent?: "run" | "analysis"): Promise; /** * Set this directory up as a humanish project. The surface's only WRITING action outside of * starting runs — offered because "cd somewhere else and run init" is a dead end shown to * exactly the person who has just arrived (#505). */ initProject(cwd: string): Promise; } export interface TuiOptions { /** Return to setup after the host-owned hidden prompt has finished. */ initialScreen?: "connections"; connectionNotice?: string; /** The project the surface is reading. Already resolved by the CLI. */ cwd: string; version: TuiVersionInfo; capabilities: TuiCapabilities; /** * Terminal streams, injected so a test can drive the surface without a real TTY. The CLI passes * the real ones; both are known to be TTYs by the time this is called, because the command * refuses to start otherwise. */ stdin: NodeJS.ReadStream; stdout: NodeJS.WriteStream; /** Test seam: render one frame and resolve, instead of waiting for the operator to quit. */ exitAfterFirstFrame?: boolean; } /** * Start the surface. Resolves with the process exit code when the operator quits — the TUI owns the * screen until then, so the CLI must not write to stdout while this is pending. */ export type TuiHandoff = { action: "agentmail-key"; }; export type StartTui = (options: TuiOptions) => Promise; /** The shape `dist/tui-app.js` exports. Asserted at the load boundary in program.ts. */ export interface TuiModule { startTui: StartTui; } /** Node version the Ink runtime requires (ink@7 declares `engines.node >= 22`). */ export declare const TUI_MIN_NODE_MAJOR = 22; /** * Whether this runtime can host the surface. Kept here, beside the reason, so the CLI's refusal and * `doctor`'s readiness row can never disagree about the answer. */ export declare function nodeSupportsTui(versionString?: string): boolean; /** * Where the bundle sits relative to the compiled CLI. Shared so the command that loads it and the * readiness row that reports it can never look in different places. */ export declare function tuiBundleUrl(baseUrl: string): URL; /** * What `doctor` says about the stakeholder surface — a pure function of the machine's state and, * crucially, of WHO IS READING. * * A real first-contact study (labs/first-contact.yaml) is why the reader matters. An autonomous * agent evaluating humanish read "`humanish tui` is available in an interactive terminal", * correctly concluded it was not in one, and dropped it — then wrote a report FOR A HUMAN that * never mentioned the human surface at all. Discovery worked and handoff did not. A capability * described to a reader who cannot use it has to be phrased as something to PASS ON, or it reads * as "not for you" and dies in the transcript. */ export declare function terminalSurfaceMessage(state: { supported: boolean; bundlePresent: boolean; interactive: boolean; nodeVersion: string; }): string;