autosnippet 3.3.0 → 3.3.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.
Files changed (245) hide show
  1. package/dashboard/dist/assets/icons-BJ2mUBi8.js +1 -0
  2. package/dashboard/dist/assets/index-B659K9t5.js +128 -0
  3. package/dashboard/dist/assets/index-NCm40PMD.css +1 -0
  4. package/dashboard/dist/index.html +3 -3
  5. package/dist/bin/cli.d.ts +1 -0
  6. package/dist/bin/cli.js +284 -142
  7. package/dist/lib/agent/context/ExplorationTracker.d.ts +2 -0
  8. package/dist/lib/agent/context/ExplorationTracker.js +21 -3
  9. package/dist/lib/agent/core/ToolExecutionPipeline.d.ts +3 -1
  10. package/dist/lib/agent/core/ToolExecutionPipeline.js +8 -1
  11. package/dist/lib/agent/forge/DynamicComposer.d.ts +58 -0
  12. package/dist/lib/agent/forge/DynamicComposer.js +99 -0
  13. package/dist/lib/agent/forge/SandboxRunner.d.ts +60 -0
  14. package/dist/lib/agent/forge/SandboxRunner.js +251 -0
  15. package/dist/lib/agent/forge/TemporaryToolRegistry.d.ts +76 -0
  16. package/dist/lib/agent/forge/TemporaryToolRegistry.js +154 -0
  17. package/dist/lib/agent/forge/ToolForge.d.ts +92 -0
  18. package/dist/lib/agent/forge/ToolForge.js +239 -0
  19. package/dist/lib/agent/forge/ToolRequirementAnalyzer.d.ts +44 -0
  20. package/dist/lib/agent/forge/ToolRequirementAnalyzer.js +119 -0
  21. package/dist/lib/agent/tools/ToolRegistry.d.ts +2 -0
  22. package/dist/lib/agent/tools/ToolRegistry.js +4 -0
  23. package/dist/lib/agent/tools/composite.js +0 -1
  24. package/dist/lib/agent/tools/index.d.ts +2 -50
  25. package/dist/lib/agent/tools/index.js +2 -3
  26. package/dist/lib/agent/tools/lifecycle.d.ts +1 -58
  27. package/dist/lib/agent/tools/lifecycle.js +2 -75
  28. package/dist/lib/cli/KnowledgeSyncService.d.ts +26 -0
  29. package/dist/lib/cli/KnowledgeSyncService.js +33 -1
  30. package/dist/lib/cli/deploy/FileManifest.d.ts +0 -21
  31. package/dist/lib/cli/deploy/FileManifest.js +0 -11
  32. package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +10 -0
  33. package/dist/lib/domain/knowledge/KnowledgeEntry.js +2 -0
  34. package/dist/lib/domain/knowledge/Lifecycle.d.ts +19 -2
  35. package/dist/lib/domain/knowledge/Lifecycle.js +32 -6
  36. package/dist/lib/domain/knowledge/UnifiedValidator.d.ts +1 -5
  37. package/dist/lib/domain/knowledge/UnifiedValidator.js +7 -44
  38. package/dist/lib/domain/knowledge/values/Stats.d.ts +29 -0
  39. package/dist/lib/domain/knowledge/values/Stats.js +41 -0
  40. package/dist/lib/external/mcp/McpServer.d.ts +19 -38
  41. package/dist/lib/external/mcp/McpServer.js +145 -117
  42. package/dist/lib/external/mcp/autoApproveInjector.js +0 -2
  43. package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.d.ts +26 -1
  44. package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +41 -0
  45. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +49 -0
  46. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +3 -0
  47. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +27 -0
  48. package/dist/lib/external/mcp/handlers/bootstrap/skills.js +1 -1
  49. package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -0
  50. package/dist/lib/external/mcp/handlers/bootstrap-internal.js +2 -0
  51. package/dist/lib/external/mcp/handlers/browse.d.ts +1 -0
  52. package/dist/lib/external/mcp/handlers/browse.js +2 -1
  53. package/dist/lib/external/mcp/handlers/consolidated.d.ts +117 -6
  54. package/dist/lib/external/mcp/handlers/consolidated.js +251 -71
  55. package/dist/lib/external/mcp/handlers/guard.d.ts +150 -0
  56. package/dist/lib/external/mcp/handlers/guard.js +239 -5
  57. package/dist/lib/external/mcp/handlers/knowledge.d.ts +0 -29
  58. package/dist/lib/external/mcp/handlers/knowledge.js +1 -76
  59. package/dist/lib/external/mcp/handlers/panorama.d.ts +36 -0
  60. package/dist/lib/external/mcp/handlers/panorama.js +156 -0
  61. package/dist/lib/external/mcp/handlers/system.d.ts +2 -54
  62. package/dist/lib/external/mcp/handlers/system.js +3 -113
  63. package/dist/lib/external/mcp/handlers/task.d.ts +13 -24
  64. package/dist/lib/external/mcp/handlers/task.js +218 -557
  65. package/dist/lib/external/mcp/handlers/types.d.ts +91 -8
  66. package/dist/lib/external/mcp/handlers/types.js +18 -1
  67. package/dist/lib/external/mcp/handlers/wiki-external.d.ts +18 -1
  68. package/dist/lib/external/mcp/handlers/wiki-external.js +16 -1
  69. package/dist/lib/external/mcp/tools.d.ts +18 -24
  70. package/dist/lib/external/mcp/tools.js +132 -159
  71. package/dist/lib/http/HttpServer.js +52 -0
  72. package/dist/lib/http/middleware/validate.js +7 -3
  73. package/dist/lib/http/routes/audit.d.ts +8 -0
  74. package/dist/lib/http/routes/audit.js +51 -0
  75. package/dist/lib/http/routes/guardReport.d.ts +10 -0
  76. package/dist/lib/http/routes/guardReport.js +143 -0
  77. package/dist/lib/http/routes/knowledge.js +32 -1
  78. package/dist/lib/http/routes/panorama.d.ts +11 -0
  79. package/dist/lib/http/routes/panorama.js +322 -0
  80. package/dist/lib/http/routes/signals.d.ts +10 -0
  81. package/dist/lib/http/routes/signals.js +104 -0
  82. package/dist/lib/http/routes/task.d.ts +2 -3
  83. package/dist/lib/http/routes/task.js +17 -347
  84. package/dist/lib/http/routes/violations.js +1 -1
  85. package/dist/lib/infrastructure/audit/AuditLogger.d.ts +6 -1
  86. package/dist/lib/infrastructure/audit/AuditLogger.js +14 -1
  87. package/dist/lib/infrastructure/database/drizzle/schema.d.ts +202 -504
  88. package/dist/lib/infrastructure/database/drizzle/schema.js +38 -69
  89. package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.d.ts +8 -0
  90. package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.js +43 -0
  91. package/dist/lib/infrastructure/database/migrations/005_recipe_source_refs.d.ts +9 -0
  92. package/dist/lib/infrastructure/database/migrations/005_recipe_source_refs.js +24 -0
  93. package/dist/lib/infrastructure/logging/Logger.d.ts +2 -0
  94. package/dist/lib/infrastructure/logging/Logger.js +34 -7
  95. package/dist/lib/infrastructure/monitoring/ErrorTracker.js +3 -1
  96. package/dist/lib/infrastructure/monitoring/PerformanceMonitor.d.ts +2 -2
  97. package/dist/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -10
  98. package/dist/lib/infrastructure/notification/LarkNotifier.d.ts +24 -0
  99. package/dist/lib/infrastructure/notification/LarkNotifier.js +97 -0
  100. package/dist/lib/infrastructure/report/ReportStore.d.ts +45 -0
  101. package/dist/lib/infrastructure/report/ReportStore.js +133 -0
  102. package/dist/lib/infrastructure/signal/SignalAggregator.d.ts +18 -0
  103. package/dist/lib/infrastructure/signal/SignalAggregator.js +84 -0
  104. package/dist/lib/infrastructure/signal/SignalBridge.d.ts +13 -0
  105. package/dist/lib/infrastructure/signal/SignalBridge.js +20 -0
  106. package/dist/lib/infrastructure/signal/SignalBus.d.ts +63 -0
  107. package/dist/lib/infrastructure/signal/SignalBus.js +106 -0
  108. package/dist/lib/infrastructure/signal/SignalTraceWriter.d.ts +36 -0
  109. package/dist/lib/infrastructure/signal/SignalTraceWriter.js +130 -0
  110. package/dist/lib/infrastructure/vector/HnswVectorAdapter.js +18 -2
  111. package/dist/lib/injection/ServiceContainer.js +8 -0
  112. package/dist/lib/injection/ServiceMap.d.ts +16 -10
  113. package/dist/lib/injection/modules/AgentModule.d.ts +1 -1
  114. package/dist/lib/injection/modules/AgentModule.js +7 -1
  115. package/dist/lib/injection/modules/AppModule.d.ts +1 -1
  116. package/dist/lib/injection/modules/AppModule.js +4 -13
  117. package/dist/lib/injection/modules/GuardModule.js +27 -2
  118. package/dist/lib/injection/modules/InfraModule.d.ts +0 -1
  119. package/dist/lib/injection/modules/InfraModule.js +9 -7
  120. package/dist/lib/injection/modules/KnowledgeModule.d.ts +5 -0
  121. package/dist/lib/injection/modules/KnowledgeModule.js +131 -0
  122. package/dist/lib/injection/modules/PanoramaModule.d.ts +18 -0
  123. package/dist/lib/injection/modules/PanoramaModule.js +76 -0
  124. package/dist/lib/injection/modules/SignalModule.d.ts +10 -0
  125. package/dist/lib/injection/modules/SignalModule.js +84 -0
  126. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +1 -0
  127. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +6 -0
  128. package/dist/lib/service/bootstrap/BootstrapTaskManager.d.ts +3 -1
  129. package/dist/lib/service/bootstrap/BootstrapTaskManager.js +20 -1
  130. package/dist/lib/service/bootstrap/UiStartupTasks.d.ts +45 -0
  131. package/dist/lib/service/bootstrap/UiStartupTasks.js +101 -0
  132. package/dist/lib/service/delivery/AgentInstructionsGenerator.js +4 -5
  133. package/dist/lib/service/delivery/CursorDeliveryPipeline.d.ts +3 -1
  134. package/dist/lib/service/delivery/CursorDeliveryPipeline.js +13 -10
  135. package/dist/lib/service/delivery/RulesGenerator.js +3 -2
  136. package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +114 -0
  137. package/dist/lib/service/evolution/ConsolidationAdvisor.js +542 -0
  138. package/dist/lib/service/evolution/ContradictionDetector.d.ts +54 -0
  139. package/dist/lib/service/evolution/ContradictionDetector.js +253 -0
  140. package/dist/lib/service/evolution/DecayDetector.d.ts +71 -0
  141. package/dist/lib/service/evolution/DecayDetector.js +244 -0
  142. package/dist/lib/service/evolution/EnhancementSuggester.d.ts +38 -0
  143. package/dist/lib/service/evolution/EnhancementSuggester.js +220 -0
  144. package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +82 -0
  145. package/dist/lib/service/evolution/KnowledgeMetabolism.js +167 -0
  146. package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +53 -0
  147. package/dist/lib/service/evolution/RedundancyAnalyzer.js +210 -0
  148. package/dist/lib/service/evolution/StagingManager.d.ts +57 -0
  149. package/dist/lib/service/evolution/StagingManager.js +201 -0
  150. package/dist/lib/service/guard/ComplianceReporter.d.ts +42 -2
  151. package/dist/lib/service/guard/ComplianceReporter.js +43 -5
  152. package/dist/lib/service/guard/CoverageAnalyzer.d.ts +54 -0
  153. package/dist/lib/service/guard/CoverageAnalyzer.js +149 -0
  154. package/dist/lib/service/guard/GuardCheckEngine.d.ts +42 -0
  155. package/dist/lib/service/guard/GuardCheckEngine.js +465 -14
  156. package/dist/lib/service/guard/GuardFeedbackLoop.d.ts +3 -0
  157. package/dist/lib/service/guard/GuardFeedbackLoop.js +9 -0
  158. package/dist/lib/service/guard/ReverseGuard.d.ts +73 -0
  159. package/dist/lib/service/guard/ReverseGuard.js +256 -0
  160. package/dist/lib/service/guard/RuleLearner.d.ts +12 -0
  161. package/dist/lib/service/guard/RuleLearner.js +38 -0
  162. package/dist/lib/service/guard/UncertaintyCollector.d.ts +83 -0
  163. package/dist/lib/service/guard/UncertaintyCollector.js +149 -0
  164. package/dist/lib/service/guard/ViolationsStore.d.ts +1 -0
  165. package/dist/lib/service/guard/ViolationsStore.js +33 -3
  166. package/dist/lib/service/knowledge/ConfidenceRouter.d.ts +13 -0
  167. package/dist/lib/service/knowledge/ConfidenceRouter.js +14 -0
  168. package/dist/lib/service/knowledge/KnowledgeService.js +22 -4
  169. package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +68 -0
  170. package/dist/lib/service/knowledge/SourceRefReconciler.js +309 -0
  171. package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +27 -0
  172. package/dist/lib/service/panorama/CouplingAnalyzer.js +192 -0
  173. package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +28 -0
  174. package/dist/lib/service/panorama/DimensionAnalyzer.js +320 -0
  175. package/dist/lib/service/panorama/LayerInferrer.d.ts +19 -0
  176. package/dist/lib/service/panorama/LayerInferrer.js +182 -0
  177. package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +24 -0
  178. package/dist/lib/service/panorama/ModuleDiscoverer.js +185 -0
  179. package/dist/lib/service/panorama/PanoramaAggregator.d.ts +29 -0
  180. package/dist/lib/service/panorama/PanoramaAggregator.js +228 -0
  181. package/dist/lib/service/panorama/PanoramaScanner.d.ts +52 -0
  182. package/dist/lib/service/panorama/PanoramaScanner.js +188 -0
  183. package/dist/lib/service/panorama/PanoramaService.d.ts +125 -0
  184. package/dist/lib/service/panorama/PanoramaService.js +363 -0
  185. package/dist/lib/service/panorama/PanoramaTypes.d.ts +134 -0
  186. package/dist/lib/service/panorama/PanoramaTypes.js +6 -0
  187. package/dist/lib/service/panorama/RoleRefiner.d.ts +48 -0
  188. package/dist/lib/service/panorama/RoleRefiner.js +535 -0
  189. package/dist/lib/service/search/BM25Scorer.d.ts +2 -2
  190. package/dist/lib/service/search/CoarseRanker.d.ts +7 -6
  191. package/dist/lib/service/search/CoarseRanker.js +11 -10
  192. package/dist/lib/service/search/FieldWeightedScorer.d.ts +81 -0
  193. package/dist/lib/service/search/FieldWeightedScorer.js +318 -0
  194. package/dist/lib/service/search/MultiSignalRanker.d.ts +3 -2
  195. package/dist/lib/service/search/MultiSignalRanker.js +17 -1
  196. package/dist/lib/service/search/SearchEngine.d.ts +9 -7
  197. package/dist/lib/service/search/SearchEngine.js +67 -10
  198. package/dist/lib/service/search/SearchTypes.d.ts +25 -3
  199. package/dist/lib/service/search/SearchTypes.js +6 -1
  200. package/dist/lib/service/signal/HitRecorder.d.ts +68 -0
  201. package/dist/lib/service/signal/HitRecorder.js +173 -0
  202. package/dist/lib/service/skills/SignalCollector.d.ts +3 -1
  203. package/dist/lib/service/skills/SignalCollector.js +31 -1
  204. package/dist/lib/service/task/IntentExtractor.d.ts +66 -0
  205. package/dist/lib/service/task/IntentExtractor.js +256 -0
  206. package/dist/lib/service/task/PrimeSearchPipeline.d.ts +54 -0
  207. package/dist/lib/service/task/PrimeSearchPipeline.js +113 -0
  208. package/dist/lib/service/vector/VectorService.d.ts +3 -0
  209. package/dist/lib/service/vector/VectorService.js +38 -4
  210. package/dist/lib/shared/schemas/mcp-tools.d.ts +41 -96
  211. package/dist/lib/shared/schemas/mcp-tools.js +59 -119
  212. package/dist/scripts/analyze-signals.d.ts +20 -0
  213. package/dist/scripts/analyze-signals.js +155 -0
  214. package/dist/scripts/diagnose-mcp.js +1 -1
  215. package/package.json +1 -1
  216. package/skills/autosnippet-create/SKILL.md +98 -89
  217. package/skills/autosnippet-devdocs/SKILL.md +55 -57
  218. package/templates/claude-code/hooks/autosnippet-session.sh +10 -15
  219. package/templates/cursor-hooks/hooks/session-start.sh +1 -1
  220. package/templates/guard-ci.yml +2 -2
  221. package/templates/instructions/agent-static.md +2 -1
  222. package/templates/instructions/conventions.md +5 -6
  223. package/templates/recipes-setup/README.md +1 -2
  224. package/templates/recipes-setup/_template.md +39 -39
  225. package/dashboard/dist/assets/icons-BofcEZ3f.js +0 -1
  226. package/dashboard/dist/assets/index-D0whuycy.css +0 -1
  227. package/dashboard/dist/assets/index-SiN1GChm.js +0 -128
  228. package/dist/lib/domain/task/Task.d.ts +0 -140
  229. package/dist/lib/domain/task/Task.js +0 -254
  230. package/dist/lib/domain/task/TaskDependency.d.ts +0 -23
  231. package/dist/lib/domain/task/TaskDependency.js +0 -34
  232. package/dist/lib/domain/task/TaskIdGenerator.d.ts +0 -40
  233. package/dist/lib/domain/task/TaskIdGenerator.js +0 -75
  234. package/dist/lib/domain/task/index.d.ts +0 -4
  235. package/dist/lib/domain/task/index.js +0 -4
  236. package/dist/lib/infrastructure/database/migrations/002_add_tasks.d.ts +0 -11
  237. package/dist/lib/infrastructure/database/migrations/002_add_tasks.js +0 -86
  238. package/dist/lib/repository/task/TaskRepository.impl.d.ts +0 -171
  239. package/dist/lib/repository/task/TaskRepository.impl.js +0 -347
  240. package/dist/lib/service/task/TaskGraphService.d.ts +0 -222
  241. package/dist/lib/service/task/TaskGraphService.js +0 -597
  242. package/dist/lib/service/task/TaskKnowledgeBridge.d.ts +0 -95
  243. package/dist/lib/service/task/TaskKnowledgeBridge.js +0 -298
  244. package/dist/lib/service/task/TaskReadyEngine.d.ts +0 -84
  245. package/dist/lib/service/task/TaskReadyEngine.js +0 -115
