@winspan/claude-forge 1.24.0 → 1.25.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 +22 -22
- package/dist/web/routes/conventions.d.ts +8 -0
- package/dist/web/routes/conventions.d.ts.map +1 -0
- package/dist/web/routes/conventions.js +307 -0
- package/dist/web/routes/conventions.js.map +1 -0
- package/dist/web/routes/project-conventions.d.ts +7 -0
- package/dist/web/routes/project-conventions.d.ts.map +1 -0
- package/dist/web/routes/project-conventions.js +145 -0
- package/dist/web/routes/project-conventions.js.map +1 -0
- package/dist/web/routes/skills.d.ts.map +1 -1
- package/dist/web/routes/skills.js +59 -40
- package/dist/web/routes/skills.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +4 -0
- package/dist/web/server.js.map +1 -1
- package/dist/web-static/assets/index-CTfjEs-l.js +74 -0
- package/dist/web-static/assets/index-CnUp9d03.css +1 -0
- package/dist/web-static/index.html +2 -2
- package/package.json +1 -1
- package/dist/web-static/assets/index-Be6o_wyn.css +0 -1
- package/dist/web-static/assets/index-WK9QM2dI.js +0 -74
package/README.md
CHANGED
|
@@ -4,19 +4,19 @@
|
|
|
4
4
|
|
|
5
5
|
Claude Forge 是一个为 Claude Code 设计的智能编排引擎,通过透明旁听对话、自动分析意图、注入最佳实践,让 AI 辅助开发更高效、更可靠。
|
|
6
6
|
|
|
7
|
-
[](https://www.npmjs.com/package/@winspan/claude-forge)
|
|
8
|
-
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.npmjs.com/package/@winspan/claude-forge)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
9
|
|
|
10
10
|
## ✨ 核心特性
|
|
11
11
|
|
|
12
|
-
- 🎯 **智能意图识别** - 自动分析任务复杂度,决定执行策略(支持规则库匹配和 AI 推理) [x]
|
|
13
|
-
- 🔄 **Pipeline 编排** - 复杂任务自动拆分为多阶段流程(分析→设计→编码→测试→审查),支持纯事件溯源架构和状态机约束,确保状态一致性,daemon 启动时自动迁移历史数据 [x]
|
|
14
|
-
- 🛡️ **质量门禁** - 每个阶段自动 AI 审查,支持需求规格、安全性、代码质量、测试覆盖、性能等多维度检查,问题追踪和解决状态管理 [x]
|
|
15
|
-
- 📊 **Web 管理后台** - 实时监控会话、Pipeline
|
|
16
|
-
- 🧠 **知识积累** - 自动提炼决策日志、时间线、项目规范,支持树索引和语义检索 [x]
|
|
17
|
-
- 🎨 **技能编排** - 根据意图自动匹配并注入最佳实践(TDD、重构、调试等),支持关键词映射和命中率统计 [x]
|
|
18
|
-
- 📈 **数据分析** - 成本统计、满意度趋势、ROI 分析,支持延迟追踪和 SLA 告警 [x]
|
|
19
|
-
- 🔌 **多 AI 提供商** - 支持 Claude、OpenAI、Ollama,统一网关层(速率限制、熔断、缓存、预算管理) [x]
|
|
12
|
+
- 🎯 **智能意图识别** - 自动分析任务复杂度,决定执行策略(支持规则库匹配和 AI 推理) [x] 2025-04-25
|
|
13
|
+
- 🔄 **Pipeline 编排** - 复杂任务自动拆分为多阶段流程(分析→设计→编码→测试→审查),支持纯事件溯源架构和状态机约束,确保状态一致性,daemon 启动时自动迁移历史数据 [x] 2025-04-25
|
|
14
|
+
- 🛡️ **质量门禁** - 每个阶段自动 AI 审查,支持需求规格、安全性、代码质量、测试覆盖、性能等多维度检查,问题追踪和解决状态管理 [x] 2025-04-25
|
|
15
|
+
- 📊 **Web 管理后台** - 实时监控会话、Pipeline、质量问题、知识图谱、项目管理、自定义规范管理、技能管理、CLAUDE.md 管理(支持模块化查看和蒸馏压缩)、项目规范绑定管理 [x] 2025-04-25
|
|
16
|
+
- 🧠 **知识积累** - 自动提炼决策日志、时间线、项目规范,支持树索引和语义检索 [x] 2025-04-25
|
|
17
|
+
- 🎨 **技能编排** - 根据意图自动匹配并注入最佳实践(TDD、重构、调试等),支持关键词映射和命中率统计 [x] 2025-04-25
|
|
18
|
+
- 📈 **数据分析** - 成本统计、满意度趋势、ROI 分析,支持延迟追踪和 SLA 告警 [x] 2025-04-25
|
|
19
|
+
- 🔌 **多 AI 提供商** - 支持 Claude、OpenAI、Ollama,统一网关层(速率限制、熔断、缓存、预算管理) [x] 2025-04-25
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
@@ -24,18 +24,18 @@ Claude Forge 是一个为 Claude Code 设计的智能编排引擎,通过透明
|
|
|
24
24
|
|
|
25
25
|
| 功能 | 说明 |
|
|
26
26
|
|------|------|
|
|
27
|
-
| 意图识别 | 自动分析任务复杂度(simple/moderate/complex),决定执行策略,支持规则库和 AI 推理 [x]
|
|
28
|
-
| Pipeline 编排 | 复杂任务自动拆分为多阶段流程,支持纯事件溯源、状态机约束、质量门禁、阶段产物生成、daemon 启动时自动迁移历史数据 [x]
|
|
29
|
-
| 质量门禁 | 每个阶段自动 AI 审查(需求规格、安全性、代码质量、测试、性能),不合格则阻止推进 [x]
|
|
30
|
-
| 技能编排 | 根据意图自动匹配并注入最佳实践,支持关键词映射和命中率统计 [x]
|
|
31
|
-
| 知识蒸馏 | 自动提炼决策日志、时间线、项目规范,支持树索引和语义检索 [x]
|
|
32
|
-
| 会话续接 | 中断后自动恢复上次工作状态 [x]
|
|
33
|
-
| 用户画像 | 根据行为自适应调整干预深度 [x]
|
|
34
|
-
| 多 AI 提供商 | 支持 Claude、OpenAI、Ollama,统一网关层 [x]
|
|
35
|
-
| Web 管理后台 | 实时监控、项目管理、Pipeline
|
|
36
|
-
| 阶段产物 | 每个阶段自动生成结构化文档 [x]
|
|
37
|
-
| 模式学习 | 从历史失败中提炼预防建议,支持 Thompson Sampling 策略选择 [x]
|
|
38
|
-
| 项目规范 | 根据技术栈自动蒸馏项目级规范,支持自动初始化和 AI 自进化 [x]
|
|
27
|
+
| 意图识别 | 自动分析任务复杂度(simple/moderate/complex),决定执行策略,支持规则库和 AI 推理 [x] 2025-04-25 |
|
|
28
|
+
| Pipeline 编排 | 复杂任务自动拆分为多阶段流程,支持纯事件溯源、状态机约束、质量门禁、阶段产物生成、daemon 启动时自动迁移历史数据 [x] 2025-04-25 |
|
|
29
|
+
| 质量门禁 | 每个阶段自动 AI 审查(需求规格、安全性、代码质量、测试、性能),不合格则阻止推进 [x] 2025-04-25 |
|
|
30
|
+
| 技能编排 | 根据意图自动匹配并注入最佳实践,支持关键词映射和命中率统计 [x] 2025-04-25 |
|
|
31
|
+
| 知识蒸馏 | 自动提炼决策日志、时间线、项目规范,支持树索引和语义检索 [x] 2025-04-25 |
|
|
32
|
+
| 会话续接 | 中断后自动恢复上次工作状态 [x] 2025-04-25 |
|
|
33
|
+
| 用户画像 | 根据行为自适应调整干预深度 [x] 2025-04-25 |
|
|
34
|
+
| 多 AI 提供商 | 支持 Claude、OpenAI、Ollama,统一网关层 [x] 2025-04-25 |
|
|
35
|
+
| Web 管理后台 | 实时监控、项目管理、Pipeline 控制、质量追踪、自定义规范管理、技能管理、CLAUDE.md 管理、项目规范绑定管理 [x] 2025-04-25 |
|
|
36
|
+
| 阶段产物 | 每个阶段自动生成结构化文档 [x] 2025-04-25 |
|
|
37
|
+
| 模式学习 | 从历史失败中提炼预防建议,支持 Thompson Sampling 策略选择 [x] 2025-04-25 |
|
|
38
|
+
| 项目规范 | 根据技术栈自动蒸馏项目级规范,支持自动初始化和 AI 自进化 [x] 2025-04-25 |
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Express } from 'express';
|
|
2
|
+
import type { SQLiteStorage } from '../../storage/sqlite.js';
|
|
3
|
+
/**
|
|
4
|
+
* 全局规范管理路由
|
|
5
|
+
* 管理 ~/.claude-forge/conventions/ 下的所有规范模板
|
|
6
|
+
*/
|
|
7
|
+
export declare function registerConventionsRoutes(app: Express, storage: SQLiteStorage): void;
|
|
8
|
+
//# sourceMappingURL=conventions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conventions.d.ts","sourceRoot":"","sources":["../../../src/web/routes/conventions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAa7D;;;GAGG;AAEH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAoUpF"}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { ConventionLoader } from '../../convention/convention-loader.js';
|
|
2
|
+
import { ConventionManager } from '../../convention/convention-manager.js';
|
|
3
|
+
import { ConventionEvolver } from '../../convention/convention-evolver.js';
|
|
4
|
+
import { OfficialConventionSync } from '../../convention/official-sync.js';
|
|
5
|
+
import { createRequiredApi } from '../../utils/claude-api.js';
|
|
6
|
+
import { ConfigManager } from '../../config/index.js';
|
|
7
|
+
import { handleError } from '../utils/errors.js';
|
|
8
|
+
import { validateStringLength } from '../utils/validation.js';
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import os from 'os';
|
|
12
|
+
/**
|
|
13
|
+
* 全局规范管理路由
|
|
14
|
+
* 管理 ~/.claude-forge/conventions/ 下的所有规范模板
|
|
15
|
+
*/
|
|
16
|
+
export function registerConventionsRoutes(app, storage) {
|
|
17
|
+
// ── 规范列表 ────────────────────────────────────────────────────────────────
|
|
18
|
+
app.get('/api/conventions', (req, res) => {
|
|
19
|
+
try {
|
|
20
|
+
const loader = new ConventionLoader();
|
|
21
|
+
const conventions = loader.loadAll(true);
|
|
22
|
+
const items = conventions.map(conv => ({
|
|
23
|
+
id: conv.id,
|
|
24
|
+
name: conv.name,
|
|
25
|
+
version: conv.version,
|
|
26
|
+
description: conv.description,
|
|
27
|
+
source: conv.source,
|
|
28
|
+
rolesCount: Object.keys(conv.roles || {}).length,
|
|
29
|
+
rulesCount: conv.quality_standards?.length || 0,
|
|
30
|
+
autoOptimize: conv.evolution?.auto_optimize || false,
|
|
31
|
+
filePath: conv.filePath,
|
|
32
|
+
}));
|
|
33
|
+
res.json({ total: items.length, items });
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
handleError(err, res, 'GET /api/conventions');
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
// ── 规范详情 ────────────────────────────────────────────────────────────────
|
|
40
|
+
app.get('/api/conventions/:id', (req, res) => {
|
|
41
|
+
try {
|
|
42
|
+
const id = validateStringLength(req.params.id, 'id', 1, 200);
|
|
43
|
+
const loader = new ConventionLoader();
|
|
44
|
+
const convention = loader.findById(id);
|
|
45
|
+
if (!convention) {
|
|
46
|
+
res.status(404).json({ error: 'Convention not found' });
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
res.json(convention);
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
handleError(err, res, 'GET /api/conventions/:id');
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
// ── 同步官方规范 ────────────────────────────────────────────────────────────
|
|
56
|
+
app.post('/api/conventions/sync-official', (req, res) => {
|
|
57
|
+
try {
|
|
58
|
+
const loader = new ConventionLoader();
|
|
59
|
+
const sync = new OfficialConventionSync(loader);
|
|
60
|
+
const report = sync.sync();
|
|
61
|
+
res.json({
|
|
62
|
+
success: true,
|
|
63
|
+
added: report.added,
|
|
64
|
+
updated: report.updated,
|
|
65
|
+
skipped: report.skipped,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
handleError(err, res, 'POST /api/conventions/sync-official');
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
// ── 从 URL 安装规范 ─────────────────────────────────────────────────────────
|
|
73
|
+
app.post('/api/conventions/install', async (req, res) => {
|
|
74
|
+
try {
|
|
75
|
+
const url = validateStringLength(req.body.url, 'url', 1, 500);
|
|
76
|
+
const loader = new ConventionLoader();
|
|
77
|
+
const convention = await loader.installFromUrl(url);
|
|
78
|
+
res.json({ success: true, convention: { id: convention.id, name: convention.name, version: convention.version } });
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
handleError(err, res, 'POST /api/conventions/install');
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// ── 删除规范 ────────────────────────────────────────────────────────────────
|
|
85
|
+
app.delete('/api/conventions/:id', (req, res) => {
|
|
86
|
+
try {
|
|
87
|
+
const id = validateStringLength(req.params.id, 'id', 1, 200);
|
|
88
|
+
// 不允许删除官方规范
|
|
89
|
+
if (id.startsWith('official-')) {
|
|
90
|
+
res.status(400).json({ error: 'Cannot delete official conventions' });
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const loader = new ConventionLoader();
|
|
94
|
+
const convention = loader.findById(id);
|
|
95
|
+
if (!convention || !convention.filePath) {
|
|
96
|
+
res.status(404).json({ error: 'Convention not found' });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
fs.unlinkSync(convention.filePath);
|
|
100
|
+
res.json({ success: true });
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
handleError(err, res, 'DELETE /api/conventions/:id');
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
// ── 保存规范(创建或更新)──────────────────────────────────────────────────
|
|
107
|
+
app.put('/api/conventions/:id', (req, res) => {
|
|
108
|
+
try {
|
|
109
|
+
const id = validateStringLength(req.params.id, 'id', 1, 200);
|
|
110
|
+
const { convention } = req.body;
|
|
111
|
+
if (!convention) {
|
|
112
|
+
res.status(400).json({ error: 'Missing convention data' });
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// 不允许修改官方规范
|
|
116
|
+
if (id.startsWith('official-')) {
|
|
117
|
+
res.status(400).json({ error: 'Cannot modify official conventions' });
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const loader = new ConventionLoader();
|
|
121
|
+
loader.saveConvention({ ...convention, id });
|
|
122
|
+
res.json({ success: true });
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
handleError(err, res, 'PUT /api/conventions/:id');
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
// ── 批量绑定规范到项目 ──────────────────────────────────────────────────────
|
|
129
|
+
app.post('/api/conventions/batch-bind', async (req, res) => {
|
|
130
|
+
try {
|
|
131
|
+
const { conventionIds, projectPaths } = req.body;
|
|
132
|
+
if (!Array.isArray(conventionIds) || !Array.isArray(projectPaths)) {
|
|
133
|
+
res.status(400).json({ error: 'conventionIds and projectPaths must be arrays' });
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const manager = new ConventionManager();
|
|
137
|
+
const results = { success: [], failed: [] };
|
|
138
|
+
for (const projectPath of projectPaths) {
|
|
139
|
+
try {
|
|
140
|
+
for (const conventionId of conventionIds) {
|
|
141
|
+
await manager.bind(projectPath, conventionId);
|
|
142
|
+
}
|
|
143
|
+
results.success.push(projectPath);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
results.failed.push({ project: projectPath, error: String(err) });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
res.json({ success: true, results });
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
handleError(err, res, 'POST /api/conventions/batch-bind');
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
// ── 规范使用统计 ────────────────────────────────────────────────────────────
|
|
156
|
+
app.get('/api/conventions/usage-stats', (req, res) => {
|
|
157
|
+
try {
|
|
158
|
+
const loader = new ConventionLoader();
|
|
159
|
+
const conventions = loader.loadAll(true);
|
|
160
|
+
// 扫描所有项目的绑定
|
|
161
|
+
const bindingsDir = path.join(os.homedir(), '.claude-forge', 'projects');
|
|
162
|
+
const stats = {};
|
|
163
|
+
if (fs.existsSync(bindingsDir)) {
|
|
164
|
+
const projectDirs = fs.readdirSync(bindingsDir, { withFileTypes: true })
|
|
165
|
+
.filter(d => d.isDirectory())
|
|
166
|
+
.map(d => path.join(bindingsDir, d.name));
|
|
167
|
+
for (const projectDir of projectDirs) {
|
|
168
|
+
const bindingFile = path.join(projectDir, 'project-conventions.json');
|
|
169
|
+
if (fs.existsSync(bindingFile)) {
|
|
170
|
+
try {
|
|
171
|
+
const bindings = JSON.parse(fs.readFileSync(bindingFile, 'utf-8'));
|
|
172
|
+
for (const binding of bindings) {
|
|
173
|
+
if (!stats[binding.convention_id]) {
|
|
174
|
+
stats[binding.convention_id] = { conventionId: binding.convention_id, projectCount: 0, projects: [] };
|
|
175
|
+
}
|
|
176
|
+
stats[binding.convention_id].projectCount++;
|
|
177
|
+
stats[binding.convention_id].projects.push(binding.project_path);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// Skip invalid binding files
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const items = conventions.map(conv => ({
|
|
187
|
+
id: conv.id,
|
|
188
|
+
name: conv.name,
|
|
189
|
+
source: conv.source,
|
|
190
|
+
projectCount: stats[conv.id]?.projectCount || 0,
|
|
191
|
+
projects: stats[conv.id]?.projects || [],
|
|
192
|
+
}));
|
|
193
|
+
res.json({ items });
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
handleError(err, res, 'GET /api/conventions/usage-stats');
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
// ── 规范进化历史 ────────────────────────────────────────────────────────────
|
|
200
|
+
app.get('/api/conventions/:id/evolution-history', (req, res) => {
|
|
201
|
+
try {
|
|
202
|
+
const id = validateStringLength(req.params.id, 'id', 1, 200);
|
|
203
|
+
// 从 events 仓库查询该规范的进化记录
|
|
204
|
+
const events = storage.repositories.events.queryEvents({ hook_type: 'ConventionEvolved', limit: 200 });
|
|
205
|
+
const history = events
|
|
206
|
+
.filter(e => e.tool_input && e.tool_input['conventionId'] === id)
|
|
207
|
+
.slice(0, 50)
|
|
208
|
+
.map(e => {
|
|
209
|
+
const meta = e.tool_input;
|
|
210
|
+
return {
|
|
211
|
+
timestamp: e.timestamp,
|
|
212
|
+
previousVersion: meta['previousVersion'],
|
|
213
|
+
newVersion: meta['newVersion'],
|
|
214
|
+
changes: meta['changes'] || [],
|
|
215
|
+
};
|
|
216
|
+
});
|
|
217
|
+
res.json({ id, history });
|
|
218
|
+
}
|
|
219
|
+
catch (err) {
|
|
220
|
+
handleError(err, res, 'GET /api/conventions/:id/evolution-history');
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
// ── 批量进化规范 ────────────────────────────────────────────────────────────
|
|
224
|
+
app.post('/api/conventions/batch-evolve', async (req, res) => {
|
|
225
|
+
try {
|
|
226
|
+
const { conventionIds } = req.body;
|
|
227
|
+
const config = ConfigManager.getInstance().get();
|
|
228
|
+
const api = createRequiredApi(config.distill.api_key || undefined, config.distill.model, config.distill.base_url || undefined);
|
|
229
|
+
const loader = new ConventionLoader();
|
|
230
|
+
const evolver = new ConventionEvolver(api, storage, loader);
|
|
231
|
+
const results = { success: [], failed: [] };
|
|
232
|
+
if (conventionIds && conventionIds.length > 0) {
|
|
233
|
+
// 进化指定规范
|
|
234
|
+
for (const id of conventionIds) {
|
|
235
|
+
try {
|
|
236
|
+
const convention = loader.findById(id);
|
|
237
|
+
if (!convention) {
|
|
238
|
+
results.failed.push({ id, error: 'Convention not found' });
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
const result = await evolver.evolve(convention);
|
|
242
|
+
if (result) {
|
|
243
|
+
results.success.push(id);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
results.failed.push({ id, error: String(err) });
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
// 进化所有 auto_optimize=true 的规范
|
|
253
|
+
const evolveResults = await evolver.evolveAll();
|
|
254
|
+
results.success = evolveResults.map(r => r.conventionId);
|
|
255
|
+
}
|
|
256
|
+
res.json({ success: true, results });
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
handleError(err, res, 'POST /api/conventions/batch-evolve');
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
// ── 获取规范 YAML 原文 ──────────────────────────────────────────────────────
|
|
263
|
+
app.get('/api/conventions/:id/yaml', (req, res) => {
|
|
264
|
+
try {
|
|
265
|
+
const id = validateStringLength(req.params.id, 'id', 1, 200);
|
|
266
|
+
const loader = new ConventionLoader();
|
|
267
|
+
const convention = loader.findById(id);
|
|
268
|
+
if (!convention || !convention.filePath) {
|
|
269
|
+
res.status(404).json({ error: 'Convention not found' });
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const yaml = fs.readFileSync(convention.filePath, 'utf-8');
|
|
273
|
+
res.json({ id, yaml });
|
|
274
|
+
}
|
|
275
|
+
catch (err) {
|
|
276
|
+
handleError(err, res, 'GET /api/conventions/:id/yaml');
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
// ── 保存规范 YAML 原文 ──────────────────────────────────────────────────────
|
|
280
|
+
app.put('/api/conventions/:id/yaml', (req, res) => {
|
|
281
|
+
try {
|
|
282
|
+
const id = validateStringLength(req.params.id, 'id', 1, 200);
|
|
283
|
+
const { yaml } = req.body;
|
|
284
|
+
if (!yaml) {
|
|
285
|
+
res.status(400).json({ error: 'Missing yaml content' });
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
// 不允许修改官方规范
|
|
289
|
+
if (id.startsWith('official-')) {
|
|
290
|
+
res.status(400).json({ error: 'Cannot modify official conventions' });
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
const loader = new ConventionLoader();
|
|
294
|
+
const convention = loader.findById(id);
|
|
295
|
+
if (!convention || !convention.filePath) {
|
|
296
|
+
res.status(404).json({ error: 'Convention not found' });
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
fs.writeFileSync(convention.filePath, yaml, 'utf-8');
|
|
300
|
+
res.json({ success: true });
|
|
301
|
+
}
|
|
302
|
+
catch (err) {
|
|
303
|
+
handleError(err, res, 'PUT /api/conventions/:id/yaml');
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=conventions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conventions.js","sourceRoot":"","sources":["../../../src/web/routes/conventions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-conventions.d.ts","sourceRoot":"","sources":["../../../src/web/routes/project-conventions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAWvC;;;GAGG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CA+JlE"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { ConventionManager } from '../../convention/convention-manager.js';
|
|
4
|
+
import { ConventionLoader } from '../../convention/convention-loader.js';
|
|
5
|
+
import { ConventionDistiller } from '../../convention/convention-distiller.js';
|
|
6
|
+
import { ConfigManager } from '../../config/index.js';
|
|
7
|
+
import { createSharedApi } from '../../utils/claude-api.js';
|
|
8
|
+
import { handleError } from '../utils/errors.js';
|
|
9
|
+
import { validateStringLength } from '../utils/validation.js';
|
|
10
|
+
/**
|
|
11
|
+
* 项目级规范管理路由
|
|
12
|
+
* 管理项目绑定的规范列表、蒸馏规范、绑定/解绑操作
|
|
13
|
+
*/
|
|
14
|
+
export function registerProjectConventionRoutes(app) {
|
|
15
|
+
const loader = new ConventionLoader();
|
|
16
|
+
const manager = new ConventionManager(loader);
|
|
17
|
+
// ── 获取项目规范概览 ────────────────────────────────────────────────────────
|
|
18
|
+
app.get('/api/projects/:encodedPath/conventions', (req, res) => {
|
|
19
|
+
try {
|
|
20
|
+
const encodedPath = validateStringLength(req.params.encodedPath, 'encodedPath', 1, 500);
|
|
21
|
+
const projectPath = decodeURIComponent(encodedPath);
|
|
22
|
+
// 获取绑定的规范列表
|
|
23
|
+
const activeConventions = manager.getActiveConventions(projectPath);
|
|
24
|
+
// 获取项目蒸馏规范(如果存在)
|
|
25
|
+
const customConvention = manager.loadProjectCustomConvention(projectPath);
|
|
26
|
+
res.json({
|
|
27
|
+
bindings: activeConventions,
|
|
28
|
+
custom: customConvention,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
handleError(err, res, 'GET /api/projects/:encodedPath/conventions');
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
// ── 绑定规范到项目 ──────────────────────────────────────────────────────────
|
|
36
|
+
app.post('/api/projects/:encodedPath/conventions/bind', (req, res) => {
|
|
37
|
+
try {
|
|
38
|
+
const encodedPath = validateStringLength(req.params.encodedPath, 'encodedPath', 1, 500);
|
|
39
|
+
const projectPath = decodeURIComponent(encodedPath);
|
|
40
|
+
const conventionId = validateStringLength(req.body.conventionId, 'conventionId', 1, 200);
|
|
41
|
+
const convention = manager.bind(projectPath, conventionId);
|
|
42
|
+
res.json({ success: true, convention });
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
handleError(err, res, 'POST /api/projects/:encodedPath/conventions/bind');
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
// ── 解绑规范 ────────────────────────────────────────────────────────────────
|
|
49
|
+
app.delete('/api/projects/:encodedPath/conventions/:id', (req, res) => {
|
|
50
|
+
try {
|
|
51
|
+
const encodedPath = validateStringLength(req.params.encodedPath, 'encodedPath', 1, 500);
|
|
52
|
+
const projectPath = decodeURIComponent(encodedPath);
|
|
53
|
+
const conventionId = validateStringLength(req.params.id, 'id', 1, 200);
|
|
54
|
+
manager.unbind(projectPath, conventionId);
|
|
55
|
+
res.json({ success: true });
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
handleError(err, res, 'DELETE /api/projects/:encodedPath/conventions/:id');
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
// ── 获取项目蒸馏规范 ────────────────────────────────────────────────────────
|
|
62
|
+
app.get('/api/projects/:encodedPath/conventions/custom', (req, res) => {
|
|
63
|
+
try {
|
|
64
|
+
const encodedPath = validateStringLength(req.params.encodedPath, 'encodedPath', 1, 500);
|
|
65
|
+
const projectPath = decodeURIComponent(encodedPath);
|
|
66
|
+
const customConvention = manager.loadProjectCustomConvention(projectPath);
|
|
67
|
+
if (!customConvention) {
|
|
68
|
+
res.status(404).json({ error: '项目尚未生成蒸馏规范' });
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
res.json(customConvention);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
handleError(err, res, 'GET /api/projects/:encodedPath/conventions/custom');
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
// ── 更新项目蒸馏规范 ────────────────────────────────────────────────────────
|
|
78
|
+
app.put('/api/projects/:encodedPath/conventions/custom', (req, res) => {
|
|
79
|
+
try {
|
|
80
|
+
const encodedPath = validateStringLength(req.params.encodedPath, 'encodedPath', 1, 500);
|
|
81
|
+
const projectPath = decodeURIComponent(encodedPath);
|
|
82
|
+
const yaml = validateStringLength(req.body.yaml, 'yaml', 1, 100000);
|
|
83
|
+
const filePath = ConventionDistiller.customFilePath(projectPath);
|
|
84
|
+
const dir = path.dirname(filePath);
|
|
85
|
+
if (!fs.existsSync(dir))
|
|
86
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
87
|
+
fs.writeFileSync(filePath, yaml, 'utf-8');
|
|
88
|
+
// 重新加载验证
|
|
89
|
+
const updated = loader.loadFile(filePath);
|
|
90
|
+
res.json({ success: true, convention: updated });
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
handleError(err, res, 'PUT /api/projects/:encodedPath/conventions/custom');
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
// ── 触发蒸馏 ────────────────────────────────────────────────────────────────
|
|
97
|
+
app.post('/api/projects/:encodedPath/conventions/distill', async (req, res) => {
|
|
98
|
+
try {
|
|
99
|
+
const encodedPath = validateStringLength(req.params.encodedPath, 'encodedPath', 1, 500);
|
|
100
|
+
const projectPath = decodeURIComponent(encodedPath);
|
|
101
|
+
const config = ConfigManager.getInstance().get();
|
|
102
|
+
const api = createSharedApi(config.distill.api_key || undefined, config.distill.model, config.distill.base_url || undefined);
|
|
103
|
+
if (!api) {
|
|
104
|
+
res.status(400).json({ error: 'API 配置缺失,请先配置 distill.api_key' });
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const distiller = new ConventionDistiller(api, loader);
|
|
108
|
+
// 获取当前绑定的源规范
|
|
109
|
+
const sourceConventions = manager.getActiveConventions(projectPath)
|
|
110
|
+
.filter(c => !c.id.startsWith('custom-'));
|
|
111
|
+
// 获取现有蒸馏规范(增量模式)
|
|
112
|
+
const existingCustom = manager.loadProjectCustomConvention(projectPath);
|
|
113
|
+
// 执行蒸馏
|
|
114
|
+
const { convention: result, result: distillResult } = await distiller.distill(projectPath, sourceConventions, existingCustom || undefined, undefined // projectProfile 可选
|
|
115
|
+
);
|
|
116
|
+
res.json({
|
|
117
|
+
success: true,
|
|
118
|
+
convention: result,
|
|
119
|
+
changes: distillResult.changes,
|
|
120
|
+
isIncremental: !!existingCustom,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
handleError(err, res, 'POST /api/projects/:encodedPath/conventions/distill');
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
// ── 获取项目蒸馏规范的 YAML 原文 ────────────────────────────────────────────
|
|
128
|
+
app.get('/api/projects/:encodedPath/conventions/custom/yaml', (req, res) => {
|
|
129
|
+
try {
|
|
130
|
+
const encodedPath = validateStringLength(req.params.encodedPath, 'encodedPath', 1, 500);
|
|
131
|
+
const projectPath = decodeURIComponent(encodedPath);
|
|
132
|
+
const filePath = ConventionDistiller.customFilePath(projectPath);
|
|
133
|
+
if (!fs.existsSync(filePath)) {
|
|
134
|
+
res.status(404).json({ error: '项目尚未生成蒸馏规范' });
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const yaml = fs.readFileSync(filePath, 'utf-8');
|
|
138
|
+
res.json({ yaml });
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
handleError(err, res, 'GET /api/projects/:encodedPath/conventions/custom/yaml');
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=project-conventions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-conventions.js","sourceRoot":"","sources":["../../../src/web/routes/project-conventions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../../src/web/routes/skills.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../../src/web/routes/skills.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAYvC,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAuZtD"}
|