cli-blueprint 1.0.4 → 5.0.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 +1 -0
- package/cli.mjs +13 -194
- package/package.json +5 -14
- package/skill/SKILL.md +1 -1
- package/skill/skill.json +6 -6
package/README.md
CHANGED
package/cli.mjs
CHANGED
|
@@ -1,16 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { createInterface } from 'node:readline/promises'
|
|
4
|
-
import { stdin, stdout } from 'node:process'
|
|
5
|
-
import { dirname, join, resolve } from 'node:path'
|
|
2
|
+
import { dirname } from 'node:path'
|
|
6
3
|
import { fileURLToPath } from 'node:url'
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
const ENDPOINT = 'https://cli.tax/wvz6zmRWmX'
|
|
10
|
-
const SCHEMA_VERSION = 'blueprint.skill.request/1.0'
|
|
11
|
-
const PACKAGE_SKILL_DIR = join(dirname(fileURLToPath(import.meta.url)), 'skill')
|
|
12
|
-
const INSTALL_META = 'install-meta.json'
|
|
13
|
-
const LATEST_ENDPOINT = 'https://cli.tax/api/public/skills/wvz6zmRWmX'
|
|
4
|
+
import { dispatchOfficialSkillCli, runIntakeHandshake } from './installer.mjs'
|
|
14
5
|
|
|
15
6
|
const INTAKE_QUESTIONS = [
|
|
16
7
|
{
|
|
@@ -39,186 +30,14 @@ const INTAKE_QUESTIONS = [
|
|
|
39
30
|
},
|
|
40
31
|
]
|
|
41
32
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
' Run the skill handshake: discover capabilities, answer the intake questions,',
|
|
54
|
-
' and save BLUEPRINT-REQUIREMENTS.json for the IDE agent.',
|
|
55
|
-
'',
|
|
56
|
-
`Endpoint: ${ENDPOINT}`,
|
|
57
|
-
].join('\n')
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/** 读取已安装目录的版本元数据 */
|
|
61
|
-
function readMeta(dir) {
|
|
62
|
-
const p = join(dir, INSTALL_META)
|
|
63
|
-
if (!existsSync(p)) return null
|
|
64
|
-
try { return JSON.parse(readFileSync(p, 'utf8')) } catch { return null }
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** 查询 cli.tax 最新版本(GET /api/public/skills/{code}) */
|
|
68
|
-
async function fetchLatestVersion() {
|
|
69
|
-
try {
|
|
70
|
-
const resp = await fetch(LATEST_ENDPOINT)
|
|
71
|
-
if (!resp.ok) return null
|
|
72
|
-
const data = await resp.json()
|
|
73
|
-
return { version: data.version ?? '', displayName: data.displayName ?? 'blueprint' }
|
|
74
|
-
} catch {
|
|
75
|
-
return null
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async function postRequest(operation, requestId) {
|
|
80
|
-
const response = await fetch(ENDPOINT, {
|
|
81
|
-
method: 'POST',
|
|
82
|
-
headers: { 'Content-Type': 'application/json' },
|
|
83
|
-
body: JSON.stringify({
|
|
84
|
-
input: {
|
|
85
|
-
schemaVersion: SCHEMA_VERSION,
|
|
86
|
-
requestId,
|
|
87
|
-
operation,
|
|
88
|
-
input: {},
|
|
89
|
-
},
|
|
90
|
-
}),
|
|
91
|
-
})
|
|
92
|
-
let payload
|
|
93
|
-
try {
|
|
94
|
-
payload = await response.json()
|
|
95
|
-
} catch {
|
|
96
|
-
throw new Error(`Blueprint ${operation} failed: the runtime host returned a non-JSON response (HTTP ${response.status}). Check that the CLI runtime is deployed on ${ENDPOINT}.`)
|
|
97
|
-
}
|
|
98
|
-
if (!response.ok || payload?.ok !== true) {
|
|
99
|
-
const message = payload?.error?.message ?? payload?.error ?? `HTTP ${response.status}`
|
|
100
|
-
throw new Error(`Blueprint ${operation} failed: ${message}`)
|
|
101
|
-
}
|
|
102
|
-
return payload
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function installTarget(explicit) {
|
|
106
|
-
if (explicit) return resolve(explicit)
|
|
107
|
-
const codexHome = process.env.CODEX_HOME?.trim()
|
|
108
|
-
if (codexHome) return join(codexHome, 'skills', 'blueprint')
|
|
109
|
-
const projectCodex = join(process.cwd(), '.codex', 'skills', 'blueprint')
|
|
110
|
-
return projectCodex
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async function install(explicit) {
|
|
114
|
-
const target = installTarget(explicit)
|
|
115
|
-
await mkdir(target, { recursive: true })
|
|
116
|
-
const previous = readMeta(target)
|
|
117
|
-
await copyFile(join(PACKAGE_SKILL_DIR, 'SKILL.md'), join(target, 'SKILL.md'))
|
|
118
|
-
await copyFile(join(PACKAGE_SKILL_DIR, 'skill.json'), join(target, 'skill.json'))
|
|
119
|
-
const installedVersion = JSON.parse(readFileSync(join(target, 'skill.json'), 'utf8')).version
|
|
120
|
-
if (!installedVersion) throw new Error('skill.json is missing version')
|
|
121
|
-
const localVersion = process.env.npm_package_version ?? ''
|
|
122
|
-
await writeFile(join(target, INSTALL_META), `${JSON.stringify({
|
|
123
|
-
source: 'wvz6zmRWmX',
|
|
124
|
-
slug: 'blueprint',
|
|
125
|
-
version: installedVersion,
|
|
126
|
-
packageVersion: localVersion,
|
|
127
|
-
endpoint: ENDPOINT,
|
|
128
|
-
installedAt: new Date().toISOString(),
|
|
129
|
-
}, null, 2)}\n`)
|
|
130
|
-
if (previous?.version && previous.version !== installedVersion) {
|
|
131
|
-
console.log(`Blueprint skill updated: ${target}`)
|
|
132
|
-
console.log(` ⤴ ${previous.version} → ${installedVersion}`)
|
|
133
|
-
} else {
|
|
134
|
-
console.log(`Blueprint skill installed: ${target} (${installedVersion})`)
|
|
135
|
-
}
|
|
136
|
-
console.log('Next: return to your IDE conversation and state the goal.')
|
|
137
|
-
console.log('The IDE agent reads the installed SKILL.md, asks you the intake questions,')
|
|
138
|
-
console.log('and then calls the Blueprint protocol to build and validate the blueprint.')
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async function check(explicit) {
|
|
142
|
-
const target = installTarget(explicit)
|
|
143
|
-
const local = readMeta(target)
|
|
144
|
-
const latest = await fetchLatestVersion()
|
|
145
|
-
if (!latest) {
|
|
146
|
-
console.log('blueprint: cannot reach cli.tax to check updates.')
|
|
147
|
-
process.exitCode = 1
|
|
148
|
-
return
|
|
149
|
-
}
|
|
150
|
-
if (!local?.version) {
|
|
151
|
-
console.log(`blueprint: no version record in ${target} (installed before update tracking).`)
|
|
152
|
-
console.log(`Latest on cli.tax: ${latest.version}. Run install to record and refresh.`)
|
|
153
|
-
process.exitCode = 1
|
|
154
|
-
return
|
|
155
|
-
}
|
|
156
|
-
if (local.version === latest.version) {
|
|
157
|
-
console.log(`blueprint is up to date (${latest.version}) at ${target}`)
|
|
158
|
-
} else {
|
|
159
|
-
console.log(`blueprint update available: ${local.version} → ${latest.version} at ${target}`)
|
|
160
|
-
console.log('Run: npx cli-blueprint@latest install')
|
|
161
|
-
process.exitCode = 1
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
async function askOne(question, readline) {
|
|
166
|
-
const requiredMark = question.required ? ' (required)' : ''
|
|
167
|
-
console.log(`\n${question.prompt}${requiredMark}`)
|
|
168
|
-
console.log(`Example: ${question.example}`)
|
|
169
|
-
for (;;) {
|
|
170
|
-
const answer = (await readline.question('> ')).trim()
|
|
171
|
-
if (answer || !question.required) return answer || ''
|
|
172
|
-
console.log('This question is required. Please answer before continuing.')
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
async function run() {
|
|
177
|
-
const capabilities = await postRequest('capabilities', 'cli-1')
|
|
178
|
-
const skill = capabilities.output?.skill ?? {}
|
|
179
|
-
const nextStep = capabilities.output?.nextStep ?? {}
|
|
180
|
-
console.log(`Blueprint ${skill.version ?? ''} — ${skill.description ?? 'installable engineering blueprints'}`)
|
|
181
|
-
if (nextStep.instruction) console.log(nextStep.instruction)
|
|
182
|
-
|
|
183
|
-
const readline = createInterface({ input: stdin, output: stdout })
|
|
184
|
-
const answers = []
|
|
185
|
-
try {
|
|
186
|
-
for (const question of INTAKE_QUESTIONS) {
|
|
187
|
-
answers.push({ id: question.id, prompt: question.prompt, answer: await askOne(question, readline) })
|
|
188
|
-
}
|
|
189
|
-
} finally {
|
|
190
|
-
readline.close()
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const requirements = {
|
|
194
|
-
schemaVersion: SCHEMA_VERSION,
|
|
195
|
-
endpoint: ENDPOINT,
|
|
196
|
-
createdAt: new Date().toISOString(),
|
|
197
|
-
answers,
|
|
198
|
-
}
|
|
199
|
-
const target = join(process.cwd(), 'BLUEPRINT-REQUIREMENTS.json')
|
|
200
|
-
await writeFile(target, `${JSON.stringify(requirements, null, 2)}\n`)
|
|
201
|
-
console.log(`\nRequirements saved: ${target}`)
|
|
202
|
-
console.log('Next: continue in your IDE agent with this file.')
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const command = process.argv[2] ?? 'help'
|
|
206
|
-
const argument = process.argv[3] ?? ''
|
|
207
|
-
try {
|
|
208
|
-
if (command === 'install') {
|
|
209
|
-
await install(argument)
|
|
210
|
-
} else if (command === 'check') {
|
|
211
|
-
await check(argument)
|
|
212
|
-
} else if (command === 'run') {
|
|
213
|
-
await run()
|
|
214
|
-
} else if (command === '--help' || command === '-h' || command === 'help') {
|
|
215
|
-
console.log(usage())
|
|
216
|
-
} else {
|
|
217
|
-
console.error(`Unknown command: ${command}\n`)
|
|
218
|
-
console.log(usage())
|
|
219
|
-
process.exitCode = 1
|
|
220
|
-
}
|
|
221
|
-
} catch (error) {
|
|
222
|
-
console.error(error instanceof Error ? error.message : error)
|
|
223
|
-
process.exitCode = 1
|
|
224
|
-
}
|
|
33
|
+
await dispatchOfficialSkillCli({
|
|
34
|
+
packageRoot: dirname(fileURLToPath(import.meta.url)),
|
|
35
|
+
runCommand: (context) => runIntakeHandshake(context, {
|
|
36
|
+
questions: INTAKE_QUESTIONS,
|
|
37
|
+
outputFile: 'BLUEPRINT-REQUIREMENTS.json',
|
|
38
|
+
afterCapabilities(output) {
|
|
39
|
+
const instruction = output.nextStep?.instruction
|
|
40
|
+
if (typeof instruction === 'string' && instruction.trim()) console.log(instruction)
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
43
|
+
})
|
package/package.json
CHANGED
|
@@ -1,29 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "cli-blueprint",
|
|
3
|
-
"version": "1.0.4",
|
|
4
|
-
"description": "Blueprint skill installer for CLI.Tax: compile one goal into an executable, verifiable engineering blueprint.",
|
|
5
|
-
"type": "module",
|
|
6
2
|
"bin": {
|
|
7
3
|
"cli-blueprint": "./cli.mjs"
|
|
8
4
|
},
|
|
5
|
+
"description": "Blueprint skill installer for CLI.Tax: compile one goal into an executable, verifiable engineering blueprint.",
|
|
9
6
|
"files": [
|
|
10
7
|
"cli.mjs",
|
|
11
8
|
"README.md",
|
|
12
9
|
"skill/SKILL.md",
|
|
13
10
|
"skill/skill.json"
|
|
14
11
|
],
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
},
|
|
12
|
+
"license": "UNLICENSED",
|
|
13
|
+
"name": "cli-blueprint",
|
|
18
14
|
"repository": {
|
|
19
15
|
"type": "git",
|
|
20
16
|
"url": "https://github.com/88208555/blueprint-clitax.git"
|
|
21
17
|
},
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"cli.tax",
|
|
25
|
-
"skill",
|
|
26
|
-
"installer",
|
|
27
|
-
"agent"
|
|
28
|
-
]
|
|
18
|
+
"type": "module",
|
|
19
|
+
"version": "5.0.2"
|
|
29
20
|
}
|
package/skill/SKILL.md
CHANGED
|
@@ -42,7 +42,7 @@ POST JSON to the endpoint with an `input` wrapper:
|
|
|
42
42
|
|
|
43
43
|
## Official catalog hops
|
|
44
44
|
|
|
45
|
-
After `capabilities`, read `officialCatalog`. Default allowlist is official skills. Call another skill only when its capability matches this demand. User-named extras enter only when the user names them; then confirm that skill's capabilities before invoke. Do not call chain-unrelated or self-extended skills.
|
|
45
|
+
After `capabilities`, read `officialCatalog`. Default allowlist is official skills. Call another skill only when its capability matches this demand. User-named extras enter only when the user names them; then confirm that skill's capabilities before invoke. Do not call chain-unrelated or self-extended skills.
|
|
46
46
|
|
|
47
47
|
## Safety rules
|
|
48
48
|
|
package/skill/skill.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"description": "Blueprint 把一句已经说清楚的目标编译成可执行、可验证、可追溯的工程蓝图。默认由当前 IDE 的多智能体协同完成需求推演,也可连接用户自行安装的本地 Hermes;平台不托管模型密钥,不在介绍文案中展示外部申请地址。蓝图不是备忘录:每个节点、分支、依赖、合同、任务与验收标准都必须能被确定性规则检查。缺节点、断链路、无验收、把“看起来做完”当成完成,一律判失败。调用顺序为 capabilities、intake、validate、compile-inline:先在对话中问清范围、约束、交付物与验收口径,再生成结构化蓝图;校验全部变绿后才允许产出可落地工件。适合跨工具协作的工程规划,让想法进入可实施状态而不是停在口头承诺。全过程可审计、可复验,禁止静默跳步、禁止伪造验收、禁止用占位文档冒充编译结果。需要本地模型或密钥时,由对话向用户提问,用户自行配置后再继续。本技能面向真实交付:每一步都有输入、规则与失败面,禁止把加载中、超时或未知状态当成空成功。用户可见说明只讲能力与对话配置方式,不出现外链。调用前必须先走 capabilities,再按 nextStep 前进;必填项未回答不得进入下一操作。日志只保存必要元数据,密钥不得写入公开页面。",
|
|
3
3
|
"displayName": "Blueprint",
|
|
4
|
-
"description": "Blueprint 是一个跨工具的工程规划 CLI,把明确目标编译为可执行、可追溯、可验收的全站工程蓝图,并通过确定性规则检查每个节点、分支、合同、任务与验收闭环。默认由当前 IDE 的多智能体协同推演,也可连接用户自行安装的本地 Hermes;平台不托管模型密钥。",
|
|
5
|
-
"schemaVersion": "blueprint.skill.request/1.0",
|
|
6
4
|
"endpoint": "https://cli.tax/wvz6zmRWmX",
|
|
7
5
|
"method": "POST",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
|
|
6
|
+
"name": "blueprint",
|
|
7
|
+
"schemaVersion": "blueprint.skill.request/1.0",
|
|
8
|
+
"type": "Skill",
|
|
9
|
+
"version": "v5.0.2"
|
|
10
|
+
}
|