package/dist/bin/cli.js CHANGED
@@ -15,6 +15,7 @@
15
15
  * asd upgrade - 升级 IDE 集成
16
16
  * asd mirror - 镜像 .cursor/ → .qoder/ .trae/
17
17
  * asd status - 环境状态
18
+ * asd health - 综合健康报告
18
19
  */
19
20
  import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, } from 'node:fs';
20
21
  import { join, resolve } from 'node:path';
@@ -475,6 +476,8 @@ program
475
476
  .option('--fail-on-error', '有 error 级违规时 exit 1', true)
476
477
  .option('--fail-on-warning', '超过 warning 阈值时 exit 2')
477
478
  .option('--max-warnings <n>', 'warning 阈值', '20')
479
+ .option('--max-uncertain <n>', 'uncertain 条目阈值 (超出时 exit 2)', '50')
480
+ .option('--min-coverage <n>', '最低覆盖率 (0-100,低于时 exit 3)', '0')
478
481
  .option('--report <format>', '报告格式: json | text | markdown', 'text')
479
482
  .option('--output <file>', '报告输出文件')
480
483
  .option('--min-score <n>', 'Quality Gate 最低分', '70')
@@ -513,10 +516,18 @@ program
513
516
  writeFileSync(opts.output, JSON.stringify(report, null, 2), 'utf8');
