chore(i18n): refresh zh-CN translations
This commit is contained in:
parent
9eff8c6f08
commit
7cfcd2c5d3
@ -1,56 +1,53 @@
|
||||
---
|
||||
read_when:
|
||||
- 你正在构建一个与 OpenClaw 通信的外部应用、脚本、仪表板、CI 作业或 IDE 扩展
|
||||
- 你正在选择应用 SDK 还是插件 SDK
|
||||
- 你正在与 Gateway 网关的智能体运行、会话、事件、审批、模型或工具集成
|
||||
- 你正在应用 SDK 和插件 SDK 之间选择
|
||||
- 你正在集成 Gateway 网关智能体运行、会话、事件、审批、模型或工具
|
||||
sidebarTitle: App SDK
|
||||
summary: 面向外部应用、脚本、仪表盘、CI 作业和 IDE 扩展的公开 OpenClaw 应用 SDK
|
||||
summary: 面向外部应用、脚本、仪表盘、CI 作业和 IDE 扩展的公共 OpenClaw 应用 SDK
|
||||
title: OpenClaw 应用 SDK
|
||||
x-i18n:
|
||||
generated_at: "2026-04-30T01:03:29Z"
|
||||
generated_at: "2026-05-01T00:39:41Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 9c46454d172a25d329a796461982dc4307d3720a28df777eda8605996505e38c
|
||||
source_hash: e531e985ca82026b230b03f8df5ab908d66e2b608e09c46af2ec060b9def0c24
|
||||
source_path: concepts/openclaw-sdk.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
**OpenClaw 应用 SDK** 是 OpenClaw 进程外应用的公开客户端 API。当脚本、仪表板、CI 作业、IDE 扩展或其他外部应用需要连接到 Gateway 网关、启动智能体运行、流式传输事件、等待结果、取消工作或检查 Gateway 网关资源时,请使用 `@openclaw/sdk`。
|
||||
**OpenClaw 应用 SDK** 是面向 OpenClaw 进程外应用的公共客户端 API。当脚本、仪表板、CI 作业、IDE 扩展或其他外部应用需要连接到 Gateway 网关、启动智能体运行、流式传输事件、等待结果、取消工作或检查 Gateway 网关资源时,请使用 `@openclaw/sdk`。
|
||||
|
||||
<Note>
|
||||
应用 SDK 不同于[插件 SDK](/zh-CN/plugins/sdk-overview)。
|
||||
应用 SDK 不同于 [插件 SDK](/zh-CN/plugins/sdk-overview)。
|
||||
`@openclaw/sdk` 从 OpenClaw 外部与 Gateway 网关通信。
|
||||
`openclaw/plugin-sdk/*` 仅用于在 OpenClaw 内部运行并注册提供商、渠道、工具、钩子或受信任运行时的插件。
|
||||
`openclaw/plugin-sdk/*` 仅供在 OpenClaw 内部运行并注册提供商、渠道、工具、钩子或受信任运行时的插件使用。
|
||||
</Note>
|
||||
|
||||
## 今天发布的内容
|
||||
## 今日发布内容
|
||||
|
||||
`@openclaw/sdk` 包含:
|
||||
`@openclaw/sdk` 随附:
|
||||
|
||||
| 接口 | Status | 功能 |
|
||||
| ------------------------- | ---------- | ---------------------------------------------------------------------------- |
|
||||
| `OpenClaw` | 就绪 | 主客户端入口点。负责传输、连接、请求和事件。 |
|
||||
| `GatewayClientTransport` | 就绪 | 由 Gateway 网关客户端支持的 WebSocket 传输。 |
|
||||
| `oc.agents` | 就绪 | 列出、创建、更新、删除和获取智能体句柄。 |
|
||||
| `Agent.run()` | 就绪 | 启动 Gateway 网关 `agent` 运行并返回 `Run`。 |
|
||||
| `oc.runs` | 就绪 | 创建、获取、等待、取消和流式传输运行。 |
|
||||
| `Run.events()` | 就绪 | 流式传输标准化的逐运行事件,并为快速运行提供重放。 |
|
||||
| `Run.wait()` | 就绪 | 调用 `agent.wait` 并返回稳定的 `RunResult`。 |
|
||||
| `Run.cancel()` | 就绪 | 按运行 ID 调用 `sessions.abort`,可用时附带会话键。 |
|
||||
| `oc.sessions` | 就绪 | 创建、解析、发送到、修补、压缩和获取会话句柄。 |
|
||||
| `Session.send()` | 就绪 | 调用 `sessions.send` 并返回 `Run`。 |
|
||||
| `oc.models` | 就绪 | 调用 `models.list` 和当前的 `models.authStatus` Status RPC。 |
|
||||
| `oc.tools` | 部分支持 | 列出工具目录和有效工具;尚未接入直接工具调用。 |
|
||||
| `oc.approvals` | 就绪 | 通过 Gateway 网关审批 RPC 列出和解析 exec 审批。 |
|
||||
| `oc.rawEvents()` | 就绪 | 为高级使用者暴露原始 Gateway 网关事件。 |
|
||||
| `normalizeGatewayEvent()` | 就绪 | 将原始 Gateway 网关事件转换为稳定的 SDK 事件形态。 |
|
||||
| 接口 | Status | 作用 |
|
||||
| ------------------------- | --------- | ---------------------------------------------------------------------------- |
|
||||
| `OpenClaw` | 就绪 | 主客户端入口点。负责传输、连接、请求和事件。 |
|
||||
| `GatewayClientTransport` | 就绪 | 由 Gateway 网关客户端支持的 WebSocket 传输。 |
|
||||
| `oc.agents` | 就绪 | 列出、创建、更新、删除和获取智能体句柄。 |
|
||||
| `Agent.run()` | 就绪 | 启动 Gateway 网关 `agent` 运行并返回一个 `Run`。 |
|
||||
| `oc.runs` | 就绪 | 创建、获取、等待、取消和流式传输运行。 |
|
||||
| `Run.events()` | 就绪 | 流式传输规范化的按运行划分事件,并为快速运行提供重放。 |
|
||||
| `Run.wait()` | 就绪 | 调用 `agent.wait` 并返回稳定的 `RunResult`。 |
|
||||
| `Run.cancel()` | 就绪 | 按运行 ID 调用 `sessions.abort`,可用时会带上会话键。 |
|
||||
| `oc.sessions` | 就绪 | 创建、解析、发送到、修补、压缩和获取会话句柄。 |
|
||||
| `Session.send()` | 就绪 | 调用 `sessions.send` 并返回一个 `Run`。 |
|
||||
| `oc.models` | 就绪 | 调用 `models.list` 和当前的 `models.authStatus` 状态 RPC。 |
|
||||
| `oc.tools` | 部分支持 | 列出工具目录和有效工具;尚未接入直接工具调用。 |
|
||||
| `oc.artifacts` | 就绪 | 列出、获取和下载 Gateway 网关会话记录工件。 |
|
||||
| `oc.approvals` | 就绪 | 通过 Gateway 网关批准 RPC 列出和解析 exec 批准。 |
|
||||
| `oc.rawEvents()` | 就绪 | 为高级使用者公开原始 Gateway 网关事件。 |
|
||||
| `normalizeGatewayEvent()` | 就绪 | 将原始 Gateway 网关事件转换为稳定的 SDK 事件形状。 |
|
||||
|
||||
SDK 还导出这些接口使用的核心类型:
|
||||
`AgentRunParams`, `RunResult`, `RunStatus`, `OpenClawEvent`,
|
||||
`OpenClawEventType`, `GatewayEvent`, `OpenClawTransport`,
|
||||
`GatewayRequestOptions`, `SessionCreateParams`, `SessionSendParams`,
|
||||
`RuntimeSelection`, `EnvironmentSelection`, `WorkspaceSelection`,
|
||||
`ApprovalMode` 以及相关结果类型。
|
||||
`AgentRunParams`、`RunResult`、`RunStatus`、`OpenClawEvent`、`OpenClawEventType`、`GatewayEvent`、`OpenClawTransport`、`GatewayRequestOptions`、`SessionCreateParams`、`SessionSendParams`、`ArtifactSummary`、`ArtifactQuery`、`ArtifactsListResult`、`ArtifactsGetResult`、`ArtifactsDownloadResult`、`RuntimeSelection`、`EnvironmentSelection`、`WorkspaceSelection`、`ApprovalMode` 以及相关结果类型。
|
||||
|
||||
## 连接到 Gateway 网关
|
||||
|
||||
@ -68,9 +65,9 @@ const oc = new OpenClaw({
|
||||
await oc.connect();
|
||||
```
|
||||
|
||||
`new OpenClaw({ gateway: "ws://..." })` 等同于 `url`。构造函数接受 `gateway: "auto"` 选项,但自动 Gateway 网关设备发现尚不是独立的 SDK 功能;当应用本身还不知道如何发现 Gateway 网关时,请传入 `url`。
|
||||
`new OpenClaw({ gateway: "ws://..." })` 等同于 `url`。构造函数接受 `gateway: "auto"` 选项,但自动 Gateway 网关设备发现尚未成为独立的 SDK 功能;当应用尚不知道如何发现 Gateway 网关时,请传入 `url`。
|
||||
|
||||
对于测试,传入一个实现 `OpenClawTransport` 的对象:
|
||||
对于测试,请传入实现 `OpenClawTransport` 的对象:
|
||||
|
||||
```typescript
|
||||
const oc = new OpenClaw({
|
||||
@ -108,13 +105,13 @@ const result = await run.wait({ timeoutMs: 120_000 });
|
||||
console.log(result.status);
|
||||
```
|
||||
|
||||
像 `openai/gpt-5.5` 这样的提供商限定模型引用会拆分为 Gateway 网关的 `provider` 和 `model` 覆盖项。`timeoutMs` 在 SDK 中保持为毫秒,并会为 `agent` RPC 转换为 Gateway 网关超时秒数。
|
||||
像 `openai/gpt-5.5` 这样的带提供商限定的模型引用会拆分成 Gateway 网关的 `provider` 和 `model` 覆盖项。`timeoutMs` 在 SDK 中保持毫秒单位,并会为 `agent` RPC 转换为 Gateway 网关超时秒数。
|
||||
|
||||
`run.wait()` 使用 Gateway 网关的 `agent.wait` RPC。当等待截止时间到期但运行仍处于活动状态时,会返回 `status: "accepted"`,而不是假装运行本身已超时。运行时超时、中止的运行和取消的运行会标准化为 `timed_out` 或 `cancelled`。
|
||||
`run.wait()` 使用 Gateway 网关的 `agent.wait` RPC。如果等待截止时间到期时运行仍处于活动状态,则返回 `status: "accepted"`,而不是假装运行本身已超时。运行时超时、中止运行和取消运行会被规范化为 `timed_out` 或 `cancelled`。
|
||||
|
||||
## 创建和复用会话
|
||||
|
||||
当应用需要持久的转录状态时,请使用会话。
|
||||
当应用需要持久会话记录状态时,请使用会话。
|
||||
|
||||
```typescript
|
||||
const session = await oc.sessions.create({
|
||||
@ -126,7 +123,7 @@ const run = await session.send("Prepare release notes from the current diff.");
|
||||
await run.wait();
|
||||
```
|
||||
|
||||
`Session.send()` 调用 `sessions.send` 并返回 `Run`。会话句柄还支持:
|
||||
`Session.send()` 调用 `sessions.send` 并返回一个 `Run`。会话句柄还支持:
|
||||
|
||||
```typescript
|
||||
await session.abort(run.id);
|
||||
@ -136,7 +133,7 @@ await session.compact({ maxLines: 200 });
|
||||
|
||||
## 流式传输事件
|
||||
|
||||
SDK 会将原始 Gateway 网关事件标准化为稳定的 `OpenClawEvent` 信封:
|
||||
SDK 将原始 Gateway 网关事件规范化为稳定的 `OpenClawEvent` 信封:
|
||||
|
||||
```typescript
|
||||
type OpenClawEvent = {
|
||||
@ -156,30 +153,30 @@ type OpenClawEvent = {
|
||||
|
||||
常见事件类型包括:
|
||||
|
||||
| 事件类型 | 来源 Gateway 网关事件 |
|
||||
| --------------------- | ----------------------------------------- |
|
||||
| `run.started` | `agent` 生命周期开始 |
|
||||
| `run.completed` | `agent` 生命周期结束 |
|
||||
| `run.failed` | `agent` 生命周期错误 |
|
||||
| `run.cancelled` | 已中止/已取消的生命周期结束 |
|
||||
| `run.timed_out` | 超时生命周期结束 |
|
||||
| `assistant.delta` | Assistant 流式传输增量 |
|
||||
| `assistant.message` | Assistant 消息 |
|
||||
| `thinking.delta` | 思考或计划流 |
|
||||
| `tool.call.started` | 工具/项目/命令开始 |
|
||||
| `tool.call.delta` | 工具/项目/命令更新 |
|
||||
| `tool.call.completed` | 工具/项目/命令完成 |
|
||||
| `tool.call.failed` | 工具/项目/命令失败或被阻止状态 |
|
||||
| `approval.requested` | Exec 或插件审批请求 |
|
||||
| `approval.resolved` | Exec 或插件审批解析 |
|
||||
| `session.created` | `sessions.changed` 创建 |
|
||||
| `session.updated` | `sessions.changed` 更新 |
|
||||
| `session.compacted` | `sessions.changed` 压缩 |
|
||||
| `task.updated` | 任务更新事件 |
|
||||
| `artifact.updated` | 补丁流事件 |
|
||||
| `raw` | 尚未有稳定 SDK 映射的任意事件 |
|
||||
| 事件类型 | 来源 Gateway 网关事件 |
|
||||
| --------------------- | ------------------------------------------- |
|
||||
| `run.started` | `agent` 生命周期开始 |
|
||||
| `run.completed` | `agent` 生命周期结束 |
|
||||
| `run.failed` | `agent` 生命周期错误 |
|
||||
| `run.cancelled` | 已中止/已取消的生命周期结束 |
|
||||
| `run.timed_out` | 超时生命周期结束 |
|
||||
| `assistant.delta` | 助手流式增量 |
|
||||
| `assistant.message` | 助手消息 |
|
||||
| `thinking.delta` | 思考或计划流 |
|
||||
| `tool.call.started` | 工具/项目/命令开始 |
|
||||
| `tool.call.delta` | 工具/项目/命令更新 |
|
||||
| `tool.call.completed` | 工具/项目/命令完成 |
|
||||
| `tool.call.failed` | 工具/项目/命令失败或被阻止状态 |
|
||||
| `approval.requested` | Exec 或插件批准请求 |
|
||||
| `approval.resolved` | Exec 或插件批准解析 |
|
||||
| `session.created` | `sessions.changed` 创建 |
|
||||
| `session.updated` | `sessions.changed` 更新 |
|
||||
| `session.compacted` | `sessions.changed` 压缩 |
|
||||
| `task.updated` | 任务更新事件 |
|
||||
| `artifact.updated` | 补丁流事件 |
|
||||
| `raw` | 尚无稳定 SDK 映射的任何事件 |
|
||||
|
||||
`Run.events()` 会将事件筛选到一个运行 ID,并为快速运行重放已看到的事件。这意味着以下记录的流程是安全的:
|
||||
`Run.events()` 将事件过滤到单个运行 ID,并为快速运行重放已经看到的事件。这意味着以下记录的流程是安全的:
|
||||
|
||||
```typescript
|
||||
const run = await agent.run("Summarize the latest session.");
|
||||
@ -191,34 +188,47 @@ for await (const event of run.events()) {
|
||||
}
|
||||
```
|
||||
|
||||
对于应用范围的流,请使用 `oc.events()`。对于原始 Gateway 网关帧,请使用 `oc.rawEvents()`。
|
||||
对于应用级流,请使用 `oc.events()`。对于原始 Gateway 网关帧,请使用 `oc.rawEvents()`。
|
||||
|
||||
## 模型、工具和审批
|
||||
## 模型、工具、工件和批准
|
||||
|
||||
模型助手映射到当前 Gateway 网关方法:
|
||||
模型辅助方法会映射到当前 Gateway 网关方法:
|
||||
|
||||
```typescript
|
||||
await oc.models.list();
|
||||
await oc.models.status({ probe: false }); // calls models.authStatus
|
||||
```
|
||||
|
||||
工具助手暴露 Gateway 网关目录和有效工具视图:
|
||||
工具辅助方法会公开 Gateway 网关目录和有效工具视图:
|
||||
|
||||
```typescript
|
||||
await oc.tools.list();
|
||||
await oc.tools.effective({ sessionKey: "main" });
|
||||
```
|
||||
|
||||
审批助手使用 exec 审批 RPC:
|
||||
工件辅助方法会公开用于会话、运行或任务上下文的 Gateway 网关工件投影。每次调用都需要一个显式的 `sessionKey`、`runId` 或 `taskId` 作用域:
|
||||
|
||||
```typescript
|
||||
const { artifacts } = await oc.artifacts.list({ sessionKey: "main" });
|
||||
const first = artifacts[0];
|
||||
|
||||
if (first) {
|
||||
const { artifact } = await oc.artifacts.get(first.id, { sessionKey: "main" });
|
||||
const download = await oc.artifacts.download(artifact.id, { sessionKey: "main" });
|
||||
console.log(download.encoding, download.url);
|
||||
}
|
||||
```
|
||||
|
||||
批准辅助方法使用 exec 批准 RPC:
|
||||
|
||||
```typescript
|
||||
const approvals = await oc.approvals.list();
|
||||
await oc.approvals.respond("approval-id", { decision: "approve" });
|
||||
```
|
||||
|
||||
## 今天明确不支持的内容
|
||||
## 今日明确不支持
|
||||
|
||||
SDK 包含我们想要的产品模型名称,但不会静默假装 Gateway 网关 RPC 存在。这些调用目前会抛出明确的不支持错误:
|
||||
SDK 包含我们想要的产品模型名称,但不会静默假装 Gateway 网关 RPC 已存在。这些调用目前会抛出明确的不支持错误:
|
||||
|
||||
```typescript
|
||||
await oc.tasks.list();
|
||||
@ -227,21 +237,17 @@ await oc.tasks.cancel("task-id");
|
||||
|
||||
await oc.tools.invoke("tool-name", {});
|
||||
|
||||
await oc.artifacts.list();
|
||||
await oc.artifacts.get("artifact-id");
|
||||
await oc.artifacts.download("artifact-id");
|
||||
|
||||
await oc.environments.list();
|
||||
await oc.environments.create({});
|
||||
await oc.environments.status("environment-id");
|
||||
await oc.environments.delete("environment-id");
|
||||
```
|
||||
|
||||
逐运行的 `workspace`、`runtime`、`environment` 和 `approvals` 字段已按未来形态进行类型定义,但当前 Gateway 网关不支持在 `agent` RPC 上使用这些覆盖项。如果调用方传入它们,SDK 会在提交运行前抛出错误,避免工作意外使用默认工作区、运行时、环境或审批行为执行。
|
||||
按运行划分的 `workspace`、`runtime`、`environment` 和 `approvals` 字段已按未来形状进行类型定义,但当前 Gateway 网关不支持在 `agent` RPC 上使用这些覆盖项。如果调用方传入它们,SDK 会在提交运行之前抛出错误,避免工作意外使用默认工作区、运行时、环境或批准行为执行。
|
||||
|
||||
## 应用 SDK 与插件 SDK
|
||||
|
||||
当代码位于 OpenClaw 外部时,使用应用 SDK:
|
||||
当代码位于 OpenClaw 外部时,请使用应用 SDK:
|
||||
|
||||
- 启动或观察智能体运行的 Node 脚本
|
||||
- 调用 Gateway 网关的 CI 作业
|
||||
@ -250,15 +256,15 @@ await oc.environments.delete("environment-id");
|
||||
- 不需要成为渠道插件的外部桥接
|
||||
- 使用假的或真实 Gateway 网关传输的集成测试
|
||||
|
||||
当代码在 OpenClaw 内部运行时,使用插件 SDK:
|
||||
当代码在 OpenClaw 内部运行时,请使用插件 SDK:
|
||||
|
||||
- 提供商插件
|
||||
- 渠道插件
|
||||
- 工具或生命周期钩子
|
||||
- Agent harness plugins
|
||||
- 受信任运行时助手
|
||||
- 受信任运行时辅助方法
|
||||
|
||||
应用 SDK 代码应从 `@openclaw/sdk` 导入。插件代码应从记录在文档中的 `openclaw/plugin-sdk/*` 子路径导入。不要混用这两种契约。
|
||||
应用 SDK 代码应从 `@openclaw/sdk` 导入。插件代码应从记录在文档中的 `openclaw/plugin-sdk/*` 子路径导入。不要混用这两份契约。
|
||||
|
||||
## 相关文档
|
||||
|
||||
@ -268,5 +274,5 @@ await oc.environments.delete("environment-id");
|
||||
- [Agent Runtimes](/zh-CN/concepts/agent-runtimes)
|
||||
- [会话](/zh-CN/concepts/session)
|
||||
- [后台任务](/zh-CN/automation/tasks)
|
||||
- [ACP agents](/zh-CN/tools/acp-agents)
|
||||
- [ACP 智能体](/zh-CN/tools/acp-agents)
|
||||
- [插件 SDK 概览](/zh-CN/plugins/sdk-overview)
|
||||
|
||||
@ -2,25 +2,25 @@
|
||||
read_when:
|
||||
- 实现或更新 Gateway 网关 WS 客户端
|
||||
- 调试协议不匹配或连接失败
|
||||
- 重新生成协议模式/模型
|
||||
summary: Gateway 网关 WebSocket 协议:握手、帧、版本管理
|
||||
- 重新生成协议架构/模型
|
||||
summary: Gateway 网关 WebSocket 协议:握手、帧、版本控制
|
||||
title: Gateway 网关协议
|
||||
x-i18n:
|
||||
generated_at: "2026-04-29T23:55:19Z"
|
||||
generated_at: "2026-05-01T00:39:35Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: c0d922e9b4b778c333873e551498b905461f30f944e809555b45669ae2f5c404
|
||||
source_hash: a6da9ce755b941789ae6b9e866247c8bebb86e9a1530fb8cb258fb0650b24b8a
|
||||
source_path: gateway/protocol.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Gateway 网关 WS 协议是 OpenClaw 的**单一控制平面 + 节点传输协议**。所有客户端(CLI、网页 UI、macOS 应用、iOS/Android 节点、无头节点)都通过 WebSocket 连接,并在握手时声明它们的**角色** + **作用域**。
|
||||
Gateway 网关 WS 协议是 OpenClaw 的**单一控制平面 + 节点传输协议**。所有客户端(CLI、Web UI、macOS 应用、iOS/Android 节点、无头节点)都通过 WebSocket 连接,并在握手时声明其**角色** + **范围**。
|
||||
|
||||
## 传输
|
||||
## 传输协议
|
||||
|
||||
- WebSocket,文本帧使用 JSON 负载。
|
||||
- WebSocket,使用带 JSON 载荷的文本帧。
|
||||
- 第一帧**必须**是 `connect` 请求。
|
||||
- 连接前帧上限为 64 KiB。握手成功后,客户端应遵循 `hello-ok.policy.maxPayload` 和 `hello-ok.policy.maxBufferedBytes` 限制。启用诊断后,超大的入站帧和缓慢的出站缓冲区会在 Gateway 网关关闭或丢弃受影响的帧之前发出 `payload.large` 事件。这些事件会保留大小、限制、表面和安全原因代码。它们不会保留消息正文、附件内容、原始帧正文、令牌、Cookie 或密钥值。
|
||||
- 连接前帧限制为 64 KiB。握手成功后,客户端应遵循 `hello-ok.policy.maxPayload` 和 `hello-ok.policy.maxBufferedBytes` 限制。启用诊断后,过大的入站帧和缓慢的出站缓冲区会在 Gateway 网关关闭或丢弃受影响帧之前发出 `payload.large` 事件。这些事件会保留大小、限制、表面和安全原因代码。它们不会保留消息正文、附件内容、原始帧正文、令牌、Cookie 或密钥值。
|
||||
|
||||
## 握手(connect)
|
||||
|
||||
@ -95,11 +95,11 @@ Gateway 网关 → 客户端:
|
||||
}
|
||||
```
|
||||
|
||||
当 Gateway 网关仍在完成启动 sidecar 时,`connect` 请求可能会返回可重试的 `UNAVAILABLE` 错误,其中 `details.reason` 设置为 `"startup-sidecars"`,并带有 `retryAfterMs`。客户端应在整体连接预算内重试该响应,而不是将其作为终止性的握手失败呈现。
|
||||
当 Gateway 网关仍在完成启动 sidecar 时,`connect` 请求可能会返回可重试的 `UNAVAILABLE` 错误,其中 `details.reason` 设为 `"startup-sidecars"`,并带有 `retryAfterMs`。客户端应在其总体连接预算内重试该响应,而不是将其呈现为终止性的握手失败。
|
||||
|
||||
`server`、`features`、`snapshot` 和 `policy` 都是 schema(`src/gateway/protocol/schema/frames.ts`)要求的字段。`auth` 也是必填字段,并报告协商后的角色/作用域。`canvasHostUrl` 是可选字段。
|
||||
`server`、`features`、`snapshot` 和 `policy` 均为 schema(`src/gateway/protocol/schema/frames.ts`)要求的字段。`auth` 也是必需字段,并报告协商后的角色/范围。`canvasHostUrl` 是可选字段。
|
||||
|
||||
未签发设备令牌时,`hello-ok.auth` 会报告协商后的权限,不包含令牌字段:
|
||||
未签发设备令牌时,`hello-ok.auth` 会报告协商后的权限,且不包含令牌字段:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -110,7 +110,7 @@ Gateway 网关 → 客户端:
|
||||
}
|
||||
```
|
||||
|
||||
受信任的同进程后端客户端(`client.id: "gateway-client"`、`client.mode: "backend"`)在使用共享 Gateway 网关令牌/密码进行身份验证时,可在直接 loopback 连接上省略 `device`。此路径仅供内部控制平面 RPC 使用,并避免过期的 CLI/设备配对基线阻塞本地后端工作,例如子智能体会话更新。远程客户端、浏览器源客户端、节点客户端以及显式设备令牌/设备身份客户端仍使用正常的配对和作用域升级检查。
|
||||
受信任的同进程后端客户端(`client.id: "gateway-client"`,`client.mode: "backend"`)在使用共享 Gateway 网关令牌/密码认证时,可以在直接 loopback 连接上省略 `device`。此路径保留给内部控制平面 RPC,并防止过期的 CLI/设备配对基线阻塞本地后端工作,例如子智能体会话更新。远程客户端、浏览器来源客户端、节点客户端,以及显式设备令牌/设备身份客户端,仍使用正常的配对和范围升级检查。
|
||||
|
||||
签发设备令牌时,`hello-ok` 还会包含:
|
||||
|
||||
@ -124,7 +124,7 @@ Gateway 网关 → 客户端:
|
||||
}
|
||||
```
|
||||
|
||||
在受信任的 bootstrap 交接期间,`hello-ok.auth` 还可能在 `deviceTokens` 中包含其他有边界的角色条目:
|
||||
在受信任的引导交接期间,`hello-ok.auth` 也可能在 `deviceTokens` 中包含额外的有界角色条目:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -143,7 +143,7 @@ Gateway 网关 → 客户端:
|
||||
}
|
||||
```
|
||||
|
||||
对于内置的节点/operator bootstrap 流,主节点令牌保持 `scopes: []`,任何交接的 operator 令牌都限制在 bootstrap operator 允许列表(`operator.approvals`、`operator.read`、`operator.talk.secrets`、`operator.write`)内。Bootstrap 作用域检查保持角色前缀:operator 条目只满足 operator 请求,非 operator 角色仍需要其自身角色前缀下的作用域。
|
||||
对于内置的节点/operator 引导流程,主节点令牌保持 `scopes: []`,并且任何交接的 operator 令牌都保持限制在引导 operator 允许列表内(`operator.approvals`、`operator.read`、`operator.talk.secrets`、`operator.write`)。引导范围检查仍保持角色前缀:operator 条目仅满足 operator 请求,非 operator 角色仍需要其自身角色前缀下的范围。
|
||||
|
||||
### 节点示例
|
||||
|
||||
@ -188,16 +188,16 @@ Gateway 网关 → 客户端:
|
||||
|
||||
有副作用的方法需要**幂等键**(见 schema)。
|
||||
|
||||
## 角色 + 作用域
|
||||
## 角色 + 范围
|
||||
|
||||
### 角色
|
||||
|
||||
- `operator` = 控制平面客户端(CLI/UI/自动化)。
|
||||
- `node` = 能力宿主(camera/screen/canvas/system.run)。
|
||||
|
||||
### 作用域(operator)
|
||||
### 范围(operator)
|
||||
|
||||
常用作用域:
|
||||
常见范围:
|
||||
|
||||
- `operator.read`
|
||||
- `operator.write`
|
||||
@ -208,11 +208,11 @@ Gateway 网关 → 客户端:
|
||||
|
||||
带有 `includeSecrets: true` 的 `talk.config` 需要 `operator.talk.secrets`(或 `operator.admin`)。
|
||||
|
||||
插件注册的 Gateway 网关 RPC 方法可以请求自己的 operator 作用域,但保留的核心 admin 前缀(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)始终解析为 `operator.admin`。
|
||||
插件注册的 Gateway 网关 RPC 方法可以请求自己的 operator 范围,但保留的核心管理员前缀(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)始终解析为 `operator.admin`。
|
||||
|
||||
方法作用域只是第一道门。某些通过 `chat.send` 到达的斜杠命令会在其上应用更严格的命令级检查。例如,持久化的 `/config set` 和 `/config unset` 写入需要 `operator.admin`。
|
||||
方法范围只是第一道门槛。某些通过 `chat.send` 触达的斜杠命令还会在此之上应用更严格的命令级检查。例如,持久化的 `/config set` 和 `/config unset` 写入需要 `operator.admin`。
|
||||
|
||||
`node.pair.approve` 除基础方法作用域外,还在批准时增加额外的作用域检查:
|
||||
`node.pair.approve` 在基础方法范围之上,还会在批准时进行额外范围检查:
|
||||
|
||||
- 无命令请求:`operator.pairing`
|
||||
- 带有非 exec 节点命令的请求:`operator.pairing` + `operator.write`
|
||||
@ -222,21 +222,21 @@ Gateway 网关 → 客户端:
|
||||
|
||||
节点在连接时声明能力声明:
|
||||
|
||||
- `caps`:高层能力类别。
|
||||
- `commands`:用于 invoke 的命令允许列表。
|
||||
- `caps`:高级能力类别。
|
||||
- `commands`:invoke 的命令允许列表。
|
||||
- `permissions`:细粒度开关(例如 `screen.record`、`camera.capture`)。
|
||||
|
||||
Gateway 网关将这些视为**声明**,并强制执行服务器端允许列表。
|
||||
Gateway 网关将这些视为**声明**,并强制执行服务端允许列表。
|
||||
|
||||
## 在线状态
|
||||
|
||||
- `system-presence` 返回以设备身份为键的条目。
|
||||
- 在线状态条目包含 `deviceId`、`roles` 和 `scopes`,因此 UI 可以为每个设备显示一行,即使它同时以 **operator** 和 **node** 身份连接。
|
||||
- `node.list` 包含可选的 `lastSeenAtMs` 和 `lastSeenReason` 字段。已连接节点会将其当前连接时间报告为 `lastSeenAtMs`,原因为 `connect`;当受信任的节点事件更新其配对元数据时,已配对节点也可以报告持久的后台在线状态。
|
||||
- `system-presence` 返回按设备身份键控的条目。
|
||||
- 在线状态条目包含 `deviceId`、`roles` 和 `scopes`,因此即使设备同时作为 **operator** 和**节点**连接,UI 也能为每个设备显示单行。
|
||||
- `node.list` 包含可选的 `lastSeenAtMs` 和 `lastSeenReason` 字段。已连接节点会将其当前连接时间报告为 `lastSeenAtMs`,原因为 `connect`;当受信任的节点事件更新其配对元数据时,已配对节点也可以报告持久后台在线状态。
|
||||
|
||||
### 节点后台存活事件
|
||||
|
||||
节点可以调用带有 `event: "node.presence.alive"` 的 `node.event`,以记录已配对节点在后台唤醒期间处于存活状态,而不将其标记为已连接。
|
||||
节点可以调用 `node.event` 并传入 `event: "node.presence.alive"`,以记录已配对节点在后台唤醒期间处于存活状态,但不将其标记为已连接。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -245,7 +245,7 @@ Gateway 网关将这些视为**声明**,并强制执行服务器端允许列
|
||||
}
|
||||
```
|
||||
|
||||
`trigger` 是封闭枚举:`background`、`silent_push`、`bg_app_refresh`、`significant_location`、`manual` 或 `connect`。未知的 trigger 字符串会在持久化前由 Gateway 网关规范化为 `background`。该事件仅对经过身份验证的节点设备会话持久化;无设备或未配对会话会返回 `handled: false`。
|
||||
`trigger` 是封闭枚举:`background`、`silent_push`、`bg_app_refresh`、`significant_location`、`manual` 或 `connect`。未知触发器字符串会在持久化前由 Gateway 网关规范化为 `background`。该事件仅对经过认证的节点设备会话持久化;无设备或未配对会话会返回 `handled: false`。
|
||||
|
||||
成功的 Gateway 网关会返回结构化结果:
|
||||
|
||||
@ -258,53 +258,53 @@ Gateway 网关将这些视为**声明**,并强制执行服务器端允许列
|
||||
}
|
||||
```
|
||||
|
||||
较旧的 Gateway 网关仍可能为 `node.event` 返回 `{ "ok": true }`;客户端应将其视为已确认的 RPC,而不是持久在线状态的持久化。
|
||||
较旧的 Gateway 网关仍可能对 `node.event` 返回 `{ "ok": true }`;客户端应将其视为已确认的 RPC,而不是持久在线状态已保存。
|
||||
|
||||
## 广播事件作用域限定
|
||||
## 广播事件范围控制
|
||||
|
||||
服务器推送的 WebSocket 广播事件会经过作用域门控,因此配对作用域或仅节点会话不会被动接收会话内容。
|
||||
服务端推送的 WebSocket 广播事件受范围门控,因此仅具备配对范围或仅节点会话不会被动接收会话内容。
|
||||
|
||||
- **聊天、智能体和工具结果帧**(包括流式 `agent` 事件和工具调用结果)至少需要 `operator.read`。没有 `operator.read` 的会话会完全跳过这些帧。
|
||||
- **插件定义的 `plugin.*` 广播**会根据插件注册方式,以 `operator.write` 或 `operator.admin` 作为门控。
|
||||
- **Status 和传输事件**(`heartbeat`、`presence`、`tick`、连接/断开生命周期等)保持不受限制,因此每个经过身份验证的会话都可以观察传输健康状况。
|
||||
- **未知广播事件族**默认会经过作用域门控(故障关闭),除非注册的处理程序显式放宽它们。
|
||||
- **插件定义的 `plugin.*` 广播**会根据插件注册方式,受 `operator.write` 或 `operator.admin` 门控。
|
||||
- **Status 和传输事件**(`heartbeat`、`presence`、`tick`、连接/断开生命周期等)保持不受限制,因此每个已认证会话都可以观察传输健康状态。
|
||||
- **未知广播事件族**默认受范围门控(失败关闭),除非已注册的处理程序显式放宽它们。
|
||||
|
||||
每个客户端连接都会保留自己的每客户端序列号,因此即使不同客户端看到事件流中不同的作用域过滤子集,广播也会在该套接字上保持单调顺序。
|
||||
每个客户端连接都会维护自己的按客户端序列号,因此即使不同客户端看到不同的按范围过滤后的事件流子集,广播也会在该套接字上保持单调顺序。
|
||||
|
||||
## 常见 RPC 方法族
|
||||
|
||||
公共 WS 表面比上面的握手/身份验证示例更广。这不是生成的转储 — `hello-ok.features.methods` 是一个保守的发现列表,由 `src/gateway/server-methods-list.ts` 加上已加载的插件/渠道方法导出构建而来。请将其视为功能发现,而不是 `src/gateway/server-methods/*.ts` 的完整枚举。
|
||||
公共 WS 表面比上面的握手/认证示例更广。这不是生成的转储 — `hello-ok.features.methods` 是从 `src/gateway/server-methods-list.ts` 以及已加载插件/渠道方法导出构建的保守发现列表。请将其视为功能发现,而不是 `src/gateway/server-methods/*.ts` 的完整枚举。
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="系统和身份">
|
||||
<Accordion title="System and identity">
|
||||
- `health` 返回缓存的或新探测的 Gateway 网关健康快照。
|
||||
- `diagnostics.stability` 返回最近的有界诊断稳定性记录器。它保留事件名称、计数、字节大小、内存读数、队列/会话状态、渠道/插件名称和会话 ID 等运营元数据。它不会保留聊天文本、webhook 正文、工具输出、原始请求或响应正文、令牌、Cookie 或密钥值。需要 operator 读取作用域。
|
||||
- `status` 返回 `/status` 风格的 Gateway 网关摘要;敏感字段仅包含在 admin 作用域的 operator 客户端中。
|
||||
- `gateway.identity.get` 返回 relay 和配对流程使用的 Gateway 网关设备身份。
|
||||
- `system-presence` 返回当前已连接 operator/node 设备的在线状态快照。
|
||||
- `system-event` 追加系统事件,并可更新/广播在线状态上下文。
|
||||
- `diagnostics.stability` 返回最近的有界诊断稳定性记录器。它保留事件名称、计数、字节大小、内存读数、队列/会话状态、渠道/插件名称和会话 ID 等操作元数据。它不会保留聊天文本、webhook 正文、工具输出、原始请求或响应正文、令牌、Cookie 或密钥值。需要 operator 读取范围。
|
||||
- `status` 返回 `/status` 风格的 Gateway 网关摘要;敏感字段仅对管理员范围的 operator 客户端包含。
|
||||
- `gateway.identity.get` 返回中继和配对流程使用的 Gateway 网关设备身份。
|
||||
- `system-presence` 返回已连接 operator/节点设备的当前在线状态快照。
|
||||
- `system-event` 追加系统事件,并可以更新/广播在线状态上下文。
|
||||
- `last-heartbeat` 返回最新持久化的 Heartbeat 事件。
|
||||
- `set-heartbeats` 切换 Gateway 网关上的 Heartbeat 处理。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="模型和用量">
|
||||
- `models.list` 返回运行时允许的模型目录。传入 `{ "view": "configured" }` 可获取适合选择器大小的已配置模型(先是 `agents.defaults.models`,然后是 `models.providers.*.models`),或传入 `{ "view": "all" }` 获取完整目录。
|
||||
<Accordion title="Models 和用量">
|
||||
- `models.list` 返回运行时允许的模型目录。传入 `{ "view": "configured" }` 可获取适合选择器显示的已配置模型(先是 `agents.defaults.models`,然后是 `models.providers.*.models`),或传入 `{ "view": "all" }` 获取完整目录。
|
||||
- `usage.status` 返回提供商用量窗口/剩余额度摘要。
|
||||
- `usage.cost` 返回某个日期范围内的聚合成本用量摘要。
|
||||
- `doctor.memory.status` 返回当前默认智能体工作区的向量记忆/缓存嵌入就绪状态。仅当调用方明确需要实时嵌入提供商 ping 时,才传入 `{ "probe": true }` 或 `{ "deep": true }`。
|
||||
- `doctor.memory.remHarness` 为远程控制平面客户端返回有界、只读的 REM harness 预览。它可以包含工作区路径、记忆片段、渲染后的有依据 Markdown,以及深度提升候选项,因此调用方需要 `operator.read`。
|
||||
- `sessions.usage` 返回每个会话的用量摘要。
|
||||
- `doctor.memory.status` 返回当前默认 Agent 工作区的向量记忆 / 缓存嵌入就绪状态。仅当调用方明确想要实时 ping 嵌入提供商时,才传入 `{ "probe": true }` 或 `{ "deep": true }`。
|
||||
- `doctor.memory.remHarness` 为远程控制平面客户端返回有界、只读的 REM harness 预览。它可以包含工作区路径、记忆片段、渲染后的 grounded markdown,以及深度提升候选项,因此调用方需要 `operator.read`。
|
||||
- `sessions.usage` 返回按会话划分的用量摘要。
|
||||
- `sessions.usage.timeseries` 返回一个会话的时间序列用量。
|
||||
- `sessions.usage.logs` 返回一个会话的用量日志条目。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="渠道和登录辅助方法">
|
||||
- `channels.status` 返回内置 + 打包渠道/插件的 Status 摘要。
|
||||
- `channels.logout` 会在渠道支持登出的情况下登出指定渠道/账户。
|
||||
- `web.login.start` 为当前支持 QR 的 Web 渠道提供商启动 QR/Web 登录流程。
|
||||
- `web.login.wait` 等待该 QR/Web 登录流程完成,并在成功后启动渠道。
|
||||
<Accordion title="渠道和登录辅助工具">
|
||||
- `channels.status` 返回内置 + 捆绑渠道/插件 Status 摘要。
|
||||
- `channels.logout` 会在渠道支持登出的情况下登出特定渠道/账号。
|
||||
- `web.login.start` 为当前支持二维码的 Web 渠道提供商启动二维码/Web 登录流程。
|
||||
- `web.login.wait` 等待该二维码/Web 登录流程完成,并在成功后启动渠道。
|
||||
- `push.test` 向已注册的 iOS 节点发送测试 APNs 推送。
|
||||
- `voicewake.get` 返回已存储的唤醒词触发器。
|
||||
- `voicewake.set` 更新唤醒词触发器并广播变更。
|
||||
@ -312,8 +312,8 @@ Gateway 网关将这些视为**声明**,并强制执行服务器端允许列
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="消息和日志">
|
||||
- `send` 是直接出站投递 RPC,用于在聊天运行器之外按渠道/账户/线程目标发送。
|
||||
- `logs.tail` 返回已配置的 Gateway 网关文件日志尾部内容,带 cursor/limit 和最大字节控制。
|
||||
- `send` 是用于在聊天运行器之外按渠道/账号/线程目标发送消息的直接出站投递 RPC。
|
||||
- `logs.tail` 返回已配置 Gateway 网关文件日志尾部,带有游标/限制和最大字节控制。
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -323,7 +323,7 @@ Gateway 网关将这些视为**声明**,并强制执行服务器端允许列
|
||||
- `talk.speak` 通过当前 Talk 语音提供商合成语音。
|
||||
- `tts.status` 返回 TTS 启用状态、当前提供商、回退提供商,以及提供商配置状态。
|
||||
- `tts.providers` 返回可见的 TTS 提供商清单。
|
||||
- `tts.enable` 和 `tts.disable` 切换 TTS 偏好设置状态。
|
||||
- `tts.enable` 和 `tts.disable` 切换 TTS 首选项状态。
|
||||
- `tts.setProvider` 更新首选 TTS 提供商。
|
||||
- `tts.convert` 执行一次性文本转语音转换。
|
||||
|
||||
@ -331,68 +331,69 @@ Gateway 网关将这些视为**声明**,并强制执行服务器端允许列
|
||||
|
||||
<Accordion title="密钥、配置、更新和向导">
|
||||
- `secrets.reload` 重新解析活动 SecretRefs,并且仅在完全成功时替换运行时密钥状态。
|
||||
- `secrets.resolve` 解析特定命令/目标集合的命令目标密钥分配。
|
||||
- `secrets.resolve` 为特定命令/目标集合解析面向命令目标的密钥分配。
|
||||
- `config.get` 返回当前配置快照和哈希。
|
||||
- `config.set` 写入经过验证的配置载荷。
|
||||
- `config.patch` 合并部分配置更新。
|
||||
- `config.apply` 验证并替换完整配置载荷。
|
||||
- `config.schema` 返回 Control UI 和 CLI 工具使用的实时配置 schema 载荷:schema、`uiHints`、版本和生成元数据;当运行时可以加载插件 + 渠道 schema 元数据时,也会包含这些元数据。该 schema 包含字段 `title` / `description` 元数据,这些元数据派生自 UI 使用的相同标签和帮助文本;当存在匹配的字段文档时,也包含嵌套对象、通配符、数组项,以及 `anyOf` / `oneOf` / `allOf` 组合分支。
|
||||
- `config.schema.lookup` 为一个配置路径返回路径范围的查找载荷:规范化路径、浅层 schema 节点、匹配的提示 + `hintPath`,以及供 UI/CLI 下钻使用的直接子项摘要。查找 schema 节点会保留面向用户的文档和常见验证字段(`title`、`description`、`type`、`enum`、`const`、`format`、`pattern`、数字/字符串/数组/对象边界,以及 `additionalProperties`、`deprecated`、`readOnly`、`writeOnly` 等标志)。子项摘要会公开 `key`、规范化后的 `path`、`type`、`required`、`hasChildren`,以及匹配的 `hint` / `hintPath`。
|
||||
- `config.schema` 返回 Control UI 和 CLI 工具使用的实时配置 schema 载荷:schema、`uiHints`、版本和生成元数据;当运行时能够加载时,还包括插件 + 渠道 schema 元数据。该 schema 包含字段 `title` / `description` 元数据,这些元数据来自 UI 使用的相同标签和帮助文本;当存在匹配的字段文档时,也包括嵌套对象、通配符、数组项,以及 `anyOf` / `oneOf` / `allOf` 组合分支。
|
||||
- `config.schema.lookup` 为一个配置路径返回限定路径的查询载荷:规范化路径、浅层 schema 节点、匹配的提示 + `hintPath`,以及用于 UI/CLI 下钻的直接子项摘要。查询 schema 节点会保留面向用户的文档和常见验证字段(`title`、`description`、`type`、`enum`、`const`、`format`、`pattern`、数字/字符串/数组/对象边界,以及 `additionalProperties`、`deprecated`、`readOnly`、`writeOnly` 等标志)。子项摘要公开 `key`、规范化的 `path`、`type`、`required`、`hasChildren`,以及匹配的 `hint` / `hintPath`。
|
||||
- `update.run` 运行 Gateway 网关更新流程,并且仅在更新本身成功时安排重启。
|
||||
- `update.status` 返回最新缓存的更新重启哨兵;可用时包括重启后的运行版本。
|
||||
- `update.status` 返回最新缓存的更新重启哨兵;可用时包含重启后正在运行的版本。
|
||||
- `wizard.start`、`wizard.next`、`wizard.status` 和 `wizard.cancel` 通过 WS RPC 暴露新手引导向导。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="智能体和工作区辅助方法">
|
||||
<Accordion title="Agent 和工作区辅助工具">
|
||||
- `agents.list` 返回已配置的智能体条目,包括生效模型和运行时元数据。
|
||||
- `agents.create`、`agents.update` 和 `agents.delete` 管理智能体记录和工作区接线。
|
||||
- `agents.files.list`、`agents.files.get` 和 `agents.files.set` 管理为智能体暴露的引导工作区文件。
|
||||
- `agents.create`、`agents.update` 和 `agents.delete` 管理智能体记录和工作区连线。
|
||||
- `agents.files.list`、`agents.files.get` 和 `agents.files.set` 管理为某个智能体暴露的启动工作区文件。
|
||||
- `artifacts.list`、`artifacts.get` 和 `artifacts.download` 为显式 `sessionKey`、`runId` 或 `taskId` 作用域暴露从转录记录派生的工件摘要和下载。运行和任务查询会在服务端解析所属会话,并且只返回来源匹配的转录媒体;不安全或本地 URL 来源会返回不支持的下载,而不是在服务端抓取。
|
||||
- `agent.identity.get` 返回某个智能体或会话的生效助手身份。
|
||||
- `agent.wait` 等待运行完成,并在可用时返回终态快照。
|
||||
- `agent.wait` 等待一次运行完成,并在可用时返回终态快照。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="会话控制">
|
||||
- `sessions.list` 返回当前会话索引;当配置了智能体运行时后端时,包括每行的 `agentRuntime` 元数据。
|
||||
- `sessions.list` 返回当前会话索引;配置了智能体运行时后端时,包含每行的 `agentRuntime` 元数据。
|
||||
- `sessions.subscribe` 和 `sessions.unsubscribe` 为当前 WS 客户端切换会话变更事件订阅。
|
||||
- `sessions.messages.subscribe` 和 `sessions.messages.unsubscribe` 为一个会话切换转录/消息事件订阅。
|
||||
- `sessions.preview` 返回特定会话键的有界转录预览。
|
||||
- `sessions.resolve` 解析或规范化会话目标。
|
||||
- `sessions.messages.subscribe` 和 `sessions.messages.unsubscribe` 为一个会话切换转录记录/消息事件订阅。
|
||||
- `sessions.preview` 返回特定会话键的有界转录记录预览。
|
||||
- `sessions.resolve` 解析或规范化一个会话目标。
|
||||
- `sessions.create` 创建新的会话条目。
|
||||
- `sessions.send` 向现有会话发送消息。
|
||||
- `sessions.steer` 是活动会话的中断并引导变体。
|
||||
- `sessions.abort` 中止某个会话的活动工作。调用方可以传入 `key` 加可选的 `runId`,也可以仅为 Gateway 网关能解析到会话的活动运行传入 `runId`。
|
||||
- `sessions.steer` 是用于活动会话的中断并引导变体。
|
||||
- `sessions.abort` 中止某个会话的活动工作。调用方可以传入 `key` 加可选 `runId`,或对 Gateway 网关可解析到会话的活动运行仅传入 `runId`。
|
||||
- `sessions.patch` 更新会话元数据/覆盖项,并报告解析后的规范模型以及生效的 `agentRuntime`。
|
||||
- `sessions.reset`、`sessions.delete` 和 `sessions.compact` 执行会话维护。
|
||||
- `sessions.get` 返回完整的已存储会话行。
|
||||
- 聊天执行仍使用 `chat.history`、`chat.send`、`chat.abort` 和 `chat.inject`。`chat.history` 会为 UI 客户端做显示规范化:从可见文本中剥离内联指令标签,剥离纯文本工具调用 XML 载荷(包括 `<tool_call>...</tool_call>`、`<function_call>...</function_call>`、`<tool_calls>...</tool_calls>`、`<function_calls>...</function_calls>` 和被截断的工具调用块)以及泄漏的 ASCII/全角模型控制 token,省略精确为 `NO_REPLY` / `no_reply` 等纯静默 token 的助手行,并且可用占位符替换过大的行。
|
||||
- `sessions.get` 返回完整存储的会话行。
|
||||
- 聊天执行仍使用 `chat.history`、`chat.send`、`chat.abort` 和 `chat.inject`。`chat.history` 已为 UI 客户端做显示规范化:内联指令标签会从可见文本中剥离,纯文本工具调用 XML 载荷(包括 `<tool_call>...</tool_call>`、`<function_call>...</function_call>`、`<tool_calls>...</tool_calls>`、`<function_calls>...</function_calls>` 和截断的工具调用块)以及泄漏的 ASCII/全角模型控制 token 会被剥离,像精确的 `NO_REPLY` / `no_reply` 这类纯静默 token 助手行会被省略,超大行可被替换为占位符。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="设备配对和设备 token">
|
||||
- `device.pair.list` 返回待处理和已批准的配对设备。
|
||||
- `device.pair.approve`、`device.pair.reject` 和 `device.pair.remove` 管理设备配对记录。
|
||||
- `device.token.rotate` 在其已批准角色和调用方 scope 边界内轮换配对设备 token。
|
||||
- `device.token.revoke` 在其已批准角色和调用方 scope 边界内撤销配对设备 token。
|
||||
- `device.token.rotate` 在已批准角色和调用方作用域边界内轮换配对设备 token。
|
||||
- `device.token.revoke` 在已批准角色和调用方作用域边界内撤销配对设备 token。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="节点配对、调用和待处理工作">
|
||||
- `node.pair.request`、`node.pair.list`、`node.pair.approve`、`node.pair.reject`、`node.pair.remove` 和 `node.pair.verify` 覆盖节点配对和引导验证。
|
||||
- `node.pair.request`、`node.pair.list`、`node.pair.approve`、`node.pair.reject`、`node.pair.remove` 和 `node.pair.verify` 覆盖节点配对和启动验证。
|
||||
- `node.list` 和 `node.describe` 返回已知/已连接节点状态。
|
||||
- `node.rename` 更新配对节点标签。
|
||||
- `node.invoke` 将命令转发到已连接节点。
|
||||
- `node.invoke.result` 返回调用请求的结果。
|
||||
- `node.event` 将节点来源事件带回 Gateway 网关。
|
||||
- `node.canvas.capability.refresh` 刷新限定范围的画布能力 token。
|
||||
- `node.event` 将节点产生的事件带回 Gateway 网关。
|
||||
- `node.canvas.capability.refresh` 刷新限定作用域的画布能力 token。
|
||||
- `node.pending.pull` 和 `node.pending.ack` 是已连接节点队列 API。
|
||||
- `node.pending.enqueue` 和 `node.pending.drain` 管理离线/断开连接节点的持久待处理工作。
|
||||
- `node.pending.enqueue` 和 `node.pending.drain` 管理离线/断开连接节点的持久化待处理工作。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="审批系列">
|
||||
- `exec.approval.request`、`exec.approval.get`、`exec.approval.list` 和 `exec.approval.resolve` 覆盖一次性 exec 审批请求以及待处理审批查找/重放。
|
||||
- `exec.approval.request`、`exec.approval.get`、`exec.approval.list` 和 `exec.approval.resolve` 覆盖一次性 exec 审批请求以及待处理审批查询/重放。
|
||||
- `exec.approval.waitDecision` 等待一个待处理 exec 审批,并返回最终决策(超时时返回 `null`)。
|
||||
- `exec.approvals.get` 和 `exec.approvals.set` 管理 Gateway 网关 exec 审批策略快照。
|
||||
- `exec.approvals.node.get` 和 `exec.approvals.node.set` 通过节点中继命令管理节点本地 exec 审批策略。
|
||||
@ -401,7 +402,7 @@ Gateway 网关将这些视为**声明**,并强制执行服务器端允许列
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="自动化、Skills 和工具">
|
||||
- 自动化:`wake` 安排一次立即或下一次 Heartbeat 的唤醒文本注入;`cron.list`、`cron.status`、`cron.add`、`cron.update`、`cron.remove`、`cron.run`、`cron.runs` 管理定时工作。
|
||||
- 自动化:`wake` 安排立即或下一次 Heartbeat 唤醒文本注入;`cron.list`、`cron.status`、`cron.add`、`cron.update`、`cron.remove`、`cron.run`、`cron.runs` 管理定时工作。
|
||||
- Skills 和工具:`commands.list`、`skills.*`、`tools.catalog`、`tools.effective`。
|
||||
|
||||
</Accordion>
|
||||
@ -409,12 +410,12 @@ Gateway 网关将这些视为**声明**,并强制执行服务器端允许列
|
||||
|
||||
### 常见事件系列
|
||||
|
||||
- `chat`:UI 聊天更新,例如 `chat.inject` 和其他仅转录的聊天
|
||||
- `chat`:UI 聊天更新,例如 `chat.inject` 和其他仅转录记录的聊天
|
||||
事件。
|
||||
- `session.message` 和 `session.tool`:已订阅会话的转录/事件流更新。
|
||||
- `sessions.changed`:会话索引或元数据已更改。
|
||||
- `session.message` 和 `session.tool`:已订阅会话的转录记录/事件流更新。
|
||||
- `sessions.changed`:会话索引或元数据已变更。
|
||||
- `presence`:系统在线状态快照更新。
|
||||
- `tick`:周期性 keepalive / liveness 事件。
|
||||
- `tick`:周期性保活 / 存活事件。
|
||||
- `health`:Gateway 网关健康快照更新。
|
||||
- `heartbeat`:Heartbeat 事件流更新。
|
||||
- `cron`:cron 运行/作业变更事件。
|
||||
@ -422,7 +423,7 @@ Gateway 网关将这些视为**声明**,并强制执行服务器端允许列
|
||||
- `node.pair.requested` / `node.pair.resolved`:节点配对生命周期。
|
||||
- `node.invoke.request`:节点调用请求广播。
|
||||
- `device.pair.requested` / `device.pair.resolved`:配对设备生命周期。
|
||||
- `voicewake.changed`:唤醒词触发器配置已更改。
|
||||
- `voicewake.changed`:唤醒词触发器配置已变更。
|
||||
- `exec.approval.requested` / `exec.approval.resolved`:exec 审批
|
||||
生命周期。
|
||||
- `plugin.approval.requested` / `plugin.approval.resolved`:插件审批
|
||||
@ -430,62 +431,66 @@ Gateway 网关将这些视为**声明**,并强制执行服务器端允许列
|
||||
|
||||
### 节点辅助方法
|
||||
|
||||
- 节点可以调用 `skills.bins` 来获取当前 Skills 可执行文件列表,
|
||||
- 节点可以调用 `skills.bins` 来获取当前技能可执行文件列表,
|
||||
用于自动允许检查。
|
||||
|
||||
### 操作者辅助方法
|
||||
### 操作员辅助方法
|
||||
|
||||
- 操作者可以调用 `commands.list`(`operator.read`)来获取智能体的运行时
|
||||
- 操作员可以调用 `commands.list`(`operator.read`)来获取某个智能体的运行时
|
||||
命令清单。
|
||||
- `agentId` 是可选的;省略它可读取默认 Agent 工作区。
|
||||
- `scope` 控制主 `name` 目标对应的界面:
|
||||
- `agentId` 是可选的;省略它会读取默认智能体工作区。
|
||||
- `scope` 控制主 `name` 面向哪个表面:
|
||||
- `text` 返回不带前导 `/` 的主文本命令令牌
|
||||
- `native` 和默认的 `both` 路径在可用时返回感知提供商的原生命令名
|
||||
- `native` 和默认的 `both` 路径会在可用时返回感知提供商的原生命令名
|
||||
- `textAliases` 携带精确的斜杠别名,例如 `/model` 和 `/m`。
|
||||
- `nativeName` 在存在时携带感知提供商的原生命令名。
|
||||
- `provider` 是可选的,只影响原生命名以及原生插件命令可用性。
|
||||
- `nativeName` 携带感知提供商的原生命令名(如果存在)。
|
||||
- `provider` 是可选的,并且只影响原生命名以及原生插件命令的可用性。
|
||||
- `includeArgs=false` 会从响应中省略序列化的参数元数据。
|
||||
- 操作者可以调用 `tools.catalog`(`operator.read`)来获取智能体的运行时工具目录。响应包含分组工具和来源元数据:
|
||||
- 操作员可以调用 `tools.catalog`(`operator.read`)来获取某个智能体的运行时工具目录。响应包含分组后的工具和来源元数据:
|
||||
- `source`:`core` 或 `plugin`
|
||||
- `pluginId`:当 `source="plugin"` 时的插件所有者
|
||||
- `optional`:插件工具是否为可选
|
||||
- 操作者可以调用 `tools.effective`(`operator.read`)来获取会话的运行时有效工具清单。
|
||||
- 操作员可以调用 `tools.effective`(`operator.read`)来获取某个会话的运行时有效工具
|
||||
清单。
|
||||
- `sessionKey` 是必需的。
|
||||
- Gateway 网关会从服务器端会话派生可信的运行时上下文,而不是接受调用方提供的鉴权或投递上下文。
|
||||
- 响应限定于会话范围,并反映当前活跃对话此刻可使用的内容,包括核心、插件和渠道工具。
|
||||
- 操作者可以调用 `skills.status`(`operator.read`)来获取智能体的可见
|
||||
skill 清单。
|
||||
- `agentId` 是可选的;省略它可读取默认 Agent 工作区。
|
||||
- 响应包含资格、缺失要求、配置检查,以及经过清理且不会暴露原始密钥值的安装选项。
|
||||
- 操作者可以调用 `skills.search` 和 `skills.detail`(`operator.read`)来获取
|
||||
ClawHub 发现元数据。
|
||||
- 操作者可以调用 `skills.install`(`operator.admin`),支持两种模式:
|
||||
- ClawHub 模式:`{ source: "clawhub", slug, version?, force? }` 会将
|
||||
skill 文件夹安装到默认 Agent 工作区的 `skills/` 目录中。
|
||||
- Gateway 网关会从服务端会话推导可信运行时上下文,而不是接受
|
||||
调用方提供的鉴权或投递上下文。
|
||||
- 响应限定于会话范围,并反映当前活动对话眼下可使用的内容,
|
||||
包括核心、插件和渠道工具。
|
||||
- 操作员可以调用 `skills.status`(`operator.read`)来获取某个智能体的可见
|
||||
Skills 清单。
|
||||
- `agentId` 是可选的;省略它会读取默认智能体工作区。
|
||||
- 响应包含资格状态、缺失要求、配置检查,以及
|
||||
不暴露原始 secret 值的已净化安装选项。
|
||||
- 操作员可以调用 `skills.search` 和 `skills.detail`(`operator.read`)来获取
|
||||
ClawHub 设备发现元数据。
|
||||
- 操作员可以用两种模式调用 `skills.install`(`operator.admin`):
|
||||
- ClawHub 模式:`{ source: "clawhub", slug, version?, force? }` 会将一个
|
||||
skill 文件夹安装到默认智能体工作区的 `skills/` 目录中。
|
||||
- Gateway 网关安装器模式:`{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }`
|
||||
会在 Gateway 网关主机上运行声明的 `metadata.openclaw.install` 动作。
|
||||
- 操作者可以调用 `skills.update`(`operator.admin`),支持两种模式:
|
||||
- ClawHub 模式会更新默认 Agent 工作区中一个已跟踪的 slug,或所有已跟踪的 ClawHub 安装。
|
||||
会在 Gateway 网关主机上运行已声明的 `metadata.openclaw.install` 操作。
|
||||
- 操作员可以用两种模式调用 `skills.update`(`operator.admin`):
|
||||
- ClawHub 模式会更新默认智能体工作区中的一个已跟踪 slug,或所有已跟踪的 ClawHub 安装。
|
||||
- 配置模式会修补 `skills.entries.<skillKey>` 值,例如 `enabled`、
|
||||
`apiKey` 和 `env`。
|
||||
|
||||
### `models.list` 视图
|
||||
|
||||
`models.list` 接受一个可选的 `view` 参数:
|
||||
`models.list` 接受可选的 `view` 参数:
|
||||
|
||||
- 省略或 `"default"`:当前运行时行为。如果配置了 `agents.defaults.models`,响应就是允许的目录;否则响应就是完整的 Gateway 网关目录。
|
||||
- `"configured"`:适合选择器大小的行为。如果配置了 `agents.defaults.models`,它仍然优先。否则响应会使用显式的 `models.providers.*.models` 条目,只有在不存在已配置模型行时才回退到完整目录。
|
||||
- `"all"`:完整 Gateway 网关目录,绕过 `agents.defaults.models`。将它用于诊断和发现 UI,而不是常规模型选择器。
|
||||
- 省略或 `"default"`:当前运行时行为。如果配置了 `agents.defaults.models`,响应就是允许的目录;否则响应为完整的 Gateway 网关目录。
|
||||
- `"configured"`:适合选择器大小的行为。如果配置了 `agents.defaults.models`,它仍然优先。否则响应会使用显式的 `models.providers.*.models` 条目,仅在不存在任何已配置模型行时才回退到完整目录。
|
||||
- `"all"`:完整 Gateway 网关目录,绕过 `agents.defaults.models`。将其用于诊断和发现 UI,而不是常规模型选择器。
|
||||
|
||||
## Exec 审批
|
||||
|
||||
- 当 exec 请求需要审批时,Gateway 网关会广播 `exec.approval.requested`。
|
||||
- 操作者客户端通过调用 `exec.approval.resolve` 进行处理(需要 `operator.approvals` scope)。
|
||||
- 操作员客户端通过调用 `exec.approval.resolve` 来处理(需要 `operator.approvals` scope)。
|
||||
- 对于 `host=node`,`exec.approval.request` 必须包含 `systemRunPlan`(规范的 `argv`/`cwd`/`rawCommand`/会话元数据)。缺少 `systemRunPlan` 的请求会被拒绝。
|
||||
- 审批后,转发的 `node.invoke system.run` 调用会复用该规范的
|
||||
`systemRunPlan`,作为权威命令/cwd/会话上下文。
|
||||
- 如果调用方在准备和最终获批的 `system.run` 转发之间篡改 `command`、`rawCommand`、`cwd`、`agentId` 或
|
||||
`sessionKey`,Gateway 网关会拒绝运行,而不是信任被篡改的 payload。
|
||||
- 审批后,转发的 `node.invoke system.run` 调用会复用该规范
|
||||
`systemRunPlan`,作为权威的命令/cwd/会话上下文。
|
||||
- 如果调用方在 prepare 和最终已批准的 `system.run` 转发之间改变 `command`、`rawCommand`、`cwd`、`agentId` 或
|
||||
`sessionKey`,Gateway 网关会拒绝该运行,而不是信任被修改的 payload。
|
||||
|
||||
## 智能体投递回退
|
||||
|
||||
@ -496,7 +501,7 @@ Gateway 网关将这些视为**声明**,并强制执行服务器端允许列
|
||||
## 版本控制
|
||||
|
||||
- `PROTOCOL_VERSION` 位于 `src/gateway/protocol/schema/protocol-schemas.ts`。
|
||||
- 客户端发送 `minProtocol` + `maxProtocol`;服务器会拒绝不匹配项。
|
||||
- 客户端发送 `minProtocol` + `maxProtocol`;服务端会拒绝不匹配项。
|
||||
- Schema + 模型由 TypeBox 定义生成:
|
||||
- `pnpm protocol:gen`
|
||||
- `pnpm protocol:gen:swift`
|
||||
@ -510,90 +515,104 @@ Gateway 网关将这些视为**声明**,并强制执行服务器端允许列
|
||||
| ----------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
||||
| `PROTOCOL_VERSION` | `3` | `src/gateway/protocol/schema/protocol-schemas.ts` |
|
||||
| 请求超时(每个 RPC) | `30_000` ms | `src/gateway/client.ts`(`requestTimeoutMs`) |
|
||||
| 预鉴权 / connect-challenge 超时 | `15_000` ms | `src/gateway/handshake-timeouts.ts`(配置/环境变量可以提高配对的服务器/客户端预算) |
|
||||
| 预鉴权 / 连接挑战超时 | `15_000` ms | `src/gateway/handshake-timeouts.ts`(配置/环境变量可提高配对的服务端/客户端预算) |
|
||||
| 初始重连退避 | `1_000` ms | `src/gateway/client.ts`(`backoffMs`) |
|
||||
| 最大重连退避 | `30_000` ms | `src/gateway/client.ts`(`scheduleReconnect`) |
|
||||
| device-token 关闭后的快速重试限制 | `250` ms | `src/gateway/client.ts` |
|
||||
| `terminate()` 前的强制停止宽限时间 | `250` ms | `FORCE_STOP_TERMINATE_GRACE_MS` |
|
||||
| 设备令牌关闭后的快速重试钳制 | `250` ms | `src/gateway/client.ts` |
|
||||
| `terminate()` 前的强制停止宽限 | `250` ms | `FORCE_STOP_TERMINATE_GRACE_MS` |
|
||||
| `stopAndWait()` 默认超时 | `1_000` ms | `STOP_AND_WAIT_TIMEOUT_MS` |
|
||||
| 默认 tick 间隔(`hello-ok` 前) | `30_000` ms | `src/gateway/client.ts` |
|
||||
| Tick 超时关闭 | 静默超过 `tickIntervalMs * 2` 时使用 code `4000` | `src/gateway/client.ts` |
|
||||
| tick 超时关闭 | 当静默超过 `tickIntervalMs * 2` 时使用 code `4000` | `src/gateway/client.ts` |
|
||||
| `MAX_PAYLOAD_BYTES` | `25 * 1024 * 1024`(25 MB) | `src/gateway/server-constants.ts` |
|
||||
|
||||
服务器会在 `hello-ok` 中通告有效的 `policy.tickIntervalMs`、`policy.maxPayload`
|
||||
和 `policy.maxBufferedBytes`;客户端应遵守这些值,而不是握手前的默认值。
|
||||
服务端会在 `hello-ok` 中通告有效的 `policy.tickIntervalMs`、`policy.maxPayload`
|
||||
和 `policy.maxBufferedBytes`;客户端应遵循这些值,而不是握手前默认值。
|
||||
|
||||
## 鉴权
|
||||
|
||||
- 共享密钥 Gateway 网关鉴权会使用 `connect.params.auth.token` 或
|
||||
`connect.params.auth.password`,具体取决于已配置的鉴权模式。
|
||||
- 共享 secret Gateway 网关鉴权使用 `connect.params.auth.token` 或
|
||||
`connect.params.auth.password`,具体取决于配置的鉴权模式。
|
||||
- 携带身份的模式(例如 Tailscale Serve
|
||||
(`gateway.auth.allowTailscale: true`)或非 loopback 的
|
||||
`gateway.auth.mode: "trusted-proxy"`)会通过请求头满足连接鉴权检查,而不是通过 `connect.params.auth.*`。
|
||||
- 私有入口 `gateway.auth.mode: "none"` 会完全跳过共享密钥连接鉴权;不要在公开/不可信入口上暴露该模式。
|
||||
- 配对后,Gateway 网关会签发一个限定于连接
|
||||
role + scope 的**设备令牌**。它会在 `hello-ok.auth.deviceToken` 中返回,客户端应持久化它以供后续连接使用。
|
||||
(`gateway.auth.allowTailscale: true`)或非 loopback
|
||||
`gateway.auth.mode: "trusted-proxy"`)会通过请求头满足连接鉴权检查,
|
||||
而不是使用 `connect.params.auth.*`。
|
||||
- 私有入口 `gateway.auth.mode: "none"` 会完全跳过共享 secret 连接鉴权;
|
||||
不要在公开/不可信入口上暴露该模式。
|
||||
- 配对后,Gateway 网关会颁发一个限定于连接
|
||||
角色 + scopes 的**设备令牌**。它会在 `hello-ok.auth.deviceToken` 中返回,客户端应持久化它以供后续连接使用。
|
||||
- 客户端应在任何成功连接后持久化主 `hello-ok.auth.deviceToken`。
|
||||
- 使用该**已存储**设备令牌重新连接时,也应复用为该令牌存储的已批准 scope 集。这会保留已经授予的读取/探测/Status 访问权限,并避免重连时静默收窄为隐式的仅管理员 scope。
|
||||
- 使用该**已存储**设备令牌重连时,也应复用为该令牌存储的已批准 scope 集合。这会保留已授予的读取/探测/status 访问,并避免重连静默降级为更窄的隐式仅 admin scope。
|
||||
- 客户端侧连接鉴权组装(`src/gateway/client.ts` 中的 `selectConnectAuth`):
|
||||
- `auth.password` 是正交的,只要设置就始终会转发。
|
||||
- `auth.token` 按优先级填充:首先是显式共享令牌,然后是显式 `deviceToken`,然后是已存储的每设备令牌(按 `deviceId` + `role` 作为键)。
|
||||
- 只有当上述内容都未解析出 `auth.token` 时,才会发送 `auth.bootstrapToken`。共享令牌或任何已解析设备令牌都会抑制它。
|
||||
- 在一次性的 `AUTH_TOKEN_MISMATCH` 重试中,已存储设备令牌的自动提升仅限于**可信端点**——
|
||||
- `auth.password` 是正交的,并且在设置后始终转发。
|
||||
- `auth.token` 按优先级填充:先是显式共享令牌,
|
||||
然后是显式 `deviceToken`,再是已存储的按设备令牌(按
|
||||
`deviceId` + `role` 作为键)。
|
||||
- 仅当上述都没有解析出
|
||||
`auth.token` 时才发送 `auth.bootstrapToken`。共享令牌或任何已解析的设备令牌都会抑制它。
|
||||
- 在一次性的
|
||||
`AUTH_TOKEN_MISMATCH` 重试中自动提升已存储设备令牌,仅限于**可信端点**:
|
||||
loopback,或带有固定 `tlsFingerprint` 的 `wss://`。未固定的公开 `wss://`
|
||||
不符合条件。
|
||||
- 额外的 `hello-ok.auth.deviceTokens` 条目是 bootstrap 交接令牌。只有在连接使用了 bootstrap 鉴权,且传输是可信传输(例如 `wss://` 或 loopback/本地配对)时,才持久化它们。
|
||||
- 如果客户端提供**显式** `deviceToken` 或显式 `scopes`,该调用方请求的 scope 集仍然是权威的;只有当客户端复用已存储的每设备令牌时,才会复用缓存的 scope。
|
||||
- 额外的 `hello-ok.auth.deviceTokens` 条目是 bootstrap 交接令牌。
|
||||
仅当连接在可信传输(例如 `wss://` 或 loopback/local 配对)上使用 bootstrap 鉴权时才持久化它们。
|
||||
- 如果客户端提供**显式** `deviceToken` 或显式 `scopes`,则该
|
||||
调用方请求的 scope 集合保持权威;仅当客户端复用已存储的按设备令牌时才复用缓存的 scopes。
|
||||
- 设备令牌可以通过 `device.token.rotate` 和
|
||||
`device.token.revoke` 轮换/吊销(需要 `operator.pairing` scope)。
|
||||
- `device.token.rotate` 返回轮换元数据。它只会在已经使用该设备令牌鉴权的同设备调用中回显替换后的 bearer token,以便仅使用令牌的客户端能在重连前持久化替换令牌。共享/管理员轮换不会回显 bearer token。
|
||||
- 令牌签发、轮换和吊销始终受限于记录在该设备配对条目中的已批准 role 集;令牌变更不能扩展或指定配对审批从未授予的设备 role。
|
||||
- 对于已配对设备令牌会话,设备管理是自限定范围的,除非调用方同时具有 `operator.admin`:非管理员调用方只能移除/吊销/轮换它们**自己**的设备条目。
|
||||
- `device.token.rotate` 和 `device.token.revoke` 还会根据调用方当前会话 scope 检查目标操作者令牌 scope 集。非管理员调用方不能轮换或吊销比自己已持有权限更宽的操作者令牌。
|
||||
`device.token.revoke` 轮换/撤销(需要 `operator.pairing` scope)。
|
||||
- `device.token.rotate` 返回轮换元数据。它只会在同设备调用且已使用
|
||||
该设备令牌鉴权时回显替换 bearer 令牌,因此仅令牌客户端可以在
|
||||
重连前持久化替换令牌。共享/admin 轮换不会回显 bearer 令牌。
|
||||
- 令牌签发、轮换和撤销始终限定在该设备配对条目中记录的已批准角色集合内;令牌变更无法扩展或
|
||||
指向配对审批从未授予的设备角色。
|
||||
- 对于配对设备令牌会话,除非调用方还具有 `operator.admin`,否则
|
||||
设备管理是自限定范围的:非 admin 调用方只能移除/撤销/轮换
|
||||
自己的**设备条目**。
|
||||
- `device.token.rotate` 和 `device.token.revoke` 还会根据调用方当前会话 scopes 检查目标操作员
|
||||
令牌 scope 集合。非 admin 调用方不能轮换或撤销比自己已持有范围更广的操作员令牌。
|
||||
- 鉴权失败包含 `error.details.code` 以及恢复提示:
|
||||
- `error.details.canRetryWithDeviceToken`(布尔值)
|
||||
- `error.details.canRetryWithDeviceToken`(boolean)
|
||||
- `error.details.recommendedNextStep`(`retry_with_device_token`、`update_auth_configuration`、`update_auth_credentials`、`wait_then_retry`、`review_auth_configuration`)
|
||||
- `AUTH_TOKEN_MISMATCH` 的客户端行为:
|
||||
- 可信客户端可以尝试使用缓存的每设备令牌进行一次有界重试。
|
||||
- 如果该重试失败,客户端应停止自动重连循环,并呈现操作者操作指引。
|
||||
- 客户端对 `AUTH_TOKEN_MISMATCH` 的行为:
|
||||
- 可信客户端可以使用缓存的按设备令牌尝试一次有界重试。
|
||||
- 如果该重试失败,客户端应停止自动重连循环,并显示操作员操作指导。
|
||||
|
||||
## 设备身份 + 配对
|
||||
|
||||
- 节点应包含稳定的设备身份(`device.id`),该身份派生自密钥对指纹。
|
||||
- Gateway 网关按设备 + 角色签发令牌。
|
||||
- 新设备 ID 需要配对批准,除非已启用本地自动批准。
|
||||
- Gateway 网关按设备 + 角色颁发令牌。
|
||||
- 新设备 ID 需要配对批准,除非启用了本地自动批准。
|
||||
- 配对自动批准以直接 local loopback 连接为中心。
|
||||
- OpenClaw 还为受信任的共享密钥辅助流程提供了一个狭窄的后端/容器本地自连接路径。
|
||||
- 同主机 tailnet 或 LAN 连接在配对时仍会被视为远程连接,并且需要批准。
|
||||
- WS 客户端通常会在 `connect` 期间包含 `device` 身份(操作员 + 节点)。唯一允许无设备操作员的例外是显式信任路径:
|
||||
- WS 客户端通常会在 `connect` 期间包含 `device` 身份(操作者 + 节点)。唯一不带设备的操作者例外是显式信任路径:
|
||||
- `gateway.controlUi.allowInsecureAuth=true`,用于仅限 localhost 的不安全 HTTP 兼容性。
|
||||
- 成功的 `gateway.auth.mode: "trusted-proxy"` 操作员 Control UI 认证。
|
||||
- 成功的 `gateway.auth.mode: "trusted-proxy"` 操作者 Control UI 认证。
|
||||
- `gateway.controlUi.dangerouslyDisableDeviceAuth=true`(应急开关,严重降低安全性)。
|
||||
- 使用共享 Gateway 网关令牌/密码认证的直接 loopback `gateway-client` 后端 RPC。
|
||||
- 所有连接都必须签署服务器提供的 `connect.challenge` nonce。
|
||||
- 直接 local loopback 的 `gateway-client` 后端 RPC,使用共享的 Gateway 网关令牌/密码认证。
|
||||
- 所有连接都必须签名服务器提供的 `connect.challenge` nonce。
|
||||
|
||||
### 设备认证迁移诊断
|
||||
|
||||
对于仍使用挑战前签名行为的旧客户端,`connect` 现在会在 `error.details.code` 下返回 `DEVICE_AUTH_*` 详情代码,并提供稳定的 `error.details.reason`。
|
||||
对于仍使用挑战前签名行为的旧版客户端,`connect` 现在会在 `error.details.code` 下返回 `DEVICE_AUTH_*` 详细代码,并带有稳定的 `error.details.reason`。
|
||||
|
||||
常见迁移失败:
|
||||
|
||||
| 消息 | details.code | details.reason | 含义 |
|
||||
| --------------------------- | -------------------------------- | ------------------------ | -------------------------------------------------- |
|
||||
| `device nonce required` | `DEVICE_AUTH_NONCE_REQUIRED` | `device-nonce-missing` | 客户端省略了 `device.nonce`(或发送为空)。 |
|
||||
| `device nonce mismatch` | `DEVICE_AUTH_NONCE_MISMATCH` | `device-nonce-mismatch` | 客户端使用过期/错误的 nonce 进行了签名。 |
|
||||
| `device signature invalid` | `DEVICE_AUTH_SIGNATURE_INVALID` | `device-signature` | 签名载荷与 v2 载荷不匹配。 |
|
||||
| `device signature expired` | `DEVICE_AUTH_SIGNATURE_EXPIRED` | `device-signature-stale` | 已签名时间戳超出允许偏差。 |
|
||||
| `device nonce required` | `DEVICE_AUTH_NONCE_REQUIRED` | `device-nonce-missing` | 客户端省略了 `device.nonce`(或发送了空值)。 |
|
||||
| `device nonce mismatch` | `DEVICE_AUTH_NONCE_MISMATCH` | `device-nonce-mismatch` | 客户端使用过期/错误的 nonce 进行签名。 |
|
||||
| `device signature invalid` | `DEVICE_AUTH_SIGNATURE_INVALID` | `device-signature` | 签名负载与 v2 负载不匹配。 |
|
||||
| `device signature expired` | `DEVICE_AUTH_SIGNATURE_EXPIRED` | `device-signature-stale` | 已签名时间戳超出了允许的偏移范围。 |
|
||||
| `device identity mismatch` | `DEVICE_AUTH_DEVICE_ID_MISMATCH` | `device-id-mismatch` | `device.id` 与公钥指纹不匹配。 |
|
||||
| `device public key invalid` | `DEVICE_AUTH_PUBLIC_KEY_INVALID` | `device-public-key` | 公钥格式/规范化失败。 |
|
||||
|
||||
迁移目标:
|
||||
|
||||
- 始终等待 `connect.challenge`。
|
||||
- 签署包含服务器 nonce 的 v2 载荷。
|
||||
- 签名包含服务器 nonce 的 v2 负载。
|
||||
- 在 `connect.params.device.nonce` 中发送相同的 nonce。
|
||||
- 首选签名载荷是 `v3`,它除了设备/客户端/角色/作用域/令牌/nonce 字段外,还绑定 `platform` 和 `deviceFamily`。
|
||||
- 为兼容性仍接受旧版 `v2` 签名,但已配对设备的元数据固定仍会在重连时控制命令策略。
|
||||
- 首选签名负载是 `v3`,它除了设备/客户端/角色/范围/令牌/nonce 字段外,还绑定 `platform` 和 `deviceFamily`。
|
||||
- 旧版 `v2` 签名仍会被接受以保持兼容性,但已配对设备的元数据固定仍会在重新连接时控制命令策略。
|
||||
|
||||
## TLS + 固定
|
||||
|
||||
@ -602,9 +621,9 @@ Gateway 网关将这些视为**声明**,并强制执行服务器端允许列
|
||||
|
||||
## 范围
|
||||
|
||||
此协议暴露**完整 Gateway 网关 API**(Status、渠道、模型、聊天、智能体、会话、节点、批准等)。确切范围由 `src/gateway/protocol/schema.ts` 中的 TypeBox schema 定义。
|
||||
此协议暴露**完整 Gateway 网关 API**(Status、渠道、模型、聊天、智能体、会话、节点、批准等)。确切的接口面由 `src/gateway/protocol/schema.ts` 中的 TypeBox schema 定义。
|
||||
|
||||
## 相关
|
||||
## 相关内容
|
||||
|
||||
- [桥接协议](/zh-CN/gateway/bridge-protocol)
|
||||
- [Gateway 网关运行手册](/zh-CN/gateway)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user