跳到內容

RPC 協定參考

RPC 模式以換行符分隔的 JSON 協定透過 stdio 執行編碼代理。

  • stdin:命令(RpcCommand)和擴充功能 UI 回應
  • stdout:命令回應(RpcResponse)、工作階段/代理事件、擴充功能 UI 請求

主要實作:

  • src/modes/rpc/rpc-mode.ts
  • src/modes/rpc/rpc-types.ts
  • src/session/agent-session.ts
  • packages/agent/src/agent.ts
  • packages/agent/src/agent-loop.ts
Terminal window
xcsh --mode rpc [regular CLI options]

行為說明:

  • @file CLI 引數在 RPC 模式中會被拒絕。
  • RPC 模式預設會停用自動工作階段標題生成,以避免額外的模型呼叫。
  • RPC 模式會將影響工作流程的 todo.*task.*async.* 設定重設為內建預設值,而非繼承使用者覆寫。
  • 進程以 JSONL 格式讀取 stdin(readJsonl(Bun.stdin.stream()))。
  • 當 stdin 關閉時,進程以代碼 0 退出。
  • 回應/事件以每行一個 JSON 物件的形式寫入。

每個訊框是一個 JSON 物件後接 \n

除了物件結構本身外,沒有其他封裝。

  1. RpcResponse{ type: "response", ... }
  2. AgentSessionEvent 物件(agent_startmessage_update 等)
  3. RpcExtensionUIRequest{ type: "extension_ui_request", ... }
  4. 擴充功能錯誤({ type: "extension_error", extensionPath, event, error }
  1. RpcCommand
  2. RpcExtensionUIResponse{ type: "extension_ui_response", ... }

所有命令接受可選的 id?: string

  • 若提供,正常的命令回應會回傳相同的 id
  • RpcClient 依賴此機制進行待處理請求的解析。

來自執行時期的重要邊界行為:

  • 未知命令回應會以 id: undefined 發送(即使請求帶有 id)。
  • 輸入迴圈中的解析/處理例外會發送 command: "parse"id: undefined
  • promptabort_and_prompt 會回傳即時成功,之後若非同步提示排程失敗,可能會以相同 id 發送後續錯誤回應。

RpcCommand 定義在 src/modes/rpc/rpc-types.ts

  • { id?, type: "prompt", message: string, images?: ImageContent[], streamingBehavior?: "steer" | "followUp" }
  • { id?, type: "steer", message: string, images?: ImageContent[] }
  • { id?, type: "follow_up", message: string, images?: ImageContent[] }
  • { id?, type: "abort" }
  • { id?, type: "abort_and_prompt", message: string, images?: ImageContent[] }
  • { id?, type: "new_session", parentSession?: string }
  • { id?, type: "get_state" }
  • { id?, type: "set_todos", phases: TodoPhase[] }
  • { id?, type: "set_host_tools", tools: RpcHostToolDefinition[] }
  • { id?, type: "set_model", provider: string, modelId: string }
  • { id?, type: "cycle_model" }
  • { id?, type: "get_available_models" }
  • { id?, type: "set_thinking_level", level: ThinkingLevel }
  • { id?, type: "cycle_thinking_level" }
  • { id?, type: "set_steering_mode", mode: "all" | "one-at-a-time" }
  • { id?, type: "set_follow_up_mode", mode: "all" | "one-at-a-time" }
  • { id?, type: "set_interrupt_mode", mode: "immediate" | "wait" }
  • { id?, type: "compact", customInstructions?: string }
  • { id?, type: "set_auto_compaction", enabled: boolean }
  • { id?, type: "set_auto_retry", enabled: boolean }
  • { id?, type: "abort_retry" }
  • { id?, type: "bash", command: string }
  • { id?, type: "abort_bash" }
  • { id?, type: "get_session_stats" }
  • { id?, type: "export_html", outputPath?: string }
  • { id?, type: "switch_session", sessionPath: string }
  • { id?, type: "branch", entryId: string }
  • { id?, type: "get_branch_messages" }
  • { id?, type: "get_last_assistant_text" }
  • { id?, type: "set_session_name", name: string }
  • { id?, type: "get_messages" }

所有命令結果使用 RpcResponse

  • 成功:{ id?, type: "response", command: <command>, success: true, data?: ... }
  • 失敗:{ id?, type: "response", command: string, success: false, error: string }

資料酬載因命令而異,定義在 rpc-types.ts 中。

{
"model": { "provider": "...", "id": "..." },
"thinkingLevel": "off|minimal|low|medium|high|xhigh",
"isStreaming": false,
"isCompacting": false,
"steeringMode": "all|one-at-a-time",
"followUpMode": "all|one-at-a-time",
"interruptMode": "immediate|wait",
"sessionFile": "...",
"sessionId": "...",
"sessionName": "...",
"autoCompactionEnabled": true,
"messageCount": 0,
"queuedMessageCount": 0,
"todoPhases": [
{
"id": "phase-1",
"name": "Todos",
"tasks": [
{
"id": "task-1",
"content": "Map the tool surface",
"status": "in_progress"
}
]
}
]
}

替換當前工作階段的記憶體內待辦事項狀態,並回傳正規化的階段列表:

{
"id": "req_2",
"type": "set_todos",
"phases": [
{
"id": "phase-1",
"name": "Evaluation",
"tasks": [
{
"id": "task-1",
"content": "Map the read tool surface",
"status": "in_progress"
},
{
"id": "task-2",
"content": "Exercise edit operations",
"status": "pending"
}
]
}
]
}

這對於希望在第一次提示之前預先設定計畫的主機端非常有用。

替換 RPC 伺服器可透過 stdio 回呼的當前主機端擁有的工具集:

{
"id": "req_3",
"type": "set_host_tools",
"tools": [
{
"name": "echo_host",
"label": "Echo Host",
"description": "Echo a value from the embedding host",
"parameters": {
"type": "object",
"properties": {
"message": { "type": "string" }
},
"required": ["message"],
"additionalProperties": false
}
}
]
}

回應酬載為:

{
"toolNames": ["echo_host"]
}

這些工具會在下次模型呼叫前加入活動工作階段的工具登錄中。重新發送 set_host_tools 會替換先前的主機端擁有集合。

RPC 模式從 AgentSession.subscribe(...) 轉發 AgentSessionEvent 物件。

常見事件類型:

  • agent_startagent_end
  • turn_startturn_end
  • message_startmessage_updatemessage_end
  • tool_execution_starttool_execution_updatetool_execution_end
  • auto_compaction_startauto_compaction_end
  • auto_retry_startauto_retry_end
  • ttsr_triggered
  • todo_reminder
  • todo_auto_clear

擴充功能執行器錯誤以單獨方式發送:

{ "type": "extension_error", "extensionPath": "...", "event": "...", "error": "..." }

message_updateassistantMessageEvent 中包含串流增量(文字/思考/工具呼叫增量)。

這是最重要的操作行為。

promptabort_and_prompt立即確認

{ "id": "req_1", "type": "response", "command": "prompt", "success": true }

這表示:

  • 命令接受 != 執行完成
  • 最終完成透過 agent_end 觀察

AgentSession.prompt() 在活動串流期間需要 streamingBehavior

  • "steer" => 佇列中的引導訊息(中斷路徑)
  • "followUp" => 佇列中的後續訊息(輪次後路徑)

若在串流期間省略,提示將失敗。

來自編碼代理設定結構描述(packages/coding-agent/src/config/settings-schema.ts):

  • steeringMode"one-at-a-time"
  • followUpMode"one-at-a-time"
  • interruptMode"wait"
  • set_steering_mode / set_follow_up_mode
    • "one-at-a-time":每輪從佇列取出一則訊息
    • "all":一次取出整個佇列
  • set_interrupt_mode
    • "immediate":工具執行在工具呼叫之間檢查引導;待處理的引導可以中止該輪中剩餘的工具呼叫
    • "wait":延遲引導直到輪次完成

RPC 模式中的擴充功能使用請求/回應 UI 訊框。

RpcExtensionUIRequesttype: "extension_ui_request")方法:

  • selectconfirminputeditor
  • notifysetStatussetWidgetsetTitleset_editor_text