514
517
  }
515
518
  await bootstrap.shutdown();
516
- // Exit code
519
+ // Exit code: 0=PASS, 1=FAIL(violations), 2=WARN(uncertain/warnings), 3=FAIL(coverage)
520
+ const maxUncertain = parseInt(opts.maxUncertain, 10);
521
+ const minCoverage = parseInt(opts.minCoverage, 10);
517
522
  if (report.qualityGate.status === 'FAIL') {
518
523
  process.exit(report.summary.errors > 0 ? 1 : 2);
519
524
  }
525
+ if (minCoverage > 0 && (report.coverageScore ?? 100) < minCoverage) {
526
+ process.exit(3);
527
+ }
528
+ if (maxUncertain > 0 && (report.uncertainSummary?.total ?? 0) > maxUncertain) {
529
+ process.exit(2);
530
+ }
520
531
  process.exit(0);
521
532
  }
522
533
  catch (err) {
@@ -604,6 +615,86 @@ program
604
615
  }
605
616
  });
606
617
  // ─────────────────────────────────────────────────────
618
+ // panorama 命令
619
+ // ─────────────────────────────────────────────────────
620
+ program
621
+ .command('panorama [path]')
622
+ .description('项目全景分析:架构层级、覆盖率、知识空白')
623
+ .option('--json', '以 JSON 格式输出')
624
+ .option('--gaps', '仅显示知识空白区')
625
+ .option('--health', '仅显示健康度评分')
626
+ .action(async (scanPath, opts) => {
627
+ try {
628
+ const projectRoot = resolve(scanPath || '.');
629
+ const { bootstrap, container } = await initContainer({ projectRoot });
630
+ const panoramaService = container.get('panoramaService');
631
+ if (opts.gaps) {
632
+ const gaps = panoramaService.getGaps();
633
+ if (opts.json) {
634
+ cli.log(JSON.stringify(gaps, null, 2));
635
+ }
636
+ else {
637
+ cli.log(`\n🔍 Knowledge Gaps: ${gaps.length} found\n`);
638
+ for (const g of gaps.slice(0, 20)) {
639
+ const priority = g.priority === 'high' ? '🔴' : g.priority === 'medium' ? '🟡' : '🔵';
640
+ cli.log(` ${priority} [${g.dimensionName}] ${g.recipeCount} recipes (${g.status}) — ${g.suggestedTopics.join(', ')}`);
641
+ }
642
+ if (gaps.length > 20) {
643
+ cli.log(`\n ... and ${gaps.length - 20} more gaps`);
644
+ }
645
+ }
646
+ await bootstrap.shutdown();
647
+ return;
648
+ }
649
+ if (opts.health) {
650
+ const health = panoramaService.getHealth();
651
+ if (opts.json) {
652
+ cli.log(JSON.stringify(health, null, 2));
653
+ }
654
+ else {
655
+ const icon = health.healthScore >= 80 ? '✅' : health.healthScore >= 50 ? '⚠️' : '❌';
656
+ cli.log(`\n${icon} Panorama Health: ${health.healthScore}/100\n`);
657
+ cli.log(` Dimension Coverage: ${health.healthRadar.dimensionCoverage}%`);
658
+ cli.log(` Avg Coupling: ${health.avgCoupling}`);
659
+ cli.log(` Modules: ${health.moduleCount}`);
660
+ cli.log(` Cycles: ${health.cycleCount}`);
661
+ cli.log(` Gaps: ${health.gapCount} (${health.highPriorityGaps} high-priority)`);
662
+ }
663
+ await bootstrap.shutdown();
664
+ return;
665
+ }
666
+ // 默认: 全景概览
667
+ const overview = panoramaService.getOverview();
668
+ if (opts.json) {
669
+ cli.log(JSON.stringify(overview, null, 2));
670
+ }
671
+ else {
672
+ cli.log(`\n📐 Panorama Overview\n`);
673
+ cli.log(` Project: ${overview.projectRoot}`);
674
+ cli.log(` Modules: ${overview.moduleCount}`);
675
+ cli.log(` Layers: ${overview.layerCount}`);
676
+ cli.log(` Files: ${overview.totalFiles}`);
677
+ cli.log(` Recipes: ${overview.totalRecipes}`);
678
+ cli.log(` Coverage: ${overview.overallCoverage}%`);
679
+ cli.log(` Cycles: ${overview.cycleCount}`);
680
+ cli.log(` Gaps: ${overview.gapCount}`);
681
+ if (overview.layers && overview.layers.length > 0) {
682
+ cli.log(`\n Layers:`);
683
+ for (const layer of overview.layers) {
684
+ const totalFiles = layer.modules.reduce((sum, m) => sum + m.fileCount, 0);
685
+ cli.log(` ${layer.name}: ${layer.modules.length} modules, ${totalFiles} files`);
686
+ }
687
+ }
688
+ }
689
+ await bootstrap.shutdown();
690
+ }
691
+ catch (err) {
692
+ cli.error(`Error: ${err.message}`);
693
+ cli.debug(err.stack);
694
+ process.exit(1);
695
+ }
696
+ });
697
+ // ─────────────────────────────────────────────────────
607
698
  // server 命令
