dsh-channel-memory 0.1.1 → 0.1.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 +21 -2
- package/lib/index.js +31 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -116,14 +116,33 @@ keeper → 桥的 `--cwd`),例如:
|
|
|
116
116
|
|
|
117
117
|
## 验证
|
|
118
118
|
|
|
119
|
-
`
|
|
119
|
+
`test/contract_test.mjs` 用**宿主自己的 `defineTool`** 跑契约测试(不是 stub):
|
|
120
120
|
value-schema DSL 违规会当场抛。夹具强制宿主不变量(cwd 不符则 `attachSession` 抛),
|
|
121
121
|
因此「外来会话被拒绝挂载」是被真实验证的,而不是被假 object 允许的。
|
|
122
122
|
|
|
123
|
+
在插件目录里运行(`<APP>` 同上;Windows 桌面形态必须用 DSH 自带的 Electron 跑,
|
|
124
|
+
因为宿主模块在 `app.asar` 里):
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
set ELECTRON_RUN_AS_NODE=1
|
|
128
|
+
"<APP>\DeepSeek Harness.exe" --expose-internals test\contract_test.mjs
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
可选覆盖(默认指向本机安装布局):`DSH_TOOLS_ENTRY`、`DSH_PLUGIN_ENTRY`。
|
|
132
|
+
|
|
133
|
+
实测输出:
|
|
134
|
+
|
|
123
135
|
```
|
|
124
|
-
|
|
136
|
+
tools registered: 5
|
|
137
|
+
prompt sections : channel-memory:index@3200(text=function)
|
|
138
|
+
attached (channel session): ["sess-abc"]
|
|
139
|
+
after foreign session : ["sess-abc"] (must not contain sess-elsewhere)
|
|
140
|
+
index reflects post-apply write: true
|
|
141
|
+
RESULT: PASS
|
|
125
142
|
```
|
|
126
143
|
|
|
144
|
+
测试会把 `DSH_HOME` 指到临时目录,不会碰你真实的 `~/.dsh`。
|
|
145
|
+
|
|
127
146
|
权限面见 `PERMISSIONS.md`。
|
|
128
147
|
|
|
129
148
|
## License
|
package/lib/index.js
CHANGED
|
@@ -303,9 +303,25 @@ export function apply(ctx, config) {
|
|
|
303
303
|
},
|
|
304
304
|
]
|
|
305
305
|
|
|
306
|
-
const diag = { toolsService: '
|
|
306
|
+
const diag = { toolsService: 'absent', defineTool: typeof defineTool, errors: [], registered: [] }
|
|
307
|
+
|
|
308
|
+
// Written before it is called: registration can land either synchronously (hosts
|
|
309
|
+
// that resolve `tools` eagerly) or from the inject callback, and both paths report
|
|
310
|
+
// through here. A single early snapshot would always show registered:0 on profiles
|
|
311
|
+
// where inject defers, which previously read as "plugin not installed".
|
|
312
|
+
const writeStatus = () => {
|
|
313
|
+
try {
|
|
314
|
+
writeJson(join(cfg.dataDir, 'status.json'), {
|
|
315
|
+
version: 1, at: new Date().toISOString(), registered: diag.registered.length, total: tools.length,
|
|
316
|
+
diag, workspace: state.workspaceId || null, memories: mem.items.length,
|
|
317
|
+
})
|
|
318
|
+
} catch { }
|
|
319
|
+
}
|
|
320
|
+
|
|
307
321
|
const registerAll = (toolsSvc) => {
|
|
322
|
+
if (diag.registered.length) return // exactly once
|
|
308
323
|
if (!toolsSvc || typeof toolsSvc.register !== 'function') { diag.toolsService = 'unavailable'; return }
|
|
324
|
+
diag.toolsService = 'ok'
|
|
309
325
|
for (const t of tools) {
|
|
310
326
|
try {
|
|
311
327
|
toolsSvc.register(defineTool({ ...t, output: OUT() }))
|
|
@@ -316,29 +332,25 @@ export function apply(ctx, config) {
|
|
|
316
332
|
ctx.logger?.warn?.(`channel-memory: tool ${msg}`)
|
|
317
333
|
}
|
|
318
334
|
}
|
|
335
|
+
writeStatus()
|
|
319
336
|
}
|
|
320
337
|
|
|
321
|
-
// inject
|
|
322
|
-
//
|
|
323
|
-
|
|
338
|
+
// `tools` is requested through inject rather than read off the root context:
|
|
339
|
+
// on some profiles (observed under `--profile acp`, the path phone turns take)
|
|
340
|
+
// touching ctx.tools without declaring it throws
|
|
341
|
+
// `cannot get property "tools" without inject`, which would abort apply() and
|
|
342
|
+
// leave the plugin mounted but tool-less.
|
|
343
|
+
ctx.inject(['tools'], (host) => registerAll(host.tools))
|
|
324
344
|
|
|
325
|
-
//
|
|
326
|
-
//
|
|
327
|
-
//
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
// channel_workspace_info and looks like a mount failure.
|
|
331
|
-
const writeStatus = () => {
|
|
332
|
-
try {
|
|
333
|
-
writeJson(join(cfg.dataDir, 'status.json'), {
|
|
334
|
-
version: 1, at: new Date().toISOString(), registered: diag.registered.length, total: tools.length,
|
|
335
|
-
diag, workspace: state.workspaceId || null, memories: mem.items.length,
|
|
336
|
-
})
|
|
337
|
-
} catch { }
|
|
345
|
+
// Hosts that already resolved the service call the callback synchronously; where
|
|
346
|
+
// they do not, keep the direct handle as a guarded fallback so registration can
|
|
347
|
+
// never silently no-op. registerAll ignores the second attempt.
|
|
348
|
+
if (!diag.registered.length) {
|
|
349
|
+
try { registerAll(ctx.tools) } catch (e) { diag.errors.push('direct: ' + String(e?.message ?? e).slice(0, 120)) }
|
|
338
350
|
}
|
|
339
351
|
writeStatus()
|
|
340
|
-
setTimeout(writeStatus, 2000)
|
|
352
|
+
setTimeout(writeStatus, 2000) // after the workspace effect has had time to land
|
|
341
353
|
setTimeout(writeStatus, 10000)
|
|
342
354
|
|
|
343
355
|
ctx.logger?.info?.(`channel-memory ready: tools=${diag.registered.length}/${tools.length} memories=${mem.items.length} ws=${cfg.workspacePath}`)
|
|
344
|
-
}
|
|
356
|
+
}
|