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
@@ -1,259 +1,15 @@
1
1
  /**
2
- * XcodeAutomation Xcode AppleScript 自动化
3
- *
4
- * 通过 osascript 向 Xcode 发送键盘事件,实现行级操作:
5
- * 跳转行、选中行内容、剪切行、粘贴、在行首插入、删除行内容、保存文档。
6
- *
7
- * 所有操作都带超时保护(OSASCRIPT_TIMEOUT),Xcode 未运行时安全跳过。
8
- * 仅支持 macOS。
9
- */
10
-
11
- import { execSync, spawnSync } from 'node:child_process';
12
-
13
- const OSASCRIPT_TIMEOUT = 5000;
14
-
15
- // ─────────────────────────────────────────────
16
- // 内部辅助
17
- // ─────────────────────────────────────────────
18
-
19
- /**
20
- * 将行号限制为有效正整数(最小值 1)
21
- * @param {number} n 原始行号
22
- * @returns {number} 安全的 1-based 行号
23
- */
24
- function _safeLine(n) {
25
- return Number.isFinite(n) && n > 0 ? n : 1;
26
- }
27
-
28
- /**
29
- * 执行 osascript 并返回是否成功
30
- * @param {string[]} args osascript 参数数组(每对 `-e`, `script`)
31
- * @returns {boolean}
32
- */
33
- function _run(args) {
34
- try {
35
- const res = spawnSync('osascript', args, { stdio: 'ignore', timeout: OSASCRIPT_TIMEOUT });
36
- return res.status === 0;
37
- } catch {
38
- return false;
39
- }
40
- }
41
-
42
- // ─────────────────────────────────────────────
43
- // 状态查询
44
- // ─────────────────────────────────────────────
45
-
46
- /**
47
- * 检查 Xcode 是否正在运行(不会启动 Xcode)
48
- */
49
- export function isXcodeRunning() {
50
- if (process.platform !== 'darwin') return false;
51
- try {
52
- const result = execSync('pgrep -x Xcode', {
53
- encoding: 'utf8',
54
- timeout: 2000,
55
- stdio: 'pipe',
56
- });
57
- return result.trim().length > 0;
58
- } catch {
59
- return false;
60
- }
61
- }
62
-
63
- /**
64
- * 检查 Xcode 是否为当前前台应用
65
- */
66
- export function isXcodeFrontmost() {
67
- if (!isXcodeRunning()) return false;
68
- try {
69
- const result = execSync(
70
- 'osascript -e \'tell application "System Events" to get name of first process whose frontmost is true\'',
71
- { encoding: 'utf8', timeout: OSASCRIPT_TIMEOUT, stdio: 'pipe' }
72
- );
73
- return result.trim() === 'Xcode';
74
- } catch {
75
- return false;
76
- }
77
- }
78
-
79
- // ─────────────────────────────────────────────
80
- // 行操作
81
- // ─────────────────────────────────────────────
82
-
83
- /**
84
- * 跳转到指定行
85
- *
86
- * 按键序列:Cmd+L → 输入行号 → Return
87
- *
88
- * @param {number} lineNumber 1-based 行号
89
- * @returns {boolean} 是否成功
90
- */
91
- export function jumpToLineInXcode(lineNumber) {
92
- if (!isXcodeRunning()) return false;
93
- const n = _safeLine(lineNumber);
94
- return _run([
95
- '-e', 'tell application "Xcode" to activate',
96
- '-e', 'delay 0.2',
97
- '-e', 'tell application "System Events"',
98
- '-e', ' keystroke "l" using command down',
99
- '-e', ' delay 0.2',
100
- '-e', ` keystroke "${String(n)}"`,
101
- '-e', ' delay 0.2',
102
- '-e', ' key code 36',
103
- '-e', 'end tell',
104
- ]);
105
- }
106
-
107
- /**
108
- * 剪切指定行的文本内容(不含换行符)
109
- *
110
- * 按键序列:Cmd+L 跳转 → Cmd+← 行首 → Cmd+Shift+→ 选到行尾 → Cmd+X 剪切
111
- *
112
- * @param {number} lineNumber 1-based 行号
113
- * @returns {boolean} 是否成功
114
- */
115
- export function cutLineInXcode(lineNumber) {
116
- if (!isXcodeRunning()) return false;
117
- const n = _safeLine(lineNumber);
118
- return _run([
119
- '-e', 'tell application "Xcode" to activate',
120
- '-e', 'delay 0.5',
121
- '-e', 'tell application "System Events"',
122
- '-e', ' keystroke "l" using command down', // Cmd+L: Go to Line
123
- '-e', ' delay 0.5',
124
- '-e', ` keystroke "${String(n)}"`, // 输入行号
125
- '-e', ' delay 0.5',
126
- '-e', ' key code 36', // Return
127
- '-e', ' delay 0.5',
128
- '-e', ' key code 123 using command down', // Cmd+← 行首
129
- '-e', ' delay 0.5',
130
- '-e', ' key code 124 using {command down, shift down}', // Cmd+Shift+→ 选到行尾
131
- '-e', ' delay 0.5',
132
- '-e', ' keystroke "x" using command down', // Cmd+X
133
- '-e', 'end tell',
134
- ]);
135
- }
136
-
137
- /**
138
- * 删除指定行的文本内容(保留空行,不删除行本身)
139
- *
140
- * 按键序列:Cmd+L 跳转 → Cmd+← 行首 → Cmd+Shift+→ 选到行尾 → Delete
141
- *
142
- * @param {number} lineNumber 1-based 行号
143
- * @returns {boolean} 是否成功
144
- */
145
- export function deleteLineContentInXcode(lineNumber) {
146
- if (!isXcodeRunning()) return false;
147
- const n = _safeLine(lineNumber);
148
- return _run([
149
- '-e', 'tell application "Xcode" to activate',
150
- '-e', 'delay 0.3',
151
- '-e', 'tell application "System Events"',
152
- '-e', ' keystroke "l" using command down',
153
- '-e', ' delay 0.3',
154
- '-e', ` keystroke "${String(n)}"`,
155
- '-e', ' delay 0.3',
156
- '-e', ' key code 36',
157
- '-e', ' delay 0.3',
158
- '-e', ' key code 123 using command down', // Cmd+← 行首
159
- '-e', ' delay 0.2',
160
- '-e', ' key code 124 using {command down, shift down}', // Cmd+Shift+→ 选到行尾
161
- '-e', ' delay 0.2',
162
- '-e', ' key code 51', // Delete 键
163
- '-e', ' delay 0.3',
164
- '-e', 'end tell',
165
- ]);
166
- }
167
-
168
- // ─────────────────────────────────────────────
169
- // 粘贴操作
170
- // ─────────────────────────────────────────────
171
-
172
- /**
173
- * 执行粘贴(Cmd+V)
174
- *
175
- * 调用前须确保剪贴板已写入目标内容。
176
- * @returns {boolean} 是否成功
177
- */
178
- export function pasteInXcode() {
179
- if (!isXcodeRunning()) return false;
180
- return _run([
181
- '-e', 'tell application "Xcode" to activate',
182
- '-e', 'delay 0.2',
183
- '-e', 'tell application "System Events"',
184
- '-e', ' keystroke "v" using command down',
185
- '-e', 'end tell',
186
- ]);
187
- }
188
-
189
- /**
190
- * 选中当前行内容后粘贴替换
191
- *
192
- * 假设光标已在目标行(通常由 jumpToLineInXcode 定位后调用)。
193
- * 按键序列:Cmd+← 行首 → Cmd+Shift+→ 选到行尾 → Cmd+V 粘贴替换
194
- *
195
- * @returns {boolean} 是否成功
196
- */
197
- export function selectAndPasteInXcode() {
198
- if (!isXcodeRunning()) return false;
199
- return _run([
200
- '-e', 'tell application "Xcode" to activate',
201
- '-e', 'delay 0.5',
202
- '-e', 'tell application "System Events"',
203
- '-e', ' key code 123 using command down', // Cmd+← 行首
204
- '-e', ' delay 0.1',
205
- '-e', ' key code 124 using {command down, shift down}', // Cmd+Shift+→ 选到行尾
206
- '-e', ' delay 0.2',
207
- '-e', ' keystroke "v" using command down', // Cmd+V 粘贴替换
208
- '-e', 'end tell',
209
- ]);
210
- }
211
-
212
- /**
213
- * 跳转到指定行行首并粘贴剪贴板内容
214
- *
215
- * 用于在 import 区域插入新行。
216
- * 按键序列:Cmd+L → 输入行号 → Return → Cmd+← 行首 → Cmd+V 粘贴
217
- *
218
- * @param {number} lineNumber 1-based 行号
219
- * @returns {boolean} 是否成功
220
- */
221
- export function insertAtLineStartInXcode(lineNumber) {
222
- if (!isXcodeRunning()) return false;
223
- const n = _safeLine(lineNumber);
224
- return _run([
225
- '-e', 'tell application "Xcode" to activate',
226
- '-e', 'delay 0.3',
227
- '-e', 'tell application "System Events"',
228
- '-e', ' keystroke "l" using command down', // Cmd+L: Go to Line
229
- '-e', ' delay 0.3',
230
- '-e', ` keystroke "${String(n)}"`, // 输入行号
231
- '-e', ' delay 0.3',
232
- '-e', ' key code 36', // Return
233
- '-e', ' delay 0.3',
234
- '-e', ' key code 123 using command down', // Cmd+← 行首
235
- '-e', ' delay 0.2',
236
- '-e', ' keystroke "v" using command down', // Cmd+V 粘贴
237
- '-e', ' delay 0.3',
238
- '-e', 'end tell',
239
- ]);
240
- }
241
-
242
- // ─────────────────────────────────────────────
243
- // 文档操作
244
- // ─────────────────────────────────────────────
245
-
246
- /**
247
- * 保存 Xcode 当前活动文档(Cmd+S)
248
- * @returns {boolean} 是否成功
249
- */
250
- export function saveActiveDocumentInXcode() {
251
- if (!isXcodeRunning()) return false;
252
- return _run([
253
- '-e', 'tell application "Xcode" to activate',
254
- '-e', 'delay 0.1',
255
- '-e', 'tell application "System Events"',
256
- '-e', ' keystroke "s" using command down',
257
- '-e', 'end tell',
258
- ]);
259
- }
2
+ * @deprecated Moved to lib/platform/ios/xcode/XcodeAutomation.js
3
+ * This re-export shim maintains backward compatibility.
4
+ */
5
+ export {
6
+ isXcodeRunning,
7
+ isXcodeFrontmost,
8
+ jumpToLineInXcode,
9
+ cutLineInXcode,
10
+ deleteLineContentInXcode,
11
+ pasteInXcode,
12
+ selectAndPasteInXcode,
13
+ insertAtLineStartInXcode,
14
+ saveActiveDocumentInXcode,
15
+ } from '../../platform/ios/xcode/XcodeAutomation.js';
@@ -1,31 +1,38 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
1
3
  import winston from 'winston';
