import type { Run } from "./wire/run.js"; import { type WorkflowManifest } from "./wire/manifest.js"; import type { HostCapabilities } from "./host_server.js"; import { type ClaimContextExtras } from "./run_context.js"; import type { SecretRedactor } from "./agent/secret_redactor.js"; import { type LogStream } from "./program_log_capture.js"; /** Default 5-minute lease (matches the engine spec). */ export declare const DEFAULT_LEASE_MS: number; /** Race-safe claim surface — the broker claim adapter satisfies it. Returns the claimed run row * plus the claim payload's context siblings (`workflowVersion` int, `environment {id,name}|null` * — P3.7), or null when the claim was lost. */ export interface RunClaimer { claimForWorker(runId: string, workerId: string, leaseUntil: number, nowMs: number): Promise<{ run: Run; context: ClaimContextExtras; } | null>; } /** The pinned program's download reference (the worker fetches + verifies + extracts it). */ export interface ProgramRef { entry: string; digest: string; sdkVersion: string; downloadUrl: string; } /** Reads the pinned version's manifest + program artifact reference. */ export interface ProgramVersionReader { getById(id: string): Promise<{ manifest: unknown; program: ProgramRef; } | null>; } /** Books the run's RUNTIME usage as periodic deltas (the worker's RuntimeFlusher). The * orchestrator drives the lifecycle: the timer flushes mid-run, `stop()` halts it at the body's end, * and `flushFinal()` books the tail on a clean terminal (skipped on a `lease_lost` handoff — the new * owner books its own runtime). Replaces the old single terminal runtime charge. */ export interface RuntimeFlushHandle { /** Stop the periodic flush timer (does NOT book the tail). */ stop(): Promise; /** Book the remaining runtime since the last flush (the terminal tail). */ flushFinal(): Promise; } /** Starts periodic runtime metering for a claimed run. `startedAtMs` is this session's claim time (the * point runtime begins accruing). Optional: absent disables runtime metering (the local/test path). */ export type RuntimeMeterStarter = (args: { run: Run; startedAtMs: number; }) => RuntimeFlushHandle; /** Marks a run terminal (status + output/error + completedAt + lease release). */ export interface RunFinalizer { finalize(runId: string, status: "completed" | "failed", output: unknown): Promise; } /** Restores/snapshots the workflow's persistent `/workspace`. Best-effort — both no-op when the * run isn't eligible (not opted-in / self-hosted), and neither throws. */ export interface WorkspaceHandle { hydrate(): Promise; /** Returns the snapshot byte size (0 on no-op) for the orchestrator's logging. */ persist(): Promise; } export interface PhaseLifecycleHandle { close(status: "completed" | "failed" | "cancelled"): void; } /** The run's engine-native LSP service (the engine's `LspService` satisfies it). Constructed once per * run (not per leaf) so the language server stays warm across the run's edits/leaves; the orchestrator * closes it on teardown so no language-server process leaks. `close()` is idempotent + never throws. */ export interface LspLifecycleHandle { close(): Promise; } /** Emits the program's declared `output` onto the run's event stream (v1 `output` kind). */ export interface RunOutputHandle { output(value: unknown): void; } /** Builds the per-run capability seam (leaf + sleep + children + secrets + shell + usage + auth) * for a claimed run — what the host-protocol server dispatches onto. Receives the run's * cooperative-cancellation `signal` so every hook honors it (credit exhaustion / cancel). * Returns the run's `SecretRedactor` alongside so the orchestrator can scrub a terminal * error with the SAME instance every resolved secret was recorded into, and an optional * `workspace` handle the orchestrator hydrates at start + persists at terminal. */ export type ProgramHostBuilder = (run: Run, manifest: WorkflowManifest, signal: AbortSignal) => Promise<{ capabilities: HostCapabilities; redactor: SecretRedactor; workspace?: WorkspaceHandle; phases?: PhaseLifecycleHandle; /** The run's engine-native LSP service (constructed per run; held by the `agent()` leaf). The * orchestrator closes it on terminal — success AND failure — so no language-server process leaks. * Optional — absent on paths with no LSP (the local/test path). */ lsp?: LspLifecycleHandle; /** Emits the program's declared output onto the run's event stream. */ activity?: RunOutputHandle; /** Records the extracted program directory once the runner unpacks the artifact, so the `agent()` * leaf can resolve this run's bundled skill files (`/skills/.md`). The orchestrator wires * it to the runner's `onExtracted`. Optional — absent on paths that don't surface bundled files. */ setProgramDir?: (dir: string) => void; /** The run's browser-session manager (browser tier). The orchestrator reaps every still-open session * on EVERY terminal path so no Chromium / Playwright MCP process leaks past the run. `closeAll` is * best-effort + never throws. Absent on images without the browser stack. */ browserSessions?: { closeAll(): Promise; }; /** The run's desktop-session manager (desktop tier); reaped on every terminal path like the * browser tier. Absent on images without the desktop stack. */ desktopSessions?: { closeAll(): Promise; }; /** Session recording + live-view capture (docs/SCREEN_CAPTURE.md). The orchestrator starts it before * the program runs and flushes it on EVERY terminal path. Best-effort; absent without the desktop * stack. */ capture?: { start(): Promise; stopAndFlush(): Promise; }; /** The compute-budget breach watcher (budget_gate.ts): detects a `max_compute_seconds` breach * between capability seams. The orchestrator stops it on EVERY terminal path (its interval is * unref'd, so this is hygiene, not liveness). Absent on paths without a budget gate. */ budgetWatch?: { stop(): void; }; }>; /** Handle to a running per-session loop (metering or credit watch); `stop()` ends + drains it. */ export interface RunSessionHandle { stop(): Promise; } /** Starts mid-run credit watching for a claimed run (the worker wires it to a CreditWatcher → broker * `/credit`). `onExhausted` fires once when the org runs out of credit — the orchestrator aborts the * run. Optional: absent disables credit watching. */ export type CreditWatchStarter = (args: { run: Run; onExhausted: () => void; }) => RunSessionHandle; /** Starts mid-run user-cancel watching for a claimed run (the worker wires it to a CancelWatcher → * broker `/cancel`). `onCancelled` fires once when the user cancels — the orchestrator aborts the run. * Optional: absent disables cancel watching (e.g. the local/pre-broker path). */ export type CancelWatchStarter = (args: { run: Run; onCancelled: () => void; }) => RunSessionHandle; /** Starts periodic lease renewal for a claimed run (the worker wires it to a LeaseRenewer → broker * `/renew`), so a run longer than the lease isn't reclaimed mid-flight. `onLost` fires once if the * lease is definitively lost (another worker reclaimed it) — the orchestrator aborts `lease_lost`, * and the run stops WITHOUT finalizing. Optional: absent disables renewal (the local/pre-broker path). */ export type LeaseWatchStarter = (args: { run: Run; onLost: () => void; }) => RunSessionHandle; export interface ProgramWorkerDeps { runs: RunClaimer; versions: ProgramVersionReader; /** The run's `/workspace` — cwd + HOME for author code (docs/WORKSPACE_PERSISTENCE.md I1), and the * tree `workspace.persist` archives. Passed through to the program runner. */ workspaceRoot: string; /** Where the program artifact extracts — OUTSIDE the workspace (I2). Passed through to the runner. */ programRoot: string; /** Download the program artifact bytes from the broker's presigned URL (broker.downloadBytes). */ fetchProgram: (downloadUrl: string) => Promise; /** Extract a gzipped tar into a dir (system `tar`); passed through to the program runner. */ extractArchive: (tgzPath: string, destDir: string) => Promise; /** Ensure the run's `/workspace` sandbox dir exists BEFORE the program runs — on EVERY run * (persist or not, snapshot or not). This makes "`/workspace` always exists" a guaranteed * contract a program can rely on, so authors write to `/workspace` WITHOUT a defensive `mkdir`. * Wired by the entrypoint to `mkdir(workspaceRoot, { recursive: true })`. Optional (the * local/test path may omit it); best-effort — a failure is logged, not thrown (the program's * own write would surface the real error, and the image already pre-creates the dir). */ ensureWorkspace?: () => Promise; /** Periodic runtime metering (optional — absent disables it, e.g. the local/test path). */ startRuntimeFlush?: RuntimeMeterStarter; finalizer: RunFinalizer; buildHost: ProgramHostBuilder; /** Starts mid-run credit watching for the session (optional — absent disables it). */ startCreditWatch?: CreditWatchStarter; /** Starts mid-run user-cancel watching for the session (optional — absent disables it). */ startCancelWatch?: CancelWatchStarter; /** Starts periodic lease renewal for the session, so a long run isn't spuriously reclaimed * (optional — absent disables renewal). */ startLeaseRenew?: LeaseWatchStarter; /** Emit the program's `console.*` output as `log` run-events while the body runs (optional — * absent disables capture). Wired by the entrypoint to the batched telemetry publisher. */ onProgramLog?: (stream: LogStream, text: string) => void; /** Task ARN (or any stable worker identity). */ workerId: string; /** Drain any buffered telemetry before the worker exits (brokered path's BrokerEventPublisher). * Called by the worker entrypoint's cleanup; the orchestrator itself never invokes it. */ flushTelemetry?: () => Promise; now?: () => number; leaseMs?: number; } export type ProgramWorkerOutcome = { kind: "claim_lost"; } | { kind: "completed"; } | { kind: "failed"; reason: string; }; export declare function runProgramWorker(runId: string, deps: ProgramWorkerDeps): Promise;