執行時期說明:

  • 在 RPC 模式中自動工作階段標題生成已停用,且 setTitle UI 請求也預設被抑制,因為大多數主機端沒有有意義的終端機標題介面。設定 PI_RPC_EMIT_TITLE=1 可重新啟用 UI 事件。

範例:

{ "type": "extension_ui_request", "id": "123", "method": "confirm", "title": "Confirm", "message": "Continue?", "timeout": 30000 }

RpcExtensionUIResponsetype: "extension_ui_response"):

  • { type: "extension_ui_response", id: string, value: string }
  • { type: "extension_ui_response", id: string, confirmed: boolean }
  • { type: "extension_ui_response", id: string, cancelled: true }

若對話框有逾時設定,RPC 模式在逾時/中止觸發時會解析為預設值。

RPC 主機端可以透過發送 set_host_tools 向代理公開自訂工具,然後透過相同的傳輸層服務執行請求。

當代理希望主機端執行其中一個工具時,RPC 模式會發送:

{
"type": "host_tool_call",
"id": "host_1",
"toolCallId": "toolu_123",
"toolName": "echo_host",
"arguments": { "message": "hello" }
}

若工具執行稍後被中止,RPC 模式會發送:

{
"type": "host_tool_cancel",
"id": "host_cancel_1",
"targetId": "host_1"
}

