cli-blueprint 0.2.6 → 1.0.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.
Files changed (41) hide show
  1. package/README.md +21 -150
  2. package/cli.mjs +226 -0
  3. package/package.json +20 -7
  4. package/skill/skill.json +7 -0
  5. package/LICENSE +0 -201
  6. package/install.mjs +0 -442
  7. package/skills/blueprint/install-meta.json +0 -7
  8. package/skills/blueprint/skill.json +0 -10
  9. package/skills/calctool/SKILL.md +0 -173
  10. package/skills/calctool/install-meta.json +0 -7
  11. package/skills/calctool/platform-template/README.md +0 -74
  12. package/skills/calctool/platform-template/index.html +0 -12
  13. package/skills/calctool/platform-template/package.json +0 -26
  14. package/skills/calctool/platform-template/src/App.tsx +0 -233
  15. package/skills/calctool/platform-template/src/authz.ts +0 -103
  16. package/skills/calctool/platform-template/src/engine/evaluate.ts +0 -114
  17. package/skills/calctool/platform-template/src/engine-definition.json +0 -195
  18. package/skills/calctool/platform-template/src/main.tsx +0 -13
  19. package/skills/calctool/platform-template/src/pipeline.ts +0 -80
  20. package/skills/calctool/platform-template/src/store.ts +0 -53
  21. package/skills/calctool/platform-template/tsconfig.json +0 -15
  22. package/skills/calctool/platform-template/vite.config.ts +0 -7
  23. package/skills/calctool/references/declarative-pages.md +0 -69
  24. package/skills/calctool/references/engine-meta-model.md +0 -123
  25. package/skills/calctool/references/finance-example.md +0 -132
  26. package/skills/calctool/references/formula-dsl.md +0 -92
  27. package/skills/calctool/references/import-ocr.md +0 -72
  28. package/skills/calctool/skill.json +0 -10
  29. package/skills/calctool/templates/ecommerce-ops/README.md +0 -27
  30. package/skills/calctool/templates/ecommerce-ops/domain-reference.yaml +0 -172
  31. package/skills/swarm/SKILL.md +0 -120
  32. package/skills/swarm/install-meta.json +0 -7
  33. package/skills/swarm/references/ops-heartbeat.md +0 -45
  34. package/skills/swarm/references/org-chart.md +0 -50
  35. package/skills/swarm/references/security-guard.md +0 -56
  36. package/skills/swarm/references/task-lifecycle.md +0 -53
  37. package/skills/swarm/references/traffic-light.md +0 -52
  38. package/skills/swarm/skill.json +0 -10
  39. package/skills/swarm/swarm-runtime.mjs +0 -600
  40. package/sources.json +0 -25
  41. /package/{skills/blueprint → skill}/SKILL.md +0 -0
