autosnippet 3.0.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +230 -324
- package/bin/api-server.js +1 -1
- package/bin/cli.js +204 -244
- package/bin/mcp-server.js +5 -3
- package/config/knowledge-base.config.js +132 -132
- package/dashboard/dist/assets/{icons-CEfgGaZi.js → icons-Cdq22n2i.js} +95 -100
- package/dashboard/dist/assets/index-ClkyPkDX.js +133 -0
- package/dashboard/dist/assets/index-t4QrJwv1.css +1 -0
- package/dashboard/dist/index.html +3 -3
- package/lib/bootstrap.js +8 -8
- package/lib/cli/AiScanService.js +86 -40
- package/lib/cli/KnowledgeSyncService.js +113 -74
- package/lib/cli/SetupService.js +439 -277
- package/lib/cli/UpgradeService.js +63 -100
- package/lib/core/AstAnalyzer.js +276 -597
- package/lib/core/ast/ProjectGraph.js +101 -40
- package/lib/core/ast/ensure-grammars.js +232 -0
- package/lib/core/ast/index.js +115 -0
- package/lib/core/ast/lang-dart.js +661 -0
- package/lib/core/ast/lang-go.js +530 -0
- package/lib/core/ast/lang-java.js +435 -0
- package/lib/core/ast/lang-javascript.js +272 -0
- package/lib/core/ast/lang-kotlin.js +423 -0
- package/lib/core/ast/lang-objc.js +388 -0
- package/lib/core/ast/lang-python.js +371 -0
- package/lib/core/ast/lang-swift.js +337 -0
- package/lib/core/ast/lang-typescript.js +503 -0
- package/lib/core/capability/CapabilityProbe.js +18 -9
- package/lib/core/constitution/Constitution.js +2 -3
- package/lib/core/constitution/ConstitutionValidator.js +65 -24
- package/lib/core/discovery/DartDiscoverer.js +534 -0
- package/lib/core/discovery/DiscovererRegistry.js +83 -0
- package/lib/core/discovery/GenericDiscoverer.js +225 -0
- package/lib/core/discovery/GoDiscoverer.js +541 -0
- package/lib/core/discovery/JvmDiscoverer.js +506 -0
- package/lib/core/discovery/NodeDiscoverer.js +466 -0
- package/lib/core/discovery/ProjectDiscoverer.js +93 -0
- package/lib/core/discovery/PythonDiscoverer.js +338 -0
- package/lib/core/discovery/SpmDiscoverer.js +5 -0
- package/lib/core/discovery/index.js +53 -0
- package/lib/core/enhancement/EnhancementPack.js +71 -0
- package/lib/core/enhancement/EnhancementRegistry.js +47 -0
- package/lib/core/enhancement/android-enhancement.js +102 -0
- package/lib/core/enhancement/django-enhancement.js +70 -0
- package/lib/core/enhancement/fastapi-enhancement.js +63 -0
- package/lib/core/enhancement/go-grpc-enhancement.js +152 -0
- package/lib/core/enhancement/go-web-enhancement.js +201 -0
- package/lib/core/enhancement/index.js +65 -0
- package/lib/core/enhancement/node-server-enhancement.js +88 -0
- package/lib/core/enhancement/react-enhancement.js +86 -0
- package/lib/core/enhancement/spring-enhancement.js +112 -0
- package/lib/core/enhancement/vue-enhancement.js +96 -0
- package/lib/core/gateway/Gateway.js +8 -9
- package/lib/core/gateway/GatewayActionRegistry.js +1 -1
- package/lib/core/permission/PermissionManager.js +12 -8
- package/lib/domain/index.js +13 -9
- package/lib/domain/knowledge/KnowledgeEntry.js +111 -101
- package/lib/domain/knowledge/KnowledgeRepository.js +0 -1
- package/lib/domain/knowledge/Lifecycle.js +22 -22
- package/lib/domain/knowledge/index.js +9 -12
- package/lib/domain/knowledge/values/Constraints.js +31 -21
- package/lib/domain/knowledge/values/Content.js +21 -13
- package/lib/domain/knowledge/values/Quality.js +31 -18
- package/lib/domain/knowledge/values/Reasoning.js +20 -12
- package/lib/domain/knowledge/values/Relations.js +37 -25
- package/lib/domain/knowledge/values/Stats.js +18 -12
- package/lib/domain/knowledge/values/index.js +4 -3
- package/lib/domain/snippet/Snippet.js +35 -10
- package/lib/external/ai/AiFactory.js +48 -16
- package/lib/external/ai/AiProvider.js +184 -90
- package/lib/external/ai/providers/ClaudeProvider.js +25 -12
- package/lib/external/ai/providers/GoogleGeminiProvider.js +59 -30
- package/lib/external/ai/providers/MockProvider.js +9 -3
- package/lib/external/ai/providers/OpenAiProvider.js +51 -29
- package/lib/external/mcp/McpServer.js +66 -36
- package/lib/external/mcp/errorHandler.js +23 -11
- package/lib/external/mcp/handlers/LanguageExtensions.js +138 -53
- package/lib/external/mcp/handlers/TargetClassifier.js +52 -16
- package/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +81 -20
- package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +71 -42
- package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +9 -17
- package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +14 -9
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +15 -7
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +352 -153
- package/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +52 -12
- package/lib/external/mcp/handlers/bootstrap/skills.js +143 -39
- package/lib/external/mcp/handlers/bootstrap.js +691 -168
- package/lib/external/mcp/handlers/browse.js +66 -22
- package/lib/external/mcp/handlers/candidate.js +118 -35
- package/lib/external/mcp/handlers/consolidated.js +49 -17
- package/lib/external/mcp/handlers/guard.js +104 -39
- package/lib/external/mcp/handlers/knowledge.js +60 -36
- package/lib/external/mcp/handlers/search.js +43 -14
- package/lib/external/mcp/handlers/skill.js +120 -45
- package/lib/external/mcp/handlers/structure.js +240 -86
- package/lib/external/mcp/handlers/system.js +42 -12
- package/lib/external/mcp/handlers/wiki.js +58 -33
- package/lib/external/mcp/tools.js +306 -123
- package/lib/http/HttpServer.js +72 -47
- package/lib/http/middleware/RateLimiter.js +5 -3
- package/lib/http/middleware/errorHandler.js +6 -1
- package/lib/http/middleware/requestLogger.js +14 -3
- package/lib/http/middleware/roleResolver.js +30 -23
- package/lib/http/routes/ai.js +387 -265
- package/lib/http/routes/auth.js +81 -61
- package/lib/http/routes/candidates.js +430 -320
- package/lib/http/routes/commands.js +289 -189
- package/lib/http/routes/extract.js +158 -125
- package/lib/http/routes/guardRules.js +309 -217
- package/lib/http/routes/knowledge.js +213 -154
- package/lib/http/routes/modules.js +578 -0
- package/lib/http/routes/monitoring.js +6 -6
- package/lib/http/routes/recipes.js +104 -93
- package/lib/http/routes/search.js +361 -305
- package/lib/http/routes/skills.js +145 -98
- package/lib/http/routes/snippets.js +42 -30
- package/lib/http/routes/spm.js +3 -405
- package/lib/http/routes/violations.js +113 -93
- package/lib/http/routes/wiki.js +211 -170
- package/lib/http/utils/routeHelpers.js +3 -1
- package/lib/http/utils/sse-sessions.js +16 -6
- package/lib/http/utils/sse.js +15 -5
- package/lib/infrastructure/audit/AuditLogger.js +5 -2
- package/lib/infrastructure/audit/AuditStore.js +10 -7
- package/lib/infrastructure/cache/CacheService.js +3 -1
- package/lib/infrastructure/cache/GraphCache.js +8 -4
- package/lib/infrastructure/cache/UnifiedCacheAdapter.js +1 -1
- package/lib/infrastructure/config/ConfigLoader.js +9 -5
- package/lib/infrastructure/config/Defaults.js +30 -10
- package/lib/infrastructure/config/Paths.js +28 -8
- package/lib/infrastructure/config/TriggerSymbol.js +22 -10
- package/lib/infrastructure/database/DatabaseConnection.js +15 -10
- package/lib/infrastructure/database/migrations/001_initial_schema.js +0 -1
- package/lib/infrastructure/external/ClipboardManager.js +6 -2
- package/lib/infrastructure/external/NativeUi.js +50 -43
- package/lib/infrastructure/external/OpenBrowser.js +14 -17
- package/lib/infrastructure/external/XcodeAutomation.js +14 -258
- package/lib/infrastructure/logging/Logger.js +46 -30
- package/lib/infrastructure/monitoring/ErrorTracker.js +7 -5
- package/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -4
- package/lib/infrastructure/paths/HeaderResolver.js +25 -9
- package/lib/infrastructure/paths/PathFinder.js +34 -12
- package/lib/infrastructure/plugin/PluginManager.js +26 -8
- package/lib/infrastructure/realtime/RealtimeService.js +2 -2
- package/lib/infrastructure/vector/Chunker.js +22 -7
- package/lib/infrastructure/vector/IndexingPipeline.js +46 -22
- package/lib/infrastructure/vector/JsonVectorAdapter.js +90 -53
- package/lib/infrastructure/vector/VectorStore.js +28 -10
- package/lib/injection/ServiceContainer.js +247 -93
- package/lib/platform/ios/index.js +63 -0
- package/lib/platform/ios/routes/spm.js +437 -0
- package/lib/platform/ios/snippet/PlaceholderConverter.js +55 -0
- package/lib/platform/ios/snippet/XcodeCodec.js +112 -0
- package/lib/{service → platform/ios}/spm/DependencyGraph.js +41 -17
- package/lib/{service → platform/ios}/spm/PackageSwiftParser.js +41 -14
- package/lib/{service → platform/ios}/spm/PolicyEngine.js +9 -4
- package/lib/platform/ios/spm/SpmDiscoverer.js +122 -0
- package/lib/{service → platform/ios}/spm/SpmService.js +385 -127
- package/lib/{service/automation → platform/ios/xcode}/SaveEventFilter.js +8 -7
- package/lib/platform/ios/xcode/XcodeAutomation.js +350 -0
- package/lib/{service/automation → platform/ios/xcode}/XcodeIntegration.js +325 -145
- package/lib/repository/base/BaseRepository.js +7 -9
- package/lib/repository/knowledge/KnowledgeRepository.impl.js +98 -75
- package/lib/repository/token/TokenUsageStore.js +4 -2
- package/lib/service/automation/ActionPipeline.js +1 -1
- package/lib/service/automation/AutomationOrchestrator.js +8 -4
- package/lib/service/automation/ContextCollector.js +7 -5
- package/lib/service/automation/DirectiveDetector.js +23 -16
- package/lib/service/automation/FileWatcher.js +112 -56
- package/lib/service/automation/TriggerResolver.js +6 -4
- package/lib/service/automation/handlers/AlinkHandler.js +24 -12
- package/lib/service/automation/handlers/CreateHandler.js +19 -20
- package/lib/service/automation/handlers/DraftHandler.js +14 -8
- package/lib/service/automation/handlers/GuardHandler.js +93 -63
- package/lib/service/automation/handlers/HeaderHandler.js +1 -6
- package/lib/service/automation/handlers/SearchHandler.js +155 -88
- package/lib/service/bootstrap/BootstrapTaskManager.js +77 -35
- package/lib/service/candidate/SimilarityService.js +25 -9
- package/lib/service/chat/AnalystAgent.js +50 -24
- package/lib/service/chat/CandidateGuardrail.js +143 -17
- package/lib/service/chat/ChatAgent.js +655 -260
- package/lib/service/chat/ContextWindow.js +116 -71
- package/lib/service/chat/ConversationStore.js +77 -36
- package/lib/service/chat/EpisodicConsolidator.js +47 -23
- package/lib/service/chat/HandoffProtocol.js +98 -22
- package/lib/service/chat/Memory.js +34 -14
- package/lib/service/chat/ProducerAgent.js +40 -20
- package/lib/service/chat/ProjectSemanticMemory.js +109 -78
- package/lib/service/chat/ReasoningLayer.js +148 -70
- package/lib/service/chat/ReasoningTrace.js +44 -32
- package/lib/service/chat/TaskPipeline.js +39 -19
- package/lib/service/chat/ToolRegistry.js +48 -29
- package/lib/service/chat/WorkingMemory.js +44 -18
- package/lib/service/chat/tools.js +1096 -494
- package/lib/service/context/RecipeExtractor.js +132 -51
- package/lib/service/cursor/CursorDeliveryPipeline.js +82 -37
- package/lib/service/cursor/KnowledgeCompressor.js +25 -22
- package/lib/service/cursor/RulesGenerator.js +13 -7
- package/lib/service/cursor/SkillsSyncer.js +77 -27
- package/lib/service/cursor/TokenBudget.js +2 -2
- package/lib/service/cursor/TopicClassifier.js +54 -20
- package/lib/service/guard/ComplianceReporter.js +55 -43
- package/lib/service/guard/ExclusionManager.js +67 -29
- package/lib/service/guard/GuardCheckEngine.js +381 -86
- package/lib/service/guard/GuardFeedbackLoop.js +22 -10
- package/lib/service/guard/GuardService.js +29 -19
- package/lib/service/guard/RuleLearner.js +55 -23
- package/lib/service/guard/SourceFileCollector.js +27 -20
- package/lib/service/guard/ViolationsStore.js +43 -38
- package/lib/service/knowledge/CodeEntityGraph.js +147 -82
- package/lib/service/knowledge/ConfidenceRouter.js +12 -10
- package/lib/service/knowledge/KnowledgeFileWriter.js +147 -56
- package/lib/service/knowledge/KnowledgeGraphService.js +81 -34
- package/lib/service/knowledge/KnowledgeService.js +222 -112
- package/lib/service/module/ModuleService.js +969 -0
- package/lib/service/quality/FeedbackCollector.js +27 -15
- package/lib/service/quality/QualityScorer.js +78 -24
- package/lib/service/recipe/RecipeCandidateValidator.js +110 -44
- package/lib/service/recipe/RecipeParser.js +78 -45
- package/lib/service/search/CoarseRanker.js +43 -28
- package/lib/service/search/CrossEncoderReranker.js +32 -21
- package/lib/service/search/InvertedIndex.js +21 -7
- package/lib/service/search/MultiSignalRanker.js +90 -28
- package/lib/service/search/RetrievalFunnel.js +45 -24
- package/lib/service/search/SearchEngine.js +255 -103
- package/lib/service/skills/EventAggregator.js +32 -15
- package/lib/service/skills/SignalCollector.js +140 -64
- package/lib/service/skills/SkillAdvisor.js +79 -42
- package/lib/service/skills/SkillHooks.js +16 -14
- package/lib/service/snippet/PlaceholderConverter.js +5 -0
- package/lib/service/snippet/SnippetFactory.js +116 -99
- package/lib/service/snippet/SnippetInstaller.js +234 -62
- package/lib/service/snippet/codecs/SnippetCodec.js +67 -0
- package/lib/service/snippet/codecs/VSCodeCodec.js +102 -0
- package/lib/service/snippet/codecs/XcodeCodec.js +5 -0
- package/lib/service/wiki/WikiGenerator.js +637 -263
- package/lib/shared/DimensionCopyRegistry.js +472 -0
- package/lib/shared/LanguageService.js +399 -0
- package/lib/shared/PathGuard.js +45 -28
- package/lib/shared/RecipeReadinessChecker.js +72 -12
- package/lib/shared/constants.js +41 -41
- package/lib/shared/errors/BaseError.js +2 -2
- package/lib/shared/errors/index.js +4 -4
- package/lib/shared/similarity.js +25 -8
- package/lib/shared/token-utils.js +6 -2
- package/lib/shared/utils/common.js +12 -4
- package/package.json +49 -13
- package/scripts/bench-real-projects.mjs +256 -0
- package/scripts/build-native-ui.js +30 -30
- package/scripts/clear-old-vector-index.js +5 -35
- package/scripts/clear-vector-cache.js +7 -37
- package/scripts/collect-test-project-stats.mjs +160 -0
- package/scripts/diagnose-mcp.js +41 -32
- package/scripts/ensure-parse-package.js +6 -9
- package/scripts/generate-recipe-drafts.js +116 -77
- package/scripts/init-db.js +3 -20
- package/scripts/init-snippets.js +305 -0
- package/scripts/init-vector-db.js +173 -170
- package/scripts/install-cursor-skill.js +148 -104
- package/scripts/install-full.js +8 -21
- package/scripts/install-vscode-copilot.js +146 -145
- package/scripts/migrate-md-to-knowledge.mjs +139 -151
- package/scripts/postinstall-safe.js +5 -17
- package/scripts/recipe-audit.js +106 -82
- package/scripts/release.js +283 -323
- package/scripts/setup-mcp-config.js +60 -52
- package/scripts/verify-context-api.js +20 -20
- package/skills/autosnippet-analysis/SKILL.md +10 -6
- package/skills/autosnippet-candidates/SKILL.md +27 -26
- package/skills/autosnippet-coldstart/SKILL.md +555 -38
- package/skills/autosnippet-concepts/SKILL.md +349 -337
- package/skills/autosnippet-create/SKILL.md +5 -5
- package/skills/autosnippet-reference-dart/SKILL.md +543 -0
- package/skills/autosnippet-reference-go/SKILL.md +539 -0
- package/skills/autosnippet-reference-java/SKILL.md +534 -0
- package/skills/autosnippet-reference-jsts/SKILL.md +41 -9
- package/skills/autosnippet-reference-kotlin/SKILL.md +526 -0
- package/skills/autosnippet-reference-objc/SKILL.md +29 -6
- package/skills/autosnippet-reference-python/SKILL.md +800 -0
- package/skills/autosnippet-reference-swift/SKILL.md +70 -14
- package/skills/autosnippet-structure/SKILL.md +4 -4
- package/templates/cursor-rules/autosnippet-conventions.mdc +2 -2
- package/templates/recipes-setup/README.md +2 -2
- package/templates/recipes-setup/_template.md +1 -1
- package/dashboard/dist/assets/index-Bun3ld_J.css +0 -1
- package/dashboard/dist/assets/index-_Sk_Dmg3.js +0 -143
- package/resources/asd-entry/main.swift +0 -159
- package/scripts/build-asd-entry.js +0 -51
- package/scripts/init-xcode-snippets.js +0 -311
- package/template.json +0 -39
|
@@ -5,57 +5,82 @@
|
|
|
5
5
|
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import path from 'node:path';
|
|
8
|
-
import { envelope } from '../envelope.js';
|
|
9
8
|
import * as Paths from '../../../infrastructure/config/Paths.js';
|
|
9
|
+
import { LanguageService } from '../../../shared/LanguageService.js';
|
|
10
|
+
import { envelope } from '../envelope.js';
|
|
10
11
|
|
|
11
|
-
// ───
|
|
12
|
+
// ─── Discoverer 缓存 ─────────────────────────────────────
|
|
12
13
|
// 同一 projectRoot 在模块生命期内只初始化一次
|
|
13
|
-
let
|
|
14
|
+
let _discovererCache = null; // { projectRoot, discoverer, targets }
|
|
14
15
|
|
|
15
|
-
async function
|
|
16
|
+
async function _getLoadedDiscoverer() {
|
|
16
17
|
const projectRoot = process.env.ASD_PROJECT_DIR || process.cwd();
|
|
17
|
-
if (
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
if (_discovererCache && _discovererCache.projectRoot === projectRoot) {
|
|
19
|
+
return _discovererCache;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 优先使用 DiscovererRegistry(多语言统一接口)
|
|
23
|
+
const { getDiscovererRegistry } = await import('../../../core/discovery/index.js');
|
|
24
|
+
const registry = getDiscovererRegistry();
|
|
25
|
+
const discoverer = await registry.detect(projectRoot);
|
|
26
|
+
await discoverer.load(projectRoot);
|
|
27
|
+
const targets = (await discoverer.listTargets()) || [];
|
|
28
|
+
_discovererCache = { projectRoot, discoverer, targets };
|
|
29
|
+
return _discovererCache;
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
function _findTarget(targets, targetName) {
|
|
27
|
-
const t = targets.find(t => t.name === targetName);
|
|
28
|
-
if (!t)
|
|
33
|
+
const t = targets.find((t) => t.name === targetName);
|
|
34
|
+
if (!t) {
|
|
35
|
+
throw new Error(`Target not found: ${targetName}`);
|
|
36
|
+
}
|
|
29
37
|
return t;
|
|
30
38
|
}
|
|
31
39
|
|
|
32
|
-
/** 推断语言 */
|
|
40
|
+
/** 推断语言 — 委托给 LanguageService */
|
|
33
41
|
function _inferLang(filename) {
|
|
34
|
-
|
|
35
|
-
const map = {
|
|
36
|
-
'.swift': 'swift', '.m': 'objectivec', '.h': 'objectivec', '.mm': 'objectivec',
|
|
37
|
-
'.c': 'c', '.cpp': 'cpp', '.js': 'javascript', '.ts': 'typescript',
|
|
38
|
-
'.py': 'python', '.rb': 'ruby', '.java': 'java', '.kt': 'kotlin',
|
|
39
|
-
'.go': 'go', '.rs': 'rust',
|
|
40
|
-
};
|
|
41
|
-
return map[ext] || 'unknown';
|
|
42
|
+
return LanguageService.inferLang(filename);
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
/** 推断 Target 职责 */
|
|
45
46
|
function _inferTargetRole(targetName) {
|
|
46
47
|
const n = targetName.toLowerCase();
|
|
47
|
-
if (/core|kit|shared|common|foundation|base/i.test(n))
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (/
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (/
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (/
|
|
57
|
-
|
|
58
|
-
|
|
48
|
+
if (/core|kit|shared|common|foundation|base/i.test(n)) {
|
|
49
|
+
return 'core';
|
|
50
|
+
}
|
|
51
|
+
if (/service|manager|provider|repository|store/i.test(n)) {
|
|
52
|
+
return 'service';
|
|
53
|
+
}
|
|
54
|
+
if (/ui|view|screen|component|widget/i.test(n)) {
|
|
55
|
+
return 'ui';
|
|
56
|
+
}
|
|
57
|
+
if (/network|api|http|grpc|socket/i.test(n)) {
|
|
58
|
+
return 'networking';
|
|
59
|
+
}
|
|
60
|
+
if (/storage|database|cache|persist|realm|coredata/i.test(n)) {
|
|
61
|
+
return 'storage';
|
|
62
|
+
}
|
|
63
|
+
if (/test|spec|mock|stub|fake/i.test(n)) {
|
|
64
|
+
return 'test';
|
|
65
|
+
}
|
|
66
|
+
if (/app|main|launch|entry/i.test(n)) {
|
|
67
|
+
return 'app';
|
|
68
|
+
}
|
|
69
|
+
if (/router|coordinator|navigation/i.test(n)) {
|
|
70
|
+
return 'routing';
|
|
71
|
+
}
|
|
72
|
+
if (/util|helper|extension|tool/i.test(n)) {
|
|
73
|
+
return 'utility';
|
|
74
|
+
}
|
|
75
|
+
if (/model|entity|dto|schema/i.test(n)) {
|
|
76
|
+
return 'model';
|
|
77
|
+
}
|
|
78
|
+
if (/auth|login|session|token/i.test(n)) {
|
|
79
|
+
return 'auth';
|
|
80
|
+
}
|
|
81
|
+
if (/config|setting|environment|constant/i.test(n)) {
|
|
82
|
+
return 'config';
|
|
83
|
+
}
|
|
59
84
|
return 'feature';
|
|
60
85
|
}
|
|
61
86
|
|
|
@@ -64,7 +89,7 @@ function _inferTargetRole(targetName) {
|
|
|
64
89
|
// ═══════════════════════════════════════════════════════════
|
|
65
90
|
|
|
66
91
|
export async function getTargets(ctx, args = {}) {
|
|
67
|
-
const {
|
|
92
|
+
const { discoverer, targets } = await _getLoadedDiscoverer();
|
|
68
93
|
const includeSummary = args.includeSummary !== false; // 默认 true
|
|
69
94
|
|
|
70
95
|
if (!includeSummary) {
|
|
@@ -80,14 +105,16 @@ export async function getTargets(ctx, args = {}) {
|
|
|
80
105
|
let fileCount = 0;
|
|
81
106
|
const langStats = {};
|
|
82
107
|
try {
|
|
83
|
-
const fileList = await
|
|
108
|
+
const fileList = await discoverer.getTargetFiles(t);
|
|
84
109
|
fileCount = fileList.length;
|
|
85
110
|
for (const f of fileList) {
|
|
86
111
|
const lang = _inferLang(f.name);
|
|
87
112
|
langStats[lang] = (langStats[lang] || 0) + 1;
|
|
88
113
|
globalLangStats[lang] = (globalLangStats[lang] || 0) + 1;
|
|
89
114
|
}
|
|
90
|
-
} catch {
|
|
115
|
+
} catch {
|
|
116
|
+
/* skip */
|
|
117
|
+
}
|
|
91
118
|
totalFiles += fileCount;
|
|
92
119
|
enriched.push({
|
|
93
120
|
name: t.name,
|
|
@@ -114,12 +141,14 @@ export async function getTargets(ctx, args = {}) {
|
|
|
114
141
|
// ═══════════════════════════════════════════════════════════
|
|
115
142
|
|
|
116
143
|
export async function getTargetFiles(ctx, args) {
|
|
117
|
-
if (!args.targetName)
|
|
118
|
-
|
|
144
|
+
if (!args.targetName) {
|
|
145
|
+
throw new Error('targetName is required');
|
|
146
|
+
}
|
|
147
|
+
const { discoverer, targets } = await _getLoadedDiscoverer();
|
|
119
148
|
const target = _findTarget(targets, args.targetName);
|
|
120
149
|
|
|
121
|
-
// 使用
|
|
122
|
-
const rawFiles = await
|
|
150
|
+
// 使用 Discoverer.getTargetFiles — 统一接口定位源文件
|
|
151
|
+
const rawFiles = await discoverer.getTargetFiles(target);
|
|
123
152
|
|
|
124
153
|
const includeContent = args.includeContent || false;
|
|
125
154
|
const contentMaxLines = args.contentMaxLines || 100;
|
|
@@ -127,7 +156,9 @@ export async function getTargetFiles(ctx, args) {
|
|
|
127
156
|
|
|
128
157
|
const files = [];
|
|
129
158
|
for (const f of rawFiles) {
|
|
130
|
-
if (files.length >= maxFiles)
|
|
159
|
+
if (files.length >= maxFiles) {
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
131
162
|
const entry = {
|
|
132
163
|
name: f.name,
|
|
133
164
|
path: f.path,
|
|
@@ -142,14 +173,20 @@ export async function getTargetFiles(ctx, args) {
|
|
|
142
173
|
entry.content = lines.slice(0, contentMaxLines).join('\n');
|
|
143
174
|
entry.totalLines = lines.length;
|
|
144
175
|
entry.truncated = lines.length > contentMaxLines;
|
|
145
|
-
} catch {
|
|
176
|
+
} catch {
|
|
177
|
+
entry.content = null;
|
|
178
|
+
entry.totalLines = 0;
|
|
179
|
+
entry.truncated = false;
|
|
180
|
+
}
|
|
146
181
|
}
|
|
147
182
|
files.push(entry);
|
|
148
183
|
}
|
|
149
184
|
|
|
150
185
|
// 文件语言统计
|
|
151
186
|
const langStats = {};
|
|
152
|
-
for (const f of files) {
|
|
187
|
+
for (const f of files) {
|
|
188
|
+
langStats[f.language] = (langStats[f.language] || 0) + 1;
|
|
189
|
+
}
|
|
153
190
|
|
|
154
191
|
return envelope({
|
|
155
192
|
success: true,
|
|
@@ -169,21 +206,27 @@ export async function getTargetFiles(ctx, args) {
|
|
|
169
206
|
// ═══════════════════════════════════════════════════════════
|
|
170
207
|
|
|
171
208
|
export async function getTargetMetadata(ctx, args) {
|
|
172
|
-
if (!args.targetName)
|
|
173
|
-
|
|
209
|
+
if (!args.targetName) {
|
|
210
|
+
throw new Error('targetName is required');
|
|
211
|
+
}
|
|
212
|
+
const { targets } = await _getLoadedDiscoverer();
|
|
174
213
|
const target = _findTarget(targets, args.targetName);
|
|
214
|
+
const projectRoot = _discovererCache.projectRoot;
|
|
175
215
|
|
|
176
216
|
// ── 基础元数据 ──
|
|
177
217
|
const meta = {
|
|
178
218
|
name: target.name,
|
|
219
|
+
path: target.path || null,
|
|
179
220
|
packageName: target.packageName || null,
|
|
180
221
|
packagePath: target.packagePath || null,
|
|
181
222
|
type: target.type || 'target',
|
|
223
|
+
language: target.language || null,
|
|
224
|
+
framework: target.framework || null,
|
|
182
225
|
inferredRole: _inferTargetRole(target.name),
|
|
183
226
|
targetDir: target.targetDir || null,
|
|
184
227
|
sourcesPath: target.info?.path || null,
|
|
185
228
|
sources: target.info?.sources || null,
|
|
186
|
-
dependencies: target.info?.dependencies || [],
|
|
229
|
+
dependencies: target.info?.dependencies || target.metadata?.dependencies || [],
|
|
187
230
|
};
|
|
188
231
|
|
|
189
232
|
// ── SPM 图谱 (spmmap.json) ──
|
|
@@ -199,7 +242,9 @@ export async function getTargetMetadata(ctx, args) {
|
|
|
199
242
|
meta.packageTargets = pkg.targets || [];
|
|
200
243
|
}
|
|
201
244
|
}
|
|
202
|
-
} catch {
|
|
245
|
+
} catch {
|
|
246
|
+
/* ignore */
|
|
247
|
+
}
|
|
203
248
|
|
|
204
249
|
// ── 知识图谱关系 (knowledge_edges) ──
|
|
205
250
|
try {
|
|
@@ -207,11 +252,21 @@ export async function getTargetMetadata(ctx, args) {
|
|
|
207
252
|
if (graphService) {
|
|
208
253
|
const edges = graphService.getEdges(target.name, 'module', 'both');
|
|
209
254
|
meta.graphEdges = {
|
|
210
|
-
outgoing: (edges.outgoing || []).map(e => ({
|
|
211
|
-
|
|
255
|
+
outgoing: (edges.outgoing || []).map((e) => ({
|
|
256
|
+
toId: e.toId,
|
|
257
|
+
toType: e.toType,
|
|
258
|
+
relation: e.relation,
|
|
259
|
+
})),
|
|
260
|
+
incoming: (edges.incoming || []).map((e) => ({
|
|
261
|
+
fromId: e.fromId,
|
|
262
|
+
fromType: e.fromType,
|
|
263
|
+
relation: e.relation,
|
|
264
|
+
})),
|
|
212
265
|
};
|
|
213
266
|
}
|
|
214
|
-
} catch {
|
|
267
|
+
} catch {
|
|
268
|
+
/* knowledge_edges may not exist */
|
|
269
|
+
}
|
|
215
270
|
|
|
216
271
|
return envelope({ success: true, data: meta, meta: { tool: 'autosnippet_structure' } });
|
|
217
272
|
}
|
|
@@ -219,7 +274,11 @@ export async function getTargetMetadata(ctx, args) {
|
|
|
219
274
|
export async function graphQuery(ctx, args) {
|
|
220
275
|
const graphService = ctx.container.get('knowledgeGraphService');
|
|
221
276
|
if (!graphService) {
|
|
222
|
-
return envelope({
|
|
277
|
+
return envelope({
|
|
278
|
+
success: false,
|
|
279
|
+
message: 'KnowledgeGraphService not available — knowledge_edges 表可能未初始化',
|
|
280
|
+
meta: { tool: 'autosnippet_graph' },
|
|
281
|
+
});
|
|
223
282
|
}
|
|
224
283
|
const nodeType = args.nodeType || 'recipe';
|
|
225
284
|
const direction = args.direction || 'both';
|
|
@@ -234,7 +293,11 @@ export async function graphQuery(ctx, args) {
|
|
|
234
293
|
// knowledge_edges 表不存在时 graceful 降级到 relations 字段
|
|
235
294
|
if (err.message?.includes('no such table')) {
|
|
236
295
|
data = await _fallbackRelationsFromRecipe(ctx, args.nodeId, args.relation, direction);
|
|
237
|
-
return envelope({
|
|
296
|
+
return envelope({
|
|
297
|
+
success: true,
|
|
298
|
+
data,
|
|
299
|
+
meta: { tool: 'autosnippet_graph', source: 'relations-fallback' },
|
|
300
|
+
});
|
|
238
301
|
}
|
|
239
302
|
throw err;
|
|
240
303
|
}
|
|
@@ -244,7 +307,11 @@ export async function graphQuery(ctx, args) {
|
|
|
244
307
|
export async function graphImpact(ctx, args) {
|
|
245
308
|
const graphService = ctx.container.get('knowledgeGraphService');
|
|
246
309
|
if (!graphService) {
|
|
247
|
-
return envelope({
|
|
310
|
+
return envelope({
|
|
311
|
+
success: false,
|
|
312
|
+
message: 'KnowledgeGraphService not available — knowledge_edges 表可能未初始化',
|
|
313
|
+
meta: { tool: 'autosnippet_graph' },
|
|
314
|
+
});
|
|
248
315
|
}
|
|
249
316
|
const nodeType = args.nodeType || 'recipe';
|
|
250
317
|
let impacted;
|
|
@@ -254,11 +321,25 @@ export async function graphImpact(ctx, args) {
|
|
|
254
321
|
// knowledge_edges 表不存在时 graceful 降级
|
|
255
322
|
if (err.message?.includes('no such table')) {
|
|
256
323
|
impacted = await _fallbackImpactFromRecipe(ctx, args.nodeId);
|
|
257
|
-
return envelope({
|
|
324
|
+
return envelope({
|
|
325
|
+
success: true,
|
|
326
|
+
data: {
|
|
327
|
+
nodeId: args.nodeId,
|
|
328
|
+
impactedCount: impacted.length,
|
|
329
|
+
impacted,
|
|
330
|
+
degraded: true,
|
|
331
|
+
degradedReason: 'knowledge_edges 表不存在,仅从 relations 字段反查',
|
|
332
|
+
},
|
|
333
|
+
meta: { tool: 'autosnippet_graph', source: 'relations-fallback' },
|
|
334
|
+
});
|
|
258
335
|
}
|
|
259
336
|
throw err;
|
|
260
337
|
}
|
|
261
|
-
return envelope({
|
|
338
|
+
return envelope({
|
|
339
|
+
success: true,
|
|
340
|
+
data: { nodeId: args.nodeId, impactedCount: impacted.length, impacted },
|
|
341
|
+
meta: { tool: 'autosnippet_graph' },
|
|
342
|
+
});
|
|
262
343
|
}
|
|
263
344
|
|
|
264
345
|
/**
|
|
@@ -268,15 +349,28 @@ async function _fallbackRelationsFromRecipe(ctx, nodeId, relation, direction) {
|
|
|
268
349
|
try {
|
|
269
350
|
const knowledgeService = ctx.container.get('knowledgeService');
|
|
270
351
|
const entry = await knowledgeService.get(nodeId);
|
|
271
|
-
if (!entry)
|
|
352
|
+
if (!entry) {
|
|
353
|
+
return { outgoing: [], incoming: [] };
|
|
354
|
+
}
|
|
272
355
|
|
|
273
|
-
const relJson =
|
|
356
|
+
const relJson =
|
|
357
|
+
typeof entry.relations?.toJSON === 'function'
|
|
358
|
+
? entry.relations.toJSON()
|
|
359
|
+
: entry.relations || {};
|
|
274
360
|
const outgoing = [];
|
|
275
361
|
if (direction === 'both' || direction === 'out') {
|
|
276
362
|
for (const [relType, targets] of Object.entries(relJson)) {
|
|
277
|
-
if (relation && relType !== relation)
|
|
278
|
-
|
|
279
|
-
|
|
363
|
+
if (relation && relType !== relation) {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
for (const t of Array.isArray(targets) ? targets : []) {
|
|
367
|
+
outgoing.push({
|
|
368
|
+
fromId: nodeId,
|
|
369
|
+
fromType: 'knowledge',
|
|
370
|
+
toId: t.target || t.id || t,
|
|
371
|
+
toType: 'knowledge',
|
|
372
|
+
relation: relType,
|
|
373
|
+
});
|
|
280
374
|
}
|
|
281
375
|
}
|
|
282
376
|
}
|
|
@@ -285,27 +379,39 @@ async function _fallbackRelationsFromRecipe(ctx, nodeId, relation, direction) {
|
|
|
285
379
|
const incoming = [];
|
|
286
380
|
if (direction === 'both' || direction === 'in') {
|
|
287
381
|
const knowledgeRepo = ctx.container.get('knowledgeRepository');
|
|
288
|
-
const reverseRows = knowledgeRepo.db
|
|
289
|
-
`SELECT id, relations FROM knowledge_entries WHERE relations LIKE ? AND id != ?`
|
|
290
|
-
|
|
382
|
+
const reverseRows = knowledgeRepo.db
|
|
383
|
+
.prepare(`SELECT id, relations FROM knowledge_entries WHERE relations LIKE ? AND id != ?`)
|
|
384
|
+
.all(`%${nodeId}%`, nodeId);
|
|
291
385
|
for (const row of reverseRows) {
|
|
292
386
|
try {
|
|
293
387
|
const rels = JSON.parse(row.relations || '{}');
|
|
294
388
|
for (const [relType, targets] of Object.entries(rels)) {
|
|
295
|
-
if (relation && relType !== relation)
|
|
296
|
-
|
|
389
|
+
if (relation && relType !== relation) {
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
for (const t of Array.isArray(targets) ? targets : []) {
|
|
297
393
|
const targetId = t.target || t.id || t;
|
|
298
394
|
if (targetId === nodeId) {
|
|
299
|
-
incoming.push({
|
|
395
|
+
incoming.push({
|
|
396
|
+
fromId: row.id,
|
|
397
|
+
fromType: 'knowledge',
|
|
398
|
+
toId: nodeId,
|
|
399
|
+
toType: 'knowledge',
|
|
400
|
+
relation: relType,
|
|
401
|
+
});
|
|
300
402
|
}
|
|
301
403
|
}
|
|
302
404
|
}
|
|
303
|
-
} catch {
|
|
405
|
+
} catch {
|
|
406
|
+
/* ignore parse error */
|
|
407
|
+
}
|
|
304
408
|
}
|
|
305
409
|
}
|
|
306
410
|
|
|
307
411
|
return { outgoing, incoming };
|
|
308
|
-
} catch {
|
|
412
|
+
} catch {
|
|
413
|
+
return { outgoing: [], incoming: [] };
|
|
414
|
+
}
|
|
309
415
|
}
|
|
310
416
|
|
|
311
417
|
/**
|
|
@@ -314,34 +420,52 @@ async function _fallbackRelationsFromRecipe(ctx, nodeId, relation, direction) {
|
|
|
314
420
|
async function _fallbackImpactFromRecipe(ctx, nodeId) {
|
|
315
421
|
try {
|
|
316
422
|
const knowledgeRepo = ctx.container.get('knowledgeRepository');
|
|
317
|
-
const rows = knowledgeRepo.db
|
|
318
|
-
|
|
319
|
-
|
|
423
|
+
const rows = knowledgeRepo.db
|
|
424
|
+
.prepare(
|
|
425
|
+
`SELECT id, title, relations FROM knowledge_entries WHERE relations LIKE ? AND id != ?`
|
|
426
|
+
)
|
|
427
|
+
.all(`%${nodeId}%`, nodeId);
|
|
320
428
|
|
|
321
429
|
const impacted = [];
|
|
322
430
|
for (const row of rows) {
|
|
323
431
|
try {
|
|
324
432
|
const rels = JSON.parse(row.relations || '{}');
|
|
325
433
|
for (const [relType, targets] of Object.entries(rels)) {
|
|
326
|
-
for (const t of
|
|
434
|
+
for (const t of Array.isArray(targets) ? targets : []) {
|
|
327
435
|
if ((t.target || t.id || t) === nodeId) {
|
|
328
|
-
impacted.push({
|
|
436
|
+
impacted.push({
|
|
437
|
+
id: row.id,
|
|
438
|
+
title: row.title,
|
|
439
|
+
type: 'knowledge',
|
|
440
|
+
relation: relType,
|
|
441
|
+
depth: 1,
|
|
442
|
+
});
|
|
329
443
|
}
|
|
330
444
|
}
|
|
331
445
|
}
|
|
332
|
-
} catch {
|
|
446
|
+
} catch {
|
|
447
|
+
/* ignore */
|
|
448
|
+
}
|
|
333
449
|
}
|
|
334
450
|
return impacted;
|
|
335
|
-
} catch {
|
|
451
|
+
} catch {
|
|
452
|
+
return [];
|
|
453
|
+
}
|
|
336
454
|
}
|
|
337
455
|
|
|
338
456
|
// ─── graph_path — 路径查找 ─────────────────────────────────
|
|
339
457
|
|
|
340
458
|
export async function graphPath(ctx, args) {
|
|
341
|
-
if (!args.fromId || !args.toId)
|
|
459
|
+
if (!args.fromId || !args.toId) {
|
|
460
|
+
throw new Error('fromId and toId are required');
|
|
461
|
+
}
|
|
342
462
|
const graphService = ctx.container.get('knowledgeGraphService');
|
|
343
463
|
if (!graphService) {
|
|
344
|
-
return envelope({
|
|
464
|
+
return envelope({
|
|
465
|
+
success: false,
|
|
466
|
+
message: 'KnowledgeGraphService not available',
|
|
467
|
+
meta: { tool: 'autosnippet_graph' },
|
|
468
|
+
});
|
|
345
469
|
}
|
|
346
470
|
const fromType = args.fromType || 'recipe';
|
|
347
471
|
const toType = args.toType || 'recipe';
|
|
@@ -353,7 +477,11 @@ export async function graphPath(ctx, args) {
|
|
|
353
477
|
if (err.message?.includes('no such table')) {
|
|
354
478
|
// 降级:用 relations 字段做单跳查找
|
|
355
479
|
result = await _fallbackPathFromRecipe(ctx, args.fromId, args.toId);
|
|
356
|
-
return envelope({
|
|
480
|
+
return envelope({
|
|
481
|
+
success: true,
|
|
482
|
+
data: result,
|
|
483
|
+
meta: { tool: 'autosnippet_graph', source: 'relations-fallback' },
|
|
484
|
+
});
|
|
357
485
|
}
|
|
358
486
|
throw err;
|
|
359
487
|
}
|
|
@@ -367,23 +495,36 @@ async function _fallbackPathFromRecipe(ctx, fromId, toId) {
|
|
|
367
495
|
try {
|
|
368
496
|
const knowledgeService = ctx.container.get('knowledgeService');
|
|
369
497
|
const entry = await knowledgeService.get(fromId);
|
|
370
|
-
if (!entry)
|
|
498
|
+
if (!entry) {
|
|
499
|
+
return { found: false, path: [], depth: -1 };
|
|
500
|
+
}
|
|
371
501
|
|
|
372
|
-
const relJson =
|
|
502
|
+
const relJson =
|
|
503
|
+
typeof entry.relations?.toJSON === 'function'
|
|
504
|
+
? entry.relations.toJSON()
|
|
505
|
+
: entry.relations || {};
|
|
373
506
|
for (const [relType, targets] of Object.entries(relJson)) {
|
|
374
|
-
for (const t of
|
|
507
|
+
for (const t of Array.isArray(targets) ? targets : []) {
|
|
375
508
|
const targetId = t.target || t.id || t;
|
|
376
509
|
if (targetId === toId) {
|
|
377
510
|
return {
|
|
378
511
|
found: true,
|
|
379
|
-
path: [
|
|
512
|
+
path: [
|
|
513
|
+
{
|
|
514
|
+
from: { id: fromId, type: 'knowledge' },
|
|
515
|
+
to: { id: toId, type: 'knowledge' },
|
|
516
|
+
relation: relType,
|
|
517
|
+
},
|
|
518
|
+
],
|
|
380
519
|
depth: 1,
|
|
381
520
|
};
|
|
382
521
|
}
|
|
383
522
|
}
|
|
384
523
|
}
|
|
385
524
|
return { found: false, path: [], depth: -1 };
|
|
386
|
-
} catch {
|
|
525
|
+
} catch {
|
|
526
|
+
return { found: false, path: [], depth: -1 };
|
|
527
|
+
}
|
|
387
528
|
}
|
|
388
529
|
|
|
389
530
|
// ─── graph_stats — 图谱统计 ────────────────────────────────
|
|
@@ -391,14 +532,27 @@ async function _fallbackPathFromRecipe(ctx, fromId, toId) {
|
|
|
391
532
|
export async function graphStats(ctx) {
|
|
392
533
|
const graphService = ctx.container.get('knowledgeGraphService');
|
|
393
534
|
if (!graphService) {
|
|
394
|
-
return envelope({
|
|
535
|
+
return envelope({
|
|
536
|
+
success: false,
|
|
537
|
+
message: 'KnowledgeGraphService not available',
|
|
538
|
+
meta: { tool: 'autosnippet_graph' },
|
|
539
|
+
});
|
|
395
540
|
}
|
|
396
541
|
let stats;
|
|
397
542
|
try {
|
|
398
543
|
stats = graphService.getStats();
|
|
399
544
|
} catch (err) {
|
|
400
545
|
if (err.message?.includes('no such table')) {
|
|
401
|
-
return envelope({
|
|
546
|
+
return envelope({
|
|
547
|
+
success: true,
|
|
548
|
+
data: {
|
|
549
|
+
totalEdges: 0,
|
|
550
|
+
byRelation: {},
|
|
551
|
+
nodeTypes: [],
|
|
552
|
+
note: 'knowledge_edges 表不存在,请运行数据库迁移',
|
|
553
|
+
},
|
|
554
|
+
meta: { tool: 'autosnippet_graph' },
|
|
555
|
+
});
|
|
402
556
|
}
|
|
403
557
|
throw err;
|
|
404
558
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { envelope } from '../envelope.js';
|
|
9
|
-
import {
|
|
9
|
+
import { TIER_ORDER, TOOL_GATEWAY_MAP, TOOLS } from '../tools.js';
|
|
10
10
|
|
|
11
11
|
export async function health(ctx) {
|
|
12
12
|
const checks = { database: false, gateway: false, vectorStore: false };
|
|
@@ -31,24 +31,36 @@ export async function health(ctx) {
|
|
|
31
31
|
// 知识库统计(轻量聚合查询)
|
|
32
32
|
try {
|
|
33
33
|
// V3: knowledge_entries 统一表(lifecycle 替代 status)
|
|
34
|
-
const rStats = db
|
|
34
|
+
const rStats = db
|
|
35
|
+
.prepare(`
|
|
35
36
|
SELECT COUNT(*) as total,
|
|
36
37
|
SUM(CASE WHEN lifecycle='active' THEN 1 ELSE 0 END) as active,
|
|
37
38
|
SUM(CASE WHEN kind='rule' THEN 1 ELSE 0 END) as rules,
|
|
38
39
|
SUM(CASE WHEN kind='pattern' THEN 1 ELSE 0 END) as patterns,
|
|
39
40
|
SUM(CASE WHEN kind='fact' THEN 1 ELSE 0 END) as facts
|
|
40
41
|
FROM knowledge_entries
|
|
41
|
-
`)
|
|
42
|
-
|
|
42
|
+
`)
|
|
43
|
+
.get();
|
|
44
|
+
const cPending = db
|
|
45
|
+
.prepare(`
|
|
43
46
|
SELECT COUNT(*) as total,
|
|
44
47
|
SUM(CASE WHEN lifecycle='pending' THEN 1 ELSE 0 END) as pending
|
|
45
48
|
FROM knowledge_entries
|
|
46
|
-
`)
|
|
49
|
+
`)
|
|
50
|
+
.get();
|
|
47
51
|
knowledgeBase = {
|
|
48
|
-
recipes: {
|
|
52
|
+
recipes: {
|
|
53
|
+
total: rStats.total,
|
|
54
|
+
active: rStats.active,
|
|
55
|
+
rules: rStats.rules,
|
|
56
|
+
patterns: rStats.patterns,
|
|
57
|
+
facts: rStats.facts,
|
|
58
|
+
},
|
|
49
59
|
candidates: { total: cPending.total, pending: cPending.pending },
|
|
50
60
|
};
|
|
51
|
-
} catch {
|
|
61
|
+
} catch {
|
|
62
|
+
/* 统计查询失败不影响 health */
|
|
63
|
+
}
|
|
52
64
|
}
|
|
53
65
|
} catch (e) {
|
|
54
66
|
issues.push(`database: ${e.message}`);
|
|
@@ -70,7 +82,9 @@ export async function health(ctx) {
|
|
|
70
82
|
checks.vectorStore = true;
|
|
71
83
|
if (vsStats) {
|
|
72
84
|
knowledgeBase = knowledgeBase || {};
|
|
73
|
-
knowledgeBase.vectorIndex = {
|
|
85
|
+
knowledgeBase.vectorIndex = {
|
|
86
|
+
documentCount: vsStats.documentCount ?? vsStats.totalDocuments ?? 0,
|
|
87
|
+
};
|
|
74
88
|
}
|
|
75
89
|
}
|
|
76
90
|
} catch (e) {
|
|
@@ -135,9 +149,9 @@ export function capabilities() {
|
|
|
135
149
|
// 根据当前 tier 决定可见工具
|
|
136
150
|
const tierName = process.env.ASD_MCP_TIER || 'agent';
|
|
137
151
|
const maxTier = TIER_ORDER[tierName] ?? TIER_ORDER.agent;
|
|
138
|
-
const visibleTools = TOOLS.filter(t => (TIER_ORDER[t.tier || 'agent'] ?? 0) <= maxTier);
|
|
152
|
+
const visibleTools = TOOLS.filter((t) => (TIER_ORDER[t.tier || 'agent'] ?? 0) <= maxTier);
|
|
139
153
|
|
|
140
|
-
const tools = visibleTools.map(t => {
|
|
154
|
+
const tools = visibleTools.map((t) => {
|
|
141
155
|
const props = t.inputSchema.properties || {};
|
|
142
156
|
const requiredSet = new Set(t.inputSchema.required || []);
|
|
143
157
|
const params = Object.entries(props).map(([key, schema]) => ({
|
|
@@ -185,9 +199,25 @@ export function capabilities() {
|
|
|
185
199
|
byCategory,
|
|
186
200
|
tools,
|
|
187
201
|
workflows: [
|
|
188
|
-
{
|
|
202
|
+
{
|
|
203
|
+
name: '知识查询',
|
|
204
|
+
steps: [
|
|
205
|
+
'search(推荐首选,auto mode 融合)',
|
|
206
|
+
'knowledge op=get',
|
|
207
|
+
'knowledge op=confirm_usage',
|
|
208
|
+
],
|
|
209
|
+
tips: '精确匹配用 mode=keyword,需意图+会话上下文用 mode=context',
|
|
210
|
+
},
|
|
189
211
|
{ name: '单条知识提交', steps: ['submit_knowledge(内置校验+去重)'] },
|
|
190
|
-
{
|
|
212
|
+
{
|
|
213
|
+
name: '批量 Target 扫描',
|
|
214
|
+
steps: [
|
|
215
|
+
'structure op=targets',
|
|
216
|
+
'structure op=files',
|
|
217
|
+
'(Agent 分析)',
|
|
218
|
+
'submit_knowledge_batch',
|
|
219
|
+
],
|
|
220
|
+
},
|
|
191
221
|
{ name: '冷启动', steps: ['bootstrap op=knowledge', 'bootstrap op=refine'] },
|
|
192
222
|
{ name: '代码审计', steps: ['guard (code/files)', 'knowledge op=list kind=rule'] },
|
|
193
223
|
],
|