@xenosystem/agent-interface-host 0.1.3

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 (482) hide show
  1. package/LICENSE +67 -0
  2. package/dist/acp/AcpAgentRegistryService.d.ts +77 -0
  3. package/dist/acp/AcpAgentRegistryService.d.ts.map +1 -0
  4. package/dist/acp/AcpAgentRegistryService.js +754 -0
  5. package/dist/acp/AcpAgentRegistryService.js.map +1 -0
  6. package/dist/acp/AcpAgentTurnExecutionAdapter.d.ts +56 -0
  7. package/dist/acp/AcpAgentTurnExecutionAdapter.d.ts.map +1 -0
  8. package/dist/acp/AcpAgentTurnExecutionAdapter.js +323 -0
  9. package/dist/acp/AcpAgentTurnExecutionAdapter.js.map +1 -0
  10. package/dist/acp/AcpApprovalPortAdapter.d.ts +41 -0
  11. package/dist/acp/AcpApprovalPortAdapter.d.ts.map +1 -0
  12. package/dist/acp/AcpApprovalPortAdapter.js +82 -0
  13. package/dist/acp/AcpApprovalPortAdapter.js.map +1 -0
  14. package/dist/acp/AcpCoordinationBridge.d.ts +13 -0
  15. package/dist/acp/AcpCoordinationBridge.d.ts.map +1 -0
  16. package/dist/acp/AcpCoordinationBridge.js +13 -0
  17. package/dist/acp/AcpCoordinationBridge.js.map +1 -0
  18. package/dist/acp/AcpDiagnosticsService.d.ts +61 -0
  19. package/dist/acp/AcpDiagnosticsService.d.ts.map +1 -0
  20. package/dist/acp/AcpDiagnosticsService.js +203 -0
  21. package/dist/acp/AcpDiagnosticsService.js.map +1 -0
  22. package/dist/acp/AcpExternalCertificationHarness.d.ts +47 -0
  23. package/dist/acp/AcpExternalCertificationHarness.d.ts.map +1 -0
  24. package/dist/acp/AcpExternalCertificationHarness.js +176 -0
  25. package/dist/acp/AcpExternalCertificationHarness.js.map +1 -0
  26. package/dist/acp/AcpHostBridge.d.ts +81 -0
  27. package/dist/acp/AcpHostBridge.d.ts.map +1 -0
  28. package/dist/acp/AcpHostBridge.js +101 -0
  29. package/dist/acp/AcpHostBridge.js.map +1 -0
  30. package/dist/acp/AcpInteractivePermissionBridge.d.ts +77 -0
  31. package/dist/acp/AcpInteractivePermissionBridge.d.ts.map +1 -0
  32. package/dist/acp/AcpInteractivePermissionBridge.js +127 -0
  33. package/dist/acp/AcpInteractivePermissionBridge.js.map +1 -0
  34. package/dist/acp/AcpPermissionBridge.d.ts +19 -0
  35. package/dist/acp/AcpPermissionBridge.d.ts.map +1 -0
  36. package/dist/acp/AcpPermissionBridge.js +110 -0
  37. package/dist/acp/AcpPermissionBridge.js.map +1 -0
  38. package/dist/acp/AcpPermissionPolicy.d.ts +111 -0
  39. package/dist/acp/AcpPermissionPolicy.d.ts.map +1 -0
  40. package/dist/acp/AcpPermissionPolicy.js +167 -0
  41. package/dist/acp/AcpPermissionPolicy.js.map +1 -0
  42. package/dist/acp/AcpProcessSupervisor.d.ts +134 -0
  43. package/dist/acp/AcpProcessSupervisor.d.ts.map +1 -0
  44. package/dist/acp/AcpProcessSupervisor.js +674 -0
  45. package/dist/acp/AcpProcessSupervisor.js.map +1 -0
  46. package/dist/acp/AcpProviderApprovalService.d.ts +27 -0
  47. package/dist/acp/AcpProviderApprovalService.d.ts.map +1 -0
  48. package/dist/acp/AcpProviderApprovalService.js +128 -0
  49. package/dist/acp/AcpProviderApprovalService.js.map +1 -0
  50. package/dist/acp/AcpProviderCatalogService.d.ts +69 -0
  51. package/dist/acp/AcpProviderCatalogService.d.ts.map +1 -0
  52. package/dist/acp/AcpProviderCatalogService.js +707 -0
  53. package/dist/acp/AcpProviderCatalogService.js.map +1 -0
  54. package/dist/acp/AcpProviderModelService.d.ts +6 -0
  55. package/dist/acp/AcpProviderModelService.d.ts.map +1 -0
  56. package/dist/acp/AcpProviderModelService.js +274 -0
  57. package/dist/acp/AcpProviderModelService.js.map +1 -0
  58. package/dist/acp/AcpProviderVersionReadiness.d.ts +6 -0
  59. package/dist/acp/AcpProviderVersionReadiness.d.ts.map +1 -0
  60. package/dist/acp/AcpProviderVersionReadiness.js +100 -0
  61. package/dist/acp/AcpProviderVersionReadiness.js.map +1 -0
  62. package/dist/acp/AcpRuntimeEventMapper.d.ts +16 -0
  63. package/dist/acp/AcpRuntimeEventMapper.d.ts.map +1 -0
  64. package/dist/acp/AcpRuntimeEventMapper.js +326 -0
  65. package/dist/acp/AcpRuntimeEventMapper.js.map +1 -0
  66. package/dist/acp/AcpSessionService.d.ts +65 -0
  67. package/dist/acp/AcpSessionService.d.ts.map +1 -0
  68. package/dist/acp/AcpSessionService.js +931 -0
  69. package/dist/acp/AcpSessionService.js.map +1 -0
  70. package/dist/acp/DurableAcpPermissionPolicyStore.d.ts +25 -0
  71. package/dist/acp/DurableAcpPermissionPolicyStore.d.ts.map +1 -0
  72. package/dist/acp/DurableAcpPermissionPolicyStore.js +100 -0
  73. package/dist/acp/DurableAcpPermissionPolicyStore.js.map +1 -0
  74. package/dist/acp/acpCommandSafety.d.ts +63 -0
  75. package/dist/acp/acpCommandSafety.d.ts.map +1 -0
  76. package/dist/acp/acpCommandSafety.js +90 -0
  77. package/dist/acp/acpCommandSafety.js.map +1 -0
  78. package/dist/acp/acpErrors.d.ts +47 -0
  79. package/dist/acp/acpErrors.d.ts.map +1 -0
  80. package/dist/acp/acpErrors.js +93 -0
  81. package/dist/acp/acpErrors.js.map +1 -0
  82. package/dist/acp/acpRedaction.d.ts +9 -0
  83. package/dist/acp/acpRedaction.d.ts.map +1 -0
  84. package/dist/acp/acpRedaction.js +69 -0
  85. package/dist/acp/acpRedaction.js.map +1 -0
  86. package/dist/acp/acpSessionResume.d.ts +8 -0
  87. package/dist/acp/acpSessionResume.d.ts.map +1 -0
  88. package/dist/acp/acpSessionResume.js +31 -0
  89. package/dist/acp/acpSessionResume.js.map +1 -0
  90. package/dist/acp/acpTypes.d.ts +467 -0
  91. package/dist/acp/acpTypes.d.ts.map +1 -0
  92. package/dist/acp/acpTypes.js +2 -0
  93. package/dist/acp/acpTypes.js.map +1 -0
  94. package/dist/agent/chooseDirectoryBridge.d.ts +29 -0
  95. package/dist/agent/chooseDirectoryBridge.d.ts.map +1 -0
  96. package/dist/agent/chooseDirectoryBridge.js +116 -0
  97. package/dist/agent/chooseDirectoryBridge.js.map +1 -0
  98. package/dist/agent/permissionProfiles.d.ts +29 -0
  99. package/dist/agent/permissionProfiles.d.ts.map +1 -0
  100. package/dist/agent/permissionProfiles.js +107 -0
  101. package/dist/agent/permissionProfiles.js.map +1 -0
  102. package/dist/agent/runtimeAuthorityPrompt.d.ts +13 -0
  103. package/dist/agent/runtimeAuthorityPrompt.d.ts.map +1 -0
  104. package/dist/agent/runtimeAuthorityPrompt.js +45 -0
  105. package/dist/agent/runtimeAuthorityPrompt.js.map +1 -0
  106. package/dist/agent/runtimeModeOutputGuard.d.ts +6 -0
  107. package/dist/agent/runtimeModeOutputGuard.d.ts.map +1 -0
  108. package/dist/agent/runtimeModeOutputGuard.js +40 -0
  109. package/dist/agent/runtimeModeOutputGuard.js.map +1 -0
  110. package/dist/agent/workspacePlacementBridge.d.ts +29 -0
  111. package/dist/agent/workspacePlacementBridge.d.ts.map +1 -0
  112. package/dist/agent/workspacePlacementBridge.js +143 -0
  113. package/dist/agent/workspacePlacementBridge.js.map +1 -0
  114. package/dist/agentSearch/AgentSearchService.d.ts +81 -0
  115. package/dist/agentSearch/AgentSearchService.d.ts.map +1 -0
  116. package/dist/agentSearch/AgentSearchService.js +1038 -0
  117. package/dist/agentSearch/AgentSearchService.js.map +1 -0
  118. package/dist/agentSearch/JsonInvertedIndexAdapter.d.ts +44 -0
  119. package/dist/agentSearch/JsonInvertedIndexAdapter.d.ts.map +1 -0
  120. package/dist/agentSearch/JsonInvertedIndexAdapter.js +307 -0
  121. package/dist/agentSearch/JsonInvertedIndexAdapter.js.map +1 -0
  122. package/dist/agentSearch/SearchIndexAdapter.d.ts +33 -0
  123. package/dist/agentSearch/SearchIndexAdapter.d.ts.map +1 -0
  124. package/dist/agentSearch/SearchIndexAdapter.js +2 -0
  125. package/dist/agentSearch/SearchIndexAdapter.js.map +1 -0
  126. package/dist/agentSearch/SearchSourceWatcher.d.ts +29 -0
  127. package/dist/agentSearch/SearchSourceWatcher.d.ts.map +1 -0
  128. package/dist/agentSearch/SearchSourceWatcher.js +150 -0
  129. package/dist/agentSearch/SearchSourceWatcher.js.map +1 -0
  130. package/dist/agentSearch/SqliteFtsIndexAdapter.d.ts +58 -0
  131. package/dist/agentSearch/SqliteFtsIndexAdapter.d.ts.map +1 -0
  132. package/dist/agentSearch/SqliteFtsIndexAdapter.js +420 -0
  133. package/dist/agentSearch/SqliteFtsIndexAdapter.js.map +1 -0
  134. package/dist/agentSearch/conversationIndexer.d.ts +69 -0
  135. package/dist/agentSearch/conversationIndexer.d.ts.map +1 -0
  136. package/dist/agentSearch/conversationIndexer.js +313 -0
  137. package/dist/agentSearch/conversationIndexer.js.map +1 -0
  138. package/dist/agentSearch/searchTypes.d.ts +264 -0
  139. package/dist/agentSearch/searchTypes.d.ts.map +1 -0
  140. package/dist/agentSearch/searchTypes.js +2 -0
  141. package/dist/agentSearch/searchTypes.js.map +1 -0
  142. package/dist/agentSearch/searchUtils.d.ts +12 -0
  143. package/dist/agentSearch/searchUtils.d.ts.map +1 -0
  144. package/dist/agentSearch/searchUtils.js +125 -0
  145. package/dist/agentSearch/searchUtils.js.map +1 -0
  146. package/dist/agentSearch/workspaceMetadataIndexer.d.ts +3 -0
  147. package/dist/agentSearch/workspaceMetadataIndexer.d.ts.map +1 -0
  148. package/dist/agentSearch/workspaceMetadataIndexer.js +125 -0
  149. package/dist/agentSearch/workspaceMetadataIndexer.js.map +1 -0
  150. package/dist/cli/CliControlPlaneService.d.ts +269 -0
  151. package/dist/cli/CliControlPlaneService.d.ts.map +1 -0
  152. package/dist/cli/CliControlPlaneService.js +1874 -0
  153. package/dist/cli/CliControlPlaneService.js.map +1 -0
  154. package/dist/cloud/XenoCloudAgentTurnExecutionAdapter.d.ts +91 -0
  155. package/dist/cloud/XenoCloudAgentTurnExecutionAdapter.d.ts.map +1 -0
  156. package/dist/cloud/XenoCloudAgentTurnExecutionAdapter.js +379 -0
  157. package/dist/cloud/XenoCloudAgentTurnExecutionAdapter.js.map +1 -0
  158. package/dist/codebase/CodebaseIntelligenceService.d.ts +68 -0
  159. package/dist/codebase/CodebaseIntelligenceService.d.ts.map +1 -0
  160. package/dist/codebase/CodebaseIntelligenceService.js +1717 -0
  161. package/dist/codebase/CodebaseIntelligenceService.js.map +1 -0
  162. package/dist/codebase/LanguageServerProcessManager.d.ts +85 -0
  163. package/dist/codebase/LanguageServerProcessManager.d.ts.map +1 -0
  164. package/dist/codebase/LanguageServerProcessManager.js +607 -0
  165. package/dist/codebase/LanguageServerProcessManager.js.map +1 -0
  166. package/dist/codebase/codeTypes.d.ts +485 -0
  167. package/dist/codebase/codeTypes.d.ts.map +1 -0
  168. package/dist/codebase/codeTypes.js +2 -0
  169. package/dist/codebase/codeTypes.js.map +1 -0
  170. package/dist/codebase/codeUtils.d.ts +24 -0
  171. package/dist/codebase/codeUtils.d.ts.map +1 -0
  172. package/dist/codebase/codeUtils.js +177 -0
  173. package/dist/codebase/codeUtils.js.map +1 -0
  174. package/dist/codebase/contextPacks.d.ts +18 -0
  175. package/dist/codebase/contextPacks.d.ts.map +1 -0
  176. package/dist/codebase/contextPacks.js +180 -0
  177. package/dist/codebase/contextPacks.js.map +1 -0
  178. package/dist/codebase/dependencyGraph.d.ts +3 -0
  179. package/dist/codebase/dependencyGraph.d.ts.map +1 -0
  180. package/dist/codebase/dependencyGraph.js +209 -0
  181. package/dist/codebase/dependencyGraph.js.map +1 -0
  182. package/dist/codebase/fileIndexer.d.ts +27 -0
  183. package/dist/codebase/fileIndexer.d.ts.map +1 -0
  184. package/dist/codebase/fileIndexer.js +167 -0
  185. package/dist/codebase/fileIndexer.js.map +1 -0
  186. package/dist/codebase/symbolIndexer.d.ts +3 -0
  187. package/dist/codebase/symbolIndexer.d.ts.map +1 -0
  188. package/dist/codebase/symbolIndexer.js +184 -0
  189. package/dist/codebase/symbolIndexer.js.map +1 -0
  190. package/dist/codebase/whatChanged.d.ts +4 -0
  191. package/dist/codebase/whatChanged.d.ts.map +1 -0
  192. package/dist/codebase/whatChanged.js +138 -0
  193. package/dist/codebase/whatChanged.js.map +1 -0
  194. package/dist/coordination/CoordinationService.d.ts +166 -0
  195. package/dist/coordination/CoordinationService.d.ts.map +1 -0
  196. package/dist/coordination/CoordinationService.js +247 -0
  197. package/dist/coordination/CoordinationService.js.map +1 -0
  198. package/dist/coordination/claims.d.ts +122 -0
  199. package/dist/coordination/claims.d.ts.map +1 -0
  200. package/dist/coordination/claims.js +196 -0
  201. package/dist/coordination/claims.js.map +1 -0
  202. package/dist/coordination/coordinationTools.d.ts +40 -0
  203. package/dist/coordination/coordinationTools.d.ts.map +1 -0
  204. package/dist/coordination/coordinationTools.js +92 -0
  205. package/dist/coordination/coordinationTools.js.map +1 -0
  206. package/dist/coordination/laneBridge.d.ts +84 -0
  207. package/dist/coordination/laneBridge.d.ts.map +1 -0
  208. package/dist/coordination/laneBridge.js +86 -0
  209. package/dist/coordination/laneBridge.js.map +1 -0
  210. package/dist/coordination/messages.d.ts +225 -0
  211. package/dist/coordination/messages.d.ts.map +1 -0
  212. package/dist/coordination/messages.js +335 -0
  213. package/dist/coordination/messages.js.map +1 -0
  214. package/dist/coordination/permissionWaitRegistry.d.ts +32 -0
  215. package/dist/coordination/permissionWaitRegistry.d.ts.map +1 -0
  216. package/dist/coordination/permissionWaitRegistry.js +59 -0
  217. package/dist/coordination/permissionWaitRegistry.js.map +1 -0
  218. package/dist/coordination/query.d.ts +187 -0
  219. package/dist/coordination/query.d.ts.map +1 -0
  220. package/dist/coordination/query.js +138 -0
  221. package/dist/coordination/query.js.map +1 -0
  222. package/dist/coordination/renderInbox.d.ts +15 -0
  223. package/dist/coordination/renderInbox.d.ts.map +1 -0
  224. package/dist/coordination/renderInbox.js +19 -0
  225. package/dist/coordination/renderInbox.js.map +1 -0
  226. package/dist/coordination/runtimeEvents.d.ts +53 -0
  227. package/dist/coordination/runtimeEvents.d.ts.map +1 -0
  228. package/dist/coordination/runtimeEvents.js +112 -0
  229. package/dist/coordination/runtimeEvents.js.map +1 -0
  230. package/dist/detachedHostService.d.ts +77 -0
  231. package/dist/detachedHostService.d.ts.map +1 -0
  232. package/dist/detachedHostService.js +66 -0
  233. package/dist/detachedHostService.js.map +1 -0
  234. package/dist/detachedHostSupervisor.d.ts +102 -0
  235. package/dist/detachedHostSupervisor.d.ts.map +1 -0
  236. package/dist/detachedHostSupervisor.js +168 -0
  237. package/dist/detachedHostSupervisor.js.map +1 -0
  238. package/dist/durableRuntimeEventStore.d.ts +49 -0
  239. package/dist/durableRuntimeEventStore.d.ts.map +1 -0
  240. package/dist/durableRuntimeEventStore.js +364 -0
  241. package/dist/durableRuntimeEventStore.js.map +1 -0
  242. package/dist/engineering/EngineeringWorkbenchService.d.ts +142 -0
  243. package/dist/engineering/EngineeringWorkbenchService.d.ts.map +1 -0
  244. package/dist/engineering/EngineeringWorkbenchService.js +2301 -0
  245. package/dist/engineering/EngineeringWorkbenchService.js.map +1 -0
  246. package/dist/engineering/LandingService.d.ts +112 -0
  247. package/dist/engineering/LandingService.d.ts.map +1 -0
  248. package/dist/engineering/LandingService.js +239 -0
  249. package/dist/engineering/LandingService.js.map +1 -0
  250. package/dist/engineering/engineeringTypes.d.ts +2 -0
  251. package/dist/engineering/engineeringTypes.d.ts.map +1 -0
  252. package/dist/engineering/engineeringTypes.js +2 -0
  253. package/dist/engineering/engineeringTypes.js.map +1 -0
  254. package/dist/engineering/patchReview.d.ts +11 -0
  255. package/dist/engineering/patchReview.d.ts.map +1 -0
  256. package/dist/engineering/patchReview.js +174 -0
  257. package/dist/engineering/patchReview.js.map +1 -0
  258. package/dist/index.d.ts +834 -0
  259. package/dist/index.d.ts.map +1 -0
  260. package/dist/index.js +3242 -0
  261. package/dist/index.js.map +1 -0
  262. package/dist/intake/IntakeService.d.ts +84 -0
  263. package/dist/intake/IntakeService.d.ts.map +1 -0
  264. package/dist/intake/IntakeService.js +117 -0
  265. package/dist/intake/IntakeService.js.map +1 -0
  266. package/dist/intake/RepositoryTodoIntakeSource.d.ts +72 -0
  267. package/dist/intake/RepositoryTodoIntakeSource.d.ts.map +1 -0
  268. package/dist/intake/RepositoryTodoIntakeSource.js +168 -0
  269. package/dist/intake/RepositoryTodoIntakeSource.js.map +1 -0
  270. package/dist/intake/WorkspaceTodoIntakeSource.d.ts +53 -0
  271. package/dist/intake/WorkspaceTodoIntakeSource.d.ts.map +1 -0
  272. package/dist/intake/WorkspaceTodoIntakeSource.js +81 -0
  273. package/dist/intake/WorkspaceTodoIntakeSource.js.map +1 -0
  274. package/dist/isolation/CommandExecution.d.ts +132 -0
  275. package/dist/isolation/CommandExecution.d.ts.map +1 -0
  276. package/dist/isolation/CommandExecution.js +48 -0
  277. package/dist/isolation/CommandExecution.js.map +1 -0
  278. package/dist/isolation/LocalCommandExecutor.d.ts +27 -0
  279. package/dist/isolation/LocalCommandExecutor.d.ts.map +1 -0
  280. package/dist/isolation/LocalCommandExecutor.js +97 -0
  281. package/dist/isolation/LocalCommandExecutor.js.map +1 -0
  282. package/dist/isolation/RunExecutionEnvironment.d.ts +135 -0
  283. package/dist/isolation/RunExecutionEnvironment.d.ts.map +1 -0
  284. package/dist/isolation/RunExecutionEnvironment.js +206 -0
  285. package/dist/isolation/RunExecutionEnvironment.js.map +1 -0
  286. package/dist/isolation/RunIsolationService.d.ts +90 -0
  287. package/dist/isolation/RunIsolationService.d.ts.map +1 -0
  288. package/dist/isolation/RunIsolationService.js +86 -0
  289. package/dist/isolation/RunIsolationService.js.map +1 -0
  290. package/dist/isolation/SandboxCommandExecutor.d.ts +93 -0
  291. package/dist/isolation/SandboxCommandExecutor.d.ts.map +1 -0
  292. package/dist/isolation/SandboxCommandExecutor.js +189 -0
  293. package/dist/isolation/SandboxCommandExecutor.js.map +1 -0
  294. package/dist/knowledge/WorkspaceKnowledgeService.d.ts +71 -0
  295. package/dist/knowledge/WorkspaceKnowledgeService.d.ts.map +1 -0
  296. package/dist/knowledge/WorkspaceKnowledgeService.js +103 -0
  297. package/dist/knowledge/WorkspaceKnowledgeService.js.map +1 -0
  298. package/dist/localHostAuthority.d.ts +24 -0
  299. package/dist/localHostAuthority.d.ts.map +1 -0
  300. package/dist/localHostAuthority.js +87 -0
  301. package/dist/localHostAuthority.js.map +1 -0
  302. package/dist/localHostLease.d.ts +51 -0
  303. package/dist/localHostLease.d.ts.map +1 -0
  304. package/dist/localHostLease.js +167 -0
  305. package/dist/localHostLease.js.map +1 -0
  306. package/dist/localHostPaths.d.ts +30 -0
  307. package/dist/localHostPaths.d.ts.map +1 -0
  308. package/dist/localHostPaths.js +60 -0
  309. package/dist/localHostPaths.js.map +1 -0
  310. package/dist/localRpcTransport.d.ts +21 -0
  311. package/dist/localRpcTransport.d.ts.map +1 -0
  312. package/dist/localRpcTransport.js +423 -0
  313. package/dist/localRpcTransport.js.map +1 -0
  314. package/dist/node.d.ts +104 -0
  315. package/dist/node.d.ts.map +1 -0
  316. package/dist/node.js +103 -0
  317. package/dist/node.js.map +1 -0
  318. package/dist/observation/DirectoryBaselineScanner.d.ts +44 -0
  319. package/dist/observation/DirectoryBaselineScanner.d.ts.map +1 -0
  320. package/dist/observation/DirectoryBaselineScanner.js +112 -0
  321. package/dist/observation/DirectoryBaselineScanner.js.map +1 -0
  322. package/dist/observation/MountContentReader.d.ts +63 -0
  323. package/dist/observation/MountContentReader.d.ts.map +1 -0
  324. package/dist/observation/MountContentReader.js +158 -0
  325. package/dist/observation/MountContentReader.js.map +1 -0
  326. package/dist/observation/RunObservationService.d.ts +229 -0
  327. package/dist/observation/RunObservationService.d.ts.map +1 -0
  328. package/dist/observation/RunObservationService.js +248 -0
  329. package/dist/observation/RunObservationService.js.map +1 -0
  330. package/dist/observation/XenoUseObservationSource.d.ts +42 -0
  331. package/dist/observation/XenoUseObservationSource.d.ts.map +1 -0
  332. package/dist/observation/XenoUseObservationSource.js +104 -0
  333. package/dist/observation/XenoUseObservationSource.js.map +1 -0
  334. package/dist/observation/XenoUseRunObserver.d.ts +140 -0
  335. package/dist/observation/XenoUseRunObserver.d.ts.map +1 -0
  336. package/dist/observation/XenoUseRunObserver.js +256 -0
  337. package/dist/observation/XenoUseRunObserver.js.map +1 -0
  338. package/dist/pluginMcp/PluginMcpManagerService.d.ts +141 -0
  339. package/dist/pluginMcp/PluginMcpManagerService.d.ts.map +1 -0
  340. package/dist/pluginMcp/PluginMcpManagerService.js +1821 -0
  341. package/dist/pluginMcp/PluginMcpManagerService.js.map +1 -0
  342. package/dist/pluginMcp/pluginMcpTypes.d.ts +349 -0
  343. package/dist/pluginMcp/pluginMcpTypes.d.ts.map +1 -0
  344. package/dist/pluginMcp/pluginMcpTypes.js +2 -0
  345. package/dist/pluginMcp/pluginMcpTypes.js.map +1 -0
  346. package/dist/policy/WorkspacePolicyService.d.ts +83 -0
  347. package/dist/policy/WorkspacePolicyService.d.ts.map +1 -0
  348. package/dist/policy/WorkspacePolicyService.js +809 -0
  349. package/dist/policy/WorkspacePolicyService.js.map +1 -0
  350. package/dist/policy/policyGuard.d.ts +27 -0
  351. package/dist/policy/policyGuard.d.ts.map +1 -0
  352. package/dist/policy/policyGuard.js +143 -0
  353. package/dist/policy/policyGuard.js.map +1 -0
  354. package/dist/policy/policyTypes.d.ts +190 -0
  355. package/dist/policy/policyTypes.d.ts.map +1 -0
  356. package/dist/policy/policyTypes.js +2 -0
  357. package/dist/policy/policyTypes.js.map +1 -0
  358. package/dist/runtime/RuntimeEventStore.d.ts +42 -0
  359. package/dist/runtime/RuntimeEventStore.d.ts.map +1 -0
  360. package/dist/runtime/RuntimeEventStore.js +412 -0
  361. package/dist/runtime/RuntimeEventStore.js.map +1 -0
  362. package/dist/runtime/RuntimeEventStoreRepositoryAdapter.d.ts +21 -0
  363. package/dist/runtime/RuntimeEventStoreRepositoryAdapter.d.ts.map +1 -0
  364. package/dist/runtime/RuntimeEventStoreRepositoryAdapter.js +41 -0
  365. package/dist/runtime/RuntimeEventStoreRepositoryAdapter.js.map +1 -0
  366. package/dist/runtime/RuntimeTimelineProjection.d.ts +5 -0
  367. package/dist/runtime/RuntimeTimelineProjection.d.ts.map +1 -0
  368. package/dist/runtime/RuntimeTimelineProjection.js +705 -0
  369. package/dist/runtime/RuntimeTimelineProjection.js.map +1 -0
  370. package/dist/runtime/runtimeEventTypes.d.ts +73 -0
  371. package/dist/runtime/runtimeEventTypes.d.ts.map +1 -0
  372. package/dist/runtime/runtimeEventTypes.js +2 -0
  373. package/dist/runtime/runtimeEventTypes.js.map +1 -0
  374. package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.d.ts +117 -0
  375. package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.d.ts.map +1 -0
  376. package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.js +214 -0
  377. package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.js.map +1 -0
  378. package/dist/session/AgentSessionService.d.ts +285 -0
  379. package/dist/session/AgentSessionService.d.ts.map +1 -0
  380. package/dist/session/AgentSessionService.js +444 -0
  381. package/dist/session/AgentSessionService.js.map +1 -0
  382. package/dist/session/bufferedSessionPty.d.ts +27 -0
  383. package/dist/session/bufferedSessionPty.d.ts.map +1 -0
  384. package/dist/session/bufferedSessionPty.js +49 -0
  385. package/dist/session/bufferedSessionPty.js.map +1 -0
  386. package/dist/session/renderSupport.d.ts +53 -0
  387. package/dist/session/renderSupport.d.ts.map +1 -0
  388. package/dist/session/renderSupport.js +41 -0
  389. package/dist/session/renderSupport.js.map +1 -0
  390. package/dist/session/runtimeEventChannel.d.ts +56 -0
  391. package/dist/session/runtimeEventChannel.d.ts.map +1 -0
  392. package/dist/session/runtimeEventChannel.js +53 -0
  393. package/dist/session/runtimeEventChannel.js.map +1 -0
  394. package/dist/state/JsonAgentStateRepository.d.ts +29 -0
  395. package/dist/state/JsonAgentStateRepository.d.ts.map +1 -0
  396. package/dist/state/JsonAgentStateRepository.js +165 -0
  397. package/dist/state/JsonAgentStateRepository.js.map +1 -0
  398. package/dist/state/SqliteAgentStateRepository.d.ts +58 -0
  399. package/dist/state/SqliteAgentStateRepository.d.ts.map +1 -0
  400. package/dist/state/SqliteAgentStateRepository.js +777 -0
  401. package/dist/state/SqliteAgentStateRepository.js.map +1 -0
  402. package/dist/state/createAgentStateRepository.d.ts +4 -0
  403. package/dist/state/createAgentStateRepository.d.ts.map +1 -0
  404. package/dist/state/createAgentStateRepository.js +12 -0
  405. package/dist/state/createAgentStateRepository.js.map +1 -0
  406. package/dist/state/stateSanitizers.d.ts +7 -0
  407. package/dist/state/stateSanitizers.d.ts.map +1 -0
  408. package/dist/state/stateSanitizers.js +87 -0
  409. package/dist/state/stateSanitizers.js.map +1 -0
  410. package/dist/subagents/AcpSubagentExecutionAdapter.d.ts +12 -0
  411. package/dist/subagents/AcpSubagentExecutionAdapter.d.ts.map +1 -0
  412. package/dist/subagents/AcpSubagentExecutionAdapter.js +119 -0
  413. package/dist/subagents/AcpSubagentExecutionAdapter.js.map +1 -0
  414. package/dist/subagents/CliSubagentExecutionAdapter.d.ts +13 -0
  415. package/dist/subagents/CliSubagentExecutionAdapter.d.ts.map +1 -0
  416. package/dist/subagents/CliSubagentExecutionAdapter.js +217 -0
  417. package/dist/subagents/CliSubagentExecutionAdapter.js.map +1 -0
  418. package/dist/subagents/HostTurnSubagentExecutionAdapter.d.ts +78 -0
  419. package/dist/subagents/HostTurnSubagentExecutionAdapter.d.ts.map +1 -0
  420. package/dist/subagents/HostTurnSubagentExecutionAdapter.js +160 -0
  421. package/dist/subagents/HostTurnSubagentExecutionAdapter.js.map +1 -0
  422. package/dist/subagents/SubagentRunService.d.ts +103 -0
  423. package/dist/subagents/SubagentRunService.d.ts.map +1 -0
  424. package/dist/subagents/SubagentRunService.js +1183 -0
  425. package/dist/subagents/SubagentRunService.js.map +1 -0
  426. package/dist/subagents/SubagentScheduler.d.ts +167 -0
  427. package/dist/subagents/SubagentScheduler.d.ts.map +1 -0
  428. package/dist/subagents/SubagentScheduler.js +530 -0
  429. package/dist/subagents/SubagentScheduler.js.map +1 -0
  430. package/dist/subagents/TeamAgentRouter.d.ts +104 -0
  431. package/dist/subagents/TeamAgentRouter.d.ts.map +1 -0
  432. package/dist/subagents/TeamAgentRouter.js +435 -0
  433. package/dist/subagents/TeamAgentRouter.js.map +1 -0
  434. package/dist/subagents/capabilityMatcher.d.ts +3 -0
  435. package/dist/subagents/capabilityMatcher.d.ts.map +1 -0
  436. package/dist/subagents/capabilityMatcher.js +127 -0
  437. package/dist/subagents/capabilityMatcher.js.map +1 -0
  438. package/dist/subagents/subagentRunPort.d.ts +43 -0
  439. package/dist/subagents/subagentRunPort.d.ts.map +1 -0
  440. package/dist/subagents/subagentRunPort.js +24 -0
  441. package/dist/subagents/subagentRunPort.js.map +1 -0
  442. package/dist/subagents/subagentTypes.d.ts +330 -0
  443. package/dist/subagents/subagentTypes.d.ts.map +1 -0
  444. package/dist/subagents/subagentTypes.js +2 -0
  445. package/dist/subagents/subagentTypes.js.map +1 -0
  446. package/dist/subagents/subagentWorkspaceAuthority.d.ts +29 -0
  447. package/dist/subagents/subagentWorkspaceAuthority.d.ts.map +1 -0
  448. package/dist/subagents/subagentWorkspaceAuthority.js +173 -0
  449. package/dist/subagents/subagentWorkspaceAuthority.js.map +1 -0
  450. package/dist/support/SupportDiagnosticsService.d.ts +87 -0
  451. package/dist/support/SupportDiagnosticsService.d.ts.map +1 -0
  452. package/dist/support/SupportDiagnosticsService.js +1199 -0
  453. package/dist/support/SupportDiagnosticsService.js.map +1 -0
  454. package/dist/turns/DurableInterruptedTurnStore.d.ts +14 -0
  455. package/dist/turns/DurableInterruptedTurnStore.d.ts.map +1 -0
  456. package/dist/turns/DurableInterruptedTurnStore.js +63 -0
  457. package/dist/turns/DurableInterruptedTurnStore.js.map +1 -0
  458. package/dist/turns/interruptedTurns.d.ts +50 -0
  459. package/dist/turns/interruptedTurns.d.ts.map +1 -0
  460. package/dist/turns/interruptedTurns.js +54 -0
  461. package/dist/turns/interruptedTurns.js.map +1 -0
  462. package/dist/turns/turnAdmission.d.ts +113 -0
  463. package/dist/turns/turnAdmission.d.ts.map +1 -0
  464. package/dist/turns/turnAdmission.js +136 -0
  465. package/dist/turns/turnAdmission.js.map +1 -0
  466. package/dist/workspace/WorkspaceHostService.d.ts +126 -0
  467. package/dist/workspace/WorkspaceHostService.d.ts.map +1 -0
  468. package/dist/workspace/WorkspaceHostService.js +841 -0
  469. package/dist/workspace/WorkspaceHostService.js.map +1 -0
  470. package/dist/workspace/WorkspaceShellService.d.ts +71 -0
  471. package/dist/workspace/WorkspaceShellService.d.ts.map +1 -0
  472. package/dist/workspace/WorkspaceShellService.js +273 -0
  473. package/dist/workspace/WorkspaceShellService.js.map +1 -0
  474. package/dist/workspace/fileAssociations.d.ts +12 -0
  475. package/dist/workspace/fileAssociations.d.ts.map +1 -0
  476. package/dist/workspace/fileAssociations.js +202 -0
  477. package/dist/workspace/fileAssociations.js.map +1 -0
  478. package/dist/workspace/scrollbackBuffer.d.ts +48 -0
  479. package/dist/workspace/scrollbackBuffer.d.ts.map +1 -0
  480. package/dist/workspace/scrollbackBuffer.js +94 -0
  481. package/dist/workspace/scrollbackBuffer.js.map +1 -0
  482. package/package.json +42 -0
