//#region src/contexts/types.d.ts
/**
 * Execution context types.
 *
 * An execution context defines *where* and *how* an agent's tools run.
 * The agent loop and tools interact through this interface without knowing
 * whether they're running in-process, in a Docker container, or in a
 * remote sandbox.
 */
/**
 * Lifetime guarantee of background tasks started through
 * {@link ExecutionContext.execBackground}.
 *
 * - `'none'` — the context cannot detach tasks at all.
 * - `'process-lifetime'` — tasks live as long as the HOST process; a
 *   crash/restart of the host orphans or kills them (`ProcessContext`).
 * - `'durable'` — tasks live on a remote runner and survive host process
 *   death (remote execution contexts driven by durable runtimes).
 *
 * Durable-execution adapters (e.g. `zidane/restate`) consult this to
 * decide whether backgrounding is safe to expose: a `'durable'` context
 * keeps its tasks across worker crashes, so there is no reason to strip
 * the capability from the model.
 */
type DetachedTasksCapability = 'none' | 'process-lifetime' | 'durable';
interface ContextCapabilities {
  /** Can execute shell commands */
  shell: boolean;
  /** Can read/write files in a workspace */
  filesystem: boolean;
  /** Can make outbound network requests */
  network: boolean;
  /** Has GPU access */
  gpu: boolean;
  /**
   * Background-task lifetime guarantee. Optional for backward
   * compatibility — when absent, callers infer `'process-lifetime'`
   * if the context implements `execBackground`, `'none'` otherwise
   * (see {@link resolveDetachedTasksCapability}).
   */
  detachedTasks?: DetachedTasksCapability;
}
/**
 * Effective {@link DetachedTasksCapability} of a context, with the
 * backward-compatible inference for contexts that predate the field.
 */
