跳转到内容

协议参考

这是 Pinix 的权威协议参考。它覆盖 Connect-RPC API、ProviderStream wire format 和 IPC v2 协议。

所有 Hub 通信都使用 Connect-RPC(HTTP/2、Protocol Buffers)。Hub 暴露以下 RPC:

RPC类型说明
InvokeUnary调用 Clip command
InvokeStreamServer stream以流式响应调用
ListClipsUnary列出所有已注册的 Clip
GetClipManifestUnary获取 Clip 的完整 manifest
GetClipWebUnary代理 Clip Web UI 资源
AddClipUnary从 Registry 安装 Clip
RemoveClipUnary卸载 Clip
ProviderStreamBidirectionalProvider 连接(注册 + invoke 转发)
RuntimeStreamBidirectionalRuntime 生命周期管理
GetLogsServer stream流式读取 Clip 日志
HubInfoUnaryHub metadata(version、mode)
DataReadUnary读取 Clip 数据
DataWriteUnary写入 Clip 数据

三种 token 类型:

Token作用域使用场景
Hub Token用户作用域(@usernameCLI、Console、Cloud Hub
Clip Token单个 ClipClip 到 Hub 的通信
Super Token完全访问本地开发

Token 通过 Authorization: Bearer <token> header 传递。

ProviderStream 是 Provider 和 Hub 之间的双向 stream。

type ProviderMessage =
| { type: "RegisterClips"; clips: ClipInfo[] }
| { type: "UnregisterClips"; aliases: string[] }
| { type: "InvokeResponse"; requestId: string; output: any }
| { type: "InvokeStreamChunk"; requestId: string; chunk: any }
| { type: "InvokeStreamEnd"; requestId: string }
| { type: "Heartbeat" }
| { type: "Log"; alias: string; level: string; message: string };
type HubMessage =
| { type: "ProviderHello"; sessionId: string }
| { type: "InvokeRequest"; requestId: string; alias: string; command: string; input: any }
| { type: "Heartbeat" }
| { type: "RuntimeInstall"; package: string; version: string }
| { type: "RuntimeUninstall"; alias: string };
  • 格式:UUID v4
  • 每次调用唯一
  • 用于匹配 InvokeRequestInvokeResponse
  • 必须包含在所有 response 和 streaming 消息中

Runtime 和 SDK Clip 之间通过 stdin/stdout 上的 NDJSON(newline-delimited JSON)通信。

{"type":"invoke","id":"req-1","command":"list","input":{}}

每行一个 JSON object,以 \n 结尾。

类型方向用途
invokeRuntime → Clip调用一个 command
responseClip → Runtimecommand 结果
streamClip → Runtime流式分块
stream_endClip → Runtimestream 结束
invoke_clipClip → Runtime跨 Clip 调用请求
invoke_clip_responseRuntime → Clip跨 Clip 结果
logClip → Runtime结构化日志消息
Runtime Clip (Bun process)
│ │
│─── {"type":"invoke","id":"r1", ───►│
│ "command":"list","input":{}} │
│ │
│◄── {"type":"response","id":"r1", ───│
│ "output":{"items":[...]}} │
│ │
Runtime Clip A Clip B
│ │ │
│── invoke ──────────►│ │
│ │ │
│ │── invoke_clip ────────►│ (via Runtime + Hub)
│ │ │
│ │◄─ invoke_clip_response─│
│ │ │
│◄── response ───────│ │
代码含义
NOT_FOUND找不到 Clip 或 command
INVALID_ARGUMENT缺少输入参数或输入参数无效
PERMISSION_DENIEDToken 没有访问权限
UNAVAILABLEClip 离线或 Provider 已断开
INTERNALClip handler 抛出错误
DEADLINE_EXCEEDED调用超时

错误以结构化 object 返回:

{
"error": {
"code": "NOT_FOUND",
"message": "Clip 'my-clip' not found"
}
}
Provider Hub
│ │
│── ProviderStream (connect) ──►│
│◄── ProviderHello ────────────│
│ │
│── RegisterClips ─────────────►│
│ [{package, alias, commands}]│
│ │
│ Hub adds to routing table │
│ │
Client Hub Provider Clip
│ │ │ │
│─Invoke─►│ │ │
│ │─InvokeReq►│ │
│ │ │─invoke──►│
│ │ │◄─response│
│ │◄InvokeRes─│ │
│◄─result─│ │ │
Client Hub Provider Clip
│ │ │ │
│─Stream─►│ │ │
│ │─InvokeReq►│ │
│ │ │─invoke──►│
│ │ │◄─stream──│ (chunk 1)
│ │◄StreamChk─│ │
│◄─chunk──│ │ │
│ │ │◄─stream──│ (chunk 2)
│ │◄StreamChk─│ │
│◄─chunk──│ │ │
│ │ │◄stream_end│
│ │◄StreamEnd─│ │
│◄─end────│ │ │