dsh-multi-chat 0.4.0 → 0.4.2

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 CHANGED
@@ -1,8 +1,8 @@
1
- # 🧱 DSH 多窗口墙 · Multi-Window Wall
1
+ # 💬 dsh-multi-chat —— 多对话,一屏驾驭
2
2
 
3
- > **一个浏览器,并排盯住你所有的 AI 任务。** 让 DSH 从「一次一个对话」变成「一屏全景驾驶舱」,还能用手机躺着看进度。
3
+ > **在 DeepSeek Harness 里同时开 N 个对话,并排盯住每一个 Agent 的实时进度,还能用手机躺着看。** 一个浏览器,从「一次一个对话」升级成「全景多对话驾驶舱」。
4
4
 
5
- 给 [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) 官方 Web 界面装上一个**多窗口墙**:在一张网格里同时显示 N 个正在运行的 DSH 实例(每个实例独立跑一个任务),所有 Agent 的实时进度、对话、输出**一眼尽收**,不用在无数标签页/窗口之间切来切去。
5
+ 给 [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) 官方 Web 界面装上一面**多窗口墙**:在一张网格里同时显示 N 个正在运行的 DSH 对话实例(每个实例独立跑一个任务),所有 Agent 的实时进度、对话、输出**一眼尽收**,不用在无数标签页/窗口之间切来切去。
6
6
 
7
7
  ## ✨ 它能做什么
8
8
 
@@ -10,11 +10,11 @@
10
10
  |------|------|
11
11
  | 📺 **多窗口墙** | 侧边栏一键进入,右侧对话区原位变成窗口网格,一个端口一格,并排看全部任务 |
12
12
  | 🔍 **自动发现** | 扫描端口区间自动发现正在运行的 DSH 实例,也可手动管理 |
13
- | ➕ **一键新建窗口** | 墙内直接启动全新 DSH 实例,凑成你的多任务矩阵 |
14
- | 📱 **手机访问** | 点「手机访问」自动起一个**带口令认证的局域网网关**,手机扫码/输入口令即可看进度 |
13
+ | ➕ **一键新建窗口** | 墙内直接启动全新 DSH 实例,凑成你的多对话矩阵 |
14
+ | 📱 **手机访问** | 点「手机访问」自动起一个**内置带口令认证的局域网网关**,手机打开 URL、输入口令即可看进度 |
15
15
  | 🛑 **窗口控制** | 单窗口放大、刷新、新标签页打开、关闭实例、列数切换(自动/1/2/3/4/6)|
16
16
 
17
- > **多任务 = 多端口。** 启动 N 个 `dsh web --port <n>`,每个实例独立跑一个任务;在任意一个实例里打开多窗口墙,即可并排看到全部。
17
+ > **多对话 = 多端口。** 启动 N 个 `dsh web --port <n>`,每个实例独立跑一个对话/任务;在任意一个实例里打开多窗口墙,即可并排看到全部。
18
18
 
19
19
  ## 🚀 30 秒上手
20
20
 
@@ -30,7 +30,7 @@ npx dsh-multi-chat start --ports 3080,3081,3082
30
30
 
31
31
  ## 为什么这样做
32
32
 
33
- - **不改动任何官方逻辑**:插件只注册两个**增量列表槽位**(`conversation.view` 视图环条目、`sidebar.footer.action` 侧边栏快捷入口)和只读 JSON 探活路由(`/multi/api/ports`、`/multi/api/status`、`/multi/api/stop`)。不替换任何既有槽位、不改写任何行、不触碰会话/代理/工具等核心逻辑。
33
+ - **不改动任何官方逻辑**:插件只注册两个**增量列表槽位**(`conversation.view` 视图环条目、`sidebar.footer.action` 侧边栏快捷入口)和五个只读 JSON 路由(`/multi/api/ports`、`/multi/api/status`、`/multi/api/stop`、`/multi/api/create`、`/multi/api/link`)。不替换任何既有槽位、不改写任何行、不触碰会话/代理/工具等核心逻辑。
34
34
  - **界面就是官方界面**:墙是官方视图环的一个视图,渲染在对话主面板内(不是弹层),主题、字号、图标、控件全部走官方 `--dsw-*` token 与官方 primitives(Button/Input/Menu/StateDot)。
35
35
  - **递归防护**:墙永远不嵌入自身端口;被嵌入页面带 `?multi-wall=embed` 标记,不注册任何墙界面,杜绝「墙中墙」无限递归。
