autosnippet 2.9.0 → 2.11.0
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 +12 -12
- package/bin/cli.js +53 -40
- package/config/constitution.yaml +9 -2
- package/dashboard/dist/assets/{icons-CH-H9x0E.js → icons-D4IWpDIk.js} +105 -100
- package/dashboard/dist/assets/index-CWBNcF9z.css +1 -0
- package/dashboard/dist/assets/index-DHtzhbuG.js +120 -0
- package/dashboard/dist/index.html +3 -3
- package/lib/cli/AiScanService.js +35 -36
- package/lib/cli/KnowledgeSyncService.js +345 -0
- package/lib/cli/SetupService.js +8 -26
- package/lib/cli/UpgradeService.js +28 -0
- package/lib/core/gateway/GatewayActionRegistry.js +48 -58
- package/lib/domain/index.js +16 -11
- package/lib/domain/knowledge/KnowledgeEntry.js +289 -0
- package/lib/domain/knowledge/KnowledgeRepository.js +123 -0
- package/lib/domain/knowledge/Lifecycle.js +99 -0
- package/lib/domain/knowledge/index.js +27 -0
- package/lib/domain/knowledge/values/Constraints.js +128 -0
- package/lib/domain/knowledge/values/Content.js +69 -0
- package/lib/domain/knowledge/values/Quality.js +81 -0
- package/lib/domain/knowledge/values/Reasoning.js +70 -0
- package/lib/domain/knowledge/values/Relations.js +142 -0
- package/lib/domain/knowledge/values/Stats.js +72 -0
- package/lib/domain/knowledge/values/index.js +9 -0
- package/lib/external/ai/AiProvider.js +85 -11
- package/lib/external/mcp/McpServer.js +7 -5
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +18 -2
- package/lib/external/mcp/handlers/bootstrap.js +116 -11
- package/lib/external/mcp/handlers/browse.js +76 -73
- package/lib/external/mcp/handlers/candidate.js +26 -275
- package/lib/external/mcp/handlers/guard.js +2 -0
- package/lib/external/mcp/handlers/knowledge.js +267 -0
- package/lib/external/mcp/handlers/structure.js +25 -23
- package/lib/external/mcp/handlers/system.js +10 -12
- package/lib/external/mcp/tools.js +134 -140
- package/lib/http/HttpServer.js +14 -8
- package/lib/http/routes/ai.js +4 -3
- package/lib/http/routes/extract.js +48 -4
- package/lib/http/routes/knowledge.js +246 -0
- package/lib/http/routes/search.js +12 -17
- package/lib/infrastructure/database/migrations/016_unified_knowledge_entries.js +395 -0
- package/lib/infrastructure/database/migrations/017_camelcase_knowledge_entries.js +107 -0
- package/lib/infrastructure/external/XcodeAutomation.js +187 -103
- package/lib/injection/ServiceContainer.js +69 -60
- package/lib/repository/knowledge/KnowledgeRepository.impl.js +338 -0
- package/lib/service/automation/DirectiveDetector.js +2 -3
- package/lib/service/automation/FileWatcher.js +59 -28
- package/lib/service/automation/XcodeIntegration.js +931 -156
- package/lib/service/automation/handlers/AlinkHandler.js +5 -4
- package/lib/service/automation/handlers/CreateHandler.js +53 -19
- package/lib/service/automation/handlers/DraftHandler.js +1 -1
- package/lib/service/automation/handlers/GuardHandler.js +183 -20
- package/lib/service/automation/handlers/SearchHandler.js +25 -22
- package/lib/service/candidate/SimilarityService.js +2 -2
- package/lib/service/chat/AnalystAgent.js +9 -0
- package/lib/service/chat/CandidateGuardrail.js +22 -11
- package/lib/service/chat/ChatAgent.js +132 -54
- package/lib/service/chat/ContextWindow.js +5 -5
- package/lib/service/chat/HandoffProtocol.js +1 -0
- package/lib/service/chat/ProducerAgent.js +40 -13
- package/lib/service/chat/ReasoningLayer.js +854 -0
- package/lib/service/chat/ReasoningTrace.js +329 -0
- package/lib/service/chat/tools.js +308 -205
- package/lib/service/cursor/CursorDeliveryPipeline.js +279 -0
- package/lib/service/cursor/KnowledgeCompressor.js +87 -0
- package/lib/service/cursor/RulesGenerator.js +168 -0
- package/lib/service/cursor/SkillsSyncer.js +268 -0
- package/lib/service/cursor/TokenBudget.js +58 -0
- package/lib/service/cursor/TopicClassifier.js +141 -0
- package/lib/service/guard/GuardCheckEngine.js +99 -10
- package/lib/service/guard/GuardService.js +57 -46
- package/lib/service/knowledge/ConfidenceRouter.js +159 -0
- package/lib/service/knowledge/KnowledgeFileWriter.js +595 -0
- package/lib/service/knowledge/KnowledgeService.js +802 -0
- package/lib/service/recipe/RecipeParser.js +3 -12
- package/lib/service/search/SearchEngine.js +67 -22
- package/lib/service/skills/SignalCollector.js +14 -9
- package/lib/service/skills/SkillAdvisor.js +13 -11
- package/lib/service/snippet/SnippetFactory.js +5 -5
- package/lib/service/spm/SpmService.js +15 -48
- package/lib/shared/RecipeReadinessChecker.js +6 -11
- package/package.json +1 -1
- package/scripts/install-cursor-skill.js +0 -6
- package/scripts/migrate-md-to-knowledge.mjs +364 -0
- package/skills/autosnippet-analysis/SKILL.md +15 -7
- package/skills/autosnippet-candidates/SKILL.md +8 -8
- package/skills/autosnippet-coldstart/SKILL.md +8 -4
- package/skills/autosnippet-concepts/SKILL.md +7 -6
- package/skills/autosnippet-create/SKILL.md +13 -13
- package/skills/autosnippet-intent/SKILL.md +3 -2
- package/skills/autosnippet-lifecycle/SKILL.md +5 -5
- package/skills/autosnippet-recipes/SKILL.md +18 -6
- package/templates/constitution.yaml +1 -1
- package/templates/copilot-instructions.md +6 -6
- package/templates/recipes-setup/README.md +3 -3
- package/dashboard/dist/assets/index-CqJRvYRL.js +0 -197
- package/dashboard/dist/assets/index-DICm9PNa.css +0 -1
- package/lib/cli/CandidateSyncService.js +0 -261
- package/lib/cli/SyncService.js +0 -356
- package/lib/domain/candidate/Candidate.js +0 -196
- package/lib/domain/candidate/CandidateRepository.js +0 -107
- package/lib/domain/candidate/Reasoning.js +0 -52
- package/lib/domain/recipe/Recipe.js +0 -421
- package/lib/domain/recipe/RecipeRepository.js +0 -54
- package/lib/domain/types/CandidateStatus.js +0 -52
- package/lib/http/routes/candidates.js +0 -559
- package/lib/http/routes/recipes.js +0 -397
- package/lib/repository/candidate/CandidateRepository.impl.js +0 -230
- package/lib/repository/recipe/RecipeRepository.impl.js +0 -498
- package/lib/service/candidate/CandidateAggregator.js +0 -52
- package/lib/service/candidate/CandidateFileWriter.js +0 -383
- package/lib/service/candidate/CandidateService.js +0 -1001
- package/lib/service/recipe/RecipeFileWriter.js +0 -514
- package/lib/service/recipe/RecipeService.js +0 -786
- package/lib/service/recipe/RecipeStatsTracker.js +0 -148
package/README.md
CHANGED
|
@@ -86,7 +86,7 @@ asd status # 自检项目根、AI Provider、索引、Dashboard
|
|
|
86
86
|
|
|
87
87
|
```
|
|
88
88
|
用户:「扫描 NetworkModule 这个 Target,提取最佳实践」
|
|
89
|
-
Cursor →
|
|
89
|
+
Cursor → get_targets → get_target_files → 逐文件提取 → submit_knowledge_batch
|
|
90
90
|
→ Dashboard Candidates 页面审核 → 保存为 Recipe
|
|
91
91
|
```
|
|
92
92
|
|
|
@@ -171,20 +171,20 @@ asd install:vscode-copilot # 配置 MCP 和 Copilot 指令
|
|
|
171
171
|
|
|
172
172
|
## MCP 工具一览
|
|
173
173
|
|
|
174
|
-
38 个 MCP
|
|
174
|
+
38 个 MCP 工具按功能分组(省略了 **autosnippet_** 前缀):
|
|
175
175
|
|
|
176
176
|
| 分类 | 工具 |
|
|
177
177
|
|------|------|
|
|
178
|
-
| **系统** | `
|
|
179
|
-
| **搜索** | `
|
|
180
|
-
| **Recipe 浏览** | `
|
|
181
|
-
| **候选管理** | `
|
|
182
|
-
| **知识图谱** | `
|
|
183
|
-
| **项目结构** | `
|
|
184
|
-
| **Guard** | `
|
|
185
|
-
| **冷启动** | `
|
|
186
|
-
| **Skills** | `
|
|
187
|
-
| **治理** | `
|
|
178
|
+
| **系统** | `health`、`capabilities` |
|
|
179
|
+
| **搜索** | `search`(统合入口)、`context_search`(4 层漏斗)、`keyword_search`、`semantic_search` |
|
|
180
|
+
| **Recipe 浏览** | `list_recipes`、`get_recipe`、`list_rules`、`patterns`、`list_facts`、`recipe_insights`、`confirm_usage` |
|
|
181
|
+
| **候选管理** | `validate_candidate`、`check_duplicate`、`submit_knowledge`、`submit_knowledge_batch`、`submit_knowledge_batch`、`enrich_candidates` |
|
|
182
|
+
| **知识图谱** | `graph_query`、`graph_impact`、`graph_path`、`graph_stats` |
|
|
183
|
+
| **项目结构** | `get_targets`、`get_target_files`、`get_target_metadata` |
|
|
184
|
+
| **Guard** | `guard_check`、`guard_audit_files`、`scan_project` |
|
|
185
|
+
| **冷启动** | `bootstrap_knowledge`、`bootstrap_refine` |
|
|
186
|
+
| **Skills** | `list_skills`、`load_skill`、`create_skill`、`delete_skill`、`update_skill`、`suggest_skills` |
|
|
187
|
+
| **治理** | `compliance_report` |
|
|
188
188
|
|
|
189
189
|
## 配置
|
|
190
190
|
|
package/bin/cli.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Usage:
|
|
7
7
|
* asd setup - 初始化项目
|
|
8
|
-
* asd ais [Target] - AI 扫描 Target →
|
|
8
|
+
* asd ais [Target] - AI 扫描 Target → 直接发布 Recipes
|
|
9
9
|
* asd search <query> - 搜索知识库
|
|
10
10
|
* asd guard <file> - Guard 检查
|
|
11
11
|
* asd watch - 文件监控
|
|
@@ -78,10 +78,10 @@ program
|
|
|
78
78
|
// ─────────────────────────────────────────────────────
|
|
79
79
|
program
|
|
80
80
|
.command('ais [target]')
|
|
81
|
-
.description('AI 扫描 Target 源码 →
|
|
81
|
+
.description('AI 扫描 Target 源码 → 提取并发布 Recipes(需配置 AI Provider)')
|
|
82
82
|
.option('-d, --dir <path>', '项目目录', '.')
|
|
83
83
|
.option('-m, --max-files <n>', '最大扫描文件数', '200')
|
|
84
|
-
.option('--dry-run', '
|
|
84
|
+
.option('--dry-run', '仅预览,不发布 Recipe')
|
|
85
85
|
.option('--json', '以 JSON 格式输出')
|
|
86
86
|
.action(async (target, opts) => {
|
|
87
87
|
const projectRoot = resolve(opts.dir);
|
|
@@ -99,7 +99,7 @@ program
|
|
|
99
99
|
const scanner = new AiScanService({ container, projectRoot });
|
|
100
100
|
|
|
101
101
|
const ora = (await import('ora')).default;
|
|
102
|
-
const spinner = ora('
|
|
102
|
+
const spinner = ora('正在扫描源文件并提取 Recipe...').start();
|
|
103
103
|
|
|
104
104
|
const report = await scanner.scan(target || null, {
|
|
105
105
|
maxFiles: parseInt(opts.maxFiles, 10),
|
|
@@ -114,7 +114,7 @@ program
|
|
|
114
114
|
console.log(`\n✅ AI 扫描完成`);
|
|
115
115
|
console.log(` 扫描文件: ${report.files}`);
|
|
116
116
|
console.log(` 跳过: ${report.skipped}`);
|
|
117
|
-
console.log(`
|
|
117
|
+
console.log(` 发布 Recipe: ${report.published}`);
|
|
118
118
|
if (report.errors.length > 0) {
|
|
119
119
|
console.log(`\n⚠️ ${report.errors.length} 个错误:`);
|
|
120
120
|
for (const err of report.errors.slice(0, 10)) {
|
|
@@ -122,8 +122,8 @@ program
|
|
|
122
122
|
}
|
|
123
123
|
if (report.errors.length > 10) console.log(` ... 及其他 ${report.errors.length - 10} 个`);
|
|
124
124
|
}
|
|
125
|
-
if (!opts.dryRun && report.
|
|
126
|
-
console.log(`\n📋
|
|
125
|
+
if (!opts.dryRun && report.published > 0) {
|
|
126
|
+
console.log(`\n📋 Recipe 已发布,可通过 asd search 或 Cursor Rules 使用`);
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
@@ -490,6 +490,47 @@ program
|
|
|
490
490
|
});
|
|
491
491
|
});
|
|
492
492
|
|
|
493
|
+
// ─────────────────────────────────────────────────────
|
|
494
|
+
// cursor-rules 命令
|
|
495
|
+
// ─────────────────────────────────────────────────────
|
|
496
|
+
program
|
|
497
|
+
.command('cursor-rules')
|
|
498
|
+
.description('生成 Cursor 4 通道交付物料(Rules + Skills → .cursor/)')
|
|
499
|
+
.option('-d, --dir <path>', '项目目录', '.')
|
|
500
|
+
.option('--verbose', '详细输出')
|
|
501
|
+
.action(async (opts) => {
|
|
502
|
+
const projectRoot = resolve(opts.dir);
|
|
503
|
+
|
|
504
|
+
console.log(`\n🚀 AutoSnippet — Cursor Delivery Pipeline`);
|
|
505
|
+
console.log(` 项目: ${basename(projectRoot)}`);
|
|
506
|
+
console.log(` 路径: ${projectRoot}\n`);
|
|
507
|
+
|
|
508
|
+
const { bootstrap, container } = await initContainer({ projectRoot });
|
|
509
|
+
try {
|
|
510
|
+
const pipeline = container.get('cursorDeliveryPipeline');
|
|
511
|
+
const result = await pipeline.deliver();
|
|
512
|
+
|
|
513
|
+
console.log(`✅ Cursor 交付物料生成完成\n`);
|
|
514
|
+
console.log(` Channel A (Always-On Rules): ${result.channelA.rulesCount} 条规则 (${result.channelA.tokensUsed} tokens)`);
|
|
515
|
+
console.log(` Channel B (Smart Rules): ${result.channelB.topicCount} 个主题, ${result.channelB.patternsCount} 个模式 (${result.channelB.totalTokens} tokens)`);
|
|
516
|
+
console.log(` Channel C (Agent Skills): ${result.channelC.synced} 个 Skills 已同步`);
|
|
517
|
+
if (result.channelC.errors > 0) {
|
|
518
|
+
console.log(` ⚠️ ${result.channelC.errors} 个错误`);
|
|
519
|
+
}
|
|
520
|
+
console.log(`\n 总耗时: ${result.stats.duration}ms`);
|
|
521
|
+
|
|
522
|
+
if (opts.verbose && result.channelB.topics) {
|
|
523
|
+
console.log(`\n Channel B 主题明细:`);
|
|
524
|
+
for (const [topic, info] of Object.entries(result.channelB.topics)) {
|
|
525
|
+
console.log(` - ${topic}: ${info.patternsCount} patterns (${info.tokensUsed} tokens)`);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
console.log('');
|
|
529
|
+
} finally {
|
|
530
|
+
await bootstrap.shutdown?.();
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
|
|
493
534
|
// ─────────────────────────────────────────────────────
|
|
494
535
|
// sync 命令
|
|
495
536
|
// ─────────────────────────────────────────────────────
|
|
@@ -501,12 +542,10 @@ program
|
|
|
501
542
|
.option('--force', '忽略 hash 强制覆盖')
|
|
502
543
|
.action(async (opts) => {
|
|
503
544
|
const projectRoot = resolve(opts.dir);
|
|
504
|
-
const {
|
|
505
|
-
const
|
|
506
|
-
const syncService = new SyncService(projectRoot);
|
|
507
|
-
const candidateSyncService = new CandidateSyncService(projectRoot);
|
|
545
|
+
const { KnowledgeSyncService } = await import('../lib/cli/KnowledgeSyncService.js');
|
|
546
|
+
const syncService = new KnowledgeSyncService(projectRoot);
|
|
508
547
|
|
|
509
|
-
console.log(`\n🔄 AutoSnippet
|
|
548
|
+
console.log(`\n🔄 AutoSnippet V3 — 同步 knowledge entries`);
|
|
510
549
|
console.log(` 项目: ${basename(projectRoot)}`);
|
|
511
550
|
console.log(` 路径: ${projectRoot}`);
|
|
512
551
|
if (opts.dryRun) console.log(' 模式: dry-run(仅报告)');
|
|
@@ -533,7 +572,7 @@ program
|
|
|
533
572
|
});
|
|
534
573
|
|
|
535
574
|
// 输出报告
|
|
536
|
-
console.log(`✅
|
|
575
|
+
console.log(`✅ Knowledge 同步完成`);
|
|
537
576
|
console.log(` 扫描: ${report.synced + report.skipped} 文件`);
|
|
538
577
|
console.log(` 新增: ${report.created}`);
|
|
539
578
|
console.log(` 更新: ${report.updated}`);
|
|
@@ -547,38 +586,12 @@ program
|
|
|
547
586
|
}
|
|
548
587
|
|
|
549
588
|
if (report.orphaned.length > 0) {
|
|
550
|
-
console.log(`\n🗑️ ${report.orphaned.length}
|
|
589
|
+
console.log(`\n🗑️ ${report.orphaned.length} 个孤儿条目已标记 deprecated:`);
|
|
551
590
|
for (const id of report.orphaned) {
|
|
552
591
|
console.log(` - ${id}`);
|
|
553
592
|
}
|
|
554
593
|
}
|
|
555
594
|
|
|
556
|
-
// ── Candidates 同步 ──
|
|
557
|
-
const cReport = candidateSyncService.sync(db, {
|
|
558
|
-
dryRun: opts.dryRun,
|
|
559
|
-
force: opts.force,
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
console.log(`\n✅ Candidates 同步完成`);
|
|
563
|
-
console.log(` 扫描: ${cReport.synced + cReport.skipped} 文件`);
|
|
564
|
-
console.log(` 新增: ${cReport.created}`);
|
|
565
|
-
console.log(` 更新: ${cReport.updated}`);
|
|
566
|
-
console.log(` 跳过: ${cReport.skipped}`);
|
|
567
|
-
|
|
568
|
-
if (cReport.violations.length > 0) {
|
|
569
|
-
console.log(`\n⚠️ 检测到 ${cReport.violations.length} 个 Candidate 手动编辑:`);
|
|
570
|
-
for (const v of cReport.violations) {
|
|
571
|
-
console.log(` - ${v}`);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
if (cReport.orphaned.length > 0) {
|
|
576
|
-
console.log(`\n📋 ${cReport.orphaned.length} 个 Candidate 仅存于 DB(无 .md 文件):`);
|
|
577
|
-
for (const id of cReport.orphaned) {
|
|
578
|
-
console.log(` - ${id}`);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
|
|
582
595
|
console.log('');
|
|
583
596
|
} finally {
|
|
584
597
|
await bootstrap.shutdown?.();
|
package/config/constitution.yaml
CHANGED
|
@@ -32,12 +32,19 @@ roles:
|
|
|
32
32
|
- "read:recipes"
|
|
33
33
|
- "read:guard_rules"
|
|
34
34
|
- "create:candidates"
|
|
35
|
-
- "
|
|
35
|
+
- "candidate:update"
|
|
36
|
+
- "knowledge:create"
|
|
37
|
+
- "knowledge:update"
|
|
38
|
+
- "submit:knowledge"
|
|
36
39
|
- "read:audit_logs:self"
|
|
37
40
|
- "knowledge:bootstrap"
|
|
38
41
|
- "create:skills"
|
|
42
|
+
- "update:skills"
|
|
43
|
+
- "delete:skills"
|
|
39
44
|
constraints:
|
|
40
|
-
- "
|
|
45
|
+
- "can submit knowledge entries (all go to pending)"
|
|
46
|
+
- "cannot publish/deprecate knowledge — only developer can do that"
|
|
47
|
+
- "can reactivate deprecated entries back to pending"
|
|
41
48
|
- "cannot modify Guard rules"
|
|
42
49
|
- "cannot delete any data"
|
|
43
50
|
- id: "chat_agent"
|