@twinsearth/dsh-master 3.2.8 → 3.2.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.md +7 -3
- package/client.js +102 -31
- package/dist-host/kernel.js +1 -1
- package/docs/ARCHITECTURE.md +2 -2
- package/docs/CHANGELOG.md +12 -0
- package/docs/RELEASE-v3.2.8.md +27 -0
- package/docs/RELEASE-v3.2.9.md +29 -0
- package/docs/ROADMAP.md +1 -1
- package/docs/SECURITY.md +1 -1
- package/docs/SUPERAGENT.md +2 -2
- package/package.json +1 -1
- package/src/kernel.ts +1 -1
package/README.md
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# dsh-Master(房主)
|
|
2
2
|
|
|
3
3
|
> 与瓮城 **dsh-Fang** 并行的主 Agent 插件。
|
|
4
|
-
> 当前版本:`3.2.
|
|
4
|
+
> 当前版本:`3.2.9`(面板交互修复线;tag / GitHub Release / NPM public)。
|
|
5
5
|
> 仓库:https://github.com/TwinsEarth/dsh-Master
|
|
6
6
|
|
|
7
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
8
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
9
|
+
|
|
7
10
|
## 这是什么
|
|
8
11
|
|
|
9
12
|
dsh-Master 不接管瓮城的「母体 / 原身 / 分身」生命周期;它是一块**并列的主插件**,
|
|
@@ -84,7 +87,8 @@ dsh plugin add <package> # 加载 dist-host/dist-worker
|
|
|
84
87
|
|
|
85
88
|
## 状态
|
|
86
89
|
|
|
90
|
+
- 3.2.9 发布线:房主面板改注册到 `shell.overlay` 常驻浮层——点击面板之外不收起、侧栏「房主」按钮二次点击收起、正文独立滚动;新增无浏览器 hook 运行时行为测试(开关、无 outside-click 监听、滚动容器、SSE 失败不卸载面板)。
|
|
87
91
|
- 3.2.8 发布线:与瓮城通过 fang-master contract 1.0 互联(local/http/file/legacy 四级保底);GitHub Release + NPM public。
|
|
88
92
|
- 当前工作树完成新一轮审计修复:工具名/死循环阈值、Router 鉴权与生命周期、真实路由分流、契约幂等与超时、PR 护栏与交付、飞书加密、长 Shell 后台作业、成本实测接线、PJM 派生契约。
|
|
89
|
-
- 验收:`npm run check` / `npm run build` / `npm test`
|
|
90
|
-
-
|
|
93
|
+
- 验收:`npm run check` / `npm run build` / `npm test` 全绿(188/188);真实双 Host/fork 落库、工具写读、SSE、回写、配额与桥清理断言通过。详见复盘文档。
|
|
94
|
+
- 发布不等于安装:本流程不修改任何用户 profile(当前 desktop profile 仍为 3.2.8,升级需另行授权)。
|
package/client.js
CHANGED
|
@@ -2,11 +2,18 @@
|
|
|
2
2
|
// Copyright (c) 2026 dsh-Master contributors — see LICENSE-CORE.
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Dsh-Master(房主)Web Client:侧栏「房主」入口 +
|
|
5
|
+
* Dsh-Master(房主)Web Client:侧栏「房主」入口 + 只读状态面板。
|
|
6
6
|
*
|
|
7
7
|
* 只做观察面板(3.2.0 架构骨架):展示角色、三个子插件的激活状态、与瓮城的
|
|
8
8
|
* 服务协作状态。数据来自 core 的只读路由 `/dsh-master/api/status`。
|
|
9
9
|
* 不写任何业务状态,不接管宿主根节点。
|
|
10
|
+
*
|
|
11
|
+
* 面板与按钮分离(3.2.9):按钮注册在 `sidebar.footer.action`,面板注册在
|
|
12
|
+
* `shell.overlay`(DSH 的整框浮层,位于所有列与滚动容器之外,且本身
|
|
13
|
+
* click-through)。两者通过模块级 store 共享「是否展开」:
|
|
14
|
+
* - 点击页面其他位置不会关闭面板(浮层没有 outside-click 收回逻辑);
|
|
15
|
+
* - 再次点击「房主」按钮由 `togglePanel()` 收起;
|
|
16
|
+
* - 面板固定 viewport 高度,正文 `overflow-y: auto`,长内容可滚动查看。
|
|
10
17
|
*/
|
|
11
18
|
window.__ModuleLoader__.load({
|
|
12
19
|
id: '@twinsearth/dsh-master',
|
|
@@ -21,12 +28,22 @@ window.__ModuleLoader__.load({
|
|
|
21
28
|
boxShadow: '-16px 0 40px rgba(16,17,20,.16)', display: 'flex', flexDirection: 'column',
|
|
22
29
|
fontFamily: '-apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei",sans-serif',
|
|
23
30
|
fontSize: 13, color: '#1D1D1F',
|
|
31
|
+
// shell.overlay 整层是 click-through:面板自己opt-in接收指针事件,
|
|
32
|
+
// 面板之外的点击穿透到下面的应用,不会触发任何收回。
|
|
33
|
+
pointerEvents: 'auto',
|
|
34
|
+
},
|
|
35
|
+
head: {
|
|
36
|
+
flex: '0 0 auto', display: 'flex', alignItems: 'center', gap: 8, padding: '14px 16px',
|
|
37
|
+
borderBottom: '1px solid rgba(16,17,20,.08)',
|
|
24
38
|
},
|
|
25
|
-
head: { display: 'flex', alignItems: 'center', gap: 8, padding: '14px 16px', borderBottom: '1px solid rgba(16,17,20,.08)' },
|
|
26
39
|
title: { fontSize: 14, fontWeight: 700 },
|
|
27
40
|
sub: { fontSize: 11.5, color: '#86868B' },
|
|
28
41
|
close: { marginLeft: 'auto', width: 28, height: 28, borderRadius: 8, border: '1px solid rgba(16,17,20,.12)', background: '#fff', color: '#5F6368', cursor: 'pointer' },
|
|
29
|
-
body: {
|
|
42
|
+
body: {
|
|
43
|
+
flex: '1 1 auto', minHeight: 0, overflowY: 'auto', overscrollBehavior: 'contain',
|
|
44
|
+
scrollbarGutter: 'stable', scrollbarWidth: 'thin',
|
|
45
|
+
padding: '12px 14px 18px', display: 'flex', flexDirection: 'column', gap: 10,
|
|
46
|
+
},
|
|
30
47
|
card: { border: '1px solid rgba(16,17,20,.1)', borderRadius: 12, padding: '10px 11px', background: '#FAFAFC', display: 'flex', flexDirection: 'column', gap: 4 },
|
|
31
48
|
row: { display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' },
|
|
32
49
|
name: { fontSize: 13, fontWeight: 600 },
|
|
@@ -40,7 +57,37 @@ window.__ModuleLoader__.load({
|
|
|
40
57
|
borderRadius: 8, border: '1px solid rgba(16,17,20,.12)', background: '#fff', color: '#1D1D1F',
|
|
41
58
|
cursor: 'pointer', fontSize: 12.5, fontWeight: 600, fontFamily: 'inherit',
|
|
42
59
|
},
|
|
43
|
-
|
|
60
|
+
fabOpen: {
|
|
61
|
+
display: 'inline-flex', alignItems: 'center', gap: 6, height: 28, padding: '0 9px',
|
|
62
|
+
borderRadius: 8, border: '1px solid rgba(16,17,20,.24)', background: '#F2F2F5', color: '#1D1D1F',
|
|
63
|
+
cursor: 'pointer', fontSize: 12.5, fontWeight: 600, fontFamily: 'inherit',
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 面板展开状态:按钮(sidebar.footer.action)与面板(shell.overlay)是两个
|
|
69
|
+
* 独立注册的组件,状态必须放在模块级 store 里,不能放在任一组件内部。
|
|
70
|
+
*/
|
|
71
|
+
const panelState = { open: false }
|
|
72
|
+
const panelListeners = new Set()
|
|
73
|
+
const getPanelOpen = () => panelState.open
|
|
74
|
+
const setPanelOpen = (next) => {
|
|
75
|
+
const value = Boolean(next)
|
|
76
|
+
if (panelState.open === value) return
|
|
77
|
+
panelState.open = value
|
|
78
|
+
for (const listener of panelListeners) {
|
|
79
|
+
try { listener() } catch { /* 订阅者异常不影响其他订阅者 */ }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const togglePanel = () => setPanelOpen(!panelState.open)
|
|
83
|
+
const subscribePanel = (listener) => {
|
|
84
|
+
panelListeners.add(listener)
|
|
85
|
+
return () => { panelListeners.delete(listener) }
|
|
86
|
+
}
|
|
87
|
+
function usePanelOpen() {
|
|
88
|
+
const [open, setOpen] = React.useState(getPanelOpen)
|
|
89
|
+
React.useEffect(() => subscribePanel(() => setOpen(getPanelOpen())), [])
|
|
90
|
+
return open
|
|
44
91
|
}
|
|
45
92
|
|
|
46
93
|
const tag = (text, color) => h('span', { style: { ...S.tag, ...(color ? { color, background: 'rgba(16,17,20,.05)' } : {}) } }, text)
|
|
@@ -194,7 +241,7 @@ window.__ModuleLoader__.load({
|
|
|
194
241
|
)
|
|
195
242
|
}
|
|
196
243
|
|
|
197
|
-
function MasterPanel(
|
|
244
|
+
function MasterPanel() {
|
|
198
245
|
const [status, setStatus] = React.useState(null)
|
|
199
246
|
const [error, setError] = React.useState('')
|
|
200
247
|
|
|
@@ -217,35 +264,51 @@ window.__ModuleLoader__.load({
|
|
|
217
264
|
}, [])
|
|
218
265
|
|
|
219
266
|
const items = status && Array.isArray(status.subplugins) ? status.subplugins : []
|
|
220
|
-
return h('
|
|
221
|
-
h('div', { style: S.
|
|
222
|
-
|
|
223
|
-
h('
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
h(
|
|
236
|
-
h(
|
|
237
|
-
|
|
238
|
-
)),
|
|
239
|
-
|
|
267
|
+
return h('aside', { style: S.panel, id: 'dsh-master-panel', 'aria-label': '房主状态' },
|
|
268
|
+
h('div', { style: S.head },
|
|
269
|
+
h('span', { style: S.title }, '房主 · dsh-Master'),
|
|
270
|
+
h('span', { style: S.sub }, status ? `${status.version} · ${status.role}` : '读取中'),
|
|
271
|
+
h('button', {
|
|
272
|
+
type: 'button',
|
|
273
|
+
style: S.close,
|
|
274
|
+
title: '收起面板',
|
|
275
|
+
'aria-label': '收起房主面板',
|
|
276
|
+
onClick: () => setPanelOpen(false),
|
|
277
|
+
}, '×')),
|
|
278
|
+
h('div', { style: S.body },
|
|
279
|
+
error ? h('div', { style: S.error }, error) : null,
|
|
280
|
+
status ? h('div', { style: S.card },
|
|
281
|
+
h('div', { style: S.row }, h('span', { style: S.name }, '主 Agent 控制面'), tag('与瓮城并行')),
|
|
282
|
+
h('div', { style: S.desc }, '角色:' + status.role + ' · 版本:' + status.version),
|
|
283
|
+
h('div', { style: S.desc }, '运行:' + Math.max(1, Math.round((status.uptimeMs || 0) / 60000)) + ' 分钟'),
|
|
284
|
+
) : null,
|
|
285
|
+
...items.map((item) => h(SubpluginCard, { key: item.id, item })),
|
|
286
|
+
h(FangCard, { cooperation: status && status.cooperation }),
|
|
287
|
+
h(LiveFeed),
|
|
288
|
+
h('div', { style: S.desc }, '3.2.9:面板常驻(点面板外不收起、按钮二次点击收起、长内容可滚动);实时流(SSE)+ token 轮换/审计 + Worker 并发配额。'),
|
|
289
|
+
))
|
|
240
290
|
}
|
|
241
291
|
|
|
242
|
-
/**
|
|
292
|
+
/** shell.overlay:整框浮层里的面板本体;关闭时不渲染任何节点。 */
|
|
293
|
+
function MasterOverlay() {
|
|
294
|
+
const open = usePanelOpen()
|
|
295
|
+
return open ? h(MasterPanel) : null
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* sidebar.footer.action 槽:一个「房主」按钮。
|
|
300
|
+
* 再点一次收起面板(之前只 setOpen(true),面板打开后按钮无法关闭)。
|
|
301
|
+
*/
|
|
243
302
|
function MasterSeat() {
|
|
244
|
-
const
|
|
245
|
-
return h('
|
|
246
|
-
|
|
247
|
-
open ?
|
|
248
|
-
|
|
303
|
+
const open = usePanelOpen()
|
|
304
|
+
return h('button', {
|
|
305
|
+
type: 'button',
|
|
306
|
+
style: open ? S.fabOpen : S.fab,
|
|
307
|
+
title: open ? '房主 · 点击收起控制面' : '房主 · 主 Agent 控制面',
|
|
308
|
+
'aria-expanded': open ? 'true' : 'false',
|
|
309
|
+
'aria-controls': 'dsh-master-panel',
|
|
310
|
+
onClick: () => togglePanel(),
|
|
311
|
+
}, '◈ 房主')
|
|
249
312
|
}
|
|
250
313
|
|
|
251
314
|
return {
|
|
@@ -257,6 +320,14 @@ window.__ModuleLoader__.load({
|
|
|
257
320
|
order: 79,
|
|
258
321
|
label: '房主',
|
|
259
322
|
}, MasterSeat))
|
|
323
|
+
// 面板放在 shell.overlay:位于所有列与滚动容器之外,且整层 click-through,
|
|
324
|
+
// 因此不会随侧栏(或宿主弹层)卸载,点击面板外也不会收回。
|
|
325
|
+
ctx.slots.inject('shell.overlay', () => ctx.slots.register({
|
|
326
|
+
name: 'shell.overlay',
|
|
327
|
+
id: 'dsh-master-panel',
|
|
328
|
+
order: 78,
|
|
329
|
+
label: '房主面板',
|
|
330
|
+
}, MasterOverlay))
|
|
260
331
|
},
|
|
261
332
|
}
|
|
262
333
|
},
|
package/dist-host/kernel.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* 与瓮城 dsh-Fang 的协作只走 DSH 服务键,不 import fang 代码。
|
|
8
8
|
*/
|
|
9
9
|
import crypto from 'node:crypto';
|
|
10
|
-
export const MASTER_VERSION = '3.2.
|
|
10
|
+
export const MASTER_VERSION = '3.2.9';
|
|
11
11
|
export const FANG_CONTRACT_MIN = '3.1.14';
|
|
12
12
|
export const SERVICE = Object.freeze({
|
|
13
13
|
master: 'dshMaster',
|
package/docs/ARCHITECTURE.md
CHANGED
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 3.2.9(2026-11-12,tag / GitHub Release / NPM public)
|
|
2
|
+
|
|
3
|
+
**主题:房主面板交互修复(常驻 / 可收起 / 可滚动)+ 客户端行为测试。**
|
|
4
|
+
|
|
5
|
+
- 面板常驻:面板从 `sidebar.footer.action` 单元格移到 `shell.overlay` 整框浮层(位于所有列与宿主滚动容器之外,整层 click-through,面板自行 opt-in 指针事件),不再随侧栏或宿主弹层卸载;插件不注册任何 window/document 监听,因此点击面板之外不会收起。
|
|
6
|
+
- 按钮收起:侧栏「房主」按钮由 `setOpen(true)` 改为 `togglePanel()`,二次点击收起;按钮补 `aria-expanded` / `aria-controls` 与展开态样式。
|
|
7
|
+
- 面板滚动:`aside` 固定 viewport 高度,正文成为独立滚动容器(`flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable`),长内容不再被裁切。
|
|
8
|
+
- 状态共享:按钮与面板是两个独立注册的组件,展开态放在模块级 store(订阅 + `useState` 同步),不依赖任一组件生命周期。
|
|
9
|
+
- 测试:新增 `test/client-panel.test.mjs`,用最小 hook 运行时(`node:vm` + 假 React/槽位)真实渲染组件,断言开关、无 outside-click 监听、滚动容器样式,以及 SSE token 405 时面板不卸载;全量 188/188 通过。
|
|
10
|
+
- 顺带把面板底部过期的版本说明从 3.2.7 更新到 3.2.9。
|
|
11
|
+
- 已知限制(非本版范围):mother 角色下 Router 子插件按角色门禁禁用,`/superagent/stream-token` 路由不存在,DSH 未匹配路由对 POST 回 405,面板因此显示「实时流 token 获取失败(HTTP 405)」;这是角色门禁的预期表现,本版未改文案。
|
|
12
|
+
|
|
1
13
|
## 3.2.8(2026-11-12,tag / GitHub Release / NPM public)
|
|
2
14
|
|
|
3
15
|
**主题:真实双 Host/fork 验收驱动的安全、生命周期、契约与 UI 收口。**
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# dsh-Master v3.2.8 发布门禁
|
|
2
|
+
|
|
3
|
+
日期:2026-11-12。
|
|
4
|
+
|
|
5
|
+
## 内容
|
|
6
|
+
|
|
7
|
+
本版将 v3.2.7 后的全面审计修复正式发布:Worker/工具、Router 生命周期与鉴权、契约幂等与文件桥清理、PR 交付护栏与接线、飞书加密、长 Shell 后台作业、HarnessMM 实测接线、PJM 派生契约、UI token 轮换与测试基础设施。
|
|
8
|
+
|
|
9
|
+
完整证据见 `REVIEW-v3.2.7.md` 与 `SMOKE-3.2.7.md`。
|
|
10
|
+
|
|
11
|
+
## 发布前实测
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
npm run check 0 error
|
|
15
|
+
npm run build 0 error(dist-host + dist-worker)
|
|
16
|
+
npm test 185 / 185 pass / 0 fail
|
|
17
|
+
npm run test:clean 185 / 185 pass / 0 fail(不使用 --test-force-exit)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 三方发布目标
|
|
21
|
+
|
|
22
|
+
- `main`:发布提交;
|
|
23
|
+
- `v3.2.8`:annotated tag;
|
|
24
|
+
- GitHub Release:tarball + sha256 + manifest;
|
|
25
|
+
- NPM:`@twinsearth/dsh-master@3.2.8`,`access=public`。
|
|
26
|
+
|
|
27
|
+
发布不等同于安装:本流程不修改任何用户 profile。
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# dsh-Master v3.2.9 发布门禁
|
|
2
|
+
|
|
3
|
+
日期:2026-11-12。
|
|
4
|
+
|
|
5
|
+
## 内容
|
|
6
|
+
|
|
7
|
+
本版只修房主面板的三项交互:面板常驻(点击面板之外不收起)、侧栏「房主」按钮二次点击收起、面板正文可滚动。面板从侧栏单元格改注册到 `shell.overlay` 整框浮层,展开态由模块级 store 共享,按钮与面板互不依赖对方生命周期。新增无浏览器行为测试 `test/client-panel.test.mjs`(最小 hook 运行时真实渲染注册组件)。
|
|
8
|
+
|
|
9
|
+
## 发布前实测
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
npm run check 0 error
|
|
13
|
+
npm run build 0 error(dist-host + dist-worker)
|
|
14
|
+
npm test 188 / 188 pass / 0 fail
|
|
15
|
+
npm run test:clean 188 / 188 pass / 0 fail(不使用 --test-force-exit)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 三方发布目标
|
|
19
|
+
|
|
20
|
+
- `main`:发布提交;
|
|
21
|
+
- `v3.2.9`:annotated tag;
|
|
22
|
+
- GitHub Release:tarball + sha256 + manifest;
|
|
23
|
+
- NPM:`@twinsearth/dsh-master@3.2.9`,`access=public`。
|
|
24
|
+
|
|
25
|
+
发布不等同于安装:本流程不修改任何用户 profile(desktop profile 仍停在 3.2.8,升级需另行授权)。
|
|
26
|
+
|
|
27
|
+
## 已知限制
|
|
28
|
+
|
|
29
|
+
mother 角色下 Router 子插件按角色门禁禁用,`/superagent/stream-token` 不存在,DSH 未匹配路由对 POST 返回 405,面板显示「实时流 token 获取失败(HTTP 405)」。这是角色门禁的预期表现,本版未改文案。
|
package/docs/ROADMAP.md
CHANGED
package/docs/SECURITY.md
CHANGED
package/docs/SUPERAGENT.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# SuperAgent(v3.2.
|
|
1
|
+
# SuperAgent(v3.2.9)
|
|
2
2
|
|
|
3
3
|
> 把“用户从多窗口注意力调度中解放出来”的架构跃迁:**Router(常驻控制面)** 与
|
|
4
4
|
> **Worker(隔离执行体)** 分离,Ticket/Mandate 约束授权,渐进式信任控制自动接单。
|
|
5
|
-
> 3.2.
|
|
5
|
+
> 3.2.9 为面板交互修复发布线。历史限制与实机证据见 `REVIEW-v3.2.7.md`。
|
|
6
6
|
|
|
7
7
|
## 1. 双层结构
|
|
8
8
|
|
package/package.json
CHANGED