UNPKG

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.

93 lines 5.51 kB
import { type StoreFs } from './store/index.js'; /** * The committed conversations (#908): the human turns and the agent's replies of a run, kept in * the Git repo so a clone carries the chat and not just the fact a run happened (#857). * * Deliberately not the verbose transcript — #857 leaves the tool-call-level log to the model * provider, which is also the standing policy in run-store.ts. What lands here is what a person * would reread: what was asked, and what came back. * * One file per run rather than one shared file, because run worktrees are live concurrently and * each auto-commits its own pending work on teardown; a shared file would be a merge conflict * every time two runs chatted at once. The run id is the join key back to the `- run:` field * LOGS.md records (#898), so the committed session list and the committed chat line up. * * Pure core over the same {@link StoreFs} seam as logs.ts. */ /** The directory, under `.the-framework/`, that holds one markdown file per conversation. */ export declare const CONVERSATIONS_DIR = "conversations"; /** * The `.the-framework/.gitignore` that keeps run state transient while committing the DB. The * conversations rules need both entries: the `*` rule makes git skip the directory without ever * descending into it, so un-ignoring the files alone would never be reached. */ export declare const CONVERSATIONS_GITIGNORE = "!conversations/\n!conversations/**\n"; /** Who said it. The transport is {@link ConversationMessage.via}, not this. */ export type ConversationRole = 'user' | 'agent'; /** One turn in a conversation. */ export interface ConversationMessage { /** ISO timestamp. */ at: string; role: ConversationRole; /** * The surface the turn came through — `dashboard`, `discord`, … Recorded so a conversation * read back shows where it happened, while this module stays free of any transport. */ via: string; /** The message. Multi-line and kept that way; only line-leading markers are escaped. */ text: string; } /** * Whether a transport name is safe to record. Exported because #917 lets a surface name itself * over the control channel, so the name now arrives from outside this module: a `via` carrying * the heading separator, a newline or a `#` would forge structure in a file whose entries are * line-parsed, exactly the way #897 forged a LOGS.md title. Checked at the boundary rather than * trusted, and the same predicate {@link parseConversation} reads back with. */ export declare function isSafeVia(via: unknown): via is string; /** * Escape a message body so it cannot forge structure (#897's threat model, applied to a * transcript). LOGS.md collapses free text to one line, which is right for a line-parsed record * and wrong here: a multi-paragraph reply has to stay readable in a `git diff`. So the text stays * as written and only a line's leading `#` or `\` is escaped, which is enough — an entry is only * ever started by a line beginning `## `. Reversed by {@link unescapeBody}. */ export declare function escapeBody(text: string): string; /** Reverse {@link escapeBody}. */ export declare function unescapeBody(text: string): string; /** The directory holding every conversation under `cwd`. */ export declare function conversationsDir(cwd: string): string; /** * One conversation's path. `undefined` for an unsafe run id: the id reaches this from a run * store and, once #680 lands, indirectly from a chat surface, so it is checked rather than * trusted into a path. */ export declare function conversationPath(cwd: string, runId: string): string | undefined; /** Markdown for one message, starting at `## ` (no file header, no blank lines around it). */ export declare function renderMessage(message: ConversationMessage): string; /** * Parse every message out of the markdown, in file order (append order, so oldest-first — a * transcript reads forwards, unlike the newest-first project log). Forgiving: a malformed or * torn message is skipped, never thrown. */ export declare function parseConversation(md: string): ConversationMessage[]; /** * Make sure `.the-framework/.gitignore` un-ignores the conversations dir, returning whether it * wrote. Done lazily on append rather than only at install time: the seeded ignore file is * written once and only when absent (`install.ts`), so every repo activated before this feature * still carries the old three-line allow-list and would silently drop its own conversations. * * Only ours is upgraded — a file we do not recognize is left alone rather than appended to. */ export declare function ensureConversationsIgnored(cwd: string, fs?: StoreFs): Promise<boolean>; /** * Append one message to `.the-framework/conversations/<runId>.md`, creating the dir, the * one-time file header, and the ignore rule when absent. A raw write (may reject); the caller * decides best-effort. A no-op for an unsafe run id. */ export declare function appendMessage(cwd: string, runId: string, message: ConversationMessage, fs?: StoreFs): Promise<void>; /** Read one conversation, oldest-first. Missing file (or unsafe id) yields `[]`. */ export declare function readConversation(cwd: string, runId: string, fs?: StoreFs): Promise<ConversationMessage[]>; /** The run ids that have a committed conversation, sorted. Missing dir yields `[]`. */ export declare function listConversations(cwd: string, fs?: StoreFs): Promise<string[]>; //# sourceMappingURL=conversations.d.ts.map