/** * OpenKernel — Agent Backend types * * A backend is *who actually runs a dispatched task* on a node. The mesh's * default backend is the local kernel (`kernel.execute`), but a node can also * run a third-party coding CLI — Claude Code, Codex, OpenCode — as the executor. * That is what lets a task dispatched across the mesh be fulfilled by a real * external agent, and (with a persisted session id) lets those agents be * messaged again later. * * Everything here is transport-agnostic: the Federation manager owns spawning + * streaming; a backend just knows how to drive one CLI and parse its output. */ import type { Capability } from '../../types.js'; /** Identifier of a backend. 'kernel' is the built-in native path. */ export type BackendId = 'kernel' | 'claude' | 'codex' | 'opencode' | 'gemini' | (string & {}); /** A unit of work handed to a backend. */ export interface BackendTask { prompt: string; capabilities?: Capability[]; /** Optional model hint (provider/model or a CLI-native model id). */ model?: string; /** Extra CLI args for this run (e.g. from a coder profile). Appended verbatim. */ args?: string[]; /** Resume an existing CLI session instead of starting fresh. */ sessionId?: string; } /** A streamed activity fragment emitted while a backend runs. */ export interface BackendFrame { kind: 'log' | 'event' | 'output' | 'error'; text?: string; data?: unknown; } /** Context passed to a backend run — where to stream, how to cancel. */ export interface BackendRunContext { runId: string; /** Called for each activity fragment (streamed up the mesh SSE feed). */ onFrame: (frame: BackendFrame) => void; /** Abort the underlying process. */ signal?: AbortSignal; /** Working directory for the spawned CLI (defaults to process.cwd()). */ cwd?: string; /** Persistent device role, prepended to the prompt so the agent is in-character. */ rolePreamble?: string; } /** Terminal result of a backend run. */ export interface BackendRunResult { status: 'completed' | 'failed'; /** The CLI's native session id — enables resume + later messaging. */ sessionId?: string; /** Final assistant text, if captured. */ content?: string; error?: string; } /** Drives one executor (a CLI or the native kernel). */ export interface AgentBackend { id: BackendId; displayName: string; /** True when this backend can run here (e.g. the CLI is on PATH). Sync + cheap. */ available(): boolean; /** Run a task to completion, streaming frames along the way. */ run(task: BackendTask, ctx: BackendRunContext): Promise; /** Send a follow-up message into an existing session (mailbox — slice 2). */ send?(sessionId: string, message: string, ctx: BackendRunContext): Promise; /** Best-effort stop of a running session. */ stop?(sessionId: string): Promise; }