spec-agent 1.0.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 +256 -0
- package/bin/spec-agent.js +14 -0
- package/dist/commands/analyze.d.ts +16 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +283 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/clean.d.ts +9 -0
- package/dist/commands/clean.d.ts.map +1 -0
- package/dist/commands/clean.js +109 -0
- package/dist/commands/clean.js.map +1 -0
- package/dist/commands/dispatch.d.ts +12 -0
- package/dist/commands/dispatch.d.ts.map +1 -0
- package/dist/commands/dispatch.js +232 -0
- package/dist/commands/dispatch.js.map +1 -0
- package/dist/commands/doctor.d.ts +9 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +153 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/learn.d.ts +13 -0
- package/dist/commands/learn.d.ts.map +1 -0
- package/dist/commands/learn.js +234 -0
- package/dist/commands/learn.js.map +1 -0
- package/dist/commands/merge.d.ts +11 -0
- package/dist/commands/merge.d.ts.map +1 -0
- package/dist/commands/merge.js +335 -0
- package/dist/commands/merge.js.map +1 -0
- package/dist/commands/pipeline.d.ts +19 -0
- package/dist/commands/pipeline.d.ts.map +1 -0
- package/dist/commands/pipeline.js +266 -0
- package/dist/commands/pipeline.js.map +1 -0
- package/dist/commands/plan.d.ts +13 -0
- package/dist/commands/plan.d.ts.map +1 -0
- package/dist/commands/plan.js +314 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/scan.d.ts +28 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +488 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/status.d.ts +8 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +146 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +126 -0
- package/dist/index.js.map +1 -0
- package/dist/services/document-parser.d.ts +49 -0
- package/dist/services/document-parser.d.ts.map +1 -0
- package/dist/services/document-parser.js +499 -0
- package/dist/services/document-parser.js.map +1 -0
- package/dist/services/llm.d.ts +61 -0
- package/dist/services/llm.d.ts.map +1 -0
- package/dist/services/llm.js +716 -0
- package/dist/services/llm.js.map +1 -0
- package/dist/types.d.ts +159 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/file.d.ts +10 -0
- package/dist/utils/file.d.ts.map +1 -0
- package/dist/utils/file.js +96 -0
- package/dist/utils/file.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +55 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +48 -0
- package/scripts/publish-npm.js +174 -0
- package/spec-agent-implementation.md +750 -0
- package/src/commands/analyze.ts +322 -0
- package/src/commands/clean.ts +88 -0
- package/src/commands/dispatch.ts +250 -0
- package/src/commands/doctor.ts +136 -0
- package/src/commands/learn.ts +261 -0
- package/src/commands/merge.ts +377 -0
- package/src/commands/pipeline.ts +306 -0
- package/src/commands/plan.ts +331 -0
- package/src/commands/scan.ts +568 -0
- package/src/commands/status.ts +129 -0
- package/src/index.ts +137 -0
- package/src/services/document-parser.ts +548 -0
- package/src/services/llm.ts +857 -0
- package/src/types.ts +161 -0
- package/src/utils/file.ts +60 -0
- package/src/utils/logger.ts +58 -0
- package/tsconfig.json +19 -0
package/README.md
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# spec-agent
|
|
2
|
+
|
|
3
|
+
多 Agent CLI 工具,用于拆解大型需求文档。
|
|
4
|
+
|
|
5
|
+
## 在 Cursor 中使用
|
|
6
|
+
|
|
7
|
+
### 1. 配置环境变量
|
|
8
|
+
|
|
9
|
+
在 Cursor 的终端中设置 API Key:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# 使用 OpenAI
|
|
13
|
+
export OPENAI_API_KEY=your_openai_key_here
|
|
14
|
+
|
|
15
|
+
# 或使用其他兼容 OpenAI API 的服务
|
|
16
|
+
export LLM_API_KEY=your_key_here
|
|
17
|
+
export LLM_BASE_URL=https://api.your-provider.com/v1
|
|
18
|
+
export LLM_MODEL=gpt-4o-mini
|
|
19
|
+
export LLM_TIMEOUT_MS=60000
|
|
20
|
+
export LLM_RETRIES=2
|
|
21
|
+
export LLM_RETRY_DELAY_MS=1200
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Windows PowerShell:
|
|
25
|
+
```powershell
|
|
26
|
+
$env:OPENAI_API_KEY="your_openai_key_here"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 2. 快速开始
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# 1. 扫描文档,生成分片清单
|
|
33
|
+
spec-agent scan --input ./docs --output ./output/manifest.json
|
|
34
|
+
|
|
35
|
+
# 2. 并行分析文档(需要配置 API Key)
|
|
36
|
+
spec-agent analyze --manifest ./output/manifest.json --output ./output/summaries
|
|
37
|
+
|
|
38
|
+
# 3. 合并分析结果
|
|
39
|
+
spec-agent merge --summaries ./output/summaries --output ./output/spec_summary.json
|
|
40
|
+
|
|
41
|
+
# 4. 生成任务计划
|
|
42
|
+
spec-agent plan --spec ./output/spec_summary.json --output ./output/task_plan.json
|
|
43
|
+
|
|
44
|
+
# 5. 分配任务给不同 Agent
|
|
45
|
+
spec-agent dispatch --plan ./output/task_plan.json --output ./output/dispatch_plan.json
|
|
46
|
+
|
|
47
|
+
# 或者一键执行全部
|
|
48
|
+
spec-agent pipeline --input ./docs --output ./output
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 3. 命令详解
|
|
52
|
+
|
|
53
|
+
#### scan - 文档扫描
|
|
54
|
+
```bash
|
|
55
|
+
spec-agent scan --input <path> --output <manifest.json> [options]
|
|
56
|
+
|
|
57
|
+
Options:
|
|
58
|
+
--chunk-size <size> 分片大小 (默认: 200kb)
|
|
59
|
+
--min-chunk-size <size> 小分片合并阈值 (默认: 10kb)
|
|
60
|
+
--no-llm-chunking 关闭 LLM 智能切分,改为规则切分
|
|
61
|
+
--strict-llm LLM 切分失败时直接报错(不回退)
|
|
62
|
+
--format <type> 文档格式: auto, md, pdf, docx, html
|
|
63
|
+
--dry-run 预览分片计划
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
说明:
|
|
67
|
+
- `scan` 默认启用 LLM 结构分析(按语义和行号切分),更适合复杂文档。
|
|
68
|
+
- 当 LLM 调用临时失败时,会自动退回到“按大小强制切分”,避免使用脆弱的标题正则切分。
|
|
69
|
+
- `scan` 现在会提取文档中的嵌入图片(如 docx 内截图)并保留图片引用,不再直接丢弃图片信息。
|
|
70
|
+
- 在已配置 LLM 且模型支持多模态时,`scan` 会为图片生成简要语义摘要并写入 chunk 文本。
|
|
71
|
+
|
|
72
|
+
#### analyze - 并行分析
|
|
73
|
+
```bash
|
|
74
|
+
spec-agent analyze --manifest <path> --output <dir> [options]
|
|
75
|
+
|
|
76
|
+
Options:
|
|
77
|
+
--agents <count> 并行 Agent 数量 (默认: auto)
|
|
78
|
+
--chunks <indices> 指定分析的 chunk,如: 0,1,2
|
|
79
|
+
--focus <type> 分析重点: full, features, data-model, api, pages
|
|
80
|
+
--retries <count> 单个 chunk 失败后的重试次数 (默认: 1)
|
|
81
|
+
--dry-run 预览分析计划
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
说明:
|
|
85
|
+
- 若有失败 chunk,会在输出目录生成 `analyze_failures.json`,便于后续重跑或排查。
|
|
86
|
+
|
|
87
|
+
#### merge - 合并结果
|
|
88
|
+
```bash
|
|
89
|
+
spec-agent merge --summaries <dir> --output <spec.json> [options]
|
|
90
|
+
|
|
91
|
+
Options:
|
|
92
|
+
--strategy <type> 去重策略: conservative, aggressive
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### plan - 生成任务计划
|
|
96
|
+
```bash
|
|
97
|
+
spec-agent plan --spec <path> --output <plan.json> [options]
|
|
98
|
+
|
|
99
|
+
Options:
|
|
100
|
+
--framework <name> 目标框架: vue, react, angular
|
|
101
|
+
--type <type> 项目类型: spa, ssr, micro-frontend
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### dispatch - 任务分配
|
|
105
|
+
```bash
|
|
106
|
+
spec-agent dispatch --plan <path> --output <plan.json> [options]
|
|
107
|
+
|
|
108
|
+
Options:
|
|
109
|
+
--pool <agents> Agent 池配置,如: frontend:2,backend:1
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### pipeline - 一键执行
|
|
113
|
+
```bash
|
|
114
|
+
spec-agent pipeline --input <path> --output <dir> [options]
|
|
115
|
+
|
|
116
|
+
Options:
|
|
117
|
+
--chunk-size <size> 分片大小 (默认: 200kb)
|
|
118
|
+
--min-chunk-size <size> 小分片合并阈值 (默认: 10kb)
|
|
119
|
+
--analyze-retries <count> analyze 阶段单 chunk 重试次数 (默认: 1)
|
|
120
|
+
--analyze-budget-tokens <count> analyze 阶段 token 预算上限 (默认: 0=不限制)
|
|
121
|
+
--strict-llm LLM 切分失败时直接报错(不回退)
|
|
122
|
+
--from <phase> 从指定阶段恢复: scan, analyze, merge, plan, dispatch
|
|
123
|
+
--stop-at <phase> 执行到指定阶段停止
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### doctor - 环境自检
|
|
127
|
+
```bash
|
|
128
|
+
spec-agent doctor --workspace <dir> [--check-llm]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 退出码约定(用于脚本/CI)
|
|
132
|
+
|
|
133
|
+
- `scan`:
|
|
134
|
+
- `1` 输入错误(路径/参数)
|
|
135
|
+
- `2` 配置错误(LLM API Key 缺失)
|
|
136
|
+
- `3` 严格 LLM 模式失败(`--strict-llm`)
|
|
137
|
+
- `10` 其他运行时错误
|
|
138
|
+
- `analyze`:
|
|
139
|
+
- `1` 输入错误(manifest/chunk 索引)
|
|
140
|
+
- `2` 配置错误(LLM 配置)
|
|
141
|
+
- `3` 部分 chunk 失败(会生成 `analyze_failures.json`)
|
|
142
|
+
- `10` 其他运行时错误
|
|
143
|
+
- `doctor`:
|
|
144
|
+
- `2` 存在失败检查项
|
|
145
|
+
- `1` 命令本身运行失败
|
|
146
|
+
- `pipeline`:
|
|
147
|
+
- `2` 任一阶段失败(同时输出 `pipeline_summary.json` 与 `run_report.json`)
|
|
148
|
+
|
|
149
|
+
#### status - 查看状态
|
|
150
|
+
```bash
|
|
151
|
+
spec-agent status --workspace <dir>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### clean - 清理文件
|
|
155
|
+
```bash
|
|
156
|
+
spec-agent clean --workspace <dir> [--all]
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 4. 环境变量配置
|
|
160
|
+
|
|
161
|
+
| 变量 | 说明 | 默认值 |
|
|
162
|
+
|------|------|--------|
|
|
163
|
+
| `OPENAI_API_KEY` | OpenAI API Key | - |
|
|
164
|
+
| `LLM_API_KEY` | 通用 LLM API Key | - |
|
|
165
|
+
| `OPENAI_BASE_URL` / `LLM_BASE_URL` | API 基础 URL | https://api.openai.com/v1 |
|
|
166
|
+
| `LLM_MODEL` | 模型名称 | gpt-4o-mini |
|
|
167
|
+
| `LLM_MODEL_SCAN` | scan 阶段模型(可选,未设置则使用 LLM_MODEL) | - |
|
|
168
|
+
| `LLM_MODEL_ANALYZE` | analyze 阶段模型(可选) | - |
|
|
169
|
+
| `LLM_MODEL_VISION` | 图片语义模型(可选) | - |
|
|
170
|
+
| `LLM_MAX_TOKENS` | 最大 token 数 | 4000 |
|
|
171
|
+
| `LLM_TEMPERATURE` | 温度参数 | 0.3 |
|
|
172
|
+
| `LLM_TIMEOUT_MS` | 单次请求超时(毫秒) | 60000 |
|
|
173
|
+
| `LLM_RETRIES` | 请求失败重试次数 | 2 |
|
|
174
|
+
| `LLM_RETRY_DELAY_MS` | 首次重试等待毫秒(指数退避) | 1200 |
|
|
175
|
+
| `LLM_IMAGE_MAX_PER_DOC` | 每个文档最多做语义理解的图片数 | 12 |
|
|
176
|
+
| `LLM_IMAGE_MAX_BYTES` | 单张图片最大请求字节(超出跳过) | 2097152 |
|
|
177
|
+
| `PDF_IMAGE_PAGE_LIMIT` | PDF 最多抽取多少页做图片语义理解 | 8 |
|
|
178
|
+
| `MAX_ANALYZE_TOKENS` | analyze 阶段总 token 预算(0=不限制) | 0 |
|
|
179
|
+
|
|
180
|
+
说明:
|
|
181
|
+
- PDF 图片页抽取依赖系统命令 `pdftoppm`(Poppler)。若环境中不存在该命令,流程会自动降级为仅文本解析,不会中断。
|
|
182
|
+
|
|
183
|
+
#### 阿里百炼(DashScope)配置示例
|
|
184
|
+
|
|
185
|
+
PowerShell(当前终端生效):
|
|
186
|
+
|
|
187
|
+
```powershell
|
|
188
|
+
$env:LLM_API_KEY="你的百炼API-KEY"
|
|
189
|
+
$env:LLM_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1"
|
|
190
|
+
$env:LLM_MODEL="qwen-plus"
|
|
191
|
+
$env:LLM_MODEL_VISION="qwen-vl-plus"
|
|
192
|
+
$env:LLM_MODEL_ANALYZE="qwen-plus"
|
|
193
|
+
$env:MAX_ANALYZE_TOKENS="250000"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
PowerShell(持久化到用户环境变量):
|
|
197
|
+
|
|
198
|
+
```powershell
|
|
199
|
+
setx LLM_API_KEY "你的百炼API-KEY"
|
|
200
|
+
setx LLM_BASE_URL "https://dashscope.aliyuncs.com/compatible-mode/v1"
|
|
201
|
+
setx LLM_MODEL "qwen-plus"
|
|
202
|
+
setx LLM_MODEL_VISION "qwen-vl-plus"
|
|
203
|
+
setx LLM_MODEL_ANALYZE "qwen-plus"
|
|
204
|
+
setx MAX_ANALYZE_TOKENS "250000"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
可用以下命令验证配置是否生效:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
node dist/index.js doctor --workspace . --check-llm --format json
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 5. 工作流程
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
┌─────────┐ ┌──────────┐ ┌────────┐ ┌────────┐ ┌──────────┐
|
|
217
|
+
│ Scan │ → │ Analyze │ → │ Merge │ → │ Plan │ → │ Dispatch │
|
|
218
|
+
│ (Scanner)│ │(Analyst×N)│ │(Architect)│ │(Planner)│ │(Dispatcher)│
|
|
219
|
+
└─────────┘ └──────────┘ └────────┘ └────────┘ └──────────┘
|
|
220
|
+
│ │ │ │ │
|
|
221
|
+
▼ ▼ ▼ ▼ ▼
|
|
222
|
+
manifest.json chunk_*.json spec.json task_plan.json dispatch.json
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 6. 支持的文档格式
|
|
226
|
+
|
|
227
|
+
- `.md` - Markdown
|
|
228
|
+
- `.txt` - 纯文本
|
|
229
|
+
- `.html` / `.htm` - HTML
|
|
230
|
+
- `.pdf` - PDF (需要安装依赖)
|
|
231
|
+
- `.docx` - Word 文档 (需要安装依赖)
|
|
232
|
+
|
|
233
|
+
### 7. 断点恢复
|
|
234
|
+
|
|
235
|
+
如果流程中断,可以从任意阶段恢复:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
# 查看当前状态
|
|
239
|
+
spec-agent status --workspace ./output
|
|
240
|
+
|
|
241
|
+
# 从指定阶段恢复
|
|
242
|
+
spec-agent pipeline --input ./docs --output ./output --from analyze
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 开发
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
# 安装依赖
|
|
249
|
+
npm install
|
|
250
|
+
|
|
251
|
+
# 编译
|
|
252
|
+
npm run build
|
|
253
|
+
|
|
254
|
+
# 开发模式
|
|
255
|
+
npm run dev
|
|
256
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
|
|
6
|
+
// Check if dist exists, if not show helpful message
|
|
7
|
+
const distPath = path.join(__dirname, '..', 'dist', 'index.js');
|
|
8
|
+
if (!fs.existsSync(distPath)) {
|
|
9
|
+
console.error('Error: spec-agent is not built yet.');
|
|
10
|
+
console.error('Please run: npm install && npm run build');
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
require(distPath);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
interface AnalyzeOptions {
|
|
3
|
+
manifest: string;
|
|
4
|
+
output: string;
|
|
5
|
+
agents: string;
|
|
6
|
+
chunks?: string;
|
|
7
|
+
focus: string;
|
|
8
|
+
retries: string;
|
|
9
|
+
budgetTokens?: string;
|
|
10
|
+
applyLearned?: boolean;
|
|
11
|
+
dryRun?: boolean;
|
|
12
|
+
yes?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function analyzeCommand(options: AnalyzeOptions, command: Command): Promise<void>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=analyze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,UAAU,cAAc;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAoBD,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA8Q7F"}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.analyzeCommand = analyzeCommand;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const crypto_1 = require("crypto");
|
|
39
|
+
const logger_1 = require("../utils/logger");
|
|
40
|
+
const file_1 = require("../utils/file");
|
|
41
|
+
const llm_1 = require("../services/llm");
|
|
42
|
+
const document_parser_1 = require("../services/document-parser");
|
|
43
|
+
const ANALYZE_EXIT_CODE = {
|
|
44
|
+
INPUT_ERROR: 1,
|
|
45
|
+
CONFIG_ERROR: 2,
|
|
46
|
+
PARTIAL_FAILED: 3,
|
|
47
|
+
RUNTIME_ERROR: 10,
|
|
48
|
+
};
|
|
49
|
+
async function analyzeCommand(options, command) {
|
|
50
|
+
const logger = new logger_1.Logger();
|
|
51
|
+
try {
|
|
52
|
+
// Check manifest exists
|
|
53
|
+
const manifestPath = path.resolve(options.manifest);
|
|
54
|
+
if (!(await (0, file_1.fileExists)(manifestPath))) {
|
|
55
|
+
logger.error(`[E_ANALYZE_INPUT] Manifest not found: ${options.manifest}`);
|
|
56
|
+
logger.info('Run spec-agent scan first to create a manifest.');
|
|
57
|
+
process.exit(ANALYZE_EXIT_CODE.INPUT_ERROR);
|
|
58
|
+
}
|
|
59
|
+
const manifest = await (0, file_1.readJson)(manifestPath);
|
|
60
|
+
// Determine which chunks to analyze
|
|
61
|
+
let chunkIndices = [];
|
|
62
|
+
if (options.chunks) {
|
|
63
|
+
chunkIndices = options.chunks.split(',').map(s => parseInt(s.trim(), 10));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
chunkIndices = manifest.chunks.map((_, i) => i);
|
|
67
|
+
}
|
|
68
|
+
// Validate chunk indices
|
|
69
|
+
const invalidIndices = chunkIndices.filter(i => i < 0 || i >= manifest.chunks.length);
|
|
70
|
+
if (invalidIndices.length > 0) {
|
|
71
|
+
logger.error(`[E_ANALYZE_INPUT] Invalid chunk indices: ${invalidIndices.join(', ')}`);
|
|
72
|
+
logger.info(`Valid range: 0-${manifest.chunks.length - 1}`);
|
|
73
|
+
process.exit(ANALYZE_EXIT_CODE.INPUT_ERROR);
|
|
74
|
+
}
|
|
75
|
+
// Get LLM config
|
|
76
|
+
const llmConfig = (0, llm_1.getLLMConfigForPurpose)('analyze');
|
|
77
|
+
if (options.dryRun) {
|
|
78
|
+
logger.info('Dry run mode - analysis plan:');
|
|
79
|
+
logger.info(`LLM Config: ${llmConfig.model} @ ${llmConfig.baseUrl}`);
|
|
80
|
+
for (const idx of chunkIndices) {
|
|
81
|
+
const chunk = manifest.chunks[idx];
|
|
82
|
+
logger.info(` Chunk ${idx}: ${chunk.sourceFiles.length} files, ${(0, file_1.formatSize)(chunk.size)}`);
|
|
83
|
+
}
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// Validate LLM config (skip if explicitly bypassed)
|
|
87
|
+
try {
|
|
88
|
+
(0, llm_1.validateLLMConfig)(llmConfig);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
logger.error(`LLM Configuration Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
92
|
+
logger.info('\nTo use analyze, set one of these environment variables:');
|
|
93
|
+
logger.info(' export OPENAI_API_KEY=your_key_here');
|
|
94
|
+
logger.info(' export LLM_API_KEY=your_key_here');
|
|
95
|
+
logger.info('\nOptional configuration:');
|
|
96
|
+
logger.info(' export OPENAI_BASE_URL=https://api.openai.com/v1 # or your custom endpoint');
|
|
97
|
+
logger.info(' export LLM_MODEL=gpt-4o-mini # or gpt-4o, claude-3-sonnet, etc.');
|
|
98
|
+
process.exit(ANALYZE_EXIT_CODE.CONFIG_ERROR);
|
|
99
|
+
}
|
|
100
|
+
logger.info(`Analyzing ${chunkIndices.length} chunks with focus: ${options.focus}`);
|
|
101
|
+
logger.info(`Using LLM: ${llmConfig.model}`);
|
|
102
|
+
// Ensure output directory
|
|
103
|
+
const outputDir = path.resolve(options.output);
|
|
104
|
+
await (0, file_1.ensureDir)(outputDir);
|
|
105
|
+
const cacheDir = path.join(outputDir, '.cache', 'analyze');
|
|
106
|
+
await (0, file_1.ensureDir)(cacheDir);
|
|
107
|
+
// Analyze chunks
|
|
108
|
+
const results = [];
|
|
109
|
+
const startTime = Date.now();
|
|
110
|
+
logger.info('Starting parallel analysis...');
|
|
111
|
+
// Process chunks in parallel
|
|
112
|
+
const concurrencyRaw = options.agents === 'auto'
|
|
113
|
+
? Math.min(4, chunkIndices.length)
|
|
114
|
+
: parseInt(options.agents, 10);
|
|
115
|
+
const concurrency = Number.isFinite(concurrencyRaw) && concurrencyRaw > 0
|
|
116
|
+
? concurrencyRaw
|
|
117
|
+
: 1;
|
|
118
|
+
let totalTokens = 0;
|
|
119
|
+
let cachedChunks = 0;
|
|
120
|
+
let llmInvocations = 0;
|
|
121
|
+
const maxRetries = Math.max(0, parseInt(options.retries || '1', 10) || 0);
|
|
122
|
+
const budgetTokens = Math.max(0, parseInt(options.budgetTokens || process.env.MAX_ANALYZE_TOKENS || '0', 10) || 0);
|
|
123
|
+
const failures = [];
|
|
124
|
+
for (let i = 0; i < chunkIndices.length; i += concurrency) {
|
|
125
|
+
const batch = chunkIndices.slice(i, i + concurrency);
|
|
126
|
+
logger.progress(i, chunkIndices.length, `Analyzing chunks ${batch.join(', ')}...`);
|
|
127
|
+
// Process batch in parallel
|
|
128
|
+
const batchResults = await Promise.all(batch.map(async (idx) => {
|
|
129
|
+
const chunk = manifest.chunks[idx];
|
|
130
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
131
|
+
try {
|
|
132
|
+
// Read chunk content
|
|
133
|
+
logger.debug(`Reading chunk ${idx}: ${chunk.sourceFiles.length} files`);
|
|
134
|
+
let content;
|
|
135
|
+
if (chunk.contentPath && await (0, file_1.fileExists)(chunk.contentPath)) {
|
|
136
|
+
// Read from chunk file
|
|
137
|
+
content = await (0, file_1.readFileContent)(chunk.contentPath);
|
|
138
|
+
}
|
|
139
|
+
else if (chunk.content) {
|
|
140
|
+
// Read from manifest (legacy)
|
|
141
|
+
content = chunk.content;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// Fallback: read from source files
|
|
145
|
+
content = await (0, document_parser_1.readChunkContent)(chunk.sourceFiles);
|
|
146
|
+
}
|
|
147
|
+
const cacheKey = (0, crypto_1.createHash)('sha256')
|
|
148
|
+
.update(content)
|
|
149
|
+
.update(`|focus:${options.focus}|model:${llmConfig.model}|v:analyze-2`)
|
|
150
|
+
.digest('hex');
|
|
151
|
+
const cachePath = path.join(cacheDir, `${cacheKey}.json`);
|
|
152
|
+
if (await (0, file_1.fileExists)(cachePath)) {
|
|
153
|
+
const cached = await (0, file_1.readJson)(cachePath);
|
|
154
|
+
cachedChunks++;
|
|
155
|
+
if (cached.llmUsage) {
|
|
156
|
+
totalTokens += cached.llmUsage.totalTokens;
|
|
157
|
+
}
|
|
158
|
+
cached.sourceFiles = chunk.sourceFiles;
|
|
159
|
+
cached.size = (0, file_1.formatSize)(chunk.size);
|
|
160
|
+
return { ok: true, summary: cached };
|
|
161
|
+
}
|
|
162
|
+
if (budgetTokens > 0 && totalTokens >= budgetTokens) {
|
|
163
|
+
return {
|
|
164
|
+
ok: false,
|
|
165
|
+
failure: {
|
|
166
|
+
chunkId: idx,
|
|
167
|
+
sourceFiles: chunk.sourceFiles,
|
|
168
|
+
attempts: attempt + 1,
|
|
169
|
+
error: `Token budget exceeded (${totalTokens}/${budgetTokens})`,
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// Analyze with LLM
|
|
174
|
+
logger.debug(`Sending chunk ${idx} to LLM (${content.length} chars), attempt ${attempt + 1}/${maxRetries + 1}`);
|
|
175
|
+
llmInvocations++;
|
|
176
|
+
const summary = await (0, llm_1.analyzeChunkWithLLM)(content, idx, options.focus, llmConfig, logger);
|
|
177
|
+
// Fill in source info
|
|
178
|
+
summary.sourceFiles = chunk.sourceFiles;
|
|
179
|
+
summary.size = (0, file_1.formatSize)(chunk.size);
|
|
180
|
+
if (summary.llmUsage) {
|
|
181
|
+
totalTokens += summary.llmUsage.totalTokens;
|
|
182
|
+
}
|
|
183
|
+
await (0, file_1.writeJson)(cachePath, summary);
|
|
184
|
+
return { ok: true, summary };
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
const canRetry = attempt < maxRetries;
|
|
188
|
+
const errorText = error instanceof Error ? error.message : String(error);
|
|
189
|
+
if (canRetry) {
|
|
190
|
+
logger.warn(`Chunk ${idx} 分析失败,准备重试 (${attempt + 1}/${maxRetries}): ${errorText}`);
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
ok: false,
|
|
195
|
+
failure: {
|
|
196
|
+
chunkId: idx,
|
|
197
|
+
sourceFiles: chunk.sourceFiles,
|
|
198
|
+
attempts: attempt + 1,
|
|
199
|
+
error: errorText,
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
ok: false,
|
|
206
|
+
failure: {
|
|
207
|
+
chunkId: idx,
|
|
208
|
+
sourceFiles: chunk.sourceFiles,
|
|
209
|
+
attempts: maxRetries + 1,
|
|
210
|
+
error: 'Unknown analysis error',
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
}));
|
|
214
|
+
const successResults = batchResults
|
|
215
|
+
.filter((item) => item.ok)
|
|
216
|
+
.map(item => item.summary);
|
|
217
|
+
const failedResults = batchResults
|
|
218
|
+
.filter((item) => !item.ok)
|
|
219
|
+
.map(item => item.failure);
|
|
220
|
+
results.push(...successResults);
|
|
221
|
+
failures.push(...failedResults);
|
|
222
|
+
// Save individual chunk summaries
|
|
223
|
+
for (const summary of successResults) {
|
|
224
|
+
const summaryPath = path.join(outputDir, `chunk_${summary.chunkId}_summary.json`);
|
|
225
|
+
await (0, file_1.writeJson)(summaryPath, summary);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const duration = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
229
|
+
const failuresPath = path.join(outputDir, 'analyze_failures.json');
|
|
230
|
+
if (failures.length > 0) {
|
|
231
|
+
await (0, file_1.writeJson)(failuresPath, {
|
|
232
|
+
status: 'partial_failed',
|
|
233
|
+
createdAt: new Date().toISOString(),
|
|
234
|
+
chunksRequested: chunkIndices.length,
|
|
235
|
+
chunksSucceeded: results.length,
|
|
236
|
+
chunksFailed: failures.length,
|
|
237
|
+
failures,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
logger.success(`Analysis complete in ${duration}s`);
|
|
241
|
+
if (failures.length > 0) {
|
|
242
|
+
logger.warn(`有 ${failures.length} 个 chunk 失败,详情见: ${failuresPath}`);
|
|
243
|
+
}
|
|
244
|
+
logger.json({
|
|
245
|
+
status: failures.length > 0 ? 'partial_failed' : 'success',
|
|
246
|
+
chunksAnalyzed: results.length,
|
|
247
|
+
chunksFailed: failures.length,
|
|
248
|
+
totalFeatures: results.reduce((sum, r) => sum + r.features.length, 0),
|
|
249
|
+
totalDataModels: results.reduce((sum, r) => sum + r.dataModels.length, 0),
|
|
250
|
+
totalPages: results.reduce((sum, r) => sum + r.pages.length, 0),
|
|
251
|
+
totalApis: results.reduce((sum, r) => sum + r.apis.length, 0),
|
|
252
|
+
totalTokens,
|
|
253
|
+
cachedChunks,
|
|
254
|
+
llmInvocations,
|
|
255
|
+
tokenBudget: budgetTokens > 0 ? budgetTokens : undefined,
|
|
256
|
+
retriesPerChunk: maxRetries,
|
|
257
|
+
failuresPath: failures.length > 0 ? failuresPath : undefined,
|
|
258
|
+
outputDir,
|
|
259
|
+
});
|
|
260
|
+
const analyzeReportPath = path.join(outputDir, 'analyze_report.json');
|
|
261
|
+
await (0, file_1.writeJson)(analyzeReportPath, {
|
|
262
|
+
createdAt: new Date().toISOString(),
|
|
263
|
+
status: failures.length > 0 ? 'partial_failed' : 'success',
|
|
264
|
+
chunksRequested: chunkIndices.length,
|
|
265
|
+
chunksSucceeded: results.length,
|
|
266
|
+
chunksFailed: failures.length,
|
|
267
|
+
retriesPerChunk: maxRetries,
|
|
268
|
+
cachedChunks,
|
|
269
|
+
llmInvocations,
|
|
270
|
+
totalTokens,
|
|
271
|
+
tokenBudget: budgetTokens > 0 ? budgetTokens : undefined,
|
|
272
|
+
cacheDir,
|
|
273
|
+
});
|
|
274
|
+
if (failures.length > 0) {
|
|
275
|
+
process.exit(ANALYZE_EXIT_CODE.PARTIAL_FAILED);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
logger.error(`Analysis failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
280
|
+
process.exit(ANALYZE_EXIT_CODE.RUNTIME_ERROR);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
//# sourceMappingURL=analyze.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
interface CleanOptions {
|
|
3
|
+
workspace: string;
|
|
4
|
+
dryRun?: boolean;
|
|
5
|
+
yes?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function cleanCommand(options: CleanOptions, command: Command): Promise<void>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=clean.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clean.d.ts","sourceRoot":"","sources":["../../src/commands/clean.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,UAAU,YAAY;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAgBD,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA6DzF"}
|