package/install.mjs DELETED
@@ -1,442 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * dsh-skillpack — 多 IDE 通用 skill 插件包安装器
4
- *
5
- * 从本包 `skills/` 目录同步一组 skill 到全世界各 IDE/编码 agent 的 skills 根目录。
6
- * 每个子目录(含 SKILL.md + skill.json)即一个 skill;新增/删除子目录后重跑即可扩展。
7
- *
8
- * 设计原则:
9
- * - 内置「全世界已知 IDE 的 skills 安装位置表」(IDES,官方文档核实);
10
- * - 默认「自动匹配」:检测本机真实安装的 IDE(which 命令 / 应用路径 / 配置文件),
11
- * 只装给已安装的 IDE,让每个 IDE 自己识别需要的 skill;--all 才全量安装;
12
- * - 每个 IDE 装到它自己的专属用户级根 → IDE 内部唯一、IDE 之间互不重复;
13
- * - 跨工具互操作标准 ~/.agents/skills(agentskills.io)默认跳过——它会被多个工具
14
- * 同时扫描(Codex 新约定/Gemini/Zed/OpenCode/Cursor/Antigravity),装进去会被重复发现;
15
- * 需要时用 --agents 显式开启(会打印警告);
16
- * - --ide / --skip 精确控制;新增 IDE 只需在 IDES 表加一行。
17
- *
18
- * 更新感知:
19
- * - pull 时把 cli.tax 返回的 version 写入 skills/<slug>/install-meta.json;
20
- * - install / update 时对比「已安装版本」与「远端最新版本」,有新版本会提示;
21
- * - check 子命令:遍历本机已装 IDE 的 skill 目录,对比远端最新版本并报告更新。
22
- *
23
- * 用法:
24
- * node install.mjs pull # 从 sources.json(cli.tax)拉取全部 skill 到 skills/
25
- * node install.mjs install # 自动匹配:只装本机已安装的 IDE(推荐)
26
- * # skills/ 为空时自动先 pull;--pull 强制重新拉取
27
- * node install.mjs install --all # 装到所有已知 IDE(不管是否安装)
28
- * node install.mjs install --ide codex # 仅安装到指定 IDE(可重复: --ide codex --ide dsh)
29
- * node install.mjs install --skip cursor # 自动匹配但跳过指定 IDE(可重复)
30
- * node install.mjs install --project # 额外安装到当前项目的项目级根(每个选中 IDE 一个)
31
- * node install.mjs install --agents # 额外安装到共享 ~/.agents/skills(警告)
32
- * node install.mjs install --target /abs/path # 仅自定义目录
33
- * node install.mjs update # 同 install(幂等覆盖)
34
- * node install.mjs check # 检查已安装 skill 是否有新版本(对比 cli.tax)
35
- * node install.mjs uninstall # 从相同目标移除本包安装的 skills
36
- * node install.mjs list # 列出本包包含的 skills
37
- * node install.mjs ides # 列出已知 IDE 及本机检测结果
38
- *
39
- * 作为 npm 包发布后: npx dsh-skillpack@latest install
40
- */
41
- import { cp, mkdir, readdir, rm, writeFile } from 'node:fs/promises'
42
- import { existsSync, readFileSync, readdirSync } from 'node:fs'
43
- import { homedir } from 'node:os'
44
- import { join, resolve } from 'node:path'
45
- import { fileURLToPath } from 'node:url'
46
- import { spawnSync } from 'node:child_process'
47
-
48
- const __dirname = fileURLToPath(new URL('.', import.meta.url))
49
- const SKILLS_SRC = join(__dirname, 'skills')
50
-
51
- const HOME = homedir()
52
- const CWD = process.cwd()
53
-
54
- /** 每个 skill 安装/拉取时的版本元数据文件名(IDE 目录与 skills/ 内都会写) */
55
- const INSTALL_META = 'install-meta.json'
56
-
57
- /**
58
- * 全世界已知 IDE/编码 agent 的 skills 安装位置表(官方文档核实,2026-08)。
59
- * key: 命令行标识
60
- * label: 显示名
61
- * detect: 安装探测规则数组(任一命中即视为已安装):
62
- * { cmd: 'codex' } —— which 命令存在
63
- * { app: '/Applications/X.app' } —— 应用路径存在
64
- * { file: '~/.codex/config.toml' } —— 配置文件存在(确认真实安装,非本工具创建)
65
- * user: 用户级 skills 根(默认安装目标,每个 IDE 一份)
66
- * project: 项目级 skills 根(--project 时使用)
67
- * doc: 官方文档 URL
68
- * 新增 IDE 只需在此加一行,其余逻辑自动生效。
69
- */
70
- const IDES = [
71
- // OpenAI / Anthropic / Google 系
72
- { key: 'codex', label: 'Codex CLI', detect: [{ cmd: 'codex' }, { file: join(HOME, '.codex', 'config.toml') }], user: join(HOME, '.codex', 'skills'), project: join(CWD, '.codex', 'skills'), doc: 'https://developers.openai.com/codex/skills', note: '新官方约定 ~/.agents/skills;此处用旧约定 ~/.codex/skills(skill-installer 仍默认写入),避免共享根重复' },
73
- { key: 'dsh', label: 'DSH', detect: [{ file: join(HOME, '.dsh', 'settings.yaml') }, { file: join(HOME, '.dsh', '.credentials.yaml') }], user: join(HOME, '.dsh', 'skills'), project: join(CWD, '.dsh', 'skills'), doc: 'https://github.com/deepseek-ai/Harness', note: 'skill-filesystem 扫描 ~/.dsh/skills + ~/.agents/skills' },
74
- { key: 'claude', label: 'Claude Code', detect: [{ cmd: 'claude' }, { file: join(HOME, '.claude', 'settings.json') }, { dir: join(HOME, '.claude') }], user: join(HOME, '.claude', 'skills'), project: join(CWD, '.claude', 'skills'), doc: 'https://code.claude.com/docs/en/skills', note: '含父目录向上扫描至 repo root;monorepo 子目录生效' },
75
- { key: 'gemini', label: 'Gemini CLI', detect: [{ cmd: 'gemini' }, { file: join(HOME, '.gemini', 'settings.json') }], user: join(HOME, '.gemini', 'skills'), project: join(CWD, '.gemini', 'skills'), doc: 'https://geminicli.com/docs/cli/skills/', note: '别名 .agents/skills 优先级更高(此处用专属根避免共享冲突)' },
76
- { key: 'antigravity', label: 'Google Antigravity', detect: [{ cmd: 'antigravity' }, { app: '/Applications/Antigravity.app' }], user: join(HOME, '.gemini', 'antigravity', 'skills'), project: join(CWD, '.agents', 'skills'), doc: 'https://antigravity.google/docs/ide/skills', note: 'workspace 级固定用 .agents/skills(需 --agents 才装项目级)' },
77
-
78
- // 编辑器 / VS Code 生态
79
- { key: 'cursor', label: 'Cursor', detect: [{ cmd: 'cursor' }, { app: '/Applications/Cursor.app' }, { file: join(HOME, '.cursor', 'cursor.db') }], user: join(HOME, '.cursor', 'skills'), project: join(CWD, '.cursor', 'skills'), doc: 'https://cursor.com/help/customization/skills.md', note: '兼容加载 .claude/.codex/.agents/skills' },
80
- { key: 'cline', label: 'Cline', detect: [{ cmd: 'cline' }, { dir: join(HOME, '.cline') }], user: join(HOME, '.cline', 'skills'), project: join(CWD, '.cline', 'skills'), doc: 'https://cline.bot/blog/cline-3-48-0-skills-and-websearch-make-cline-smarter', note: '全局优先于项目' },
81
- { key: 'roo', label: 'Roo Code', detect: [{ cmd: 'roo' }, { dir: join(HOME, '.roo') }], user: join(HOME, '.roo', 'skills'), project: join(CWD, '.roo', 'skills'), doc: 'https://docs.roocode.com/features/skills', note: '项目覆盖全局,模式级覆盖通用' },
82
- { key: 'kilo', label: 'Kilo Code', detect: [{ cmd: 'kilo' }, { dir: join(HOME, '.kilo') }], user: join(HOME, '.kilo', 'skills'), project: join(CWD, '.kilo', 'skills'), doc: 'https://kilo.ai/docs/customize/skills', note: 'kilo.jsonc 可配 skills.paths/urls;另默认加载 .agents/skills' },
83
- { key: 'windsurf', label: 'Windsurf', detect: [{ cmd: 'windsurf' }, { app: '/Applications/Windsurf.app' }], user: join(HOME, '.codeium', 'windsurf', 'skills'), project: join(CWD, '.windsurf', 'skills'), doc: 'https://docs.windsurf.com/windsurf/cascade/skills', note: '全局 ~/.codeium/windsurf/skills,workspace .windsurf/skills' },
84
- { key: 'copilot', label: 'VS Code / Copilot', detect: [{ cmd: 'copilot' }, { app: '/Applications/Visual Studio Code.app' }, { file: join(HOME, '.copilot', 'accounts.json') }], user: join(HOME, '.copilot', 'skills'), project: join(CWD, '.github', 'skills'), doc: 'https://code.visualstudio.com/docs/agent-customization/agent-skills', note: 'workspace .github/skills + .claude/skills;user ~/.copilot/skills + ~/.claude/skills' },
85
- { key: 'trae', label: 'Trae', detect: [{ cmd: 'trae' }, { app: '/Applications/Trae.app' }, { dir: join(HOME, '.trae-cn') }], user: join(HOME, '.trae-cn', 'skills'), project: join(CWD, '.trae', 'skills'), doc: 'https://docs.trae.cn/work_skills', note: '国内版 ~/.trae-cn/skills;国际版用户级未确认;另有 .trae/rules' },
86
-
87
- // CLI agent
88
- { key: 'qwen', label: 'Qwen Code', detect: [{ cmd: 'qwen' }, { file: join(HOME, '.qwen', 'settings.json') }], user: join(HOME, '.qwen', 'skills'), project: join(CWD, '.qwen', 'skills'), doc: 'https://qwenlm.github.io/qwen-code-docs/users/features/skills/', note: '模型自动调用;/learn 生成到项目 .qwen/skills' },
89
- { key: 'opencode', label: 'OpenCode', detect: [{ cmd: 'opencode' }, { dir: join(HOME, '.config', 'opencode') }], user: join(HOME, '.config', 'opencode', 'skills'), project: join(CWD, '.opencode', 'skills'), doc: 'https://github.com/anomalyco/opencode/blob/main/packages/web/src/content/docs/skills.mdx', note: '兼容 .claude/skills 与 .agents/skills' },
90
- { key: 'zed', label: 'Zed', detect: [{ cmd: 'zed' }, { app: '/Applications/Zed.app' }], user: join(HOME, '.agents', 'skills'), project: join(CWD, '.agents', 'skills'), doc: 'https://zed.dev/docs/ai/skills', note: '官方即用 .agents/skills 标准根,仅 --agents 时安装(避免默认触碰共享根)', agentsOnly: true },
91
- // Amazon Q Developer:官方确认无 SKILL.md skills 机制(能力目录为 ~/.aws/amazonq/cli-agents/),故不入表
92
- ]
93
-
94
- // 跨工具互操作标准根(默认跳过;--agents 显式开启)
95
- const AGENTS = { label: '共享 agents 级 (.agents/skills 标准)', path: join(HOME, '.agents', 'skills') }
96
-
97
- function print(line = '') { process.stdout.write(`${line}\n`) }
98
-
99
- /** 探测 IDE 是否真实安装(which 命令 / 应用路径 / 配置文件,任一命中即已安装) */
100
- function isIdeInstalled(ide) {
101
- for (const probe of ide.detect) {
102
- if (probe.cmd !== undefined) {
103
- const r = spawnSync('which', [probe.cmd], { stdio: 'ignore' })
104
- if (r.status === 0) return true
105
- }
106
- if (probe.app !== undefined && existsSync(probe.app)) return true
107
- if (probe.file !== undefined && existsSync(probe.file)) return true
108
- if (probe.dir !== undefined) {
109
- // 目录存在且包含非 skills 的真实内容(避免本安装器创建的 skills 子目录误判)
110
- try {
111
- const entries = readdirSync(probe.dir)
112
- if (entries.some((e) => e !== 'skills' && e !== '.git')) return true
113
- } catch { /* 目录不存在或不可读,忽略 */ }
114
- }
115
- }
116
- return false
117
- }
118
-
119
- async function listSkills() {
120
- if (!existsSync(SKILLS_SRC)) return []
121
- const entries = await readdir(SKILLS_SRC, { withFileTypes: true })
122
- const skills = []
123
- for (const e of entries) {
124
- if (!e.isDirectory()) continue
125
- const skillDir = join(SKILLS_SRC, e.name)
126
- if (existsSync(join(skillDir, 'SKILL.md'))) skills.push(e.name)
127
- }
128
- return skills.sort()
129
- }
130
-
131
- async function syncOne(name, targetRoot, { remove = false, silent = false } = {}) {
132
- const dest = join(targetRoot, name)
133
- if (remove) {
134
- if (existsSync(dest)) { await rm(dest, { recursive: true, force: true }); print(` ✓ 已移除 ${name} ← ${targetRoot}`) }
135
- return
136
- }
137
- await mkdir(dest, { recursive: true })
138
- const sourceDir = join(SKILLS_SRC, name)
139
- const destMeta = readMeta(dest) // 覆盖前读取旧版本
140
- await cp(sourceDir, dest, { recursive: true, force: true })
141
- const srcMeta = readMeta(sourceDir)
142
- // 安装时注入版本横幅到 SKILL.md(IDE 每次读取即见版本与更新入口)
143
- if (srcMeta?.version) {
144
- const installedSkillMd = readFileSync(join(dest, 'SKILL.md'), 'utf8')
145
- await writeFile(join(dest, 'SKILL.md'), injectVersionBanner(installedSkillMd, srcMeta.version, name))
146
- }
147
- if (srcMeta) {
148
- await writeMeta(dest, { ...srcMeta, installedAt: new Date().toISOString() })
149
- }
150
- const upgrade = destMeta && srcMeta && destMeta.version && srcMeta.version && destMeta.version !== srcMeta.version
151
- if (silent) return
152
- if (upgrade) {
153
- print(` ⤴ 已更新 ${name} ${destMeta.version} → ${srcMeta.version} → ${dest}`)
154
- } else {
155
- print(` ✓ 已安装 ${name} → ${dest}${srcMeta?.version ? `(${srcMeta.version})` : ''}`)
156
- }
157
- }
158
-
159
- async function syncAll(targetRoot, { remove = false, reportUpdated, silent = false } = {}) {
160
- const skills = await listSkills()
161
- if (!remove) await mkdir(targetRoot, { recursive: true })
162
- for (const s of skills) {
163
- const before = reportUpdated ? readMeta(join(targetRoot, s)) : null
164
- await syncOne(s, targetRoot, { remove, silent })
165
- if (reportUpdated && before && before.version) {
166
- const after = readMeta(join(targetRoot, s))
167
- if (after && after.version && after.version !== before.version) reportUpdated(1)
168
- }
169
- }
170
- }
171
-
172
- /** 解析目标列表:--target / --ide / --skip / 默认(全部已知 IDE) */
173
- function parseTargets(args) {
174
- const flags = args.filter((a) => a.startsWith('--'))
175
-
176
- const targetFlag = args.indexOf('--target')
177
- if (targetFlag !== -1) {
178
- const p = args[targetFlag + 1]
179
- if (!p) { print('--target 需要一个绝对路径'); process.exit(1) }
180
- return [{ label: '自定义', path: resolve(p) }]
181
- }
182
-
183
- const selected = []
184
- const withProject = flags.includes('--project')
185
-
186
- // 显式 --ide(可重复)
187
- const ideKeys = []
188
- for (let i = 0; i < args.length; i++) {
189
- if (args[i] === '--ide') {
190
- const k = args[i + 1]
191
- if (!k) { print('--ide 需要一个 IDE key(如 codex)'); process.exit(1) }
192
- ideKeys.push(k)
193
- i++
194
- }
195
- }
196
- if (ideKeys.length) {
197
- for (const k of ideKeys) {
198
- const ide = IDES.find((x) => x.key === k)
199
- if (!ide) { print(`未知 IDE: ${k}(可用: ${IDES.map((x) => x.key).join(', ')})`); process.exit(1) }
200
- selected.push({ label: `${ide.label} 用户级`, path: ide.user })
201
- if (withProject) selected.push({ label: `${ide.label} 项目级`, path: ide.project })
202
- }
203
- return selected
204
- }
205
-
206
- // --skip(排除某些 IDE)
207
- const skipped = []
208
- for (let i = 0; i < args.length; i++) {
209
- if (args[i] === '--skip') {
210
- const k = args[i + 1]
211
- if (!k) { print('--skip 需要一个 IDE key(如 cursor)'); process.exit(1) }
212
- skipped.push(k)
213
- i++
214
- }
215
- }
216
-
217
- // 默认:自动匹配——只装本机真实安装的 IDE;--all 则装全部已知 IDE。
218
- const wantAgents = flags.includes('--agents')
219
- const wantAll = flags.includes('--all')
220
- for (const ide of IDES) {
221
- if (skipped.includes(ide.key)) continue
222
- // agentsOnly(如 Zed):仅 --agents 时安装,默认不触碰共享根
223
- if (ide.agentsOnly && !wantAgents) continue
224
- // 默认只装检测到已安装的 IDE;--all 忽略检测
225
- if (!wantAll && !isIdeInstalled(ide)) continue
226
- selected.push({ label: `${ide.label} 用户级`, path: ide.user })
227
- if (withProject) selected.push({ label: `${ide.label} 项目级`, path: ide.project })
228
- }
229
- if (!selected.length) {
230
- print('未检测到任何已安装的 IDE;可用 --all 安装全部已知 IDE,或 --ide <key> 指定。')
231
- process.exit(1)
232
- }
233
- return selected
234
- }
235
-
236
- const [cmd, ...rest] = process.argv.slice(2)
237
-
238
- /** 读取 skill 目录的 install-meta.json(没有则返回 null) */
239
- function readMeta(skillDir) {
240
- const p = join(skillDir, INSTALL_META)
241
- if (!existsSync(p)) return null
242
- try { return JSON.parse(readFileSync(p, 'utf8')) } catch { return null }
243
- }
244
-
245
- /** 写入 skill 目录的 install-meta.json(来源/版本/时间/地址) */
246
- async function writeMeta(skillDir, meta) {
247
- await writeFile(join(skillDir, INSTALL_META), `${JSON.stringify(meta, null, 2)}\n`)
248
- }
249
-
250
- /** 在 SKILL.md frontmatter 之后注入版本横幅:IDE 每次读取即见版本与更新命令 */
251
- function injectVersionBanner(skillMd, version, slug) {
252
- if (!skillMd || !version) return skillMd
253
- const banner = `<!-- cli-${slug}-installer: version ${version} · 检查更新见 install-meta.json / npx cli-${slug}@latest check -->\n`
254
- if (skillMd.startsWith('---')) {
255
- const end = skillMd.indexOf('\n---', 3)
256
- if (end !== -1) {
257
- return `${skillMd.slice(0, end + 5)}\n\n${banner}${skillMd.slice(end + 5).replace(/^\n+/, '')}`
258
- }
259
- }
260
- return `${banner}${skillMd}`
261
- }
262
-
263
- /** 从 cli.tax 拉取一个 skill 到 skills/<slug>/(覆盖本地副本) */
264
- async function pullSkill(source) {
265
- const url = source.endpoint.replace('{code}', source.code)
266
- const resp = await fetch(url)
267
- if (!resp.ok) {
268
- print(` ✗ 拉取失败 ${source.slug}(${url} → HTTP ${resp.status})`)
269
- return false
270
- }
271
- const data = await resp.json()
272
- const dir = join(SKILLS_SRC, data.slug || source.slug)
273
- await mkdir(dir, { recursive: true })
274
- await writeFile(join(dir, 'SKILL.md'), data.skillMd)
275
- await writeFile(join(dir, 'skill.json'), data.skillJson)
276
- const previous = readMeta(dir)
277
- await writeMeta(dir, {
278
- source: source.code,
279
- slug: data.slug || source.slug,
280
- version: data.version ?? '',
281
- endpoint: url,
282
- installedAt: new Date().toISOString(),
283
- })
284
- const changed = previous && previous.version && previous.version !== data.version
285
- if (changed) {
286
- print(` ⤴ 已更新 ${data.displayName} ${previous.version} → ${data.version ?? ''} → skills/${data.slug}/`)
287
- } else {
288
- print(` ✓ 已拉取 ${data.displayName} ${data.version ?? ''} → skills/${data.slug}/`)
289
- }
290
- return true
291
- }
292
-
293
- /** 从 cli.tax 拉取单个 skill 的最新元数据(check 用,不写盘) */
294
- async function fetchLatestMeta(source) {
295
- const url = source.endpoint.replace('{code}', source.code)
296
- try {
297
- const resp = await fetch(url)
298
- if (!resp.ok) return null
299
- const data = await resp.json()
300
- return {
301
- source: source.code,
302
- slug: data.slug || source.slug,
303
- version: data.version ?? '',
304
- displayName: data.displayName ?? data.slug ?? source.slug,
305
- endpoint: url,
306
- }
307
- } catch {
308
- return null
309
- }
310
- }
311
-
312
- /** check:遍历已安装目标的 skill 目录,对比远端最新版本,报告更新 */
313
- async function checkUpdates(targets) {
314
- const sources = loadSources()
315
- if (!sources.length) {
316
- print('⚠ sources.json 无源,无法检查更新。')
317
- return 1
318
- }
319
- let found = 0
320
- for (const t of targets) {
321
- print(`[${t.label}] ${t.path}`)
322
- if (!existsSync(t.path)) { print(' · 未安装'); continue }
323
- const entries = (await readdir(t.path, { withFileTypes: true }).catch(() => []))
324
- .filter((e) => e.isDirectory())
325
- if (!entries.length) { print(' · 无已安装 skill'); continue }
326
- for (const e of entries) {
327
- const skillDir = join(t.path, e.name)
328
- const local = readMeta(skillDir)
329
- const source = sources.find((s) => (s.slug === e.name)
330
- || (local && local.source === s.code))
331
- if (!source) continue
332
- const remote = await fetchLatestMeta(source)
333
- if (!remote) { print(` · ${e.name}:远端查询失败,跳过`); continue }
334
- if (!local || !local.version) {
335
- print(` · ${e.name}:本地无版本记录(旧安装),远端最新 ${remote.version} —— 运行 install 补齐`)
336
- found++
337
- } else if (local.version === remote.version) {
338
- print(` ✓ ${e.name} 已是最新(${remote.version})`)
339
- } else {
340
- print(` ⤴ ${e.name} 有新版本 ${local.version} → ${remote.version} —— 运行 install 更新`)
341
- found++
342
- }
343
- }
344
- }
345
- if (found) {
346
- print(`\n发现 ${found} 个 skill 可更新。执行: node install.mjs install`)
347
- } else {
348
- print('\n全部已是最新。')
349
- }
350
- return 0
351
- }
352
-
353
- /** 读取 sources.json 中的源列表 */
354
- function loadSources() {
355
- const p = join(__dirname, 'sources.json')
356
- if (!existsSync(p)) return []
357
- try {
358
- const raw = readFileSync(p, 'utf8')
359
- return JSON.parse(raw).cliTax ?? []
360
- } catch {
361
- print('⚠ sources.json 解析失败,忽略源。')
362
- return []
363
- }
364
- }
365
-
366
- /** 拉取全部源;失败不影响本地已有 skills */
367
- async function pullAllSources() {
368
- const sources = loadSources()
369
- if (!sources.length) return false
370
- print(`从 cli.tax 拉取 ${sources.length} 个 skill 源:`)
371
- let ok = 0
372
- for (const s of sources) { if (await pullSkill(s)) ok++ }
373
- print(`拉取完成(${ok}/${sources.length})。`)
374
- return ok > 0
375
- }
376
-
377
- if (cmd === 'list') {
378
- const skills = await listSkills()
379
- print(`本包包含 ${skills.length} 个 skills:`)
380
- for (const s of skills) print(` - ${s}`)
381
- } else if (cmd === 'ides') {
382
- print(`已知 IDE 及本机检测结果(共 ${IDES.length} 个):`)
383
- for (const ide of IDES) {
384
- const installed = isIdeInstalled(ide)
385
- print(` ${installed ? '✓' : '·'} ${ide.key.padEnd(11)} ${ide.label.padEnd(20)} ${ide.user}`)
386
- }
387
- print(` · agents 共享 agents 级 ${AGENTS.path}(默认跳过,--agents 开启)`)
388
- print('默认 install 只装 ✓ 标记的 IDE;--all 装全部。')
389
- } else if (cmd === 'pull') {
390
- const ok = await pullAllSources()
391
- if (ok) print('已更新 skills/ 目录;可用 git add/commit 提交到仓库。')
392
- process.exit(ok ? 0 : 1)
393
- } else if (cmd === 'install' || cmd === 'update') {
394
- // 自动拉取:--pull 强制拉取;skills/ 为空时也自动拉取
395
- if (rest.includes('--pull') || !existsSync(SKILLS_SRC) || (await readdir(SKILLS_SRC).catch(() => [])).length === 0) {
396
- await pullAllSources()
397
- }
398
- const targets = parseTargets(rest)
399
- const skills = await listSkills()
400
- if (!skills.length) { print('skills/ 目录为空,无法安装'); process.exit(1) }
401
- if (rest.includes('--agents') && !targets.some((t) => t.path === AGENTS.path)) targets.push(AGENTS)
402
- const silent = rest.includes('--silent') || rest.includes('--yes')
403
- if (!silent) print(`将安装 ${skills.length} 个 skills → ${targets.length} 个目标`)
404
- let updated = 0
405
- for (const t of targets) {
406
- if (!silent) print(`[${t.label}] ${t.path}`)
407
- await syncAll(t.path, { reportUpdated: (n) => { updated += n }, silent })
408
- }
409
- if (rest.includes('--agents')) {
410
- print('⚠ 已安装到共享 ~/.agents/skills:该目录会被 Codex/Gemini/Zed/OpenCode/Cursor 等同时扫描,同一 skill 可能被重复发现。')
411
- }
412
- if (!silent) {
413
- print('完成。各 IDE 会自动发现各自用户级根中的新目录(可立即在新会话中调用)。')
414
- if (updated) {
415
- print(`提示:${updated} 个 skill 有更新。以后可用 node install.mjs check 检查新版本。`)
416
- }
417
- }
418
- } else if (cmd === 'check') {
419
- const targets = parseTargets(rest)
420
- if (rest.includes('--agents') && !targets.some((t) => t.path === AGENTS.path)) targets.push(AGENTS)
421
- process.exitCode = await checkUpdates(targets)
422
- } else if (cmd === 'uninstall') {
423
- const targets = parseTargets(rest)
424
- if (rest.includes('--agents') && !targets.some((t) => t.path === AGENTS.path)) targets.push(AGENTS)
425
- for (const t of targets) {
426
- print(`[${t.label}] ${t.path}`)
427
- await syncAll(t.path, { remove: true })
428
- }
429
- print('完成。')
430
- } else {
431
- print(`用法:
432
- node install.mjs install [--all|--ide <key>|--skip <key>|--project|--agents|--pull|--target <dir>]
433
- node install.mjs pull
434
- node install.mjs update
435
- node install.mjs check
436
- node install.mjs uninstall
437
- node install.mjs list
438
- node install.mjs ides
439
-
440
- npm 安装后(npx cli-blueprint@latest / npx cli-calctool@latest)用法相同。`)
441
- process.exit(1)
442
- }
@@ -1,7 +0,0 @@
1
- {
2
- "source": "wvz6zmRWmX",
3
- "slug": "blueprint",
4
- "version": "v0.4.0",
5
- "endpoint": "https://cli.tax/api/public/skills/wvz6zmRWmX",
6
- "installedAt": "2026-08-17T00:00:00.000Z"
7
- }
@@ -1,10 +0,0 @@
1
- {
2
- "name": "blueprint",
3
- "displayName": "Blueprint",
4
- "description": "Blueprint 是一个跨工具的工程规划 CLI,把明确目标编译为可执行、可追溯、可验收的全站工程蓝图,并通过确定性规则检查每个节点、分支、合同、任务与验收闭环。默认由当前 IDE 的多智能体协同推演,也可连接用户自行安装的本地 Hermes;平台不托管模型密钥。",
5
- "schemaVersion": "cli.request/1.0",
6
- "endpoint": "https://cli.tax/wvz6zmRWmX",
7
- "method": "POST",
8
- "version": "v0.4.0",
9
- "type": "Skill"
10
- }
@@ -1,173 +0,0 @@
1
- ---
2
- name: calctool
3
- description: '按需生成「万能计算工具」:用户输入一个领域需求(如"我是财务,想要一个经营健康诊断工具"),本技能通过提问明确指标、公式、输入方式与输出形式,生成一个可执行、可验证、可发布的在线计算工具——支持自定义指标、自定义公式逻辑、用户上传内容自动识别(Excel 映射 / 图片 OCR)、报告输出。当用户想"把某套计算逻辑/指标/公式做成在线工具"时使用。 Generate a runnable, verifiable, publishable online calculator from a domain need, with custom metrics, formulas, and upload recognition (Excel mapping / image OCR). Use when the user wants to turn a calculation logic into an online tool. Создаёт работающий, проверяемый онлайн-калькулятор по потребности домена: пользовательские метрики, формулы и распознавание загрузок (Excel / OCR). Используйте, когда нужно превратить расчётную логику в онлайн-инструмент.'
4
- ---
5
-
6
- # calctool
7
-
8
- 把「业务计算逻辑」编译为「可执行的在线计算工具」的生成器。
9
-
10
- ## 全链路总流程(老板视角 → 可运行工具)
11
-
12
- ```
13
- 老板(任何 IDE / DSH):"我要搭电商运营计算工具"
14
-
15
- 1. 顾问式对话(intake-round) —— 智能体主动给方案(基于领域参考包),
16
- 老板逐轮确认指标/公式/口径,直到说"创建"
17
-
18
- 2. 情报蜂群(research) —— 自动派情报智能体搜索行业标准/抓指定地址,
19
- 产出可溯源参考包(老板说"电商"等关键词时自动触发)
20
-
21
- 3. 蜂群编排(swarm-orchestrate)—— 需求自动拆解为 fields/formulas/rules/
22
- imports/reports/pages 项目 JSON,交给 swarm 大脑编排:企业组织架构派单 →
23
- 认领 → 执行 → 回传 → 红绿灯监控 → 固定运维(心跳/回收/接替/继承)
24
- → 安全守卫(注入检测),确定性合并
25
-
26
- 4. 编译工具(compile-tool) —— 引擎定义 → 可运行工程文件清单
27
- (App 壳/公式引擎/存储/构建,页面自动生成:录入/指标卡/报告)
28
-
29
- 5. 环境适配(probe-env/adapt-config)—— 自动探测 Node 版本/包管理器/OS/架构,
30
- Node≥18 全功能、16 兼容(sql.js)、<16 零构建预览;pnpm/yarn/npm 自动适配
31
-
32
- 6. 完成前门禁(final-gate) —— 审计/测试/运维三智能体协调接管检测,
33
- 全部符合通过(engine-valid / 基准样例全通过 / 环境就绪)才标记完成
34
-
35
- 7. 交付运行 —— 按适配命令一键搭建(pnpm install → pnpm run dev)
36
- → 老板得到可交互工具;后续对话继续改指标/公式(热更新)
37
-
38
- 或直接走「全自动流水线」(auto-pipeline)——老板只需说需求 + 授权一次:
39
- 授权(告知消耗) → 情报蜂群 → 蜂群生成 → 测试审计 → 编译 → 自动启动弹出页面
40
- → 完成前门禁(审计/测试/运维三智能体协调接管,全部符合通过才标记完成)
41
- 全程无需老板参与,热更新即时生效
42
- ```
43
-
44
- **关键**:老板一句话 → 对话确认 → 情报 → 蜂群 → 编译 → 环境适配 → **可运行工具**。全程框架不变,需求变更只改配置。
45
-
46
- ## 何时使用
47
-
48
- - 用户描述了一个领域场景(财务、运营、工程、教育、医疗……)并想要一个可交互的在线计算工具
49
- - 用户已有指标、公式、评分或报告逻辑,想固化成工具
50
- - 用户需要"自定义指标 + 自定义公式 + 上传识别"能力
51
-
52
- 不要用于:纯展示型页面(无计算)、与计算无关的 CRUD 后台。
53
-
54
- ## 核心原则
55
-
56
- 1. **确定性计算**:正式数字由版本化确定性引擎(公式 AST + Decimal 运行时)产生;模型/OCR/AI 只产生候选、草稿与解释,绝不直接给出不可追溯的正式结果。
57
- 2. **配置化而非代码化**:工具 = 一份可发布的引擎定义(字段目录 + 公式图 + 规则包 + 导入映射 + 视图 + 报告),不是散落的页面代码。
58
- 3. **显式除零**:所有除法必须选 `div`(除零报错)或 `safeDivide`(除零回退),不静默吞错。
59
- 4. **零虚构**:能力未接入时保持"未接入态"(planned/not_installed/disconnected),不虚构数据、状态或按钮。
60
-
61
- ## 五步实施流程
62
-
63
- ### 1. intake —— 收集需求(必须提问,一次一问)
64
- 调用运行时 intake 或按下面问题逐条问用户:
65
- - 目标:这个工具帮用户完成什么?什么必须发生、什么绝不允许发生?
66
- - 输入指标:用户会输入哪些字段?(如收入、成本、人数、月份)
67
- - 公式逻辑:哪些指标由公式算出?(如毛利 = 收入 - 成本)
68
- - 输入方式:手工录入 / Excel 上传 / 图片 OCR / 三者都要?
69
- - 输出形式:指标卡、表格、诊断报告、历史记录?
70
- - 约束:单位、精度、语言、离线/在线、禁止项?
71
-
72
- ### 2. 生成引擎定义(Engine Definition)
73
- ```yaml
74
- engineId: <kebab-case-引擎名>
75
- name: <显示名>
76
- category: <领域,如 finance/operations/education>
77
- ownerType: platform-template
78
- status: draft
79
- semanticVersion: 1.0.0
80
- compatibilityProfile: legacy-compatible
81
- decimalPolicy: decimal-string
82
- defaultLocale: zh-CN
83
- ```
84
- 包含(详见 references/engine-meta-model.md):
85
- - field-catalog:字段目录(类型:amount/ratio/int/enum/dimension/date)
86
- - formula-graph:公式图(节点 = 字段/公式,边 = 依赖)
87
- - rule-packs:规则包(阈值、评分、分级)
88
- - import-profiles:导入映射(Excel 列 / OCR 字段 → 字段目录)
89
- - report-template:报告模板(指标卡 + 表格 + 诊断结论)
90
-
91
- ### 3. 编译公式(详见 references/formula-dsl.md)
92
- - 把自然语言/Excel 公式编译为 JSON AST(禁止 eval/new Function)
93
- - 运算符走最小注册表(add/sub/mul/div/safeDivide/percentOf/if/case/sum/avg/lookup…)
94
- - 数值用 Decimal 字符串,单位编译期推断,错误结构化传播
95
- - 发布前跑依赖图检查:引用存在、无环、可见范围
96
-
97
- ### 4. 生成在线工具(详见 references/declarative-pages.md)
98
- - 表单页:录入字段(按 field-catalog 自动生成)
99
- - 指标卡页:公式结果 StatGrid
100
- - 报告页:结构化输出 + 可导出
101
- - 页面用声明式规格(ApplicationPageSpec),不手写重复模板
102
-
103
- ### 5. 验收与发布
104
- - validate:确定性校验引擎定义(引用闭合、无环、单位一致、测试通过)
105
- - 上传识别走导入 Profile(Excel 映射 + OCR 草稿确认,自动导入先进草稿)
106
- - **完成前门禁(final-gate)**:每次项目完成之前,审计/测试/运维三智能体协调接管检测——
107
- - **审计智能体**:引擎定义确定性校验 0 findings、公式仅走受控 AST(禁 eval)、引用闭合
108
- - **测试智能体**:基准样例(testSuites)全部通过,一个不过都不放行
109
- - **运维智能体**:环境探测成功、依赖分级适配、安装/启动命令可用、热更新就绪
110
- - 三智能体全部符合通过(gate passed)才标记完成;任一未通过返回 findings,修复后重新接管检测
111
- - 发布为版本化引擎,任何公式/字段/阈值变化都创建新版本,不原地修改
112
- - 输出:可运行的在线工具 + 引擎定义包 + 验收报告 + 完成前门禁结论
113
-
114
- ## 多智能体蜂群模式(接入 swarm 编排,推荐复杂工具用)
115
-
116
- 单智能体 `compile-inline` 适合简单工具;复杂工具(多字段 + 多公式 + 规则 + 导入 + 报告)用**蜂群编排(swarm)**:通过智能体大脑调度创建 N 个子智能体,企业级组织架构规则 + 项目 JSON 任务派单/认领/回传 + 红绿灯 + 固定运维与安全守卫——准确率更高、产出更强、可观测可自治。
117
-
118
- ### 接入方式(swarm-orchestrate)
119
-
120
- 1. **swarm-orchestrate**:传需求 → calctool **自动拆解**为项目 JSON(需要几个派几个):
121
- - `research` 情报收集(有领域关键词才派)
122
- - `fields` 字段目录(入口,总是有)
123
- - `formulas` 公式图(有公式才派)· 独立复核
124
- - `rules` 规则包(有规则才派)· 独立复核
125
- - `imports` 导入映射(有导入才派)
126
- - `reports` 报告模板(有报告才派)
127
- - `pages` 页面规格(总是有)
128
- 2. **swarm 大脑编排**:项目 JSON 交给 swarm 运行时(https://cli.tax/zj7fTPVh4p):
129
- - `org-chart`:按企业组织架构创建 N 个子智能体(board/dispatcher/ops/security-guard/workers)
130
- - `dispatch`:依赖图驱动派单(fields 先 → formulas/imports 并行 → reports → pages)
131
- - `claim`:worker 认领任务;`report`:回传结果
132
- - `traffic-light`:每任务/智能体实时绿/黄/红状态 + 进度/错误汇报
133
- - `ops`:固定运维——心跳检测,卡死/死亡自动回收,派新智能体继承任务续跑
134
- - `security-guard`:固定安全守卫——注入/危险指令检测、异常警报
135
- 3. **确定性合并**:收集全部 worker 回传 → 合并为引擎定义 → 校验 → 发布
136
-
137
- ### 准确率与用户控制
138
- - **准确率**:合并后引擎定义必须通过确定性校验(引用闭合/公式链/单位/Decimal/无环),0 findings 才发布
139
- - **用户控制**:每一步产物可查看、修改、重试(budget.maxAttempts);最终工具可测算、改公式、调阈值
140
- - **编程能力**:蜂群产物是真实可编译的引擎定义(JSON AST + Decimal 运行时),不是伪代码
141
-
142
- ## 输出产物
143
-
144
- ```
145
- <engine-id>/
146
- ├── manifest.yaml # 引擎身份与版本
147
- ├── field-catalog.json # 字段目录
148
- ├── formula-graph.json # 公式图(AST)
149
- ├── rule-packs.json # 规则包
150
- ├── import-profiles.json # 导入映射
151
- ├── report-template.json # 报告模板
152
- └── tests/ # 确定性测试(样例 → 期望结果)
153
- ```
154
-
155
- ## 参考文档
156
-
157
- - `references/engine-meta-model.md` —— 引擎元模型(字段/公式/规则/导入/报告)
158
- - `references/formula-dsl.md` —— 公式 DSL 与运行时(AST/Decimal/依赖图/错误值)
159
- - `references/declarative-pages.md` —— 声明式页面规格系统(表单/指标/报告渲染)
160
- - `references/import-ocr.md` —— 导入与 OCR(Excel 映射/图片识别/草稿确认)
161
- - `references/finance-example.md` —— 经营健康诊断完整范例(50 字段 → 10 指标 → 报告)
162
-
163
- ### Blueprint 协同(可选)
164
- `brain-handshake` 时可选择 `blueprintEnabled`:生成引擎定义后,先交给 Blueprint 技能规划工具开发蓝图
165
- (`blueprint-orchestrate` → `https://cli.tax/wvz6zmRWmX`,operation `compile-inline`),
166
- 再回到蜂群执行开发任务,验收标准全部可追溯。不开启时直接蜂群生成,全程框架一致。
167
-
168
- ## 安全规则
169
-
170
- - 不执行任意 JavaScript;公式只走受控 AST
171
- - 上传文件先验证类型/大小/指纹,OCR 结果进草稿不覆盖正式数据
172
- - 不虚构后端数据;未接入能力显示真实状态
173
- - 财务/税务输出需明确"经营估算模型,生产使用前由专业人员复核"
@@ -1,7 +0,0 @@
1
- {
2
- "source": "KKyA6xljUX",
3
- "slug": "calctool",
4
- "version": "v0.4.0",
5
- "endpoint": "https://cli.tax/api/public/skills/KKyA6xljUX",
6
- "installedAt": "2026-08-17T00:00:00.000Z"
7
- }