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.
Files changed (290) hide show
  1. package/README.md +230 -324
  2. package/bin/api-server.js +1 -1
  3. package/bin/cli.js +204 -244
  4. package/bin/mcp-server.js +5 -3
  5. package/config/knowledge-base.config.js +132 -132
  6. package/dashboard/dist/assets/{icons-CEfgGaZi.js → icons-Cdq22n2i.js} +95 -100
  7. package/dashboard/dist/assets/index-ClkyPkDX.js +133 -0
  8. package/dashboard/dist/assets/index-t4QrJwv1.css +1 -0
  9. package/dashboard/dist/index.html +3 -3
  10. package/lib/bootstrap.js +8 -8
  11. package/lib/cli/AiScanService.js +86 -40
  12. package/lib/cli/KnowledgeSyncService.js +113 -74
  13. package/lib/cli/SetupService.js +439 -277
  14. package/lib/cli/UpgradeService.js +63 -100
  15. package/lib/core/AstAnalyzer.js +276 -597
  16. package/lib/core/ast/ProjectGraph.js +101 -40
  17. package/lib/core/ast/ensure-grammars.js +232 -0
  18. package/lib/core/ast/index.js +115 -0
  19. package/lib/core/ast/lang-dart.js +661 -0
  20. package/lib/core/ast/lang-go.js +530 -0
  21. package/lib/core/ast/lang-java.js +435 -0
  22. package/lib/core/ast/lang-javascript.js +272 -0
  23. package/lib/core/ast/lang-kotlin.js +423 -0
  24. package/lib/core/ast/lang-objc.js +388 -0
  25. package/lib/core/ast/lang-python.js +371 -0
  26. package/lib/core/ast/lang-swift.js +337 -0
  27. package/lib/core/ast/lang-typescript.js +503 -0
  28. package/lib/core/capability/CapabilityProbe.js +18 -9
  29. package/lib/core/constitution/Constitution.js +2 -3
  30. package/lib/core/constitution/ConstitutionValidator.js +65 -24
  31. package/lib/core/discovery/DartDiscoverer.js +534 -0
  32. package/lib/core/discovery/DiscovererRegistry.js +83 -0
  33. package/lib/core/discovery/GenericDiscoverer.js +225 -0
  34. package/lib/core/discovery/GoDiscoverer.js +541 -0
  35. package/lib/core/discovery/JvmDiscoverer.js +506 -0
  36. package/lib/core/discovery/NodeDiscoverer.js +466 -0
  37. package/lib/core/discovery/ProjectDiscoverer.js +93 -0
  38. package/lib/core/discovery/PythonDiscoverer.js +338 -0
  39. package/lib/core/discovery/SpmDiscoverer.js +5 -0
  40. package/lib/core/discovery/index.js +53 -0
  41. package/lib/core/enhancement/EnhancementPack.js +71 -0
  42. package/lib/core/enhancement/EnhancementRegistry.js +47 -0
  43. package/lib/core/enhancement/android-enhancement.js +102 -0
  44. package/lib/core/enhancement/django-enhancement.js +70 -0
  45. package/lib/core/enhancement/fastapi-enhancement.js +63 -0
  46. package/lib/core/enhancement/go-grpc-enhancement.js +152 -0
  47. package/lib/core/enhancement/go-web-enhancement.js +201 -0
  48. package/lib/core/enhancement/index.js +65 -0
  49. package/lib/core/enhancement/node-server-enhancement.js +88 -0
  50. package/lib/core/enhancement/react-enhancement.js +86 -0
  51. package/lib/core/enhancement/spring-enhancement.js +112 -0
  52. package/lib/core/enhancement/vue-enhancement.js +96 -0
  53. package/lib/core/gateway/Gateway.js +8 -9
  54. package/lib/core/gateway/GatewayActionRegistry.js +1 -1
  55. package/lib/core/permission/PermissionManager.js +12 -8
  56. package/lib/domain/index.js +13 -9
  57. package/lib/domain/knowledge/KnowledgeEntry.js +111 -101
  58. package/lib/domain/knowledge/KnowledgeRepository.js +0 -1
  59. package/lib/domain/knowledge/Lifecycle.js +22 -22
  60. package/lib/domain/knowledge/index.js +9 -12
  61. package/lib/domain/knowledge/values/Constraints.js +31 -21
  62. package/lib/domain/knowledge/values/Content.js +21 -13
  63. package/lib/domain/knowledge/values/Quality.js +31 -18
  64. package/lib/domain/knowledge/values/Reasoning.js +20 -12
  65. package/lib/domain/knowledge/values/Relations.js +37 -25
  66. package/lib/domain/knowledge/values/Stats.js +18 -12
  67. package/lib/domain/knowledge/values/index.js +4 -3
  68. package/lib/domain/snippet/Snippet.js +35 -10
  69. package/lib/external/ai/AiFactory.js +48 -16
  70. package/lib/external/ai/AiProvider.js +184 -90
  71. package/lib/external/ai/providers/ClaudeProvider.js +25 -12
  72. package/lib/external/ai/providers/GoogleGeminiProvider.js +59 -30
  73. package/lib/external/ai/providers/MockProvider.js +9 -3
  74. package/lib/external/ai/providers/OpenAiProvider.js +51 -29
  75. package/lib/external/mcp/McpServer.js +66 -36
  76. package/lib/external/mcp/errorHandler.js +23 -11
  77. package/lib/external/mcp/handlers/LanguageExtensions.js +138 -53
  78. package/lib/external/mcp/handlers/TargetClassifier.js +52 -16
  79. package/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +81 -20
  80. package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +71 -42
  81. package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +9 -17
  82. package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +14 -9
  83. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +15 -7
  84. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +352 -153
  85. package/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +52 -12
  86. package/lib/external/mcp/handlers/bootstrap/skills.js +143 -39
  87. package/lib/external/mcp/handlers/bootstrap.js +691 -168
  88. package/lib/external/mcp/handlers/browse.js +66 -22
  89. package/lib/external/mcp/handlers/candidate.js +118 -35
  90. package/lib/external/mcp/handlers/consolidated.js +49 -17
  91. package/lib/external/mcp/handlers/guard.js +104 -39
  92. package/lib/external/mcp/handlers/knowledge.js +60 -36
  93. package/lib/external/mcp/handlers/search.js +43 -14
  94. package/lib/external/mcp/handlers/skill.js +120 -45
  95. package/lib/external/mcp/handlers/structure.js +240 -86
  96. package/lib/external/mcp/handlers/system.js +42 -12
  97. package/lib/external/mcp/handlers/wiki.js +58 -33
  98. package/lib/external/mcp/tools.js +306 -123
  99. package/lib/http/HttpServer.js +72 -47
  100. package/lib/http/middleware/RateLimiter.js +5 -3
  101. package/lib/http/middleware/errorHandler.js +6 -1
  102. package/lib/http/middleware/requestLogger.js +14 -3
  103. package/lib/http/middleware/roleResolver.js +30 -23
  104. package/lib/http/routes/ai.js +387 -265
  105. package/lib/http/routes/auth.js +81 -61
  106. package/lib/http/routes/candidates.js +430 -320
  107. package/lib/http/routes/commands.js +289 -189
  108. package/lib/http/routes/extract.js +158 -125
  109. package/lib/http/routes/guardRules.js +309 -217
  110. package/lib/http/routes/knowledge.js +213 -154
  111. package/lib/http/routes/modules.js +578 -0
  112. package/lib/http/routes/monitoring.js +6 -6
  113. package/lib/http/routes/recipes.js +104 -93
  114. package/lib/http/routes/search.js +361 -305
  115. package/lib/http/routes/skills.js +145 -98
  116. package/lib/http/routes/snippets.js +42 -30
  117. package/lib/http/routes/spm.js +3 -405
  118. package/lib/http/routes/violations.js +113 -93
  119. package/lib/http/routes/wiki.js +211 -170
  120. package/lib/http/utils/routeHelpers.js +3 -1
  121. package/lib/http/utils/sse-sessions.js +16 -6
  122. package/lib/http/utils/sse.js +15 -5
  123. package/lib/infrastructure/audit/AuditLogger.js +5 -2
  124. package/lib/infrastructure/audit/AuditStore.js +10 -7
  125. package/lib/infrastructure/cache/CacheService.js +3 -1
  126. package/lib/infrastructure/cache/GraphCache.js +8 -4
  127. package/lib/infrastructure/cache/UnifiedCacheAdapter.js +1 -1
  128. package/lib/infrastructure/config/ConfigLoader.js +9 -5
  129. package/lib/infrastructure/config/Defaults.js +30 -10
  130. package/lib/infrastructure/config/Paths.js +28 -8
  131. package/lib/infrastructure/config/TriggerSymbol.js +22 -10
  132. package/lib/infrastructure/database/DatabaseConnection.js +15 -10
  133. package/lib/infrastructure/database/migrations/001_initial_schema.js +0 -1
  134. package/lib/infrastructure/external/ClipboardManager.js +6 -2
  135. package/lib/infrastructure/external/NativeUi.js +50 -43
  136. package/lib/infrastructure/external/OpenBrowser.js +14 -17
  137. package/lib/infrastructure/external/XcodeAutomation.js +14 -258
  138. package/lib/infrastructure/logging/Logger.js +46 -30
  139. package/lib/infrastructure/monitoring/ErrorTracker.js +7 -5
  140. package/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -4
  141. package/lib/infrastructure/paths/HeaderResolver.js +25 -9
  142. package/lib/infrastructure/paths/PathFinder.js +34 -12
  143. package/lib/infrastructure/plugin/PluginManager.js +26 -8
  144. package/lib/infrastructure/realtime/RealtimeService.js +2 -2
  145. package/lib/infrastructure/vector/Chunker.js +22 -7
  146. package/lib/infrastructure/vector/IndexingPipeline.js +46 -22
  147. package/lib/infrastructure/vector/JsonVectorAdapter.js +90 -53
  148. package/lib/infrastructure/vector/VectorStore.js +28 -10
  149. package/lib/injection/ServiceContainer.js +247 -93
  150. package/lib/platform/ios/index.js +63 -0
  151. package/lib/platform/ios/routes/spm.js +437 -0
  152. package/lib/platform/ios/snippet/PlaceholderConverter.js +55 -0
  153. package/lib/platform/ios/snippet/XcodeCodec.js +112 -0
  154. package/lib/{service → platform/ios}/spm/DependencyGraph.js +41 -17
  155. package/lib/{service → platform/ios}/spm/PackageSwiftParser.js +41 -14
  156. package/lib/{service → platform/ios}/spm/PolicyEngine.js +9 -4
  157. package/lib/platform/ios/spm/SpmDiscoverer.js +122 -0
  158. package/lib/{service → platform/ios}/spm/SpmService.js +385 -127
  159. package/lib/{service/automation → platform/ios/xcode}/SaveEventFilter.js +8 -7
  160. package/lib/platform/ios/xcode/XcodeAutomation.js +350 -0
  161. package/lib/{service/automation → platform/ios/xcode}/XcodeIntegration.js +325 -145
  162. package/lib/repository/base/BaseRepository.js +7 -9
  163. package/lib/repository/knowledge/KnowledgeRepository.impl.js +98 -75
  164. package/lib/repository/token/TokenUsageStore.js +4 -2
  165. package/lib/service/automation/ActionPipeline.js +1 -1
  166. package/lib/service/automation/AutomationOrchestrator.js +8 -4
  167. package/lib/service/automation/ContextCollector.js +7 -5
  168. package/lib/service/automation/DirectiveDetector.js +23 -16
  169. package/lib/service/automation/FileWatcher.js +112 -56
  170. package/lib/service/automation/TriggerResolver.js +6 -4
  171. package/lib/service/automation/handlers/AlinkHandler.js +24 -12
  172. package/lib/service/automation/handlers/CreateHandler.js +19 -20
  173. package/lib/service/automation/handlers/DraftHandler.js +14 -8
  174. package/lib/service/automation/handlers/GuardHandler.js +93 -63
  175. package/lib/service/automation/handlers/HeaderHandler.js +1 -6
  176. package/lib/service/automation/handlers/SearchHandler.js +155 -88
  177. package/lib/service/bootstrap/BootstrapTaskManager.js +77 -35
  178. package/lib/service/candidate/SimilarityService.js +25 -9
  179. package/lib/service/chat/AnalystAgent.js +50 -24
  180. package/lib/service/chat/CandidateGuardrail.js +143 -17
  181. package/lib/service/chat/ChatAgent.js +759 -243
  182. package/lib/service/chat/ContextWindow.js +116 -71
  183. package/lib/service/chat/ConversationStore.js +77 -36
  184. package/lib/service/chat/EpisodicConsolidator.js +47 -23
  185. package/lib/service/chat/HandoffProtocol.js +98 -22
  186. package/lib/service/chat/Memory.js +34 -14
  187. package/lib/service/chat/ProducerAgent.js +40 -20
  188. package/lib/service/chat/ProjectSemanticMemory.js +109 -78
  189. package/lib/service/chat/ReasoningLayer.js +148 -70
  190. package/lib/service/chat/ReasoningTrace.js +44 -32
  191. package/lib/service/chat/TaskPipeline.js +39 -19
  192. package/lib/service/chat/ToolRegistry.js +48 -29
  193. package/lib/service/chat/WorkingMemory.js +44 -18
  194. package/lib/service/chat/tools.js +1096 -494
  195. package/lib/service/context/RecipeExtractor.js +132 -51
  196. package/lib/service/cursor/CursorDeliveryPipeline.js +82 -37
  197. package/lib/service/cursor/KnowledgeCompressor.js +25 -22
  198. package/lib/service/cursor/RulesGenerator.js +13 -7
  199. package/lib/service/cursor/SkillsSyncer.js +77 -27
  200. package/lib/service/cursor/TokenBudget.js +2 -2
  201. package/lib/service/cursor/TopicClassifier.js +54 -20
  202. package/lib/service/guard/ComplianceReporter.js +55 -43
  203. package/lib/service/guard/ExclusionManager.js +67 -29
  204. package/lib/service/guard/GuardCheckEngine.js +381 -86
  205. package/lib/service/guard/GuardFeedbackLoop.js +22 -10
  206. package/lib/service/guard/GuardService.js +29 -19
  207. package/lib/service/guard/RuleLearner.js +55 -23
  208. package/lib/service/guard/SourceFileCollector.js +27 -20
  209. package/lib/service/guard/ViolationsStore.js +43 -38
  210. package/lib/service/knowledge/CodeEntityGraph.js +147 -82
  211. package/lib/service/knowledge/ConfidenceRouter.js +12 -10
  212. package/lib/service/knowledge/KnowledgeFileWriter.js +147 -56
  213. package/lib/service/knowledge/KnowledgeGraphService.js +81 -34
  214. package/lib/service/knowledge/KnowledgeService.js +222 -112
  215. package/lib/service/module/ModuleService.js +969 -0
  216. package/lib/service/quality/FeedbackCollector.js +27 -15
  217. package/lib/service/quality/QualityScorer.js +78 -24
  218. package/lib/service/recipe/RecipeCandidateValidator.js +110 -44
  219. package/lib/service/recipe/RecipeParser.js +78 -45
  220. package/lib/service/search/CoarseRanker.js +43 -28
  221. package/lib/service/search/CrossEncoderReranker.js +32 -21
  222. package/lib/service/search/InvertedIndex.js +21 -7
  223. package/lib/service/search/MultiSignalRanker.js +90 -28
  224. package/lib/service/search/RetrievalFunnel.js +45 -24
  225. package/lib/service/search/SearchEngine.js +255 -103
  226. package/lib/service/skills/EventAggregator.js +32 -15
  227. package/lib/service/skills/SignalCollector.js +140 -64
  228. package/lib/service/skills/SkillAdvisor.js +79 -42
  229. package/lib/service/skills/SkillHooks.js +16 -14
  230. package/lib/service/snippet/PlaceholderConverter.js +5 -0
  231. package/lib/service/snippet/SnippetFactory.js +116 -99
  232. package/lib/service/snippet/SnippetInstaller.js +234 -62
  233. package/lib/service/snippet/codecs/SnippetCodec.js +67 -0
  234. package/lib/service/snippet/codecs/VSCodeCodec.js +102 -0
  235. package/lib/service/snippet/codecs/XcodeCodec.js +5 -0
  236. package/lib/service/wiki/WikiGenerator.js +637 -263
  237. package/lib/shared/DimensionCopyRegistry.js +472 -0
  238. package/lib/shared/LanguageService.js +399 -0
  239. package/lib/shared/PathGuard.js +45 -28
  240. package/lib/shared/RecipeReadinessChecker.js +72 -12
  241. package/lib/shared/constants.js +41 -41
  242. package/lib/shared/errors/BaseError.js +2 -2
  243. package/lib/shared/errors/index.js +4 -4
  244. package/lib/shared/similarity.js +25 -8
  245. package/lib/shared/token-utils.js +6 -2
  246. package/lib/shared/utils/common.js +12 -4
  247. package/package.json +49 -13
  248. package/scripts/bench-real-projects.mjs +256 -0
  249. package/scripts/build-native-ui.js +30 -30
  250. package/scripts/clear-old-vector-index.js +5 -35
  251. package/scripts/clear-vector-cache.js +7 -37
  252. package/scripts/collect-test-project-stats.mjs +160 -0
  253. package/scripts/diagnose-mcp.js +41 -32
  254. package/scripts/ensure-parse-package.js +6 -9
  255. package/scripts/generate-recipe-drafts.js +116 -77
  256. package/scripts/init-db.js +3 -20
  257. package/scripts/init-snippets.js +305 -0
  258. package/scripts/init-vector-db.js +173 -170
  259. package/scripts/install-cursor-skill.js +148 -104
  260. package/scripts/install-full.js +8 -21
  261. package/scripts/install-vscode-copilot.js +146 -145
  262. package/scripts/migrate-md-to-knowledge.mjs +139 -151
  263. package/scripts/postinstall-safe.js +5 -17
  264. package/scripts/recipe-audit.js +106 -82
  265. package/scripts/release.js +283 -323
  266. package/scripts/setup-mcp-config.js +60 -52
  267. package/scripts/verify-context-api.js +20 -20
  268. package/skills/autosnippet-analysis/SKILL.md +10 -6
  269. package/skills/autosnippet-candidates/SKILL.md +27 -26
  270. package/skills/autosnippet-coldstart/SKILL.md +555 -38
  271. package/skills/autosnippet-concepts/SKILL.md +349 -337
  272. package/skills/autosnippet-create/SKILL.md +5 -5
  273. package/skills/autosnippet-reference-dart/SKILL.md +543 -0
  274. package/skills/autosnippet-reference-go/SKILL.md +539 -0
  275. package/skills/autosnippet-reference-java/SKILL.md +534 -0
  276. package/skills/autosnippet-reference-jsts/SKILL.md +41 -9
  277. package/skills/autosnippet-reference-kotlin/SKILL.md +526 -0
  278. package/skills/autosnippet-reference-objc/SKILL.md +29 -6
  279. package/skills/autosnippet-reference-python/SKILL.md +800 -0
  280. package/skills/autosnippet-reference-swift/SKILL.md +70 -14
  281. package/skills/autosnippet-structure/SKILL.md +4 -4
  282. package/templates/cursor-rules/autosnippet-conventions.mdc +2 -2
  283. package/templates/recipes-setup/README.md +2 -2
  284. package/templates/recipes-setup/_template.md +1 -1
  285. package/dashboard/dist/assets/index-Bun3ld_J.css +0 -1
  286. package/dashboard/dist/assets/index-_Sk_Dmg3.js +0 -143
  287. package/resources/asd-entry/main.swift +0 -159
  288. package/scripts/build-asd-entry.js +0 -51
  289. package/scripts/init-xcode-snippets.js +0 -311
  290. package/template.json +0 -39
