dsh-cherry-bridge 0.1.7 → 0.1.9
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.
- package/README.en.md +31 -17
- package/README.md +20 -12
- package/dist/index.mjs +201 -43
- package/docs/e2e-checklist.md +1 -1
- package/lib/client.js +2 -2
- package/locale/en.json +1 -1
- package/locale/zh.json +1 -1
- package/package.json +1 -1
- package/src/connection.ts +61 -0
- package/src/defaults.ts +23 -0
- package/src/tools.ts +264 -78
- package/ui/index.html +1 -1
- package/ui/src/i18n.ts +2 -2
package/README.en.md
CHANGED
|
@@ -38,13 +38,13 @@ flowchart TB
|
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
40
|
# From npm (recommended, pinned)
|
|
41
|
-
npx @deepseek-ai/dsh plugin --profile web add dsh-cherry-bridge@0.1.
|
|
41
|
+
npx @deepseek-ai/dsh plugin --profile web add dsh-cherry-bridge@0.1.9
|
|
42
42
|
|
|
43
43
|
# Install the latest npm release
|
|
44
44
|
npx @deepseek-ai/dsh plugin --profile web add dsh-cherry-bridge
|
|
45
45
|
|
|
46
46
|
# From GitHub source (same commit as the npm release)
|
|
47
|
-
npx @deepseek-ai/dsh plugin --profile web add github:SAXEM1997/dsh-cherry-bridge#v0.1.
|
|
47
|
+
npx @deepseek-ai/dsh plugin --profile web add github:SAXEM1997/dsh-cherry-bridge#v0.1.9
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
The package ships `cordis.patch.yml` (`package.json`'s `dsh.bundle.patch` points
|
|
@@ -103,15 +103,15 @@ cherry_interactions → see pending question/approval cards; cherry_respond answ
|
|
|
103
103
|
| Tool | What it does |
|
|
104
104
|
| --- | --- |
|
|
105
105
|
| `cherry_devices` | List every paired device and its connection state (`connected`/`connecting`/`offline`/`disabled`/`identity-mismatch`). |
|
|
106
|
-
| `cherry_agents` | List the agents available on a device (paginated). A truncated answer always carries `truncated` + `truncationReason` (`limit` or `safety-bound`, the latter the 1000-item internal ceiling)
|
|
107
|
-
| `cherry_workspaces` | List an agent's **registered** workspaces, and whether a system workspace exists. A truncated answer always carries `truncated` + `truncationReason
|
|
108
|
-
| `cherry_sessions` | List an agent's sessions, optionally filtered by workspace. A truncated answer always carries `truncated` + `truncationReason` (`limit` or `safety-bound`)
|
|
109
|
-
| `cherry_read` | Read a session's message history snapshot, **newest-first** (`limit` drops the **oldest** messages). Attachment parts come back as `name`/`mediaType`/`byteLength` with an empty `content` — the bytes are never fetched. A truncated walk always says so (`truncated` + `truncationReason`): `limit` means your own ceiling was reached and raising `limit` helps; `aggregate-bytes` means the answer hit its **output size limit** — independent of `limit` (a larger `limit` only costs more round trips and stops at the same budget). **The older messages are reached by the resume token**: pass the `messagesResumeCursor` a truncated answer returned as this tool's own `messagesResumeCursor` argument to continue from that stop point (`limit` then bounds how many messages come back **from there**), walking a long history in successive answers. Two token forms: `cursor:<peer position>` (the peer page position after a whole window was consumed) and `after:<messageId>` (the walk stopped inside its window; the resume scans from the newest end to that message and returns the older ones). A token this tool did not emit is **refused locally** (never forwarded — the desktop silently falls back to the newest page for one), and an `after:` anchor that is no longer in the history is an **error**, not an empty result. |
|
|
106
|
+
| `cherry_agents` | List the agents available on a device (paginated). A truncated answer always carries `truncated` + `truncationReason` (`limit` or `safety-bound`, the latter the 1000-item internal ceiling); when the stop point can be named it also carries a `resumeCursor`: replay it as `cursor` with the same device and filters to continue from that stop point (`limit` then bounds the next answer). A token from another tool, device or filter set is refused **locally**, never forwarded. |
|
|
107
|
+
| `cherry_workspaces` | List an agent's **registered** workspaces, and whether a system workspace exists. A truncated answer always carries `truncated` + `truncationReason`; when the stop point can be named it also carries a `resumeCursor` — replay it as `cursor` with the same filters to continue. |
|
|
108
|
+
| `cherry_sessions` | List an agent's sessions, optionally filtered by workspace. A truncated answer always carries `truncated` + `truncationReason` (`limit` or `safety-bound`); when the stop point can be named it also carries a `resumeCursor`: replay it as `cursor` with the same device and **identical filters** to continue (`limit` then bounds the next answer); a token from another tool, device or filter set is refused **locally**. |
|
|
109
|
+
| `cherry_read` | Read a session's message history snapshot, **newest-first** (`limit` drops the **oldest** messages). Attachment parts come back as `name`/`mediaType`/`byteLength` with an empty `content` — the bytes are never fetched. A truncated walk always says so (`truncated` + `truncationReason`): `limit` means your own ceiling was reached and raising `limit` helps; `aggregate-bytes` means the answer hit its **output size limit** — independent of `limit` (a larger `limit` only costs more round trips and stops at the same budget). **The older messages are reached by the resume token**: pass the `messagesResumeCursor` a truncated answer returned as this tool's own `messagesResumeCursor` argument to continue from that stop point (`limit` then bounds how many messages come back **from there**), walking a long history in successive answers. When the stop point cannot be named the token is **absent** (`truncated` stays `true`, and the absence does **not** mean the history ended); a wider `limit` is not a general remedy — it moves a `limit` stop only, while an `aggregate-bytes` stop leaves the older messages unreachable in that answer (see [Errors and limits](#errors-and-limits)). Two token forms: `cursor:<peer position>` (the peer page position after a whole window was consumed) and `after:<messageId>` (the walk stopped inside its window; the resume scans from the newest end to that message and returns the older ones). A token this tool did not emit is **refused locally** (never forwarded — the desktop silently falls back to the newest page for one), and an `after:` anchor that is no longer in the history is an **error**, not an empty result. |
|
|
110
110
|
| `cherry_events` | Read the session's buffered events newer than `cursor`, acking them after delivery. The answer is `{events, nextCursor}`; pass that `nextCursor` back as `cursor` to continue from it. |
|
|
111
111
|
| `cherry_create` | Create a session in an agent workspace (workspace selection is **required**; identity is read back). |
|
|
112
112
|
| `cherry_send` | Send a message, by default waiting for a terminal state and returning the assistant text; `wait: false` returns the command receipt immediately. `messagesTruncated`/`messagesTruncationReason` report a **message**-level cut (older messages dropped); `deadline` means the **answer's own assembly budget** ran out (see below), with the content read so far still returned. |
|
|
113
113
|
| `cherry_wait` | Wait only for the session's in-flight execution to settle (sends nothing). |
|
|
114
|
-
| `cherry_interactions` | List the session's **pending** interaction cards (questions / approvals). A truncated answer always carries `truncated` + `truncationReason
|
|
114
|
+
| `cherry_interactions` | List the session's **pending** interaction cards (questions / approvals). A truncated answer always carries `truncated` + `truncationReason`; when the stop point can be named it also carries a `resumeCursor` — replay it as `cursor` from the same `sessionId` to continue (`limit` counts the peer's pre-filter rows). |
|
|
115
115
|
| `cherry_respond` | Answer an interaction card: questions must be answered in full; approvals take `decision`. |
|
|
116
116
|
| `cherry_cancel` | Cancel the session's in-flight execution (`expectedExecutionId` required). |
|
|
117
117
|
| `cherry_pair` | Pair with a desktop using the pairing information shown by the scanned page. |
|
|
@@ -124,12 +124,12 @@ The `device` argument accepts an **exact `deviceId`**, or a **prefix of a
|
|
|
124
124
|
`cherry_send(wait: true)` / `cherry_wait` results carry one of **8 `status`
|
|
125
125
|
values**: the four protocol terminal states
|
|
126
126
|
(`completed`/`failed`/`cancelled`/`interrupted`), plus `awaiting-interaction`
|
|
127
|
-
(a pending card appeared while the run is still alive), `timeout` (the window
|
|
128
|
-
out, **not a failure** — partial content plus a stop-point
|
|
129
|
-
`idle` (`cherry_wait` met a session with nothing
|
|
130
|
-
snapshot immediately), and `subscription-lost` (the
|
|
131
|
-
could not be rebuilt, so the outcome is
|
|
132
|
-
with it).
|
|
127
|
+
(a pending card appeared while the run is still alive), `timeout` (the window
|
|
128
|
+
ran out, **not a failure** — partial content comes back, plus a stop-point
|
|
129
|
+
cursor when one can be named), `idle` (`cherry_wait` met a session with nothing
|
|
130
|
+
in flight and returned the snapshot immediately), and `subscription-lost` (the
|
|
131
|
+
subscription was lost and could not be rebuilt, so the outcome is
|
|
132
|
+
**unknowable**; repair guidance ships with it).
|
|
133
133
|
|
|
134
134
|
## Errors and limits
|
|
135
135
|
|
|
@@ -152,9 +152,23 @@ with it).
|
|
|
152
152
|
- A truncated history walk always says so (`truncationReason`; `limit`,
|
|
153
153
|
`aggregate-bytes` and `deadline` mean different things, see above) and,
|
|
154
154
|
whenever a stop point can be named honestly, carries a `messagesResumeCursor`
|
|
155
|
-
resume token
|
|
156
|
-
|
|
157
|
-
|
|
155
|
+
resume token. **When it cannot be named the token is absent**: the peer's
|
|
156
|
+
position is empty, carries leading/trailing whitespace or a control character,
|
|
157
|
+
looks like a retired v1 token, the token would exceed the 4,096-character
|
|
158
|
+
ceiling, or there is no message id to anchor on. The absence does **not** mean
|
|
159
|
+
the history ended (`truncated` stays `true`); the remedy follows the reason —
|
|
160
|
+
a `limit` stop answers to a wider `limit` only where the caller owns that
|
|
161
|
+
ceiling (`cherry_read` and the four list tools; a **wait answer's** `limit` is
|
|
162
|
+
its own fixed allowance, so read further with `cherry_read`), an
|
|
163
|
+
`aggregate-bytes` stop does not (nothing reaches past it in that answer), a
|
|
164
|
+
`safety-bound` stop is an internal circuit breaker no caller can move, and a
|
|
165
|
+
wait answer cut by its deadline is continued with `cherry_read`, which carries
|
|
166
|
+
no deadline. **Both faces obey one rule**:
|
|
167
|
+
the message face's `messagesResumeCursor` and the four list tools'
|
|
168
|
+
`resumeCursor` are emitted only when this tool would accept them back; an
|
|
169
|
+
interior plain space is legal and is not a reason to withhold one.
|
|
170
|
+
A message whose own parts could not be fully read carries `incomplete: true`
|
|
171
|
+
(inside a wait answer, a message cut by the deadline carries
|
|
158
172
|
`partsTruncated: "deadline"`).
|
|
159
173
|
- **A wait answer has an assembly budget of its own.** After the window ends,
|
|
160
174
|
`cherry_send(wait: true)` / `cherry_wait` still read some history (the message
|
|
@@ -189,7 +203,7 @@ with it).
|
|
|
189
203
|
|
|
190
204
|
The plugin is also a **web client bundle** (`package.json`'s `dsh.client`,
|
|
191
205
|
exporting `./client`). Through the `settings.section` slot it registers a
|
|
192
|
-
**`cherry-remote`** page (nav label “Cherry
|
|
206
|
+
**`cherry-remote`** page (nav label “Cherry Bridge”): device cards
|
|
193
207
|
(enable/disable/remove), a pairing wizard (paste → 6-digit code → verdict), a
|
|
194
208
|
scope panel, and live state pushed over the same-origin SSE feed
|
|
195
209
|
(`/cherry-remote/api/events`).
|
package/README.md
CHANGED
|
@@ -36,13 +36,13 @@ flowchart TB
|
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
# 从 npm 安装(推荐,钉住版本)
|
|
39
|
-
npx @deepseek-ai/dsh plugin --profile web add dsh-cherry-bridge@0.1.
|
|
39
|
+
npx @deepseek-ai/dsh plugin --profile web add dsh-cherry-bridge@0.1.9
|
|
40
40
|
|
|
41
41
|
# 安装 npm 最新发布版
|
|
42
42
|
npx @deepseek-ai/dsh plugin --profile web add dsh-cherry-bridge
|
|
43
43
|
|
|
44
44
|
# 从 GitHub 源码安装(与 npm 发布同一提交)
|
|
45
|
-
npx @deepseek-ai/dsh plugin --profile web add github:SAXEM1997/dsh-cherry-bridge#v0.1.
|
|
45
|
+
npx @deepseek-ai/dsh plugin --profile web add github:SAXEM1997/dsh-cherry-bridge#v0.1.9
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
本包自带 `cordis.patch.yml`(`package.json` 的 `dsh.bundle.patch` 指向它),
|
|
@@ -94,15 +94,15 @@ cherry_interactions → 看待答的提问/审批卡;cherry_respond 作答
|
|
|
94
94
|
| 工具 | 作用 |
|
|
95
95
|
| --- | --- |
|
|
96
96
|
| `cherry_devices` | 列出已配对设备及连接状态(`connected`/`connecting`/`offline`/`disabled`/`identity-mismatch`)。 |
|
|
97
|
-
| `cherry_agents` | 列出某设备上可用的 agent(分页)。被截断时必带 `truncated`+`truncationReason`(`limit` 或 `safety-bound`,后者是 1000
|
|
98
|
-
| `cherry_workspaces` | 列出某 agent 的**已注册**工作区,以及是否存在系统工作区。被截断时必带 `truncated`+`truncationReason
|
|
99
|
-
| `cherry_sessions` | 列出某 agent 的会话,可按工作区过滤。被截断时必带 `truncated`+`truncationReason`(`limit` 或 `safety-bound
|
|
100
|
-
| `cherry_read` | 读会话消息历史快照,**从新到旧**返回(`limit` 丢掉的是**最旧**的消息)。附件 part 只回 `name`/`mediaType`/`byteLength`,`content` 为空——字节不取。被截断时 `truncated` + `truncationReason` 一定说明:`limit` 表示你设的条数到了,提高 `limit` 即可;`aggregate-bytes` 表示单次回答达到了**输出大小上限**——与 `limit` 无关,提高 `limit` 只会多付往返、仍停在同一预算。**被挡下的更旧消息用 `messagesResumeCursor` 续读**:把本次返回的 `messagesResumeCursor` 原样传给下一次调用的 `messagesResumeCursor` 参数即可从停点继续(`limit`
|
|
97
|
+
| `cherry_agents` | 列出某设备上可用的 agent(分页)。被截断时必带 `truncated`+`truncationReason`(`limit` 或 `safety-bound`,后者是 1000 条内部上限);停点可命名时还给出 `resumeCursor`——用同一 device 与过滤条件把它回传为 `cursor` 即可从停点继续(此时 `limit` 约束的是下一次回答);跨工具/设备/过滤条件的令牌会被**本地拒绝**,不会转发给对端。 |
|
|
98
|
+
| `cherry_workspaces` | 列出某 agent 的**已注册**工作区,以及是否存在系统工作区。被截断时必带 `truncated`+`truncationReason`;停点可命名时还给出 `resumeCursor`——用相同过滤条件回传为 `cursor` 即可续读。 |
|
|
99
|
+
| `cherry_sessions` | 列出某 agent 的会话,可按工作区过滤。被截断时必带 `truncated`+`truncationReason`(`limit` 或 `safety-bound`),停点可命名时还给出 `resumeCursor`——用同一 device 与**相同过滤条件**把它回传为 `cursor` 即可从停点继续(此时 `limit` 约束的是下一次回答);跨工具/设备/过滤条件的令牌会被**本地拒绝**。 |
|
|
100
|
+
| `cherry_read` | 读会话消息历史快照,**从新到旧**返回(`limit` 丢掉的是**最旧**的消息)。附件 part 只回 `name`/`mediaType`/`byteLength`,`content` 为空——字节不取。被截断时 `truncated` + `truncationReason` 一定说明:`limit` 表示你设的条数到了,提高 `limit` 即可;`aggregate-bytes` 表示单次回答达到了**输出大小上限**——与 `limit` 无关,提高 `limit` 只会多付往返、仍停在同一预算。**被挡下的更旧消息用 `messagesResumeCursor` 续读**:把本次返回的 `messagesResumeCursor` 原样传给下一次调用的 `messagesResumeCursor` 参数即可从停点继续(`limit` 此时约束的是**从停点起**本次最多返回多少条),长历史分几次回答读完。停点不可命名时**没有**这个令牌(`truncated` 仍为 `true`,**缺失本身不代表历史已到底**;补救按 `truncationReason` 分:`limit` 可以提高 `limit`,`aggregate-bytes` 不行——被挡住的旧消息在这一回答里拿不到,详见[错误与限制](#错误与限制))。两种令牌:`cursor:<peer position>`(整窗读完后的 peer 分页位置)与 `after:<messageId>`(停在窗内,续读从最新端扫到该消息、返回它更旧的那些)。不是本工具发出的令牌会被**本地拒绝**(不转发给桌面端——桌面端会静默回退到最新页);`after:` 锚点在历史里找不到则**报错**,不会返回空结果。 |
|
|
101
101
|
| `cherry_events` | 读取该会话缓冲区内比 `cursor` 更新的事件,并在投递后 ack。返回 `{events, nextCursor}`;把 `nextCursor` 作为下次的 `cursor` 传回即可续读。 |
|
|
102
102
|
| `cherry_create` | 在 agent 工作区创建会话(工作区选择**必填**;创建后回读身份)。 |
|
|
103
103
|
| `cherry_send` | 向会话发消息,默认等待运行到终态并返回助手文本;`wait: false` 立即返回命令回执。内容被截断时 `messagesTruncated`/`messagesTruncationReason` 说的是**消息**被截断(丢更旧的);`deadline` 表示**回答自身的装配时限**到了(见下),已读到的内容照常返回。 |
|
|
104
104
|
| `cherry_wait` | 只等待该会话在途执行收敛(不发送新消息)。 |
|
|
105
|
-
| `cherry_interactions` | 列出该会话**待答**的交互卡(提问 / 审批)。被截断时必带 `truncated`+`truncationReason
|
|
105
|
+
| `cherry_interactions` | 列出该会话**待答**的交互卡(提问 / 审批)。被截断时必带 `truncated`+`truncationReason`;停点可命名时还给出 `resumeCursor`——用 `sessionId` 相同的调用回传为 `cursor` 即可续读(`limit` 计的是过滤**前**的对端条目)。 |
|
|
106
106
|
| `cherry_respond` | 应答交互卡:提问必须全量作答,审批走 `decision`。 |
|
|
107
107
|
| `cherry_cancel` | 取消会话在途执行(`expectedExecutionId` 必填)。 |
|
|
108
108
|
| `cherry_pair` | 用「扫码后页面显示的配对信息」建立与桌面端的配对。 |
|
|
@@ -113,7 +113,7 @@ cherry_interactions → 看待答的提问/审批卡;cherry_respond 作答
|
|
|
113
113
|
|
|
114
114
|
`cherry_send(wait: true)` / `cherry_wait` 的 `status` 有 **8 个取值**:四个协议终态
|
|
115
115
|
(`completed`/`failed`/`cancelled`/`interrupted`),加上 `awaiting-interaction`(出现待答
|
|
116
|
-
交互卡,运行仍活着)、`timeout
|
|
116
|
+
交互卡,运行仍活着)、`timeout`(窗口用尽,**不是失败**,随附部分内容,停点可命名时再带游标)、
|
|
117
117
|
`idle`(`cherry_wait` 遇到没有在途执行的会话,立即返回快照)、`subscription-lost`
|
|
118
118
|
(事件订阅丢失且重建失败,运行结局**不可知**,随附修复指引)。
|
|
119
119
|
|
|
@@ -128,9 +128,17 @@ cherry_interactions → 看待答的提问/审批卡;cherry_respond 作答
|
|
|
128
128
|
不在这个乘积里(每次并发读最多再带一整条消息,因为输出预算只在消息之间检查),parts 缓存另计。
|
|
129
129
|
等待槽位也计入等待类回答的时限:排到时限就放弃并把这一 part 标 `unavailable`。
|
|
130
130
|
- 历史走查被截断时一定说明(`truncationReason`,`limit` / `aggregate-bytes` / `deadline` 三种含义不同,见上),
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
`
|
|
131
|
+
并在停点可命名时给出 `messagesResumeCursor` 续读令牌。**停点不可命名时就不给**:对端位置为空、
|
|
132
|
+
带首尾空白或任意控制字符、形如已停用的 v1 令牌、令牌会超过 4096 字符上限、或没有可当锚点的
|
|
133
|
+
消息 id——此时 `truncated` 仍为 `true`,**缺失本身不代表历史已到底**。补救按 `truncationReason`
|
|
134
|
+
分:`limit` 停点只有在调用方自己握着上限时才靠更宽的 `limit`(`cherry_read` 与四个列表工具);
|
|
135
|
+
**wait 类回答的 `limit` 是它自己的固定条数额度**,更旧的历史要用 `cherry_read` 去读。
|
|
136
|
+
`aggregate-bytes` 停点不行——预算是它停下的原因,更宽的 `limit` 只会多付往返,被挡住的旧消息
|
|
137
|
+
在这一回答里拿不到;`safety-bound` 停点是内部熔断,调用方动不了它;`deadline`(只出现在 wait
|
|
138
|
+
类回答)同样改用 `cherry_read` 续读,它没有时限。
|
|
139
|
+
**两个面是同一条规则**:消息面的 `messagesResumeCursor` 与四个列表工具的
|
|
140
|
+
`resumeCursor` 都只发出本工具会收回的令牌;位置内部的普通空格合法,不会因此被拒。
|
|
141
|
+
某条消息自身 parts 没读全时带 `incomplete: true`(wait 类回答里被时限截断的那条消息会带 `partsTruncated: "deadline"`)。
|
|
134
142
|
- **等待类回答有自己的装配时限**:`cherry_send(wait: true)` / `cherry_wait` 在窗口结束后仍要读一段历史
|
|
135
143
|
(消息页 + 每条消息的 parts + 每个外置 `{ref}` 内容),这一步现在是**有时限的**——截至「你的窗口 +
|
|
136
144
|
同样长度的时间」,下限 1 秒、上限 15 秒(即窗口 1 秒 → 最多再等 1 秒;窗口 20 秒 → 最多再等 15 秒)。
|
|
@@ -151,7 +159,7 @@ cherry_interactions → 看待答的提问/审批卡;cherry_respond 作答
|
|
|
151
159
|
## 设置页与启用范围
|
|
152
160
|
|
|
153
161
|
插件同时是 **web client bundle**(`package.json` 的 `dsh.client`,导出 `./client`),通过
|
|
154
|
-
`settings.section` 槽位注册 **`cherry-remote`**(导航标签「Cherry
|
|
162
|
+
`settings.section` 槽位注册 **`cherry-remote`**(导航标签「Cherry 互联」)页面:
|
|
155
163
|
设备卡片(启用/停用/删除)、配对向导(粘贴 → 6 位验证码 → 终态)、启用范围面板,以及经
|
|
156
164
|
`/cherry-remote/api/events` SSE 推送的实时状态。
|
|
157
165
|
|