autosnippet 3.0.0 → 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 +759 -243
- 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
|
@@ -8,13 +8,19 @@ import path from 'node:path';
|
|
|
8
8
|
import { envelope } from '../envelope.js';
|
|
9
9
|
|
|
10
10
|
export async function guardCheck(ctx, args) {
|
|
11
|
-
const { GuardCheckEngine, detectLanguage } = await import(
|
|
11
|
+
const { GuardCheckEngine, detectLanguage } = await import(
|
|
12
|
+
'../../../service/guard/GuardCheckEngine.js'
|
|
13
|
+
);
|
|
12
14
|
|
|
13
15
|
// 输入校验:空代码直接返回
|
|
14
16
|
if (!args.code || !args.code.trim()) {
|
|
15
17
|
return envelope({
|
|
16
18
|
success: true,
|
|
17
|
-
data: {
|
|
19
|
+
data: {
|
|
20
|
+
language: args.language || 'unknown',
|
|
21
|
+
violations: [],
|
|
22
|
+
summary: { total: 0, errors: 0, warnings: 0 },
|
|
23
|
+
},
|
|
18
24
|
meta: { tool: 'autosnippet_guard', note: 'Empty code — skipped' },
|
|
19
25
|
});
|
|
20
26
|
}
|
|
@@ -30,10 +36,14 @@ export async function guardCheck(ctx, args) {
|
|
|
30
36
|
if (skillHooks.has('onGuardCheck')) {
|
|
31
37
|
for (let i = 0; i < violations.length; i++) {
|
|
32
38
|
const modified = await skillHooks.run('onGuardCheck', violations[i], { language });
|
|
33
|
-
if (modified && typeof modified === 'object')
|
|
39
|
+
if (modified && typeof modified === 'object') {
|
|
40
|
+
violations[i] = modified;
|
|
41
|
+
}
|
|
34
42
|
}
|
|
35
43
|
}
|
|
36
|
-
} catch {
|
|
44
|
+
} catch {
|
|
45
|
+
/* skillHooks not available */
|
|
46
|
+
}
|
|
37
47
|
|
|
38
48
|
const warnings = [];
|
|
39
49
|
if (language === 'unknown') {
|
|
@@ -42,7 +52,16 @@ export async function guardCheck(ctx, args) {
|
|
|
42
52
|
|
|
43
53
|
return envelope({
|
|
44
54
|
success: true,
|
|
45
|
-
data: {
|
|
55
|
+
data: {
|
|
56
|
+
language,
|
|
57
|
+
violations,
|
|
58
|
+
summary: {
|
|
59
|
+
total: violations.length,
|
|
60
|
+
errors: violations.filter((v) => v.severity === 'error').length,
|
|
61
|
+
warnings: violations.filter((v) => v.severity === 'warning').length,
|
|
62
|
+
},
|
|
63
|
+
...(warnings.length ? { warnings } : {}),
|
|
64
|
+
},
|
|
46
65
|
meta: { tool: 'autosnippet_guard' },
|
|
47
66
|
});
|
|
48
67
|
}
|
|
@@ -58,7 +77,7 @@ export async function guardAuditFiles(ctx, args) {
|
|
|
58
77
|
const engine = new GuardCheckEngine(db);
|
|
59
78
|
|
|
60
79
|
// 补充缺失的 content(从磁盘读取)
|
|
61
|
-
const filesToAudit = args.files.map(f => ({
|
|
80
|
+
const filesToAudit = args.files.map((f) => ({
|
|
62
81
|
path: f.path,
|
|
63
82
|
content: f.content || (fs.existsSync(f.path) ? fs.readFileSync(f.path, 'utf8') : ''),
|
|
64
83
|
}));
|
|
@@ -68,7 +87,7 @@ export async function guardAuditFiles(ctx, args) {
|
|
|
68
87
|
// 写入 ViolationsStore + GuardFeedbackLoop
|
|
69
88
|
try {
|
|
70
89
|
const violationsStore = ctx.container.get('violationsStore');
|
|
71
|
-
for (const fileResult of
|
|
90
|
+
for (const fileResult of result.files || []) {
|
|
72
91
|
if (fileResult.violations.length > 0) {
|
|
73
92
|
violationsStore.appendRun({
|
|
74
93
|
filePath: fileResult.filePath,
|
|
@@ -81,21 +100,27 @@ export async function guardAuditFiles(ctx, args) {
|
|
|
81
100
|
try {
|
|
82
101
|
const feedbackLoop = ctx.container.get('guardFeedbackLoop');
|
|
83
102
|
feedbackLoop.processFixDetection(fileResult, fileResult.filePath);
|
|
84
|
-
} catch {
|
|
103
|
+
} catch {
|
|
104
|
+
/* guardFeedbackLoop not available */
|
|
105
|
+
}
|
|
85
106
|
}
|
|
86
|
-
} catch {
|
|
107
|
+
} catch {
|
|
108
|
+
/* ViolationsStore not available */
|
|
109
|
+
}
|
|
87
110
|
|
|
88
111
|
return envelope({
|
|
89
112
|
success: true,
|
|
90
113
|
data: {
|
|
91
114
|
summary: result.summary,
|
|
92
|
-
files: result.files.map(f => ({
|
|
115
|
+
files: result.files.map((f) => ({
|
|
93
116
|
filePath: f.filePath,
|
|
94
117
|
language: f.language,
|
|
95
118
|
violations: f.violations,
|
|
96
119
|
summary: f.summary,
|
|
97
120
|
})),
|
|
98
|
-
...(result.crossFileViolations?.length
|
|
121
|
+
...(result.crossFileViolations?.length
|
|
122
|
+
? { crossFileViolations: result.crossFileViolations }
|
|
123
|
+
: {}),
|
|
99
124
|
},
|
|
100
125
|
meta: { tool: 'autosnippet_guard' },
|
|
101
126
|
});
|
|
@@ -107,13 +132,25 @@ export async function scanProject(ctx, args) {
|
|
|
107
132
|
const contentMaxLines = args.contentMaxLines || 100;
|
|
108
133
|
|
|
109
134
|
const projectRoot = process.env.ASD_PROJECT_DIR || process.cwd();
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
135
|
+
|
|
136
|
+
// 优先使用 ModuleService(多语言统一入口),回退到 SpmService
|
|
137
|
+
let service;
|
|
138
|
+
try {
|
|
139
|
+
const { ModuleService } = await import('../../../service/module/ModuleService.js');
|
|
140
|
+
service = new ModuleService(projectRoot);
|
|
141
|
+
} catch {
|
|
142
|
+
const { SpmService } = await import('../../../platform/ios/spm/SpmService.js');
|
|
143
|
+
service = new SpmService(projectRoot);
|
|
144
|
+
}
|
|
145
|
+
await service.load();
|
|
146
|
+
const allTargets = await service.listTargets();
|
|
114
147
|
|
|
115
148
|
if (!allTargets || allTargets.length === 0) {
|
|
116
|
-
return envelope({
|
|
149
|
+
return envelope({
|
|
150
|
+
success: true,
|
|
151
|
+
data: { targets: [], files: [], guardAudit: null, message: 'No module targets found' },
|
|
152
|
+
meta: { tool: 'autosnippet_bootstrap' },
|
|
153
|
+
});
|
|
117
154
|
}
|
|
118
155
|
|
|
119
156
|
// 收集所有文件(去重)
|
|
@@ -121,12 +158,19 @@ export async function scanProject(ctx, args) {
|
|
|
121
158
|
const allFiles = [];
|
|
122
159
|
for (const t of allTargets) {
|
|
123
160
|
try {
|
|
124
|
-
const fileList = await
|
|
161
|
+
const fileList = await service.getTargetFiles(t);
|
|
125
162
|
for (const f of fileList) {
|
|
126
163
|
const fp = typeof f === 'string' ? f : f.path;
|
|
127
|
-
if (seenPaths.has(fp))
|
|
164
|
+
if (seenPaths.has(fp)) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
128
167
|
seenPaths.add(fp);
|
|
129
|
-
const entry = {
|
|
168
|
+
const entry = {
|
|
169
|
+
name: f.name || path.basename(fp),
|
|
170
|
+
path: fp,
|
|
171
|
+
relativePath: f.relativePath || path.basename(fp),
|
|
172
|
+
targetName: t.name,
|
|
173
|
+
};
|
|
130
174
|
if (includeContent) {
|
|
131
175
|
try {
|
|
132
176
|
const raw = fs.readFileSync(fp, 'utf8');
|
|
@@ -134,13 +178,22 @@ export async function scanProject(ctx, args) {
|
|
|
134
178
|
entry.content = lines.slice(0, contentMaxLines).join('\n');
|
|
135
179
|
entry.totalLines = lines.length;
|
|
136
180
|
entry.truncated = lines.length > contentMaxLines;
|
|
137
|
-
} catch {
|
|
181
|
+
} catch {
|
|
182
|
+
entry.content = '';
|
|
183
|
+
entry.totalLines = 0;
|
|
184
|
+
}
|
|
138
185
|
}
|
|
139
186
|
allFiles.push(entry);
|
|
140
|
-
if (allFiles.length >= maxFiles)
|
|
187
|
+
if (allFiles.length >= maxFiles) {
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
141
190
|
}
|
|
142
|
-
} catch {
|
|
143
|
-
|
|
191
|
+
} catch {
|
|
192
|
+
/* skip target */
|
|
193
|
+
}
|
|
194
|
+
if (allFiles.length >= maxFiles) {
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
144
197
|
}
|
|
145
198
|
|
|
146
199
|
// Guard 审计
|
|
@@ -150,7 +203,7 @@ export async function scanProject(ctx, args) {
|
|
|
150
203
|
const db = ctx.container.get('database');
|
|
151
204
|
const engine = new GuardCheckEngine(db);
|
|
152
205
|
|
|
153
|
-
const filesToAudit = allFiles.map(f => {
|
|
206
|
+
const filesToAudit = allFiles.map((f) => {
|
|
154
207
|
const content = f.content || (fs.existsSync(f.path) ? fs.readFileSync(f.path, 'utf8') : '');
|
|
155
208
|
return { path: f.path, content };
|
|
156
209
|
});
|
|
@@ -159,7 +212,7 @@ export async function scanProject(ctx, args) {
|
|
|
159
212
|
// 写入 ViolationsStore
|
|
160
213
|
try {
|
|
161
214
|
const violationsStore = ctx.container.get('violationsStore');
|
|
162
|
-
for (const fileResult of
|
|
215
|
+
for (const fileResult of guardAudit.files || []) {
|
|
163
216
|
if (fileResult.violations.length > 0) {
|
|
164
217
|
violationsStore.appendRun({
|
|
165
218
|
filePath: fileResult.filePath,
|
|
@@ -168,34 +221,46 @@ export async function scanProject(ctx, args) {
|
|
|
168
221
|
});
|
|
169
222
|
}
|
|
170
223
|
}
|
|
171
|
-
} catch {
|
|
224
|
+
} catch {
|
|
225
|
+
/* store not available */
|
|
226
|
+
}
|
|
172
227
|
} catch (e) {
|
|
173
228
|
ctx.logger.warn(`[MCP] Guard audit in scanProject failed: ${e.message}`);
|
|
174
229
|
}
|
|
175
230
|
|
|
176
231
|
// 构建文件列表摘要
|
|
177
|
-
const fileSummary = allFiles.map(f => {
|
|
232
|
+
const fileSummary = allFiles.map((f) => {
|
|
178
233
|
const base = { name: f.name, path: f.relativePath, targetName: f.targetName };
|
|
179
|
-
if (includeContent) {
|
|
234
|
+
if (includeContent) {
|
|
235
|
+
base.content = f.content;
|
|
236
|
+
base.totalLines = f.totalLines;
|
|
237
|
+
base.truncated = f.truncated;
|
|
238
|
+
}
|
|
180
239
|
return base;
|
|
181
240
|
});
|
|
182
241
|
|
|
183
242
|
return envelope({
|
|
184
243
|
success: true,
|
|
185
244
|
data: {
|
|
186
|
-
targets: allTargets.map(t => ({ name: t.name, type: t.type, packageName: t.packageName })),
|
|
245
|
+
targets: allTargets.map((t) => ({ name: t.name, type: t.type, packageName: t.packageName })),
|
|
187
246
|
files: fileSummary,
|
|
188
247
|
fileCount: allFiles.length,
|
|
189
|
-
guardAudit: guardAudit
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
248
|
+
guardAudit: guardAudit
|
|
249
|
+
? {
|
|
250
|
+
summary: guardAudit.summary,
|
|
251
|
+
filesWithViolations: (guardAudit.files || [])
|
|
252
|
+
.filter((f) => f.violations.length > 0)
|
|
253
|
+
.map((f) => ({
|
|
254
|
+
filePath: f.filePath,
|
|
255
|
+
language: f.language,
|
|
256
|
+
violations: f.violations,
|
|
257
|
+
summary: f.summary,
|
|
258
|
+
})),
|
|
259
|
+
...(guardAudit.crossFileViolations?.length
|
|
260
|
+
? { crossFileViolations: guardAudit.crossFileViolations }
|
|
261
|
+
: {}),
|
|
262
|
+
}
|
|
263
|
+
: null,
|
|
199
264
|
},
|
|
200
265
|
meta: { tool: 'autosnippet_bootstrap' },
|
|
201
266
|
});
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* submitKnowledge, submitKnowledgeBatch, knowledgeLifecycle
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { envelope } from '../envelope.js';
|
|
7
6
|
import { checkRecipeReadiness } from '../../../shared/RecipeReadinessChecker.js';
|
|
7
|
+
import { envelope } from '../envelope.js';
|
|
8
8
|
|
|
9
9
|
// ─── 限流 ──────────────────────────────────────────────────
|
|
10
10
|
|
|
@@ -36,7 +36,9 @@ function _enrichToV3(args, container) {
|
|
|
36
36
|
const data = { ...args };
|
|
37
37
|
|
|
38
38
|
// 来源标记(非 Cursor 职责)
|
|
39
|
-
if (!data.source)
|
|
39
|
+
if (!data.source) {
|
|
40
|
+
data.source = 'mcp';
|
|
41
|
+
}
|
|
40
42
|
|
|
41
43
|
// QualityScorer 评分(程序化)
|
|
42
44
|
try {
|
|
@@ -55,7 +57,9 @@ function _enrichToV3(args, container) {
|
|
|
55
57
|
grade: scoreResult.grade || '',
|
|
56
58
|
};
|
|
57
59
|
}
|
|
58
|
-
} catch {
|
|
60
|
+
} catch {
|
|
61
|
+
/* best effort */
|
|
62
|
+
}
|
|
59
63
|
|
|
60
64
|
// RecipeExtractor 语义标签(程序化)
|
|
61
65
|
try {
|
|
@@ -64,17 +68,25 @@ function _enrichToV3(args, container) {
|
|
|
64
68
|
const codeForTags = data.content?.pattern || '';
|
|
65
69
|
if (codeForTags) {
|
|
66
70
|
const extracted = recipeExtractor.extractFromContent(
|
|
67
|
-
codeForTags,
|
|
71
|
+
codeForTags,
|
|
72
|
+
`${data.title || 'unknown'}.${data.language || 'unknown'}`,
|
|
73
|
+
''
|
|
68
74
|
);
|
|
69
75
|
if (extracted.semanticTags?.length > 0) {
|
|
70
76
|
data.tags = [...new Set([...(data.tags || []), ...extracted.semanticTags])];
|
|
71
77
|
}
|
|
72
|
-
if (
|
|
78
|
+
if (
|
|
79
|
+
(!data.category || data.category === 'Utility') &&
|
|
80
|
+
extracted.category &&
|
|
81
|
+
extracted.category !== 'general'
|
|
82
|
+
) {
|
|
73
83
|
data.category = extracted.category;
|
|
74
84
|
}
|
|
75
85
|
}
|
|
76
86
|
}
|
|
77
|
-
} catch {
|
|
87
|
+
} catch {
|
|
88
|
+
/* best effort */
|
|
89
|
+
}
|
|
78
90
|
|
|
79
91
|
return data;
|
|
80
92
|
}
|
|
@@ -90,7 +102,9 @@ function _enrichToV3(args, container) {
|
|
|
90
102
|
export async function submitKnowledge(ctx, args) {
|
|
91
103
|
// 限流
|
|
92
104
|
const blocked = await _checkRateLimit('autosnippet_submit_knowledge', args.client_id);
|
|
93
|
-
if (blocked)
|
|
105
|
+
if (blocked) {
|
|
106
|
+
return blocked;
|
|
107
|
+
}
|
|
94
108
|
|
|
95
109
|
const service = ctx.container.get('knowledgeService');
|
|
96
110
|
|
|
@@ -135,23 +149,27 @@ export async function submitKnowledgeBatch(ctx, args) {
|
|
|
135
149
|
|
|
136
150
|
// 限流
|
|
137
151
|
const blocked = await _checkRateLimit('autosnippet_submit_knowledge_batch', args.client_id);
|
|
138
|
-
if (blocked)
|
|
152
|
+
if (blocked) {
|
|
153
|
+
return blocked;
|
|
154
|
+
}
|
|
139
155
|
|
|
140
156
|
// 去重(可选)
|
|
141
157
|
let items = args.items;
|
|
142
158
|
if (args.deduplicate !== false) {
|
|
143
159
|
try {
|
|
144
|
-
const { aggregateCandidates } = await import(
|
|
160
|
+
const { aggregateCandidates } = await import(
|
|
161
|
+
'../../../service/candidate/CandidateAggregator.js'
|
|
162
|
+
);
|
|
145
163
|
// 对 title 字段做去重
|
|
146
|
-
const readinessItems = items.map(it => ({
|
|
164
|
+
const readinessItems = items.map((it) => ({
|
|
147
165
|
...it,
|
|
148
166
|
code: it.content?.pattern || it.code || '',
|
|
149
167
|
}));
|
|
150
168
|
const result = aggregateCandidates(readinessItems);
|
|
151
169
|
// 保留原始 items 顺序中去重后的
|
|
152
170
|
if (result.items && result.items.length < items.length) {
|
|
153
|
-
const titles = new Set(result.items.map(it => it.title));
|
|
154
|
-
items = items.filter(it => titles.has(it.title));
|
|
171
|
+
const titles = new Set(result.items.map((it) => it.title));
|
|
172
|
+
items = items.filter((it) => titles.has(it.title));
|
|
155
173
|
}
|
|
156
174
|
} catch {
|
|
157
175
|
// CandidateAggregator 加载失败时降级:不去重
|
|
@@ -188,11 +206,13 @@ export async function submitKnowledgeBatch(ctx, args) {
|
|
|
188
206
|
}
|
|
189
207
|
|
|
190
208
|
const data = { count, total: items.length, targetName: args.target_name };
|
|
191
|
-
if (itemErrors.length > 0)
|
|
209
|
+
if (itemErrors.length > 0) {
|
|
210
|
+
data.errors = itemErrors;
|
|
211
|
+
}
|
|
192
212
|
|
|
193
213
|
// 被拒绝的条目:告知 Agent 需补齐哪些字段
|
|
194
214
|
if (rejectedItems.length > 0) {
|
|
195
|
-
const allMissing = [...new Set(rejectedItems.flatMap(it => it.missingFields))];
|
|
215
|
+
const allMissing = [...new Set(rejectedItems.flatMap((it) => it.missingFields))];
|
|
196
216
|
data.rejectedItems = rejectedItems;
|
|
197
217
|
data.rejectedSummary = {
|
|
198
218
|
rejectedCount: rejectedItems.length,
|
|
@@ -268,34 +288,36 @@ export async function saveDocument(ctx, args) {
|
|
|
268
288
|
|
|
269
289
|
// 限流
|
|
270
290
|
const blocked = await _checkRateLimit('autosnippet_save_document', args.client_id);
|
|
271
|
-
if (blocked)
|
|
291
|
+
if (blocked) {
|
|
292
|
+
return blocked;
|
|
293
|
+
}
|
|
272
294
|
|
|
273
295
|
const service = ctx.container.get('knowledgeService');
|
|
274
296
|
|
|
275
297
|
const data = {
|
|
276
|
-
title:
|
|
277
|
-
description:
|
|
298
|
+
title: args.title.trim(),
|
|
299
|
+
description: args.description || '',
|
|
278
300
|
knowledgeType: 'dev-document',
|
|
279
|
-
kind:
|
|
280
|
-
source:
|
|
281
|
-
scope:
|
|
282
|
-
tags:
|
|
301
|
+
kind: 'fact',
|
|
302
|
+
source: args.source || 'agent',
|
|
303
|
+
scope: args.scope || 'project-specific',
|
|
304
|
+
tags: args.tags || [],
|
|
283
305
|
content: {
|
|
284
306
|
markdown: args.markdown,
|
|
285
|
-
pattern:
|
|
307
|
+
pattern: '',
|
|
286
308
|
},
|
|
287
309
|
// 文档不需要 Cursor Delivery 字段
|
|
288
|
-
trigger:
|
|
289
|
-
doClause:
|
|
310
|
+
trigger: '',
|
|
311
|
+
doClause: '',
|
|
290
312
|
dontClause: '',
|
|
291
313
|
whenClause: '',
|
|
292
|
-
topicHint:
|
|
293
|
-
coreCode:
|
|
314
|
+
topicHint: '',
|
|
315
|
+
coreCode: '',
|
|
294
316
|
// 基础推理
|
|
295
317
|
reasoning: {
|
|
296
318
|
whyStandard: 'Agent development document — preserved for team knowledge',
|
|
297
|
-
sources:
|
|
298
|
-
confidence:
|
|
319
|
+
sources: ['agent'],
|
|
320
|
+
confidence: 0.8,
|
|
299
321
|
},
|
|
300
322
|
};
|
|
301
323
|
|
|
@@ -311,10 +333,10 @@ export async function saveDocument(ctx, args) {
|
|
|
311
333
|
return envelope({
|
|
312
334
|
success: true,
|
|
313
335
|
data: {
|
|
314
|
-
id:
|
|
336
|
+
id: entry.id,
|
|
315
337
|
lifecycle: 'active',
|
|
316
|
-
title:
|
|
317
|
-
kind:
|
|
338
|
+
title: entry.title,
|
|
339
|
+
kind: 'fact',
|
|
318
340
|
knowledgeType: 'dev-document',
|
|
319
341
|
},
|
|
320
342
|
message: `文档「${entry.title}」已保存到知识库。`,
|
|
@@ -336,11 +358,13 @@ function _toReadinessInput(args) {
|
|
|
336
358
|
trigger: args.trigger,
|
|
337
359
|
description: args.description,
|
|
338
360
|
headers: args.headers,
|
|
339
|
-
reasoning: args.reasoning
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
361
|
+
reasoning: args.reasoning
|
|
362
|
+
? {
|
|
363
|
+
whyStandard: args.reasoning.whyStandard,
|
|
364
|
+
sources: args.reasoning.sources,
|
|
365
|
+
confidence: args.reasoning.confidence,
|
|
366
|
+
}
|
|
367
|
+
: undefined,
|
|
344
368
|
knowledgeType: args.knowledgeType,
|
|
345
369
|
complexity: args.complexity,
|
|
346
370
|
usageGuide: args.usageGuide,
|
|
@@ -50,8 +50,10 @@ function groupByKind(items) {
|
|
|
50
50
|
* 根据 kind 参数过滤 items
|
|
51
51
|
*/
|
|
52
52
|
function filterByKind(items, kind) {
|
|
53
|
-
if (!kind || kind === 'all')
|
|
54
|
-
|
|
53
|
+
if (!kind || kind === 'all') {
|
|
54
|
+
return items;
|
|
55
|
+
}
|
|
56
|
+
return items.filter((it) => (it.kind || it.metadata?.kind || 'pattern') === kind);
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
// ─── 1. autosnippet_search — 统合搜索入口 ─────────────────────
|
|
@@ -64,7 +66,7 @@ function filterByKind(items, kind) {
|
|
|
64
66
|
*/
|
|
65
67
|
export async function search(ctx, args) {
|
|
66
68
|
const t0 = Date.now();
|
|
67
|
-
const engine = getSearchEngine(ctx) || await getFallbackEngine(ctx);
|
|
69
|
+
const engine = getSearchEngine(ctx) || (await getFallbackEngine(ctx));
|
|
68
70
|
const query = args.query;
|
|
69
71
|
const limit = args.limit || 10;
|
|
70
72
|
const kind = args.kind || args.type || 'all';
|
|
@@ -72,7 +74,10 @@ export async function search(ctx, args) {
|
|
|
72
74
|
|
|
73
75
|
// 统一调用 SearchEngine(auto 模式内置 BM25+semantic 融合去重 + Ranking Pipeline)
|
|
74
76
|
const result = await engine.search(query, {
|
|
75
|
-
mode,
|
|
77
|
+
mode,
|
|
78
|
+
limit: kind !== 'all' ? limit * 2 : limit,
|
|
79
|
+
rank: true,
|
|
80
|
+
groupByKind: true,
|
|
76
81
|
});
|
|
77
82
|
let items = result?.items || [];
|
|
78
83
|
const actualMode = result?.mode || mode;
|
|
@@ -93,7 +98,11 @@ export async function search(ctx, args) {
|
|
|
93
98
|
totalResults: items.length,
|
|
94
99
|
items,
|
|
95
100
|
byKind,
|
|
96
|
-
kindCounts: {
|
|
101
|
+
kindCounts: {
|
|
102
|
+
rule: byKind.rule.length,
|
|
103
|
+
pattern: byKind.pattern.length,
|
|
104
|
+
fact: byKind.fact.length,
|
|
105
|
+
},
|
|
97
106
|
},
|
|
98
107
|
meta: { tool: 'autosnippet_search', responseTimeMs: elapsed },
|
|
99
108
|
});
|
|
@@ -111,11 +120,14 @@ export async function search(ctx, args) {
|
|
|
111
120
|
*/
|
|
112
121
|
export async function contextSearch(ctx, args) {
|
|
113
122
|
const t0 = Date.now();
|
|
114
|
-
const engine = getSearchEngine(ctx) || await getFallbackEngine(ctx);
|
|
123
|
+
const engine = getSearchEngine(ctx) || (await getFallbackEngine(ctx));
|
|
115
124
|
const limit = args.limit ?? 5;
|
|
116
125
|
|
|
117
126
|
const result = await engine.search(args.query, {
|
|
118
|
-
mode: 'bm25',
|
|
127
|
+
mode: 'bm25',
|
|
128
|
+
limit,
|
|
129
|
+
rank: true,
|
|
130
|
+
groupByKind: true,
|
|
119
131
|
context: {
|
|
120
132
|
intent: 'search',
|
|
121
133
|
language: args.language,
|
|
@@ -136,7 +148,11 @@ export async function contextSearch(ctx, args) {
|
|
|
136
148
|
metadata: {
|
|
137
149
|
responseTimeMs: elapsed,
|
|
138
150
|
totalResults: items.length,
|
|
139
|
-
kindCounts: {
|
|
151
|
+
kindCounts: {
|
|
152
|
+
rule: byKind.rule.length,
|
|
153
|
+
pattern: byKind.pattern.length,
|
|
154
|
+
fact: byKind.fact.length,
|
|
155
|
+
},
|
|
140
156
|
},
|
|
141
157
|
},
|
|
142
158
|
meta: { tool: 'autosnippet_context_search', source, responseTimeMs: elapsed },
|
|
@@ -154,13 +170,15 @@ export async function contextSearch(ctx, args) {
|
|
|
154
170
|
*/
|
|
155
171
|
export async function keywordSearch(ctx, args) {
|
|
156
172
|
const t0 = Date.now();
|
|
157
|
-
const engine = getSearchEngine(ctx) || await getFallbackEngine(ctx);
|
|
173
|
+
const engine = getSearchEngine(ctx) || (await getFallbackEngine(ctx));
|
|
158
174
|
const query = args.query;
|
|
159
175
|
const limit = args.limit || 10;
|
|
160
176
|
const kind = args.kind || 'all';
|
|
161
177
|
|
|
162
178
|
const result = await engine.search(query, {
|
|
163
|
-
mode: 'keyword',
|
|
179
|
+
mode: 'keyword',
|
|
180
|
+
limit,
|
|
181
|
+
groupByKind: true,
|
|
164
182
|
});
|
|
165
183
|
|
|
166
184
|
let items = result?.items || [];
|
|
@@ -177,7 +195,11 @@ export async function keywordSearch(ctx, args) {
|
|
|
177
195
|
totalResults: items.length,
|
|
178
196
|
items,
|
|
179
197
|
byKind,
|
|
180
|
-
kindCounts: {
|
|
198
|
+
kindCounts: {
|
|
199
|
+
rule: byKind.rule.length,
|
|
200
|
+
pattern: byKind.pattern.length,
|
|
201
|
+
fact: byKind.fact.length,
|
|
202
|
+
},
|
|
181
203
|
},
|
|
182
204
|
meta: { tool: 'autosnippet_keyword_search', responseTimeMs: elapsed },
|
|
183
205
|
});
|
|
@@ -194,13 +216,16 @@ export async function keywordSearch(ctx, args) {
|
|
|
194
216
|
*/
|
|
195
217
|
export async function semanticSearch(ctx, args) {
|
|
196
218
|
const t0 = Date.now();
|
|
197
|
-
const engine = getSearchEngine(ctx) || await getFallbackEngine(ctx);
|
|
219
|
+
const engine = getSearchEngine(ctx) || (await getFallbackEngine(ctx));
|
|
198
220
|
const query = args.query;
|
|
199
221
|
const limit = args.limit || 10;
|
|
200
222
|
const kind = args.kind || 'all';
|
|
201
223
|
|
|
202
224
|
const result = await engine.search(query, {
|
|
203
|
-
mode: 'semantic',
|
|
225
|
+
mode: 'semantic',
|
|
226
|
+
limit: limit * 2,
|
|
227
|
+
rank: true,
|
|
228
|
+
groupByKind: true,
|
|
204
229
|
});
|
|
205
230
|
|
|
206
231
|
let items = result?.items || [];
|
|
@@ -223,7 +248,11 @@ export async function semanticSearch(ctx, args) {
|
|
|
223
248
|
totalResults: items.length,
|
|
224
249
|
items,
|
|
225
250
|
byKind,
|
|
226
|
-
kindCounts: {
|
|
251
|
+
kindCounts: {
|
|
252
|
+
rule: byKind.rule.length,
|
|
253
|
+
pattern: byKind.pattern.length,
|
|
254
|
+
fact: byKind.fact.length,
|
|
255
|
+
},
|
|
227
256
|
},
|
|
228
257
|
meta: { tool: 'autosnippet_semantic_search', responseTimeMs: elapsed },
|
|
229
258
|
});
|