import type { LanguageModel } from "ai"; import type { AgentProvider, AgentTarget, ExecutableTarget, ExecutorResult, Loop, LoopMachineRef, LoopRun, PersistGuardOptions } from "../types.js"; import { type BundleExecutionRefusal } from "./bundle/executor-bundle.js"; import type { RunReceiptBundle } from "../types.js"; export interface SpawnedProcessInfo { pid: number; pgid: number; processStartedAt: string; } export interface AgentProgressInfo { provider: AgentProvider; agentId?: string; status?: string; summary?: string; statusReason?: string; threadId?: string; rolloutPath?: string; pid?: number; lastEventSeq?: number; } export interface ExecuteOptions extends PersistGuardOptions { maxOutputBytes?: number; env?: NodeJS.ProcessEnv; goalModel?: LanguageModel; log?: (message: string) => void; signal?: AbortSignal; onSpawn?: (pid: number) => void; /** Children are spawned detached in their own process group, so pgid === pid. */ onSpawnProcess?: (info: SpawnedProcessInfo) => void; /** Progress from durable provider controllers, for example Codewith background agents. */ onAgentProgress?: (info: AgentProgressInfo) => void; machine?: LoopMachineRef; machineResolver?: (machine: LoopMachineRef) => LoopMachineRef; machineCommandResolver?: (machineId: string, command: string) => MachineCommandPlan; /** * Run a bundled loop whose tree no longer matches its manifest. * * Set by `loops run-now --allow-dirty`, per run, by the operator standing in * front of the station - and by nothing else. The daemon and the runner never * set it: an implicit bypass would make the drift refusal advisory, and an * advisory integrity check is not one. */ allowDirtyBundle?: boolean; } export interface ExecutionMetadata { loopId?: string; loopName?: string; runId?: string; scheduledFor?: string; workflowId?: string; workflowName?: string; workflowRunId?: string; workflowStepId?: string; goalId?: string; goalObjective?: string; goalNodeKey?: string; } export interface PreflightResult { command: string; accountProfile?: string; accountTool?: string; } interface MachineCommandPlan { command: string; args: string[]; source: string; } /** Exported for tests: resolves the default idle watchdog for agent targets. */ export declare function defaultAgentIdleTimeoutMs(target: AgentTarget, opts: ExecuteOptions): number | undefined; /** * Detects git's "missing but already registered worktree" error: the target * path is recorded in `.git/worktrees/` but its directory was deleted out from * under it, so `git worktree add` refuses. git's own prescribed remedy is * `git worktree prune` (or `add -f`). Left unhandled this terminal-fails worktree * prep on every attempt and the drain dedupes the failed item into a silent * wedge — historically the single biggest burner of the redispatch cap. */ export declare function isStaleWorktreeRegistration(detail: string | undefined): boolean; export declare function preflightTarget(target: ExecutableTarget, metadata?: ExecutionMetadata, opts?: ExecuteOptions): PreflightResult; export declare function executeTarget(target: ExecutableTarget, metadata?: ExecutionMetadata, opts?: ExecuteOptions): Promise; /** * The bundle gate: resolve a bundled loop's target against its bundle root, or * refuse the run. * * Exported for the tests that assert NOTHING is spawned on a refusal - the * check has to happen before `executeTarget`, not inside it, because by the * time a spec exists the decision to run has already been made. */ export type BundleExecutionDecision = { target: ExecutableTarget; opts: ExecuteOptions; bundle?: RunReceiptBundle; } | { refusal: BundleExecutionRefusal; }; /** * The run result a bundle refusal produces. * * One place, because two callers need it: `executeLoop` for a plain command * loop and `executeLoopTarget` for the goal and workflow shapes, which never * reach `executeLoop` at all. `loop_runs.error` is what an operator greps, so * the coded prefix has to be identical on both paths. */ export declare function bundleRefusalResult(refusal: BundleExecutionRefusal): ExecutorResult; export declare function applyBundleExecution(loop: Loop, opts: ExecuteOptions): BundleExecutionDecision; export declare function executeLoop(loop: Loop, run: LoopRun, opts?: ExecuteOptions, /** * The bundle decision, when the caller has already taken it. * * `executeLoopTarget` gates BEFORE it branches to a goal or a workflow, so * for a plain command loop it hands the verdict down rather than making the * tree be read, hashed and secret-scanned a second time in the same run. * Absent, this verifies for itself — a direct `executeLoop` caller is gated * exactly as before. */ decision?: BundleExecutionDecision): Promise; export {};