dsh-context-toolkit 0.1.0 → 0.2.1

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
@@ -36,6 +36,12 @@ It separates *raw bytes* from *conclusions*: commands run in a child process, fi
36
36
 
37
37
  ## Install
38
38
 
39
+ From npm (recommended):
40
+
41
+ ```bash
42
+ dsh plugin --profile desktop add dsh-context-toolkit
43
+ ```
44
+
39
45
  From GitHub:
40
46
 
41
47
  ```bash
@@ -107,9 +113,10 @@ Tool switches: `tools.execute`, `tools.executeFile`, `tools.batchExecute`, `tool
107
113
  The offline suites need no DSH runtime:
108
114
 
109
115
  ```bash
110
- node smoke.mjs # 52 checks: contract, runtime discovery, tools, gate, knowledge base, observability
116
+ node smoke.mjs # 58 checks: contract, runtime discovery, tools, gate, knowledge base, observability, version reporting
111
117
  node test-client.mjs # 27 checks: browser-half contract and bilingual dictionary parity
112
- node test-package.mjs # 18 checks: publish manifest and the zero-dependency constraint
118
+ node test-package.mjs # 20 checks: publish manifest and the zero-dependency constraint
119
+ node release-check.mjs # 24 checks: release readiness (manifest, deps, tool count, gate, version, SHA coverage, no hardcoded paths)
113
120
  ```
114
121
 
115
122
  ## Known limits
package/README.zh.md CHANGED
@@ -36,6 +36,12 @@
36
36
 
37
37
  ## 安装
38
38
 
39
+ 从 npm 安装(推荐):
40
+
41
+ ```bash
42
+ dsh plugin --profile desktop add dsh-context-toolkit
43
+ ```
44
+
39
45
  从 GitHub 安装:
40
46
 
41
47
  ```bash
@@ -107,9 +113,10 @@ await ctk_search({ queries: ['rate limit', 'auth'] }); // 只取相关片段
107
113
  离线套件不依赖 DSH 运行时:
108
114
 
109
115
  ```bash
110
- node smoke.mjs # 52 项:契约、运行时探测、三工具、门禁、知识库、观测
116
+ node smoke.mjs # 58 项:契约、运行时探测、三工具、门禁、知识库、观测、版本自述
111
117
  node test-client.mjs # 27 项:浏览器半体契约与双语字典一致性
112
- node test-package.mjs # 18 项:发布清单与零依赖约束
118
+ node test-package.mjs # 20 项:发布清单与零依赖约束
119
+ node release-check.mjs # 24 项:发布就绪(清单/依赖/工具数/门禁/版本/SHA 覆盖/无硬编码路径)
113
120
  ```
114
121
 
115
122
  ## 已知边界
package/index.js CHANGED
@@ -18,8 +18,9 @@
18
18
  * no third-party runtime dependencies.
19
19
  */
20
20
  import { homedir } from 'node:os'
21
- import { existsSync, statSync, readdirSync } from 'node:fs'
22
- import { join, isAbsolute, resolve, basename } from 'node:path'
21
+ import { existsSync, statSync, readdirSync, readFileSync } from 'node:fs'
22
+ import { join, isAbsolute, resolve, basename, dirname } from 'node:path'
23
+ import { fileURLToPath } from 'node:url'
23
24
  import { runProcess, availableRuntimes, probeRuntimes, shellPlan, scratchDir } from './lib/runner.js'
24
25
  import { mkdtempSync, rmSync } from 'node:fs'
25
26
  import { openStore } from './lib/store.js'
@@ -27,6 +28,26 @@ import { openStore } from './lib/store.js'
27
28
  export const name = 'dsh-context-toolkit'
28
29
  export const inject = ['tools', 'systemPrompt']
29
30
 
31
+ /**
32
+ * The version this bundle actually ships, read from its own manifest.
33
+ *
34
+ * It used to be hardcoded and drifted: the manifest moved to 0.2.0 while the
35
+ * doctor still reported 0.1.0, so the one line meant to identify the build was
36
+ * the one line that could not be trusted. Reading the manifest keeps the two in
37
+ * step without a release step of its own.
38
+ */
39
+ export const PLUGIN_VERSION = readManifestVersion()
40
+
41
+ /** Read the neighbouring package.json; a bundled copy still gets a usable value. */
42
+ export function readManifestVersion() {
43
+ try {
44
+ const here = dirname(fileURLToPath(import.meta.url))
45
+ const parsed = JSON.parse(readFileSync(join(here, 'package.json'), 'utf8'))
46
+ if (parsed && typeof parsed.version === 'string' && parsed.version) return parsed.version
47
+ } catch { /* not resolvable from here: still report something the doctor can print */ }
48
+ return '0.0.0'
49
+ }
50
+
30
51
  const z = await loadSchemastery()
31
52
 
32
53
  /**
@@ -262,9 +283,22 @@ export function apply(ctx, rawConfig) {
262
283
  /** Names whose whole purpose is to pour raw bytes into the conversation. */
263
284
  const FLOOD_TOOLS = new Set(['curl', 'wget', 'httpie', 'http', 'aria2c'])
264
285
 
286
+ /**
287
+ * Every tool name that runs a shell command, so the gate can read its `command`.
288
+ *
289
+ * This list is the gate's blind spot if it drifts: a host name that is absent here
290
+ * is simply not inspected, and the flood tools run unchecked through it. `ops_bash`
291
+ * is the live example - dsh-ops publishes it (and does not publish `bash` at all),
292
+ * so before this list existed `curl` through `ops_bash` slipped past a gate that
293
+ * was refusing the identical command through `pwsh`.
294
+ *
295
+ * Add a name here when a shell tool appears; the other branches key off this set.
296
+ */
297
+ const SHELL_TOOL_NAMES = new Set(['bash', 'pwsh', 'shell', 'ops_bash', 'bash_persistent', 'pwsh_persistent'])
298
+
265
299
  function floodReason(toolName, args) {
266
300
  const command = typeof args.command === 'string' ? args.command : ''
267
- if (toolName !== 'bash' && toolName !== 'pwsh' && toolName !== 'shell') return undefined
301
+ if (!SHELL_TOOL_NAMES.has(toolName)) return undefined
268
302
  for (const word of FLOOD_TOOLS) {
269
303
  if (new RegExp('(^|[ \\t;&|(])' + word + '([ \\t;&|)]|$)', 'i').test(command)) {
270
304
  return 'dsh-context-toolkit: "' + word + '" pours whole responses into the transcript. '
@@ -312,7 +346,7 @@ function registerRoutingGate(ctx, config, stats) {
312
346
  }
313
347
  }
314
348
 
315
- if ((toolName === 'bash' || toolName === 'pwsh') && config.bashNudgeMinCommandBytes > 0) {
349
+ if (SHELL_TOOL_NAMES.has(toolName) && config.bashNudgeMinCommandBytes > 0) {
316
350
  const command = typeof args.command === 'string' ? args.command : ''
317
351
  if (command.length > config.bashNudgeMinCommandBytes) {
318
352
  const reason = 'dsh-context-toolkit: this command is about ' + command.length
@@ -1210,7 +1244,7 @@ function registerObservabilityTools(ctx, config, stats, store, storageDir, log)
1210
1244
 
1211
1245
  // storage
1212
1246
  ok('存储目录 Storage', storageDir)
1213
- ok('版本 Version', '0.1.0')
1247
+ ok('版本 Version', PLUGIN_VERSION)
1214
1248
 
1215
1249
  lines.push('')
1216
1250
  const failed = lines.filter((l) => l.startsWith('[FAIL]')).length
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-context-toolkit",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
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",