/** * RPC protocol types for headless operation. * * Commands are sent as JSON lines on stdin. * Responses and events are emitted as JSON lines on stdout. */ import type { AgentMessage, ThinkingLevel } from "@f5-sales-demo/pi-agent-core"; import type { Effort, ImageContent, Model } from "@f5-sales-demo/pi-ai"; import type { BashResult } from "../../exec/bash-executor"; import type { SkillSummary } from "../../extensibility/skills"; import type { SlashCommandSummary } from "../../extensibility/slash-commands"; // The host-tool wire types are transport-neutral and live in the shared host-tool // core so both the stdio RPC driver and the WS chat bridge use one vocabulary. import type { RpcHostToolCallRequest, RpcHostToolCancelRequest, RpcHostToolDefinition, RpcHostToolResult, RpcHostToolUpdate, } from "../../host-tools/types"; import type { MediaAssetChunk, MediaAssetReadRequest } from "../../media/transport"; import type { MediaDescriptorV1 } from "../../media/types"; import type { SessionStats } from "../../session/agent-session"; import type { CompactionResult } from "../../session/compaction"; import type { TodoPhase } from "../../tools/todo-write"; // ============================================================================ // RPC Commands (stdin) // ============================================================================ export type RpcCommand = // Prompting | { id?: string; type: "prompt"; message: string; locale?: string; images?: ImageContent[]; streamingBehavior?: "steer" | "followUp"; } | { id?: string; type: "steer"; message: string; images?: ImageContent[] } | { id?: string; type: "follow_up"; message: string; images?: ImageContent[] } | { id?: string; type: "abort" } | { id?: string; type: "abort_and_prompt"; message: string; images?: ImageContent[] } | { id?: string; type: "new_session"; parentSession?: string } // Locale | { id?: string; type: "set_locale"; locale: string } // State | { id?: string; type: "get_state" } | { id?: string; type: "set_todos"; phases: TodoPhase[] } | { id?: string; type: "set_host_tools"; tools: RpcHostToolDefinition[] } | { id?: string; type: "get_integrations" } | { id?: string; type: "list_skills" } | { id?: string; type: "list_commands" } // Model | { id?: string; type: "set_model"; provider: string; modelId: string } | { id?: string; type: "cycle_model" } | { id?: string; type: "get_available_models" } // Thinking | { id?: string; type: "set_thinking_level"; level: ThinkingLevel } | { id?: string; type: "cycle_thinking_level" } // Queue modes | { id?: string; type: "set_steering_mode"; mode: "all" | "one-at-a-time" } | { id?: string; type: "set_follow_up_mode"; mode: "all" | "one-at-a-time" } | { id?: string; type: "set_interrupt_mode"; mode: "immediate" | "wait" } // Compaction | { id?: string; type: "compact"; customInstructions?: string } | { id?: string; type: "set_auto_compaction"; enabled: boolean } // Retry | { id?: string; type: "set_auto_retry"; enabled: boolean } | { id?: string; type: "abort_retry" } // Bash | { id?: string; type: "bash"; command: string } | { id?: string; type: "abort_bash" } // Session | { id?: string; type: "get_session_stats" } | { id?: string; type: "export_html"; outputPath?: string } | { id?: string; type: "switch_session"; sessionPath: string } | { id?: string; type: "branch"; entryId: string } | { id?: string; type: "get_branch_messages" } | { id?: string; type: "get_last_assistant_text" } | { id?: string; type: "set_session_name"; name: string } | ({ id?: string; type: "media_asset_read" } & MediaAssetReadRequest) // Messages | { id?: string; type: "get_messages" }; // ============================================================================ // RPC State // ============================================================================ export interface RpcSessionState { model?: Model; thinkingLevel: ThinkingLevel | undefined; isStreaming: boolean; isCompacting: boolean; steeringMode: "all" | "one-at-a-time"; followUpMode: "all" | "one-at-a-time"; interruptMode: "immediate" | "wait"; sessionFile?: string; sessionId: string; sessionName?: string; autoCompactionEnabled: boolean; messageCount: number; queuedMessageCount: number; todoPhases: TodoPhase[]; /** For session dump / export (plain-text parity with /dump). */ systemPrompt?: string; dumpTools?: Array<{ name: string; description: string; parameters: unknown }>; } // ============================================================================ // RPC Responses (stdout) // ============================================================================ // Success responses with data export type RpcResponse = // Prompting (async - events follow) | { id?: string; type: "response"; command: "prompt"; success: true } | { id?: string; type: "response"; command: "steer"; success: true } | { id?: string; type: "response"; command: "follow_up"; success: true } | { id?: string; type: "response"; command: "abort"; success: true } | { id?: string; type: "response"; command: "abort_and_prompt"; success: true } | { id?: string; type: "response"; command: "new_session"; success: true; data: { cancelled: boolean } } // Locale | { id?: string; type: "response"; command: "set_locale"; success: true } // State | { id?: string; type: "response"; command: "get_state"; success: true; data: RpcSessionState } | { id?: string; type: "response"; command: "set_todos"; success: true; data: { todoPhases: TodoPhase[] } } | { id?: string; type: "response"; command: "set_host_tools"; success: true; data: { toolNames: string[] } } | { id?: string; type: "response"; command: "list_skills"; success: true; data: { skills: SkillSummary[] }; } | { id?: string; type: "response"; command: "list_commands"; success: true; data: { commands: SlashCommandSummary[] }; } | { id?: string; type: "response"; command: "get_integrations"; success: true; data: { version: string; model: { state: "no_provider" | "connected" | "auth_error"; provider?: string; latencyMs?: number }; services: Array<{ name: string; state: "connected" | "unauthenticated" | "unavailable"; hint?: string }>; }; } // Model | { id?: string; type: "response"; command: "set_model"; success: true; data: Model; } | { id?: string; type: "response"; command: "cycle_model"; success: true; data: { model: Model; thinkingLevel: ThinkingLevel | undefined; isScoped: boolean } | null; } | { id?: string; type: "response"; command: "get_available_models"; success: true; data: { models: Model[] }; } // Thinking | { id?: string; type: "response"; command: "set_thinking_level"; success: true } | { id?: string; type: "response"; command: "cycle_thinking_level"; success: true; data: { level: Effort } | null; } // Queue modes | { id?: string; type: "response"; command: "set_steering_mode"; success: true } | { id?: string; type: "response"; command: "set_follow_up_mode"; success: true } | { id?: string; type: "response"; command: "set_interrupt_mode"; success: true } // Compaction | { id?: string; type: "response"; command: "compact"; success: true; data: CompactionResult } | { id?: string; type: "response"; command: "set_auto_compaction"; success: true } // Retry | { id?: string; type: "response"; command: "set_auto_retry"; success: true } | { id?: string; type: "response"; command: "abort_retry"; success: true } // Bash | { id?: string; type: "response"; command: "bash"; success: true; data: BashResult } | { id?: string; type: "response"; command: "abort_bash"; success: true } // Session | { id?: string; type: "response"; command: "get_session_stats"; success: true; data: SessionStats } | { id?: string; type: "response"; command: "export_html"; success: true; data: { path: string } } | { id?: string; type: "response"; command: "switch_session"; success: true; data: { cancelled: boolean } } | { id?: string; type: "response"; command: "branch"; success: true; data: { text: string; cancelled: boolean } } | { id?: string; type: "response"; command: "get_branch_messages"; success: true; data: { messages: Array<{ entryId: string; text: string }> }; } | { id?: string; type: "response"; command: "get_last_assistant_text"; success: true; data: { text: string | null }; } | { id?: string; type: "response"; command: "set_session_name"; success: true } | { id?: string; type: "response"; command: "media_asset_read"; success: true; data: MediaAssetChunk } // Messages | { id?: string; type: "response"; command: "get_messages"; success: true; data: { messages: AgentMessage[] } } // Error response (any command can fail) | { id?: string; type: "response"; command: string; success: false; error: string }; export interface RpcMediaEvent { type: "chat_media"; media: MediaDescriptorV1; } // ============================================================================ // Extension UI Events (stdout) // ============================================================================ /** Emitted when an extension needs user input */ export type RpcExtensionUIRequest = | { type: "extension_ui_request"; id: string; method: "select"; title: string; options: string[]; timeout?: number } | { type: "extension_ui_request"; id: string; method: "confirm"; title: string; message: string; timeout?: number } | { type: "extension_ui_request"; id: string; method: "input"; title: string; placeholder?: string; timeout?: number; } | { type: "extension_ui_request"; id: string; method: "editor"; title: string; prefill?: string; promptStyle?: boolean; } | { type: "extension_ui_request"; id: string; method: "cancel"; targetId: string } | { type: "extension_ui_request"; id: string; method: "notify"; message: string; notifyType?: "info" | "warning" | "error"; } | { type: "extension_ui_request"; id: string; method: "setStatus"; statusKey: string; statusText: string | undefined; } | { type: "extension_ui_request"; id: string; method: "setWidget"; widgetKey: string; widgetLines: string[] | undefined; widgetPlacement?: "aboveEditor" | "belowEditor"; } | { type: "extension_ui_request"; id: string; method: "setTitle"; title: string } | { type: "extension_ui_request"; id: string; method: "set_editor_text"; text: string }; // ============================================================================ // Host Tool Frames (bidirectional) // ============================================================================ // Re-exported here for RPC consumers (imported above for use within this module). export type { RpcHostToolCallRequest, RpcHostToolCancelRequest, RpcHostToolDefinition, RpcHostToolResult, RpcHostToolUpdate, }; // ============================================================================ // Extension UI Commands (stdin) // ============================================================================ /** Response to an extension UI request */ export type RpcExtensionUIResponse = | { type: "extension_ui_response"; id: string; value: string } | { type: "extension_ui_response"; id: string; confirmed: boolean } | { type: "extension_ui_response"; id: string; cancelled: true; timedOut?: boolean }; // ============================================================================ // Helper type for extracting command types // ============================================================================ export type RpcCommandType = RpcCommand["type"];