import type { AgentSessionEvent, RpcCommand, RpcExtensionUIRequest, RpcExtensionUIResponse, RpcResponse, } from "@earendil-works/pi-coding-agent"; import type { ErrorResponse, InstanceSummary, ListRequest, ListResponse, RpcBridgeResponse, RpcReadyResponse, RpcRequest, RpcStreamRequest, ServerRequest, ServerResponse, SpawnRequest, SpawnResponse, StatusRequest, StatusResponse, StopRequest, StopResponse, } from "./ipc/protocol.ts"; import { supervisor } from "./supervisor.ts"; import type { InstanceRecord } from "./types.ts"; function toInstanceSummary(instance: InstanceRecord): InstanceSummary { return { id: instance.id, status: instance.status, cwd: instance.cwd, label: instance.label, sessionId: instance.sessionId, sessionFile: instance.sessionFile, radiusPiId: instance.radiusPiId, }; } function unknownInstanceError(instanceId: string): ErrorResponse { return { type: "error", ok: false, error: `Unknown instance: ${instanceId}`, }; } // Overhead types export async function handleIpcRequest(request: SpawnRequest): Promise; export async function handleIpcRequest(request: ListRequest): Promise; export async function handleIpcRequest(request: StopRequest): Promise; export async function handleIpcRequest(request: StatusRequest): Promise; export async function handleIpcRequest(request: RpcRequest): Promise; export async function handleIpcRequest(request: RpcStreamRequest): Promise; export async function handleIpcRequest(request: ServerRequest): Promise; export async function handleIpcRequest(request: ServerRequest): Promise { switch (request.type) { case "spawn": { const instance = await supervisor.spawnInstance({ cwd: request.cwd, label: request.label, }); return { type: "spawn_result", ok: true, instance: toInstanceSummary(instance), }; } case "list": { return { type: "list_result", ok: true, instances: supervisor.listInstances().map(toInstanceSummary), }; } case "status": { const instance = supervisor.getInstance(request.instanceId); if (!instance) { return unknownInstanceError(request.instanceId); } return { type: "status_result", ok: true, instance: toInstanceSummary(instance), }; } case "stop": { const instance = await supervisor.stopInstance(request.instanceId); if (!instance) { return unknownInstanceError(request.instanceId); } return { type: "stop_result", ok: true, instanceId: request.instanceId, }; } case "rpc": { const response = await supervisor.handleRpc(request.instanceId, request.command); if (!response) { return unknownInstanceError(request.instanceId); } return { type: "rpc_result", ok: true, response, }; } case "rpc_stream": { const instance = supervisor.getInstance(request.instanceId); if (!instance) { return unknownInstanceError(request.instanceId); } return { type: "rpc_ready", ok: true, instance: toInstanceSummary(instance), }; } } } export function openRpcStream( instanceId: string, onResponse: (response: RpcResponse) => void, onSessionEvent: (event: AgentSessionEvent) => void, onUiRequest: (request: RpcExtensionUIRequest) => void, ): | { handleRequest(request: RpcCommand | RpcExtensionUIResponse): Promise; close(): void; } | undefined { const handle = supervisor.openRpcStream(instanceId, onSessionEvent, onUiRequest); if (!handle) { return undefined; } return { async handleRequest(request): Promise { if (request.type === "extension_ui_response") { handle.handleUiResponse(request); return; } const response = await handle.handleRpc(request); onResponse(response); }, close(): void { handle.close(); }, }; }