608
699
  // ─────────────────────────────────────────────────────
609
700
  program
@@ -651,6 +742,17 @@ program
651
742
  httpServer = new HttpServer({ port, host });
652
743
  await httpServer.initialize();
653
744
  await httpServer.start();
745
+ // ── UiStartupTasks: 后台异步刷新(不阻塞 UI) ──
746
+ import('../lib/service/bootstrap/UiStartupTasks.js')
747
+ .then(({ runUiStartupTasks }) => runUiStartupTasks({ projectRoot, container }))
748
+ .then((report) => {
749
+ if (report.errors.length > 0) {
750
+ cli.warn(`⚠️ UiStartupTasks completed with ${report.errors.length} error(s)`);
751
+ }
752
+ })
753
+ .catch((err) => {
754
+ cli.debug(`UiStartupTasks failed: ${err.message}`);
755
+ });
654
756
  // ── MCP 配置检测 ──
655
757
  const cursorMcpPath = join(projectRoot, '.cursor', 'mcp.json');
656
758
  const vscodeMcpPath = join(projectRoot, '.vscode', 'mcp.json');
@@ -777,7 +879,8 @@ program
777
879
  program
778
880
  .command('status')
779
881
  .description('检查环境状态')
780
- .action(async () => {
882
+ .option('--json', 'JSON 格式输出')
883
+ .action(async (opts) => {
781
884
  cli.log('\n AutoSnippet Environment Status');
782
885
  cli.log(` ${'─'.repeat(40)}`);
783
886
  // AI 配置
@@ -810,9 +913,165 @@ program
810
913
  cli.log(` ❌ ${dep} (missing)`);
811
914
  }
812
915
  }
916
+ // 如果数据库存在,加载知识库统计
917
+ if (dbExists) {
918
+ try {
919
+ const projectRoot = resolve('.');
920
+ const { bootstrap, container } = await initContainer({ projectRoot });
921
+ const knowledgeService = container.get('knowledgeService');
922
+ const stats = (await knowledgeService.getStats());
923
+ if (stats) {
924
+ cli.log(' Knowledge:');
925
+ cli.log(` Total: ${stats.total ?? 0} Active: ${stats.active ?? 0} Staging: ${stats.staging ?? 0} Evolving: ${stats.evolving ?? 0} Decaying: ${stats.decaying ?? 0} Pending: ${stats.pending ?? 0} Deprecated: ${stats.deprecated ?? 0}`);
926
+ cli.log(` Rules: ${stats.rules ?? 0} Patterns: ${stats.patterns ?? 0} Facts: ${stats.facts ?? 0}`);
927
+ }
928
+ // Signal Bus 统计
929
+ const signalBus = container.get('signalBus');
930
+ if (signalBus) {
931
+ const bus = signalBus;
932
+ cli.log(' Signals:');
933
+ cli.log(` Emitted: ${bus.emitCount ?? 0} Listeners: ${bus.listenerCount ?? 0}`);
934
+ }
935
+ await bootstrap.shutdown();
936
+ }
937
+ catch {
938
+ // 降级: 无法加载容器时只展示基础状态
939
+ }
940
+ }
941
+ if (opts.json) {
942
+ // 简化 JSON 输出模式
943
+ const result = {
944
+ aiProvider: aiInfo.provider ?? 'ide-agent',
945
+ aiModel: aiInfo.model ?? null,
946
+ database: dbExists,
947
+ workspace: existsSync(asdDir),
948
+ };
949
+ cli.json(result);
950
+ }
813
951
  cli.blank();
814
952
  });