declare function resolveDetachedTasksCapability(context: ExecutionContext): DetachedTasksCapability;
/** Opaque handle to a running execution context instance */
interface ExecutionHandle {
  id: string;
  type: ContextType;
  /** Working directory within the context */
  cwd: string;
}
interface ExecResult {
  stdout: string;
  stderr: string;
  exitCode: number;
}
interface SpawnConfig {
  /** Working directory (created if it doesn't exist) */
  cwd?: string;
  /** Environment variables */
  env?: Record<string, string>;
  /** Docker image (only for 'docker' context) */
  image?: string;
  /** Docker container name prefix (only for 'docker' context) */
  name?: string;
  /** Host paths mounted into the context (only for 'docker' context today) */
  mounts?: ContextMount[];
  /** Resource limits */
  limits?: {
    /** Memory limit in MB */memory?: number; /** CPU limit (e.g. '1.0' = 1 core) */
    cpu?: string; /** Timeout in seconds for the entire context lifetime */
    timeout?: number;
  };
  /** Sandbox provider config (only for 'sandbox' context) */
  sandbox?: {
    provider: string;
    apiKey?: string;
    [key: string]: unknown;
  };
  /**
   * How long `destroy()` waits for a SIGTERM'd background task to settle
   * before escalating to SIGKILL and abandoning the wait (process context
   * only). Bounds `agent.destroy()` against tasks that trap SIGTERM or
   * whose stdio pipes are held open by escaped grandchildren.
   *
   * Default: `5000`.
   */
  destroyGraceMs?: number;
  /**
   * Publish container ports on the host (docker context only).
   *
   * Each entry maps a container port to either an explicit host port or
   * (when `host` is omitted) a Docker-assigned random port. Retrieve the
   * actual host port at runtime via `getMappedPort(container)` on the
   * docker context.
   */
  ports?: Array<{
    container: number;
    host?: number;
    proto?: 'tcp' | 'udp';
  }>;
  /**
   * UID/GID the container should run as (docker context only).
   *
   * Accepts the same forms Docker's `--user` does: `uid`, `uid:gid`, or a
   * named user that exists in the image. Default is the image's default
   * user (typically root). Setting this to the host user's `uid:gid`
   * avoids the EACCES-on-cleanup problem when sharing a workspace via
   * a `shared` mount.
   */
  user?: string;
  /**
   * User-defined Docker network to join (docker context only).
   *
   * Defaults to Docker's default bridge. Use a user network when you
   * need multiple sibling containers (e.g. agent + database + dev
   * server) to discover each other by name.
   */
  network?: string;
  /**
   * Docker labels to attach to the container (docker context only).
   *
   * Useful for ownership tracking — callers can sweep abandoned
   * containers (e.g. from a crashed parent process) by filtering on
   * a label they own: `docker ps -aq --filter label=my-app=true`.
   */
  labels?: Record<string, string>;
}
interface ContextMount {
  /** Absolute host path to mount. */
  source: string;
  /** Absolute path inside the execution context. */
  target: string;
  /** Mount read-only. Defaults to false for Docker's native bind behavior. */
  readonly?: boolean;
  /**
   * Apply the SELinux shared label (`:z`) so the host user and the container
   * user can both read/write the mount (docker context only). No-op on
   * non-SELinux hosts. Combine with `SpawnConfig.user` to avoid root-owned
   * files leaking onto the host. Mutually exclusive with `readonly`.
   */
  shared?: boolean;
}
type ContextType = 'process' | 'docker' | 'sandbox';
interface ExecutionContext {
  /** Context type identifier */
  readonly type: ContextType;
  /** What this context supports */
  readonly capabilities: ContextCapabilities;
  /** Spawn a new execution environment */
  spawn: (config?: SpawnConfig) => Promise<ExecutionHandle>;
  /**
   * Execute a shell command in the context.
   *
   * `signal` propagates abort all the way down to the underlying child
   * process — the implementation is expected to wire it into whatever
   * spawn primitive it uses so the OS receives a SIGTERM (or equivalent)
   * when the caller aborts. Without it, a cancelled tool returns its
   * cancellation marker to the model but the underlying process keeps
   * running in the background, orphaning compute / locks / IO. Pass
   * `ctx.signal` from a tool body to inherit the per-call + run-level
   * abort union; pass a freshly-built one for a host-driven kill.
   *
   * Implementations are free to ignore `signal` (the contract degrades
   * gracefully — the process simply won't be killed), but the in-process
   * default DOES honor it via `child_process.exec`'s native `signal`
   * option.
   */
  exec: (handle: ExecutionHandle, command: string, options?: {
    cwd?: string;
    env?: Record<string, string>;
    timeout?: number;
    signal?: AbortSignal;
  }) => Promise<ExecResult>;
  /**
   * Start a process in the background. Settles as soon as `spawn` returns
   * — does NOT wait for the child to exit. Stdout + stderr stream
   * interleaved to the file at the returned `outputPath`. The caller
   * (typically the agent) reads incremental output via the regular
   * {@link ExecutionContext.readFile} seam.
   *
   * Optional — contexts without background support (some remote sandboxes)
   * just don't implement it. The shell tool surfaces a clean
   * "background mode is not supported in this execution context" error
   * when this is undefined.
   *
   * `onExit` is called once when the child terminates (natural, killed,
   * or error). The same instance that called `execBackground` is the
   * exclusive owner of the callback — it's not a multi-cast bus. Hosts
   * wire this to the agent's pending-notification queue so the model
   * gets a `<task-notification>` on its next turn.
   *
   * `onExit` is OPTIONAL: remote / durable contexts may have no legal
   * way to push a callback from a timer back into the host (a Restate
   * journal, for instance, forbids out-of-band writes). Such contexts
   * simply record the exit in their registry; the agent loop reconciles
   * by polling {@link ExecutionContext.listBackground} at run
   * boundaries, where a host journal wrapper is legal (the
   * `background:reconcile` hook is the journalable seam).
   *
   * See `docs/RUN_IN_BACKGROUND.md` for the broader design contract
   * (file location, replay semantics, suppression rules).
   */
  execBackground?: (handle: ExecutionHandle, command: string, options: {
    cwd?: string;
    env?: Record<string, string>;
    /**
     * Absolute directory the context appends `<task-id>.log` to. The
     * agent owns this path because it carries session-shaped knowledge
     * (`<userDir>/<sessionId>/tasks/`) the context can't synthesize.
     * Must already exist OR be creatable by the context — the
     * implementation handles `mkdir -p` defensively.
     */
    outputDir: string; /** Push-style exit callback. Optional — see the method doc. */
    onExit?: (info: TaskExitInfo) => void;
    /**
     * Cap on bytes written to the output file. Beyond the cap the
     * process KEEPS RUNNING; further output is counted but dropped,
     * and a `<output-truncated bytes-dropped="N"/>` marker is
     * appended when the task settles. Unset / non-positive = no cap.
     */
    maxOutputBytes?: number;
    /**
     * Stall watchdog: when the task produces no output for this many
     * milliseconds, `onStall` fires ONCE (one-shot — re-arms only
     * after fresh output arrives). The process is NOT killed; the
     * consumer decides (typically by telling the model the task may
     * be stuck at an interactive prompt). Unset = no watchdog.
     */
    stallTimeoutMs?: number; /** One-shot stall callback — see `stallTimeoutMs`. */
    onStall?: (info: TaskStallInfo) => void;
  }) => Promise<TaskHandle>;
  /**
   * SIGTERM the whole process group of a running background task.
   * Idempotent — second call returns `null` (or the cached exit info).
   * Resolves once the process has exited AND its output stream has
   * been flushed + closed.
   *
   * `null` return on miss (unknown id, already cleaned up) so the
   * shell_kill tool can surface a clean "no such task" message
   * without throwing.
   */
  killBackground?: (handle: ExecutionHandle, taskId: string) => Promise<TaskExitInfo | null>;
  /**
   * Snapshot of every task in the context's registry — running AND
   * terminated (entries remain until the next context destroy, so
   * the model can still read output of exited tasks).
   */
  listBackground?: (handle: ExecutionHandle) => Promise<readonly TaskEntry[]>;
  /**
   * Block until a background task terminates, then resolve with its
   * exit info. Resolves immediately for already-terminated tasks.
   *
   * Returns `null` when:
   *   - the task id is unknown (or owned by another handle — same
   *     isolation contract as `killBackground`), OR
   *   - `timeoutMs` elapsed / `signal` aborted before the task exited.
   *
   * Callers that need to distinguish "unknown" from "still running"
   * should consult `listBackground` first (the `wait_task` tool does).
   *
   * This is the injectable wait seam for the `wait_task` tool:
   * in-process contexts implement it on the existing `onExit`
   * machinery; durable hosts implement it as an awakeable park
   * (runner fires task-exit over their bridge → resolveAwakeable).
   */
  waitBackground?: (handle: ExecutionHandle, taskId: string, options?: {
    timeoutMs?: number;
    signal?: AbortSignal;
  }) => Promise<TaskExitInfo | null>;
  /**
   * Transfer ownership of every still-running task from `fromHandle`
   * to `toHandle`. Used by the spawn tool to "promote" a subagent's
   * background tasks up to the parent's handle so they outlive the
   * subagent's destroy() — matching shell semantics, where a `&`-ed
   * command outlives the parent process.
   *
   * Side effects:
   *   - The task's `handleId` is rewritten, so subsequent
   *     `listBackground(toHandle)` / `killBackground(toHandle, …)` /
   *     `destroy(toHandle)` see it (and `fromHandle`-scoped operations
   *     don't).
   *   - When `newOnExit` is provided, the original `onExit` is
   *     REPLACED with it. Critical: the task's natural exit callback
   *     was captured against the spawning agent's hook bus, which is
   *     about to be destroyed; without rewiring, the parent never
   *     learns when the task terminates. Pass a closure that fires
   *     the parent agent's `background:exit` hook.
   *
   * Returns the entries that were actually reassigned (running tasks
   * only; terminated ones stay where they are). Implementations that
   * don't support reassignment can leave this undefined; the caller
   * (spawn.ts) falls back to the current behavior of killing child
   * tasks at subagent shutdown.
   */
  reassignBackgroundTasks?: (fromHandle: ExecutionHandle, toHandle: ExecutionHandle, newOnExit?: (info: TaskExitInfo) => void) => Promise<readonly TaskEntry[]>;
  /** Read a file from the context's filesystem */
  readFile: (handle: ExecutionHandle, path: string) => Promise<string>;
  /**
   * Read a file from the context's filesystem as raw bytes.
   *
   * Used by `read_file` to dispatch image / binary files into the multimodal
   * `ToolResultContent[]` route. Optional — when not implemented, the tool
   * falls back to `base64 < path` via the `exec` seam, which works in any
   * shell-capable context. Implementations that already have a native
   * binary read (in-process `fs.readFile` without encoding, container API,
   * sandbox SDK) should override for the latency win.
   */
  readFileBinary?: (handle: ExecutionHandle, path: string) => Promise<Uint8Array>;
  /** Write a file to the context's filesystem */
  writeFile: (handle: ExecutionHandle, path: string, content: string) => Promise<void>;
  /** List files in a directory */
  listFiles: (handle: ExecutionHandle, path: string) => Promise<string[]>;
  /**
   * Resolve the host-side port that a container port was published on
   * (docker context only, and only when the matching entry was created
   * with `host` omitted in `SpawnConfig.ports`).
   *
   * Resolves to `null` if the container port isn't published. Other
   * contexts (process, sandbox) don't implement this; they don't have
   * a port-mapping concept.
   */
  getMappedPort?: (handle: ExecutionHandle, containerPort: number) => Promise<number | null>;
  /** Destroy the execution environment and clean up resources */
  destroy: (handle: ExecutionHandle) => Promise<void>;
}
/**
 * Lifecycle status of a background task.
 *
 * - `'running'` — process is still live; `exitCode` / `signal` unset.
 * - `'exited'` — process terminated on its own (clean or non-zero exit).
 * - `'killed'` — the host issued `killBackground` (SIGTERM to the group).
 *
 * The status is a coarse-grained signal; the exit code carries the
 * fine-grained detail (e.g. `143 = SIGTERM` for `'killed'`).
 */
