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.

108 lines 4.98 kB
import { resolveAgentCheckout } from '../store/index.js'; import { defaultProjectsProvider } from '../dashboard/projects.js'; /** * What the dashboard's RPCs act through: the daemon's own closures, set once when it comes up. * * A module-level value, not a per-request one. It used to ride Telefunc's request context, read * back through `getContext()` inside an AsyncLocalStorage — machinery for a per-caller context * that never varied per caller. Two rounds of simplification got it here: three hosts wired * different subsets, so every accessor returned `T | undefined` and every RPC branched on the * absent case (D3 left one host, which wires all of it); and the request scoping itself was only * ever carrying process-wide wiring (F3). What is left is what it always was — the daemon's * capabilities, set at boot. */ let wired; /** Wire the dashboard's capabilities. The daemon calls this once at start-up; a test calls it per case. */ export function setDashboardContext(context) { wired = context; } /** * Read one capability. * * Unwired is a bug rather than a degraded host, so it throws and names the field instead of * silently answering as if nothing were configured. */ function fromContext(key) { const value = wired?.[key]; if (value === undefined) throw new Error(`the dashboard's RPC context has no ${String(key)}`); return value; } /** No run is relayed from here — see {@link contextRemote}. */ const NO_RELAYED_RUNS = { target: () => undefined, list: () => [] }; /** The projects every RPC resolves a project id against: the global registry. */ export function contextProjects() { return defaultProjectsProvider(); } /** The workspace path for a project id, or undefined when no project has that id. */ export function resolveProjectPath(projectId) { return contextProjects().resolvePath(projectId); } /** * The checkout a call should act on: a live agent's own worktree when `agentId` names one (#738/#749), * else the project root. Since #736 an agent reads and writes inside its worktree — its event log, * its control log, its working tree — so anything addressed at a *run* has to resolve here, not * at the project path, or it reads an empty log and steers an agent that is not listening. The * resolution itself (and its #766 first-seconds subtlety) lives in the store's * {@link resolveAgentCheckout}, shared with the daemon; this adds only the project-id lookup. */ export async function resolveAgentPath(projectId, agentId) { const cwd = await resolveProjectPath(projectId); return cwd ? resolveAgentCheckout(cwd, agentId) : undefined; } /** * The in-memory {@link EventsSource} (#426). It answers only for an agent this daemon is relaying * from a connected device (#1067) — such an agent has no `.the-framework/events.jsonl` here — and * returns undefined for an ordinary local agent, whose log `onEvents` tails off disk. */ export function contextEventsSource() { return fromContext('eventsSource'); } /** * The relayed-agent lookup (#1067 slice 2). A run-scoped RPC uses it to tell an ordinary local agent * (resolve a local checkout) from one running on a connected device (forward the call there). * * The one accessor with a default rather than a throw, because "unwired" has a real meaning here: * a call arriving over `/_relay/rpc` is the *device* side of the relay, and the agent it names is * local to that device. Forwarding it onward would be a loop, so the honest answer there is that * nothing is relayed from here. */ export function contextRemote() { return wired?.remote ?? NO_RELAYED_RUNS; } /** The user-preferences store (#410), over the registry file. */ export function contextPreferences() { return fromContext('preferences'); } /** * The Discord credentials store (#1095): it writes the credential to the registry, then rebuilds * this daemon's own Discord services against it, so the bot connects without a restart. */ export function contextDiscord() { return fromContext('discord'); } /** The quota source behind the usage panel (#533). */ export function contextQuota() { return fromContext('quota'); } /** Where auto PM's last decision is read from (#1161). */ export function contextAutoPm() { return fromContext('autoPm'); } /** How a sweep is fired on demand (#1210). */ export function contextAutoPmSweep() { return fromContext('autoPmSweep'); } /** What a project currently suffers from (#1500), as the daemon's background jobs last recorded it. */ export function contextProjectErrors() { return fromContext('projectErrors'); } /** The daemon's own `startAgent`, so a start from the dashboard is the same start the CLI makes. */ export function contextStartAgent() { return fromContext('startAgent'); } /** Install + register a repo (#433), which only the daemon can do. */ export function contextAddProject() { return fromContext('addProject'); } //# sourceMappingURL=context.js.map