@sema-agent/core
Version:
Stateless, task-oriented AI agent core
52 lines (51 loc) • 3.26 kB
TypeScript
import type { ExecutionEnv } from "../internal/harness-types.js";
/** Private parent dir (under the repo root) that holds all managed worktrees, so {@link pruneWorktrees} and a
* userland reaper can find orphans by a single known location. */
export declare const WORKTREE_PARENT = ".sema-worktrees";
export interface AddWorktreeOptions {
/** The base repository root — where `git worktree add` runs (the base env's cwd is typically this). */
repoRoot: string;
/** Stable per-task identity, sanitized into the worktree dir name (for human-readable orphan diagnosis). */
sessionId: string;
/**
* How to build a worktree-ROOTED {@link ExecutionEnv} for THIS env type — the only env-specific bit. Local:
* `(dir) => new NodeExecutionEnv({ cwd: dir })`. A single-E2B deployment: an E2B env whose cwd is `dir`. The
* returned env's fs/shell must operate relative to `dir`, so the agent's hands AND exec are confined there.
*/
rootEnvAt: (worktreeDir: string) => ExecutionEnv | Promise<ExecutionEnv>;
/** Base commit/ref for the worktree (default `HEAD` at creation time). */
commit?: string;
}
/**
* design/97 CORE-6 — the env-agnostic git-WORKTREE isolation primitive. Creates a detached worktree under
* {@link WORKTREE_PARENT} in `repoRoot` (via the BASE env's shell) and returns a worktree-ROOTED ExecutionEnv
* (built by `rootEnvAt`) whose `destroy()` removes the worktree. A control-plane `executionEnvFactory` calls this
* when its `ctx.isolation === "worktree"` and returns the result (with `destroy`); for a non-isolated task it
* returns the SHARED base env (no `destroy`) so the Runner never tears the base down.
*
* ISOLATE-ONLY: the runtime never merges — the orchestrator script reads each worktree's result and
* decides verify/merge in userland. Caveats: `git worktree` isolates the git WORKING COPY, not
* arbitrary shell access (bash can still reach the host — sandbox separately); UNCOMMITTED changes in the base
* repo are absent in the child (detached HEAD); a worktree orphaned by a process crash is reaped by
* {@link pruneWorktrees} (userland — there is no Runner hook for post-kill cleanup).
*/
export declare function addWorktree(baseEnv: ExecutionEnv, opts: AddWorktreeOptions): Promise<{
env: ExecutionEnv & {
destroy(): Promise<void>;
};
worktreeDir: string;
}>;
/** Reap orphaned worktrees (after a crash removed their dirs) — `git worktree prune` deregisters them. A userland
* reaper calls this periodically against the base repo; core ships no post-kill Runner hook.
*
* HRD-PTL-11: the exec Result used to be discarded, so every caller had to ASSUME the prune landed — and
* ExitWorktree's "already gone externally" leg told the model "stale git worktree metadata was pruned"
* on a claim it could not have checked. Same fail-loud treatment {@link removeWorktree} already got
* Report the outcome, let the caller decide what to say. Never throws (a throwing env
* lands on the same `{ok:false}`), so a caller that ignores the value behaves exactly as before. */
export declare function pruneWorktrees(baseEnv: ExecutionEnv, repoRoot: string): Promise<{
ok: true;
} | {
ok: false;
detail: string;
}>;