dsh-toolbox-bundle 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +121 -2
- package/cordis.patch.yml +17 -0
- package/package.json +77 -4
- package/scripts/check.mjs +36 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ax2
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,122 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-toolbox-bundle
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**一条命令,给 DSH 装上 46 个确定性工具**:JSON/YAML/CSV/文本/编码/正则这类"格式活",加上 JVM、Python、Windows 生产报告的"诊断活"。纯本地、无网络、无安装期脚本、无二进制依赖。
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/dsh-toolbox-bundle)
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
## 30 秒安装
|
|
12
|
+
|
|
13
|
+
> **包名与仓库**:npm 上是 `dsh-toolbox-bundle`,仓库是 [`ax2/dsh-toolbox-bundle`](https://github.com/ax2/dsh-toolbox-bundle)。(前身 `dsh-zidev-toolbox`、`@ax2zicode/dsh-dev-toolbox` 都已在 npm 上废弃并指向这里——`dsh-dev-toolbox` 这个名字发不出去:npm 判定它与生态里已有的 `dsh-devtoolbox` 过于相似。)
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
dsh plugin --profile web add dsh-toolbox-bundle
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
装完**重启应用**(bundle 列表是启动时读的)。想装到桌面版就把 `web` 换成 `desktop`。
|
|
20
|
+
|
|
21
|
+
**家族总览**:[zicode.com/software](https://zicode.com/software/) 是四个插件、合装包与桌面软件的统一入口。
|
|
22
|
+
|
|
23
|
+
离线或固定版本:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
dsh plugin --profile web add https://github.com/ax2/dsh-toolbox-bundle/releases/latest/download/dsh-toolbox-bundle.tgz
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
> 这个包是**四个独立插件的合装层**:它一次插入四行 bundle,四个插件仍各自独立版本。**不要**把它和单独安装的那四个混用(会重复注册同名工具)。
|
|
30
|
+
|
|
31
|
+
## 15 秒看到效果
|
|
32
|
+
|
|
33
|
+
把这段贴进对话:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Traceback (most recent call last):
|
|
37
|
+
File "svc.py", line 42, in handle
|
|
38
|
+
KeyError: 'user_id'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
模型会调用 `python_traceback`,拿回这样的结构化结果(实测输出):
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"exception_type": "KeyError",
|
|
46
|
+
"exception_message": "'user_id'",
|
|
47
|
+
"deepest_frame": { "file": "svc.py", "line": 42, "function": "handle" },
|
|
48
|
+
"cause_hints": [{ "hint": "The mapping has no key 'user_id'; production data is usually missing the key that test data always has." }],
|
|
49
|
+
"coverage": { "total_lines": 3, "parsed_lines": 3, "unknown_count": 0, "confidence": 1, "parser_version": "tb-1" }
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
其他几个一看就懂的:
|
|
54
|
+
|
|
55
|
+
| 你说 | 它调用 | 你拿到 |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| "校验 `{"a":1,}`,要精确行列" | `json_validate` | `line 1 / column 9 / position 8` + 错误文案 |
|
|
58
|
+
| "`C:\temp\CON.txt` 这个路径能用吗" | `path_inspect` | `reserved_name`(error):保留 DOS 设备名,带扩展名也算,`position: 8` |
|
|
59
|
+
| "贴上 jstack,有没有死锁" | `java_thread_dump` | Java 级死锁环(`waiting_for`/`holding` 链)、锁竞争队列、状态直方图 |
|
|
60
|
+
| "这是 GC 日志,p99 停顿多少" | `java_gc_log` | 事件与停顿计数、p50/p90/p99、Young/Full 拆分、promotion failure |
|
|
61
|
+
| "`netstat -ano` 里谁在监听 8080" | `netstat_parse` | 监听项 + PID/进程名,并按状态分组;**文本里没有的绝不编造** |
|
|
62
|
+
| "D 盘哪个目录最占空间" | `dir_usage` | 总字节、最大文件、扩展名直方图(只读,符号链接从不跟随) |
|
|
63
|
+
|
|
64
|
+
## 装了哪四个
|
|
65
|
+
|
|
66
|
+
| 插件 | 工具 | 做什么 | 测试 |
|
|
67
|
+
|---|---|---|---|
|
|
68
|
+
| [dsh-deterministic-tools](https://github.com/ax2/dsh-deterministic-tools) | 29 | JSON 校验(精确行列偏移)/ 受限 JSONPath / 结构化 diff / CSV↔JSON / YAML↔JSON / 文本统计 / 正则捕获 / base64·hex·URL 编解码 / 哈希 / Unicode·进制·颜色·CIDR·JWT·时间戳检查 | 35 |
|
|
69
|
+
| [dsh-jvm-doctor](https://github.com/ax2/dsh-jvm-doctor) | 5 | thread dump(含 Java 级死锁环)/ GC 日志 / Maven·Gradle 依赖冲突 / 异常链(`... N more` 还原)/ Spring 配置 diff(载荷前脱敏) | 47 |
|
|
70
|
+
| [dsh-py-doctor](https://github.com/ax2/dsh-py-doctor) | 6 | traceback 根因 / pytest 摘要 / Django migrations·N+1·checks / celery 报告 —— 每个都带解析覆盖率 | 75 |
|
|
71
|
+
| [dsh-win-native](https://github.com/ax2/dsh-win-native) | 6 | 编码检测与转换(GBK/Big5/Shift-JIS 置信度)/ Windows 路径合法性 / netstat 解读 / 只读磁盘巡检与重复文件 | 57 |
|
|
72
|
+
|
|
73
|
+
## 为什么不直接让模型自己算?
|
|
74
|
+
|
|
75
|
+
**它确实能算。** 我们实测过:不给插件、只让它算 `hello world` 的 sha256,模型自己写了两轮 pwsh,**算对了**。所以这些工具卖的不是"模型做不到",而是:
|
|
76
|
+
|
|
77
|
+
- **一次就对的概率**——214 个测试盯着的固定实现,而不是每次现写命令、和引号/编码/PowerShell 版本搏斗;
|
|
78
|
+
- **可复现**:同样输入永远同样输出;
|
|
79
|
+
- **边界明确**:结构化输入超预算**拒绝**(`INPUT_TOO_LARGE`),文本截断按 code point 并标 `truncated`,解析覆盖率与未识别行**明确上报**;
|
|
80
|
+
- **知道自己不知道**:`jwt_inspect` 声明不验签、`netstat_parse` 不编造进程名与 UDP 状态、诊断工具只出事实不做因果推断;
|
|
81
|
+
- **结构化回执**:`{ result, meta }` 可以直接进下一步,而不是让模型解析自由文本。
|
|
82
|
+
|
|
83
|
+
## 它要花多少 token(实测,不是估算)
|
|
84
|
+
|
|
85
|
+
工具 schema 每个请求都要发,**装了不用也要付**:
|
|
86
|
+
|
|
87
|
+
| 配置 | 工具名数 | 首次请求 inputTokens |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| 干净 headless base | 75 | 11,931 |
|
|
90
|
+
| base + 这四个插件(46 工具) | 121 | **19,608**(+7,677,占 39%) |
|
|
91
|
+
|
|
92
|
+
同一个"校验 JSON 并给精确行列"的任务:不装插件,模型自己写 pwsh 走 3 步、输出 1,323 tokens、13.0 s;装插件 2 步、输出 314 tokens、6.1 s,但 **raw token 反而多 17%**。
|
|
93
|
+
|
|
94
|
+
**所以:一次性小活它更贵。** 划算的是聚合压缩(内容不进上下文)、结果远小于输入、shell 一行搞不定的活、以及模型算不准的活。只想留常用的就按 id 覆盖:
|
|
95
|
+
|
|
96
|
+
```yaml
|
|
97
|
+
# profiles/<name>/cordis.patch.yml
|
|
98
|
+
- id: deterministic-tools
|
|
99
|
+
config:
|
|
100
|
+
only: [json_format, json_validate, json_query, text_diff, csv_to_json]
|
|
101
|
+
toolPrefix: zi
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
(同一任务实测三组首次请求 prompt:干净 base 75 个工具名 **12,838** → 只留 5 个 **13,529**(+0.7k)→ 装全部 29 个 **16,799**(+4.0k)。裁剪配置要写进 **profile 自己的** `cordis.patch.yml`(文件头写着 "applied after every bundle layer");用 `dsh --patch <file>` 那种 CLI 覆盖层改同一个 id 会报 `patch: entry "deterministic-tools" not found`。真实启动后模型只收到 `zi__json_format`、`zi__json_validate`。)
|
|
105
|
+
|
|
106
|
+
## 边界
|
|
107
|
+
|
|
108
|
+
- **46 个工具里只有 2 个碰磁盘**:`dir_usage`、`file_duplicates`,都是只读、有文件数/字节预算、软链接与 junction 跳过并上报、从不跟随。
|
|
109
|
+
- 其余全部是**纯文本/纯字节分析**:你不给数据,它不会自己去读。
|
|
110
|
+
- 不发网络请求、不装二进制、不写安装期脚本(pnpm 的 `allowBuilds` 拦不住它)。
|
|
111
|
+
- 超预算**拒绝**而不是静默截断;截断一定标出来。
|
|
112
|
+
|
|
113
|
+
## 从哪来
|
|
114
|
+
|
|
115
|
+
这四个插件是 [zi-devtools](https://github.com/ax2)(Rust 工具箱,16 个 crate / 154 个工具)在 DSH 上的对应实现:按同一份契约(回执信封、预算门禁、边界行为)用 TypeScript 重写,独立版本、独立测试。
|
|
116
|
+
|
|
117
|
+
- npm:[dsh-deterministic-tools](https://www.npmjs.com/package/dsh-deterministic-tools) · [dsh-jvm-doctor](https://www.npmjs.com/package/dsh-jvm-doctor) · [dsh-py-doctor](https://www.npmjs.com/package/dsh-py-doctor) · [dsh-win-native](https://www.npmjs.com/package/dsh-win-native)
|
|
118
|
+
- 每个仓库都有 Release + 预构建 tarball(`releases/latest/download/<repo>.tgz`)
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
MIT
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# One-command install: this layer inserts the four plugin rows that the four
|
|
2
|
+
# individual bundles would insert. A row references a package by name, so the
|
|
3
|
+
# four packages must be dependencies of this one (see package.json) and land in
|
|
4
|
+
# the profile's node_modules.
|
|
5
|
+
#
|
|
6
|
+
# ids are the same ones the individual plugins use on purpose: a profile should
|
|
7
|
+
# install either this toolbox or the individual bundles, never both (duplicate
|
|
8
|
+
# rows would register the same tool names twice).
|
|
9
|
+
- insert:
|
|
10
|
+
- id: deterministic-tools
|
|
11
|
+
name: dsh-deterministic-tools
|
|
12
|
+
- id: jvm-doctor
|
|
13
|
+
name: dsh-jvm-doctor
|
|
14
|
+
- id: py-doctor
|
|
15
|
+
name: dsh-py-doctor
|
|
16
|
+
- id: win-native
|
|
17
|
+
name: dsh-win-native
|
package/package.json
CHANGED
|
@@ -1,6 +1,79 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-toolbox-bundle",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "DSH plugin bundle: one command installs four deterministic, offline plugins (46 tools) covering JSON/YAML/CSV/diff/regex/encoding chores plus JVM, Python and Windows production diagnostics. Ships no code of its own — it inserts the four bundle rows, and the four plugins stay independently versioned.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"cordis.patch.yml",
|
|
8
|
+
"scripts",
|
|
9
|
+
"README.md",
|
|
10
|
+
"LICENSE"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=20.10"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"check": "node scripts/check.mjs",
|
|
17
|
+
"build": "node scripts/check.mjs",
|
|
18
|
+
"prepublishOnly": "npm run check"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"dsh",
|
|
22
|
+
"dsh-plugin",
|
|
23
|
+
"dsh-plugins",
|
|
24
|
+
"deepseek-harness",
|
|
25
|
+
"deepseek",
|
|
26
|
+
"cordis",
|
|
27
|
+
"plugin",
|
|
28
|
+
"plugin-bundle",
|
|
29
|
+
"bundle",
|
|
30
|
+
"toolbox",
|
|
31
|
+
"one-command",
|
|
32
|
+
"deterministic",
|
|
33
|
+
"offline",
|
|
34
|
+
"local-first",
|
|
35
|
+
"no-network",
|
|
36
|
+
"read-only",
|
|
37
|
+
"developer-tools",
|
|
38
|
+
"agent-tools",
|
|
39
|
+
"json",
|
|
40
|
+
"yaml",
|
|
41
|
+
"csv",
|
|
42
|
+
"diff",
|
|
43
|
+
"regex",
|
|
44
|
+
"encoding",
|
|
45
|
+
"hash",
|
|
46
|
+
"jvm",
|
|
47
|
+
"thread-dump",
|
|
48
|
+
"gc-log",
|
|
49
|
+
"python",
|
|
50
|
+
"traceback",
|
|
51
|
+
"pytest",
|
|
52
|
+
"django",
|
|
53
|
+
"windows",
|
|
54
|
+
"netstat"
|
|
55
|
+
],
|
|
56
|
+
"license": "MIT",
|
|
57
|
+
"repository": {
|
|
58
|
+
"type": "git",
|
|
59
|
+
"url": "git+https://github.com/ax2/dsh-toolbox-bundle.git"
|
|
60
|
+
},
|
|
61
|
+
"homepage": "https://zicode.com/software/",
|
|
62
|
+
"bugs": {
|
|
63
|
+
"url": "https://github.com/ax2/dsh-toolbox-bundle/issues"
|
|
64
|
+
},
|
|
65
|
+
"publishConfig": {
|
|
66
|
+
"access": "public"
|
|
67
|
+
},
|
|
68
|
+
"dsh": {
|
|
69
|
+
"bundle": {
|
|
70
|
+
"patch": "./cordis.patch.yml"
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"dsh-deterministic-tools": "^0.1.6",
|
|
75
|
+
"dsh-jvm-doctor": "^0.1.5",
|
|
76
|
+
"dsh-py-doctor": "^0.1.5",
|
|
77
|
+
"dsh-win-native": "^0.1.5"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Prepublish gate for a bundle-only package: there is no build and no test
|
|
2
|
+
// suite here, so the thing that can silently break is the patch/dependency
|
|
3
|
+
// agreement. Verify it without pulling in a YAML parser.
|
|
4
|
+
import { readFileSync } from 'node:fs'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
import { dirname, join } from 'node:path'
|
|
7
|
+
|
|
8
|
+
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
|
|
9
|
+
const pkg = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'))
|
|
10
|
+
const patch = readFileSync(join(root, 'cordis.patch.yml'), 'utf8')
|
|
11
|
+
|
|
12
|
+
const problems = []
|
|
13
|
+
const expected = Object.keys(pkg.dependencies ?? {})
|
|
14
|
+
const inserted = [...patch.matchAll(/^\s*-?\s*id:\s*([a-z0-9-]+)\s*$/gmu)].map((m) => m[1])
|
|
15
|
+
const names = [...patch.matchAll(/^\s*name:\s*([@a-z0-9/._-]+)\s*$/gmu)].map((m) => m[1])
|
|
16
|
+
|
|
17
|
+
if (pkg.dsh?.bundle?.patch !== './cordis.patch.yml') problems.push('dsh.bundle.patch must point at ./cordis.patch.yml')
|
|
18
|
+
if (!pkg.files?.includes('cordis.patch.yml')) problems.push('files[] must ship cordis.patch.yml')
|
|
19
|
+
if (inserted.length !== expected.length) {
|
|
20
|
+
problems.push(`patch inserts ${inserted.length} rows but package.json declares ${expected.length} dependencies`)
|
|
21
|
+
}
|
|
22
|
+
for (const dep of expected) {
|
|
23
|
+
if (!names.includes(dep)) problems.push(`no patch row references the dependency ${dep}`)
|
|
24
|
+
if (!/^\d+\.\d+\.\d+/.test(pkg.dependencies[dep]) && !pkg.dependencies[dep].startsWith('^')) {
|
|
25
|
+
problems.push(`dependency ${dep} has a range that is not caret-pinned: ${pkg.dependencies[dep]}`)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
for (const name of names) {
|
|
29
|
+
if (name.startsWith('@deepseek-ai/')) continue
|
|
30
|
+
if (!expected.includes(name)) problems.push(`patch row references ${name}, which is not a dependency`)
|
|
31
|
+
}
|
|
32
|
+
if (problems.length > 0) {
|
|
33
|
+
for (const p of problems) console.error(`FAIL ${p}`)
|
|
34
|
+
process.exit(1)
|
|
35
|
+
}
|
|
36
|
+
console.log(`OK ${inserted.length} rows: ${names.join(', ')}`)
|