autosnippet 3.2.21 → 3.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 -1
- package/dist/bin/cli.js +244 -261
- 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/SetupService.d.ts +46 -2
- package/dist/lib/cli/SetupService.js +2 -27
- package/dist/lib/cli/deploy/FileManifest.d.ts +0 -21
- package/dist/lib/cli/deploy/FileManifest.js +0 -11
- package/dist/lib/{platform/ios/spm → core/discovery}/SpmDiscoverer.d.ts +2 -5
- package/dist/lib/{platform/ios/spm → core/discovery}/SpmDiscoverer.js +159 -44
- package/dist/lib/core/discovery/index.d.ts +1 -1
- package/dist/lib/core/discovery/index.js +2 -2
- 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/consolidated.d.ts +116 -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 +245 -8
- 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 +217 -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 +14 -20
- package/dist/lib/external/mcp/tools.js +62 -91
- package/dist/lib/http/HttpServer.js +52 -6
- package/dist/lib/http/routes/{snippets.d.ts → audit.d.ts} +4 -2
- package/dist/lib/http/routes/audit.js +51 -0
- package/dist/lib/http/routes/commands.d.ts +1 -1
- package/dist/lib/http/routes/commands.js +1 -66
- 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/remote.js +0 -5
- 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 +181 -583
- package/dist/lib/infrastructure/database/drizzle/schema.js +28 -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/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/injection/ServiceContainer.js +6 -0
- package/dist/lib/injection/ServiceMap.d.ts +16 -19
- 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 +3 -4
- package/dist/lib/injection/modules/AppModule.js +7 -43
- package/dist/lib/injection/modules/GuardModule.js +59 -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.js +51 -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/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 +55 -1
- package/dist/lib/service/guard/GuardCheckEngine.js +508 -15
- 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/module/ModuleService.js +3 -13
- 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 +108 -0
- package/dist/lib/service/panorama/PanoramaService.js +220 -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/MultiSignalRanker.d.ts +1 -0
- package/dist/lib/service/search/MultiSignalRanker.js +16 -0
- package/dist/lib/service/search/SearchEngine.d.ts +1 -0
- package/dist/lib/service/search/SearchEngine.js +9 -1
- package/dist/lib/service/search/SearchTypes.d.ts +2 -0
- 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 +58 -0
- package/dist/lib/service/task/IntentExtractor.js +142 -0
- package/dist/lib/service/task/PrimeSearchPipeline.d.ts +54 -0
- package/dist/lib/service/task/PrimeSearchPipeline.js +98 -0
- package/dist/lib/shared/constants.d.ts +0 -15
- package/dist/lib/shared/constants.js +0 -10
- package/dist/lib/shared/schemas/config.d.ts +4 -1
- package/dist/lib/shared/schemas/config.js +8 -1
- 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/dist/scripts/release.js +2 -10
- package/package.json +4 -19
- package/skills/autosnippet-devdocs/SKILL.md +11 -8
- package/templates/claude-code/hooks/autosnippet-session.sh +10 -15
- package/templates/cursor-hooks/hooks/session-start.sh +1 -1
- package/templates/instructions/agent-static.md +2 -1
- package/templates/instructions/conventions.md +5 -6
- package/templates/recipes-setup/README.md +1 -2
- package/dashboard/dist/assets/icons-C1dUryS-.js +0 -1
- package/dashboard/dist/assets/index-D0whuycy.css +0 -1
- package/dashboard/dist/assets/index-DdvZE4Yd.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/http/routes/snippets.js +0 -49
- 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/platform/ClipboardManager.d.ts +0 -24
- package/dist/lib/platform/ClipboardManager.js +0 -142
- package/dist/lib/platform/NativeUi.d.ts +0 -53
- package/dist/lib/platform/NativeUi.js +0 -284
- package/dist/lib/platform/ios/index.d.ts +0 -38
- package/dist/lib/platform/ios/index.js +0 -42
- package/dist/lib/platform/ios/routes/spm.d.ts +0 -9
- package/dist/lib/platform/ios/routes/spm.js +0 -371
- package/dist/lib/platform/ios/snippet/PlaceholderConverter.d.ts +0 -21
- package/dist/lib/platform/ios/snippet/PlaceholderConverter.js +0 -48
- package/dist/lib/platform/ios/snippet/XcodeCodec.d.ts +0 -23
- package/dist/lib/platform/ios/snippet/XcodeCodec.js +0 -96
- package/dist/lib/platform/ios/spm/DependencyGraph.d.ts +0 -56
- package/dist/lib/platform/ios/spm/DependencyGraph.js +0 -195
- package/dist/lib/platform/ios/spm/PackageSwiftParser.d.ts +0 -69
- package/dist/lib/platform/ios/spm/PackageSwiftParser.js +0 -231
- package/dist/lib/platform/ios/spm/PathFinder.d.ts +0 -28
- package/dist/lib/platform/ios/spm/PathFinder.js +0 -117
- package/dist/lib/platform/ios/spm/PolicyEngine.d.ts +0 -44
- package/dist/lib/platform/ios/spm/PolicyEngine.js +0 -79
- package/dist/lib/platform/ios/spm/SpmHelper.d.ts +0 -102
- package/dist/lib/platform/ios/spm/SpmHelper.js +0 -464
- package/dist/lib/platform/ios/xcode/HeaderResolver.d.ts +0 -33
- package/dist/lib/platform/ios/xcode/HeaderResolver.js +0 -90
- package/dist/lib/platform/ios/xcode/SaveEventFilter.d.ts +0 -66
- package/dist/lib/platform/ios/xcode/SaveEventFilter.js +0 -142
- package/dist/lib/platform/ios/xcode/XcodeAutomation.d.ts +0 -71
- package/dist/lib/platform/ios/xcode/XcodeAutomation.js +0 -327
- package/dist/lib/platform/ios/xcode/XcodeImportResolver.d.ts +0 -130
- package/dist/lib/platform/ios/xcode/XcodeImportResolver.js +0 -404
- package/dist/lib/platform/ios/xcode/XcodeIntegration.d.ts +0 -89
- package/dist/lib/platform/ios/xcode/XcodeIntegration.js +0 -588
- package/dist/lib/platform/ios/xcode/XcodeWriteUtils.d.ts +0 -99
- package/dist/lib/platform/ios/xcode/XcodeWriteUtils.js +0 -190
- 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/automation/ActionPipeline.d.ts +0 -34
- package/dist/lib/service/automation/ActionPipeline.js +0 -53
- package/dist/lib/service/automation/AutomationOrchestrator.d.ts +0 -86
- package/dist/lib/service/automation/AutomationOrchestrator.js +0 -57
- package/dist/lib/service/automation/ContextCollector.d.ts +0 -24
- package/dist/lib/service/automation/ContextCollector.js +0 -35
- package/dist/lib/service/automation/DirectiveDetector.d.ts +0 -51
- package/dist/lib/service/automation/DirectiveDetector.js +0 -112
- package/dist/lib/service/automation/FileWatcher.d.ts +0 -51
- package/dist/lib/service/automation/FileWatcher.js +0 -366
- package/dist/lib/service/automation/TriggerResolver.d.ts +0 -36
- package/dist/lib/service/automation/TriggerResolver.js +0 -62
- package/dist/lib/service/automation/handlers/AlinkHandler.d.ts +0 -7
- package/dist/lib/service/automation/handlers/AlinkHandler.js +0 -80
- package/dist/lib/service/automation/handlers/CreateHandler.d.ts +0 -11
- package/dist/lib/service/automation/handlers/CreateHandler.js +0 -170
- package/dist/lib/service/automation/handlers/GuardHandler.d.ts +0 -17
- package/dist/lib/service/automation/handlers/GuardHandler.js +0 -218
- package/dist/lib/service/automation/handlers/HeaderHandler.d.ts +0 -2
- package/dist/lib/service/automation/handlers/HeaderHandler.js +0 -32
- package/dist/lib/service/automation/handlers/SearchHandler.d.ts +0 -11
- package/dist/lib/service/automation/handlers/SearchHandler.js +0 -278
- package/dist/lib/service/snippet/SnippetFactory.d.ts +0 -101
- package/dist/lib/service/snippet/SnippetFactory.js +0 -145
- package/dist/lib/service/snippet/SnippetInstaller.d.ts +0 -91
- package/dist/lib/service/snippet/SnippetInstaller.js +0 -276
- package/dist/lib/service/snippet/codecs/SnippetCodec.d.ts +0 -44
- package/dist/lib/service/snippet/codecs/SnippetCodec.js +0 -35
- package/dist/lib/service/snippet/codecs/VSCodeCodec.d.ts +0 -27
- package/dist/lib/service/snippet/codecs/VSCodeCodec.js +0 -82
- 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/scripts/build-native-ui.d.ts +0 -3
- package/dist/scripts/build-native-ui.js +0 -62
- package/dist/scripts/init-snippets.d.ts +0 -30
- package/dist/scripts/init-snippets.js +0 -298
- package/dist/scripts/install-full.d.ts +0 -7
- package/dist/scripts/install-full.js +0 -38
- package/resources/native-ui/README.md +0 -29
- package/resources/native-ui/combined-window.swift +0 -494
- package/resources/native-ui/main.swift +0 -598
- package/scripts/postinstall-safe.mjs +0 -89
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* bootstrap_dim_files, code_entities
|
|
11
11
|
* 002: tasks, task_dependencies, task_events
|
|
12
12
|
* 003: remote_commands
|
|
13
|
+
* 004: evolution_proposals (+ knowledge_entries.staging_deadline)
|
|
13
14
|
* 内联: remote_state
|
|
14
15
|
* 内部: schema_migrations
|
|
15
16
|
*/
|
|
@@ -77,6 +78,8 @@ export const knowledgeEntries = sqliteTable('knowledge_entries', {
|
|
|
77
78
|
publishedBy: text('publishedBy'),
|
|
78
79
|
// Content hash
|
|
79
80
|
contentHash: text('contentHash'),
|
|
81
|
+
// M2: Staging support (migration 004)
|
|
82
|
+
stagingDeadline: integer('staging_deadline'),
|
|
80
83
|
}, (table) => [
|
|
81
84
|
index('idx_ke3_lifecycle').on(table.lifecycle),
|
|
82
85
|
index('idx_ke3_language').on(table.language),
|
|
@@ -275,75 +278,7 @@ export const codeEntities = sqliteTable('code_entities', {
|
|
|
275
278
|
index('idx_ce_superclass').on(table.superclass),
|
|
276
279
|
]);
|
|
277
280
|
// ═══════════════════════════════════════════════════════════════
|
|
278
|
-
// 11.
|
|
279
|
-
// ═══════════════════════════════════════════════════════════════
|
|
280
|
-
export const tasks = sqliteTable('tasks', {
|
|
281
|
-
id: text('id').primaryKey(),
|
|
282
|
-
parentId: text('parent_id'),
|
|
283
|
-
childSeq: integer('child_seq').default(0),
|
|
284
|
-
title: text('title').notNull(),
|
|
285
|
-
description: text('description').default(''),
|
|
286
|
-
design: text('design').default(''),
|
|
287
|
-
acceptance: text('acceptance').default(''),
|
|
288
|
-
notes: text('notes').default(''),
|
|
289
|
-
status: text('status').notNull().default('open'),
|
|
290
|
-
priority: integer('priority').notNull().default(2),
|
|
291
|
-
taskType: text('task_type').notNull().default('task'),
|
|
292
|
-
closeReason: text('close_reason').default(''),
|
|
293
|
-
contentHash: text('content_hash').default(''),
|
|
294
|
-
failCount: integer('fail_count').default(0),
|
|
295
|
-
lastFailReason: text('last_fail_reason').default(''),
|
|
296
|
-
assignee: text('assignee').default(''),
|
|
297
|
-
createdBy: text('created_by').default('agent'),
|
|
298
|
-
createdAt: integer('created_at').notNull(),
|
|
299
|
-
updatedAt: integer('updated_at').notNull(),
|
|
300
|
-
closedAt: integer('closed_at'),
|
|
301
|
-
metadata: text('metadata').default('{}'),
|
|
302
|
-
}, (table) => [
|
|
303
|
-
index('idx_tasks_status').on(table.status),
|
|
304
|
-
index('idx_tasks_priority').on(table.priority),
|
|
305
|
-
index('idx_tasks_parent').on(table.parentId),
|
|
306
|
-
index('idx_tasks_type').on(table.taskType),
|
|
307
|
-
index('idx_tasks_assignee').on(table.assignee),
|
|
308
|
-
index('idx_tasks_created').on(table.createdAt),
|
|
309
|
-
index('idx_tasks_hash').on(table.contentHash),
|
|
310
|
-
]);
|
|
311
|
-
// ═══════════════════════════════════════════════════════════════
|
|
312
|
-
// 12. task_dependencies — 任务依赖表 (migration 002)
|
|
313
|
-
// ═══════════════════════════════════════════════════════════════
|
|
314
|
-
export const taskDependencies = sqliteTable('task_dependencies', {
|
|
315
|
-
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
316
|
-
taskId: text('task_id').notNull(),
|
|
317
|
-
dependsOnId: text('depends_on_id').notNull(),
|
|
318
|
-
depType: text('dep_type').notNull().default('blocks'),
|
|
319
|
-
metadata: text('metadata').default('{}'),
|
|
320
|
-
createdAt: integer('created_at').notNull(),
|
|
321
|
-
createdBy: text('created_by').default('agent'),
|
|
322
|
-
}, (table) => [
|
|
323
|
-
uniqueIndex('task_dependencies_unique').on(table.taskId, table.dependsOnId, table.depType),
|
|
324
|
-
index('idx_td_task').on(table.taskId),
|
|
325
|
-
index('idx_td_depends_on').on(table.dependsOnId),
|
|
326
|
-
index('idx_td_type').on(table.depType),
|
|
327
|
-
]);
|
|
328
|
-
// ═══════════════════════════════════════════════════════════════
|
|
329
|
-
// 13. task_events — 任务事件审计表 (migration 002)
|
|
330
|
-
// ═══════════════════════════════════════════════════════════════
|
|
331
|
-
export const taskEvents = sqliteTable('task_events', {
|
|
332
|
-
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
333
|
-
taskId: text('task_id').notNull(),
|
|
334
|
-
eventType: text('event_type').notNull(),
|
|
335
|
-
actor: text('actor').default('agent'),
|
|
336
|
-
oldValue: text('old_value'),
|
|
337
|
-
newValue: text('new_value'),
|
|
338
|
-
comment: text('comment'),
|
|
339
|
-
createdAt: integer('created_at').notNull(),
|
|
340
|
-
}, (table) => [
|
|
341
|
-
index('idx_te_task').on(table.taskId),
|
|
342
|
-
index('idx_te_type').on(table.eventType),
|
|
343
|
-
index('idx_te_created').on(table.createdAt),
|
|
344
|
-
]);
|
|
345
|
-
// ═══════════════════════════════════════════════════════════════
|
|
346
|
-
// 14. remote_commands — 远程指令队列 (migration 003)
|
|
281
|
+
// 11. remote_commands — 远程指令队列 (migration 003)
|
|
347
282
|
// ═══════════════════════════════════════════════════════════════
|
|
348
283
|
export const remoteCommands = sqliteTable('remote_commands', {
|
|
349
284
|
id: text('id').primaryKey(),
|
|
@@ -370,3 +305,27 @@ export const remoteState = sqliteTable('remote_state', {
|
|
|
370
305
|
value: text('value'),
|
|
371
306
|
updatedAt: integer('updated_at'),
|
|
372
307
|
});
|
|
308
|
+
// ═══════════════════════════════════════════════════════════════
|
|
309
|
+
// 16. evolution_proposals — 知识进化提案 (M2 Recipe 治理)
|
|
310
|
+
// ═══════════════════════════════════════════════════════════════
|
|
311
|
+
export const evolutionProposals = sqliteTable('evolution_proposals', {
|
|
312
|
+
id: text('id').primaryKey(),
|
|
313
|
+
type: text('type').notNull(),
|
|
314
|
+
targetRecipeId: text('target_recipe_id').notNull(),
|
|
315
|
+
relatedRecipeIds: text('related_recipe_ids').default('[]'),
|
|
316
|
+
confidence: real('confidence').notNull().default(0),
|
|
317
|
+
source: text('source').notNull(),
|
|
318
|
+
description: text('description').default(''),
|
|
319
|
+
evidence: text('evidence').default('[]'),
|
|
320
|
+
status: text('status').notNull().default('pending'),
|
|
321
|
+
proposedAt: integer('proposed_at').notNull(),
|
|
322
|
+
expiresAt: integer('expires_at').notNull(),
|
|
323
|
+
resolvedAt: integer('resolved_at'),
|
|
324
|
+
resolvedBy: text('resolved_by'),
|
|
325
|
+
resolution: text('resolution'),
|
|
326
|
+
}, (table) => [
|
|
327
|
+
index('idx_ep_status').on(table.status),
|
|
328
|
+
index('idx_ep_target').on(table.targetRecipeId),
|
|
329
|
+
index('idx_ep_expires').on(table.expiresAt),
|
|
330
|
+
index('idx_ep_source').on(table.source),
|
|
331
|
+
]);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration 004 — Evolution Proposals + Staging Support
|
|
3
|
+
*
|
|
4
|
+
* M2 Recipe 治理所需的 schema 扩展:
|
|
5
|
+
* 1. evolution_proposals 表 — 存储进化提案(矛盾/冗余/衰退/增强)
|
|
6
|
+
* 2. knowledge_entries 添加 staging_deadline 列
|
|
7
|
+
*/
|
|
8
|
+
export default function migrate(db: import('better-sqlite3').Database): void;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration 004 — Evolution Proposals + Staging Support
|
|
3
|
+
*
|
|
4
|
+
* M2 Recipe 治理所需的 schema 扩展:
|
|
5
|
+
* 1. evolution_proposals 表 — 存储进化提案(矛盾/冗余/衰退/增强)
|
|
6
|
+
* 2. knowledge_entries 添加 staging_deadline 列
|
|
7
|
+
*/
|
|
8
|
+
export default function migrate(db) {
|
|
9
|
+
db.exec(`
|
|
10
|
+
-- 进化提案表
|
|
11
|
+
CREATE TABLE IF NOT EXISTS evolution_proposals (
|
|
12
|
+
id TEXT PRIMARY KEY,
|
|
13
|
+
type TEXT NOT NULL,
|
|
14
|
+
target_recipe_id TEXT NOT NULL,
|
|
15
|
+
related_recipe_ids TEXT DEFAULT '[]',
|
|
16
|
+
confidence REAL NOT NULL DEFAULT 0,
|
|
17
|
+
source TEXT NOT NULL,
|
|
18
|
+
description TEXT DEFAULT '',
|
|
19
|
+
evidence TEXT DEFAULT '[]',
|
|
20
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
21
|
+
proposed_at INTEGER NOT NULL,
|
|
22
|
+
expires_at INTEGER NOT NULL,
|
|
23
|
+
resolved_at INTEGER,
|
|
24
|
+
resolved_by TEXT,
|
|
25
|
+
resolution TEXT,
|
|
26
|
+
|
|
27
|
+
FOREIGN KEY (target_recipe_id) REFERENCES knowledge_entries(id)
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
CREATE INDEX IF NOT EXISTS idx_ep_status ON evolution_proposals(status);
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_ep_target ON evolution_proposals(target_recipe_id);
|
|
32
|
+
CREATE INDEX IF NOT EXISTS idx_ep_expires ON evolution_proposals(expires_at);
|
|
33
|
+
CREATE INDEX IF NOT EXISTS idx_ep_source ON evolution_proposals(source);
|
|
34
|
+
`);
|
|
35
|
+
// knowledge_entries 添加 staging_deadline 列(兼容已有数据)
|
|
36
|
+
// 使用 ALTER TABLE — SQLite 不支持 IF NOT EXISTS for columns,需要 try/catch
|
|
37
|
+
try {
|
|
38
|
+
db.exec(`ALTER TABLE knowledge_entries ADD COLUMN staging_deadline INTEGER`);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// 列已存在,忽略
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -23,5 +23,7 @@ export declare class Logger {
|
|
|
23
23
|
static info(message: string, meta?: Record<string, unknown>): void;
|
|
24
24
|
static warn(message: string, meta?: Record<string, unknown>): void;
|
|
25
25
|
static error(message: string, meta?: Record<string, unknown>): void;
|
|
26
|
+
/** 审计日志 — 写入独立 audit.log,不受 LOG_LEVEL 控制 */
|
|
27
|
+
static audit(event: string, meta?: Record<string, unknown>): void;
|
|
26
28
|
}
|
|
27
29
|
export default Logger;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import winston from 'winston';
|
|
4
|
+
import pathGuard from '../../shared/PathGuard.js';
|
|
4
5
|
// Agent 系统相关标签 — 终端高亮显示
|
|
5
6
|
const AGENT_TAGS = [
|
|
6
7
|
'AgentRuntime',
|
|
@@ -11,7 +12,7 @@ const AGENT_TAGS = [
|
|
|
11
12
|
'CircuitBreaker',
|
|
12
13
|
'EventAggregator',
|
|
13
14
|
];
|
|
14
|
-
const MUTED_PREFIXES = ['
|
|
15
|
+
const MUTED_PREFIXES = ['Tool registered:'];
|
|
15
16
|
// ANSI 颜色常量 — 保证深色终端可读性
|
|
16
17
|
const C = {
|
|
17
18
|
reset: '\x1b[0m',
|
|
@@ -33,6 +34,19 @@ const LEVEL_COLORS = {
|
|
|
33
34
|
info: C.green,
|
|
34
35
|
debug: C.blue,
|
|
35
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* 静音过滤器(winston format)
|
|
39
|
+
* 通过 transform 返回 false 彻底丢弃匹配消息,避免空行。
|
|
40
|
+
* 注意:printf 返回 '' 并不会被 winston 跳过,Console transport 仍会写 '\n'。
|
|
41
|
+
*/
|
|
42
|
+
const muteFilter = winston.format((info) => {
|
|
43
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: intentional ANSI escape sequence stripping
|
|
44
|
+
const rawLevel = info.level.replace(/\u001b\[\d+m/g, '');
|
|
45
|
+
if (rawLevel === 'info' && MUTED_PREFIXES.some((p) => info.message.startsWith(p))) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return info;
|
|
49
|
+
});
|
|
36
50
|
/**
|
|
37
51
|
* 精简 Console 格式
|
|
38
52
|
* - Agent 相关日志: 高亮 cyan/magenta,显示完整信息
|
|
@@ -50,10 +64,6 @@ const compactConsoleFormat = winston.format.printf(({ level, message, timestamp,
|
|
|
50
64
|
// biome-ignore lint/suspicious/noControlCharactersInRegex: intentional ANSI escape sequence stripping
|
|
51
65
|
const rawLevel = level.replace(/\u001b\[\d+m/g, ''); // 去 ANSI
|
|
52
66
|
const lc = LEVEL_COLORS[rawLevel] || C.gray;
|
|
53
|
-
// 静音高频噪音日志
|
|
54
|
-
if (rawLevel === 'info' && MUTED_PREFIXES.some((p) => message.startsWith(p))) {
|
|
55
|
-
return ''; // 返回空字符串会被 winston 跳过
|
|
56
|
-
}
|
|
57
67
|
// 判断是否为 Agent 相关日志
|
|
58
68
|
const isAgentLog = AGENT_TAGS.some((tag) => message.includes(tag) || message.startsWith(`[${tag}]`));
|
|
59
69
|
if (isAgentLog) {
|
|
@@ -98,7 +108,12 @@ export class Logger {
|
|
|
98
108
|
static instance = null;
|
|
99
109
|
static getInstance(config = {}) {
|
|
100
110
|
if (!this.instance) {
|
|
101
|
-
const
|
|
111
|
+
const rawLogsDir = config.file?.path || './.autosnippet/logs';
|
|
112
|
+
// 与 DatabaseConnection 一致:相对路径按 PathGuard.projectRoot 解析,避免 MCP cwd 非项目目录时写到错误位置
|
|
113
|
+
const projectRoot = pathGuard.projectRoot;
|
|
114
|
+
const logsDir = projectRoot && !path.isAbsolute(rawLogsDir)
|
|
115
|
+
? path.resolve(projectRoot, rawLogsDir)
|
|
116
|
+
: path.resolve(rawLogsDir);
|
|
102
117
|
// 确保日志目录存在
|
|
103
118
|
if (!fs.existsSync(logsDir)) {
|
|
104
119
|
fs.mkdirSync(logsDir, { recursive: true });
|
|
@@ -110,7 +125,7 @@ export class Logger {
|
|
|
110
125
|
if (config.console !== false && !isMcpMode) {
|
|
111
126
|
transports.push(new winston.transports.Console({
|
|
112
127
|
stderrLevels: ['error', 'warn', 'info', 'debug'],
|
|
113
|
-
format: winston.format.combine(winston.format.timestamp(), compactConsoleFormat),
|
|
128
|
+
format: winston.format.combine(winston.format.timestamp(), muteFilter(), compactConsoleFormat),
|
|
114
129
|
}));
|
|
115
130
|
}
|
|
116
131
|
// File transports
|
|
@@ -124,6 +139,14 @@ export class Logger {
|
|
|
124
139
|
filename: path.join(logsDir, 'combined.log'),
|
|
125
140
|
format: winston.format.json(),
|
|
126
141
|
}));
|
|
142
|
+
// audit 独立通道 — 不受 LOG_LEVEL 影响,业务关键事件永不丢失
|
|
143
|
+
transports.push(new winston.transports.File({
|
|
144
|
+
filename: path.join(logsDir, 'audit.log'),
|
|
145
|
+
level: 'info',
|
|
146
|
+
format: winston.format.combine(winston.format((info) => {
|
|
147
|
+
return info.audit === true ? info : false;
|
|
148
|
+
})(), winston.format.timestamp(), winston.format.json()),
|
|
149
|
+
}));
|
|
127
150
|
}
|
|
128
151
|
this.instance = winston.createLogger({
|
|
129
152
|
level: logLevel,
|
|
@@ -145,5 +168,9 @@ export class Logger {
|
|
|
145
168
|
static error(message, meta = {}) {
|
|
146
169
|
this.getInstance().error(message, meta);
|
|
147
170
|
}
|
|
171
|
+
/** 审计日志 — 写入独立 audit.log,不受 LOG_LEVEL 控制 */
|
|
172
|
+
static audit(event, meta = {}) {
|
|
173
|
+
this.getInstance().info(event, { ...meta, audit: true });
|
|
174
|
+
}
|
|
148
175
|
}
|
|
149
176
|
export default Logger;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import path from 'node:path';
|
|
7
|
+
import pathGuard from '../../shared/PathGuard.js';
|
|
7
8
|
import Logger from '../logging/Logger.js';
|
|
8
9
|
export class ErrorTracker {
|
|
9
10
|
criticalErrors;
|
|
@@ -14,7 +15,8 @@ export class ErrorTracker {
|
|
|
14
15
|
reportInterval;
|
|
15
16
|
constructor(options = {}) {
|
|
16
17
|
this.config = {
|
|
17
|
-
logDirectory: options.logDirectory ||
|
|
18
|
+
logDirectory: options.logDirectory ||
|
|
19
|
+
path.join(pathGuard.projectRoot ?? process.cwd(), '.autosnippet', 'logs', 'errors'),
|
|
18
20
|
maxErrorsInMemory: options.maxErrorsInMemory || 500,
|
|
19
21
|
enableFileLogging: options.enableFileLogging !== false,
|
|
20
22
|
enableConsoleLogging: options.enableConsoleLogging !== false,
|
|
@@ -56,8 +56,8 @@ export declare class PerformanceMonitor {
|
|
|
56
56
|
}, next: () => void) => void;
|
|
57
57
|
/** 记录请求 */
|
|
58
58
|
recordRequest(requestData: RequestData): void;
|
|
59
|
-
/**
|
|
60
|
-
calculateStats(): void;
|
|
59
|
+
/** 计算统计数据。silent=true 时不输出日志(定时器调用) */
|
|
60
|
+
calculateStats(silent?: boolean): void;
|
|
61
61
|
/** 获取统计信息 */
|
|
62
62
|
getStats(): {
|
|
63
63
|
summary: {
|
|
@@ -27,7 +27,7 @@ export class PerformanceMonitor {
|
|
|
27
27
|
maxSlowRequests: 100, // 最多保留慢请求数
|
|
28
28
|
};
|
|
29
29
|
// 定期计算统计数据(unref 避免阻止进程退出)
|
|
30
|
-
this.statsInterval = setInterval(() => this.calculateStats(), 30000);
|
|
30
|
+
this.statsInterval = setInterval(() => this.calculateStats(true), 30000);
|
|
31
31
|
if (this.statsInterval.unref) {
|
|
32
32
|
this.statsInterval.unref();
|
|
33
33
|
}
|
|
@@ -117,8 +117,8 @@ export class PerformanceMonitor {
|
|
|
117
117
|
Logger.warn(`🐢 慢请求: ${route} - ${duration}ms`);
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
|
-
/**
|
|
121
|
-
calculateStats() {
|
|
120
|
+
/** 计算统计数据。silent=true 时不输出日志(定时器调用) */
|
|
121
|
+
calculateStats(silent = false) {
|
|
122
122
|
const { total, errors } = this.metrics.requests;
|
|
123
123
|
// 错误率
|
|
124
124
|
this.metrics.errorRate = total > 0 ? ((errors / total) * 100).toFixed(2) : 0;
|
|
@@ -138,13 +138,15 @@ export class PerformanceMonitor {
|
|
|
138
138
|
this.metrics.p95 = sorted[p95Index] || 0;
|
|
139
139
|
this.metrics.p99 = sorted[p99Index] || 0;
|
|
140
140
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
141
|
+
if (!silent) {
|
|
142
|
+
Logger.debug('📊 性能统计已更新', {
|
|
143
|
+
requests: total,
|
|
144
|
+
errors,
|
|
145
|
+
errorRate: `${this.metrics.errorRate}%`,
|
|
146
|
+
avgResponseTime: `${this.metrics.averageResponseTime}ms`,
|
|
147
|
+
rpm: this.metrics.rpm,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
148
150
|
}
|
|
149
151
|
/** 获取统计信息 */
|
|
150
152
|
getStats() {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LarkNotifier — Lark notification transport
|
|
3
|
+
*
|
|
4
|
+
* Extracted from task.ts. Sends task progress notifications via API Server → Lark.
|
|
5
|
+
* All methods are non-blocking and fire-and-forget.
|
|
6
|
+
*
|
|
7
|
+
* @module infrastructure/notification/LarkNotifier
|
|
8
|
+
*/
|
|
9
|
+
interface NotifyArgs {
|
|
10
|
+
id?: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
reason?: string;
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}
|
|
15
|
+
interface NotifyResult {
|
|
16
|
+
success: boolean;
|
|
17
|
+
data?: unknown;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Send task progress notification to Lark (async, non-blocking).
|
|
21
|
+
* Fire-and-forget — failures are logged to stderr but never throw.
|
|
22
|
+
*/
|
|
23
|
+
export declare function notifyTaskProgress(operation: string, args: NotifyArgs, result: NotifyResult): Promise<void>;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LarkNotifier — Lark notification transport
|
|
3
|
+
*
|
|
4
|
+
* Extracted from task.ts. Sends task progress notifications via API Server → Lark.
|
|
5
|
+
* All methods are non-blocking and fire-and-forget.
|
|
6
|
+
*
|
|
7
|
+
* @module infrastructure/notification/LarkNotifier
|
|
8
|
+
*/
|
|
9
|
+
// ── Internal Transport ──────────────────────────────
|
|
10
|
+
async function sendLarkViaApi(text) {
|
|
11
|
+
try {
|
|
12
|
+
const port = process.env.PORT || 3000;
|
|
13
|
+
const resp = await fetch(`http://localhost:${port}/api/v1/remote/notify`, {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
headers: { 'Content-Type': 'application/json' },
|
|
16
|
+
body: JSON.stringify({ text }),
|
|
17
|
+
signal: AbortSignal.timeout(5000),
|
|
18
|
+
});
|
|
19
|
+
if (!resp.ok) {
|
|
20
|
+
process.stderr.write(`[LarkNotifier] HTTP ${resp.status}\n`);
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const body = (await resp.json());
|
|
24
|
+
return body.success === true;
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
process.stderr.write(`[LarkNotifier] notify failed: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function sendScreenshotViaApi(caption = '') {
|
|
32
|
+
try {
|
|
33
|
+
const port = process.env.PORT || 3000;
|
|
34
|
+
const resp = await fetch(`http://localhost:${port}/api/v1/remote/screenshot`, {
|
|
35
|
+
method: 'POST',
|
|
36
|
+
headers: { 'Content-Type': 'application/json' },
|
|
37
|
+
body: JSON.stringify({ caption }),
|
|
38
|
+
signal: AbortSignal.timeout(15000),
|
|
39
|
+
});
|
|
40
|
+
if (!resp.ok) {
|
|
41
|
+
process.stderr.write(`[LarkNotifier] Screenshot HTTP ${resp.status}\n`);
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const body = (await resp.json());
|
|
45
|
+
return body.success === true;
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
process.stderr.write(`[LarkNotifier] Screenshot failed: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// ── Public API ──────────────────────────────────────
|
|
53
|
+
/**
|
|
54
|
+
* Send task progress notification to Lark (async, non-blocking).
|
|
55
|
+
* Fire-and-forget — failures are logged to stderr but never throw.
|
|
56
|
+
*/
|
|
57
|
+
export async function notifyTaskProgress(operation, args, result) {
|
|
58
|
+
if (!result || result.success === false) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const data = result.data;
|
|
62
|
+
let text = '';
|
|
63
|
+
switch (operation) {
|
|
64
|
+
case 'create': {
|
|
65
|
+
const title = data?.title || args.title || '';
|
|
66
|
+
const id = data?.id || '';
|
|
67
|
+
text = `📋 新任务: ${id}\n${title}`;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case 'close': {
|
|
71
|
+
const closed = (data?.closed || data);
|
|
72
|
+
const title = closed?.title || args.title || '';
|
|
73
|
+
const id = closed?.id || args.id;
|
|
74
|
+
const reason = closed?.reason || args.reason || '';
|
|
75
|
+
text = `✅ 完成: ${id}\n${title}\n原因: ${reason}`;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
case 'fail': {
|
|
79
|
+
const failed = (data?.failed || data);
|
|
80
|
+
const id = failed?.id || args.id;
|
|
81
|
+
const reason = failed?.reason || args.reason || '未知';
|
|
82
|
+
text = `❌ 失败: ${id}\n原因: ${reason}`;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case 'record_decision': {
|
|
86
|
+
const title = args.title || '';
|
|
87
|
+
text = `📌 决策: ${title}`;
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
default:
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (text) {
|
|
94
|
+
await sendLarkViaApi(text);
|
|
95
|
+
await sendScreenshotViaApi();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReportStore — 报告持久化服务
|
|
3
|
+
*
|
|
4
|
+
* 管道产物(governance / compliance / metrics / analysis)写入 JSONL,
|
|
5
|
+
* 供 API 查询历史报告。
|
|
6
|
+
*
|
|
7
|
+
* @module infrastructure/report/ReportStore
|
|
8
|
+
*/
|
|
9
|
+
export type ReportCategory = 'governance' | 'compliance' | 'metrics' | 'analysis';
|
|
10
|
+
export interface ReportEntry {
|
|
11
|
+
/** 自动生成 `rpt-{date}-{rand}` */
|
|
12
|
+
id: string;
|
|
13
|
+
category: ReportCategory;
|
|
14
|
+
/** 如 'metabolism_cycle', 'redundancy_report' */
|
|
15
|
+
type: string;
|
|
16
|
+
/** 生产者类名 */
|
|
17
|
+
producer: string;
|
|
18
|
+
data: Record<string, unknown>;
|
|
19
|
+
timestamp: number;
|
|
20
|
+
duration_ms?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface ReportQueryOptions {
|
|
23
|
+
category?: ReportCategory[];
|
|
24
|
+
type?: string;
|
|
25
|
+
from?: number;
|
|
26
|
+
to?: number;
|
|
27
|
+
limit?: number;
|
|
28
|
+
offset?: number;
|
|
29
|
+
}
|
|
30
|
+
export declare class ReportStore {
|
|
31
|
+
#private;
|
|
32
|
+
constructor(baseDir: string);
|
|
33
|
+
/** 写入一条报告(追加 JSONL) */
|
|
34
|
+
write(entry: Omit<ReportEntry, 'id'>): Promise<ReportEntry>;
|
|
35
|
+
/** 查询报告列表 */
|
|
36
|
+
query(opts?: ReportQueryOptions): Promise<{
|
|
37
|
+
reports: ReportEntry[];
|
|
38
|
+
total: number;
|
|
39
|
+
}>;
|
|
40
|
+
/** 分类统计 */
|
|
41
|
+
stats(opts?: {
|
|
42
|
+
from?: number;
|
|
43
|
+
to?: number;
|
|
44
|
+
}): Promise<Record<string, number>>;
|
|
45
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReportStore — 报告持久化服务
|
|
3
|
+
*
|
|
4
|
+
* 管道产物(governance / compliance / metrics / analysis)写入 JSONL,
|
|
5
|
+
* 供 API 查询历史报告。
|
|
6
|
+
*
|
|
7
|
+
* @module infrastructure/report/ReportStore
|
|
8
|
+
*/
|
|
9
|
+
import { randomBytes } from 'node:crypto';
|
|
10
|
+
import fs from 'node:fs';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
// ── Constants ───────────────────────────────────────
|
|
13
|
+
const VALID_CATEGORIES = new Set([
|
|
14
|
+
'governance',
|
|
15
|
+
'compliance',
|
|
16
|
+
'metrics',
|
|
17
|
+
'analysis',
|
|
18
|
+
]);
|
|
19
|
+
// ── ReportStore ─────────────────────────────────────
|
|
20
|
+
export class ReportStore {
|
|
21
|
+
#baseDir;
|
|
22
|
+
constructor(baseDir) {
|
|
23
|
+
this.#baseDir = baseDir;
|
|
24
|
+
}
|
|
25
|
+
/** 写入一条报告(追加 JSONL) */
|
|
26
|
+
async write(entry) {
|
|
27
|
+
const id = ReportStore.#generateId(entry.timestamp);
|
|
28
|
+
const full = { id, ...entry };
|
|
29
|
+
const filePath = this.#resolveFile(entry.category, entry.timestamp);
|
|
30
|
+
const dir = path.dirname(filePath);
|
|
31
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
32
|
+
fs.appendFileSync(filePath, `${JSON.stringify(full)}\n`, 'utf8');
|
|
33
|
+
return full;
|
|
34
|
+
}
|
|
35
|
+
/** 查询报告列表 */
|
|
36
|
+
async query(opts = {}) {
|
|
37
|
+
const categories = opts.category?.length
|
|
38
|
+
? opts.category.filter((c) => VALID_CATEGORIES.has(c))
|
|
39
|
+
: [...VALID_CATEGORIES];
|
|
40
|
+
const all = [];
|
|
41
|
+
for (const cat of categories) {
|
|
42
|
+
const catDir = path.join(this.#baseDir, cat);
|
|
43
|
+
if (!fs.existsSync(catDir)) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const files = fs
|
|
47
|
+
.readdirSync(catDir)
|
|
48
|
+
.filter((f) => f.endsWith('.jsonl'))
|
|
49
|
+
.sort()
|
|
50
|
+
.reverse();
|
|
51
|
+
for (const file of files) {
|
|
52
|
+
const entries = this.#readJsonl(path.join(catDir, file));
|
|
53
|
+
all.push(...entries);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// 过滤
|
|
57
|
+
let filtered = all;
|
|
58
|
+
if (opts.type) {
|
|
59
|
+
filtered = filtered.filter((e) => e.type === opts.type);
|
|
60
|
+
}
|
|
61
|
+
if (opts.from) {
|
|
62
|
+
filtered = filtered.filter((e) => e.timestamp >= opts.from);
|
|
63
|
+
}
|
|
64
|
+
if (opts.to) {
|
|
65
|
+
filtered = filtered.filter((e) => e.timestamp <= opts.to);
|
|
66
|
+
}
|
|
67
|
+
// 按时间倒序
|
|
68
|
+
filtered.sort((a, b) => b.timestamp - a.timestamp);
|
|
69
|
+
const total = filtered.length;
|
|
70
|
+
const offset = opts.offset ?? 0;
|
|
71
|
+
const limit = opts.limit ?? 20;
|
|
72
|
+
const reports = filtered.slice(offset, offset + limit);
|
|
73
|
+
return { reports, total };
|
|
74
|
+
}
|
|
75
|
+
/** 分类统计 */
|
|
76
|
+
async stats(opts = {}) {
|
|
77
|
+
const result = {};
|
|
78
|
+
for (const cat of VALID_CATEGORIES) {
|
|
79
|
+
const catDir = path.join(this.#baseDir, cat);
|
|
80
|
+
if (!fs.existsSync(catDir)) {
|
|
81
|
+
result[cat] = 0;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const files = fs.readdirSync(catDir).filter((f) => f.endsWith('.jsonl'));
|
|
85
|
+
let count = 0;
|
|
86
|
+
for (const file of files) {
|
|
87
|
+
const entries = this.#readJsonl(path.join(catDir, file));
|
|
88
|
+
for (const e of entries) {
|
|
89
|
+
if (opts.from && e.timestamp < opts.from) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (opts.to && e.timestamp > opts.to) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
count++;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
result[cat] = count;
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
// ── Private ───────────────────────────────────────
|
|
103
|
+
#resolveFile(category, timestamp) {
|
|
104
|
+
const d = new Date(timestamp);
|
|
105
|
+
const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
|
106
|
+
return path.join(this.#baseDir, category, `${dateStr}.jsonl`);
|
|
107
|
+
}
|
|
108
|
+
#readJsonl(filePath) {
|
|
109
|
+
try {
|
|
110
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
111
|
+
const lines = content.split('\n').filter((l) => l.trim());
|
|
112
|
+
const entries = [];
|
|
113
|
+
for (const line of lines) {
|
|
114
|
+
try {
|
|
115
|
+
entries.push(JSON.parse(line));
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// 跳过损坏行
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return entries;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
static #generateId(timestamp) {
|
|
128
|
+
const d = new Date(timestamp);
|
|
129
|
+
const dateStr = `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, '0')}${String(d.getDate()).padStart(2, '0')}`;
|
|
130
|
+
const rand = randomBytes(4).toString('hex');
|
|
131
|
+
return `rpt-${dateStr}-${rand}`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignalAggregator — 滑窗统计 + 异常检测
|
|
3
|
+
*
|
|
4
|
+
* 订阅可聚合的事实型信号,周期性写入 Report(统计)并在异常时发射 Signal。
|
|
5
|
+
*
|
|
6
|
+
* @module infrastructure/signal/SignalAggregator
|
|
7
|
+
*/
|
|
8
|
+
import type { ReportStore } from '../report/ReportStore.js';
|
|
9
|
+
import type { SignalBus } from './SignalBus.js';
|
|
10
|
+
export declare class SignalAggregator {
|
|
11
|
+
#private;
|
|
12
|
+
constructor(signalBus: SignalBus, reportStore: ReportStore, opts?: {
|
|
13
|
+
intervalMs?: number;
|
|
14
|
+
windowMs?: number;
|
|
15
|
+
});
|
|
16
|
+
start(): void;
|
|
17
|
+
stop(): void;
|
|
18
|
+
}
|