主機端可以選擇性地串流進度:

{
"type": "host_tool_update",
"id": "host_1",
"partialResult": {
"content": [{ "type": "text", "text": "working" }]
}
}

完成使用:

{
"type": "host_tool_result",
"id": "host_1",
"result": {
"content": [{ "type": "text", "text": "done" }]
}
}

host_tool_result 上設定 isError: true 可將回傳的內容作為工具錯誤呈現。

失敗為 success: false 附帶字串 error

{ "id": "req_2", "type": "response", "command": "set_model", "success": false, "error": "Model not found: provider/model" }
  • 大多數命令失敗是可恢復的;進程保持存活。
  • 格式錯誤的 JSONL / 解析迴圈例外會發送 parse 錯誤回應並繼續讀取後續行。
  • 空的 set_session_name 會被拒絕(Session name cannot be empty)。
  • 具有未知 id 的擴充功能 UI 回應會被忽略。
  • 進程終止條件為 stdin 關閉或擴充功能觸發的明確關閉。

stdin:

{ "id": "req_1", "type": "prompt", "message": "Summarize this repo" }

stdout 序列(典型):

{ "id": "req_1", "type": "response", "command": "prompt", "success": true }
{ "type": "agent_start" }
{ "type": "message_update", "assistantMessageEvent": { "type": "text_delta", "delta": "..." }, "message": { "role": "assistant", "content": [] } }
{ "type": "agent_end", "messages": [] }

2) 串流期間使用明確佇列策略提示

Section titled “2) 串流期間使用明確佇列策略提示”

stdin:

{ "id": "req_2", "type": "prompt", "message": "Also include risks", "streamingBehavior": "followUp" }

stdin:

{ "id": "q1", "type": "get_state" }
{ "id": "q2", "type": "set_steering_mode", "mode": "all" }
{ "id": "q3", "type": "set_interrupt_mode", "mode": "wait" }

stdout:

{ "type": "extension_ui_request", "id": "ui_7", "method": "input", "title": "Branch name", "placeholder": "feature/..." }

stdin:

{ "type": "extension_ui_response", "id": "ui_7", "value": "feature/rpc-host" }

src/modes/rpc/rpc-client.ts 是一個便利封裝,而非協定定義。

目前輔助工具特性:

  • 產生 bun <cliPath> --mode rpc
  • 透過生成的 req_<n> id 關聯回應
  • 僅將已識別的 AgentEvent 類型分派給監聽器
  • 透過 setCustomTools() 支援主機端擁有的自訂工具,並自動處理 host_tool_call / host_tool_cancel
  • 為每個協定命令提供輔助方法(例如,set_interrupt_modeset_session_name 存在於協定類型中,但未封裝為專用方法)

若您需要完整的介面覆蓋,請使用原始協定訊框。