@zhin.js/adapter-sandbox 1.1.11 → 1.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +100 -13
  3. package/package.json +17 -17
package/CHANGELOG.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # @zhin.js/adapter-process
2
2
 
3
+ ## 1.1.13
4
+
5
+ ### Patch Changes
6
+
7
+ - b8317b0: Document the full Sandbox WebSocket wire protocol in the README: connection paths, token and demo-scope rules, close codes, every inbound field (including `messageId`, button `action` segments and `agentRun`), and the `ready`, reply and read-only `error` frames with media segment handling.
8
+ - Updated dependencies [5be09ae]
9
+ - Updated dependencies [a3ab153]
10
+ - Updated dependencies [e8f7309]
11
+ - Updated dependencies [5afc18f]
12
+ - Updated dependencies [f30be42]
13
+ - Updated dependencies [d3563d9]
14
+ - Updated dependencies [c618eb7]
15
+ - Updated dependencies [fbfefb7]
16
+ - @zhin.js/core@1.1.47
17
+ - @zhin.js/adapter@1.1.21
18
+ - @zhin.js/client@1.1.15
19
+ - @zhin.js/feature-kit@1.1.7
20
+ - @zhin.js/im-contract@1.1.5
21
+ - @zhin.js/page@1.1.8
22
+ - @zhin.js/skill@1.1.8
23
+ - @zhin.js/host-http@1.1.8
24
+
25
+ ## 1.1.12
26
+
27
+ ### Patch Changes
28
+
29
+ - 9816c18: 将应用插件装配改为 configVersion: 2:主配置 plugins 映射实例名到包,disable_plugins 控制启停,业务配置使用顶层同名块。package.json 继续保留 features、entry、engine 等包契约,并支持静态 displayName/icon。
30
+
31
+ 这是配置格式的破坏性更新:旧配置不能继续运行,请先停止 Bot,运行 `zhin migrate instances` 预览,再使用 `--apply` 转换;提供备份与中断继续/回滚,无法无损转换的嵌套、optional 和别名碰撞需人工迁移。Runtime、Console、CLI 与创建向导统一使用新声明。
32
+
33
+ 保留框架顶层 `menuKeyword` / `menuStyle`,通过当前 generation 的 Root 配置视图供 Command Feature 消费;严格校验和配置修改不会丢失菜单设置,子实例配置保持隔离。
34
+
35
+ - Updated dependencies [c407bd2]
36
+ - Updated dependencies [064b06d]
37
+ - Updated dependencies [2b4d6dc]
38
+ - Updated dependencies [b58548a]
39
+ - Updated dependencies [e914a93]
40
+ - Updated dependencies [e914a93]
41
+ - Updated dependencies [064b06d]
42
+ - @zhin.js/core@1.1.46
43
+ - @zhin.js/feature-kit@1.1.6
44
+ - @zhin.js/host-http@1.1.7
45
+ - @zhin.js/client@1.1.14
46
+ - @zhin.js/adapter@1.1.20
47
+ - @zhin.js/page@1.1.7
48
+ - @zhin.js/skill@1.1.7
49
+
3
50
  ## 1.1.11
4
51
 
5
52
  ### Patch Changes
package/README.md CHANGED
@@ -48,23 +48,27 @@ Sandbox 声明 `html: direct`,聊天页在隔离 iframe 中展示 canonical `h
48
48
 
49
49
  ## 配置
50
50
 
51
- **推荐(与 [minimal-bot](../../../examples/minimal-bot/) 一致)**:`plugins.sandbox.endpoints: []`,运行时提供默认 `sandbox-bot` endpoint,无需额外账号配置。
51
+ **推荐(与 [minimal-bot](../../../examples/minimal-bot/) 一致)**:`sandbox.endpoints: []`,运行时提供默认 `sandbox-bot` endpoint,无需额外账号配置。
52
52
 
53
53
  ```yaml
54
+ configVersion: 2
54
55
  # zhin.config.yml(Plugin Runtime)
55
56
  plugins:
56
- sandbox:
57
- endpoints: []
57
+ sandbox: "@zhin.js/adapter-sandbox"
58
+ sandbox:
59
+ endpoints: []
58
60
  ```
59
61
 
60
62
  可选:若需在启动时即在 bot 列表显示**固定名称**的离线占位 bot,可显式配置:
61
63
 
62
64
  ```yaml
65
+ configVersion: 2
63
66
  plugins:
