import type { ClaimResponse } from "../contract.js"; import { type Logger } from "../runtime/support/index.js"; import type { PoolClient } from "./pool_client.js"; export interface RunProcessHandle { /** Resolves with the exit code when the run process ends. */ wait: () => Promise; /** Ask the process to stop (SIGTERM — the runtime exits and the lease recovers the run). */ kill: () => void; } export interface RunSpawner { (opts: { entry: string; env: Record; cwd: string; }): RunProcessHandle; } export interface DaemonDeps { client: Pick; /** Absolute path to the runtime process entry (dist/runtime/main.js). */ runtimeEntry: string; /** Root under which per-run workspaces are created (and always removed). */ workDir: string; /** Stable runner identity (stamped as WORKER_ID on run processes). */ runnerId: string; spawn: RunSpawner; log?: Logger; sleep?: (ms: number) => Promise; now?: () => number; /** Execute at most one run, then return (CI-friendly). */ once?: boolean; /** Test hook: called at the top of each loop iteration. */ onIdle?: () => void; /** Called once, after the FIRST poll the control plane actually accepts. Announcing the runner * before this is a lie: registration succeeding says nothing about whether poll is allowed. */ onOnline?: () => void; } export interface DaemonController { /** Resolves when the daemon has fully stopped (drained + last run finished). */ done: Promise; /** Begin draining: finish the current run (if any), then stop claiming. */ drain: () => void; } /** Env for one run process: the platform contract + the claim's resolved non-secret vars. */ export declare function runProcessEnv(claim: ClaimResponse, opts: { runnerId: string; workspaceRoot: string; persistScopeDir: string; }): Record; export declare function startDaemon(deps: DaemonDeps): DaemonController;