autosnippet 3.0.1 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +655 -260
  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
@@ -3,12 +3,13 @@
3
3
  * 从路径或文本提取 Recipe 候选
4
4
  */
5
5
 
6
- import express from 'express';
7
6
  import { basename } from 'node:path';
8
- import { asyncHandler } from '../middleware/errorHandler.js';
7
+ import express from 'express';
8
+ import Logger from '../../infrastructure/logging/Logger.js';
9
9
  import { getServiceContainer } from '../../injection/ServiceContainer.js';
10
+ import { LanguageService } from '../../shared/LanguageService.js';
10
11
  import { ValidationError } from '../../shared/errors/index.js';
11
- import Logger from '../../infrastructure/logging/Logger.js';
12
+ import { asyncHandler } from '../middleware/errorHandler.js';
12
13
 
13
14
  const router = express.Router();
14
15
  const logger = Logger.getInstance();
@@ -18,148 +19,180 @@ const logger = Logger.getInstance();
18
19
  * 从文件路径提取代码片段
19
20
  * 管线: RecipeParser(MD解析) → AI 提取(ChatAgent) → 原始兜底
20
21
  */
21
- router.post('/path', asyncHandler(async (req, res) => {
22
- const { relativePath, projectRoot: bodyRoot } = req.body;
23
-
24
- if (!relativePath) {
25
- throw new ValidationError('relativePath is required');
26
- }
22
+ router.post(
23
+ '/path',
24
+ asyncHandler(async (req, res) => {
25
+ const { relativePath, projectRoot: bodyRoot } = req.body;
27
26
 
28
- const container = getServiceContainer();
29
- const recipeParser = container.get('recipeParser');
30
-
31
- // 优先用请求体的 projectRoot,其次用 ServiceContainer 中注册的全局值
32
- const projectRoot = bodyRoot || container.singletons?._projectRoot || process.cwd();
33
- logger.debug('extract/path: resolved projectRoot', { relativePath, projectRoot, source: bodyRoot ? 'body' : container.singletons?._projectRoot ? 'container' : 'cwd' });
27
+ if (!relativePath) {
28
+ throw new ValidationError('relativePath is required');
29
+ }
34
30
 
35
- // 1. RecipeParser 解析(对 Recipe MD 文件有效)
36
- const result = await recipeParser.extractFromPath(relativePath, {
37
- projectRoot,
38
- });
31
+ const container = getServiceContainer();
32
+ const recipeParser = container.get('recipeParser');
39
33
 
40
- const items = result.items || result;
34
+ // 优先用请求体的 projectRoot,其次用 ServiceContainer 中注册的全局值
35
+ const projectRoot = bodyRoot || container.singletons?._projectRoot || process.cwd();
36
+ logger.debug('extract/path: resolved projectRoot', {
37
+ relativePath,
38
+ projectRoot,
39
+ source: bodyRoot ? 'body' : container.singletons?._projectRoot ? 'container' : 'cwd',
40
+ });
41
41
 
42
- // 2. 判断是否为"原始兜底"结果(无 frontmatter summary/usageGuide 全空)
43
- const isRawFallback = Array.isArray(items) && items.length > 0
44
- && !items[0].summary && !items[0].usageGuide && !items[0].frontmatter?.title;
42
+ // 1. RecipeParser 解析(对 Recipe MD 文件有效)
43
+ const result = await recipeParser.extractFromPath(relativePath, {
44
+ projectRoot,
45
+ });
45
46
 
46
- if (isRawFallback) {
47
- // 3. 尝试 ChatAgent AI 提取
48
- try {
49
- const chatAgent = container.get('chatAgent');
50
- const file = items[0];
51
- const fileName = basename(relativePath); // 保留扩展名: BDMineViewController.m
52
- const aiResult = await chatAgent.executeTool('extract_recipes', {
53
- targetName: fileName,
54
- files: [{ name: fileName, content: file.code || '' }],
55
- comprehensive: true,
56
- });
47
+ const items = result.items || result;
48
+
49
+ // 2. 判断是否为"原始兜底"结果(无 frontmatter → summary/usageGuide 全空)
50
+ const isRawFallback =
51
+ Array.isArray(items) &&
52
+ items.length > 0 &&
53
+ !items[0].summary &&
54
+ !items[0].usageGuide &&
55
+ !items[0].frontmatter?.title;
56
+
57
+ if (isRawFallback) {
58
+ // 3. 尝试 ChatAgent AI 提取
59
+ try {
60
+ const chatAgent = container.get('chatAgent');
61
+ const file = items[0];
62
+ const fileName = basename(relativePath); // 保留扩展名: BDMineViewController.m
63
+ const aiResult = await chatAgent.executeTool('extract_recipes', {
64
+ targetName: fileName,
65
+ files: [{ name: fileName, content: file.code || '' }],
66
+ comprehensive: true,
67
+ });
57
68
 
58
- if (aiResult && !aiResult.error && Array.isArray(aiResult.recipes) && aiResult.recipes.length > 0) {
59
- logger.info('extract/path: AI extraction succeeded', { count: aiResult.recipes.length });
60
- return res.json({
61
- success: true,
62
- data: {
63
- result: aiResult.recipes,
64
- isMarked: false,
65
- },
69
+ if (
70
+ aiResult &&
71
+ !aiResult.error &&
72
+ Array.isArray(aiResult.recipes) &&
73
+ aiResult.recipes.length > 0
74
+ ) {
75
+ logger.info('extract/path: AI extraction succeeded', { count: aiResult.recipes.length });
76
+ return res.json({
77
+ success: true,
78
+ data: {
79
+ result: aiResult.recipes,
80
+ isMarked: false,
81
+ },
82
+ });
83
+ }
84
+ } catch (err) {
85
+ logger.debug('extract/path: AI extraction failed, using raw fallback', {
86
+ error: err.message,
66
87
  });
67
88
  }
68
- } catch (err) {
69
- logger.debug('extract/path: AI extraction failed, using raw fallback', { error: err.message });
70
89
  }
71
- }
72
-
73
- // 4. 返回 RecipeParser 结果(MD 文件或 AI 不可用时的原始兜底)
74
- res.json({
75
- success: true,
76
- data: {
77
- result: items,
78
- isMarked: result.isMarked || false,
79
- },
80
- });
81
- }));
90
+
91
+ // 4. 返回 RecipeParser 结果(MD 文件或 AI 不可用时的原始兜底)
92
+ res.json({
93
+ success: true,
94
+ data: {
95
+ result: items,
96
+ isMarked: result.isMarked || false,
97
+ },
98
+ });
99
+ })
100
+ );
82
101
 
83
102
  /**
84
103
  * POST /api/v1/extract/text
85
104
  * 从文本内容提取代码片段(剪贴板等)
86
105
  * 管线: RecipeParser(MD解析) → AI 提取(ChatAgent) → 基础兜底
87
106
  */
88
- router.post('/text', asyncHandler(async (req, res) => {
89
- const { text, language, relativePath, projectRoot: bodyRoot } = req.body;
90
-
91
- if (!text) {
92
- throw new ValidationError('text is required');
93
- }
94
-
95
- const container = getServiceContainer();
96
- const recipeParser = container.get('recipeParser');
97
- const projectRoot = bodyRoot || container.singletons?._projectRoot || process.cwd();
98
-
99
- // 1. 先尝试解析为 Recipe Markdown 格式
100
- let result;
101
- try {
102
- result = await recipeParser.parseFromText(text, {
103
- language,
104
- relativePath,
105
- });
106
- // 解析成功,直接返回
107
- return res.json({
108
- success: true,
109
- data: {
110
- result: Array.isArray(result) ? result : [result],
111
- source: 'text',
112
- },
113
- });
114
- } catch (error) {
115
- logger.debug('Recipe MD parse failed, trying AI extraction', {
116
- error: error.message,
117
- });
118
- }
119
-
120
- // 2. Recipe MD 解析失败 → 尝试 ChatAgent AI 提取
121
- try {
122
- const chatAgent = container.get('chatAgent');
123
- if (chatAgent) {
124
- const lang = language || (relativePath && /\.swift$/i.test(relativePath) ? 'swift' : 'objc');
125
- const fileName = relativePath ? basename(relativePath) : `clipboard.${lang === 'swift' ? 'swift' : 'm'}`;
126
- const aiResult = await chatAgent.executeTool('extract_recipes', {
127
- targetName: fileName,
128
- files: [{ name: fileName, content: text }],
129
- comprehensive: true,
130
- });
107
+ router.post(
108
+ '/text',
109
+ asyncHandler(async (req, res) => {
110
+ const { text, language, relativePath, projectRoot: bodyRoot } = req.body;
131
111
 
132
- if (aiResult && !aiResult.error && Array.isArray(aiResult.recipes) && aiResult.recipes.length > 0) {
133
- logger.info('extract/text: AI extraction succeeded', { count: aiResult.recipes.length });
112
+ if (!text) {
113
+ throw new ValidationError('text is required');
114
+ }
134
115
 
135
- // 多条 Recipe 时在第一条上标记总数(供前端提示)
136
- if (aiResult.recipes.length > 1) {
137
- aiResult.recipes[0]._multipleCount = aiResult.recipes.length;
138
- }
116
+ const container = getServiceContainer();
117
+ const recipeParser = container.get('recipeParser');
118
+ const _projectRoot = bodyRoot || container.singletons?._projectRoot || process.cwd();
139
119
 
140
- return res.json({
141
- success: true,
142
- data: {
143
- result: aiResult.recipes,
144
- source: 'text',
145
- },
120
+ // 1. 先尝试解析为 Recipe Markdown 格式
121
+ let result;
122
+ try {
123
+ result = await recipeParser.parseFromText(text, {
124
+ language,
125
+ relativePath,
126
+ });
127
+ // 解析成功,直接返回
128
+ return res.json({
129
+ success: true,
130
+ data: {
131
+ result: Array.isArray(result) ? result : [result],
132
+ source: 'text',
133
+ },
134
+ });
135
+ } catch (error) {
136
+ logger.debug('Recipe MD parse failed, trying AI extraction', {
137
+ error: error.message,
138
+ });
139
+ }
140
+
141
+ // 2. Recipe MD 解析失败 → 尝试 ChatAgent AI 提取
142
+ try {
143
+ const chatAgent = container.get('chatAgent');
144
+ if (chatAgent) {
145
+ const lang =
146
+ language || (relativePath ? (LanguageService.inferLang(relativePath) || 'unknown') : 'unknown');
147
+ const ext = LanguageService.extForLang(lang) || '.txt';
148
+ const fileName = relativePath
149
+ ? basename(relativePath)
150
+ : `clipboard${ext}`;
151
+ const aiResult = await chatAgent.executeTool('extract_recipes', {
152
+ targetName: fileName,
153
+ files: [{ name: fileName, content: text }],
154
+ comprehensive: true,
146
155
  });
156
+
157
+ if (
158
+ aiResult &&
159
+ !aiResult.error &&
160
+ Array.isArray(aiResult.recipes) &&
161
+ aiResult.recipes.length > 0
162
+ ) {
163
+ logger.info('extract/text: AI extraction succeeded', { count: aiResult.recipes.length });
164
+
165
+ // 多条 Recipe 时在第一条上标记总数(供前端提示)
166
+ if (aiResult.recipes.length > 1) {
167
+ aiResult.recipes[0]._multipleCount = aiResult.recipes.length;
168
+ }
169
+
170
+ return res.json({
171
+ success: true,
172
+ data: {
173
+ result: aiResult.recipes,
174
+ source: 'text',
175
+ },
176
+ });
177
+ }
147
178
  }
179
+ } catch (err) {
180
+ logger.debug('extract/text: AI extraction failed, using basic fallback', {
181
+ error: err.message,
182
+ });
148
183
  }
149
- } catch (err) {
150
- logger.debug('extract/text: AI extraction failed, using basic fallback', { error: err.message });
151
- }
152
-
153
- // 3. AI 也失败 → 基础代码块提取兜底
154
- result = await recipeParser.extractFromText(text, { language });
155
-
156
- res.json({
157
- success: true,
158
- data: {
159
- result: Array.isArray(result) ? result : [result],
160
- source: 'text',
161
- },
162
- });
163
- }));
184
+
185
+ // 3. AI 也失败 基础代码块提取兜底
186
+ result = await recipeParser.extractFromText(text, { language });
187
+
188
+ res.json({
189
+ success: true,
190
+ data: {
191
+ result: Array.isArray(result) ? result : [result],
192
+ source: 'text',
193
+ },
194
+ });
195
+ })
196
+ );
164
197
 
165
198
  export default router;