@@ -4,12 +4,12 @@
4
4
  * 构建 target 级依赖 DAG,支持层级计算、拓扑排序、可达性检查
5
5
  */
6
6
 
7
- import Logger from '../../infrastructure/logging/Logger.js';
7
+ import Logger from '../../../infrastructure/logging/Logger.js';
8
8
 
9
9
  export class DependencyGraph {
10
- #adjacency; // Map<string, Set<string>>
11
- #reverseAdj; // Map<string, Set<string>>
12
- #nodes; // Set<string>
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(`[DependencyGraph] built: ${this.#nodes.size} nodes, ${this.edgeCount()} edges`);
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)) this.#adjacency.set(name, new Set());
43
- if (!this.#reverseAdj.has(name)) this.#reverseAdj.set(name, new Set());
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) return true;
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) return true;
66
- if (visited.has(node)) continue;
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)) dfs(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) inDegree.set(node, 0);
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) queue.push(node);
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) queue.push(dep);
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, (levels.get(dep) || 0));
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()) count += deps.size;
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) edges.push({ from, to });
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 { readFileSync, existsSync, readdirSync } from 'node:fs';
7
- import { join, dirname } from 'node:path';
8
- import Logger from '../../infrastructure/logging/Logger.js';
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)) return this.#cache.get(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) break;
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)) return this.#cache.get(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(['node_modules', '.git', 'Build', '.build', '.swiftpm', 'Pods', 'DerivedData']);
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) return; // 限制深度
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)) continue;
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(`[PackageSwiftParser] 解析完成: ${result.name} (${result.targets.length} targets)`);
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] === '(') depth++;
162
- else if (content[endPos] === ')') depth--;
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) continue;
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) deps.push(dm[1]);
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) continue;
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) continue;
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)) return idx;
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
+ }