framework
Version:
The (AI) Framework: turnkey, zero-config AI orchestration that wraps a coding-agent CLI (Claude Code) as a black box and takes you from an idea to a running app. Vite for AI.
121 lines • 6.4 kB
TypeScript
import type { Driver } from './driver/index.js';
import { type TodoLoopResult } from './todo-loop.js';
import { type ChoicePick, type ChoiceRequest, type FrameworkEvent } from './events.js';
import type { AgentMessages } from './agent-messages.js';
import { type AgentLocation } from './agent-location.js';
/**
* One session: frame the wrapped agent, send it a prompt, honor the gates it answers with, and
* stream every step as a {@link FrameworkEvent}. Reversible — swap in a different `Driver`
* without touching this wiring.
*
* There used to be two of these. `runFramework` drove a build through ai-autopilot's `Bootstrap`
* spine, and `runPrompt` ran one prompt verbatim; `composeAgentSystem` exists specifically because
* the two each inlined the system composition and drifted apart (#500/#501). Once the review loop
* (A5) and the `Bootstrap` spine (A3) went, the build path *was* "one prompt, honoring gates" —
* which is what the prompt path already was. What is left of the difference is two options rather
* than two implementations: which prompt opens the session, and whether the agent's own backlog is
* worked afterwards.
*/
/** What a session is: an intent to build from, or a prompt to run verbatim. */
export type AgentKind = 'build' | 'prompt';
/** Options for {@link runAgent}. */
export interface RunAgentOptions {
/**
* What the session is asked to do. For `build`, the intent the opening prompt is composed
* around; for `prompt`, the text sent as-is (modulo the system template's user slot).
*/
prompt: string;
/** Which opening prompt this session gets, and whether the backlog loop follows. Default `build`. */
kind?: AgentKind;
/**
* Where this session's turns execute (#1050/#610). Default `local`. Only `web` hands the work
* somewhere this machine cannot follow, which makes the opening prompt the whole session —
* see {@link isHandsOff}.
*/
location?: AgentLocation;
/** The wrapped coding agent. */
driver: Driver;
/** Absolute workspace path the agent works in. */
cwd: string;
/** Model id to pass through to the driver. */
model?: string;
/**
* 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;
/** Remove the built-in #326 system prompt (#301/C3). Default `false` — it is included. */
vanilla?: boolean;
/** This session has a real browser (#824), so the system channel says so. */
browser?: boolean;
/** Transparent mode (#625): empty the system channel entirely (raw `claude -p`); overrides vanilla. */
transparent?: boolean;
/** In-context directories (#439): added as one `Context:` line to the system prompt. */
context?: readonly string[];
/**
* 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 session between turns. */
signal?: AbortSignal;
/**
* Pause on an interactive choice and await a pick (#304). Called when a turn stops to ask
* (#337/#358): the session emits a `choice` event, calls this, and resumes on the returned
* option. Omit for a headless session: the gate then auto-accepts the recommended option
* without pausing. The CLI wires this to the dashboard's Accept button.
*/
requestChoice?: (req: ChoiceRequest) => Promise<ChoicePick>;
/**
* Work the agent's own `TODO_AGENTS.md` backlog after the opening exchange settles (#323), one
* gated entry per turn until it is empty. Default: on for a `build` session with a real driver,
* off otherwise (a `prompt` session is one prompt by definition, and the fake driver's scripted
* demo writes no backlog and must stay deterministic). Set explicitly to force either way.
*/
todoLoop?: boolean;
/**
* Continue a stopped session's conversation (#720/#1467): the captured agent session id to
* `--resume`. When set, {@link prompt} is sent verbatim as a continuation message rather than
* composed — the resumed transcript already carries the framing, which is exactly why #782
* refused to bolt a resumed session onto a fresh build. Everything around the turn still runs:
* the gates, the backlog loop, live chat — the flow resumes, not just the conversation.
*/
resumeSessionId?: string;
/**
* Live chat (#714): once the opening exchange settles, take the user's own messages, each
* continuing the same session. The session then ends itself when the queue is idle (#1390)
* unless {@link stayOpenChat} parks it. Unset for a headless session, which ends when the agent
* stops asking.
*/
messages?: AgentMessages;
/**
* Keep the chat parked for the next message instead of ending on an idle queue (#1390).
* Only for a session whose own surface is the single one — it has no dashboard to resume
* through, so ending would leave its composer a dead end.
*/
stayOpenChat?: boolean;
/** Observe the unified event stream. */
onEvent?: (event: FrameworkEvent) => void;
}
/** What a session returns. */
export interface RunAgentResult {
/** The final turn's text. */
text: string;
/** Every event emitted, in order. */
events: FrameworkEvent[];
/** How the backlog loop (#323) ended, when it ran. */
todo?: TodoLoopResult;
}
/**
* Run one session to completion: send the opening prompt, honor each await gate (#337/#339) by
* re-prompting with the user's answer, work the backlog if this is a build, and stay open for the
* user's own messages when a chat source is wired.
*
* Emits the same {@link FrameworkEvent} stream throughout — `session`, `system-prompt`, `driver`,
* `choice`, `usage`, `intent`, `end` — so the dashboard, the store, and the control channel (#344)
* read one shape regardless of what opened the session.
*/
export declare function runAgent(opts: RunAgentOptions): Promise<RunAgentResult>;
//# sourceMappingURL=agent.d.ts.map