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.
- package/dashboard/dist/assets/icons-BJ2mUBi8.js +1 -0
- package/dashboard/dist/assets/index-B659K9t5.js +128 -0
- package/dashboard/dist/assets/index-NCm40PMD.css +1 -0
- package/dashboard/dist/index.html +3 -3
- package/dist/bin/cli.d.ts +1 -0
- package/dist/bin/cli.js +284 -142
- package/dist/lib/agent/context/ExplorationTracker.d.ts +2 -0
- package/dist/lib/agent/context/ExplorationTracker.js +21 -3
- package/dist/lib/agent/core/ToolExecutionPipeline.d.ts +3 -1
- package/dist/lib/agent/core/ToolExecutionPipeline.js +8 -1
- package/dist/lib/agent/forge/DynamicComposer.d.ts +58 -0
- package/dist/lib/agent/forge/DynamicComposer.js +99 -0
- package/dist/lib/agent/forge/SandboxRunner.d.ts +60 -0
- package/dist/lib/agent/forge/SandboxRunner.js +251 -0
- package/dist/lib/agent/forge/TemporaryToolRegistry.d.ts +76 -0
- package/dist/lib/agent/forge/TemporaryToolRegistry.js +154 -0
- package/dist/lib/agent/forge/ToolForge.d.ts +92 -0
- package/dist/lib/agent/forge/ToolForge.js +239 -0
- package/dist/lib/agent/forge/ToolRequirementAnalyzer.d.ts +44 -0
- package/dist/lib/agent/forge/ToolRequirementAnalyzer.js +119 -0
- package/dist/lib/agent/tools/ToolRegistry.d.ts +2 -0
- package/dist/lib/agent/tools/ToolRegistry.js +4 -0
- package/dist/lib/agent/tools/composite.js +0 -1
- package/dist/lib/agent/tools/index.d.ts +2 -50
- package/dist/lib/agent/tools/index.js +2 -3
- package/dist/lib/agent/tools/lifecycle.d.ts +1 -58
- package/dist/lib/agent/tools/lifecycle.js +2 -75
- package/dist/lib/cli/KnowledgeSyncService.d.ts +26 -0
- package/dist/lib/cli/KnowledgeSyncService.js +33 -1
- package/dist/lib/cli/deploy/FileManifest.d.ts +0 -21
- package/dist/lib/cli/deploy/FileManifest.js +0 -11
- package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +10 -0
- package/dist/lib/domain/knowledge/KnowledgeEntry.js +2 -0
- package/dist/lib/domain/knowledge/Lifecycle.d.ts +19 -2
- package/dist/lib/domain/knowledge/Lifecycle.js +32 -6
- package/dist/lib/domain/knowledge/UnifiedValidator.d.ts +1 -5
- package/dist/lib/domain/knowledge/UnifiedValidator.js +7 -44
- package/dist/lib/domain/knowledge/values/Stats.d.ts +29 -0
- package/dist/lib/domain/knowledge/values/Stats.js +41 -0
- package/dist/lib/external/mcp/McpServer.d.ts +19 -38
- package/dist/lib/external/mcp/McpServer.js +145 -117
- package/dist/lib/external/mcp/autoApproveInjector.js +0 -2
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.d.ts +26 -1
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +41 -0
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +49 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +3 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +27 -0
- package/dist/lib/external/mcp/handlers/bootstrap/skills.js +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -0
- package/dist/lib/external/mcp/handlers/bootstrap-internal.js +2 -0
- package/dist/lib/external/mcp/handlers/browse.d.ts +1 -0
- package/dist/lib/external/mcp/handlers/browse.js +2 -1
- package/dist/lib/external/mcp/handlers/consolidated.d.ts +117 -6
- package/dist/lib/external/mcp/handlers/consolidated.js +251 -71
- package/dist/lib/external/mcp/handlers/guard.d.ts +150 -0
- package/dist/lib/external/mcp/handlers/guard.js +239 -5
- package/dist/lib/external/mcp/handlers/knowledge.d.ts +0 -29
- package/dist/lib/external/mcp/handlers/knowledge.js +1 -76
- package/dist/lib/external/mcp/handlers/panorama.d.ts +36 -0
- package/dist/lib/external/mcp/handlers/panorama.js +156 -0
- package/dist/lib/external/mcp/handlers/system.d.ts +2 -54
- package/dist/lib/external/mcp/handlers/system.js +3 -113
- package/dist/lib/external/mcp/handlers/task.d.ts +13 -24
- package/dist/lib/external/mcp/handlers/task.js +218 -557
- package/dist/lib/external/mcp/handlers/types.d.ts +91 -8
- package/dist/lib/external/mcp/handlers/types.js +18 -1
- package/dist/lib/external/mcp/handlers/wiki-external.d.ts +18 -1
- package/dist/lib/external/mcp/handlers/wiki-external.js +16 -1
- package/dist/lib/external/mcp/tools.d.ts +18 -24
- package/dist/lib/external/mcp/tools.js +132 -159
- package/dist/lib/http/HttpServer.js +52 -0
- package/dist/lib/http/middleware/validate.js +7 -3
- package/dist/lib/http/routes/audit.d.ts +8 -0
- package/dist/lib/http/routes/audit.js +51 -0
- package/dist/lib/http/routes/guardReport.d.ts +10 -0
- package/dist/lib/http/routes/guardReport.js +143 -0
- package/dist/lib/http/routes/knowledge.js +32 -1
- package/dist/lib/http/routes/panorama.d.ts +11 -0
- package/dist/lib/http/routes/panorama.js +322 -0
- package/dist/lib/http/routes/signals.d.ts +10 -0
- package/dist/lib/http/routes/signals.js +104 -0
- package/dist/lib/http/routes/task.d.ts +2 -3
- package/dist/lib/http/routes/task.js +17 -347
- package/dist/lib/http/routes/violations.js +1 -1
- package/dist/lib/infrastructure/audit/AuditLogger.d.ts +6 -1
- package/dist/lib/infrastructure/audit/AuditLogger.js +14 -1
- package/dist/lib/infrastructure/database/drizzle/schema.d.ts +202 -504
- package/dist/lib/infrastructure/database/drizzle/schema.js +38 -69
- package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.d.ts +8 -0
- package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.js +43 -0
- package/dist/lib/infrastructure/database/migrations/005_recipe_source_refs.d.ts +9 -0
- package/dist/lib/infrastructure/database/migrations/005_recipe_source_refs.js +24 -0
- package/dist/lib/infrastructure/logging/Logger.d.ts +2 -0
- package/dist/lib/infrastructure/logging/Logger.js +34 -7
- package/dist/lib/infrastructure/monitoring/ErrorTracker.js +3 -1
- package/dist/lib/infrastructure/monitoring/PerformanceMonitor.d.ts +2 -2
- package/dist/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -10
- package/dist/lib/infrastructure/notification/LarkNotifier.d.ts +24 -0
- package/dist/lib/infrastructure/notification/LarkNotifier.js +97 -0
- package/dist/lib/infrastructure/report/ReportStore.d.ts +45 -0
- package/dist/lib/infrastructure/report/ReportStore.js +133 -0
- package/dist/lib/infrastructure/signal/SignalAggregator.d.ts +18 -0
- package/dist/lib/infrastructure/signal/SignalAggregator.js +84 -0
- package/dist/lib/infrastructure/signal/SignalBridge.d.ts +13 -0
- package/dist/lib/infrastructure/signal/SignalBridge.js +20 -0
- package/dist/lib/infrastructure/signal/SignalBus.d.ts +63 -0
- package/dist/lib/infrastructure/signal/SignalBus.js +106 -0
- package/dist/lib/infrastructure/signal/SignalTraceWriter.d.ts +36 -0
- package/dist/lib/infrastructure/signal/SignalTraceWriter.js +130 -0
- package/dist/lib/infrastructure/vector/HnswVectorAdapter.js +18 -2
- package/dist/lib/injection/ServiceContainer.js +8 -0
- package/dist/lib/injection/ServiceMap.d.ts +16 -10
- package/dist/lib/injection/modules/AgentModule.d.ts +1 -1
- package/dist/lib/injection/modules/AgentModule.js +7 -1
- package/dist/lib/injection/modules/AppModule.d.ts +1 -1
- package/dist/lib/injection/modules/AppModule.js +4 -13
- package/dist/lib/injection/modules/GuardModule.js +27 -2
- package/dist/lib/injection/modules/InfraModule.d.ts +0 -1
- package/dist/lib/injection/modules/InfraModule.js +9 -7
- package/dist/lib/injection/modules/KnowledgeModule.d.ts +5 -0
- package/dist/lib/injection/modules/KnowledgeModule.js +131 -0
- package/dist/lib/injection/modules/PanoramaModule.d.ts +18 -0
- package/dist/lib/injection/modules/PanoramaModule.js +76 -0
- package/dist/lib/injection/modules/SignalModule.d.ts +10 -0
- package/dist/lib/injection/modules/SignalModule.js +84 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +1 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +6 -0
- package/dist/lib/service/bootstrap/BootstrapTaskManager.d.ts +3 -1
- package/dist/lib/service/bootstrap/BootstrapTaskManager.js +20 -1
- package/dist/lib/service/bootstrap/UiStartupTasks.d.ts +45 -0
- package/dist/lib/service/bootstrap/UiStartupTasks.js +101 -0
- package/dist/lib/service/delivery/AgentInstructionsGenerator.js +4 -5
- package/dist/lib/service/delivery/CursorDeliveryPipeline.d.ts +3 -1
- package/dist/lib/service/delivery/CursorDeliveryPipeline.js +13 -10
- package/dist/lib/service/delivery/RulesGenerator.js +3 -2
- package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +114 -0
- package/dist/lib/service/evolution/ConsolidationAdvisor.js +542 -0
- package/dist/lib/service/evolution/ContradictionDetector.d.ts +54 -0
- package/dist/lib/service/evolution/ContradictionDetector.js +253 -0
- package/dist/lib/service/evolution/DecayDetector.d.ts +71 -0
- package/dist/lib/service/evolution/DecayDetector.js +244 -0
- package/dist/lib/service/evolution/EnhancementSuggester.d.ts +38 -0
- package/dist/lib/service/evolution/EnhancementSuggester.js +220 -0
- package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +82 -0
- package/dist/lib/service/evolution/KnowledgeMetabolism.js +167 -0
- package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +53 -0
- package/dist/lib/service/evolution/RedundancyAnalyzer.js +210 -0
- package/dist/lib/service/evolution/StagingManager.d.ts +57 -0
- package/dist/lib/service/evolution/StagingManager.js +201 -0
- package/dist/lib/service/guard/ComplianceReporter.d.ts +42 -2
- package/dist/lib/service/guard/ComplianceReporter.js +43 -5
- package/dist/lib/service/guard/CoverageAnalyzer.d.ts +54 -0
- package/dist/lib/service/guard/CoverageAnalyzer.js +149 -0
- package/dist/lib/service/guard/GuardCheckEngine.d.ts +42 -0
- package/dist/lib/service/guard/GuardCheckEngine.js +465 -14
- package/dist/lib/service/guard/GuardFeedbackLoop.d.ts +3 -0
- package/dist/lib/service/guard/GuardFeedbackLoop.js +9 -0
- package/dist/lib/service/guard/ReverseGuard.d.ts +73 -0
- package/dist/lib/service/guard/ReverseGuard.js +256 -0
- package/dist/lib/service/guard/RuleLearner.d.ts +12 -0
- package/dist/lib/service/guard/RuleLearner.js +38 -0
- package/dist/lib/service/guard/UncertaintyCollector.d.ts +83 -0
- package/dist/lib/service/guard/UncertaintyCollector.js +149 -0
- package/dist/lib/service/guard/ViolationsStore.d.ts +1 -0
- package/dist/lib/service/guard/ViolationsStore.js +33 -3
- package/dist/lib/service/knowledge/ConfidenceRouter.d.ts +13 -0
- package/dist/lib/service/knowledge/ConfidenceRouter.js +14 -0
- package/dist/lib/service/knowledge/KnowledgeService.js +22 -4
- package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +68 -0
- package/dist/lib/service/knowledge/SourceRefReconciler.js +309 -0
- package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +27 -0
- package/dist/lib/service/panorama/CouplingAnalyzer.js +192 -0
- package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +28 -0
- package/dist/lib/service/panorama/DimensionAnalyzer.js +320 -0
- package/dist/lib/service/panorama/LayerInferrer.d.ts +19 -0
- package/dist/lib/service/panorama/LayerInferrer.js +182 -0
- package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +24 -0
- package/dist/lib/service/panorama/ModuleDiscoverer.js +185 -0
- package/dist/lib/service/panorama/PanoramaAggregator.d.ts +29 -0
- package/dist/lib/service/panorama/PanoramaAggregator.js +228 -0
- package/dist/lib/service/panorama/PanoramaScanner.d.ts +52 -0
- package/dist/lib/service/panorama/PanoramaScanner.js +188 -0
- package/dist/lib/service/panorama/PanoramaService.d.ts +125 -0
- package/dist/lib/service/panorama/PanoramaService.js +363 -0
- package/dist/lib/service/panorama/PanoramaTypes.d.ts +134 -0
- package/dist/lib/service/panorama/PanoramaTypes.js +6 -0
- package/dist/lib/service/panorama/RoleRefiner.d.ts +48 -0
- package/dist/lib/service/panorama/RoleRefiner.js +535 -0
- package/dist/lib/service/search/BM25Scorer.d.ts +2 -2
- package/dist/lib/service/search/CoarseRanker.d.ts +7 -6
- package/dist/lib/service/search/CoarseRanker.js +11 -10
- package/dist/lib/service/search/FieldWeightedScorer.d.ts +81 -0
- package/dist/lib/service/search/FieldWeightedScorer.js +318 -0
- package/dist/lib/service/search/MultiSignalRanker.d.ts +3 -2
- package/dist/lib/service/search/MultiSignalRanker.js +17 -1
- package/dist/lib/service/search/SearchEngine.d.ts +9 -7
- package/dist/lib/service/search/SearchEngine.js +67 -10
- package/dist/lib/service/search/SearchTypes.d.ts +25 -3
- package/dist/lib/service/search/SearchTypes.js +6 -1
- package/dist/lib/service/signal/HitRecorder.d.ts +68 -0
- package/dist/lib/service/signal/HitRecorder.js +173 -0
- package/dist/lib/service/skills/SignalCollector.d.ts +3 -1
- package/dist/lib/service/skills/SignalCollector.js +31 -1
- package/dist/lib/service/task/IntentExtractor.d.ts +66 -0
- package/dist/lib/service/task/IntentExtractor.js +256 -0
- package/dist/lib/service/task/PrimeSearchPipeline.d.ts +54 -0
- package/dist/lib/service/task/PrimeSearchPipeline.js +113 -0
- package/dist/lib/service/vector/VectorService.d.ts +3 -0
- package/dist/lib/service/vector/VectorService.js +38 -4
- package/dist/lib/shared/schemas/mcp-tools.d.ts +41 -96
- package/dist/lib/shared/schemas/mcp-tools.js +59 -119
- package/dist/scripts/analyze-signals.d.ts +20 -0
- package/dist/scripts/analyze-signals.js +155 -0
- package/dist/scripts/diagnose-mcp.js +1 -1
- package/package.json +1 -1
- package/skills/autosnippet-create/SKILL.md +98 -89
- package/skills/autosnippet-devdocs/SKILL.md +55 -57
- package/templates/claude-code/hooks/autosnippet-session.sh +10 -15
- package/templates/cursor-hooks/hooks/session-start.sh +1 -1
- package/templates/guard-ci.yml +2 -2
- package/templates/instructions/agent-static.md +2 -1
- package/templates/instructions/conventions.md +5 -6
- package/templates/recipes-setup/README.md +1 -2
- package/templates/recipes-setup/_template.md +39 -39
- package/dashboard/dist/assets/icons-BofcEZ3f.js +0 -1
- package/dashboard/dist/assets/index-D0whuycy.css +0 -1
- package/dashboard/dist/assets/index-SiN1GChm.js +0 -128
- package/dist/lib/domain/task/Task.d.ts +0 -140
- package/dist/lib/domain/task/Task.js +0 -254
- package/dist/lib/domain/task/TaskDependency.d.ts +0 -23
- package/dist/lib/domain/task/TaskDependency.js +0 -34
- package/dist/lib/domain/task/TaskIdGenerator.d.ts +0 -40
- package/dist/lib/domain/task/TaskIdGenerator.js +0 -75
- package/dist/lib/domain/task/index.d.ts +0 -4
- package/dist/lib/domain/task/index.js +0 -4
- package/dist/lib/infrastructure/database/migrations/002_add_tasks.d.ts +0 -11
- package/dist/lib/infrastructure/database/migrations/002_add_tasks.js +0 -86
- package/dist/lib/repository/task/TaskRepository.impl.d.ts +0 -171
- package/dist/lib/repository/task/TaskRepository.impl.js +0 -347
- package/dist/lib/service/task/TaskGraphService.d.ts +0 -222
- package/dist/lib/service/task/TaskGraphService.js +0 -597
- package/dist/lib/service/task/TaskKnowledgeBridge.d.ts +0 -95
- package/dist/lib/service/task/TaskKnowledgeBridge.js +0 -298
- package/dist/lib/service/task/TaskReadyEngine.d.ts +0 -84
- 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
|
-
.
|
|
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 命令 —
|
|
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('
|
|
1237
|
+
.description('Task 管理(已迁移到 MCP — 通过 autosnippet_task 操作)');
|
|
978
1238
|
taskCmd
|
|
979
1239
|
.command('list')
|
|
980
|
-
.description('
|
|
981
|
-
.
|
|
982
|
-
.
|
|
983
|
-
.
|
|
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.
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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 {};
|