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.

61 lines 3.35 kB
import { type DiscordMessage, type GatewayDeps } from './gateway.js'; import { type ProjectTarget, type RunSnapshot } from './routing.js'; /** * The Discord chatbot (#680): chat to The Framework from Discord instead of the dashboard. * * Every effect is an injected function, so the whole bot is testable by handing it a fake * message — the routing decisions live in `routing.ts` and are pure, and this module is only * the wiring. Same seam-and-`stop()` shape as the intervention/activity watchers. * * Chat history is not written here: a message routed into a run reaches that run's conversation * through the control channel, and the run commits it to `.the-framework/conversations/` (#908). * That is the answer to the question #680 asked — the Git repo, via the run that received it. */ /** * How a turn that arrived here is attributed in the committed conversation (#917). Named once, * here, so the surface owns its own name rather than the daemon spelling it inline twice. */ export declare const DISCORD_VIA = "discord"; /** Everything the bot needs from the daemon. */ export interface DiscordBotOptions { /** The bot token. Distinct from the notification webhook (#627), which cannot read replies. */ token: string; /** The project a message belongs to when no run is live. */ target: () => Promise<ProjectTarget | undefined>; /** That project's live run, if it has one. */ liveRun: (projectId: string) => Promise<RunSnapshot | undefined>; /** Start a new run; resolves the run id, or `undefined` when it could not start. */ start: (projectId: string, text: string) => Promise<string | undefined>; sendMessage: (projectId: string, text: string, runId: string) => Promise<void>; sendChoice: (projectId: string, gateId: string, pick: string | string[], runId: string) => Promise<void>; sendStop: (projectId: string, runId: string) => Promise<void>; /** * Bind a run to the channel this message came from (#932), so the session's answers are posted * back where it was asked. Awaited *before* the run is handed the message: binding first is what * makes the reply reliably count as new rather than being baselined away. */ onRunBound?: (runId: string, channelId: string) => Promise<void>; /** * Whether the bot should act, read per message rather than at start, so turning it off takes * effect without restarting the daemon — the same contract the notification watchers follow. */ enabled?: () => Promise<boolean>; /** Restrict the bot to one channel. Unset means it answers wherever it is addressed. */ channelId?: string | undefined; fetchImpl?: typeof fetch; onLog?: (message: string) => void; /** Gateway seams, for tests. */ gateway?: GatewayDeps; } /** A running bot. `stop()` is what takes it offline on `Ctrl+C`. */ export interface DiscordBot { stop(): void; /** Handle one message. Exposed so tests drive a cycle without a socket, like the watchers' `poll()`. */ handleMessage(message: DiscordMessage): Promise<void>; } /** * Connect the bot and route messages. Never throws: a chat integration that can take the daemon * down is worse than one that is quiet. */ export declare function startDiscordBot(opts: DiscordBotOptions): DiscordBot; //# sourceMappingURL=bot.d.ts.map