2
- import path from 'path';
3
- import fs from 'fs';
4
4
 
5
5
  // ChatAgent 相关标签 — 终端高亮显示
6
- const AGENT_TAGS = ['ChatAgent', 'ToolRegistry', 'SignalCollector', 'SkillAdvisor', 'CircuitBreaker', 'EventAggregator'];
6
+ const AGENT_TAGS = [
7
+ 'ChatAgent',
8
+ 'ToolRegistry',
9
+ 'SignalCollector',
10
+ 'SkillAdvisor',
11
+ 'CircuitBreaker',
12
+ 'EventAggregator',
13
+ ];
7
14
  const MUTED_PREFIXES = ['HTTP Request', 'Tool registered:', '📊 性能统计已更新'];
8
15
 
9
16
  // ANSI 颜色常量 — 保证深色终端可读性
10
17
  const C = {
11
- reset: '\x1b[0m',
12
- dim: '\x1b[2m', // 真正的 dim(用于次要信息)
13
- bold: '\x1b[1m',
18
+ reset: '\x1b[0m',
19
+ dim: '\x1b[2m', // 真正的 dim(用于次要信息)
20
+ bold: '\x1b[1m',
14
21
  // 前景色 — 使用亮色变体,深色终端更清晰
15
- gray: '\x1b[37m', // 白色(替代 90 暗灰)
16
- cyan: '\x1b[96m', // 亮青
17
- green: '\x1b[92m', // 亮绿
18
- yellow: '\x1b[93m', // 亮黄
19
- red: '\x1b[91m', // 亮红
20
- magenta: '\x1b[95m', // 亮洋红
21
- blue: '\x1b[94m', // 亮蓝
22
- dimGray: '\x1b[2;37m', // dim 白色 — 比 90 在深色背景上更可读
22
+ gray: '\x1b[37m', // 白色(替代 90 暗灰)
23
+ cyan: '\x1b[96m', // 亮青
24
+ green: '\x1b[92m', // 亮绿
25
+ yellow: '\x1b[93m', // 亮黄
26
+ red: '\x1b[91m', // 亮红
27
+ magenta: '\x1b[95m', // 亮洋红
28
+ blue: '\x1b[94m', // 亮蓝
29
+ dimGray: '\x1b[2;37m', // dim 白色 — 比 90 在深色背景上更可读
23
30
  };