36
36
  - **最小改动**:新增一个 client 插件包 + 一个 patch 行。
@@ -78,26 +78,23 @@ dsh plugin --profile web add <tarball> # 装进 profile
78
78
  3. 墙视图内:自动发现实例(自动排除自身端口)、列数切换(自动/1/2/3/4/6,默认横向铺满)、点标题放大、⟳ 单独刷新、↗ 新标签页打开、✕ 从视图移除、全部刷新、实时在线状态点。布局保存在 localStorage。
79
79
  4. 退出墙:点工具栏**右上角的「退出」按钮**,一键切回对话视图。
80
80
 
81
- ## 手机 / 远程访问(认证网关)
81
+ ## 手机 / 远程访问(内置认证网关)
82
82
 
83
- 官方 `dsh web` 出于安全**刻意禁止 `--host 0.0.0.0`**(会向网络暴露远程代码执行)。因此跨设备访问的正确姿势是:实例保持仅本机回环,在实例前挂一个**带令牌认证的网关**,由网关对外监听 `0.0.0.0`。
83
+ 官方 `dsh web` 出于安全**刻意禁止 `--host 0.0.0.0`**(会向网络暴露远程代码执行)。本插件内置了一个**带令牌认证的内联网关**:点工具栏「手机访问」按钮,它会**自动**为本实例启动一个网关(监听 `0.0.0.0`,反向代理到 `127.0.0.1:<本实例端口>`),并返回局域网 URL + 登录口令。
84
84
 
85
- ```bash
86
- # 一个实例 + 一个认证网关(手机在同一内网时打开 http://<局域网IP>:8443 登录)
87
- node scripts/gateway.mjs --target 127.0.0.1:3080 --listen 0.0.0.0:8443 --token <口令>
88
-
89
- # 加密:提供证书即走 HTTPS(跨公网必须,否则用 VPN)
90
- node scripts/gateway.mjs --target 127.0.0.1:3080 --listen 0.0.0.0:8443 --token <口令> --tls-cert cert.pem --tls-key key.pem
85
+ ```text
86
+ 点击「手机访问」→ 得到:
87
+ 手机在同一网络时可用:http://10.105.7.204:9477 口令:2efb23eade16
91
88
  ```
92
89
 
93
- 网关的安全模型:HMAC 签名的 HttpOnly/SameSite 会话 Cookie(默认 12h)、`Authorization: Bearer` 与 `?token=` 供脚本使用、按 IP 限流登录失败;所有代理请求把 Host/Origin 重写为回环目标,官方 `/api` 浏览器信任栅栏(DNS-rebinding 防线)因此判定为本地请求,无需重启加 `--trusted-host`;WebSocket 升级与 SSE 流原样透传。
90
+ 手机打开该 URL、输入口令即可进入完整 DSH 界面。网关的安全模型:
94
91
 
95
- `start-multi.ps1` 也能一键带网关启动:
92
+ - HMAC 签名的 HttpOnly/SameSite 会话 Cookie(默认 12h),`?token=` 供脚本快捷使用,按 IP 限流登录失败
93
+ - 所有代理请求把 Host/Origin 重写为回环目标,官方 `/api` 浏览器信任栅栏(DNS-rebinding 防线)判定为本地请求,无需重启加 `--trusted-host`
94
+ - WebSocket 升级与 SSE 流原样透传
95
+ - 目标端口撞上 Windows 排除段或已占用时,自动回退到 OS 分配的空闲端口
96
96
 
97
- ```powershell
98
- .\scripts\start-multi.ps1 -Ports "3080,3081" -Remote -Token "my-secret"
99
- # 或自签名加密:-TlsCert cert.pem -TlsKey key.pem
100
- ```
97
+ > 也有独立的 `scripts/gateway.mjs`(带可选 TLS)供进阶场景手动使用。
101
98
 
102
99
  ## 分发与安装
103
100
 
@@ -147,6 +144,14 @@ node bin/dsh-multi-chat.mjs stop
147
144
  node bin/dsh-multi-chat.mjs gateway --target 127.0.0.1:3080 --token <口令>
148
145
  ```
149
146
 
