dsh-context-toolkit 0.2.2 → 0.2.3
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 +1 -1
- package/README.zh.md +1 -1
- package/index.js +30 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -113,7 +113,7 @@ Tool switches: `tools.execute`, `tools.executeFile`, `tools.batchExecute`, `tool
|
|
|
113
113
|
The offline suites need no DSH runtime:
|
|
114
114
|
|
|
115
115
|
```bash
|
|
116
|
-
node smoke.mjs #
|
|
116
|
+
node smoke.mjs # 68 checks: contract, runtime discovery, tools, gate (segment matching, prefix/path normalisation, script_path coverage and relative-path alignment), resource disposal, knowledge base, observability, version reporting
|
|
117
117
|
node test-client.mjs # 27 checks: browser-half contract and bilingual dictionary parity
|
|
118
118
|
node test-package.mjs # 20 checks: publish manifest and the zero-dependency constraint
|
|
119
119
|
node release-check.mjs # 27 checks: release readiness (manifest, deps, tool count, gate matching, version, SHA coverage, no hardcoded paths)
|
package/README.zh.md
CHANGED
|
@@ -113,7 +113,7 @@ await ctk_search({ queries: ['rate limit', 'auth'] }); // 只取相关片段
|
|
|
113
113
|
离线套件不依赖 DSH 运行时:
|
|
114
114
|
|
|
115
115
|
```bash
|
|
116
|
-
node smoke.mjs #
|
|
116
|
+
node smoke.mjs # 68 项:契约、运行时探测、三工具、门禁(分段匹配 + 前缀/路径归一 + script_path 覆盖与相对路径对齐)、资源释放、知识库、观测、版本自述
|
|
117
117
|
node test-client.mjs # 27 项:浏览器半体契约与双语字典一致性
|
|
118
118
|
node test-package.mjs # 20 项:发布清单与零依赖约束
|
|
119
119
|
node release-check.mjs # 27 项:发布就绪(清单/依赖/工具数/门禁匹配/版本/SHA 覆盖/无硬编码路径)
|
package/index.js
CHANGED
|
@@ -365,18 +365,43 @@ const SCRIPT_READ_MAX = 256 * 1024
|
|
|
365
365
|
* the same bypass the shell-name list fixed, one field over: whichever field carries
|
|
366
366
|
* the payload, the gate has to follow it.
|
|
367
367
|
*/
|
|
368
|
-
function shellTextOf(args) {
|
|
368
|
+
function shellTextOf(args, exec) {
|
|
369
369
|
const parts = []
|
|
370
370
|
if (typeof args.command === 'string') parts.push(args.command)
|
|
371
371
|
if (typeof args.script_path === 'string' && args.script_path.trim()) {
|
|
372
|
+
const path = resolveScriptPath(args.script_path, args.cwd, exec)
|
|
372
373
|
try {
|
|
373
|
-
const st = statSync(
|
|
374
|
-
if (st.isFile()) parts.push(readFileSync(
|
|
374
|
+
const st = statSync(path)
|
|
375
|
+
if (st.isFile()) parts.push(readFileSync(path, 'utf8').slice(0, SCRIPT_READ_MAX))
|
|
375
376
|
} catch { /* an unreadable script is the shell tool's error to report, not the gate's */ }
|
|
376
377
|
}
|
|
377
378
|
return parts.join('\n')
|
|
378
379
|
}
|
|
379
380
|
|
|
381
|
+
/**
|
|
382
|
+
* Where a relative script_path actually points.
|
|
383
|
+
*
|
|
384
|
+
* The host resolves a relative script against the *session* working directory, while
|
|
385
|
+
* statSync resolves it against this process's cwd — the install directory. The two
|
|
386
|
+
* disagree, so reading the raw string saw nothing for a relative script_path and waved
|
|
387
|
+
* the call through even though the host would run it happily. Aligning the base closes
|
|
388
|
+
* the last way a shell call can carry a payload the gate cannot see: whenever the host
|
|
389
|
+
* can run the file, the gate resolves the same file.
|
|
390
|
+
*/
|
|
391
|
+
function resolveScriptPath(requested, requestedCwd, exec) {
|
|
392
|
+
if (isAbsolute(requested)) return requested
|
|
393
|
+
let session = null
|
|
394
|
+
try {
|
|
395
|
+
session = exec && exec.agent && exec.agent.session && exec.agent.session.header
|
|
396
|
+
? exec.agent.session.header.cwd : null
|
|
397
|
+
} catch { /* no session on this exec: fall back to the process default */ }
|
|
398
|
+
const base = session || process.cwd()
|
|
399
|
+
const cwd = typeof requestedCwd === 'string' && requestedCwd.trim()
|
|
400
|
+
? (isAbsolute(requestedCwd) ? requestedCwd : resolve(base, requestedCwd))
|
|
401
|
+
: base
|
|
402
|
+
return resolve(cwd, requested)
|
|
403
|
+
}
|
|
404
|
+
|
|
380
405
|
function floodReason(toolName, args, text) {
|
|
381
406
|
if (!SHELL_TOOL_NAMES.has(toolName)) return undefined
|
|
382
407
|
const command = text === undefined ? shellTextOf(args) : text
|
|
@@ -407,7 +432,7 @@ function registerRoutingGate(ctx, config, stats) {
|
|
|
407
432
|
|
|
408
433
|
// Read the call's text once and reuse it: a script can be 256 KB, and the deny
|
|
409
434
|
// path used to read it three times to answer three questions about one string.
|
|
410
|
-
const shellText = SHELL_TOOL_NAMES.has(toolName) ? shellTextOf(args) : ''
|
|
435
|
+
const shellText = SHELL_TOOL_NAMES.has(toolName) ? shellTextOf(args, exec) : ''
|
|
411
436
|
|
|
412
437
|
if (config.denyCurlWget !== false) {
|
|
413
438
|
const reason = floodReason(toolName, args, shellText)
|
|
@@ -459,7 +484,7 @@ function registerRoutingGate(ctx, config, stats) {
|
|
|
459
484
|
})
|
|
460
485
|
|
|
461
486
|
if (config.denyCurlWget !== false && ctx.tools && typeof ctx.tools.guard === 'function') {
|
|
462
|
-
ctx.tools.guard((exec) =>
|
|
487
|
+
ctx.tools.guard((exec) => { const a = (exec && exec.arguments) || {}; return floodReason(exec && exec.name, a, shellTextOf(a, exec)) })
|
|
463
488
|
}
|
|
464
489
|
}
|
|
465
490
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-context-toolkit",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "DeepSeek Harness bundle: native ctk_* sandbox tools, a routing gate that keeps bulk output out of the transcript, and a local full-text knowledge base. No third-party runtime dependencies.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|