64
- sandbox:
65
- endpoints:
66
- - id: sandbox-bot
67
- owner: sandbox-user
67
+ sandbox: "@zhin.js/adapter-sandbox"
68
+ sandbox:
69
+ endpoints:
70
+ - id: sandbox-bot
71
+ owner: sandbox-user
68
72
  ```
69
73
 
70
74
  ## 使用方式
@@ -75,17 +79,100 @@ plugins:
75
79
 
76
80
  浏览器客户端连接到默认 `sandbox-bot`,也可以通过多个显式 endpoint 使用不同 WebSocket 路径。
77
81
 
78
- 通过 `Router.ws("/sandbox")`(插件 `useContext("router")` 自动挂载)建立连接。
82
+ 每个 endpoint 通过 Root 提供的 HTTP Host(`httpHostToken`)挂载一个 WebSocket 路径,协议见下文「消息格式(wire 协议)」。
79
83
 
80
- ## 消息格式
84
+ ## 消息格式(wire 协议)
81
85
 
82
- Sandbox 使用 JSON 消息格式:
86
+ Console 沙盒页和自己写的测试客户端都用这套协议。每个 WebSocket 文本帧是一个 UTF-8 JSON 对象。
87
+
88
+ ### 连接
89
+
90
+ - **地址**:`ws://<host>:<port>/sandbox`。同一个 HTTP Host 上的第一个 Sandbox endpoint 挂在 `/sandbox`,其余 endpoint 挂在 `/sandbox/<endpoint id>`(重名时依次加 `-2`、`-3`),启动日志会打印 `ws mounted <path>`。
91
+ - **鉴权**:Host 配置了 token 时,握手请求需带 `Authorization: Bearer <token>` 或查询参数 `?token=<token>`,否则返回 `401`。demo 权限的 token 只能连 `/sandbox`,而且是只读的:消息会被接收,但不会进入命令和 Agent,服务端回一条 `type: "error"`。
92
+ - **单连接**:endpoint 使用固定名称(默认),同一 endpoint 只保留最新的浏览器连接。新连接接入时,旧连接以关闭码 `4000`(`replaced by new sandbox client`)断开;endpoint 停止时以 `1001` 断开;插件热重载使当前 generation 退役时,Host 以 `1012` 断开,客户端重连即可。
93
+
94
+ ### 客户端 → 服务端:发送消息
95
+
96
+ ```json
97
+ {
98
+ "type": "group",
99
+ "id": "test-group",
100
+ "content": [{ "type": "text", "data": { "text": "/hello" } }],
101
+ "messageId": "client-msg-001",
102
+ "timestamp": 1700000000000
103
+ }
104
+ ```
105
+
106
+ | 字段 | 类型 | 说明 |
107
+ | --- | --- | --- |
108
+ | `type` | `private` \| `group` \| `channel` \| `direct` \| `guild` | 会话类型,默认 `private`。`direct` 按 `private` 处理,`guild` 按 `channel` 处理 |
109
+ | `id` | string | 会话 id,默认使用 endpoint 的 `owner`(默认 `sandbox-user`) |
110
+ | `content` | string 或消息段数组 | 消息段格式为 `{ "type": string, "data": object }`;字符串等同于一个 `text` 段 |
111
+ | `text` | string | 可选。没有 `content` 时作为纯文本;`content` 里没有文本段时也用它作为消息文本 |
112
+ | `messageId` | string | 可选。客户端生成的消息 id,须匹配 `^[A-Za-z0-9._:-]{1,160}$`,不匹配时忽略;填写后作为这条入站消息的 id,引用回复时可据此定位 |
113
+ | `timestamp` | number | 可选。毫秒时间戳,默认取服务端收到的时间 |
114
+ | `agentRun` | object | 可选。Agent 试验台运行配置,见下表 |
115
+
116
+ - 帧内容不是 JSON 时,整段文本按一条纯文本消息处理。
117
+ - 消息的发送者固定为 endpoint 的 `owner`。
118
+ - **按钮回传**:`content` 中的 `{ "type": "action", "data": { "id": "...", "payload": "..." } }` 段会作为交互动作交给命令或 Agent;只填 `id` 或 `payload` 时,另一个取相同的值。消息里没有文本时,`payload` 作为消息文本。
119
+
120
+ `agentRun` 字段:
121
+
122
+ | 字段 | 取值 | 默认 |
123
+ | --- | --- | --- |
124
+ | `workingDirectory` | string,最长 4096 字符 | `""` |
125
+ | `safetyMode` | `read-only` \| `workspace-write` \| `danger-full-access` | `workspace-write` |
126
+ | `approvalMode` | `ask` \| `auto` \| `bypass` | `ask` |
127
+ | `networkAccess` | boolean | `false`;`safetyMode` 为 `danger-full-access` 时恒为 `true` |
128
+
129
+ 无法识别的取值按默认值处理。
130
+
131
+ ### 服务端 → 客户端
132
+
133
+ **连接就绪**:每次连接成功后发送一次。
134
+
135
+ ```json
136
+ {
137
+ "type": "ready",
138
+ "id": "sandbox-user",
139
+ "endpoint": "sandbox-bot",
140
+ "workingDirectory": "/path/to/bot",
141
+ "canExecute": true,
142
+ "shellIsolation": { "available": false, "provider": "docker", "message": "Docker daemon is unavailable" },
143
+ "content": [{ "type": "text", "data": { "text": "已连接 Sandbox「sandbox-bot」…" } }],
144
+ "timestamp": 1700000000000
145
+ }
146
+ ```
147
+
148
+ `canExecute` 表示当前连接是否为 full 权限(能运行命令和 Agent 任务);`shellIsolation` 是 Docker 隔离环境的探测结果,仅供展示。
149
+
150
+ **回复消息**:
151
+
152
+ ```json
153
+ {
154
+ "type": "group",
155
+ "id": "test-group",
156
+ "bot": "sandbox-bot",
157
+ "endpoint": "sandbox-bot",
158
+ "content": [{ "type": "text", "data": { "text": "Hello!" } }],
159
+ "timestamp": 1700000000001
160
+ }
161
+ ```
162
+
163
+ - `type` / `id` 是回复所在的会话(`direct` 已归一为 `private`,`guild` 已归一为 `channel`),客户端按这两个字段把消息放进对应会话;`bot` 是 endpoint id,`endpoint` 是收到消息的连接名。
164
+ - `content` 是消息段数组。文本、`html`(JSX 卡片,见上文 `html: direct`)、按钮等段原样透传。
165
+ - `image` / `audio` / `video` / `file` 段只读 `data.media`(MediaRef):`url` 原样透传;`base64` 补上 `base64://` 前缀后内联;`path` 由服务端读取文件后转成 `base64` 内联;其他类型和缺少 `data.media` 的媒体段会被丢弃,并在日志中记录 `sandbox_outbound_media_dropped`。
166
+ - 插件直接发送完整消息对象时,其他字段会原样保留。
167
+
168
+ **只读连接的提示**:demo 权限的连接发送消息后,服务端回复:
83
169
 