815
953
  // ─────────────────────────────────────────────────────
954
+ // health 命令
955
+ // ─────────────────────────────────────────────────────
956
+ program
957
+ .command('health')
958
+ .description('综合健康报告:系统状态、知识生命周期、Guard 合规、信号统计')
959
+ .option('-d, --dir <path>', '项目目录', '.')
960
+ .option('--json', '以 JSON 格式输出')
961
+ .action(async (opts) => {
962
+ const projectRoot = resolve(opts.dir);
963
+ const { getAiConfigInfo } = await import('../lib/external/ai/AiFactory.js');
964
+ const aiInfo = getAiConfigInfo();
965
+ const aiOk = !!(aiInfo.provider && aiInfo.provider !== 'none');
966
+ const dbPath = join(projectRoot, '.autosnippet', 'autosnippet.db');
967
+ const dbExists = existsSync(dbPath);
968
+ let dbSizeMB = 0;
969
+ let dbEntries = 0;
970
+ let guardRuleCount = 0;
971
+ let knowledgeStats = {};
972
+ let complianceScore = 0;
973
+ let coverageScore = 0;
974
+ let confidencePct = 0;
975
+ let signalEmitted = 0;
976
+ let signalListeners = 0;
977
+ if (dbExists) {
978
+ try {
979
+ const { statSync } = await import('node:fs');
980
+ const stat = statSync(dbPath);
981
+ dbSizeMB = +(stat.size / (1024 * 1024)).toFixed(1);
982
+ }
983
+ catch {
984
+ /* stat 失败不阻塞 */
985
+ }
986
+ try {
987
+ const { bootstrap, container } = await initContainer({ projectRoot });
988
+ try {
989
+ const knowledgeService = container.get('knowledgeService');
990
+ const stats = (await knowledgeService.getStats());
991
+ if (stats) {
992
+ knowledgeStats = stats;
993
+ dbEntries = stats.total ?? 0;
994
+ }
995
+ }
996
+ catch {
997
+ /* knowledge service 不可用 */
998
+ }
999
+ try {
1000
+ const engine = container.get('guardCheckEngine');
1001
+ const rules = engine.getRules();
1002
+ guardRuleCount = rules.length;
1003
+ }
1004
+ catch {
1005
+ /* guard engine 不可用 */
1006
+ }
1007
+ try {
1008
+ const reporter = container.get('complianceReporter');
1009
+ const report = await reporter.generate(projectRoot, {
1010
+ qualityGate: { maxErrors: 0, maxWarnings: 100, minScore: 0 },
1011
+ maxFiles: 200,
1012
+ });
1013
+ complianceScore = report.complianceScore ?? 0;
1014
+ coverageScore = report.coverageScore ?? 0;
1015
+ confidencePct = report.confidenceScore ?? 0;
1016
+ }
1017
+ catch {
1018
+ /* compliance reporter 不可用 */
1019
+ }
1020
+ try {
1021
+ const signalBus = container.get('signalBus');
1022
+ signalEmitted = signalBus.emitCount ?? 0;
1023
+ signalListeners = signalBus.listenerCount ?? 0;
1024
+ }
1025
+ catch {
1026
+ /* signal bus 不可用 */
1027
+ }
1028
+ await bootstrap.shutdown();
1029
+ }
1030
+ catch {
1031
+ /* container init 失败,降级展示基础信息 */
1032
+ }
1033
+ }
1034
+ const healthData = {
1035
+ system: {
1036
+ ai: aiOk,
1037
+ db: dbExists,
1038
+ dbSizeMB,
1039
+ dbEntries,
1040
+ guardRules: guardRuleCount,
1041
+ },
1042
+ knowledge: {
1043
+ active: knowledgeStats.active ?? 0,
1044
+ staging: knowledgeStats.staging ?? 0,
1045
+ evolving: knowledgeStats.evolving ?? 0,
1046
+ decaying: knowledgeStats.decaying ?? 0,
1047
+ },
1048
+ guard: {
1049
+ compliance: complianceScore,
1050
+ coverage: coverageScore,
1051
+ confidence: confidencePct,
1052
+ },
1053
+ signals: {
1054
+ emitted: signalEmitted,
1055
+ listeners: signalListeners,
1056
+ },
1057
+ };
1058
+ if (opts.json) {
1059
+ cli.json(healthData);
1060
+ }
1061
+ else {
1062
+ const dbStatus = dbExists ? `✅(${dbSizeMB}MB, ${dbEntries} entries)` : '❌';
1063
+ const aiIcon = aiOk ? '✅' : '❌';
1064
+ cli.log('');
1065
+ cli.log('AutoSnippet Health Report');
1066
+ cli.log('═════════════════════════');
1067
+ cli.log(`🔧 System: AI:${aiIcon} DB:${dbStatus} Guard:${guardRuleCount} rules`);
1068
+ cli.log(`📊 Knowledge: Active:${healthData.knowledge.active} Staging:${healthData.knowledge.staging} Evolving:${healthData.knowledge.evolving} Decaying:${healthData.knowledge.decaying}`);
1069
+ cli.log(`🛡️ Guard: Compliance:${complianceScore} Coverage:${coverageScore} Confidence:${confidencePct}%`);
1070
+ cli.log(`📡 Signals: emitted:${signalEmitted} listeners:${signalListeners}`);
1071
+ cli.blank();
1072
+ }
1073
+ });
1074
+ // ─────────────────────────────────────────────────────
816
1075
  // embed 命令 — 构建/重建语义向量索引