type BackgroundTaskStatus = 'running' | 'exited' | 'killed';
/**
 * Returned synchronously by `execBackground` — the handle the model and
 * the framework use to refer to the task until it terminates.
 *
 * `outputPath` is an absolute path to the log file the context is
 * appending stdout + stderr to (interleaved by emit order). The model
 * reads it via the normal `read_file` tool; no special tool is required.
 */
interface TaskHandle {
  /**
   * Stable id minted by the context — typically `bash_<n>` for
   * `ProcessContext`. Sequential within a single context instance,
   * resets when a new context is constructed. Forwarded to `killBackground` /
   * `listBackground` and stamped into every `<task-notification>` block.
   */
  taskId: string;
  /** OS pid of the spawned shell wrapper (process-group leader on POSIX). */
  pid: number;
  /** Absolute path to the log file the context is streaming output into. */
  outputPath: string;
}
/**
 * Fired exactly once per task when the child process terminates, via
 * `execBackground`'s `onExit` callback. The agent layer translates this
 * into a queued `<task-notification>` for the next turn.
 *
 * `signal` is set when the child was terminated by a signal (e.g.
 * SIGTERM from our own kill-tree, SIGKILL from oom-killer); absent on
 * natural exit. `exitCode` is `128 + signal-number` on signal-killed
 * children, matching POSIX shell conventions — `143` for SIGTERM, etc.
 */