84
170
  ```json
85
171
  {
86
- "type": "message",
87
- "id": "msg-001",
88
- "content": "你好",
172
+ "type": "error",
173
+ "id": "sandbox-user",
174
+ "endpoint": "sandbox-bot",
175
+ "content": [{ "type": "text", "data": { "text": "当前连接是只读演示权限,不能运行 Agent 任务。" } }],
89
176
  "timestamp": 1700000000000
90
177
  }
91
178
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-sandbox",
3
- "version": "1.1.11",
3
+ "version": "1.1.13",
4
4
  "description": "Zhin.js Sandbox adapter for Plugin Runtime (WebSocket /sandbox)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -47,16 +47,16 @@
47
47
  "dependencies": {
48
48
  "lucide-react": "^0.525.0",
49
49
  "react": "^19.2.8",
50
- "@zhin.js/adapter": "1.1.19",
51
- "@zhin.js/client": "1.1.13",
50
+ "@zhin.js/adapter": "1.1.21",
51
+ "@zhin.js/client": "1.1.15",
52
52
  "@zhin.js/console-contract": "1.1.2",
53
- "@zhin.js/core": "1.1.45",
54
- "@zhin.js/feature-kit": "1.1.5",
55
- "@zhin.js/host-http": "1.1.6",
56
- "@zhin.js/im-contract": "1.1.4",
53
+ "@zhin.js/core": "1.1.47",
54
+ "@zhin.js/feature-kit": "1.1.7",
55
+ "@zhin.js/host-http": "1.1.8",
56
+ "@zhin.js/im-contract": "1.1.5",
57
57
  "@zhin.js/logger": "1.1.2",
58
- "@zhin.js/page": "1.1.6",
59
- "@zhin.js/skill": "1.1.6"
58
+ "@zhin.js/page": "1.1.8",
59
+ "@zhin.js/skill": "1.1.8"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/react": "^19.2.18",
@@ -64,18 +64,18 @@
64
64
  "typescript": "^6.0.3",
65
65
  "vitest": "^4.1.10",
66
66
  "ws": "^8.21.1",
67
- "@zhin.js/pagemanager": "1.1.9",
68
- "@zhin.js/runtime": "1.1.8",
69
- "zhin.js": "1.1.10"
67
+ "@zhin.js/pagemanager": "1.1.11",
68
+ "@zhin.js/runtime": "1.1.10",
69
+ "zhin.js": "1.1.12"
70
70
  },
71
71
  "peerDependencies": {
72
72
  "react": "^19.0.0",
73
- "@zhin.js/adapter": "^1.1.19",
73
+ "@zhin.js/adapter": "^1.1.21",
74
74
  "@zhin.js/console-contract": "^1.1.2",
75
- "@zhin.js/core": "^1.1.45",
76
- "@zhin.js/host-http": "^1.1.6",
77
- "@zhin.js/page": "^1.1.6",
78
- "zhin.js": "^1.1.10"
75
+ "@zhin.js/core": "^1.1.47",
76
+ "@zhin.js/host-http": "^1.1.8",
77
+ "@zhin.js/page": "^1.1.8",
78
+ "zhin.js": "^1.1.12"
79
79
  },
80
80
  "peerDependenciesMeta": {
81
81
  "react": {