SPB Git

spb/khaelor Public

KHAELOR — a terminal-native autonomous engineering agent powered by Anthropic.

TypeScript 82.9% HTML 14.9% CSS 1.1% JavaScript 0.7%
2.1 KB · 75 lines typescript
Raw Blame History
1/**2 * KHAELOR3 * File: src/workspace/workspace.ts4 * Description: Workspace interface — the single world seam for files and process execution (ADR-13).5 *6 * Author: Simon-Pierre Boucher7 * Contact: contact@spboucher.ai8 */910/**11 * The world seam (ARCHITECTURE.md §workspace, ADR-13). Exactly four methods.12 * Tools act on the world only through this interface; `src/workspace/` is the13 * sole module allowed to import `node:fs` / `node:child_process`.14 */15export interface Workspace {16  cwd(): string;17  readFile(path: string): Promise<string>;18  /** Atomic: temp file + rename, preserving mode bits. */19  writeFile(path: string, content: string): Promise<void>;20  exec(command: Command): Promise<ProcessResult>;21}2223/** A foreground command for `Workspace.exec` (used by the `bash` tool). */24export interface Command {25  /** Run via the user shell for the `bash` tool. */26  cmd: string;27  cwd?: string;28  /** Hard ceiling; ADR-8: long commands redirect to `process`. */29  timeoutMs: number;30  env?: Record<string, string>;31  signal?: AbortSignal;32}3334/** Result of a foreground command. */35export interface ProcessResult {36  /** null = killed by timeout/signal. */37  exitCode: number | null;38  stdout: string;39  stderr: string;40  durationMs: number;41  truncated: boolean;42}4344/** Stable machine-readable error codes for workspace failures. */45export type WorkspaceErrorCode =46  | "file-not-found"47  | "file-is-directory"48  | "file-too-large"49  | "file-binary"50  | "write-failed"51  | "exec-failed"52  | "process-unknown"53  | "process-not-running";5455/**56 * Typed workspace failure. Kept module-local (the shared `KhaelorErrorCode`57 * union stays closed); messages must never contain secrets.58 */59export class WorkspaceError extends Error {60  readonly code: WorkspaceErrorCode;61  readonly details: Readonly<Record<string, unknown>>;6263  constructor(code: WorkspaceErrorCode, message: string, details: Record<string, unknown> = {}) {64    super(message);65    this.name = "WorkspaceError";66    this.code = code;67    this.details = details;68  }69}7071/** Narrowing helper. */72export function isWorkspaceError(value: unknown): value is WorkspaceError {73  return value instanceof WorkspaceError;74}75