/** * RPC isolation spawner — runs child agent in a separate Pi process via JSON-line protocol. * Spec: §4.3 — Process/RPC Isolation */ import { SessionManager, RpcClient } from "@earendil-works/pi-coding-agent"; import type { AgentLifecycle } from "@pi-orca/core"; import type { ResolvedAgentTemplate } from "../template.js"; import type { SpawnRespawnSpec } from "./sdk.js"; export interface RpcAgentRecord { client: RpcClient; unsubscribe: () => void; /** PID populated from the child's first heartbeat write (RpcClient doesn't expose it). */ pid?: number; sessionPath: string; /** Lifecycle (spec §5.13). Persistent → onTerminate("agent_end") goes idle. */ lifecycle: AgentLifecycle; /** Parent session path captured at spawn (so the prompt helper can flip status). */ parentSessionPath: string; /** When set, the next "agent_end" was triggered by a parent-driven prompt. */ inFlightPromptAt?: number; } export declare function getRpcAgent(agentId: string): RpcAgentRecord | undefined; export declare function listRpcAgents(): ReadonlyMap; export declare function clearRpcAgents(): void; export interface SpawnRpcParams { agentId: string; resolved: ResolvedAgentTemplate; task?: string; /** * Parent session's relative path (canonical form, portable across hosts). * Used for `.orca/agents/` layout and as the cross-machine fallback when * `parentSessionFile` doesn't exist locally. Spec §2.6.1. */ parentSessionPath: string; /** * Parent session's absolute file path on the host that wrote the status. * Preferred for `SessionManager.forkFrom` when it still exists locally; * otherwise we resolve `parentSessionPath` under the local sessions root. * Omit or pass "" when the parent has no on-disk file (in-memory * SDK sessions). Spec §2.6.1. */ parentSessionFile?: string; parentSessionId: string; rootSessionPath: string; parentNotifySockPath?: string; /** Optional cwd override */ cwd?: string; /** Optional Pi session directory override (for create/forkFrom) */ sessionDir?: string; /** * Optional RpcClient factory for testing. * Defaults to `new RpcClient(opts)`. */ rpcClientFactory?: (opts: { cwd: string; args: string[]; cliPath?: string; env?: Record; }) => RpcClient; /** * Optional SessionManager factory pair for testing. * Defaults to `SessionManager.create`, `SessionManager.forkFrom`, and * `SessionManager.open` (the last is used on respawn). */ sessionManagerFactory?: { create: (cwd: string, sessionDir?: string) => SessionManager; forkFrom: (sourcePath: string, cwd: string, sessionDir?: string) => Promise; open?: (sessionFile: string, sessionDir?: string, cwdOverride?: string) => SessionManager; }; /** When set, open an existing session file instead of fork/fresh. */ respawn?: SpawnRespawnSpec; /** * When true, the terminal-status worktree cleanup bypasses the W9 * uncommitted-work safeguard. Driven by `agents.worktreeForceCleanupOnTerminal`. */ worktreeForceCleanupOnTerminal?: boolean; /** Notify hook reused for worktree cleanup messages (W9 safeguard). */ notifyWorktree?: (message: string, type?: "info" | "warning" | "error") => void; } export interface SpawnRpcResult { agentId: string; status: "running"; isolation: "process"; pid: undefined; sessionPath: string; } /** * Spawn an RPC agent (fire-and-forget). * Returns immediately after RpcClient.start() resolves and the task has been * submitted via fire-and-forget prompt. Completion handled via onEvent. * * @param params - Spawn parameters * @returns Result with agentId, status, isolation, sessionPath */ export declare function spawnRpcAgent(params: SpawnRpcParams): Promise; /** * Update the cached PID for an RPC agent. * The child's first heartbeat write populates pid in agents/.yaml; * the parent's idle poller calls this to keep RpcAgentRecord in sync. * * @param agentId - Agent ID * @param pid - PID from the child's status YAML */ export declare function setRpcAgentPid(agentId: string, pid: number): void; /** * Stop an RPC agent. * Spec: §5.1.1 stopAllAgents and /agents stop * * @param agentId - Agent ID * @returns True if found and stopped */ export declare function stopRpcAgent(agentId: string): Promise; /** * Stop all RPC agents in parallel. * Spec: §5.1.1 stopAllAgents dispatcher */ export declare function stopAllRpcAgents(): Promise; /** * Drive the next prompt cycle of a persistent RPC agent. * Spec §5.13. * * Read-merge-writes status YAML to `running` (idle → running flip) then * fires `client.prompt(task)` fire-and-forget. The child's own `agent_end` * handler eventually writes `status: idle` back; `onTerminate("agent_end")` * is a redundant safety net for the same flip. * * Returns `false` when the agent isn't registered or isn't persistent. */ export declare function sendPromptToRpcAgent(agentId: string, task: string): Promise; //# sourceMappingURL=rpc.d.ts.map