dsh-session-bridge 0.2.0

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.md ADDED
@@ -0,0 +1,219 @@
1
+ # dsh-session-bridge — 会话桥 (Session bridge)
2
+
3
+ A [DSH](https://www.deepseek.com) plugin that lets the current agent drive
4
+ other real DSH sessions directly from a prompt — create sessions, send
5
+ messages to any session, wait for and read replies, resume offline sessions,
6
+ and find sessions across workspaces. On top of that it can **monitor and
7
+ schedule** a main task (watch its progress, nudge or correct its direction,
8
+ and stop it), and **archive** sessions the same way the DSH sidebar's Archive
9
+ action does.
10
+
11
+ > 中文文档见 [README.zh.md](./README.zh.md).
12
+
13
+ ## What it does
14
+
15
+ - **Create real DSH sessions.** `session_bridge_create` makes a new main
16
+ session (top-level UI session) in the current workspace, or in another
17
+ workspace when you pass `workspaceId` / `cwd`. It can send one first prompt
18
+ and optionally block until the first reply. Provider / model / reasoning
19
+ effort are inherited from the calling session by default.
20
+ - **Send messages to any session.** `session_bridge_send` appends a turn
21
+ (`mode=queue`) or injects steering into the running step (`mode=steer`), and
22
+ can optionally wait for the next reply.
23
+ - **Wait for a reply.** `session_bridge_wait` blocks until a new text assistant
24
+ reply appears after a given seq; with `requireTurnEnd` it also waits for the
25
+ turn to settle. Timeout / abort return the partial result rather than
26
+ throwing.
27
+ - **Read any session.** `session_bridge_read` folds a session's event log into
28
+ readable rows — live or offline (from persistence) — with `sinceSeq` paging,
29
+ role filtering, and a `limit` (default 20, max 100).
30
+ - **Resume offline sessions.** `session_bridge_resume` brings a persisted
31
+ session back online (idempotent); it can also override provider / model.
32
+ - **Find sessions.** `session_bridge_find` matches by title, id, workspace, or
33
+ directory across all workspaces, returning live/running state, title, and
34
+ working directory. Bridge-registered titles act as aliases.
35
+ - **Monitor and schedule a main task.** `session_bridge_status` reads a
36
+ session's real-time progress (running/idle, open turn, time since the last
37
+ event for stall detection, pending work, latest reply). `session_bridge_cancel`
38
+ stops a running session. `session_bridge_monitor_start` runs a **background
39
+ watchdog loop** that polls the task, nudges it when it stalls, corrects it
40
+ when it drifts, terminates it after it stays stuck, and wraps up when it
41
+ finishes.
42
+ - **Archive sessions.** `session_bridge_archive` adds a session to the DSH
43
+ workspace archive set (hidden from every grouping surface, history and
44
+ workspace position preserved). `session_bridge_archived` lists the archive
45
+ set, optionally resolving titles.
46
+
47
+ ## Monitoring worker
48
+
49
+ `session_bridge_monitor_start` installs a timer-driven loop. Every poll it
50
+ **observes → judges → schedules → logs** the target session:
51
+
52
+ | Observation | Action |
53
+ |---|---|
54
+ | A `doneKeywords` string appears in the reply and the session is idle | Wrap up and stop the watchdog (log `DONE`) |
55
+ | Idle with no pending work | Wrap up (settled) — no pointless nudging / cancelling |
56
+ | `running` and no event for more than `stalledMs` | Record a stall → `steer` a nudge (with `useLlm`, judge `offtrack`/`stuck` first) |
57
+ | Stall repeats ≥ `maxStuckCycles` | `cancel` the session |
58
+ | Making progress | Reset the stall counter (steady) |
59
+
60
+ The watchdog only treats **running** sessions as stalled, so a finished or idle
61
+ task is wrapped up rather than nudged forever. Logs go to
62
+ `~/.dsh/super-injector/dsh-session-bridge-monitor.log` (overridable).
63
+
64
+ Control it with `session_bridge_monitor_start` / `_stop` / `_list`.
65
+
66
+ ## Requirements
67
+
68
+ - [Node.js](https://nodejs.org) ≥ 20
69
+ - [pnpm](https://pnpm.io)
70
+ - DSH ≥ `0.1.0-rc.6`
71
+
72
+ ## Build
73
+
74
+ ```bash
75
+ # type-check + bundle the host build + pack a tgz (DSH_CHECKOUT points at the dsh source checkout)
76
+ bash scripts/build.sh && npm run build:client
77
+
78
+ # via the injector toolchain
79
+ dev_build_plugin dsh-session-bridge
80
+ ```
81
+
82
+ `build.sh` type-links against a local DSH checkout and is only for local dev.
83
+ The GitHub Actions CI (`ci.yml`) instead resolves the `@deepseek-ai/dsh-*`
84
+ prereleases from the registry — pinned to the `0.1.2-alpha.2` line, which is
85
+ the DSH API surface this code targets — then runs `pnpm typecheck` and
86
+ `pnpm build:client` (the self-contained `tsdown` bundle). Bump that pin
87
+ together with the code when you migrate to a newer DSH API.
88
+
89
+ ## Deploy
90
+
91
+ DSH web loads external plugins from the active profile. This package is a
92
+ **bundle**: its `package.json` declares `dsh.bundle.patch` →
93
+ [`cordis.patch.yml`](./cordis.patch.yml), whose `insert` row mounts the plugin.
94
+ That declaration is what lets `dsh plugin add` install the package *and*
95
+ activate it in one step.
96
+
97
+ ### Install from npm
98
+
99
+ The package is published to [npmjs.com](https://www.npmjs.com/package/dsh-session-bridge).
100
+ Releases are cut on a `v*` git tag by the `publish.yml` GitHub Actions workflow;
101
+ `package.json` and `dsh.plugin.json` versions are synced to that tag before
102
+ publishing.
103
+
104
+ ```bash
105
+ npx -p @deepseek-ai/dsh dsh plugin --profile web add dsh-session-bridge
106
+ ```
107
+
108
+ pnpm installs the published tarball and runs its `prepare` script (`tsdown`) to
109
+ ensure `lib/` is present, then `dsh` activates the bundle.
110
+
111
+ ### Install from GitHub
112
+
113
+ ```bash
114
+ npx -p @deepseek-ai/dsh dsh plugin --profile web add github:heartmove/dsh-session-bridge
115
+ ```
116
+
117
+ `dsh plugin` forwards to pnpm inside `~/.dsh/profiles/web/`, then reconciles the
118
+ bundle into the profile's `dsh.profile.bundles` layer list. A git install
119
+ fetches sources, so pnpm runs the package's `prepare` script (`tsdown`) to build
120
+ `lib/` from `src/` after checkout.
121
+
122
+ pnpm ≥ 10 refuses to run a git dependency's `prepare` script until it is
123
+ allowlisted, so the first `add` fails with an "Ignored build scripts" hint. Copy
124
+ the exact package key pnpm printed into the profile's `pnpm-workspace.yaml`
125
+ (`~/.dsh/profiles/web/pnpm-workspace.yaml`):
126
+
127
+ ```yaml
128
+ allowBuilds:
129
+ dsh-session-bridge: true
130
+ ```
131
+
132
+ then re-run the `add`. That allowance means "run this package's code on my
133
+ machine at install time" — only allow packages whose source you trust, and pin a
134
+ commit (`github:heartmove/dsh-session-bridge#<sha>`) so a later push cannot
135
+ silently change what runs.
136
+
137
+ Restart `dsh web`, then hard-refresh the page (Ctrl/Cmd+Shift+R).
138
+
139
+ ### Install from a local checkout
140
+
141
+ From the directory that contains this checkout:
142
+
143
+ ```bash
144
+ npx -p @deepseek-ai/dsh dsh plugin --profile web add ./dsh-session-bridge
145
+ ```
146
+
147
+ pnpm links the checkout and `dsh` activates the bundle the same way.
148
+
149
+ ### Manual link
150
+
151
+ To manage the profile by hand, link the package and list it as a bundle in
152
+ `~/.dsh/profiles/web/package.json` (the bundle's own `cordis.patch.yml` supplies
153
+ the loader row, so no `insert` entry is needed):
154
+
155
+ ```json
156
+ {
157
+ "dependencies": {
158
+ "dsh-session-bridge": "link:D:\\path\\to\\dsh-session-bridge"
159
+ },
160
+ "dsh": {
161
+ "profile": {
162
+ "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-session-bridge"]
163
+ }
164
+ }
165
+ }
166
+ ```
167
+
168
+ (On POSIX systems use `link:/path/to/dsh-session-bridge`.) Then run `pnpm install`
169
+ in the profile directory and restart `dsh web`.
170
+
171
+ ### Inject directly (dev)
172
+
173
+ For fast iteration while developing the plugin, you can also load it directly
174
+ through the injector toolchain (no bundle entry required):
175
+
176
+ ```bash
177
+ dev_inject_plugin D:\code\dsh-session-bridge
178
+ ```
179
+
180
+ Remove it with `dev_uninject_plugin dsh-session-bridge` (clears the injector
181
+ registration and junction; not re-assembled on restart).
182
+
183
+ ## Usage
184
+
185
+ | Tool | What it does |
186
+ |---|---|
187
+ | `session_bridge_create` | Create a main session (current or another workspace via `workspaceId` / `cwd`); optional first prompt + `waitForReply`. |
188
+ | `session_bridge_send` | Send a message (`mode=queue`/`steer`); optional wait-for-reply. |
189
+ | `session_bridge_wait` | Wait for a new text assistant reply after `sinceSeq`; optional `requireTurnEnd`. |
190
+ | `session_bridge_read` | Read messages — live or offline; `sinceSeq` paging, `role` filter, `limit`. |
191
+ | `session_bridge_resume` | Bring a persisted session back online (idempotent). |
192
+ | `session_bridge_find` | Find sessions by title / id / workspace / directory across workspaces. |
193
+ | `session_bridge_status` | Read a session's live progress (running, open turn, stall detection, pending work, latest reply). |
194
+ | `session_bridge_cancel` | Stop a running session (abort active turn; clear queued/steering work unless `keepInbox`). |
195
+ | `session_bridge_monitor_start` | Start a background watchdog on a main session (poll, nudge, correct, cancel, wrap up). |
196
+ | `session_bridge_monitor_stop` | Stop a watchdog (keep the session itself running). |
197
+ | `session_bridge_monitor_list` | List active watchdogs and their state. |
198
+ | `session_bridge_archive` | Archive a session (hidden from groupings; history and position preserved). |
199
+ | `session_bridge_archived` | List the archive set, optionally resolving titles. |
200
+
201
+ All tools return lossless JSON; wait-style tools never throw on timeout — they
202
+ return a `timedOut` / `aborted` flag.
203
+
204
+ ## Project layout
205
+
206
+ ```
207
+ src/
208
+ index.ts host plugin entry (registers the tools; mounts the monitor)
209
+ core.ts shared host logic (create/send/wait/read/find, status snapshot, archive attach)
210
+ tools.ts tool registrations (bridge + status/cancel + monitor + archive)
211
+ monitor.ts the background watchdog loop (statusSnapshot + rules + optional LLM judge)
212
+ registry.ts bridge-side title/workspace registry (~/.dsh/session-bridge-registry.json)
213
+ scripts/
214
+ build.sh type-check + link types against the DSH checkout
215
+ ```
216
+
217
+ ## License
218
+
219
+ MIT
package/README.zh.md ADDED
@@ -0,0 +1,183 @@
1
+ # dsh-session-bridge — 会话桥(Session bridge)
2
+
3
+ 一个 [DSH](https://www.deepseek.com) 插件:让当前 agent 能通过提示词驱动其它真实的 DSH 会话——
4
+ 创建主会话、向任意会话发消息、等待并读取回复、恢复离线会话、跨工作区按名称或 id 查找会话。
5
+ 在此之上,它还能**监控并调度**一个主任务(观察进度、卡住时催办、偏离时纠偏、必要时终止),
6
+ 以及像 DSH 侧边栏的 Archive 一样**归档**会话。
7
+
8
+ > English docs: [README.md](./README.md).
9
+
10
+ ## 功能
11
+
12
+ - **创建真实 DSH 会话。** `session_bridge_create` 在当前工作区创建新的主会话(顶层 UI 会话),
13
+ 传 `workspaceId` / `cwd` 则跨工作区;可选发送首条 prompt 并阻塞等待首条回复。provider / model /
14
+ reasoning effort 默认继承调用会话。
15
+ - **向任意会话发消息。** `session_bridge_send` 追加一轮(`mode=queue`)或向运行中的步骤注入
16
+ steering(`mode=steer`),可选等待下一条回复。
17
+ - **等待回复。** `session_bridge_wait` 阻塞直至 `sinceSeq` 之后出现新的带文本 assistant 回复;
18
+ 开 `requireTurnEnd` 则同时等待回合收尾。超时 / 中止返回部分结果,而非抛错。
19
+ - **读取任意会话。** `session_bridge_read` 把会话事件日志折叠为可读行——live 或离线(持久化)均可;
20
+ 支持 `sinceSeq` 分页、role 过滤、`limit`(默认 20,最大 100)。
21
+ - **恢复离线会话。** `session_bridge_resume` 让持久化会话重新上线(幂等),可覆盖 provider / model。
22
+ - **查找会话。** `session_bridge_find` 跨全部工作区按 标题 / id / workspace / 目录 匹配,返回
23
+ live/running 状态、标题、工作目录;bridge 登记的标题作为别名参与匹配。
24
+ - **监控并调度主任务。** `session_bridge_status` 读取会话实时进度(running/idle、是否 `openTurn`、
25
+ 距最近事件毫秒数做卡住检测、待处理消息、最新回复);`session_bridge_cancel` 停止一个运行中的会话;
26
+ `session_bridge_monitor_start` 运行一个**后台守护循环**,轮询任务、卡住时催办、偏离时纠偏、
27
+ 持续卡住则终止、完成即收尾。
28
+ - **归档会话。** `session_bridge_archive` 把会话加入 DSH workspace 归档集合(从所有分组视图隐藏,
29
+ 历史与位置保留);`session_bridge_archived` 列出归档集合,可选解析标题。
30
+
31
+ ## 监控守护循环
32
+
33
+ `session_bridge_monitor_start` 安装一个定时器驱动的循环。每轮对目标会话执行
34
+ 「观察 → 判定 → 调度 → 落日志」:
35
+
36
+ | 判定 | 动作 |
37
+ |---|---|
38
+ | 回复命中 `doneKeywords` 且会话空闲 | 收尾并停止守护(日志 `DONE`) |
39
+ | 空闲且无待处理 | 收尾(settled)——不无谓催办 / 取消 |
40
+ | `running` 且距最近事件超过 `stalledMs` | 记一次卡住 → `steer` 催办(开 `useLlm` 时先判 `offtrack`/`stuck`) |
41
+ | 连续卡住 ≥ `maxStuckCycles` | `cancel` 终止 |
42
+ | 正常推进 | 重置卡住计数(steady) |
43
+
44
+ 守护只对 **running** 会话判定"卡住",因此已完成/空闲的任务会被收尾而非无限催办。日志写入
45
+ `~/.dsh/super-injector/dsh-session-bridge-monitor.log`(可用 `logFile` 覆盖)。
46
+
47
+ 用 `session_bridge_monitor_start` / `_stop` / `_list` 控制。
48
+
49
+ ## 环境要求
50
+
51
+ - [Node.js](https://nodejs.org) ≥ 20
52
+ - [pnpm](https://pnpm.io)
53
+ - DSH ≥ `0.1.0-rc.6`
54
+
55
+ ## 构建
56
+
57
+ ```bash
58
+ # 类型检查 + 打包 host bundle + 生成 tgz(DSH_CHECKOUT 指向 dsh 源码 checkout)
59
+ bash scripts/build.sh && npm run build:client
60
+
61
+ # 或经注入器工具链
62
+ dev_build_plugin dsh-session-bridge
63
+ ```
64
+
65
+ ## 部署
66
+
67
+ DSH web 从活动 profile 加载外部插件。本包是一个 **bundle**:`package.json` 声明了
68
+ `dsh.bundle.patch` → [`cordis.patch.yml`](./cordis.patch.yml),其 `insert` 行挂载插件。
69
+ 正是这一声明让 `dsh plugin add` 能**一步安装并激活**本包。
70
+
71
+ ### 从 npm 安装
72
+
73
+ 本包已发布到 [npmjs.com](https://www.npmjs.com/package/dsh-session-bridge)。
74
+ 发布由 `publish.yml` GitHub Actions 工作流在 `v*` 标签触发;发布前会把
75
+ `package.json` 与 `dsh.plugin.json` 的版本同步到该标签。
76
+
77
+ ```bash
78
+ npx -p @deepseek-ai/dsh dsh plugin --profile web add dsh-session-bridge
79
+ ```
80
+
81
+ pnpm 会安装发布的 tarball 并运行其 `prepare` 脚本(`tsdown`)以确保 `lib/` 就绪,
82
+ 随后 `dsh` 激活该 bundle。
83
+
84
+ ### 从 GitHub 安装
85
+
86
+ ```bash
87
+ npx -p @deepseek-ai/dsh dsh plugin --profile web add github:heartmove/dsh-session-bridge
88
+ ```
89
+
90
+ `dsh plugin` 在 `~/.dsh/profiles/web/` 内转发给 pnpm,然后把本 bundle 归并到 profile 的
91
+ `dsh.profile.bundles` 层列表。git 安装会拉取源码,因此 pnpm 会在 checkout 后运行本包的
92
+ `prepare` 脚本(`tsdown`)从 `src/` 构建 `lib/`。
93
+
94
+ pnpm ≥ 10 默认拒绝运行 git 依赖的 `prepare` 脚本,首次 `add` 会报 "Ignored build scripts" 提示。
95
+ 把 pnpm 打印出的包名复制到 profile 的 `pnpm-workspace.yaml`
96
+ (`~/.dsh/profiles/web/pnpm-workspace.yaml`):
97
+
98
+ ```yaml
99
+ allowBuilds:
100
+ dsh-session-bridge: true
101
+ ```
102
+
103
+ 然后重新运行 `add`。该放行表示"在安装时运行这个包的代码"——只放行源码可信的包,并锁定 commit
104
+ (`github:heartmove/dsh-session-bridge#<sha>`)以避免后续推送静默改变运行内容。
105
+
106
+ 之后重启 `dsh web`,并强制刷新页面(Ctrl/Cmd+Shift+R)。
107
+
108
+ ### 从本地 checkout 安装
109
+
110
+ 在包含本 checkout 的目录下:
111
+
112
+ ```bash
113
+ npx -p @deepseek-ai/dsh dsh plugin --profile web add ./dsh-session-bridge
114
+ ```
115
+
116
+ pnpm 链接该 checkout,`dsh` 以同样的方式激活 bundle。
117
+
118
+ ### 手动 link
119
+
120
+ 想手动管理 profile 时,把本包链接并列入 `~/.dsh/profiles/web/package.json` 的 bundles
121
+ (bundle 自带的 `cordis.patch.yml` 提供 loader 行,无需额外的 `insert` 条目):
122
+
123
+ ```json
124
+ {
125
+ "dependencies": {
126
+ "dsh-session-bridge": "link:D:\\path\\to\\dsh-session-bridge"
127
+ },
128
+ "dsh": {
129
+ "profile": {
130
+ "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-session-bridge"]
131
+ }
132
+ }
133
+ }
134
+ ```
135
+
136
+ (POSIX 系统用 `link:/path/to/dsh-session-bridge`。)然后在 profile 目录运行 `pnpm install` 并重启 `dsh web`。
137
+
138
+ ### 直接注入(开发用)
139
+
140
+ 开发调试阶段也可经注入器工具链直接加载(无需 bundle 条目):
141
+
142
+ ```bash
143
+ dev_inject_plugin D:\code\dsh-session-bridge
144
+ ```
145
+
146
+ 卸载用 `dev_uninject_plugin dsh-session-bridge`(清除注入器注册与 junction;重启不再自动装配)。
147
+
148
+ ## 工具清单
149
+
150
+ | 工具 | 作用 |
151
+ |---|---|
152
+ | `session_bridge_create` | 创建主会话(当前或其它工作区,经 `workspaceId` / `cwd`);可选首条 prompt + `waitForReply`。 |
153
+ | `session_bridge_send` | 发消息(`mode=queue`/`steer`);可选等待回复。 |
154
+ | `session_bridge_wait` | 等待 `sinceSeq` 之后新的带文本 assistant 回复;可选 `requireTurnEnd`。 |
155
+ | `session_bridge_read` | 读取消息 —— live 或离线;`sinceSeq` 分页、`role` 过滤、`limit`。 |
156
+ | `session_bridge_resume` | 让持久化会话重新上线(幂等)。 |
157
+ | `session_bridge_find` | 跨工作区按 标题 / id / workspace / 目录 查找会话。 |
158
+ | `session_bridge_status` | 读取会话实时进度(running、openTurn、卡住检测、待处理、最新回复)。 |
159
+ | `session_bridge_cancel` | 停止运行中的会话(中止活动 turn;`keepInbox` 保留排队/steering 输入)。 |
160
+ | `session_bridge_monitor_start` | 对一个主会话启动后台守护(轮询、催办、纠偏、终止、收尾)。 |
161
+ | `session_bridge_monitor_stop` | 停止守护(会话本身不终止)。 |
162
+ | `session_bridge_monitor_list` | 列出活动守护及其状态。 |
163
+ | `session_bridge_archive` | 归档会话(从分组隐藏;历史与位置保留)。 |
164
+ | `session_bridge_archived` | 列出归档集合,可选解析标题。 |
165
+
166
+ 所有工具输出 lossless JSON;等待类工具超时不抛错,返回 `timedOut` / `aborted` 标记。
167
+
168
+ ## 项目结构
169
+
170
+ ```
171
+ src/
172
+ index.ts host 插件入口(注册工具;挂载监控)
173
+ core.ts 共享 host 逻辑(create/send/wait/read/find、status 快照、archive 记账)
174
+ tools.ts 工具注册(bridge + status/cancel + monitor + archive)
175
+ monitor.ts 后台守护循环(statusSnapshot + 规则 + 可选 LLM 判定)
176
+ registry.ts 桥侧标题/workspace 登记表(~/.dsh/session-bridge-registry.json)
177
+ scripts/
178
+ build.sh 类型检查 + 链接 DSH checkout 类型
179
+ ```
180
+
181
+ ## License
182
+
183
+ MIT
@@ -0,0 +1,8 @@
1
+ # Bundle patch layer for dsh-session-bridge. This file is referenced by the
2
+ # package.json `dsh.bundle.patch` declaration, so `dsh plugin add` reconciles
3
+ # this package into the profile's bundle list and this row mounts the plugin.
4
+ # `name` is the package name: the Loader resolves it from the profile's
5
+ # node_modules (where pnpm installs the checkout / git dependency).
6
+ - insert:
7
+ - id: dsh-session-bridge
8
+ name: dsh-session-bridge
@@ -0,0 +1,27 @@
1
+ {
2
+ "id": "dsh-external/dsh-session-bridge",
3
+ "version": "0.2.0",
4
+ "main": "./lib/index.js",
5
+ "description": "会话桥:创建主会话 / 向任意会话发消息 / 等待回复 / 读取消息 / 按名或 id 查找会话(支持跨工作区);另含监控/调度主任务与归档会话。",
6
+ "engines": {
7
+ "dsh": "^0.1.0-rc.6 || ^0.1.1-0 || ^0.1.2-0"
8
+ },
9
+ "contributes": {
10
+ "tools": [
11
+ "session_bridge_create",
12
+ "session_bridge_send",
13
+ "session_bridge_resume",
14
+ "session_bridge_wait",
15
+ "session_bridge_read",
16
+ "session_bridge_find",
17
+ "session_bridge_status",
18
+ "session_bridge_cancel",
19
+ "session_bridge_monitor_start",
20
+ "session_bridge_monitor_stop",
21
+ "session_bridge_monitor_list",
22
+ "session_bridge_archive",
23
+ "session_bridge_archived"
24
+ ],
25
+ "skills": []
26
+ }
27
+ }