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.

69 lines 3.37 kB
/** * The daemon's one background clock (E4). * * Every sweep used to own a timer: the CI watch on a minute, the worktree sweep and auto PM on ten, * the session committer's debounce on thirty seconds, the two Discord watchers on a minute each. * Six intervals with six `setInterval`s, six unref calls and six overlap guards, and no single * place to look when the answer to "why is nothing happening" is that a sweep is not running. * * One interval fires, and each job says how often it wants a turn. A job's cadence stops being a * duration it has to reason about and becomes a small integer: how many ticks between turns. * * The base interval is the finest cadence anything needs. Anything slower is that many ticks — * exact by construction, because the ratios are integers rather than two timers drifting apart. */ /** One thing the daemon does on a schedule. */ export interface TickJob { /** For the log line when it throws. */ name: string; /** * Ticks between turns. `1` is every tick, `20` is every twentieth. A tick is the interval * coming round, not a turn that ran, so a slow job on the same clock cannot stretch this out. * * Its own turn is *skipped* rather than queued, so a slow job never accumulates a backlog of * missed turns to work through. */ every?: number; /** Run one turn. Awaited, so a long job holds the tick rather than overlapping the next one. */ run: () => Promise<void>; /** * Run on the very first tick, which fires at start-up rather than one interval later. * * On by default, because the case most of these exist for is a machine that was off while * something happened. A job that only makes sense once the daemon has been up a while says so. */ onStart?: boolean; } /** The running clock. */ export interface DaemonTick { /** Run one tick now, awaiting it. The daemon's shutdown and the tests drive it through this. */ tick: () => Promise<void>; /** * Stop the clock, and resolve when the turn already in flight has finished. Awaiting it is how * a shutdown knows the sweeps have let go of the repo — clearing the interval only stops the * *next* turn, and these jobs commit and push. */ stop: () => Promise<void>; } /** How often the clock fires. The finest cadence any job asks for; everything else is a multiple. */ export declare const DAEMON_TICK_MS = 30000; /** What {@link startDaemonTick} needs. */ export interface DaemonTickOptions { jobs: readonly TickJob[]; /** Override the base interval (tests). */ intervalMs?: number; log: (message: string) => void; } /** * Start the clock and return the handle that stops it. * * A job that throws costs its own turn and nothing else: the others in the same tick still run, * and the failure is logged once with the job's name, because a sweep failing silently is * indistinguishable from one that is not scheduled at all. * * Overlapping ticks join the one already running rather than being dropped, so awaiting `tick()` * means the tick finished — which is what lets a test drive this deterministically. The timer is * unref'd: background work is never the reason the process stays up. */ export declare function startDaemonTick(opts: DaemonTickOptions): DaemonTick; //# sourceMappingURL=daemon-tick.d.ts.map