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
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
* 构建 target 级依赖 DAG,支持层级计算、拓扑排序、可达性检查
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import Logger from '
|
|
7
|
+
import Logger from '../../../infrastructure/logging/Logger.js';
|
|
8
8
|
|
|
9
9
|
export class DependencyGraph {
|
|
10
|
-
#adjacency;
|
|
11
|
-
#reverseAdj;
|
|
12
|
-
#nodes;
|
|
10
|
+
#adjacency; // Map<string, Set<string>>
|
|
11
|
+
#reverseAdj; // Map<string, Set<string>>
|
|
12
|
+
#nodes; // Set<string>
|
|
13
13
|
#logger;
|
|
14
14
|
|
|
15
15
|
constructor() {
|
|
@@ -31,7 +31,9 @@ export class DependencyGraph {
|
|
|
31
31
|
this.addEdge(target.name, dep);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
this.#logger.debug(
|
|
34
|
+
this.#logger.debug(
|
|
35
|
+
`[DependencyGraph] built: ${this.#nodes.size} nodes, ${this.edgeCount()} edges`
|
|
36
|
+
);
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
/**
|
|
@@ -39,8 +41,12 @@ export class DependencyGraph {
|
|
|
39
41
|
*/
|
|
40
42
|
addNode(name) {
|
|
41
43
|
this.#nodes.add(name);
|
|
42
|
-
if (!this.#adjacency.has(name))
|
|
43
|
-
|
|
44
|
+
if (!this.#adjacency.has(name)) {
|
|
45
|
+
this.#adjacency.set(name, new Set());
|
|
46
|
+
}
|
|
47
|
+
if (!this.#reverseAdj.has(name)) {
|
|
48
|
+
this.#reverseAdj.set(name, new Set());
|
|
49
|
+
}
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
/**
|
|
@@ -57,13 +63,19 @@ export class DependencyGraph {
|
|
|
57
63
|
* BFS 可达性检查
|
|
58
64
|
*/
|
|
59
65
|
isReachable(from, to) {
|
|
60
|
-
if (from === to)
|
|
66
|
+
if (from === to) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
61
69
|
const visited = new Set();
|
|
62
70
|
const queue = [from];
|
|
63
71
|
while (queue.length > 0) {
|
|
64
72
|
const node = queue.shift();
|
|
65
|
-
if (node === to)
|
|
66
|
-
|
|
73
|
+
if (node === to) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
if (visited.has(node)) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
67
79
|
visited.add(node);
|
|
68
80
|
for (const neighbor of this.#adjacency.get(node) || []) {
|
|
69
81
|
queue.push(neighbor);
|
|
@@ -103,7 +115,9 @@ export class DependencyGraph {
|
|
|
103
115
|
};
|
|
104
116
|
|
|
105
117
|
for (const node of this.#nodes) {
|
|
106
|
-
if (white.has(node))
|
|
118
|
+
if (white.has(node)) {
|
|
119
|
+
dfs(node);
|
|
120
|
+
}
|
|
107
121
|
}
|
|
108
122
|
return cycles;
|
|
109
123
|
}
|
|
@@ -114,7 +128,9 @@ export class DependencyGraph {
|
|
|
114
128
|
*/
|
|
115
129
|
topologicalSort() {
|
|
116
130
|
const inDegree = new Map();
|
|
117
|
-
for (const node of this.#nodes)
|
|
131
|
+
for (const node of this.#nodes) {
|
|
132
|
+
inDegree.set(node, 0);
|
|
133
|
+
}
|
|
118
134
|
for (const [, deps] of this.#adjacency) {
|
|
119
135
|
for (const dep of deps) {
|
|
120
136
|
inDegree.set(dep, (inDegree.get(dep) || 0) + 1);
|
|
@@ -123,7 +139,9 @@ export class DependencyGraph {
|
|
|
123
139
|
|
|
124
140
|
const queue = [];
|
|
125
141
|
for (const [node, degree] of inDegree) {
|
|
126
|
-
if (degree === 0)
|
|
142
|
+
if (degree === 0) {
|
|
143
|
+
queue.push(node);
|
|
144
|
+
}
|
|
127
145
|
}
|
|
128
146
|
|
|
129
147
|
const result = [];
|
|
@@ -132,7 +150,9 @@ export class DependencyGraph {
|
|
|
132
150
|
result.push(node);
|
|
133
151
|
for (const dep of this.#adjacency.get(node) || []) {
|
|
134
152
|
inDegree.set(dep, inDegree.get(dep) - 1);
|
|
135
|
-
if (inDegree.get(dep) === 0)
|
|
153
|
+
if (inDegree.get(dep) === 0) {
|
|
154
|
+
queue.push(dep);
|
|
155
|
+
}
|
|
136
156
|
}
|
|
137
157
|
}
|
|
138
158
|
|
|
@@ -155,7 +175,7 @@ export class DependencyGraph {
|
|
|
155
175
|
} else {
|
|
156
176
|
let maxDepLevel = 0;
|
|
157
177
|
for (const dep of deps) {
|
|
158
|
-
maxDepLevel = Math.max(maxDepLevel,
|
|
178
|
+
maxDepLevel = Math.max(maxDepLevel, levels.get(dep) || 0);
|
|
159
179
|
}
|
|
160
180
|
levels.set(node, maxDepLevel + 1);
|
|
161
181
|
}
|
|
@@ -187,7 +207,9 @@ export class DependencyGraph {
|
|
|
187
207
|
|
|
188
208
|
edgeCount() {
|
|
189
209
|
let count = 0;
|
|
190
|
-
for (const deps of this.#adjacency.values())
|
|
210
|
+
for (const deps of this.#adjacency.values()) {
|
|
211
|
+
count += deps.size;
|
|
212
|
+
}
|
|
191
213
|
return count;
|
|
192
214
|
}
|
|
193
215
|
|
|
@@ -203,7 +225,9 @@ export class DependencyGraph {
|
|
|
203
225
|
toJSON() {
|
|
204
226
|
const edges = [];
|
|
205
227
|
for (const [from, deps] of this.#adjacency) {
|
|
206
|
-
for (const to of deps)
|
|
228
|
+
for (const to of deps) {
|
|
229
|
+
edges.push({ from, to });
|
|
230
|
+
}
|
|
207
231
|
}
|
|
208
232
|
return { nodes: [...this.#nodes], edges };
|
|
209
233
|
}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* 从 V1 PackageParserV2 迁移,提取包名/版本/targets/dependencies/products/platforms
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import Logger from '
|
|
6
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
import Logger from '../../../infrastructure/logging/Logger.js';
|
|
9
9
|
|
|
10
10
|
export class PackageSwiftParser {
|
|
11
11
|
#projectRoot;
|
|
@@ -25,7 +25,9 @@ export class PackageSwiftParser {
|
|
|
25
25
|
*/
|
|
26
26
|
findPackageSwift(startPath = this.#projectRoot) {
|
|
27
27
|
const cacheKey = `find:${startPath}`;
|
|
28
|
-
if (this.#cache.has(cacheKey))
|
|
28
|
+
if (this.#cache.has(cacheKey)) {
|
|
29
|
+
return this.#cache.get(cacheKey);
|
|
30
|
+
}
|
|
29
31
|
|
|
30
32
|
let dir = startPath;
|
|
31
33
|
for (let i = 0; i < 10; i++) {
|
|
@@ -35,7 +37,9 @@ export class PackageSwiftParser {
|
|
|
35
37
|
return candidate;
|
|
36
38
|
}
|
|
37
39
|
const parent = dirname(dir);
|
|
38
|
-
if (parent === dir)
|
|
40
|
+
if (parent === dir) {
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
39
43
|
dir = parent;
|
|
40
44
|
}
|
|
41
45
|
return null;
|
|
@@ -48,18 +52,32 @@ export class PackageSwiftParser {
|
|
|
48
52
|
*/
|
|
49
53
|
findAllPackageSwifts(rootDir = this.#projectRoot) {
|
|
50
54
|
const cacheKey = `findAll:${rootDir}`;
|
|
51
|
-
if (this.#cache.has(cacheKey))
|
|
55
|
+
if (this.#cache.has(cacheKey)) {
|
|
56
|
+
return this.#cache.get(cacheKey);
|
|
57
|
+
}
|
|
52
58
|
|
|
53
59
|
const results = [];
|
|
54
|
-
const skipDirs = new Set([
|
|
60
|
+
const skipDirs = new Set([
|
|
61
|
+
'node_modules',
|
|
62
|
+
'.git',
|
|
63
|
+
'Build',
|
|
64
|
+
'.build',
|
|
65
|
+
'.swiftpm',
|
|
66
|
+
'Pods',
|
|
67
|
+
'DerivedData',
|
|
68
|
+
]);
|
|
55
69
|
|
|
56
70
|
const scan = (dir, depth = 0) => {
|
|
57
|
-
if (depth > 5)
|
|
71
|
+
if (depth > 5) {
|
|
72
|
+
return; // 限制深度
|
|
73
|
+
}
|
|
58
74
|
try {
|
|
59
75
|
const entries = readdirSync(dir, { withFileTypes: true });
|
|
60
76
|
for (const entry of entries) {
|
|
61
77
|
if (entry.isDirectory()) {
|
|
62
|
-
if (skipDirs.has(entry.name))
|
|
78
|
+
if (skipDirs.has(entry.name)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
63
81
|
scan(join(dir, entry.name), depth + 1);
|
|
64
82
|
} else if (entry.name === 'Package.swift') {
|
|
65
83
|
results.push(join(dir, entry.name));
|
|
@@ -96,7 +114,9 @@ export class PackageSwiftParser {
|
|
|
96
114
|
platforms: this.#extractPlatforms(content),
|
|
97
115
|
};
|
|
98
116
|
|
|
99
|
-
this.#logger.debug(
|
|
117
|
+
this.#logger.debug(
|
|
118
|
+
`[PackageSwiftParser] 解析完成: ${result.name} (${result.targets.length} targets)`
|
|
119
|
+
);
|
|
100
120
|
return result;
|
|
101
121
|
}
|
|
102
122
|
|
|
@@ -158,15 +178,20 @@ export class PackageSwiftParser {
|
|
|
158
178
|
let endPos = startPos;
|
|
159
179
|
|
|
160
180
|
while (depth > 0 && endPos < content.length) {
|
|
161
|
-
if (content[endPos] === '(')
|
|
162
|
-
|
|
181
|
+
if (content[endPos] === '(') {
|
|
182
|
+
depth++;
|
|
183
|
+
} else if (content[endPos] === ')') {
|
|
184
|
+
depth--;
|
|
185
|
+
}
|
|
163
186
|
endPos++;
|
|
164
187
|
}
|
|
165
188
|
|
|
166
189
|
if (depth === 0) {
|
|
167
190
|
const block = content.substring(startPos, endPos - 1);
|
|
168
191
|
const nameMatch = block.match(/name\s*:\s*"([^"]+)"/);
|
|
169
|
-
if (!nameMatch)
|
|
192
|
+
if (!nameMatch) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
170
195
|
|
|
171
196
|
const pathMatch = block.match(/path\s*:\s*"([^"]+)"/);
|
|
172
197
|
const depsMatch = block.match(/dependencies\s*:\s*\[([^\]]*)\]/s);
|
|
@@ -174,7 +199,9 @@ export class PackageSwiftParser {
|
|
|
174
199
|
if (depsMatch) {
|
|
175
200
|
const depRe = /\.(?:product|target)\s*\(\s*name\s*:\s*"([^"]+)"/g;
|
|
176
201
|
let dm;
|
|
177
|
-
while ((dm = depRe.exec(depsMatch[1])) !== null)
|
|
202
|
+
while ((dm = depRe.exec(depsMatch[1])) !== null) {
|
|
203
|
+
deps.push(dm[1]);
|
|
204
|
+
}
|
|
178
205
|
}
|
|
179
206
|
|
|
180
207
|
targets.push({
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export class PolicyEngine {
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* 全面策略检查
|
|
10
9
|
* @param {import('./DependencyGraph.js').DependencyGraph} graph
|
|
@@ -32,11 +31,15 @@ export class PolicyEngine {
|
|
|
32
31
|
|
|
33
32
|
for (const node of graph.getNodes()) {
|
|
34
33
|
const nodeLayer = this.#findLayer(node, layerIndex);
|
|
35
|
-
if (nodeLayer === -1)
|
|
34
|
+
if (nodeLayer === -1) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
36
37
|
|
|
37
38
|
for (const dep of graph.getDependencies(node)) {
|
|
38
39
|
const depLayer = this.#findLayer(dep, layerIndex);
|
|
39
|
-
if (depLayer === -1)
|
|
40
|
+
if (depLayer === -1) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
40
43
|
|
|
41
44
|
if (depLayer > nodeLayer) {
|
|
42
45
|
violations.push({
|
|
@@ -79,7 +82,9 @@ export class PolicyEngine {
|
|
|
79
82
|
#findLayer(nodeName, layerIndex) {
|
|
80
83
|
// 尝试精确匹配或前缀匹配
|
|
81
84
|
for (const [layer, idx] of layerIndex) {
|
|
82
|
-
if (nodeName === layer || nodeName.startsWith(layer))
|
|
85
|
+
if (nodeName === layer || nodeName.startsWith(layer)) {
|
|
86
|
+
return idx;
|
|
87
|
+
}
|
|
83
88
|
}
|
|
84
89
|
return -1;
|
|
85
90
|
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module SpmDiscoverer
|
|
3
|
+
* @description 包装现有 SpmService,适配 ProjectDiscoverer 接口
|
|
4
|
+
*
|
|
5
|
+
* 检测: 项目根或子目录存在 Package.swift
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
9
|
+
import { basename, join, relative } from 'node:path';
|
|
10
|
+
import { LanguageService } from '../../../shared/LanguageService.js';
|
|
11
|
+
import { ProjectDiscoverer } from '../../../core/discovery/ProjectDiscoverer.js';
|
|
12
|
+
|
|
13
|
+
export class SpmDiscoverer extends ProjectDiscoverer {
|
|
14
|
+
/** @type {import('./SpmService.js').SpmService|null} */
|
|
15
|
+
#spm = null;
|
|
16
|
+
#projectRoot = null;
|
|
17
|
+
|
|
18
|
+
get id() {
|
|
19
|
+
return 'spm';
|
|
20
|
+
}
|
|
21
|
+
get displayName() {
|
|
22
|
+
return 'Swift Package Manager (SPM)';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async detect(projectRoot) {
|
|
26
|
+
// 检查项目根是否有 Package.swift
|
|
27
|
+
const hasRoot = existsSync(join(projectRoot, 'Package.swift'));
|
|
28
|
+
if (hasRoot) {
|
|
29
|
+
return { match: true, confidence: 0.95, reason: 'Package.swift found at project root' };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 检查子目录是否有 Package.swift(多包项目)
|
|
33
|
+
try {
|
|
34
|
+
const entries = readdirSync(projectRoot, { withFileTypes: true });
|
|
35
|
+
for (const entry of entries) {
|
|
36
|
+
if (entry.isDirectory() && !entry.name.startsWith('.')) {
|
|
37
|
+
if (existsSync(join(projectRoot, entry.name, 'Package.swift'))) {
|
|
38
|
+
return {
|
|
39
|
+
match: true,
|
|
40
|
+
confidence: 0.85,
|
|
41
|
+
reason: `Package.swift found in ${entry.name}/`,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
} catch {
|
|
47
|
+
/* ignore */
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return { match: false, confidence: 0, reason: 'No Package.swift found' };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async load(projectRoot) {
|
|
54
|
+
this.#projectRoot = projectRoot;
|
|
55
|
+
// 动态加载 SpmService(避免循环导入)
|
|
56
|
+
const { SpmService } = await import('./SpmService.js');
|
|
57
|
+
this.#spm = new SpmService(projectRoot);
|
|
58
|
+
await this.#spm.load();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async listTargets() {
|
|
62
|
+
if (!this.#spm) {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
const rawTargets = await this.#spm.listTargets();
|
|
66
|
+
return rawTargets.map((t) => {
|
|
67
|
+
const name = typeof t === 'string' ? t : t.name;
|
|
68
|
+
return {
|
|
69
|
+
name,
|
|
70
|
+
path: typeof t === 'object' ? t.path || this.#projectRoot : this.#projectRoot,
|
|
71
|
+
type: typeof t === 'object' ? t.type || 'library' : 'library',
|
|
72
|
+
language: 'swift',
|
|
73
|
+
metadata: typeof t === 'object' ? t : { name },
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async getTargetFiles(target) {
|
|
79
|
+
if (!this.#spm) {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
const targetName = typeof target === 'string' ? target : target.name;
|
|
83
|
+
const fileList = await this.#spm.getTargetFiles(targetName);
|
|
84
|
+
return fileList.map((f) => {
|
|
85
|
+
const fp = typeof f === 'string' ? f : f.path;
|
|
86
|
+
const lang = this.#inferLang(fp);
|
|
87
|
+
return {
|
|
88
|
+
name: typeof f === 'object' ? f.name || basename(fp) : basename(fp),
|
|
89
|
+
path: fp,
|
|
90
|
+
relativePath:
|
|
91
|
+
typeof f === 'object'
|
|
92
|
+
? f.relativePath || relative(this.#projectRoot, fp)
|
|
93
|
+
: relative(this.#projectRoot, fp),
|
|
94
|
+
language: lang,
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async getDependencyGraph() {
|
|
100
|
+
if (!this.#spm) {
|
|
101
|
+
return { nodes: [], edges: [] };
|
|
102
|
+
}
|
|
103
|
+
const raw = await this.#spm.getDependencyGraph();
|
|
104
|
+
return {
|
|
105
|
+
nodes: (raw.nodes || []).map((n) => (typeof n === 'string' ? n : n.id || n.name)),
|
|
106
|
+
edges: (raw.edges || []).map((e) => ({
|
|
107
|
+
from: e.from,
|
|
108
|
+
to: e.to,
|
|
109
|
+
type: 'depends_on',
|
|
110
|
+
})),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** 获取底层 SpmService(向后兼容) */
|
|
115
|
+
getSpmService() {
|
|
116
|
+
return this.#spm;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
#inferLang(filePath) {
|
|
120
|
+
return LanguageService.inferLang(filePath);
|
|
121
|
+
}
|
|
122
|
+
}
|