interface TaskExitInfo {
  taskId: string;
  status: Exclude<BackgroundTaskStatus, 'running'>;
  exitCode: number;
  signal?: NodeJS.Signals;
  outputPath: string;
  /** `Date.now()` delta between spawn and exit. */
  durationMs: number;
  /** The original command string the model invoked — useful for telemetry / banner summary. */
  command: string;
}
/**
 * One row in `listBackground`'s snapshot. Living entries (status `'running'`)
 * have `exitCode` / `signal` / `endedAt` unset; terminated entries carry the
 * same data `TaskExitInfo` returned at exit time.
 */
interface TaskEntry {
  taskId: string;
  pid: number;
  command: string;
  cwd: string;
  startedAt: number;
  /**
   * Set when the task terminated. Lets pull-based consumers (the agent's
   * run-boundary reconcile) derive `durationMs = endedAt - startedAt`
   * without depending on when the snapshot was taken.
   */
  endedAt?: number;
  outputPath: string;
  status: BackgroundTaskStatus;
  exitCode?: number;
  signal?: NodeJS.Signals;
  /** Total bytes written to the output file so far — useful for "task X has produced N KB" UX hints. */
  bytesWritten: number;
}
/**
 * Fired by the optional stall watchdog (see `execBackground`'s
 * `stallTimeoutMs`) when a running task has produced no output for the
 * configured window. The process is still alive — this is a signal, not
 * a state transition.
 */
interface TaskStallInfo {
  taskId: string;
  command: string;
  outputPath: string;
  /** Milliseconds since the last output chunk (>= the configured window). */
  stalledForMs: number;
  /** Total bytes the task has written so far. */
  bytesWritten: number;
}
//#endregion
export { DetachedTasksCapability as a, ExecutionHandle as c, TaskExitInfo as d, TaskHandle as f, ContextType as i, SpawnConfig as l, resolveDetachedTasksCapability as m, ContextCapabilities as n, ExecResult as o, TaskStallInfo as p, ContextMount as r, ExecutionContext as s, BackgroundTaskStatus as t, TaskEntry as u };
//# sourceMappingURL=types-BibzMDjX.d.ts.map