817
1076
  // ─────────────────────────────────────────────────────
818
1077
  program
@@ -970,150 +1229,18 @@ program
970
1229
  }
971
1230
  });
972
1231
  // ─────────────────────────────────────────────────────
973
- // task 命令 — TaskGraph CLI 管理
1232
+ // task 命令 — Task 系统已迁移到 MCP (零 DB,纯内存 + JSONL)
1233
+ // CLI task 子命令已废弃,通过 MCP autosnippet_task 操作
974
1234
  // ─────────────────────────────────────────────────────
975
1235
  const taskCmd = program
976
1236
  .command('task')
977
- .description('TaskGraph 任务管理(列表 / 就绪 / 上下文恢复 / 统计)');
1237
+ .description('Task 管理(已迁移到 MCP 通过 autosnippet_task 操作)');
978
1238
  taskCmd
979
1239
  .command('list')
980
- .description('列出任务')
981
- .option('-d, --dir <path>', '项目目录', '.')
982
- .option('-s, --status <status>', '按状态过滤(open/in_progress/closed/deferred)')
983
- .option('-l, --limit <n>', '最大条数', '20')
984
- .action(async (opts) => {
985
- const projectRoot = resolve(opts.dir);
986
- const { bootstrap, container } = await initContainer({ projectRoot });
987
- try {
988
- const svc = container.get('taskGraphService');
989
- const filters = {};
990
- if (opts.status) {
991
- filters.status = opts.status;
992
- }
993
- const tasks = await svc.list(filters, { limit: parseInt(opts.limit, 10) });
994
- if (tasks.length === 0) {
995
- cli.log('No tasks found.');
996
- }
997
- else {
998
- cli.log(`\n ID Status Priority Title`);
999
- cli.log(` ${'─'.repeat(70)}`);
1000
- for (const t of tasks) {
1001
- if (!t) {
1002
- continue;
1003
- }
1004
- const j = t.toJSON ? t.toJSON() : t;
1005
- if (!j) {
1006
- continue;
1007
- }
1008
- const id = String(j.id || '').padEnd(16);
1009
- const status = String(j.status || '').padEnd(13);
1010
- const pri = String(j.priority ?? '-').padEnd(9);
1011
- cli.log(` ${id} ${status} ${pri} ${j.title}`);
1012
- }
1013
- cli.log(`\n Total: ${tasks.length}\n`);
1014
- }
1015
- }
1016
- finally {
1017
- await bootstrap.shutdown?.();
1018
- }
1019
- });
1020
- taskCmd
1021
- .command('ready')
1022
- .description('显示就绪任务(带知识上下文)')
1023
- .option('-d, --dir <path>', '项目目录', '.')
1024
- .option('-l, --limit <n>', '最大条数', '5')
1025
- .action(async (opts) => {
1026
- const projectRoot = resolve(opts.dir);
1027
- const { bootstrap, container } = await initContainer({ projectRoot });
1028
- try {
1029
- const svc = container.get('taskGraphService');
1030
- const tasks = await svc.ready({
1031
- limit: parseInt(opts.limit, 10),
1032
- withKnowledge: true,
1033
- });
1034
- if (tasks.length === 0) {
1035
- cli.log('No ready tasks.');
1036
- }
1037
- else {
1038
- for (const t of tasks) {
1039
- if (!t) {
1040
- continue;
1041
- }
1042
- const j = t.toJSON ? t.toJSON() : t;
1043
- if (!j) {
1044
- continue;
1045
- }
1046
- cli.log(`\n ▸ ${j.id} — ${j.title} (P${j.priority ?? '?'})`);
1047
- const kCtx = t.knowledgeContext;
1048
- if (kCtx?.relatedKnowledge?.length) {
1049
- cli.log(` Knowledge: ${kCtx.relatedKnowledge.map((k) => k.title).join(', ')}`);
1050
- }
1051
- if (kCtx?.guardRules?.length) {
1052
- cli.log(` Guard: ${kCtx.guardRules.map((r) => r.title).join(', ')}`);
1053
- }
1054
- }
1055
- cli.blank();
1056
- }
1057
- }
1058
- finally {
1059
- await bootstrap.shutdown?.();
1060
- }
1061
- });
1062
- taskCmd
1063
- .command('prime')
1064
- .description('恢复 TaskGraph 会话上下文(等同 MCP prime 操作)')
1065
- .option('-d, --dir <path>', '项目目录', '.')
1066
- .action(async (opts) => {
1067
- const projectRoot = resolve(opts.dir);
1068
- const { bootstrap, container } = await initContainer({ projectRoot });
1069
- try {
1070
- const svc = container.get('taskGraphService');
1071
- const result = await svc.prime({ withKnowledge: true });
1072
- const inProgress = result.inProgress;
1073
- const ready = result.ready;
1074
- cli.log(`\n TaskGraph Prime`);
1075
- cli.log(` ${'─'.repeat(40)}`);
1076
- cli.log(` In Progress: ${inProgress.length}`);
1077
- cli.log(` Ready: ${ready.length}`);
1078
- cli.log(` Stats: ${JSON.stringify(result.stats)}`);
1079
- if (inProgress.length > 0) {
1080
- cli.log(`\n ▸ In Progress:`);
1081
- for (const t of inProgress) {
1082
- cli.log(` ${t.id} — ${t.title}`);
1083
- }
1084
- }
1085
- if (ready.length > 0) {
1086
- cli.log(`\n ▸ Ready:`);
1087
- for (const t of ready) {
1088
- cli.log(` ${t.id} — ${t.title}`);
1089
- }
1090
- }
1091
- cli.blank();
1092
- }
1093
- finally {
1094
- await bootstrap.shutdown?.();
1095
- }
1096
- });
1097
- taskCmd
1098
- .command('stats')
1099
- .description('TaskGraph 统计信息')
1100
- .option('-d, --dir <path>', '项目目录', '.')
1101
- .action(async (opts) => {
1102
- const projectRoot = resolve(opts.dir);
1103
- const { bootstrap, container } = await initContainer({ projectRoot });
1104
- try {
1105
- const svc = container.get('taskGraphService');
1106
- const stats = await svc.stats();
1107
- cli.log(`\n TaskGraph Statistics`);
1108
- cli.log(` ${'─'.repeat(30)}`);
1109
- for (const [key, val] of Object.entries(stats)) {
1110
- cli.log(` ${key.padEnd(15)} ${val}`);
1111
- }
1112
- cli.blank();
1113
- }
1114
- finally {
1115
- await bootstrap.shutdown?.();
1116
- }
1240
+ .description('[已废弃] Task 系统不再使用数据库。通过 MCP prime 操作获取上下文。')
1241
+ .action(() => {
1242
+ cli.log('\n ⚠️ Task 系统已迁移到 MCP(零 DB,纯内存 + JSONL)。');
1243
+ cli.log(' 使用 autosnippet_task({ operation: "prime" }) 加载上下文。\n');
1117
1244
  });
1118
1245
  // ─────────────────────────────────────────────────────
1119
1246
  // mirror 命令
@@ -1221,7 +1348,7 @@ program
1221
1348
  process.exit(1);
1222
1349
  }
1223
1350
  try {
1224
- const report = syncService.sync(db, {
1351
+ const report = await syncService.syncAll(db, {
1225
1352
  dryRun: opts.dryRun,
1226
1353
  force: opts.force,
1227
1354
  });
@@ -1231,6 +1358,21 @@ program
1231
1358
  cli.log(` Updated: ${report.updated ?? 0}`);
1232
1359
  cli.log(` Unchanged: ${report.unchanged ?? 0}`);
1233
1360
  cli.log(` Deleted: ${report.deleted ?? 0}`);
1361
+ if (report.reconcileReport) {
1362
+ cli.log(`\n 📍 Source Refs`);
1363
+ cli.log(` ${'─'.repeat(40)}`);
1364
+ cli.log(` Inserted: ${report.reconcileReport.inserted ?? 0}`);
1365
+ cli.log(` Active: ${report.reconcileReport.active ?? 0}`);
1366
+ cli.log(` Stale: ${report.reconcileReport.stale ?? 0}`);
1367
+ cli.log(` Skipped: ${report.reconcileReport.skipped ?? 0}`);
1368
+ }
1369
+ if (report.repairReport &&
1370
+ (report.repairReport.renamed > 0 || report.repairReport.stillStale > 0)) {
1371
+ cli.log(`\n 🔧 Rename Repairs`);
1372
+ cli.log(` ${'─'.repeat(40)}`);
1373
+ cli.log(` Renamed: ${report.repairReport.renamed ?? 0}`);
1374
+ cli.log(` Still Stale: ${report.repairReport.stillStale ?? 0}`);
1375
+ }
1234
1376
  if (report.violations.length > 0) {
1235
1377
  cli.log(`\n ⚠️ Violations (${report.violations.length}):`);
1236
1378
  for (const v of report.violations) {
@@ -21,6 +21,7 @@
21
21
  *
22
22
  * @module ExplorationTracker
23
23
  */
24
+ import type { SignalBus } from '#infra/signal/SignalBus.js';
24
25
  import type { ExplorationBudget, ExplorationStrategy, ExplorationTrace, PipelineType } from './exploration/ExplorationStrategies.js';
25
26
  /** resolve() 选项 */
26
27
  interface ResolveOptions {
@@ -34,6 +35,7 @@ interface ResolveOptions {
34
35
  interface BudgetInput extends Partial<ExplorationBudget> {
35
36
  submitToolName?: string;
36
37
  pipelineType?: PipelineType;
38
+ signalBus?: SignalBus | null;
37
39
  }
38
40
  export declare class ExplorationTracker {
39
41
  #private;
@@ -36,6 +36,8 @@ export class ExplorationTracker {
36
36
  #phase;
37
37
  /** 日志器 */
38
38
  #logger;
39
+ /** 信号总线(可选) */
40
+ #signalBus;
39
41
  // ── 子模块 ──
40
42
  #signalDetector;
41
43
  #nudgeGenerator;
@@ -88,6 +90,7 @@ export class ExplorationTracker {
88
90
  budget.pipelineType || (strategy.name === 'analyst' ? 'analyst' : 'bootstrap');
89
91
  this.#phase = strategy.phases[0];
90
92
  this.#logger = Logger.getInstance();
93
+ this.#signalBus = budget.signalBus ?? null;
91
94
  // 初始化子模块
92
95
  this.#signalDetector = new SignalDetector(this.#metrics);
93
96
  this.#nudgeGenerator = new NudgeGenerator();
@@ -147,17 +150,17 @@ export class ExplorationTracker {
147
150
  shouldExit() {
148
151
  // Scan 管线: SUMMARIZE 无消费方,直接退出
149
152
  if (this.#isTerminalPhase() && this.#pipelineType === 'scan') {
153
+ this.#emitExitSignal('scan_terminal');
150
154
  return true;
151
155
  }
152
156
  // 终结阶段 + 已给了 3 轮 grace → 退出
153
- // 注意: phaseRounds 在 tick() 中递增 (进入终结阶段后从 1 开始计数)
154
- // 3 轮 grace 允许: round 1 (首次尝试) + round 2 (空响应重试) + 安全余量
155
- // 与 AgentRuntime#callLLM 的空响应 grace 机制对齐 (grace < 2 → 在 round 1 重试)
156
157
  if (this.#isTerminalPhase() && this.#metrics.phaseRounds >= 3) {
158
+ this.#emitExitSignal('grace_exhausted');
157
159
  return true;
158
160
  }
159
161
  // 硬上限兜底
160
162
  if (this.#metrics.iteration >= this.#budget.maxIterations + 2) {
163
+ this.#emitExitSignal('hard_limit');
161
164
  return true;
162
165
  }
163
166
  // 达到 maxIterations 但未在终结阶段 → 强制转入终结阶段
@@ -170,6 +173,13 @@ export class ExplorationTracker {
170
173
  }
171
174
  return false;
172
175
  }
176
+ #emitExitSignal(reason) {
177
+ if (this.#signalBus) {
178
+ this.#signalBus.send('exploration', 'ExplorationTracker.exit', 0, {
179
+ metadata: { totalIterations: this.#metrics.iteration, reason },
180
+ });
181
+ }
182
+ }
173
183
  /**
174
184
  * 获取本轮的 Nudge(每轮最多一条)
175
185
  * @param trace 推理链
@@ -438,6 +448,14 @@ export class ExplorationTracker {
438
448
  this.#metrics.roundsSinceSubmit = 0;
439
449
  this.#justTransitioned = true;
440
450
  this.#logger.info(`[ExplorationTracker] ${oldPhase} → ${newPhase} (iter=${this.#metrics.iteration}, submits=${this.#metrics.submitCount})`);
451
+ // Phase 3: 发射阶段转换信号
452
+ if (this.#signalBus) {
453
+ const terminalPhase = this.#getTerminalPhase();
454
+ const value = newPhase === terminalPhase ? 1.0 : 0.5;
455
+ this.#signalBus.send('exploration', 'ExplorationTracker.phase', value, {
456
+ metadata: { from: oldPhase, to: newPhase, iteration: this.#metrics.iteration },
457
+ });
458
+ }
441
459
  }
442
460
  #isTerminalPhase() {
443
461
  return this.#phase === this.#getTerminalPhase();
@@ -78,7 +78,9 @@ export declare class ToolExecutionPipeline {
78
78
  * 从 LoopContext.toolSchemas 中提取允许的工具名列表,
79
79
  * 拒绝不在列表中的调用(返回 error 提示)。
80
80
  *
81
- * before: 如果工具不在白名单中则短路返回 error
81
+ * Forge 集成:不在白名单的工具如果已由 ToolForge 锻造(存在于 ToolRegistry),则放行。
82
+ *
83
+ * before: 如果工具不在白名单中且非锻造工具则短路返回 error
82
84
  */
83
85
  export declare const allowlistGate: {
84
86
  name: string;
@@ -106,7 +106,9 @@ export class ToolExecutionPipeline {
106
106
  * 从 LoopContext.toolSchemas 中提取允许的工具名列表,
107
107
  * 拒绝不在列表中的调用(返回 error 提示)。
108
108
  *
109
- * before: 如果工具不在白名单中则短路返回 error
109
+ * Forge 集成:不在白名单的工具如果已由 ToolForge 锻造(存在于 ToolRegistry),则放行。
110
+ *
111
+ * before: 如果工具不在白名单中且非锻造工具则短路返回 error
110
112
  */
111
113
  export const allowlistGate = {
112
114
  name: 'allowlistGate',
@@ -118,6 +120,11 @@ export const allowlistGate = {
118
120
  }
119
121
  const allowedNames = new Set(schemas.map((s) => s.name || s.function?.name));
120
122
  if (!allowedNames.has(call.name)) {
123
+ // Forge fallback: 不在白名单但已注册到 ToolRegistry(如锻造的临时工具)则放行
124
+ if (ctx.runtime.toolRegistry?.has(call.name)) {
125
+ ctx.runtime.logger.info(`[ToolPipeline] Tool "${call.name}" not in allowlist but exists in registry (forged?) — allowed`);
126
+ return undefined;
127
+ }
121
128
  ctx.runtime.logger.warn(`[ToolPipeline] ⛔ Tool "${call.name}" not in allowlist — blocked (hallucinated call)`);
122
129
  return {
123
130
  blocked: true,
@@ -0,0 +1,58 @@
1
+ /**
2
+ * DynamicComposer — 运行时动态工具组合
3
+ *
4
+ * 将已有的原子工具按 sequential / parallel / conditional 策略组合成复合工具。
5
+ * 组合结果注册为临时工具(通过 TemporaryToolRegistry)。
6
+ *
7
+ * 与 PipelineStrategy 的区别:
8
+ * - PipelineStrategy 是 Agent 执行策略(Agent 层)
9
+ * - DynamicComposer 是工具组合(Tool 层),产出物是单个工具
10
+ */
11
+ interface ToolRegistryLike {
12
+ has(name: string): boolean;
13
+ execute(name: string, params: Record<string, unknown>, context?: Record<string, unknown>): Promise<unknown>;
14
+ }
15
+ export interface CompositionStep {
16
+ /** 要调用的工具名 */
17
+ tool: string;
18
+ /** 静态参数或从前一步结果构造参数的函数 */
19
+ args: Record<string, unknown> | ((prevResult: unknown) => Record<string, unknown>);
20
+ /** 可选:提取该步结果中的特定字段传给下一步 */
21
+ extractKey?: string;
22
+ }
23
+ export interface CompositionSpec {
24
+ /** 组合工具的名称 */
25
+ name: string;
26
+ /** 描述 */
27
+ description: string;
28
+ /** 执行步骤 */
29
+ steps: CompositionStep[];
30
+ /** 合并策略 */
31
+ mergeStrategy: 'sequential' | 'parallel';
32
+ /** JSON Schema 参数定义 */
33
+ parameters?: Record<string, unknown>;
34
+ }
35
+ export interface CompositionResult {
36
+ /** 是否成功 */
37
+ success: boolean;
38
+ /** 组合工具 handler */
39
+ handler?: (params: Record<string, unknown>, context: Record<string, unknown>) => Promise<unknown>;
40
+ /** 失败原因 */
41
+ error?: string;
42
+ }
43
+ export declare class DynamicComposer {
44
+ #private;
45
+ constructor(registry: ToolRegistryLike);
46
+ /**
47
+ * 验证组合 spec 的可行性(所有工具是否存在)
48
+ */
49
+ validate(spec: CompositionSpec): {
50
+ valid: boolean;
51
+ missingTools: string[];
52
+ };
53
+ /**
54
+ * 构建组合工具
55
+ */
56
+ compose(spec: CompositionSpec): CompositionResult;
57
+ }
58
+ export {};