本頁譯自英文文件。指令、識別名稱與範例保持原樣。執行環境 7.24.4 · SDK 2.6.7。 英文原文
gRPC 與原生 SDK 傳輸
狀態:現行 範圍:桌面原生傳輸契約 上次審閱:2026-09-02 負責人:ax-code sdk
AX Code 現在提供可選的、形狀如 gRPC 的傳輸契約,供桌面與原生 GUI 應用程式使用。這份契約刻意比完整的 HTTP/OpenAPI 路由樹更窄:它聚焦於 GUI 要有原生感所需的無介面執行環境能力,同時讓 HTTP/OpenAPI 仍可在內部用於相容、診斷與產生的用戶端。
建議
把 gRPC/原生傳輸當作第一方桌面應用程式的首選邊界。保留 HTTP/SSE 作為後備與除錯介面。
| 需求 | 建議路徑 | 原因 |
|---|---|---|
| 第一方桌面 GUI | @defai-digital/ax-code-sdk/grpc |
穩定的指令/事件契約、可串流、對原生友善的中繼資料與期限 |
| 同一處理程序中的 TypeScript 自動化 | @defai-digital/ax-code-sdk,並帶上 createAgent() |
最低負擔與自訂工具支援 |
| 瀏覽器、WebView 後備,或簡易診斷 | HTTP/SSE,並帶上 @defai-digital/ax-code-sdk/headless |
可搭配 fetch、curl、瀏覽器開發工具與現行伺服器驗證控制 |
| 外部非 JS 整合 | gRPC proto 或 OpenAPI 產生的用戶端 | 工具支援廣,且不必維護第一方 HTTP SDK |
| Rust 主機嵌入 | gRPC/原生服務或子處理程序橋接 | 避免把完整 HTTP 路由樹暴露給應用程式殼層 |
為何保留 HTTP
從執行環境移除 HTTP/OpenAPI,會拿掉最容易檢查、也最可攜的相容路徑。JavaScript SDK 不應把 HTTP 用戶端/伺服器子路徑當成第一方支援介面,但內部 HTTP 橋接對診斷、既有無介面後端啟動,以及產生用戶端的工作流程仍然有用。現行 HTTP 伺服器控制包括:強制僅限迴路的綁定、SDK 管理的後端輔助程式中產生的 Basic Auth 憑證、對會變更狀態的瀏覽器請求做來源檢查、目錄驗證、請求速率限制,以及僅限迴路的即時 OpenAPI 文件。
傳輸不是一般代理程式回合的主要延遲來源。LLM 呼叫、shell 指令、檔案 IO、索引、LSP 啟動與工具執行,通常比本機 JSON 更貴。gRPC 對桌面 GUI 仍然有用,因為它提供較乾淨的原生 API 契約、期限、中繼資料、伺服器串流,以及通往 Unix socket 或具名管線傳輸的路徑,而不必把面向瀏覽器的 API 拖進應用程式殼層。
契約形狀
語言中立的契約位於
packages/sdk/proto/ax_code/v1/headless.proto。JSR 套件
也把該 proto 收為資產。TypeScript 主機以 resolveAxCodeGrpcProtoUrl() 定位它;非 JavaScript
產生器應使用標準儲存庫契約。
TypeScript 外觀位於 @defai-digital/ax-code-sdk/grpc,涵蓋:
- 健康狀態與生命週期就緒
- 應用程式日誌接收,以及供原生主機生命週期管理的執行個體處置/重新啟動控制
- 工作階段建立
- 提示、指令、shell、中止、權限回覆與問題回覆
- 供應商、工作階段、權限、問題、路徑、VCS、LSP、MCP、格式化工具與指令狀態的 GUI 啟動快照
- 工作階段清單、詳細資料、訊息歷史、訊息詳細資料、子項、目標、待辦、diff、分叉、分享與摘要操作
- 代理程式、技能、專案、路徑、VCS、指令、檔案樹/內容/狀態、 文字/檔案/符號搜尋與工具結構描述的 GUI 探索與工作區導覽
- 專案情境、情境範本、快取記憶體的重新整理/清除,以及除錯引擎的待處理計畫診斷
- 受監督 GUI 流程的待處理權限與問題清單/回覆/拒絕操作
- 供應商、設定、API 金鑰驗證,以及 GUI 設定畫面的供應商 OAuth 設定
- 自主模式、隔離模式與智慧 LLM 路由的執行環境設定控制
- MCP 狀態、資源探索、動態伺服器管理、OAuth、連線與中斷控制
- 診斷與設定畫面的 LSP 與格式化工具狀態
- PTY 終端機管理與雙向終端機串流
- 審查/除錯 UI 的工作階段證據
- 工作佇列操作
- 排程工作操作
- 工作流程範本、工作流程執行、儀表板摘要、評估案例、工作流程例行作業與執行產物
- 伺服器串流的執行環境事件
proto 對指令本文與工作流程/工作承載使用結構化 JSON 承載。這樣可在 AX Code 執行環境結構描述快速演進時,維持傳輸穩定。
@defai-digital/ax-code-sdk/grpc 也匯出 AX_CODE_GRPC_METHOD_DESCRIPTORS、listAxCodeGrpcMethods()、
getAxCodeGrpcMethodDescriptor()、assertAxCodeGrpcMethodSupported()、listMissingAxCodeGrpcNativeHandlers() 與
assertAxCodeGrpcNativeHandlers()。原生主機在建立處理常式對應、gRPC 服務繫結、預載允許清單或啟動閘門時,應以這些描述元與覆蓋檢查作為標準方法目錄。每個描述元包含
方法名稱、完整限定方法路徑、串流種類、proto 請求與回應訊息名稱、GUI 領域、HTTP
橋接可用性,以及現行穩定性。這樣可讓原生傳輸邊界保持明確,而不暴露或
鏡射完整的 HTTP 路由樹。
TypeScript 用法
當主機內部仍需要既有的 HTTP 執行環境時,使用 SDK 管理的 gRPC 無介面後端。它把 HTTP 橋接留在主機處理程序內,只回傳 gRPC 用戶端與生命週期控制代碼:
import {
createAxCodeGrpcClientFromNativeBridge,
resolveAxCodeGrpcProtoUrl,
startAxCodeGrpcHeadlessBackend,
} from "@defai-digital/ax-code-sdk/grpc"
const backend = await startAxCodeGrpcHeadlessBackend({ directory: "/workspace/app" })
try {
const client = backend.client
const session = await client.createSession({ title: "GUI session" })
const messages = await client.session.messages((session as { id: string }).id, { limit: 50 })
const skills = await client.app.skills()
const readme = await client.file.read("README.md")
const authMethods = await client.provider.auth()
const bootstrap = await client.bootstrap.load({
include: { sessions: true, providers: true, providerList: true, path: true, vcs: true },
})
const terminal = (await client.pty.create({ title: "GUI shell" })) as { id: string }
const protoUrl = resolveAxCodeGrpcProtoUrl()
await client.sendPrompt((session as { id: string }).id, {
parts: [{ type: "text", text: "Review this workspace" }],
})
for await (const event of client.subscribeEvents({ sessionID: (session as { id: string }).id })) {
if (event.type === "server.heartbeat") continue
// Project event into GUI state.
}
} finally {
await backend.close()
}
當桌面主機透過 Electron preload、Tauri
指令或其他結構化複製邊界擁有特權執行環境邊界時,使用原生 IPC 橋接。IPC 呼叫刻意省略 AbortSignal,並把雙向
輸入串流留在呼叫承載之外,使呼叫物件能乾淨地跨越渲染程序/主機邊界:
const client = createAxCodeGrpcClientFromNativeIpc({
unary(call) {
return window.axCodeNative.unary(call)
},
serverStream(call) {
return window.axCodeNative.serverStream(call)
},
bidiStream(call, input) {
return window.axCodeNative.bidiStream(call, input)
},
})
請只在雙方都處於同一個 JavaScript 領域時使用 createAxCodeGrpcClientFromNativeBridge(),而且呼叫物件可以安全地直接傳遞
AbortSignal 與非同步可迭代物。
若主機暴露推送式訂閱,請使用 createAxCodeGrpcNativeIpcBridgeFromChannels() 或
createAxCodeGrpcNativeIpcStream(),把主機回呼改寫成 gRPC SDK 預期的 AsyncIterable 串流。
這些輔助程式適用於 Tauri 事件聆聽器、Electron preload 回呼,以及其他回傳
取消訂閱函式、而不是 JavaScript 非同步產生器的 IPC 系統。
原生主機也可以暴露處理常式對應,而不必手寫方法分支。這對 Rust/Tauri 指令、Electron preload API,或想逐一繫結 AX Code 執行環境操作的真正本機 gRPC 伺服器很有用。在把橋接交給 渲染程序程式碼之前,使用方法描述元驗證每個預期領域都已覆蓋:
import {
AX_CODE_GRPC_METHOD,
assertAxCodeGrpcNativeHandlers,
createAxCodeGrpcNativeBridgeFromHandlers,
listAxCodeGrpcMethods,
} from "@defai-digital/ax-code-sdk/grpc"
const handlers = {
unary: {
[AX_CODE_GRPC_METHOD.GetSession](request, options) {
return runtime.getSession(request.sessionID, options)
},
},
serverStream: {
[AX_CODE_GRPC_METHOD.SubscribeEvents](_request, options) {
return runtime.events(options)
},
},
bidiStream: {
[AX_CODE_GRPC_METHOD.ConnectPty](request, input, options) {
return runtime.connectPty(request.id, input, options)
},
},
}
const mcpMethods = listAxCodeGrpcMethods({ domain: "mcp" })
const streamingMethods = listAxCodeGrpcMethods({ kind: "serverStream" })
const ptyDescriptor = listAxCodeGrpcMethods({ kind: "bidiStream" })[0]
// ptyDescriptor.requestType === "PtyClientEvent"
// ptyDescriptor.responseType === "PtyServerEvent"
assertAxCodeGrpcNativeHandlers(handlers, {
methods: [AX_CODE_GRPC_METHOD.GetSession, AX_CODE_GRPC_METHOD.SubscribeEvents, AX_CODE_GRPC_METHOD.ConnectPty],
})
const bridge = createAxCodeGrpcNativeBridgeFromHandlers(handlers, {
requireHandlers: {
methods: [AX_CODE_GRPC_METHOD.GetSession, AX_CODE_GRPC_METHOD.SubscribeEvents, AX_CODE_GRPC_METHOD.ConnectPty],
},
})
bootstrap.load() 刻意是面向 GUI 的快照,而不是每一條 HTTP 路由的一對一複本。使用 include 只要求目前檢視所需的狀態。失敗的子請求回報在 errors,成功的欄位仍會回傳,因此缺少選用子系統不會阻止桌面殼層開啟。
事件串流接受選用的 types 與 sessionID 篩選。原生傳輸應在伺服器端套用這些篩選。
HTTP 相容橋接在既有 SSE 路由上於用戶端套用相同篩選,因此 GUI 程式碼可以在原生伺服器實作期間維持同一種
訂閱形狀。
startAxCodeGrpcHeadlessBackend() 是較佳的暫時後備,適用於主機內部仍啟動 ax-code serve
的情況。它不回傳 HTTP URL 或授權標頭,因此渲染程序程式碼可以對著 gRPC
外觀撰寫,之後再移到真正的原生 gRPC 傳輸,而不必改寫公開 API。
以 Node 為基礎的桌面主機可以用 @defai-digital/ax-code-sdk/grpc/node,從同一個原生橋接暴露真正的 HTTP/2 gRPC 端點。這是給特權主機處理程序,不是給渲染程序程式碼:
import { createAxCodeGrpcNativeBridgeFromHandlers, AX_CODE_GRPC_METHOD } from "@defai-digital/ax-code-sdk/grpc"
import { startAxCodeGrpcNodeHttp2Server } from "@defai-digital/ax-code-sdk/grpc/node"
const bridge = createAxCodeGrpcNativeBridgeFromHandlers({
unary: {
[AX_CODE_GRPC_METHOD.Health]() {
return { status: "SERVING" }
},
},
serverStream: {
[AX_CODE_GRPC_METHOD.SubscribeEvents](request) {
return runtime.subscribeEvents(request)
},
},
})
const server = await startAxCodeGrpcNodeHttp2Server({ bridge, host: "127.0.0.1" })
try {
// Native clients can generate from ax_code/v1/headless.proto and connect to server.url.
} finally {
await server.close()
}
PTY 串流被塑造成 gRPC 雙向串流。HTTP 橋接為了相容,把該串流轉接到既有的 WebSocket 路由;原生 GUI 主機應在其本機 gRPC、Unix socket 或具名管線傳輸上實作,而不是把 WebSocket 路由暴露給渲染程序程式碼。
當真正的 gRPC 傳輸可用時,把它提供給 createAxCodeGrpcClient({ transport })。高階用戶端維持不變。
安全態勢
對桌面應用程式,偏好這個順序:
- 當 GUI 是 TypeScript 且能安全載入執行環境時,使用處理程序內 SDK。
- 經由迴路、Unix socket 或具名管線的本機 gRPC/原生傳輸。
- 帶有產生的一次性 Basic Auth 憑證的 HTTP/SSE 無介面橋接。
- 不要透過網路 HTTP 暴露 AX Code。
gRPC HTTP 相容橋接與 SDK 管理的 HTTP 後端輔助程式只接受字面迴路端點。舊有
allowRemoteHttpBridge 與 allowNetworkBind 選項為了原始碼相容而保留,但不能繞過
僅限本機的原則。把 /doc 限制在迴路伺服器。
HTTP 相容橋接預設拒絕跨來源的 WebSocket 升級。只有當該瀏覽器來源屬於受信任的應用程式殼層時,才把來源加入明確的伺服器 CORS 允許清單。
不要把完整的 HTTP API、PTY WebSocket 或 OpenAPI 文件暴露給任意 WebView。若使用 WebView,請把它當作渲染程序,並透過原生主機以 gRPC/原生外觀路由特權操作。