@@ -0,0 +1,1717 @@
1
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
2
+ import { isAbsolute, join, relative, resolve } from 'path';
3
+ import { buildDependencyGraph } from './dependencyGraph.js';
4
+ import { buildFileIndex, createStats } from './fileIndexer.js';
5
+ import { extractSymbols } from './symbolIndexer.js';
6
+ import { createSnippet, hashText, isPathInside, lineColumnAt, normalizeForSearch, resolveRootDirectory, safeReadJson, safeWriteJson, workspaceIndexDirectory, } from './codeUtils.js';
7
+ import { ContextPackRepository } from './contextPacks.js';
8
+ import { LanguageServerProcessManager } from './LanguageServerProcessManager.js';
9
+ import { summarizeWhatChanged } from './whatChanged.js';
10
+ import { getEngineeringWorkbenchService } from '../engineering/EngineeringWorkbenchService.js';
11
+ const SNAPSHOT_FILE = 'snapshot.json';
12
+ const MANIFEST_FILE = 'manifest.json';
13
+ const CODE_ACTION_PATCH_STORE_FILE = 'code-action-patches.json';
14
+ export class CodebaseIntelligenceService {
15
+ snapshots = new Map();
16
+ contextPacks = new ContextPackRepository();
17
+ languageServers = new LanguageServerProcessManager();
18
+ async indexWorkspace(request) {
19
+ try {
20
+ const rootDirectory = resolveRootDirectory(request.rootDirectory, request.allowedDirectories);
21
+ const snapshot = this.buildSnapshot(rootDirectory, request);
22
+ this.snapshots.set(rootDirectory, snapshot);
23
+ this.saveSnapshot(snapshot);
24
+ return { success: true, snapshot, stats: snapshot.stats };
25
+ }
26
+ catch (err) {
27
+ return { success: false, error: errorMessage(err) };
28
+ }
29
+ }
30
+ async searchFiles(request) {
31
+ try {
32
+ const snapshot = await this.ensureIndexed(request.rootDirectory, request.allowedDirectories);
33
+ const query = normalizeForSearch(request.query || '');
34
+ const extensions = new Set((request.extensions || []).map((ext) => ext.toLowerCase().startsWith('.') ? ext.toLowerCase() : `.${ext.toLowerCase()}`));
35
+ const languages = new Set(request.languages || []);
36
+ const limit = clampLimit(request.limit, 100);
37
+ const scored = snapshot.files
38
+ .filter((file) => !extensions.size || extensions.has(file.extension))
39
+ .filter((file) => !languages.size || languages.has(file.language))
40
+ .map((file) => ({ file, score: scoreFile(file.relativePath, file.basename, query) }))
41
+ .filter((entry) => !query || entry.score > 0)
42
+ .sort((a, b) => b.score - a.score || a.file.relativePath.localeCompare(b.file.relativePath));
43
+ return { success: true, files: scored.slice(0, limit).map((entry) => entry.file), total: scored.length };
44
+ }
45
+ catch (err) {
46
+ return { success: false, files: [], total: 0, error: errorMessage(err) };
47
+ }
48
+ }
49
+ async searchText(request) {
50
+ try {
51
+ if (!request.query || !request.query.trim())
52
+ return { success: true, results: [], total: 0 };
53
+ const snapshot = await this.ensureIndexed(request.rootDirectory, request.allowedDirectories);
54
+ const results = this.searchTextSync(snapshot, request);
55
+ return { success: true, results, total: results.length };
56
+ }
57
+ catch (err) {
58
+ return { success: false, results: [], total: 0, error: errorMessage(err) };
59
+ }
60
+ }
61
+ async listSymbols(request) {
62
+ try {
63
+ const snapshot = await this.ensureIndexed(request.rootDirectory, request.allowedDirectories);
64
+ const query = normalizeForSearch(request.query || '');
65
+ const kinds = new Set(request.kinds || []);
66
+ const limit = clampLimit(request.limit, 200);
67
+ const symbols = snapshot.symbols
68
+ .filter((symbol) => !kinds.size || kinds.has(symbol.kind))
69
+ .filter((symbol) => !request.pathPrefix || symbol.relativePath.startsWith(request.pathPrefix))
70
+ .map((symbol) => ({ symbol, score: scoreSymbol(symbol.name, symbol.relativePath, query) }))
71
+ .filter((entry) => !query || entry.score > 0)
72
+ .sort((a, b) => b.score - a.score || a.symbol.relativePath.localeCompare(b.symbol.relativePath) || a.symbol.line - b.symbol.line);
73
+ return { success: true, symbols: symbols.slice(0, limit).map((entry) => entry.symbol), total: symbols.length };
74
+ }
75
+ catch (err) {
76
+ return { success: false, symbols: [], total: 0, error: errorMessage(err) };
77
+ }
78
+ }
79
+ async getSymbol(request) {
80
+ try {
81
+ const snapshot = await this.ensureIndexed(request.rootDirectory, request.allowedDirectories);
82
+ const symbol = snapshot.symbols.find((candidate) => candidate.id === request.symbolId);
83
+ if (!symbol)
84
+ return { success: false, error: 'Symbol not found.' };
85
+ const file = snapshot.files.find((candidate) => candidate.absolutePath === symbol.filePath);
86
+ const references = this.searchTextSync(snapshot, {
87
+ query: symbol.name,
88
+ limit: 30,
89
+ });
90
+ return { success: true, symbol, file, references };
91
+ }
92
+ catch (err) {
93
+ return { success: false, error: errorMessage(err) };
94
+ }
95
+ }
96
+ async references(request) {
97
+ try {
98
+ const snapshot = await this.ensureIndexed(request.rootDirectory, request.allowedDirectories);
99
+ const symbol = request.symbolId ? snapshot.symbols.find((candidate) => candidate.id === request.symbolId) : undefined;
100
+ const query = request.query || symbol?.name || '';
101
+ if (!query)
102
+ return { success: false, results: [], total: 0, error: 'Missing symbolId or query.' };
103
+ const results = this.searchTextSync(snapshot, {
104
+ query,
105
+ limit: request.limit || 100,
106
+ });
107
+ return {
108
+ success: true,
109
+ results,
110
+ total: results.length,
111
+ routing: fallbackIndexRouting(symbol?.language || 'unknown', 'Reference lookup is currently served from the local index when an exact LSP position is not provided.'),
112
+ };
113
+ }
114
+ catch (err) {
115
+ return { success: false, results: [], total: 0, error: errorMessage(err) };
116
+ }
117
+ }
118
+ async codeActions(request) {
119
+ try {
120
+ const snapshot = await this.ensureIndexed(request.rootDirectory, request.allowedDirectories);
121
+ const targetPath = resolveRequestedFilePath(snapshot.rootDirectory, request.filePath);
122
+ if (!isPathInside(targetPath, snapshot.rootDirectory)) {
123
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetPath, actions: [], diagnostics: [], error: 'filePath is outside the indexed workspace.' };
124
+ }
125
+ const targetFile = snapshot.files.find((file) => normalizePathKey(file.absolutePath) === normalizePathKey(targetPath));
126
+ if (!targetFile || !targetFile.textContent || !targetFile.isTextIndexed) {
127
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetPath, actions: [], diagnostics: [], error: 'filePath is not indexed as a text file.' };
128
+ }
129
+ if (!isTypeScriptLike(targetFile.extension)) {
130
+ if (isExternalLspLanguage(targetFile.language)) {
131
+ try {
132
+ const external = await this.languageServers.codeActions({
133
+ rootDirectory: snapshot.rootDirectory,
134
+ language: targetFile.language,
135
+ filePath: targetFile.absolutePath,
136
+ text: targetFile.textContent || '',
137
+ line: request.line,
138
+ column: request.column,
139
+ limit: request.limit,
140
+ });
141
+ const limit = Math.max(1, Math.min(request.limit || 20, 100));
142
+ return {
143
+ success: true,
144
+ rootDirectory: snapshot.rootDirectory,
145
+ filePath: targetFile.absolutePath,
146
+ actions: external.actions.slice(0, limit).map((action) => {
147
+ const editPreview = action.editPreview || 'Language server action preview is not available.';
148
+ const patchPreview = this.recordPatchPreview({
149
+ id: createPatchPreviewId(editPreview || action.title),
150
+ rootDirectory: snapshot.rootDirectory,
151
+ filePath: targetFile.absolutePath,
152
+ relativePath: targetFile.relativePath,
153
+ title: action.title,
154
+ operation: 'code-action',
155
+ source: action.source,
156
+ serviceId: external.service.id,
157
+ route: 'external-lsp',
158
+ language: targetFile.language,
159
+ files: [targetFile.relativePath],
160
+ editPreview,
161
+ expectedFileHash: targetFile.hash,
162
+ });
163
+ return {
164
+ id: action.id,
165
+ title: action.title,
166
+ kind: action.kind,
167
+ source: action.source,
168
+ language: targetFile.language,
169
+ serviceId: external.service.id,
170
+ route: 'external-lsp',
171
+ filePath: targetFile.absolutePath,
172
+ relativePath: targetFile.relativePath,
173
+ line: Math.max(1, request.line || 1),
174
+ column: Math.max(1, request.column || 1),
175
+ supportsApply: !!action.rawEdit,
176
+ editPreview,
177
+ patchPreviewId: patchPreview.id,
178
+ patchPreview,
179
+ applyRequires: ['checkpoint', 'patch-preview'],
180
+ };
181
+ }),
182
+ diagnostics: external.diagnostics.map((diagnostic, index) => mapExternalDiagnostic(snapshot.rootDirectory, targetFile, diagnostic, external.service.id, index)),
183
+ routing: externalLspRouting(targetFile.language, external.service),
184
+ };
185
+ }
186
+ catch (err) {
187
+ const reason = `${targetFile.language} language server unavailable: ${errorMessage(err)}`;
188
+ const degradedState = this.degradedStateForLanguage(snapshot.rootDirectory, targetFile.language, reason);
189
+ return {
190
+ success: false,
191
+ rootDirectory: snapshot.rootDirectory,
192
+ filePath: targetFile.absolutePath,
193
+ actions: [],
194
+ diagnostics: [],
195
+ routing: {
196
+ ...fallbackIndexRouting(targetFile.language, reason),
197
+ serviceId: degradedState.serviceId,
198
+ serviceLabel: degradedState.serviceLabel,
199
+ installHint: degradedState.installHint,
200
+ status: degradedState.status,
201
+ },
202
+ degradedState,
203
+ error: reason,
204
+ };
205
+ }
206
+ }
207
+ return {
208
+ success: true,
209
+ rootDirectory: snapshot.rootDirectory,
210
+ filePath: targetFile.absolutePath,
211
+ actions: [],
212
+ diagnostics: [],
213
+ routing: fallbackIndexRouting(targetFile.language, 'No language server route is configured for this file type.'),
214
+ error: 'Project code actions currently support TypeScript and JavaScript files.',
215
+ };
216
+ }
217
+ const ts = await import('typescript');
218
+ const scriptFiles = snapshot.files.filter((file) => file.textContent && file.isTextIndexed && isTypeScriptLike(file.extension));
219
+ const fileByPath = new Map(scriptFiles.map((file) => [normalizePathKey(file.absolutePath), file]));
220
+ const compilerOptions = {
221
+ allowJs: true,
222
+ checkJs: false,
223
+ jsx: ts.JsxEmit.ReactJSX,
224
+ module: ts.ModuleKind.NodeNext,
225
+ moduleResolution: ts.ModuleResolutionKind.NodeNext,
226
+ target: ts.ScriptTarget.ES2022,
227
+ skipLibCheck: true,
228
+ strict: false,
229
+ };
230
+ const host = {
231
+ getCompilationSettings: () => compilerOptions,
232
+ getScriptFileNames: () => scriptFiles.map((file) => file.absolutePath),
233
+ getScriptVersion: (fileName) => fileByPath.get(normalizePathKey(fileName))?.hash || '0',
234
+ getScriptSnapshot: (fileName) => {
235
+ const file = fileByPath.get(normalizePathKey(fileName));
236
+ if (file?.textContent !== undefined)
237
+ return ts.ScriptSnapshot.fromString(file.textContent);
238
+ const diskText = ts.sys.readFile(fileName);
239
+ return diskText === undefined ? undefined : ts.ScriptSnapshot.fromString(diskText);
240
+ },
241
+ getCurrentDirectory: () => snapshot.rootDirectory,
242
+ getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),
243
+ useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
244
+ fileExists: (fileName) => fileByPath.has(normalizePathKey(fileName)) || ts.sys.fileExists(fileName),
245
+ readFile: (fileName) => fileByPath.get(normalizePathKey(fileName))?.textContent || ts.sys.readFile(fileName),
246
+ readDirectory: ts.sys.readDirectory,
247
+ directoryExists: ts.sys.directoryExists,
248
+ getDirectories: ts.sys.getDirectories,
249
+ ...(ts.sys.realpath ? { realpath: ts.sys.realpath } : {}),
250
+ };
251
+ const languageService = ts.createLanguageService(host, ts.createDocumentRegistry());
252
+ const diagnostics = [
253
+ ...languageService.getSyntacticDiagnostics(targetFile.absolutePath),
254
+ ...languageService.getSemanticDiagnostics(targetFile.absolutePath),
255
+ ...languageService.getSuggestionDiagnostics(targetFile.absolutePath),
256
+ ];
257
+ const mappedDiagnostics = diagnostics
258
+ .map((diagnostic) => mapTsDiagnostic(ts, snapshot.rootDirectory, targetFile.absolutePath, targetFile.textContent || '', diagnostic))
259
+ .filter((diagnostic) => !!diagnostic)
260
+ .map((diagnostic) => ({
261
+ ...diagnostic,
262
+ language: targetFile.language,
263
+ serviceId: 'typescript-language-service',
264
+ route: 'embedded-typescript',
265
+ }));
266
+ const formatOptions = { indentSize: 2, tabSize: 2, convertTabsToSpaces: true, newLineCharacter: '\n' };
267
+ const preferences = { includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true };
268
+ const requestedPosition = offsetAtPosition(targetFile.textContent || '', request.line, request.column);
269
+ const codeActions = [];
270
+ const limit = Math.max(1, Math.min(request.limit || 20, 100));
271
+ for (const diagnostic of diagnostics) {
272
+ const start = typeof diagnostic.start === 'number' ? diagnostic.start : requestedPosition;
273
+ const end = start + Math.max(1, diagnostic.length || 1);
274
+ const fixes = languageService.getCodeFixesAtPosition(targetFile.absolutePath, start, end, [diagnostic.code], formatOptions, preferences);
275
+ for (const fix of fixes) {
276
+ const editPreview = previewTextChanges(snapshot.rootDirectory, fix.changes);
277
+ const patchPreview = this.recordPatchPreview({
278
+ id: createPatchPreviewId(editPreview),
279
+ rootDirectory: snapshot.rootDirectory,
280
+ filePath: targetFile.absolutePath,
281
+ relativePath: targetFile.relativePath,
282
+ title: fix.description,
283
+ operation: 'code-action',
284
+ source: 'typescript-language-service',
285
+ serviceId: 'typescript-language-service',
286
+ route: 'embedded-typescript',
287
+ language: targetFile.language,
288
+ files: textChangeFiles(snapshot.rootDirectory, fix.changes),
289
+ editPreview,
290
+ expectedFileHash: targetFile.hash,
291
+ });
292
+ codeActions.push({
293
+ id: `fix-${diagnostic.code}-${hashText(fix.fixName + fix.description).slice(0, 10)}`,
294
+ title: fix.description,
295
+ kind: 'quickfix',
296
+ source: 'typescript-language-service',
297
+ language: targetFile.language,
298
+ serviceId: 'typescript-language-service',
299
+ route: 'embedded-typescript',
300
+ filePath: targetFile.absolutePath,
301
+ relativePath: targetFile.relativePath,
302
+ line: mappedDiagnostics.find((entry) => entry.code === String(diagnostic.code))?.line || 1,
303
+ column: mappedDiagnostics.find((entry) => entry.code === String(diagnostic.code))?.column || 1,
304
+ diagnosticCode: String(diagnostic.code),
305
+ fixName: fix.fixName,
306
+ supportsApply: fix.changes.length > 0,
307
+ editPreview,
308
+ patchPreviewId: patchPreview.id,
309
+ patchPreview,
310
+ applyRequires: ['checkpoint', 'patch-preview'],
311
+ });
312
+ if (codeActions.length >= limit)
313
+ break;
314
+ }
315
+ if (codeActions.length >= limit)
316
+ break;
317
+ }
318
+ if (codeActions.length < limit) {
319
+ const refactors = languageService.getApplicableRefactors(targetFile.absolutePath, requestedPosition, preferences, undefined);
320
+ const loc = lineColumnAt(targetFile.textContent || '', requestedPosition);
321
+ for (const refactor of refactors) {
322
+ for (const action of refactor.actions) {
323
+ const editPreview = refactor.description;
324
+ const patchPreview = this.recordPatchPreview({
325
+ id: createPatchPreviewId(`${refactor.name}:${action.name}:${refactor.description}`),
326
+ rootDirectory: snapshot.rootDirectory,
327
+ filePath: targetFile.absolutePath,
328
+ relativePath: targetFile.relativePath,
329
+ title: action.description || refactor.description,
330
+ operation: 'code-action',
331
+ source: 'typescript-language-service',
332
+ serviceId: 'typescript-language-service',
333
+ route: 'embedded-typescript',
334
+ language: targetFile.language,
335
+ files: [targetFile.relativePath],
336
+ editPreview,
337
+ expectedFileHash: targetFile.hash,
338
+ });
339
+ codeActions.push({
340
+ id: `refactor-${hashText(refactor.name + action.name).slice(0, 10)}`,
341
+ title: action.description || refactor.description,
342
+ kind: `refactor.${refactor.name}`,
343
+ source: 'typescript-language-service',
344
+ language: targetFile.language,
345
+ serviceId: 'typescript-language-service',
346
+ route: 'embedded-typescript',
347
+ filePath: targetFile.absolutePath,
348
+ relativePath: targetFile.relativePath,
349
+ line: loc.line,
350
+ column: loc.column,
351
+ refactorName: refactor.name,
352
+ refactorActionName: action.name,
353
+ supportsApply: true,
354
+ editPreview,
355
+ patchPreviewId: patchPreview.id,
356
+ patchPreview,
357
+ applyRequires: ['checkpoint', 'patch-preview'],
358
+ });
359
+ if (codeActions.length >= limit)
360
+ break;
361
+ }
362
+ if (codeActions.length >= limit)
363
+ break;
364
+ }
365
+ }
366
+ languageService.dispose();
367
+ return {
368
+ success: true,
369
+ rootDirectory: snapshot.rootDirectory,
370
+ filePath: targetFile.absolutePath,
371
+ actions: codeActions,
372
+ diagnostics: mappedDiagnostics,
373
+ routing: embeddedTypeScriptRouting(targetFile.language),
374
+ };
375
+ }
376
+ catch (err) {
377
+ return { success: false, rootDirectory: request.rootDirectory || '', actions: [], diagnostics: [], error: errorMessage(err) };
378
+ }
379
+ }
380
+ async applyCodeAction(request) {
381
+ try {
382
+ const snapshot = await this.ensureIndexed(request.rootDirectory, request.allowedDirectories);
383
+ const target = resolveIndexedTextFile(snapshot, request.filePath);
384
+ if (!target.success)
385
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: target.filePath, applied: false, edits: [], error: target.error };
386
+ const targetFile = target.file;
387
+ if (!isTypeScriptLike(targetFile.extension)) {
388
+ if (isExternalLspLanguage(targetFile.language)) {
389
+ try {
390
+ const external = await this.languageServers.codeActions({
391
+ rootDirectory: snapshot.rootDirectory,
392
+ language: targetFile.language,
393
+ filePath: targetFile.absolutePath,
394
+ text: targetFile.textContent || '',
395
+ line: request.line,
396
+ column: request.column,
397
+ limit: request.limit,
398
+ });
399
+ const selected = external.actions.find((action) => matchesRequestedCodeAction(request, {
400
+ id: action.id,
401
+ title: action.title,
402
+ kind: action.kind,
403
+ }));
404
+ const diagnostics = external.diagnostics.map((diagnostic, index) => mapExternalDiagnostic(snapshot.rootDirectory, targetFile, diagnostic, external.service.id, index));
405
+ if (!selected) {
406
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], diagnostics, routing: externalLspRouting(targetFile.language, external.service), error: 'Selected external LSP code action was not found for the current file state.' };
407
+ }
408
+ if (!selected.rawEdit) {
409
+ return {
410
+ success: false,
411
+ rootDirectory: snapshot.rootDirectory,
412
+ filePath: targetFile.absolutePath,
413
+ applied: false,
414
+ edits: [],
415
+ diagnostics,
416
+ routing: externalLspRouting(targetFile.language, external.service),
417
+ deniedReason: 'unsupported-action',
418
+ denial: {
419
+ reason: 'unsupported-action',
420
+ remediation: 'Use an LSP action that returns a workspace edit. Arbitrary language-server commands require a configured allowlist before Hub can apply them.',
421
+ requirements: ['checkpoint', 'patch-preview'],
422
+ checkpointId: request.checkpointId,
423
+ },
424
+ error: 'Selected external LSP action only returned a command. Hub refuses arbitrary language-server commands until command allowlists are configured.',
425
+ };
426
+ }
427
+ const editPreview = selected.editPreview || selected.title;
428
+ const previewId = createPatchPreviewId(editPreview);
429
+ const patchPreview = this.recordPatchPreview({
430
+ id: previewId,
431
+ rootDirectory: snapshot.rootDirectory,
432
+ filePath: targetFile.absolutePath,
433
+ relativePath: targetFile.relativePath,
434
+ title: selected.title,
435
+ operation: 'code-action',
436
+ source: selected.source,
437
+ serviceId: external.service.id,
438
+ route: 'external-lsp',
439
+ language: targetFile.language,
440
+ files: [targetFile.relativePath],
441
+ editPreview,
442
+ expectedFileHash: targetFile.hash,
443
+ });
444
+ const safeApplyDenial = validateApplyRequirements(request, previewId);
445
+ if (safeApplyDenial) {
446
+ const deniedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'denied', { checkpointId: request.checkpointId });
447
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], diagnostics, routing: externalLspRouting(targetFile.language, external.service), patchPreview: deniedPreview || patchPreview, ...safeApplyDenial };
448
+ }
449
+ const edits = applyExternalWorkspaceEdit(snapshot.rootDirectory, selected.rawEdit);
450
+ const patchReview = this.enqueueAppliedPatchReview(snapshot.rootDirectory, selected.title, `LSP code action applied with checkpoint ${request.checkpointId}.`, edits, patchPreview);
451
+ const rollback = this.recordRollback(snapshot.rootDirectory, request, 'code-action', edits, patchReview?.id);
452
+ const appliedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'applied', { checkpointId: request.checkpointId, patchReviewId: patchReview?.id });
453
+ this.refreshSnapshot(snapshot.rootDirectory);
454
+ return {
455
+ success: true,
456
+ rootDirectory: snapshot.rootDirectory,
457
+ filePath: targetFile.absolutePath,
458
+ applied: edits.some((edit) => edit.changed),
459
+ edits,
460
+ diagnostics,
461
+ patchPreview: appliedPreview || patchPreview,
462
+ rollback,
463
+ patchReview,
464
+ routing: externalLspRouting(targetFile.language, external.service),
465
+ };
466
+ }
467
+ catch (err) {
468
+ const reason = `${targetFile.language} language server unavailable: ${errorMessage(err)}`;
469
+ const degradedState = this.degradedStateForLanguage(snapshot.rootDirectory, targetFile.language, reason);
470
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], routing: { ...fallbackIndexRouting(targetFile.language, reason), serviceId: degradedState.serviceId, serviceLabel: degradedState.serviceLabel, installHint: degradedState.installHint, status: degradedState.status }, degradedState, error: reason };
471
+ }
472
+ }
473
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], routing: fallbackIndexRouting(targetFile.language, 'No safe apply route is configured for this file type.'), error: 'Code action apply currently supports TypeScript/JavaScript files plus configured external LSP languages.' };
474
+ }
475
+ const context = await createTypeScriptLanguageService(snapshot, targetFile, request);
476
+ try {
477
+ const diagnostics = [
478
+ ...context.languageService.getSyntacticDiagnostics(targetFile.absolutePath),
479
+ ...context.languageService.getSemanticDiagnostics(targetFile.absolutePath),
480
+ ...context.languageService.getSuggestionDiagnostics(targetFile.absolutePath),
481
+ ];
482
+ const requestedPosition = context.requestedPosition;
483
+ const mappedDiagnostics = diagnostics
484
+ .map((diagnostic) => mapTsDiagnostic(context.ts, snapshot.rootDirectory, targetFile.absolutePath, targetFile.textContent || '', diagnostic))
485
+ .filter((diagnostic) => !!diagnostic)
486
+ .map((diagnostic) => ({
487
+ ...diagnostic,
488
+ language: targetFile.language,
489
+ serviceId: 'typescript-language-service',
490
+ route: 'embedded-typescript',
491
+ }));
492
+ for (const diagnostic of diagnostics) {
493
+ const start = typeof diagnostic.start === 'number' ? diagnostic.start : requestedPosition;
494
+ const end = start + Math.max(1, diagnostic.length || 1);
495
+ const fixes = context.languageService.getCodeFixesAtPosition(targetFile.absolutePath, start, end, [diagnostic.code], context.formatOptions, context.preferences);
496
+ for (const fix of fixes) {
497
+ const candidate = {
498
+ id: `fix-${diagnostic.code}-${hashText(fix.fixName + fix.description).slice(0, 10)}`,
499
+ title: fix.description,
500
+ kind: 'quickfix',
501
+ diagnosticCode: String(diagnostic.code),
502
+ fixName: fix.fixName,
503
+ };
504
+ if (!matchesRequestedCodeAction(request, candidate))
505
+ continue;
506
+ const editPreview = previewTextChanges(snapshot.rootDirectory, fix.changes);
507
+ const previewId = createPatchPreviewId(editPreview);
508
+ const patchPreview = this.recordPatchPreview({
509
+ id: previewId,
510
+ rootDirectory: snapshot.rootDirectory,
511
+ filePath: targetFile.absolutePath,
512
+ relativePath: targetFile.relativePath,
513
+ title: fix.description,
514
+ operation: 'code-action',
515
+ source: 'typescript-language-service',
516
+ serviceId: 'typescript-language-service',
517
+ route: 'embedded-typescript',
518
+ language: targetFile.language,
519
+ files: textChangeFiles(snapshot.rootDirectory, fix.changes),
520
+ editPreview,
521
+ expectedFileHash: targetFile.hash,
522
+ });
523
+ const safeApplyDenial = validateApplyRequirements(request, previewId);
524
+ if (safeApplyDenial) {
525
+ const deniedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'denied', { checkpointId: request.checkpointId });
526
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], diagnostics: mappedDiagnostics, routing: embeddedTypeScriptRouting(targetFile.language), patchPreview: deniedPreview || patchPreview, ...safeApplyDenial };
527
+ }
528
+ const edits = applyTsFileTextChanges(snapshot.rootDirectory, fix.changes);
529
+ const patchReview = this.enqueueAppliedPatchReview(snapshot.rootDirectory, fix.description, `TypeScript code action applied with checkpoint ${request.checkpointId}.`, edits, patchPreview);
530
+ const rollback = this.recordRollback(snapshot.rootDirectory, request, 'code-action', edits, patchReview?.id);
531
+ const appliedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'applied', { checkpointId: request.checkpointId, patchReviewId: patchReview?.id });
532
+ this.refreshSnapshot(snapshot.rootDirectory);
533
+ return {
534
+ success: true,
535
+ rootDirectory: snapshot.rootDirectory,
536
+ filePath: targetFile.absolutePath,
537
+ applied: edits.some((edit) => edit.changed),
538
+ edits,
539
+ diagnostics: mappedDiagnostics,
540
+ patchPreview: appliedPreview || patchPreview,
541
+ rollback,
542
+ patchReview,
543
+ routing: embeddedTypeScriptRouting(targetFile.language),
544
+ };
545
+ }
546
+ }
547
+ const refactors = context.languageService.getApplicableRefactors(targetFile.absolutePath, requestedPosition, context.preferences, undefined);
548
+ for (const refactor of refactors) {
549
+ for (const action of refactor.actions) {
550
+ const candidate = {
551
+ id: `refactor-${hashText(refactor.name + action.name).slice(0, 10)}`,
552
+ title: action.description || refactor.description,
553
+ kind: `refactor.${refactor.name}`,
554
+ refactorName: refactor.name,
555
+ refactorActionName: action.name,
556
+ };
557
+ if (!matchesRequestedCodeAction(request, candidate))
558
+ continue;
559
+ const editPreview = refactor.description;
560
+ const previewId = createPatchPreviewId(`${refactor.name}:${action.name}:${refactor.description}`);
561
+ const patchPreview = this.recordPatchPreview({
562
+ id: previewId,
563
+ rootDirectory: snapshot.rootDirectory,
564
+ filePath: targetFile.absolutePath,
565
+ relativePath: targetFile.relativePath,
566
+ title: action.description || refactor.description,
567
+ operation: 'code-action',
568
+ source: 'typescript-language-service',
569
+ serviceId: 'typescript-language-service',
570
+ route: 'embedded-typescript',
571
+ language: targetFile.language,
572
+ files: [targetFile.relativePath],
573
+ editPreview,
574
+ expectedFileHash: targetFile.hash,
575
+ });
576
+ const safeApplyDenial = validateApplyRequirements(request, previewId);
577
+ if (safeApplyDenial) {
578
+ const deniedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'denied', { checkpointId: request.checkpointId });
579
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], diagnostics: mappedDiagnostics, routing: embeddedTypeScriptRouting(targetFile.language), patchPreview: deniedPreview || patchPreview, ...safeApplyDenial };
580
+ }
581
+ const refactorEdit = context.languageService.getEditsForRefactor(targetFile.absolutePath, context.formatOptions, requestedPosition, refactor.name, action.name, context.preferences);
582
+ if (!refactorEdit) {
583
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], routing: embeddedTypeScriptRouting(targetFile.language), error: 'Selected refactor did not return edits.' };
584
+ }
585
+ const edits = applyTsFileTextChanges(snapshot.rootDirectory, refactorEdit.edits);
586
+ const patchReview = this.enqueueAppliedPatchReview(snapshot.rootDirectory, action.description || refactor.description, `TypeScript refactor applied with checkpoint ${request.checkpointId}.`, edits, patchPreview);
587
+ const rollback = this.recordRollback(snapshot.rootDirectory, request, 'code-action', edits, patchReview?.id);
588
+ const appliedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'applied', { checkpointId: request.checkpointId, patchReviewId: patchReview?.id });
589
+ this.refreshSnapshot(snapshot.rootDirectory);
590
+ return {
591
+ success: true,
592
+ rootDirectory: snapshot.rootDirectory,
593
+ filePath: targetFile.absolutePath,
594
+ applied: edits.some((edit) => edit.changed),
595
+ edits,
596
+ diagnostics: mappedDiagnostics,
597
+ patchPreview: appliedPreview || patchPreview,
598
+ rollback,
599
+ patchReview,
600
+ routing: embeddedTypeScriptRouting(targetFile.language),
601
+ };
602
+ }
603
+ }
604
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], diagnostics: mappedDiagnostics, routing: embeddedTypeScriptRouting(targetFile.language), error: 'Selected code action was not found for the current file state.' };
605
+ }
606
+ finally {
607
+ context.languageService.dispose();
608
+ }
609
+ }
610
+ catch (err) {
611
+ return { success: false, rootDirectory: request.rootDirectory || '', filePath: request.filePath, applied: false, edits: [], error: errorMessage(err) };
612
+ }
613
+ }
614
+ async organizeImports(request) {
615
+ try {
616
+ const snapshot = await this.ensureIndexed(request.rootDirectory, request.allowedDirectories);
617
+ const target = resolveIndexedTextFile(snapshot, request.filePath);
618
+ if (!target.success)
619
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: target.filePath, applied: false, edits: [], error: target.error };
620
+ const targetFile = target.file;
621
+ if (!isTypeScriptLike(targetFile.extension)) {
622
+ if (isExternalLspLanguage(targetFile.language)) {
623
+ try {
624
+ const external = await this.languageServers.organizeImports({
625
+ rootDirectory: snapshot.rootDirectory,
626
+ language: targetFile.language,
627
+ filePath: targetFile.absolutePath,
628
+ text: targetFile.textContent || '',
629
+ });
630
+ const diagnostics = external.diagnostics.map((diagnostic, index) => mapExternalDiagnostic(snapshot.rootDirectory, targetFile, diagnostic, external.service.id, index));
631
+ const action = external.actions.find((candidate) => candidate.rawEdit);
632
+ if (!action?.rawEdit) {
633
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], diagnostics, routing: externalLspRouting(targetFile.language, external.service), error: 'External language server did not return a safe organize-imports workspace edit.' };
634
+ }
635
+ const editPreview = action.editPreview || action.title;
636
+ const previewId = createPatchPreviewId(`organize:${targetFile.relativePath}:${editPreview}`);
637
+ const patchPreview = this.recordPatchPreview({
638
+ id: previewId,
639
+ rootDirectory: snapshot.rootDirectory,
640
+ filePath: targetFile.absolutePath,
641
+ relativePath: targetFile.relativePath,
642
+ title: 'Organize imports',
643
+ operation: 'organize-imports',
644
+ source: action.source,
645
+ serviceId: external.service.id,
646
+ route: 'external-lsp',
647
+ language: targetFile.language,
648
+ files: [targetFile.relativePath],
649
+ editPreview,
650
+ expectedFileHash: targetFile.hash,
651
+ });
652
+ const safeApplyDenial = validateApplyRequirements(request, previewId);
653
+ if (safeApplyDenial) {
654
+ const deniedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'denied', { checkpointId: request.checkpointId });
655
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], diagnostics, routing: externalLspRouting(targetFile.language, external.service), patchPreview: deniedPreview || patchPreview, ...safeApplyDenial };
656
+ }
657
+ const edits = applyExternalWorkspaceEdit(snapshot.rootDirectory, action.rawEdit);
658
+ const patchReview = this.enqueueAppliedPatchReview(snapshot.rootDirectory, 'Organize imports', `External LSP organize-imports applied with checkpoint ${request.checkpointId}.`, edits, patchPreview);
659
+ const rollback = this.recordRollback(snapshot.rootDirectory, request, 'organize-imports', edits, patchReview?.id);
660
+ const appliedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'applied', { checkpointId: request.checkpointId, patchReviewId: patchReview?.id });
661
+ this.refreshSnapshot(snapshot.rootDirectory);
662
+ return {
663
+ success: true,
664
+ rootDirectory: snapshot.rootDirectory,
665
+ filePath: targetFile.absolutePath,
666
+ applied: edits.some((edit) => edit.changed),
667
+ edits,
668
+ diagnostics,
669
+ patchPreview: appliedPreview || patchPreview,
670
+ rollback,
671
+ patchReview,
672
+ routing: externalLspRouting(targetFile.language, external.service),
673
+ };
674
+ }
675
+ catch (err) {
676
+ const reason = `${targetFile.language} organize imports unavailable: ${errorMessage(err)}`;
677
+ const degradedState = this.degradedStateForLanguage(snapshot.rootDirectory, targetFile.language, reason);
678
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], routing: { ...fallbackIndexRouting(targetFile.language, reason), serviceId: degradedState.serviceId, serviceLabel: degradedState.serviceLabel, installHint: degradedState.installHint, status: degradedState.status }, degradedState, error: reason };
679
+ }
680
+ }
681
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], routing: fallbackIndexRouting(targetFile.language, 'No safe organize-imports route is configured for this file type.'), error: 'Organize imports currently supports TypeScript/JavaScript files plus configured external LSP languages.' };
682
+ }
683
+ const context = await createTypeScriptLanguageService(snapshot, targetFile, {});
684
+ try {
685
+ const changes = context.languageService.organizeImports({ type: 'file', fileName: targetFile.absolutePath }, context.formatOptions, context.preferences);
686
+ const editPreview = previewTextChanges(snapshot.rootDirectory, changes) || 'Organize imports';
687
+ const previewId = createPatchPreviewId(`organize:${targetFile.relativePath}:${editPreview}`);
688
+ const patchPreview = this.recordPatchPreview({
689
+ id: previewId,
690
+ rootDirectory: snapshot.rootDirectory,
691
+ filePath: targetFile.absolutePath,
692
+ relativePath: targetFile.relativePath,
693
+ title: 'Organize imports',
694
+ operation: 'organize-imports',
695
+ source: 'typescript-language-service',
696
+ serviceId: 'typescript-language-service',
697
+ route: 'embedded-typescript',
698
+ language: targetFile.language,
699
+ files: textChangeFiles(snapshot.rootDirectory, changes),
700
+ editPreview,
701
+ expectedFileHash: targetFile.hash,
702
+ });
703
+ const safeApplyDenial = validateApplyRequirements(request, previewId);
704
+ if (safeApplyDenial) {
705
+ const deniedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'denied', { checkpointId: request.checkpointId });
706
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], routing: embeddedTypeScriptRouting(targetFile.language), patchPreview: deniedPreview || patchPreview, ...safeApplyDenial };
707
+ }
708
+ const edits = applyTsFileTextChanges(snapshot.rootDirectory, changes);
709
+ const patchReview = this.enqueueAppliedPatchReview(snapshot.rootDirectory, 'Organize imports', `TypeScript organize-imports applied with checkpoint ${request.checkpointId}.`, edits, patchPreview);
710
+ const rollback = this.recordRollback(snapshot.rootDirectory, request, 'organize-imports', edits, patchReview?.id);
711
+ const appliedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'applied', { checkpointId: request.checkpointId, patchReviewId: patchReview?.id });
712
+ this.refreshSnapshot(snapshot.rootDirectory);
713
+ return {
714
+ success: true,
715
+ rootDirectory: snapshot.rootDirectory,
716
+ filePath: targetFile.absolutePath,
717
+ applied: edits.some((edit) => edit.changed),
718
+ edits,
719
+ patchPreview: appliedPreview || patchPreview,
720
+ rollback,
721
+ patchReview,
722
+ routing: embeddedTypeScriptRouting(targetFile.language),
723
+ };
724
+ }
725
+ finally {
726
+ context.languageService.dispose();
727
+ }
728
+ }
729
+ catch (err) {
730
+ return { success: false, rootDirectory: request.rootDirectory || '', filePath: request.filePath, applied: false, edits: [], error: errorMessage(err) };
731
+ }
732
+ }
733
+ async renameSymbol(request) {
734
+ try {
735
+ const newName = String(request.newName || '').trim();
736
+ if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(newName)) {
737
+ return { success: false, rootDirectory: request.rootDirectory || '', filePath: request.filePath, applied: false, edits: [], error: 'newName must be a valid JavaScript/TypeScript identifier.' };
738
+ }
739
+ const snapshot = await this.ensureIndexed(request.rootDirectory, request.allowedDirectories);
740
+ const target = resolveIndexedTextFile(snapshot, request.filePath);
741
+ if (!target.success)
742
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: target.filePath, applied: false, edits: [], error: target.error };
743
+ const targetFile = target.file;
744
+ if (!isTypeScriptLike(targetFile.extension)) {
745
+ if (isExternalLspLanguage(targetFile.language)) {
746
+ try {
747
+ const external = await this.languageServers.rename({
748
+ rootDirectory: snapshot.rootDirectory,
749
+ language: targetFile.language,
750
+ filePath: targetFile.absolutePath,
751
+ text: targetFile.textContent || '',
752
+ line: request.line,
753
+ column: request.column,
754
+ newName,
755
+ });
756
+ const diagnostics = external.diagnostics.map((diagnostic, index) => mapExternalDiagnostic(snapshot.rootDirectory, targetFile, diagnostic, external.service.id, index));
757
+ if (!external.edit) {
758
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], diagnostics, routing: externalLspRouting(targetFile.language, external.service), error: 'External language server did not return rename edits.' };
759
+ }
760
+ const editPreview = `Rename symbol at ${targetFile.relativePath}:${request.line || 1}:${request.column || 1} to ${newName}.`;
761
+ const previewId = createPatchPreviewId(`rename:${targetFile.relativePath}:${newName}:${editPreview}`);
762
+ const patchPreview = this.recordPatchPreview({
763
+ id: previewId,
764
+ rootDirectory: snapshot.rootDirectory,
765
+ filePath: targetFile.absolutePath,
766
+ relativePath: targetFile.relativePath,
767
+ title: `Rename to ${newName}`,
768
+ operation: 'rename',
769
+ source: 'external-lsp',
770
+ serviceId: external.service.id,
771
+ route: 'external-lsp',
772
+ language: targetFile.language,
773
+ files: [targetFile.relativePath],
774
+ editPreview,
775
+ expectedFileHash: targetFile.hash,
776
+ });
777
+ const safeApplyDenial = validateApplyRequirements(request, previewId);
778
+ if (safeApplyDenial) {
779
+ const deniedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'denied', { checkpointId: request.checkpointId });
780
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], diagnostics, routing: externalLspRouting(targetFile.language, external.service), patchPreview: deniedPreview || patchPreview, ...safeApplyDenial };
781
+ }
782
+ const edits = applyExternalWorkspaceEdit(snapshot.rootDirectory, external.edit);
783
+ const patchReview = this.enqueueAppliedPatchReview(snapshot.rootDirectory, `Rename to ${newName}`, `External LSP rename applied with checkpoint ${request.checkpointId}.`, edits, patchPreview);
784
+ const rollback = this.recordRollback(snapshot.rootDirectory, request, 'rename', edits, patchReview?.id);
785
+ const appliedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'applied', { checkpointId: request.checkpointId, patchReviewId: patchReview?.id });
786
+ this.refreshSnapshot(snapshot.rootDirectory);
787
+ return {
788
+ success: true,
789
+ rootDirectory: snapshot.rootDirectory,
790
+ filePath: targetFile.absolutePath,
791
+ applied: edits.some((edit) => edit.changed),
792
+ edits,
793
+ diagnostics,
794
+ patchPreview: appliedPreview || patchPreview,
795
+ rollback,
796
+ patchReview,
797
+ routing: externalLspRouting(targetFile.language, external.service),
798
+ };
799
+ }
800
+ catch (err) {
801
+ const reason = `${targetFile.language} rename unavailable: ${errorMessage(err)}`;
802
+ const degradedState = this.degradedStateForLanguage(snapshot.rootDirectory, targetFile.language, reason);
803
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], routing: { ...fallbackIndexRouting(targetFile.language, reason), serviceId: degradedState.serviceId, serviceLabel: degradedState.serviceLabel, installHint: degradedState.installHint, status: degradedState.status }, degradedState, error: reason };
804
+ }
805
+ }
806
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], routing: fallbackIndexRouting(targetFile.language, 'No safe rename route is configured for this file type.'), error: 'Rename currently supports TypeScript/JavaScript files plus configured external LSP languages.' };
807
+ }
808
+ const context = await createTypeScriptLanguageService(snapshot, targetFile, request);
809
+ try {
810
+ const renameInfo = context.languageService.getRenameInfo(targetFile.absolutePath, context.requestedPosition, { allowRenameOfImportPath: false });
811
+ if (!renameInfo.canRename) {
812
+ const message = typeof renameInfo.localizedErrorMessage === 'string' ? renameInfo.localizedErrorMessage : 'Symbol cannot be renamed at this location.';
813
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], routing: embeddedTypeScriptRouting(targetFile.language), error: message };
814
+ }
815
+ const locations = context.languageService.findRenameLocations(targetFile.absolutePath, context.requestedPosition, false, false, true) || [];
816
+ if (locations.length === 0) {
817
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], routing: embeddedTypeScriptRouting(targetFile.language), error: 'No rename locations were found.' };
818
+ }
819
+ const changes = locations.map((location) => ({
820
+ fileName: location.fileName,
821
+ textChanges: [{ span: location.textSpan, newText: newName }],
822
+ }));
823
+ const editPreview = previewTextChanges(snapshot.rootDirectory, changes) || `Rename to ${newName}`;
824
+ const previewId = createPatchPreviewId(`rename:${targetFile.relativePath}:${newName}:${editPreview}`);
825
+ const patchPreview = this.recordPatchPreview({
826
+ id: previewId,
827
+ rootDirectory: snapshot.rootDirectory,
828
+ filePath: targetFile.absolutePath,
829
+ relativePath: targetFile.relativePath,
830
+ title: `Rename to ${newName}`,
831
+ operation: 'rename',
832
+ source: 'typescript-language-service',
833
+ serviceId: 'typescript-language-service',
834
+ route: 'embedded-typescript',
835
+ language: targetFile.language,
836
+ files: textChangeFiles(snapshot.rootDirectory, changes),
837
+ editPreview,
838
+ expectedFileHash: targetFile.hash,
839
+ });
840
+ const safeApplyDenial = validateApplyRequirements(request, previewId);
841
+ if (safeApplyDenial) {
842
+ const deniedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'denied', { checkpointId: request.checkpointId });
843
+ return { success: false, rootDirectory: snapshot.rootDirectory, filePath: targetFile.absolutePath, applied: false, edits: [], routing: embeddedTypeScriptRouting(targetFile.language), patchPreview: deniedPreview || patchPreview, ...safeApplyDenial };
844
+ }
845
+ const edits = applyTsFileTextChanges(snapshot.rootDirectory, changes);
846
+ const patchReview = this.enqueueAppliedPatchReview(snapshot.rootDirectory, `Rename to ${newName}`, `TypeScript rename applied with checkpoint ${request.checkpointId}.`, edits, patchPreview);
847
+ const rollback = this.recordRollback(snapshot.rootDirectory, request, 'rename', edits, patchReview?.id);
848
+ const appliedPreview = this.markPatchPreview(snapshot.rootDirectory, previewId, 'applied', { checkpointId: request.checkpointId, patchReviewId: patchReview?.id });
849
+ this.refreshSnapshot(snapshot.rootDirectory);
850
+ return {
851
+ success: true,
852
+ rootDirectory: snapshot.rootDirectory,
853
+ filePath: targetFile.absolutePath,
854
+ applied: edits.some((edit) => edit.changed),
855
+ edits,
856
+ patchPreview: appliedPreview || patchPreview,
857
+ rollback,
858
+ patchReview,
859
+ routing: embeddedTypeScriptRouting(targetFile.language),
860
+ };
861
+ }
862
+ finally {
863
+ context.languageService.dispose();
864
+ }
865
+ }
866
+ catch (err) {
867
+ return { success: false, rootDirectory: request.rootDirectory || '', filePath: request.filePath, applied: false, edits: [], error: errorMessage(err) };
868
+ }
869
+ }
870
+ languageServiceStatus(request) {
871
+ try {
872
+ const rootDirectory = resolveRootDirectory(request.rootDirectory, request.allowedDirectories);
873
+ const checkedAt = Date.now();
874
+ return {
875
+ success: true,
876
+ rootDirectory,
877
+ services: [
878
+ {
879
+ id: 'typescript-language-service',
880
+ label: 'TypeScript language service',
881
+ languages: ['typescript', 'tsx', 'javascript', 'jsx'],
882
+ mode: 'embedded',
883
+ status: 'ready',
884
+ detail: 'Embedded TypeScript language service for diagnostics, quick fixes, rename, organize imports, and refactors.',
885
+ capabilities: ['diagnostics', 'hover', 'definition', 'references', 'rename', 'codeActions', 'organizeImports'],
886
+ degraded: false,
887
+ lastCheckedAt: checkedAt,
888
+ },
889
+ ...this.languageServers.status(rootDirectory, checkedAt),
890
+ ],
891
+ };
892
+ }
893
+ catch (err) {
894
+ return { success: false, rootDirectory: request.rootDirectory || '', services: [], error: errorMessage(err) };
895
+ }
896
+ }
897
+ controlLanguageService(request) {
898
+ try {
899
+ const rootDirectory = resolveRootDirectory(request.rootDirectory, request.allowedDirectories);
900
+ if (request.action !== 'start' && request.action !== 'stop' && request.action !== 'restart') {
901
+ throw new Error('action must be start, stop, or restart.');
902
+ }
903
+ if (!request.serviceId || request.serviceId === 'typescript-language-service') {
904
+ throw new Error('serviceId must be an external language service id.');
905
+ }
906
+ const service = this.languageServers.control(rootDirectory, request.serviceId, request.action);
907
+ return { success: true, rootDirectory, service };
908
+ }
909
+ catch (err) {
910
+ return { success: false, rootDirectory: request.rootDirectory || '', error: errorMessage(err) };
911
+ }
912
+ }
913
+ repairIndex(request) {
914
+ const startedAt = Date.now();
915
+ try {
916
+ const rootDirectory = resolveRootDirectory(request.rootDirectory, request.allowedDirectories);
917
+ const existing = this.loadSnapshot(rootDirectory);
918
+ const removedFiles = (existing?.files || [])
919
+ .filter((file) => !existsSync(file.absolutePath))
920
+ .map((file) => file.relativePath);
921
+ const shouldRebuild = request.force === true || !existing || removedFiles.length > 0;
922
+ let rebuilt;
923
+ if (shouldRebuild) {
924
+ rebuilt = this.refreshSnapshot(rootDirectory, request).stats;
925
+ }
926
+ return {
927
+ success: true,
928
+ rootDirectory,
929
+ repaired: shouldRebuild,
930
+ removedFiles,
931
+ rebuilt,
932
+ durationMs: Date.now() - startedAt,
933
+ };
934
+ }
935
+ catch (err) {
936
+ return {
937
+ success: false,
938
+ rootDirectory: request.rootDirectory || '',
939
+ repaired: false,
940
+ removedFiles: [],
941
+ durationMs: Date.now() - startedAt,
942
+ error: errorMessage(err),
943
+ };
944
+ }
945
+ }
946
+ async dependencyGraph(request) {
947
+ try {
948
+ const snapshot = await this.ensureIndexed(request.rootDirectory, request.allowedDirectories);
949
+ const maxNodes = request.maxNodes ? Math.max(1, request.maxNodes) : undefined;
950
+ if (!maxNodes || snapshot.dependencyGraph.nodes.length <= maxNodes) {
951
+ return { success: true, graph: snapshot.dependencyGraph };
952
+ }
953
+ return {
954
+ success: true,
955
+ graph: {
956
+ ...snapshot.dependencyGraph,
957
+ nodes: snapshot.dependencyGraph.nodes.slice(0, maxNodes),
958
+ edges: snapshot.dependencyGraph.edges.filter((edge) => (snapshot.dependencyGraph.nodes.slice(0, maxNodes).some((node) => node.id === edge.from)
959
+ && snapshot.dependencyGraph.nodes.slice(0, maxNodes).some((node) => node.id === edge.to))),
960
+ },
961
+ };
962
+ }
963
+ catch (err) {
964
+ return { success: false, error: errorMessage(err) };
965
+ }
966
+ }
967
+ async createContextPack(request) {
968
+ try {
969
+ const rootDirectory = resolveRootDirectory(request.rootDirectory, request.allowedDirectories);
970
+ return { success: true, pack: this.contextPacks.create(rootDirectory, request) };
971
+ }
972
+ catch (err) {
973
+ return { success: false, error: errorMessage(err) };
974
+ }
975
+ }
976
+ async updateContextPack(request) {
977
+ try {
978
+ const rootDirectory = resolveRootDirectory(request.rootDirectory, request.allowedDirectories);
979
+ return { success: true, pack: this.contextPacks.update(rootDirectory, request) };
980
+ }
981
+ catch (err) {
982
+ return { success: false, error: errorMessage(err) };
983
+ }
984
+ }
985
+ async listContextPacks(request) {
986
+ try {
987
+ const rootDirectory = resolveRootDirectory(request.rootDirectory, request.allowedDirectories);
988
+ return { success: true, packs: this.contextPacks.list(rootDirectory) };
989
+ }
990
+ catch (err) {
991
+ return { success: false, packs: [], error: errorMessage(err) };
992
+ }
993
+ }
994
+ async materializeContextPack(request) {
995
+ try {
996
+ const snapshot = await this.ensureIndexed(request.rootDirectory, request.allowedDirectories);
997
+ const materialized = this.contextPacks.materialize({
998
+ rootDirectory: snapshot.rootDirectory,
999
+ packId: request.id,
1000
+ files: snapshot.files,
1001
+ symbols: snapshot.symbols,
1002
+ maxTokens: request.maxTokens,
1003
+ searchText: (query, limit) => this.searchTextSync(snapshot, { query, limit }),
1004
+ });
1005
+ return { success: true, materialized };
1006
+ }
1007
+ catch (err) {
1008
+ return { success: false, error: errorMessage(err) };
1009
+ }
1010
+ }
1011
+ async whatChanged(request) {
1012
+ try {
1013
+ const snapshot = await this.ensureIndexed(request.rootDirectory, request.allowedDirectories);
1014
+ return summarizeWhatChanged(snapshot.rootDirectory, snapshot.files, request.maxFiles);
1015
+ }
1016
+ catch (err) {
1017
+ return {
1018
+ success: false,
1019
+ isGitRepo: false,
1020
+ rootDirectory: request.rootDirectory,
1021
+ summary: '',
1022
+ changedFiles: [],
1023
+ workPacket: '',
1024
+ error: errorMessage(err),
1025
+ };
1026
+ }
1027
+ }
1028
+ recordPatchPreview(draft) {
1029
+ const now = Date.now();
1030
+ const store = this.readPatchStore(draft.rootDirectory);
1031
+ const id = draft.id || createPatchPreviewId(`${draft.title}:${draft.editPreview}:${draft.expectedFileHash || ''}`);
1032
+ const existing = store.previews.find((preview) => preview.id === id);
1033
+ const preview = {
1034
+ id,
1035
+ rootDirectory: draft.rootDirectory,
1036
+ filePath: draft.filePath,
1037
+ relativePath: draft.relativePath,
1038
+ title: draft.title,
1039
+ operation: draft.operation,
1040
+ source: draft.source,
1041
+ serviceId: draft.serviceId,
1042
+ route: draft.route,
1043
+ language: draft.language,
1044
+ files: [...new Set(draft.files.map((file) => file.replace(/\\/g, '/')).filter(Boolean))],
1045
+ editPreview: draft.editPreview || 'No textual preview was returned.',
1046
+ diff: draft.diff || draft.editPreview || 'No textual preview was returned.',
1047
+ expectedFileHash: draft.expectedFileHash,
1048
+ status: existing?.status === 'applied' ? 'applied' : 'previewed',
1049
+ checkpointId: existing?.checkpointId,
1050
+ patchReviewId: existing?.patchReviewId,
1051
+ createdAt: existing?.createdAt || now,
1052
+ updatedAt: now,
1053
+ };
1054
+ store.previews = [preview, ...store.previews.filter((entry) => entry.id !== id)].slice(0, 200);
1055
+ this.writePatchStore(draft.rootDirectory, store);
1056
+ return preview;
1057
+ }
1058
+ markPatchPreview(rootDirectory, previewId, status, metadata = {}) {
1059
+ if (!previewId)
1060
+ return undefined;
1061
+ const store = this.readPatchStore(rootDirectory);
1062
+ const preview = store.previews.find((entry) => entry.id === previewId);
1063
+ if (!preview)
1064
+ return undefined;
1065
+ preview.status = status;
1066
+ preview.updatedAt = Date.now();
1067
+ preview.checkpointId = metadata.checkpointId || preview.checkpointId;
1068
+ preview.patchReviewId = metadata.patchReviewId || preview.patchReviewId;
1069
+ this.writePatchStore(rootDirectory, store);
1070
+ return preview;
1071
+ }
1072
+ recordRollback(rootDirectory, request, operation, edits, patchReviewId) {
1073
+ const checkpointId = String(request.checkpointId || '').trim();
1074
+ if (!checkpointId)
1075
+ return undefined;
1076
+ const rollback = {
1077
+ id: `rollback-${Date.now()}-${hashText(`${checkpointId}:${request.patchPreviewId || ''}:${edits.map((edit) => `${edit.relativePath}:${edit.afterHash || ''}`).join('|')}`).slice(0, 10)}`,
1078
+ rootDirectory,
1079
+ checkpointId,
1080
+ patchPreviewId: request.patchPreviewId,
1081
+ patchReviewId,
1082
+ operation,
1083
+ createdAt: Date.now(),
1084
+ files: edits.map((edit) => ({
1085
+ filePath: edit.filePath,
1086
+ relativePath: edit.relativePath,
1087
+ beforeHash: edit.beforeHash || '',
1088
+ afterHash: edit.afterHash || '',
1089
+ changed: edit.changed,
1090
+ editCount: edit.editCount,
1091
+ })),
1092
+ instructions: 'Use the checkpointId to restore the workspace through the workbench checkpoint/rollback flow; hashes identify the exact files changed by this LSP apply.',
1093
+ };
1094
+ const store = this.readPatchStore(rootDirectory);
1095
+ store.rollbacks = [rollback, ...store.rollbacks.filter((entry) => entry.id !== rollback.id)].slice(0, 200);
1096
+ this.writePatchStore(rootDirectory, store);
1097
+ return rollback;
1098
+ }
1099
+ enqueueAppliedPatchReview(rootDirectory, title, description, edits, patchPreview) {
1100
+ const changedEdits = edits.filter((edit) => edit.changed);
1101
+ const diff = changedEdits.map((edit) => `# ${edit.relativePath}\n${edit.preview}`).join('\n\n').trim();
1102
+ if (!diff)
1103
+ return undefined;
1104
+ const review = getEngineeringWorkbenchService().enqueuePatchReview({
1105
+ rootDirectory,
1106
+ title,
1107
+ description,
1108
+ diff,
1109
+ files: changedEdits.map((edit) => edit.relativePath),
1110
+ source: 'agent',
1111
+ id: patchPreview?.patchReviewId || patchPreview?.id?.replace(/^patch-preview-/, 'patch-review-lsp-'),
1112
+ });
1113
+ if (!review.success || !review.item)
1114
+ return undefined;
1115
+ getEngineeringWorkbenchService().updatePatchReview({
1116
+ rootDirectory,
1117
+ id: review.item.id,
1118
+ status: 'applied',
1119
+ notes: description,
1120
+ });
1121
+ return { id: review.item.id, status: 'applied', source: 'agent' };
1122
+ }
1123
+ readPatchStore(rootDirectory) {
1124
+ return safeReadJson(this.patchStorePath(rootDirectory), { version: 1, previews: [], rollbacks: [] });
1125
+ }
1126
+ writePatchStore(rootDirectory, store) {
1127
+ safeWriteJson(this.patchStorePath(rootDirectory), {
1128
+ version: 1,
1129
+ previews: store.previews.slice(0, 200),
1130
+ rollbacks: store.rollbacks.slice(0, 200),
1131
+ });
1132
+ }
1133
+ patchStorePath(rootDirectory) {
1134
+ return join(workspaceIndexDirectory(rootDirectory), CODE_ACTION_PATCH_STORE_FILE);
1135
+ }
1136
+ degradedStateForLanguage(rootDirectory, language, reason) {
1137
+ const service = this.languageServers.status(rootDirectory).find((entry) => entry.languages.includes(language));
1138
+ return {
1139
+ degraded: true,
1140
+ reason,
1141
+ serviceId: service?.id || 'codebase-index',
1142
+ serviceLabel: service?.label || 'Codebase index',
1143
+ status: service?.status,
1144
+ installHint: service?.installHint,
1145
+ capabilities: service?.capabilities || ['searchFiles', 'searchText', 'symbols', 'dependencies'],
1146
+ };
1147
+ }
1148
+ async ensureIndexed(rootDirectoryInput, allowedDirectories) {
1149
+ const rootDirectory = resolveRootDirectory(rootDirectoryInput, allowedDirectories);
1150
+ const cached = this.snapshots.get(rootDirectory);
1151
+ if (cached)
1152
+ return cached;
1153
+ const loaded = this.loadSnapshot(rootDirectory);
1154
+ if (loaded) {
1155
+ this.snapshots.set(rootDirectory, loaded);
1156
+ return loaded;
1157
+ }
1158
+ const snapshot = this.buildSnapshot(rootDirectory, { rootDirectory });
1159
+ this.snapshots.set(rootDirectory, snapshot);
1160
+ this.saveSnapshot(snapshot);
1161
+ return snapshot;
1162
+ }
1163
+ buildSnapshot(rootDirectory, request) {
1164
+ const startedAt = Date.now();
1165
+ const fileResult = buildFileIndex({
1166
+ rootDirectory,
1167
+ maxFiles: request.maxFiles,
1168
+ maxFileBytes: request.maxFileBytes,
1169
+ });
1170
+ const symbols = extractSymbols(fileResult.files);
1171
+ const dependencyGraph = buildDependencyGraph(rootDirectory, fileResult.files, symbols);
1172
+ const fingerprint = hashText(fileResult.files.map((file) => `${file.relativePath}:${file.size}:${Math.round(file.mtimeMs)}:${file.hash}`).join('\n'));
1173
+ const stats = createStats({
1174
+ rootDirectory,
1175
+ startedAt,
1176
+ files: fileResult.files,
1177
+ ignoredCount: fileResult.ignoredCount,
1178
+ truncated: fileResult.truncated,
1179
+ totalBytes: fileResult.totalBytes,
1180
+ indexedBytes: fileResult.indexedBytes,
1181
+ symbolCount: symbols.length,
1182
+ dependencyNodeCount: dependencyGraph.nodes.length,
1183
+ dependencyEdgeCount: dependencyGraph.edges.length,
1184
+ });
1185
+ return {
1186
+ version: 1,
1187
+ rootDirectory,
1188
+ fingerprint,
1189
+ builtAt: Date.now(),
1190
+ files: fileResult.files,
1191
+ symbols,
1192
+ dependencyGraph,
1193
+ stats,
1194
+ };
1195
+ }
1196
+ searchTextSync(snapshot, request) {
1197
+ const query = request.query.trim();
1198
+ const normalizedQuery = normalizeForSearch(query);
1199
+ const extensions = new Set((request.extensions || []).map((ext) => ext.toLowerCase().startsWith('.') ? ext.toLowerCase() : `.${ext.toLowerCase()}`));
1200
+ const limit = clampLimit(request.limit, 100);
1201
+ const results = [];
1202
+ for (const file of snapshot.files) {
1203
+ if (results.length >= limit)
1204
+ break;
1205
+ if (!file.textContent || !file.isTextIndexed)
1206
+ continue;
1207
+ if (request.pathPrefix && !file.relativePath.startsWith(request.pathPrefix))
1208
+ continue;
1209
+ if (extensions.size && !extensions.has(file.extension))
1210
+ continue;
1211
+ const lower = file.textContent.toLowerCase();
1212
+ let index = lower.indexOf(normalizedQuery);
1213
+ if (index < 0) {
1214
+ const terms = normalizedQuery.split(/\s+/).filter(Boolean);
1215
+ if (!terms.every((term) => lower.includes(term)))
1216
+ continue;
1217
+ index = Math.min(...terms.map((term) => lower.indexOf(term)).filter((pos) => pos >= 0));
1218
+ }
1219
+ const loc = lineColumnAt(file.textContent, index);
1220
+ results.push({
1221
+ file,
1222
+ line: loc.line,
1223
+ column: loc.column,
1224
+ snippet: createSnippet(file.textContent, query),
1225
+ score: scoreTextMatch(file.relativePath, lower, normalizedQuery, index),
1226
+ content: request.includeContent ? file.textContent : undefined,
1227
+ });
1228
+ }
1229
+ return results.sort((a, b) => b.score - a.score || a.file.relativePath.localeCompare(b.file.relativePath));
1230
+ }
1231
+ loadSnapshot(rootDirectory) {
1232
+ const snapshotPath = join(workspaceIndexDirectory(rootDirectory), SNAPSHOT_FILE);
1233
+ const snapshot = safeReadJson(snapshotPath, null);
1234
+ if (!snapshot || snapshot.version !== 1 || snapshot.rootDirectory !== rootDirectory)
1235
+ return null;
1236
+ return snapshot;
1237
+ }
1238
+ saveSnapshot(snapshot) {
1239
+ const dir = workspaceIndexDirectory(snapshot.rootDirectory);
1240
+ safeWriteJson(join(dir, SNAPSHOT_FILE), snapshot);
1241
+ safeWriteJson(join(dir, MANIFEST_FILE), {
1242
+ version: snapshot.version,
1243
+ rootDirectory: snapshot.rootDirectory,
1244
+ fingerprint: snapshot.fingerprint,
1245
+ builtAt: snapshot.builtAt,
1246
+ stats: snapshot.stats,
1247
+ });
1248
+ }
1249
+ refreshSnapshot(rootDirectory, request) {
1250
+ const snapshot = this.buildSnapshot(rootDirectory, { rootDirectory, ...request });
1251
+ this.snapshots.set(rootDirectory, snapshot);
1252
+ this.saveSnapshot(snapshot);
1253
+ return snapshot;
1254
+ }
1255
+ }
1256
+ function embeddedTypeScriptRouting(language) {
1257
+ return {
1258
+ route: 'embedded-typescript',
1259
+ serviceId: 'typescript-language-service',
1260
+ serviceLabel: 'TypeScript language service',
1261
+ language,
1262
+ degraded: false,
1263
+ capabilities: ['diagnostics', 'hover', 'definition', 'references', 'rename', 'codeActions', 'organizeImports'],
1264
+ };
1265
+ }
1266
+ function externalLspRouting(language, service) {
1267
+ return {
1268
+ route: 'external-lsp',
1269
+ serviceId: service.id,
1270
+ serviceLabel: service.label,
1271
+ language,
1272
+ degraded: service.degraded === true,
1273
+ degradedReason: service.degradedReason,
1274
+ installHint: service.installHint,
1275
+ status: service.status,
1276
+ capabilities: service.capabilities || ['diagnostics', 'hover', 'definition', 'references', 'rename', 'codeActions'],
1277
+ };
1278
+ }
1279
+ function fallbackIndexRouting(language, degradedReason) {
1280
+ return {
1281
+ route: 'fallback-index',
1282
+ serviceId: 'codebase-index',
1283
+ serviceLabel: 'Codebase index',
1284
+ language,
1285
+ degraded: true,
1286
+ degradedReason,
1287
+ capabilities: ['searchFiles', 'searchText', 'symbols', 'dependencies'],
1288
+ };
1289
+ }
1290
+ function createPatchPreviewId(preview) {
1291
+ return `patch-preview-${hashText(preview || 'no-preview').slice(0, 16)}`;
1292
+ }
1293
+ function validateApplyRequirements(request, expectedPatchPreviewId) {
1294
+ if (!request.checkpointId || !request.checkpointId.trim()) {
1295
+ const remediation = 'Create an undo checkpoint, review the generated patch preview, then retry apply with checkpointId and patchPreviewAccepted=true.';
1296
+ return {
1297
+ deniedReason: 'missing-checkpoint',
1298
+ denial: {
1299
+ reason: 'missing-checkpoint',
1300
+ remediation,
1301
+ requirements: ['checkpoint', 'patch-preview'],
1302
+ patchPreviewId: expectedPatchPreviewId,
1303
+ },
1304
+ error: `Refusing to apply code changes without a checkpointId. ${remediation}`,
1305
+ };
1306
+ }
1307
+ if (request.patchPreviewAccepted !== true) {
1308
+ const remediation = 'Open and accept the patch preview before applying LSP edits.';
1309
+ return {
1310
+ deniedReason: 'missing-patch-preview',
1311
+ denial: {
1312
+ reason: 'missing-patch-preview',
1313
+ remediation,
1314
+ requirements: ['checkpoint', 'patch-preview'],
1315
+ patchPreviewId: expectedPatchPreviewId,
1316
+ checkpointId: request.checkpointId,
1317
+ },
1318
+ error: `Refusing to apply code changes without an accepted patch preview. ${remediation}`,
1319
+ };
1320
+ }
1321
+ if (expectedPatchPreviewId && request.patchPreviewId && request.patchPreviewId !== expectedPatchPreviewId) {
1322
+ const reason = 'stale-patch-preview';
1323
+ const remediation = 'Refresh code actions and accept the current patch preview before applying.';
1324
+ return {
1325
+ deniedReason: reason,
1326
+ denial: {
1327
+ reason,
1328
+ remediation,
1329
+ requirements: ['checkpoint', 'patch-preview'],
1330
+ patchPreviewId: expectedPatchPreviewId,
1331
+ checkpointId: request.checkpointId,
1332
+ },
1333
+ error: `Refusing to apply code changes because the patch preview is missing or no longer matches the selected action. ${remediation}`,
1334
+ };
1335
+ }
1336
+ return null;
1337
+ }
1338
+ function scoreFile(relativePath, basename, query) {
1339
+ if (!query)
1340
+ return 1;
1341
+ const path = normalizeForSearch(relativePath);
1342
+ const name = normalizeForSearch(basename);
1343
+ if (name === query)
1344
+ return 100;
1345
+ if (name.includes(query))
1346
+ return 80;
1347
+ if (path.includes(query))
1348
+ return 50;
1349
+ const terms = query.split(/\s+/).filter(Boolean);
1350
+ return terms.every((term) => path.includes(term)) ? 25 + terms.length : 0;
1351
+ }
1352
+ function scoreSymbol(name, relativePath, query) {
1353
+ if (!query)
1354
+ return 1;
1355
+ const n = normalizeForSearch(name);
1356
+ const p = normalizeForSearch(relativePath);
1357
+ if (n === query)
1358
+ return 100;
1359
+ if (n.includes(query))
1360
+ return 75;
1361
+ if (p.includes(query))
1362
+ return 30;
1363
+ const terms = query.split(/\s+/).filter(Boolean);
1364
+ return terms.every((term) => n.includes(term) || p.includes(term)) ? 20 + terms.length : 0;
1365
+ }
1366
+ function scoreTextMatch(relativePath, lowerContent, normalizedQuery, index) {
1367
+ let score = 20;
1368
+ if (index === 0)
1369
+ score += 10;
1370
+ if (normalizeForSearch(relativePath).includes(normalizedQuery))
1371
+ score += 8;
1372
+ const occurrences = normalizedQuery ? lowerContent.split(normalizedQuery).length - 1 : 0;
1373
+ return score + Math.min(occurrences, 20);
1374
+ }
1375
+ function resolveRequestedFilePath(rootDirectory, filePath) {
1376
+ const raw = String(filePath || '').trim();
1377
+ if (!raw)
1378
+ throw new Error('filePath is required.');
1379
+ return resolve(isAbsolute(raw) ? raw : join(rootDirectory, raw));
1380
+ }
1381
+ function normalizePathKey(filePath) {
1382
+ const resolved = resolve(filePath);
1383
+ return process.platform === 'win32' ? resolved.toLowerCase() : resolved;
1384
+ }
1385
+ function isTypeScriptLike(extension) {
1386
+ return extension === '.ts' || extension === '.tsx' || extension === '.js' || extension === '.jsx' || extension === '.mjs' || extension === '.cjs';
1387
+ }
1388
+ function isExternalLspLanguage(language) {
1389
+ return language === 'python' || language === 'rust' || language === 'go' || language === 'cpp' || language === 'csharp';
1390
+ }
1391
+ function resolveIndexedTextFile(snapshot, filePath) {
1392
+ const targetPath = resolveRequestedFilePath(snapshot.rootDirectory, filePath);
1393
+ if (!isPathInside(targetPath, snapshot.rootDirectory)) {
1394
+ return { success: false, filePath: targetPath, error: 'filePath is outside the indexed workspace.' };
1395
+ }
1396
+ const targetFile = snapshot.files.find((file) => normalizePathKey(file.absolutePath) === normalizePathKey(targetPath));
1397
+ if (!targetFile || !targetFile.textContent || !targetFile.isTextIndexed) {
1398
+ return { success: false, filePath: targetPath, error: 'filePath is not indexed as a text file.' };
1399
+ }
1400
+ return { success: true, file: targetFile, filePath: targetFile.absolutePath };
1401
+ }
1402
+ async function createTypeScriptLanguageService(snapshot, targetFile, request) {
1403
+ const ts = await import('typescript');
1404
+ const scriptFiles = snapshot.files.filter((file) => file.textContent && file.isTextIndexed && isTypeScriptLike(file.extension));
1405
+ const fileByPath = new Map(scriptFiles.map((file) => [normalizePathKey(file.absolutePath), file]));
1406
+ const compilerOptions = {
1407
+ allowJs: true,
1408
+ checkJs: false,
1409
+ jsx: ts.JsxEmit.ReactJSX,
1410
+ module: ts.ModuleKind.NodeNext,
1411
+ moduleResolution: ts.ModuleResolutionKind.NodeNext,
1412
+ target: ts.ScriptTarget.ES2022,
1413
+ skipLibCheck: true,
1414
+ strict: false,
1415
+ };
1416
+ const host = {
1417
+ getCompilationSettings: () => compilerOptions,
1418
+ getScriptFileNames: () => scriptFiles.map((file) => file.absolutePath),
1419
+ getScriptVersion: (fileName) => fileByPath.get(normalizePathKey(fileName))?.hash || '0',
1420
+ getScriptSnapshot: (fileName) => {
1421
+ const file = fileByPath.get(normalizePathKey(fileName));
1422
+ if (file?.textContent !== undefined)
1423
+ return ts.ScriptSnapshot.fromString(file.textContent);
1424
+ const diskText = ts.sys.readFile(fileName);
1425
+ return diskText === undefined ? undefined : ts.ScriptSnapshot.fromString(diskText);
1426
+ },
1427
+ getCurrentDirectory: () => snapshot.rootDirectory,
1428
+ getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),
1429
+ useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
1430
+ fileExists: (fileName) => fileByPath.has(normalizePathKey(fileName)) || ts.sys.fileExists(fileName),
1431
+ readFile: (fileName) => fileByPath.get(normalizePathKey(fileName))?.textContent || ts.sys.readFile(fileName),
1432
+ readDirectory: ts.sys.readDirectory,
1433
+ directoryExists: ts.sys.directoryExists,
1434
+ getDirectories: ts.sys.getDirectories,
1435
+ ...(ts.sys.realpath ? { realpath: ts.sys.realpath } : {}),
1436
+ };
1437
+ return {
1438
+ ts,
1439
+ languageService: ts.createLanguageService(host, ts.createDocumentRegistry()),
1440
+ formatOptions: { indentSize: 2, tabSize: 2, convertTabsToSpaces: true, newLineCharacter: '\n' },
1441
+ preferences: { includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true },
1442
+ requestedPosition: offsetAtPosition(targetFile.textContent || '', request.line, request.column),
1443
+ };
1444
+ }
1445
+ function matchesRequestedCodeAction(request, candidate) {
1446
+ if (request.actionId && request.actionId === candidate.id)
1447
+ return true;
1448
+ if (request.diagnosticCode && request.diagnosticCode !== candidate.diagnosticCode)
1449
+ return false;
1450
+ if (request.kind && request.kind !== candidate.kind)
1451
+ return false;
1452
+ if (request.title && request.title !== candidate.title)
1453
+ return false;
1454
+ return !request.actionId && (!!request.title || !!request.diagnosticCode || !!request.kind);
1455
+ }
1456
+ function applyTsFileTextChanges(rootDirectory, changes) {
1457
+ const grouped = new Map();
1458
+ for (const change of changes) {
1459
+ const absolutePath = resolve(change.fileName);
1460
+ if (!isPathInside(absolutePath, rootDirectory)) {
1461
+ throw new Error(`Refusing to edit file outside workspace: ${change.fileName}`);
1462
+ }
1463
+ grouped.set(absolutePath, [...(grouped.get(absolutePath) || []), ...change.textChanges]);
1464
+ }
1465
+ const summaries = [];
1466
+ for (const [filePath, textChanges] of grouped) {
1467
+ const before = existsSync(filePath) ? readFileSync(filePath, 'utf-8') : '';
1468
+ let after = before;
1469
+ const sorted = [...textChanges].sort((a, b) => b.span.start - a.span.start);
1470
+ for (const textChange of sorted) {
1471
+ const start = Math.max(0, Math.min(after.length, textChange.span.start));
1472
+ const end = Math.max(start, Math.min(after.length, start + textChange.span.length));
1473
+ after = `${after.slice(0, start)}${textChange.newText}${after.slice(end)}`;
1474
+ }
1475
+ const changed = after !== before;
1476
+ if (changed) {
1477
+ writeFileSync(filePath, after, 'utf-8');
1478
+ }
1479
+ summaries.push({
1480
+ filePath,
1481
+ relativePath: relative(rootDirectory, filePath).replace(/\\/g, '/'),
1482
+ changed,
1483
+ editCount: textChanges.length,
1484
+ preview: previewAppliedEdits(before, after, textChanges),
1485
+ beforeHash: hashText(before),
1486
+ afterHash: hashText(after),
1487
+ });
1488
+ }
1489
+ return summaries;
1490
+ }
1491
+ function applyExternalWorkspaceEdit(rootDirectory, workspaceEdit) {
1492
+ const editsByFile = collectExternalWorkspaceEdits(workspaceEdit);
1493
+ const summaries = [];
1494
+ for (const [uri, edits] of editsByFile) {
1495
+ const filePath = resolve(decodeFileUri(uri));
1496
+ if (!isPathInside(filePath, rootDirectory)) {
1497
+ throw new Error(`Refusing to apply LSP edit outside workspace: ${uri}`);
1498
+ }
1499
+ if (!existsSync(filePath)) {
1500
+ throw new Error(`Refusing to apply LSP edit to missing file: ${filePath}`);
1501
+ }
1502
+ const before = readFileSync(filePath, 'utf-8');
1503
+ let after = before;
1504
+ const normalized = edits
1505
+ .map((edit) => {
1506
+ const start = offsetAtLspPosition(before, edit.startLine, edit.startCharacter);
1507
+ const end = offsetAtLspPosition(before, edit.endLine, edit.endCharacter);
1508
+ return { start: Math.min(start, end), end: Math.max(start, end), newText: edit.newText };
1509
+ })
1510
+ .sort((a, b) => b.start - a.start || b.end - a.end);
1511
+ for (const edit of normalized) {
1512
+ after = `${after.slice(0, edit.start)}${edit.newText}${after.slice(edit.end)}`;
1513
+ }
1514
+ const changed = before !== after;
1515
+ if (changed) {
1516
+ writeFileSync(filePath, after, 'utf-8');
1517
+ }
1518
+ summaries.push({
1519
+ filePath,
1520
+ relativePath: relative(rootDirectory, filePath).replace(/\\/g, '/'),
1521
+ changed,
1522
+ editCount: normalized.length,
1523
+ preview: previewExternalAppliedEdits(before, after, normalized),
1524
+ beforeHash: hashText(before),
1525
+ afterHash: hashText(after),
1526
+ });
1527
+ }
1528
+ return summaries;
1529
+ }
1530
+ function collectExternalWorkspaceEdits(workspaceEdit) {
1531
+ const record = asPlainRecord(workspaceEdit);
1532
+ const result = new Map();
1533
+ const changes = asPlainRecord(record.changes);
1534
+ for (const [uri, edits] of Object.entries(changes)) {
1535
+ appendExternalTextEdits(result, uri, edits);
1536
+ }
1537
+ const documentChanges = Array.isArray(record.documentChanges) ? record.documentChanges : [];
1538
+ for (const change of documentChanges) {
1539
+ const changeRecord = asPlainRecord(change);
1540
+ if (typeof changeRecord.kind === 'string') {
1541
+ throw new Error(`Refusing unsupported LSP resource operation: ${changeRecord.kind}`);
1542
+ }
1543
+ const textDocument = asPlainRecord(changeRecord.textDocument);
1544
+ const uri = typeof textDocument.uri === 'string' ? textDocument.uri : '';
1545
+ if (!uri)
1546
+ continue;
1547
+ appendExternalTextEdits(result, uri, changeRecord.edits);
1548
+ }
1549
+ return result;
1550
+ }
1551
+ function appendExternalTextEdits(target, uri, edits) {
1552
+ if (!uri.startsWith('file://'))
1553
+ throw new Error(`Refusing non-file LSP edit target: ${uri}`);
1554
+ if (!Array.isArray(edits))
1555
+ return;
1556
+ const parsed = edits
1557
+ .map((edit) => parseExternalTextEdit(edit))
1558
+ .filter((edit) => !!edit);
1559
+ if (!parsed.length)
1560
+ return;
1561
+ target.set(uri, [...(target.get(uri) || []), ...parsed]);
1562
+ }
1563
+ function parseExternalTextEdit(edit) {
1564
+ const record = asPlainRecord(edit);
1565
+ const range = asPlainRecord(record.range);
1566
+ const start = asPlainRecord(range.start);
1567
+ const end = asPlainRecord(range.end);
1568
+ if (typeof record.newText !== 'string')
1569
+ return null;
1570
+ return {
1571
+ startLine: finiteNumber(start.line),
1572
+ startCharacter: finiteNumber(start.character),
1573
+ endLine: finiteNumber(end.line),
1574
+ endCharacter: finiteNumber(end.character),
1575
+ newText: record.newText,
1576
+ };
1577
+ }
1578
+ function offsetAtLspPosition(content, zeroBasedLine, zeroBasedCharacter) {
1579
+ const lines = content.split(/\r?\n/);
1580
+ let offset = 0;
1581
+ const safeLine = Math.max(0, Math.min(zeroBasedLine, lines.length - 1));
1582
+ for (let index = 0; index < safeLine; index += 1) {
1583
+ offset += lines[index].length + 1;
1584
+ }
1585
+ return Math.max(0, Math.min(content.length, offset + Math.max(0, zeroBasedCharacter)));
1586
+ }
1587
+ function previewExternalAppliedEdits(before, after, edits) {
1588
+ if (before === after)
1589
+ return 'No textual changes were required.';
1590
+ return edits.slice(0, 10).map((edit) => {
1591
+ const loc = lineColumnAt(before, edit.start);
1592
+ const inserted = edit.newText.replace(/\s+/g, ' ').trim();
1593
+ return `${loc.line}:${loc.column} ${inserted ? inserted.slice(0, 180) : '[remove text]'}`;
1594
+ }).join('\n');
1595
+ }
1596
+ function previewAppliedEdits(before, after, textChanges) {
1597
+ if (before === after)
1598
+ return 'No textual changes were required.';
1599
+ const lines = [];
1600
+ for (const textChange of textChanges.slice(0, 10)) {
1601
+ const loc = lineColumnAt(before, textChange.span.start);
1602
+ const inserted = textChange.newText.replace(/\s+/g, ' ').trim();
1603
+ lines.push(`${loc.line}:${loc.column} ${inserted ? inserted.slice(0, 180) : '[remove text]'}`);
1604
+ }
1605
+ return lines.join('\n');
1606
+ }
1607
+ function offsetAtPosition(content, line, column) {
1608
+ if (!line || !column || line < 1 || column < 1)
1609
+ return 0;
1610
+ const lines = content.split(/\r?\n/);
1611
+ let offset = 0;
1612
+ for (let index = 0; index < Math.min(line - 1, lines.length); index += 1) {
1613
+ offset += lines[index].length + 1;
1614
+ }
1615
+ return Math.max(0, Math.min(content.length, offset + column - 1));
1616
+ }
1617
+ function mapTsDiagnostic(ts, rootDirectory, fallbackFilePath, fallbackContent, diagnostic) {
1618
+ const filePath = diagnostic.file?.fileName || fallbackFilePath;
1619
+ const content = diagnostic.file?.text || fallbackContent;
1620
+ const loc = lineColumnAt(content, typeof diagnostic.start === 'number' ? diagnostic.start : 0);
1621
+ const category = diagnostic.category === ts.DiagnosticCategory.Warning
1622
+ ? 'warning'
1623
+ : diagnostic.category === ts.DiagnosticCategory.Message || diagnostic.category === ts.DiagnosticCategory.Suggestion
1624
+ ? 'info'
1625
+ : 'error';
1626
+ const absolutePath = resolve(filePath);
1627
+ const relativePath = isPathInside(absolutePath, rootDirectory)
1628
+ ? relative(rootDirectory, absolutePath).replace(/\\/g, '/')
1629
+ : filePath;
1630
+ const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
1631
+ return {
1632
+ id: `ts-${diagnostic.code}-${hashText(`${relativePath}:${diagnostic.start}:${message}`).slice(0, 10)}`,
1633
+ filePath: absolutePath,
1634
+ relativePath,
1635
+ line: loc.line,
1636
+ column: loc.column,
1637
+ severity: category,
1638
+ source: 'typescript-language-service',
1639
+ code: String(diagnostic.code),
1640
+ message,
1641
+ };
1642
+ }
1643
+ function mapExternalDiagnostic(rootDirectory, targetFile, diagnostic, source, index) {
1644
+ const idPayload = `${targetFile.relativePath}:${diagnostic.line}:${diagnostic.column}:${diagnostic.code || ''}:${diagnostic.message}`;
1645
+ return {
1646
+ id: `lsp-${source}-${hashText(idPayload).slice(0, 10)}`,
1647
+ filePath: targetFile.absolutePath,
1648
+ relativePath: isPathInside(targetFile.absolutePath, rootDirectory)
1649
+ ? relative(rootDirectory, targetFile.absolutePath).replace(/\\/g, '/')
1650
+ : targetFile.relativePath,
1651
+ line: diagnostic.line,
1652
+ column: diagnostic.column,
1653
+ severity: diagnostic.severity,
1654
+ source,
1655
+ language: targetFile.language,
1656
+ serviceId: source,
1657
+ route: 'external-lsp',
1658
+ code: diagnostic.code || String(index + 1),
1659
+ message: diagnostic.message,
1660
+ };
1661
+ }
1662
+ function previewTextChanges(rootDirectory, changes) {
1663
+ const lines = [];
1664
+ for (const change of changes.slice(0, 8)) {
1665
+ const fileLabel = isPathInside(change.fileName, rootDirectory)
1666
+ ? relative(rootDirectory, change.fileName).replace(/\\/g, '/')
1667
+ : change.fileName;
1668
+ for (const textChange of change.textChanges.slice(0, 8)) {
1669
+ const cleanText = textChange.newText.replace(/\s+/g, ' ').trim();
1670
+ lines.push(`${fileLabel}: ${cleanText ? cleanText.slice(0, 180) : '[remove text]'}`);
1671
+ if (lines.length >= 12)
1672
+ break;
1673
+ }
1674
+ if (lines.length >= 12)
1675
+ break;
1676
+ }
1677
+ return lines.join('\n');
1678
+ }
1679
+ function textChangeFiles(rootDirectory, changes) {
1680
+ const files = changes.map((change) => {
1681
+ const absolutePath = resolve(change.fileName);
1682
+ return isPathInside(absolutePath, rootDirectory)
1683
+ ? relative(rootDirectory, absolutePath).replace(/\\/g, '/')
1684
+ : change.fileName.replace(/\\/g, '/');
1685
+ });
1686
+ return [...new Set(files)];
1687
+ }
1688
+ function clampLimit(limit, fallback) {
1689
+ return Math.max(1, Math.min(1000, limit || fallback));
1690
+ }
1691
+ function errorMessage(err) {
1692
+ return err instanceof Error ? err.message : String(err);
1693
+ }
1694
+ function asPlainRecord(value) {
1695
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
1696
+ }
1697
+ function finiteNumber(value) {
1698
+ return typeof value === 'number' && Number.isFinite(value) ? Math.max(0, value) : 0;
1699
+ }
1700
+ function decodeFileUri(uri) {
1701
+ if (!uri.startsWith('file://'))
1702
+ return uri;
1703
+ const withoutScheme = uri.slice('file://'.length);
1704
+ try {
1705
+ return decodeURIComponent(withoutScheme.replace(/^\//, ''));
1706
+ }
1707
+ catch {
1708
+ return withoutScheme.replace(/^\//, '');
1709
+ }
1710
+ }
1711
+ let singleton = null;
1712
+ export function getCodebaseIntelligenceService() {
1713
+ if (!singleton)
1714
+ singleton = new CodebaseIntelligenceService();
1715
+ return singleton;
1716
+ }
1717
+ //# sourceMappingURL=CodebaseIntelligenceService.js.map