24
31
 
25
32
  const LEVEL_COLORS = {
26
33
  error: C.red,
27
- warn: C.yellow,
28
- info: C.green,
34
+ warn: C.yellow,
35
+ info: C.green,
29
36
  debug: C.blue,
30
37
  };
31
38
 
@@ -37,23 +44,32 @@ const LEVEL_COLORS = {
37
44
  * - 其他 info/debug: 一行精简格式
38
45
  */
39
46
  const compactConsoleFormat = winston.format.printf(({ level, message, timestamp, ...meta }) => {
40
- const ts = new Date(timestamp).toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });
47
+ const ts = new Date(timestamp).toLocaleTimeString('en-US', {
48
+ hour12: false,
49
+ hour: '2-digit',
50
+ minute: '2-digit',
51
+ second: '2-digit',
52
+ });
53
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: intentional ANSI escape sequence stripping
41
54
  const rawLevel = level.replace(/\u001b\[\d+m/g, ''); // 去 ANSI
42
55
  const lc = LEVEL_COLORS[rawLevel] || C.gray;
43
56
 
44
57
  // 静音高频噪音日志
45
- if (rawLevel === 'info' && MUTED_PREFIXES.some(p => message.startsWith(p))) {
58
+ if (rawLevel === 'info' && MUTED_PREFIXES.some((p) => message.startsWith(p))) {
46
59
  return ''; // 返回空字符串会被 winston 跳过
47
60
  }
48
61
 
49
62
  // 判断是否为 Agent 相关日志
50
- const isAgentLog = AGENT_TAGS.some(tag => message.includes(tag) || message.startsWith(`[${tag}]`));
63
+ const isAgentLog = AGENT_TAGS.some(
64
+ (tag) => message.includes(tag) || message.startsWith(`[${tag}]`)
65
+ );
51
66
 
52
67
  if (isAgentLog) {
53
68
  // ChatAgent 日志 — 高亮显示
54
- const metaStr = Object.keys(meta).length > 0
55
- ? ' ' + JSON.stringify(meta, null, 0).replace(/"/g, '').replace(/,/g, ', ')
56
- : '';
69
+ const metaStr =
70
+ Object.keys(meta).length > 0
71
+ ? ` ${JSON.stringify(meta, null, 0).replace(/"/g, '').replace(/,/g, ', ')}`
72
+ : '';
57
73
  return `${C.cyan}${ts}${C.reset} ${C.magenta}⚡ ${message}${C.reset}${metaStr ? `${C.dimGray}${metaStr}${C.reset}` : ''}`;
58
74
  }
59
75
 
@@ -62,17 +78,20 @@ const compactConsoleFormat = winston.format.printf(({ level, message, timestamp,
62
78
  const { method, path: reqPath, statusCode, duration } = meta;
63
79
  const status = Number(statusCode);
64
80
  const sc = status >= 500 ? C.red : status >= 400 ? C.yellow : C.dimGray;
65
- const dur = parseInt(duration) > 1000 ? `${C.yellow}${duration}${C.reset}` : `${C.dimGray}${duration}${C.reset}`;
81
+ const dur =
82
+ parseInt(duration) > 1000
83
+ ? `${C.yellow}${duration}${C.reset}`
84
+ : `${C.dimGray}${duration}${C.reset}`;
66
85
  return `${C.dimGray}${ts}${C.reset} ${lc}${rawLevel}${C.reset} ${C.dimGray}${method}${C.reset} ${C.gray}${reqPath}${C.reset} ${sc}${statusCode}${C.reset} ${dur}`;
67
86
  }
68
87
 
69
88
  if (rawLevel === 'warn') {
70
- const metaStr = Object.keys(meta).length > 0 ? ' ' + JSON.stringify(meta) : '';
89
+ const metaStr = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : '';
71
90
  return `${C.gray}${ts}${C.reset} ${C.yellow}${C.bold}warn${C.reset} ${C.yellow}${message}${C.reset}${metaStr ? `${C.dimGray}${metaStr}${C.reset}` : ''}`;
72
91
  }
73
92
 
74
93
  if (rawLevel === 'error') {
75
- const metaStr = Object.keys(meta).length > 0 ? ' ' + JSON.stringify(meta) : '';
94
+ const metaStr = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : '';
76
95
  return `${C.gray}${ts}${C.reset} ${C.red}${C.bold}error${C.reset} ${C.red}${message}${C.reset}${metaStr ? `${C.dimGray}${metaStr}${C.reset}` : ''}`;
77
96
  }
78
97
 
@@ -96,7 +115,7 @@ export class Logger {
96
115
  static getInstance(config = {}) {
97
116
  if (!this.instance) {
98
117
  const logsDir = config.file?.path || './logs';
99
-
118
+
100
119
  // 确保日志目录存在
101
120
  if (!fs.existsSync(logsDir)) {
102
121
  fs.mkdirSync(logsDir, { recursive: true });
@@ -111,10 +130,7 @@ export class Logger {
111
130
  transports.push(
112
131
  new winston.transports.Console({
113
132
  stderrLevels: ['error', 'warn', 'info', 'debug'],
114
- format: winston.format.combine(
115
- winston.format.timestamp(),
116
- compactConsoleFormat,
117
- ),
133
+ format: winston.format.combine(winston.format.timestamp(), compactConsoleFormat),
118
134
  })
119
135
  );
120
136
  }
@@ -3,9 +3,9 @@
3
3
  * 捕获、记录和分析应用程序错误
4
4
  */
5
5
 
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
6
8
  import Logger from '../logging/Logger.js';
7
- import fs from 'fs';
8
- import path from 'path';
9
9
 
10
10
  export class ErrorTracker {
11
11
  constructor(options = {}) {
@@ -29,7 +29,9 @@ export class ErrorTracker {
29
29
 
30
30
  // 定期生成错误报告(unref 避免阻止进程退出)
31
31
  this.reportInterval = setInterval(() => this._generateReport(), 60000);
32
- if (this.reportInterval.unref) this.reportInterval.unref();
32
+ if (this.reportInterval.unref) {
33
+ this.reportInterval.unref();
34
+ }
33
35
  }
34
36
 
35
37
  /**
@@ -139,10 +141,10 @@ export class ErrorTracker {
139
141
  const fileName = `errors-${date}.log`;
140
142
  const filePath = path.join(this.config.logDirectory, fileName);
141
143
 
142
- const logEntry = JSON.stringify({
144
+ const logEntry = `${JSON.stringify({
143
145
  ...errorData,
144
146
  _timestamp: Date.now(),
145
- }) + '\n';
147
+ })}\n`;
146
148
 
147
149
  fs.appendFileSync(filePath, logEntry, 'utf8');
148
150
  } catch (error) {
@@ -29,7 +29,9 @@ export class PerformanceMonitor {
29
29
 
30
30
  // 定期计算统计数据(unref 避免阻止进程退出)
31
31
  this.statsInterval = setInterval(() => this.calculateStats(), 30000);
32
- if (this.statsInterval.unref) this.statsInterval.unref();
32
+ if (this.statsInterval.unref) {
33
+ this.statsInterval.unref();
34
+ }
33
35
  }
34
36
 
35
37
  /**
@@ -79,11 +81,17 @@ export class PerformanceMonitor {
79
81
  if (!this.metrics.endpoints.has(route)) {
80
82
  if (this.metrics.endpoints.size >= 500) {
81
83
  // 淘汰最少访问的端点
82
- let minKey = null, minCount = Infinity;
84
+ let minKey = null,
85
+ minCount = Infinity;
83
86
  for (const [k, v] of this.metrics.endpoints) {
84
- if (v.count < minCount) { minCount = v.count; minKey = k; }
87
+ if (v.count < minCount) {
88
+ minCount = v.count;
89
+ minKey = k;
90
+ }
91
+ }
92
+ if (minKey) {
93
+ this.metrics.endpoints.delete(minKey);
85
94
  }
86
- if (minKey) this.metrics.endpoints.delete(minKey);
87
95
  }
88
96
  this.metrics.endpoints.set(route, {
89
97
  count: 0,
@@ -1,5 +1,5 @@
1
- import path from 'node:path';
2
1
  import fs from 'node:fs';
2
+ import path from 'node:path';
3
3
  import * as PathFinder from './PathFinder.js';
4
4
 
5
5
  /**
@@ -32,12 +32,18 @@ export function parseImportLine(headerStr) {
32
32
  * 解析单个 import 的相对路径
33
33
  */
34
34
  export async function resolveHeaderRelativePath(headerStr, targetRootDir) {
35
- if (!targetRootDir) return undefined;
35
+ if (!targetRootDir) {
36
+ return undefined;
37
+ }
36
38
  const parsed = parseImportLine(headerStr);
37
- if (!parsed) return undefined;
39
+ if (!parsed) {
40
+ return undefined;
41
+ }
38
42
  const { moduleName, headerName } = parsed;
39
43
  const headerPath = await PathFinder.findSubHeaderPath(targetRootDir, headerName, moduleName);
40
- if (!headerPath) return undefined;
44
+ if (!headerPath) {
45
+ return undefined;
46
+ }
41
47
  return path.relative(targetRootDir, headerPath);
42
48
  }
43
49
 
@@ -48,7 +54,9 @@ export function determineModuleNameFromPath(filePath, packageInfo) {
48
54
  const relativePath = path.relative(packageInfo.path, filePath);
49
55
  const segments = relativePath.split(path.sep);
50
56
  for (let i = segments.length - 1; i >= 0; i--) {
51
- if (packageInfo.targets?.includes(segments[i])) return segments[i];
57
+ if (packageInfo.targets?.includes(segments[i])) {
58
+ return segments[i];
59
+ }
52
60
  }
53
61
  return packageInfo.targets?.[0] || packageInfo.name || null;
54
62
  }
@@ -71,7 +79,7 @@ export async function resolveHeadersForText(projectRoot, relativePath, text) {
71
79
  const importRegex = /^(?:#import|import)\s+.*$/gm;
72
80
  let headers = (text.match(importRegex) || []).filter(Boolean);
73
81
  let headerPaths = targetRootDir
74
- ? await Promise.all(headers.map(h => resolveHeaderRelativePath(h, targetRootDir)))
82
+ ? await Promise.all(headers.map((h) => resolveHeaderRelativePath(h, targetRootDir)))
75
83
  : [];
76
84
 
77
85
  // 如果 .m/.mm 无 import,尝试推断同名 .h
@@ -80,10 +88,18 @@ export async function resolveHeadersForText(projectRoot, relativePath, text) {
80
88
  const headerNameWithoutExt = path.basename(fullPath, ext);
81
89
  const packagePath = await PathFinder.findPackageSwiftPath(fullPath);
82
90
  const packageInfo = packagePath ? await PathFinder.parsePackageSwift(packagePath) : null;
83
- if (packageInfo) moduleName = determineModuleNameFromPath(fullPath, packageInfo);
84
- const headerPath = await PathFinder.findSubHeaderPath(targetRootDir, headerNameWithoutExt, moduleName);
91
+ if (packageInfo) {
92
+ moduleName = determineModuleNameFromPath(fullPath, packageInfo);
93
+ }
94
+ const headerPath = await PathFinder.findSubHeaderPath(
95
+ targetRootDir,
96
+ headerNameWithoutExt,
97
+ moduleName
98
+ );
85
99
  if (headerPath) {
86
- headers = [`#import <${moduleName || path.basename(targetRootDir)}/${headerNameWithoutExt}.h>`];
100
+ headers = [
101
+ `#import <${moduleName || path.basename(targetRootDir)}/${headerNameWithoutExt}.h>`,
102
+ ];
87
103
  headerPaths = [path.relative(targetRootDir, headerPath)];
88
104
  }
89
105
  }
@@ -1,5 +1,5 @@
1
- import path from 'node:path';
2
1
  import fs from 'node:fs';
2
+ import path from 'node:path';
3
3
 
4
4
  /**
5
5
  * PathFinder — 轻量级路径发现工具(V2 ESM)
@@ -21,9 +21,13 @@ export async function findTargetRootDir(filePath) {
21
21
  return current;
22
22
  }
23
23
  }
24
- } catch { break; }
24
+ } catch {
25
+ break;
26
+ }
25
27
  const parent = path.dirname(current);
26
- if (parent === current) break;
28
+ if (parent === current) {
29
+ break;
30
+ }
27
31
  current = parent;
28
32
  }
29
33
  return null;
@@ -36,9 +40,13 @@ export async function findPackageSwiftPath(filePath) {
36
40
  let current = path.dirname(path.resolve(filePath));
37
41
  for (let i = 0; i < 15; i++) {
38
42
  const candidate = path.join(current, 'Package.swift');
39
- if (fs.existsSync(candidate)) return candidate;
43
+ if (fs.existsSync(candidate)) {
44
+ return candidate;
45
+ }
40
46
  const parent = path.dirname(current);
41
- if (parent === current) break;
47
+ if (parent === current) {
48
+ break;
49
+ }
42
50
  current = parent;
43
51
  }
44
52
  return null;
@@ -73,14 +81,18 @@ export async function parsePackageSwift(packagePath) {
73
81
  * @returns {Promise<string|null>}
74
82
  */
75
83
  export async function findSubHeaderPath(rootDir, headerName, moduleName) {
76
- if (!rootDir || !headerName) return null;
84
+ if (!rootDir || !headerName) {
85
+ return null;
86
+ }
77
87
  const target = `${headerName}.h`;
78
88
 
79
89
  // 优先在模块名子目录下找
80
90
  if (moduleName) {
81
91
  const modDir = path.join(rootDir, 'Sources', moduleName);
82
92
  const found = _findFile(modDir, target);
83
- if (found) return found;
93
+ if (found) {
94
+ return found;
95
+ }
84
96
  }
85
97
 
86
98
  // 全局搜索
@@ -88,18 +100,28 @@ export async function findSubHeaderPath(rootDir, headerName, moduleName) {
88
100
  }
89
101
 
90
102
  function _findFile(dir, filename, maxDepth = 8, depth = 0) {
91
- if (depth > maxDepth || !fs.existsSync(dir)) return null;
103
+ if (depth > maxDepth || !fs.existsSync(dir)) {
104
+ return null;
105
+ }
92
106
  try {
93
107
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
94
- if (entry.name.startsWith('.')) continue;
108
+ if (entry.name.startsWith('.')) {
109
+ continue;
110
+ }
95
111
  const full = path.join(dir, entry.name);
96
- if (entry.isFile() && entry.name === filename) return full;
112
+ if (entry.isFile() && entry.name === filename) {
113
+ return full;
114
+ }
97
115
  if (entry.isDirectory()) {
98
116
  const found = _findFile(full, filename, maxDepth, depth + 1);
99
- if (found) return found;
117
+ if (found) {
118
+ return found;
119
+ }
100
120
  }
101
121
  }
102
- } catch { /* ignore */ }
122
+ } catch {
123
+ /* ignore */
124
+ }
103
125
  return null;
104
126
  }
105
127