147
+ ## 🔍 发现与生态
148
+
149
+ 本插件遵循 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 官方 client 插件规范:
150
+
151
+ - **在 GitHub 插件生态中被发现**:给本仓库添加 [`dsh-plugin`](https://github.com/topics/dsh-plugin) topic,即可在官方 [`dsh-plugin` topic 页](https://github.com/topics/dsh-plugin) 被搜索到(官方推荐的第三方插件发现方式)。
152
+ - **三语技术文档**:插件包 `plugin/dsh-client-ui-multi-wall/` 下提供 `README.md`(英文)、`README.zh.md`(中文)与 `README.i18n.yaml`(双语一致性记录),结构与官方 `packages/client/*` 插件一致。
153
+ - **纯增量、不碰核心**:只注册 `conversation.view` / `sidebar.footer.action` 两个列表槽位 + `/multi/api/*` 只读路由,不改动任何官方核心逻辑。
154
+
150
155
  ## 在官方 monorepo 中的位置
151
156
 
152
157
  `packages/client/ui-multi-wall` 是遵循官方 client 插件规范的包(tsconfig host/client 分离、tsdown clientBundle、locales zh/en、invariant 伴随、HMR 安全测试),并已接入 `packages/bundle/web-app` 的 dsh.client roster 与 `tsconfig.client.json` 聚合。构建:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-multi-chat",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "DSH 多对话:在官方 DeepSeek Harness Web 界面里并排运行和监控多个对话实例(多窗口墙),并内置带口令认证的手机访问网关。npx dsh-multi-chat install|start|stop",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,45 +1,26 @@
1
1
  # @deepseek-ai/dsh-client-ui-multi-wall
2
2
 
3
- 多窗口墙(Multi-Window Wall):在官方 DSH Web 界面内显示所有正在运行的 DSH 实例。
3
+ English | [中文](README.zh.md)
4
4
 
5
- - **作为官方「视图环」的一个视图**(`conversation.view` 列表槽位,纯增量):点击入口后,右侧对话区**原位替换**为多窗口墙——一个窗口对应一个端口(`127.0.0.1:<port>`),每个窗口就是原版 DSH Web UI(iframe 嵌入),所有任务的进度同时可见,无需切换任务栏标签。
6
- - **侧边栏底部**新增「多窗口墙」快捷入口(`sidebar.footer.action` 列表槽位,纯增量),点击后跳到墙视图;对话区头部也会出现「多窗口墙」标签页,可直接点击切换。
7
- - 支持自动发现(扫描端口区间)、**新建窗口(启动全新 DSH 实例)**、列数切换(自动/1/2/3/4/6,默认横向铺满)、单窗口放大、单独/全部刷新、新标签页打开、实时在线状态点。
8
- - **退出**:工具栏右上角的 **✕ 退出**按钮,一键切回对话视图(等价于点击头部的「对话」标签页)。
9
- - **手机/远程访问**:工具栏「手机访问」按钮会自动为本实例启动一个**带令牌认证的内联网关**(无需外部命令),返回局域网 URL + 登录口令;手机打开 URL、输入口令即可进入。
10
- - **递归防护**:墙永远不会嵌入自身端口;被嵌入的页面携带 `?multi-wall=embed` 标记,不注册任何墙界面,从根上杜绝「墙中墙」。
11
- - **可关闭自身实例**:当前实例也显示在墙上(便于监控),其「关闭实例」按钮同样可用——两次确认后终止本端口服务(页面会断开)。
5
+ Multi-window wall plugin, browser half + node half: a grid of every running DSH instance, one pane per `127.0.0.1:<port>`, rendered inside the official web GUI as an additive `conversation.view` ring entry (order 20). The view swaps the chat panel in place for a wall of iframes, each loading the original DSH Web UI with a `?multi-wall=embed` flag that suppresses the wall UI inside the pane — recursion is stopped at the source. The sidebar foot gains a `sidebar.footer.action` shortcut (order 10) that clicks the header's view-ring tab for this plugin, so the switch goes through the official view-ring state machine rather than reaching into the chat store.
12
6
 
13
- ## 不改动任何官方逻辑
7
+ The wall's business state is a single store (`dsh.multi-wall`): the discovered port list and the grid column count, persisted across view switches and reloads. Discovery, liveness, create, and stop all flow through the node half's read-only JSON routes — `/multi/api/ports` (auto-discovery, excluding nothing so the serving instance is also watchable), `/multi/api/status` (liveness of a specific port list), `/multi/api/stop` (terminate a chosen instance), `/multi/api/create` (start a fresh instance, surfacing the child's stderr on failure), and `/multi/api/link` (phone access).
14
8
 
15
- 本插件只做两件事:
9
+ Phone/remote access: the official CLI forbids `--host 0.0.0.0` (it would expose remote code execution), so `/multi/api/link` lazily starts an **inline authenticated gateway** (raw `node:net` reverse proxy with an HMAC-signed session-cookie login, targets `127.0.0.1:<self-port>`, rewrites Host/Origin so the official `/api` browser-trust fence sees a local request, and passes WebSocket upgrades through). The route returns the LAN URLs plus the login token; the gateway falls back to an OS-assigned port when its intended port hits a Windows excluded range or is already bound.
16
10
 
17
- 1. **node half**:在 `webServer` 上注册五个只读 JSON 路由 `/multi/api/ports`(自动发现存活 DSH 实例,自动排除自身端口)、`/multi/api/status`(指定端口探活)、`/multi/api/stop`(关闭指定实例)、`/multi/api/create`(启动全新 DSH 实例,失败时回传子进程 stderr 等真实原因)、`/multi/api/link`(手机/远程访问链接)。
18
- 2. **browser half**:注册两个**增量列表槽位**(`conversation.view`、`sidebar.footer.action`),把墙作为官方视图环的一个视图渲染。
11
+ The `/client` exports the plugin body (`apply`/`inject`), the `WallView`/`WallToggle` components, the wall store factory, and the injected probe-face types.
19
12
 
20
- 不替换任何既有槽位、不改写任何行(row)、不触碰会话/代理/工具等核心逻辑。墙视图激活时,通过一条纯 CSS `:has()` 规则隐藏对话区底部的输入框与统计条(`[data-composer-seat]`),把整列高度让给墙;切回对话视图后输入框自动恢复。退出按钮通过点击官方视图环的第一个标签页(对话,order 0)来切换,复用官方 `actions.setView` 通道,不直接读取对话 store。
21
-
22
- ## 配置(可选)
13
+ ## Model Experience
23
14
 
24
- ```yaml
25
- # 覆盖自动发现区间或固定端口列表(默认扫描 3070–3110)
26
- - id: ui-multi-wall
27
- name: '@deepseek-ai/dsh-client-ui-multi-wall'
28
- config:
29
- scanFrom: 3070
30
- scanTo: 3110
31
- ports: [] # 设置后不再自动扫描
32
- publicUrl: '' # 可选:固定对外网关地址(设置则 /multi/api/link 直接返回它)
33
- gatewayPort: 0 # 内联网关端口;0(默认)= 实例端口 + 5000,撞段时自动回退 OS 分配
34
- gatewayToken: '' # 内联网关登录口令;空(默认)= 每次随机生成
35
- ```
15
+ None. The plugin adds no prompt content, no session event, and no model-visible input; the wall, its store, and every `/multi/api/*` route are UI/discovery surfaces only. No token or KV-cache effect.
36
16
 
37
- ## Model Experience
17
+ #### KV Cache effect
38
18
 
39
- 本插件不向模型请求注入任何内容,不改变模型可见输入,无 token/KV-cache 影响。
19
+ None. Nothing the plugin owns reaches the history tail or the model context.
40
20
 
41
21
  ## Known Limitations and Deferred Work
42
22
 
43
- - 墙视图依赖各实例 `127.0.0.1:<port>` 可直接访问;若某实例绑定到其它 host,请在外部自行配置。
44
- - 探活只检查 index 是否含 `__DSH_BOOT__` 标记;非 DSH 服务同端口会误报为「未发现」。
45
- - 墙视图是会话作用域的视图环条目:需要至少一个活跃会话,视图区才会渲染墙。
23
+ - **Loopback-only panes** — the wall embeds `127.0.0.1:<port>` and probes the loopback; an instance bound to a non-loopback host needs external configuration.
24
+ - **Probe is a marker check** — liveness only checks that the served index carries `__DSH_BOOT__`; a non-DSH service squatting the same port reads as "not found".
25
+ - **Session-scoped view** — the wall is a `conversation.view` ring entry, so it renders only with an active session.
26
+ - **Inline gateway is plain HTTP** — on a trusted LAN the token over plain HTTP is acceptable; across the internet prefer `publicUrl` (an external TLS gateway) or a VPN.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-multi-wall",
3
- "description": "Multi-window wall surface: a sidebar footer action that opens a full-screen wall of every running DSH instance (one pane per port), inside the official web GUI. Additive slots only 鈥?no existing row or interaction logic is changed.",
3
+ "description": "Multi-window wall surface: a sidebar footer action that opens a full-screen wall of every running DSH instance (one pane per port), inside the official web GUI. Additive slots only — no existing row or interaction logic is changed.",
4
4
  "version": "0.2.0",
5
5
  "publishConfig": {
6
6
  "access": "public"