apex-code 0.0.1-alpha.7 → 0.0.1-alpha.9

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 (393) hide show
  1. package/CHANGELOG.md +229 -0
  2. package/README.md +5 -0
  3. package/dist/cli/args.d.ts +4 -1
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +44 -9
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/concurrent-session.d.ts +3 -0
  8. package/dist/cli/concurrent-session.d.ts.map +1 -0
  9. package/dist/cli/concurrent-session.js +13 -0
  10. package/dist/cli/concurrent-session.js.map +1 -0
  11. package/dist/cli/file-processor.d.ts.map +1 -1
  12. package/dist/cli/file-processor.js +2 -1
  13. package/dist/cli/file-processor.js.map +1 -1
  14. package/dist/cli.d.ts.map +1 -1
  15. package/dist/cli.js +1 -2
  16. package/dist/cli.js.map +1 -1
  17. package/dist/config.d.ts +3 -2
  18. package/dist/config.d.ts.map +1 -1
  19. package/dist/config.js +21 -13
  20. package/dist/config.js.map +1 -1
  21. package/dist/core/agent-session-services.d.ts.map +1 -1
  22. package/dist/core/agent-session-services.js +20 -0
  23. package/dist/core/agent-session-services.js.map +1 -1
  24. package/dist/core/agent-session.d.ts +41 -9
  25. package/dist/core/agent-session.d.ts.map +1 -1
  26. package/dist/core/agent-session.js +172 -101
  27. package/dist/core/agent-session.js.map +1 -1
  28. package/dist/core/auth-storage.d.ts +4 -1
  29. package/dist/core/auth-storage.d.ts.map +1 -1
  30. package/dist/core/auth-storage.js +12 -9
  31. package/dist/core/auth-storage.js.map +1 -1
  32. package/dist/core/bash-executor.d.ts.map +1 -1
  33. package/dist/core/bash-executor.js +10 -9
  34. package/dist/core/bash-executor.js.map +1 -1
  35. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  36. package/dist/core/compaction/branch-summarization.js +3 -0
  37. package/dist/core/compaction/branch-summarization.js.map +1 -1
  38. package/dist/core/compaction/compaction.d.ts +4 -3
  39. package/dist/core/compaction/compaction.d.ts.map +1 -1
  40. package/dist/core/compaction/compaction.js +41 -32
  41. package/dist/core/compaction/compaction.js.map +1 -1
  42. package/dist/core/defaults.d.ts +1 -0
  43. package/dist/core/defaults.d.ts.map +1 -1
  44. package/dist/core/defaults.js +9 -0
  45. package/dist/core/defaults.js.map +1 -1
  46. package/dist/core/durable-state/sqlite.d.ts.map +1 -1
  47. package/dist/core/durable-state/sqlite.js +26 -2
  48. package/dist/core/durable-state/sqlite.js.map +1 -1
  49. package/dist/core/experimental.d.ts +4 -0
  50. package/dist/core/experimental.d.ts.map +1 -1
  51. package/dist/core/experimental.js +4 -0
  52. package/dist/core/experimental.js.map +1 -1
  53. package/dist/core/extensions/index.d.ts +2 -2
  54. package/dist/core/extensions/index.d.ts.map +1 -1
  55. package/dist/core/extensions/index.js +1 -1
  56. package/dist/core/extensions/index.js.map +1 -1
  57. package/dist/core/extensions/loader.d.ts.map +1 -1
  58. package/dist/core/extensions/loader.js +115 -48
  59. package/dist/core/extensions/loader.js.map +1 -1
  60. package/dist/core/extensions/types.d.ts +42 -9
  61. package/dist/core/extensions/types.d.ts.map +1 -1
  62. package/dist/core/extensions/types.js +3 -0
  63. package/dist/core/extensions/types.js.map +1 -1
  64. package/dist/core/footer-data-provider.d.ts +1 -1
  65. package/dist/core/footer-data-provider.d.ts.map +1 -1
  66. package/dist/core/footer-data-provider.js +1 -1
  67. package/dist/core/footer-data-provider.js.map +1 -1
  68. package/dist/core/http-dispatcher.d.ts +1 -2
  69. package/dist/core/http-dispatcher.d.ts.map +1 -1
  70. package/dist/core/http-dispatcher.js +2 -17
  71. package/dist/core/http-dispatcher.js.map +1 -1
  72. package/dist/core/http-idle-timeout.d.ts +12 -0
  73. package/dist/core/http-idle-timeout.d.ts.map +1 -0
  74. package/dist/core/http-idle-timeout.js +27 -0
  75. package/dist/core/http-idle-timeout.js.map +1 -0
  76. package/dist/core/keybindings.d.ts +38 -13
  77. package/dist/core/keybindings.d.ts.map +1 -1
  78. package/dist/core/keybindings.js +26 -5
  79. package/dist/core/keybindings.js.map +1 -1
  80. package/dist/core/lsp/client.d.ts +2 -0
  81. package/dist/core/lsp/client.d.ts.map +1 -1
  82. package/dist/core/lsp/client.js +27 -2
  83. package/dist/core/lsp/client.js.map +1 -1
  84. package/dist/core/model-config.d.ts +10 -0
  85. package/dist/core/model-config.d.ts.map +1 -1
  86. package/dist/core/model-config.js +4 -1
  87. package/dist/core/model-config.js.map +1 -1
  88. package/dist/core/model-resolver.d.ts +1 -0
  89. package/dist/core/model-resolver.d.ts.map +1 -1
  90. package/dist/core/model-resolver.js +14 -8
  91. package/dist/core/model-resolver.js.map +1 -1
  92. package/dist/core/models-store.d.ts.map +1 -1
  93. package/dist/core/models-store.js +2 -1
  94. package/dist/core/models-store.js.map +1 -1
  95. package/dist/core/package-manager.d.ts.map +1 -1
  96. package/dist/core/package-manager.js +22 -14
  97. package/dist/core/package-manager.js.map +1 -1
  98. package/dist/core/pi-manifest.d.ts.map +1 -1
  99. package/dist/core/pi-manifest.js +2 -1
  100. package/dist/core/pi-manifest.js.map +1 -1
  101. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  102. package/dist/core/remote-catalog-provider.js +2 -1
  103. package/dist/core/remote-catalog-provider.js.map +1 -1
  104. package/dist/core/resource-loader.d.ts.map +1 -1
  105. package/dist/core/resource-loader.js +3 -2
  106. package/dist/core/resource-loader.js.map +1 -1
  107. package/dist/core/sandbox/child-entry.d.ts.map +1 -1
  108. package/dist/core/sandbox/child-entry.js +8 -1
  109. package/dist/core/sandbox/child-entry.js.map +1 -1
  110. package/dist/core/sandbox/cli-launch.d.ts +3 -0
  111. package/dist/core/sandbox/cli-launch.d.ts.map +1 -1
  112. package/dist/core/sandbox/cli-launch.js +25 -4
  113. package/dist/core/sandbox/cli-launch.js.map +1 -1
  114. package/dist/core/sandbox/cli-supervisor.d.ts.map +1 -1
  115. package/dist/core/sandbox/cli-supervisor.js +53 -13
  116. package/dist/core/sandbox/cli-supervisor.js.map +1 -1
  117. package/dist/core/sandbox/linux-backend.d.ts.map +1 -1
  118. package/dist/core/sandbox/linux-backend.js +15 -0
  119. package/dist/core/sandbox/linux-backend.js.map +1 -1
  120. package/dist/core/sandbox/macos-backend.d.ts.map +1 -1
  121. package/dist/core/sandbox/macos-backend.js +24 -1
  122. package/dist/core/sandbox/macos-backend.js.map +1 -1
  123. package/dist/core/sandbox/rpc/credential-client.d.ts +20 -0
  124. package/dist/core/sandbox/rpc/credential-client.d.ts.map +1 -0
  125. package/dist/core/sandbox/rpc/credential-client.js +170 -0
  126. package/dist/core/sandbox/rpc/credential-client.js.map +1 -0
  127. package/dist/core/sandbox/rpc/credential-proxy.d.ts +44 -0
  128. package/dist/core/sandbox/rpc/credential-proxy.d.ts.map +1 -0
  129. package/dist/core/sandbox/rpc/credential-proxy.js +381 -0
  130. package/dist/core/sandbox/rpc/credential-proxy.js.map +1 -0
  131. package/dist/core/sandbox/supervisor.d.ts +11 -0
  132. package/dist/core/sandbox/supervisor.d.ts.map +1 -1
  133. package/dist/core/sandbox/supervisor.js.map +1 -1
  134. package/dist/core/sandbox/terminal-size.d.ts +40 -0
  135. package/dist/core/sandbox/terminal-size.d.ts.map +1 -0
  136. package/dist/core/sandbox/terminal-size.js +105 -0
  137. package/dist/core/sandbox/terminal-size.js.map +1 -0
  138. package/dist/core/sdk.d.ts +8 -5
  139. package/dist/core/sdk.d.ts.map +1 -1
  140. package/dist/core/sdk.js +26 -7
  141. package/dist/core/sdk.js.map +1 -1
  142. package/dist/core/session-export.d.ts +4 -0
  143. package/dist/core/session-export.d.ts.map +1 -0
  144. package/dist/core/session-export.js +32 -0
  145. package/dist/core/session-export.js.map +1 -0
  146. package/dist/core/session-lease.d.ts +31 -0
  147. package/dist/core/session-lease.d.ts.map +1 -0
  148. package/dist/core/session-lease.js +138 -0
  149. package/dist/core/session-lease.js.map +1 -0
  150. package/dist/core/session-manager.d.ts +5 -0
  151. package/dist/core/session-manager.d.ts.map +1 -1
  152. package/dist/core/session-manager.js +5 -4
  153. package/dist/core/session-manager.js.map +1 -1
  154. package/dist/core/settings-diagnostics.d.ts +9 -0
  155. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  156. package/dist/core/settings-diagnostics.js +21 -0
  157. package/dist/core/settings-diagnostics.js.map +1 -0
  158. package/dist/core/settings-manager.d.ts +35 -0
  159. package/dist/core/settings-manager.d.ts.map +1 -1
  160. package/dist/core/settings-manager.js +93 -12
  161. package/dist/core/settings-manager.js.map +1 -1
  162. package/dist/core/skills.d.ts.map +1 -1
  163. package/dist/core/skills.js +51 -33
  164. package/dist/core/skills.js.map +1 -1
  165. package/dist/core/slash-commands.d.ts.map +1 -1
  166. package/dist/core/slash-commands.js +4 -1
  167. package/dist/core/slash-commands.js.map +1 -1
  168. package/dist/core/system-prompt.d.ts +2 -2
  169. package/dist/core/system-prompt.d.ts.map +1 -1
  170. package/dist/core/system-prompt.js +53 -62
  171. package/dist/core/system-prompt.js.map +1 -1
  172. package/dist/core/tools/bash.d.ts +14 -1
  173. package/dist/core/tools/bash.d.ts.map +1 -1
  174. package/dist/core/tools/bash.js +38 -20
  175. package/dist/core/tools/bash.js.map +1 -1
  176. package/dist/core/tools/delegate.d.ts.map +1 -1
  177. package/dist/core/tools/delegate.js +24 -0
  178. package/dist/core/tools/delegate.js.map +1 -1
  179. package/dist/core/tools/edit-diff.d.ts +0 -5
  180. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  181. package/dist/core/tools/edit-diff.js +2 -5
  182. package/dist/core/tools/edit-diff.js.map +1 -1
  183. package/dist/core/tools/edit.d.ts.map +1 -1
  184. package/dist/core/tools/edit.js +22 -4
  185. package/dist/core/tools/edit.js.map +1 -1
  186. package/dist/core/tools/find.d.ts.map +1 -1
  187. package/dist/core/tools/find.js +1 -1
  188. package/dist/core/tools/find.js.map +1 -1
  189. package/dist/core/tools/grep.d.ts +2 -0
  190. package/dist/core/tools/grep.d.ts.map +1 -1
  191. package/dist/core/tools/grep.js +35 -10
  192. package/dist/core/tools/grep.js.map +1 -1
  193. package/dist/core/tools/index.d.ts +4 -1
  194. package/dist/core/tools/index.d.ts.map +1 -1
  195. package/dist/core/tools/index.js +9 -0
  196. package/dist/core/tools/index.js.map +1 -1
  197. package/dist/core/tools/ls.d.ts +2 -0
  198. package/dist/core/tools/ls.d.ts.map +1 -1
  199. package/dist/core/tools/ls.js +5 -1
  200. package/dist/core/tools/ls.js.map +1 -1
  201. package/dist/core/tools/powershell.d.ts +16 -0
  202. package/dist/core/tools/powershell.d.ts.map +1 -0
  203. package/dist/core/tools/powershell.js +39 -0
  204. package/dist/core/tools/powershell.js.map +1 -0
  205. package/dist/core/tools/read.d.ts.map +1 -1
  206. package/dist/core/tools/read.js +2 -0
  207. package/dist/core/tools/read.js.map +1 -1
  208. package/dist/core/tools/web-search-exa.d.ts +33 -0
  209. package/dist/core/tools/web-search-exa.d.ts.map +1 -0
  210. package/dist/core/tools/web-search-exa.js +128 -0
  211. package/dist/core/tools/web-search-exa.js.map +1 -0
  212. package/dist/core/tools/write.d.ts.map +1 -1
  213. package/dist/core/tools/write.js +2 -0
  214. package/dist/core/tools/write.js.map +1 -1
  215. package/dist/core/trust-manager.d.ts.map +1 -1
  216. package/dist/core/trust-manager.js +2 -1
  217. package/dist/core/trust-manager.js.map +1 -1
  218. package/dist/core/web-search-provider.d.ts +64 -0
  219. package/dist/core/web-search-provider.d.ts.map +1 -0
  220. package/dist/core/web-search-provider.js +149 -0
  221. package/dist/core/web-search-provider.js.map +1 -0
  222. package/dist/extensions/llama/index.d.ts.map +1 -1
  223. package/dist/extensions/llama/index.js +2 -0
  224. package/dist/extensions/llama/index.js.map +1 -1
  225. package/dist/extensions/llama/provider.d.ts.map +1 -1
  226. package/dist/extensions/llama/provider.js +6 -2
  227. package/dist/extensions/llama/provider.js.map +1 -1
  228. package/dist/index.d.ts +6 -6
  229. package/dist/index.d.ts.map +1 -1
  230. package/dist/index.js +4 -4
  231. package/dist/index.js.map +1 -1
  232. package/dist/main.d.ts +5 -0
  233. package/dist/main.d.ts.map +1 -1
  234. package/dist/main.js +38 -16
  235. package/dist/main.js.map +1 -1
  236. package/dist/migrations.d.ts.map +1 -1
  237. package/dist/migrations.js +4 -3
  238. package/dist/migrations.js.map +1 -1
  239. package/dist/modes/interactive/components/custom-editor.d.ts +23 -0
  240. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  241. package/dist/modes/interactive/components/custom-editor.js +105 -2
  242. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  243. package/dist/modes/interactive/components/dynamic-border.d.ts +7 -1
  244. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  245. package/dist/modes/interactive/components/dynamic-border.js +11 -2
  246. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  247. package/dist/modes/interactive/components/extension-selector.d.ts +4 -0
  248. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  249. package/dist/modes/interactive/components/extension-selector.js +24 -6
  250. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  251. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  252. package/dist/modes/interactive/components/first-time-setup.js +6 -3
  253. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  254. package/dist/modes/interactive/components/first-use-hints.d.ts +8 -0
  255. package/dist/modes/interactive/components/first-use-hints.d.ts.map +1 -0
  256. package/dist/modes/interactive/components/first-use-hints.js +22 -0
  257. package/dist/modes/interactive/components/first-use-hints.js.map +1 -0
  258. package/dist/modes/interactive/components/footer.d.ts +12 -0
  259. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  260. package/dist/modes/interactive/components/footer.js +128 -9
  261. package/dist/modes/interactive/components/footer.js.map +1 -1
  262. package/dist/modes/interactive/components/index.d.ts +1 -0
  263. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  264. package/dist/modes/interactive/components/index.js +1 -0
  265. package/dist/modes/interactive/components/index.js.map +1 -1
  266. package/dist/modes/interactive/components/model-selector.d.ts +12 -3
  267. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  268. package/dist/modes/interactive/components/model-selector.js +71 -14
  269. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  270. package/dist/modes/interactive/components/settings-selector.d.ts +10 -3
  271. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  272. package/dist/modes/interactive/components/settings-selector.js +128 -56
  273. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  274. package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
  275. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
  276. package/dist/modes/interactive/components/settings-submenu.js +165 -0
  277. package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
  278. package/dist/modes/interactive/components/splash-header.d.ts +29 -4
  279. package/dist/modes/interactive/components/splash-header.d.ts.map +1 -1
  280. package/dist/modes/interactive/components/splash-header.js +58 -23
  281. package/dist/modes/interactive/components/splash-header.js.map +1 -1
  282. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  283. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  284. package/dist/modes/interactive/components/thinking-selector.js +74 -17
  285. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  286. package/dist/modes/interactive/components/tool-execution.d.ts +14 -0
  287. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  288. package/dist/modes/interactive/components/tool-execution.js +113 -35
  289. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  290. package/dist/modes/interactive/components/tool-panel.d.ts +30 -0
  291. package/dist/modes/interactive/components/tool-panel.d.ts.map +1 -0
  292. package/dist/modes/interactive/components/tool-panel.js +130 -0
  293. package/dist/modes/interactive/components/tool-panel.js.map +1 -0
  294. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  295. package/dist/modes/interactive/external-editor.js +2 -1
  296. package/dist/modes/interactive/external-editor.js.map +1 -1
  297. package/dist/modes/interactive/interactive-mode.d.ts +55 -9
  298. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  299. package/dist/modes/interactive/interactive-mode.js +446 -87
  300. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  301. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  302. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  303. package/dist/modes/interactive/model-catalog-refresh.js +34 -0
  304. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  305. package/dist/modes/interactive/theme/apex.json +62 -63
  306. package/dist/modes/interactive/theme/dark.json +2 -0
  307. package/dist/modes/interactive/theme/light.json +2 -0
  308. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  309. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  310. package/dist/modes/interactive/theme/theme-controller.js +25 -11
  311. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  312. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  313. package/dist/modes/interactive/theme/theme.d.ts +14 -3
  314. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  315. package/dist/modes/interactive/theme/theme.js +60 -10
  316. package/dist/modes/interactive/theme/theme.js.map +1 -1
  317. package/dist/modes/json-event.d.ts +18 -12
  318. package/dist/modes/json-event.d.ts.map +1 -1
  319. package/dist/modes/json-event.js +22 -5
  320. package/dist/modes/json-event.js.map +1 -1
  321. package/dist/package-manager-cli.d.ts +1 -0
  322. package/dist/package-manager-cli.d.ts.map +1 -1
  323. package/dist/package-manager-cli.js +197 -5
  324. package/dist/package-manager-cli.js.map +1 -1
  325. package/dist/server/create-harness.d.ts.map +1 -1
  326. package/dist/server/create-harness.js +2 -0
  327. package/dist/server/create-harness.js.map +1 -1
  328. package/dist/themes/apex-logo.d.ts +36 -16
  329. package/dist/themes/apex-logo.d.ts.map +1 -1
  330. package/dist/themes/apex-logo.js +32 -28
  331. package/dist/themes/apex-logo.js.map +1 -1
  332. package/dist/utils/frontmatter.d.ts.map +1 -1
  333. package/dist/utils/frontmatter.js +2 -1
  334. package/dist/utils/frontmatter.js.map +1 -1
  335. package/dist/utils/management-http.d.ts +5 -3
  336. package/dist/utils/management-http.d.ts.map +1 -1
  337. package/dist/utils/management-http.js +14 -10
  338. package/dist/utils/management-http.js.map +1 -1
  339. package/dist/utils/shell.d.ts +3 -0
  340. package/dist/utils/shell.d.ts.map +1 -1
  341. package/dist/utils/shell.js +17 -5
  342. package/dist/utils/shell.js.map +1 -1
  343. package/dist/utils/syntax-highlight.d.ts +1 -0
  344. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  345. package/dist/utils/syntax-highlight.js +60 -1
  346. package/dist/utils/syntax-highlight.js.map +1 -1
  347. package/dist/utils/text.d.ts +8 -0
  348. package/dist/utils/text.d.ts.map +1 -0
  349. package/dist/utils/text.js +9 -0
  350. package/dist/utils/text.js.map +1 -0
  351. package/dist/utils/tools-manager.d.ts +10 -1
  352. package/dist/utils/tools-manager.d.ts.map +1 -1
  353. package/dist/utils/tools-manager.js +15 -20
  354. package/dist/utils/tools-manager.js.map +1 -1
  355. package/docs/compaction.md +18 -3
  356. package/docs/custom-provider.md +6 -3
  357. package/docs/environment-variables.md +1 -0
  358. package/docs/extensions.md +21 -7
  359. package/docs/json.md +12 -5
  360. package/docs/keybindings.md +15 -9
  361. package/docs/llama-cpp.md +2 -0
  362. package/docs/models.md +8 -2
  363. package/docs/packages.md +2 -2
  364. package/docs/rpc.md +24 -7
  365. package/docs/sdk.md +16 -2
  366. package/docs/settings.md +73 -2
  367. package/docs/skills.md +4 -3
  368. package/docs/terminal-setup.md +34 -9
  369. package/docs/themes.md +24 -3
  370. package/docs/tui.md +2 -2
  371. package/docs/usage.md +9 -4
  372. package/docs/windows.md +24 -2
  373. package/examples/extensions/border-status-editor.ts +1 -1
  374. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  375. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  376. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  377. package/examples/extensions/git-checkpoint.ts +2 -2
  378. package/examples/extensions/gondolin/package-lock.json +2 -2
  379. package/examples/extensions/gondolin/package.json +1 -1
  380. package/examples/extensions/notify.ts +3 -1
  381. package/examples/extensions/sandbox/package-lock.json +2 -2
  382. package/examples/extensions/sandbox/package.json +1 -1
  383. package/examples/extensions/subagent/README.md +3 -1
  384. package/examples/extensions/subagent/agents.ts +40 -9
  385. package/examples/extensions/subagent/index.ts +27 -4
  386. package/examples/extensions/titlebar-spinner.ts +1 -1
  387. package/examples/extensions/with-deps/package-lock.json +2 -2
  388. package/examples/extensions/with-deps/package.json +1 -1
  389. package/examples/rpc-extension-ui.ts +1 -1
  390. package/examples/sdk/06-extensions.ts +1 -1
  391. package/examples/sdk/README.md +1 -1
  392. package/npm-shrinkwrap.json +280 -445
  393. package/package.json +9 -11
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/core/lsp/client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ChildProcess } from \"node:child_process\";\nimport type { Readable, Writable } from \"node:stream\";\nimport { pathToFileURL } from \"node:url\";\nimport { spawnProcess } from \"../../utils/child-process.ts\";\n\nexport const LSP_MAX_HEADER_BYTES = 8 * 1024;\nexport const LSP_MAX_MESSAGE_BYTES = 8 * 1024 * 1024;\nexport const LSP_MAX_STDERR_TAIL_BYTES = 64 * 1024;\n\nconst DEFAULT_INITIALIZATION_TIMEOUT_MS = 10_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nconst SHUTDOWN_TIMEOUT_MS = 2_000;\nconst TERMINATE_GRACE_MS = 500;\nconst KILL_GRACE_MS = 1_000;\n\nexport interface LspClientOptions {\n\treadonly command: string;\n\treadonly args?: readonly string[];\n\treadonly cwd: string;\n\treadonly env?: NodeJS.ProcessEnv;\n\treadonly initializationTimeoutMs?: number;\n\treadonly requestTimeoutMs?: number;\n}\n\nexport interface LspNotification {\n\treadonly method: string;\n\treadonly params?: unknown;\n}\n\nexport type LspTextDocumentSyncKind = \"none\" | \"full\" | \"incremental\";\n\nexport interface LspTextDocumentSync {\n\treadonly kind: LspTextDocumentSyncKind;\n\treadonly openClose: boolean;\n\treadonly save: boolean;\n\treadonly saveIncludeText: boolean;\n}\n\nexport class LspJsonRpcError extends Error {\n\treadonly code: number;\n\treadonly data?: unknown;\n\n\tconstructor(error: { code: number; message: string; data?: unknown }) {\n\t\tsuper(error.message);\n\t\tthis.name = \"LspJsonRpcError\";\n\t\tthis.code = error.code;\n\t\tthis.data = error.data;\n\t}\n}\n\ntype JsonRpcId = number;\ntype PendingRequest = {\n\tresolve(value: unknown): void;\n\treject(reason: Error): void;\n};\n\ntype ClientState = \"idle\" | \"starting\" | \"ready\" | \"closing\" | \"closed\" | \"failed\";\n\ntype JsonRpcMessage = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isJsonRpcId(value: unknown): value is string | number {\n\treturn typeof value === \"string\" || (typeof value === \"number\" && Number.isSafeInteger(value));\n}\n\nfunction normalizeError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction parseTextDocumentSync(value: unknown): LspTextDocumentSync {\n\tlet kind: LspTextDocumentSyncKind = \"none\";\n\tlet openClose = false;\n\tlet save = false;\n\tlet saveIncludeText = false;\n\tif (typeof value === \"number\") {\n\t\tkind = value === 1 ? \"full\" : value === 2 ? \"incremental\" : \"none\";\n\t} else if (isRecord(value)) {\n\t\topenClose = value.openClose === true;\n\t\tkind = value.change === 1 ? \"full\" : value.change === 2 ? \"incremental\" : \"none\";\n\t\tif (value.save === true) save = true;\n\t\telse if (isRecord(value.save)) {\n\t\t\tsave = true;\n\t\t\tsaveIncludeText = value.save.includeText === true;\n\t\t}\n\t}\n\treturn { kind, openClose, save, saveIncludeText };\n}\n\nfunction validateTimeout(value: number | undefined, fallback: number, label: string): number {\n\tconst timeout = value ?? fallback;\n\tif (!Number.isSafeInteger(timeout) || timeout < 1) throw new Error(`${label} must be a positive safe integer.`);\n\treturn timeout;\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** A bounded JSON-RPC 2.0 client for one language server's stdio. */\nexport class LspClient {\n\tprivate readonly options: LspClientOptions;\n\tprivate child: ChildProcess | undefined;\n\tprivate stdin: Writable | undefined;\n\tprivate stdout: Readable | undefined;\n\tprivate input = Buffer.alloc(0);\n\tprivate stderrTail = Buffer.alloc(0);\n\tprivate nextRequestId = 1;\n\tprivate readonly pending = new Map<JsonRpcId, PendingRequest>();\n\tprivate readonly notificationListeners = new Set<(notification: LspNotification) => void>();\n\tprivate readonly failureListeners = new Set<(error: Error) => void>();\n\tprivate startPromise: Promise<void> | undefined;\n\tprivate disposePromise: Promise<void> | undefined;\n\tprivate state: ClientState = \"idle\";\n\tprivate failure: Error | undefined;\n\tprivate writeChain: Promise<void> = Promise.resolve();\n\tprivate syncCapabilities: LspTextDocumentSync = {\n\t\tkind: \"none\",\n\t\topenClose: false,\n\t\tsave: false,\n\t\tsaveIncludeText: false,\n\t};\n\n\tconstructor(options: LspClientOptions) {\n\t\tthis.options = options;\n\t}\n\n\tget capturedStderr(): string {\n\t\treturn this.stderrTail.toString(\"utf8\");\n\t}\n\n\t/** Text-document synchronization negotiated during initialization. */\n\tget textDocumentSync(): LspTextDocumentSync {\n\t\treturn this.syncCapabilities;\n\t}\n\n\tonNotification(listener: (notification: LspNotification) => void): () => void {\n\t\tthis.notificationListeners.add(listener);\n\t\treturn () => this.notificationListeners.delete(listener);\n\t}\n\n\t/** Subscribe to the first terminal protocol or process failure. */\n\tonFailure(listener: (error: Error) => void): () => void {\n\t\tthis.failureListeners.add(listener);\n\t\tif (this.failure) listener(this.failure);\n\t\treturn () => this.failureListeners.delete(listener);\n\t}\n\n\tstart(): Promise<void> {\n\t\tif (this.failure) return Promise.reject(this.failure);\n\t\tif (this.state === \"closing\" || this.state === \"closed\") {\n\t\t\treturn Promise.reject(new Error(\"Language server client is disposed.\"));\n\t\t}\n\t\tif (!this.startPromise) {\n\t\t\tthis.state = \"starting\";\n\t\t\tthis.startPromise = this.initialize().catch(async (error) => {\n\t\t\t\tconst failure = normalizeError(error);\n\t\t\t\tthis.fail(failure);\n\t\t\t\tawait this.terminateChild();\n\t\t\t\tthrow failure;\n\t\t\t});\n\t\t}\n\t\treturn this.startPromise;\n\t}\n\n\tasync request(method: string, params?: unknown, signal?: AbortSignal): Promise<unknown> {\n\t\tawait this.start();\n\t\tif (this.state !== \"ready\") throw this.failure ?? new Error(\"Language server did not become ready.\");\n\t\treturn this.sendRequest(method, params, signal, this.requestTimeoutMs());\n\t}\n\n\tnotify(method: string, params?: unknown): void {\n\t\tif (this.failure) throw this.failure;\n\t\tif (this.state !== \"ready\") throw new Error(\"Language server is not ready.\");\n\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", method, ...(params === undefined ? {} : { params }) }).catch((error) => {\n\t\t\tthis.fail(normalizeError(error));\n\t\t});\n\t}\n\n\tdispose(): Promise<void> {\n\t\tif (!this.disposePromise) this.disposePromise = this.disposeProcess();\n\t\treturn this.disposePromise;\n\t}\n\n\tprivate initializationTimeoutMs(): number {\n\t\treturn validateTimeout(\n\t\t\tthis.options.initializationTimeoutMs,\n\t\t\tDEFAULT_INITIALIZATION_TIMEOUT_MS,\n\t\t\t\"initializationTimeoutMs\",\n\t\t);\n\t}\n\n\tprivate requestTimeoutMs(): number {\n\t\treturn validateTimeout(this.options.requestTimeoutMs, DEFAULT_REQUEST_TIMEOUT_MS, \"requestTimeoutMs\");\n\t}\n\n\tprivate async initialize(): Promise<void> {\n\t\tconst child = spawnProcess(this.options.command, [...(this.options.args ?? [])], {\n\t\t\tcwd: this.options.cwd,\n\t\t\tenv: this.options.env,\n\t\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t\t});\n\t\tif (!child.stdin || !child.stdout) {\n\t\t\tchild.kill();\n\t\t\tthrow new Error(\"Language server must expose piped stdin and stdout.\");\n\t\t}\n\t\tthis.child = child;\n\t\tthis.stdin = child.stdin;\n\t\tthis.stdout = child.stdout;\n\t\tthis.stdout.on(\"data\", (chunk: Buffer | string) => this.onData(chunk));\n\t\tchild.stderr?.on(\"data\", (chunk: Buffer | string) => this.captureStderr(chunk));\n\t\tchild.stdin.on(\"error\", (error) => this.fail(error));\n\t\tchild.once(\"error\", (error) => this.fail(error));\n\t\tchild.once(\"exit\", (code, signal) => {\n\t\t\tif (this.state !== \"closing\" && this.state !== \"closed\") {\n\t\t\t\tthis.fail(new Error(`Language server exited before shutdown (code=${code} signal=${signal}).`));\n\t\t\t}\n\t\t});\n\n\t\tconst initializeResult = await this.sendRequest(\n\t\t\t\"initialize\",\n\t\t\t{\n\t\t\t\tprocessId: process.pid,\n\t\t\t\tclientInfo: { name: \"Apex Code\" },\n\t\t\t\trootUri: pathToFileURL(this.options.cwd).href,\n\t\t\t\tcapabilities: {\n\t\t\t\t\tgeneral: { positionEncodings: [\"utf-16\"] },\n\t\t\t\t\tworkspace: { workspaceFolders: false },\n\t\t\t\t\ttextDocument: {\n\t\t\t\t\t\tdefinition: {},\n\t\t\t\t\t\treferences: {},\n\t\t\t\t\t\tdocumentSymbol: {},\n\t\t\t\t\t\tpublishDiagnostics: { versionSupport: true },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tworkspaceFolders: null,\n\t\t\t},\n\t\t\tundefined,\n\t\t\tthis.initializationTimeoutMs(),\n\t\t\t\"Language server initialize timed out\",\n\t\t);\n\t\tif (!isRecord(initializeResult) || !isRecord(initializeResult.capabilities)) {\n\t\t\tthrow new Error(\"Language server returned an invalid initialize result.\");\n\t\t}\n\t\tthis.syncCapabilities = parseTextDocumentSync(initializeResult.capabilities.textDocumentSync);\n\t\tif (this.state !== \"starting\") throw new Error(\"Language server initialization was interrupted.\");\n\t\tawait this.enqueueWrite({ jsonrpc: \"2.0\", method: \"initialized\", params: {} });\n\t\tthis.state = \"ready\";\n\t}\n\n\tprivate async disposeProcess(): Promise<void> {\n\t\tif (this.state === \"closed\") return;\n\t\tconst wasReady = this.state === \"ready\";\n\t\tthis.state = \"closing\";\n\t\tthis.rejectPending(new Error(\"Language server client is closing.\"));\n\n\t\tif (wasReady) {\n\t\t\ttry {\n\t\t\t\tawait this.sendRequest(\n\t\t\t\t\t\"shutdown\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tundefined,\n\t\t\t\t\tSHUTDOWN_TIMEOUT_MS,\n\t\t\t\t\t\"Language server shutdown timed out\",\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t\tawait this.enqueueWrite({ jsonrpc: \"2.0\", method: \"exit\" });\n\t\t\t} catch {\n\t\t\t\t// Bounded termination below is the fallback for an uncooperative server.\n\t\t\t}\n\t\t}\n\t\tawait this.terminateChild();\n\t\tthis.stdin?.end();\n\t\tthis.state = \"closed\";\n\t}\n\n\tprivate async terminateChild(): Promise<void> {\n\t\tconst child = this.child;\n\t\tif (!child || child.exitCode !== null || child.signalCode !== null) return;\n\t\tconst exited = new Promise<void>((resolve) => child.once(\"exit\", () => resolve()));\n\t\tconst graceful = await Promise.race([exited.then(() => true), delay(TERMINATE_GRACE_MS).then(() => false)]);\n\t\tif (graceful) return;\n\t\tchild.kill(\"SIGTERM\");\n\t\tconst terminated = await Promise.race([exited.then(() => true), delay(KILL_GRACE_MS).then(() => false)]);\n\t\tif (terminated) return;\n\t\tchild.kill(\"SIGKILL\");\n\t\tawait exited;\n\t}\n\n\tprivate sendRequest(\n\t\tmethod: string,\n\t\tparams?: unknown,\n\t\tsignal?: AbortSignal,\n\t\ttimeoutMs?: number,\n\t\ttimeoutMessage = `Language server request ${method} timed out`,\n\t\tallowClosing = false,\n\t): Promise<unknown> {\n\t\tif (this.failure && !allowClosing) return Promise.reject(this.failure);\n\t\tif ((!allowClosing && (this.state === \"closing\" || this.state === \"closed\")) || this.state === \"failed\") {\n\t\t\treturn Promise.reject(this.failure ?? new Error(\"Language server client is disposed.\"));\n\t\t}\n\t\tconst id = this.nextRequestId++;\n\t\tif (!Number.isSafeInteger(id)) return Promise.reject(new Error(\"Language server request id space exhausted.\"));\n\t\tif (signal?.aborted)\n\t\t\treturn Promise.reject(normalizeError(signal.reason ?? new Error(\"Language server request aborted.\")));\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet timer: NodeJS.Timeout | undefined;\n\t\t\tconst settle = (fn: () => void) => {\n\t\t\t\tif (timer) clearTimeout(timer);\n\t\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\t\tfn();\n\t\t\t};\n\t\t\tconst abort = () => {\n\t\t\t\tif (!this.pending.delete(id)) return;\n\t\t\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", method: \"$/cancelRequest\", params: { id } }).catch(() => {});\n\t\t\t\tsettle(() => reject(normalizeError(signal?.reason ?? new Error(\"Language server request aborted.\"))));\n\t\t\t};\n\t\t\tthis.pending.set(id, {\n\t\t\t\tresolve: (value) => settle(() => resolve(value)),\n\t\t\t\treject: (error) => settle(() => reject(error)),\n\t\t\t});\n\t\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\tif (timeoutMs !== undefined) {\n\t\t\t\ttimer = setTimeout(() => {\n\t\t\t\t\tif (!this.pending.delete(id)) return;\n\t\t\t\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", method: \"$/cancelRequest\", params: { id } }).catch(() => {});\n\t\t\t\t\tsettle(() => reject(new Error(`${timeoutMessage} after ${timeoutMs}ms.`)));\n\t\t\t\t}, timeoutMs);\n\t\t\t}\n\t\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", id, method, ...(params === undefined ? {} : { params }) }).catch(\n\t\t\t\t(error) => {\n\t\t\t\t\tconst pending = this.pending.get(id);\n\t\t\t\t\tif (!pending) return;\n\t\t\t\t\tthis.pending.delete(id);\n\t\t\t\t\tpending.reject(normalizeError(error));\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate enqueueWrite(message: object): Promise<void> {\n\t\tconst body = Buffer.from(JSON.stringify(message), \"utf8\");\n\t\tif (body.length > LSP_MAX_MESSAGE_BYTES)\n\t\t\treturn Promise.reject(new Error(\"Language server message exceeds 8 MiB.\"));\n\t\tconst frame = Buffer.concat([Buffer.from(`Content-Length: ${body.length}\\r\\n\\r\\n`, \"ascii\"), body]);\n\t\tconst writing = this.writeChain.then(() => this.writeFrame(frame));\n\t\tthis.writeChain = writing.catch(() => {});\n\t\treturn writing;\n\t}\n\n\tprivate writeFrame(frame: Buffer): Promise<void> {\n\t\tconst stream = this.stdin;\n\t\tif (!stream || stream.destroyed || !stream.writable) {\n\t\t\treturn Promise.reject(new Error(\"Language server stdin is not writable.\"));\n\t\t}\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet waitingForDrain = false;\n\t\t\tconst cleanup = () => {\n\t\t\t\tstream.removeListener(\"error\", onError);\n\t\t\t\tstream.removeListener(\"drain\", onDrain);\n\t\t\t};\n\t\t\tconst onError = (error: Error) => {\n\t\t\t\tcleanup();\n\t\t\t\treject(error);\n\t\t\t};\n\t\t\tconst onDrain = () => {\n\t\t\t\twaitingForDrain = false;\n\t\t\t\tcleanup();\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tstream.once(\"error\", onError);\n\t\t\tconst accepted = stream.write(frame, (error) => {\n\t\t\t\tif (error) onError(error);\n\t\t\t\telse if (!waitingForDrain) {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (!accepted) {\n\t\t\t\twaitingForDrain = true;\n\t\t\t\tstream.once(\"drain\", onDrain);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate onData(chunk: Buffer | string): void {\n\t\tif (this.failure) return;\n\t\tthis.input = Buffer.concat([this.input, typeof chunk === \"string\" ? Buffer.from(chunk) : chunk]);\n\t\twhile (true) {\n\t\t\tconst headerEnd = this.input.indexOf(\"\\r\\n\\r\\n\");\n\t\t\tif (headerEnd < 0) {\n\t\t\t\tif (this.input.length > LSP_MAX_HEADER_BYTES) this.fail(new Error(\"Language server header exceeds 8 KiB.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (headerEnd > LSP_MAX_HEADER_BYTES) {\n\t\t\t\tthis.fail(new Error(\"Language server header exceeds 8 KiB.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst header = this.input.subarray(0, headerEnd).toString(\"ascii\");\n\t\t\tconst lengths = [...header.matchAll(/(?:^|\\r\\n)Content-Length:\\s*(\\d+)(?=\\r\\n|$)/gi)];\n\t\t\tif (lengths.length !== 1) {\n\t\t\t\tthis.fail(new Error(\"Language server frame must contain exactly one Content-Length header.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst contentLength = Number(lengths[0][1]);\n\t\t\tif (!Number.isSafeInteger(contentLength) || contentLength > LSP_MAX_MESSAGE_BYTES) {\n\t\t\t\tthis.fail(new Error(\"Language server message exceeds 8 MiB.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst bodyStart = headerEnd + 4;\n\t\t\tif (this.input.length < bodyStart + contentLength) return;\n\t\t\tconst body = this.input.subarray(bodyStart, bodyStart + contentLength).toString(\"utf8\");\n\t\t\tthis.input = this.input.subarray(bodyStart + contentLength);\n\t\t\ttry {\n\t\t\t\tconst parsed: unknown = JSON.parse(body);\n\t\t\t\tif (!isRecord(parsed)) throw new Error(\"Language server JSON-RPC message must be an object.\");\n\t\t\t\tthis.onMessage(parsed);\n\t\t\t} catch (error) {\n\t\t\t\tthis.fail(normalizeError(error));\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onMessage(message: JsonRpcMessage): void {\n\t\tif (message.jsonrpc !== \"2.0\") {\n\t\t\tthis.fail(new Error('Language server message must declare jsonrpc \"2.0\".'));\n\t\t\treturn;\n\t\t}\n\t\tif (typeof message.method === \"string\") {\n\t\t\tif (message.id !== undefined && message.id !== null) {\n\t\t\t\tvoid this.handleServerRequest(message);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst notification: LspNotification = {\n\t\t\t\tmethod: message.method,\n\t\t\t\t...(message.params === undefined ? {} : { params: message.params }),\n\t\t\t};\n\t\t\tfor (const listener of this.notificationListeners) listener(notification);\n\t\t\treturn;\n\t\t}\n\t\tif (typeof message.id !== \"number\" || !Number.isSafeInteger(message.id)) return;\n\t\tconst pending = this.pending.get(message.id);\n\t\tif (!pending) return;\n\t\tconst hasResult = Object.hasOwn(message, \"result\");\n\t\tconst hasError = Object.hasOwn(message, \"error\");\n\t\tif (hasResult === hasError) {\n\t\t\tthis.fail(new Error(\"Language server response must contain exactly one of result or error.\"));\n\t\t\treturn;\n\t\t}\n\t\tthis.pending.delete(message.id);\n\t\tif (hasError) {\n\t\t\tconst error = message.error;\n\t\t\tif (!isRecord(error) || !Number.isSafeInteger(error.code) || typeof error.message !== \"string\") {\n\t\t\t\tthis.fail(new Error(\"Language server returned an invalid JSON-RPC error.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpending.reject(new LspJsonRpcError({ code: error.code as number, message: error.message, data: error.data }));\n\t\t\treturn;\n\t\t}\n\t\tpending.resolve(message.result);\n\t}\n\n\tprivate async handleServerRequest(message: JsonRpcMessage): Promise<void> {\n\t\tif (!isJsonRpcId(message.id) || typeof message.method !== \"string\") return;\n\t\tlet result: unknown;\n\t\tlet error: { code: number; message: string } | undefined;\n\t\tswitch (message.method) {\n\t\t\tcase \"workspace/configuration\": {\n\t\t\t\tconst params = message.params;\n\t\t\t\tif (!isRecord(params) || !Array.isArray(params.items)) error = { code: -32602, message: \"Invalid params\" };\n\t\t\t\telse result = params.items.map(() => null);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"workspace/workspaceFolders\":\n\t\t\tcase \"window/showMessageRequest\":\n\t\t\t\tresult = null;\n\t\t\t\tbreak;\n\t\t\tcase \"client/registerCapability\":\n\t\t\tcase \"client/unregisterCapability\":\n\t\t\tcase \"window/workDoneProgress/create\":\n\t\t\tcase \"workspace/semanticTokens/refresh\":\n\t\t\tcase \"workspace/inlayHint/refresh\":\n\t\t\tcase \"workspace/diagnostic/refresh\":\n\t\t\tcase \"workspace/codeLens/refresh\":\n\t\t\t\tresult = null;\n\t\t\t\tbreak;\n\t\t\tcase \"workspace/applyEdit\":\n\t\t\t\tresult = { applied: false, failureReason: \"Apex Code does not accept server-initiated workspace edits.\" };\n\t\t\t\tbreak;\n\t\t\tcase \"window/showDocument\":\n\t\t\t\tresult = { success: false };\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\terror = { code: -32601, message: \"Method not found\" };\n\t\t}\n\t\tawait this.enqueueWrite({\n\t\t\tjsonrpc: \"2.0\",\n\t\t\tid: message.id,\n\t\t\t...(error ? { error } : { result }),\n\t\t}).catch((writeError) => this.fail(normalizeError(writeError)));\n\t}\n\n\tprivate captureStderr(chunk: Buffer | string): void {\n\t\tconst bytes = typeof chunk === \"string\" ? Buffer.from(chunk) : chunk;\n\t\tthis.stderrTail = Buffer.concat([this.stderrTail, bytes]);\n\t\tif (this.stderrTail.length > LSP_MAX_STDERR_TAIL_BYTES) {\n\t\t\tthis.stderrTail = this.stderrTail.subarray(this.stderrTail.length - LSP_MAX_STDERR_TAIL_BYTES);\n\t\t}\n\t}\n\n\tprivate rejectPending(error: Error): void {\n\t\tfor (const request of this.pending.values()) request.reject(error);\n\t\tthis.pending.clear();\n\t}\n\n\tprivate fail(error: Error): void {\n\t\tif (this.state === \"closed\") return;\n\t\tconst firstFailure = this.failure === undefined;\n\t\tthis.failure ??= error;\n\t\tif (this.state !== \"closing\") this.state = \"failed\";\n\t\tthis.rejectPending(this.failure);\n\t\tif (firstFailure) for (const listener of this.failureListeners) listener(this.failure);\n\t}\n}\n"]}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/core/lsp/client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ChildProcess } from \"node:child_process\";\nimport type { Readable, Writable } from \"node:stream\";\nimport { pathToFileURL } from \"node:url\";\nimport { spawnProcess } from \"../../utils/child-process.ts\";\n\nexport const LSP_MAX_HEADER_BYTES = 8 * 1024;\nexport const LSP_MAX_MESSAGE_BYTES = 8 * 1024 * 1024;\nexport const LSP_MAX_STDERR_TAIL_BYTES = 64 * 1024;\n\nconst DEFAULT_INITIALIZATION_TIMEOUT_MS = 10_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nconst SHUTDOWN_TIMEOUT_MS = 2_000;\nconst TERMINATE_GRACE_MS = 500;\nconst KILL_GRACE_MS = 1_000;\n\nexport interface LspClientOptions {\n\treadonly command: string;\n\treadonly args?: readonly string[];\n\treadonly cwd: string;\n\treadonly env?: NodeJS.ProcessEnv;\n\treadonly initializationTimeoutMs?: number;\n\treadonly requestTimeoutMs?: number;\n}\n\nexport interface LspNotification {\n\treadonly method: string;\n\treadonly params?: unknown;\n}\n\nexport type LspTextDocumentSyncKind = \"none\" | \"full\" | \"incremental\";\n\nexport interface LspTextDocumentSync {\n\treadonly kind: LspTextDocumentSyncKind;\n\treadonly openClose: boolean;\n\treadonly save: boolean;\n\treadonly saveIncludeText: boolean;\n}\n\nexport class LspJsonRpcError extends Error {\n\treadonly code: number;\n\treadonly data?: unknown;\n\n\tconstructor(error: { code: number; message: string; data?: unknown }) {\n\t\tsuper(error.message);\n\t\tthis.name = \"LspJsonRpcError\";\n\t\tthis.code = error.code;\n\t\tthis.data = error.data;\n\t}\n}\n\ntype JsonRpcId = number;\ntype PendingRequest = {\n\tresolve(value: unknown): void;\n\treject(reason: Error): void;\n};\n\ntype ClientState = \"idle\" | \"starting\" | \"ready\" | \"closing\" | \"closed\" | \"failed\";\n\ntype JsonRpcMessage = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isJsonRpcId(value: unknown): value is string | number {\n\treturn typeof value === \"string\" || (typeof value === \"number\" && Number.isSafeInteger(value));\n}\n\nfunction normalizeError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction parseTextDocumentSync(value: unknown): LspTextDocumentSync {\n\tlet kind: LspTextDocumentSyncKind = \"none\";\n\tlet openClose = false;\n\tlet save = false;\n\tlet saveIncludeText = false;\n\tif (typeof value === \"number\") {\n\t\tkind = value === 1 ? \"full\" : value === 2 ? \"incremental\" : \"none\";\n\t} else if (isRecord(value)) {\n\t\topenClose = value.openClose === true;\n\t\tkind = value.change === 1 ? \"full\" : value.change === 2 ? \"incremental\" : \"none\";\n\t\tif (value.save === true) save = true;\n\t\telse if (isRecord(value.save)) {\n\t\t\tsave = true;\n\t\t\tsaveIncludeText = value.save.includeText === true;\n\t\t}\n\t}\n\treturn { kind, openClose, save, saveIncludeText };\n}\n\nfunction validateTimeout(value: number | undefined, fallback: number, label: string): number {\n\tconst timeout = value ?? fallback;\n\tif (!Number.isSafeInteger(timeout) || timeout < 1) throw new Error(`${label} must be a positive safe integer.`);\n\treturn timeout;\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** A bounded JSON-RPC 2.0 client for one language server's stdio. */\nexport class LspClient {\n\tprivate readonly options: LspClientOptions;\n\tprivate child: ChildProcess | undefined;\n\tprivate stdin: Writable | undefined;\n\tprivate stdout: Readable | undefined;\n\tprivate input = Buffer.alloc(0);\n\tprivate stderrTail = Buffer.alloc(0);\n\tprivate nextRequestId = 1;\n\tprivate readonly pending = new Map<JsonRpcId, PendingRequest>();\n\tprivate readonly notificationListeners = new Set<(notification: LspNotification) => void>();\n\tprivate readonly failureListeners = new Set<(error: Error) => void>();\n\tprivate startPromise: Promise<void> | undefined;\n\tprivate disposePromise: Promise<void> | undefined;\n\tprivate state: ClientState = \"idle\";\n\tprivate failure: Error | undefined;\n\tprivate writeChain: Promise<void> = Promise.resolve();\n\tprivate syncCapabilities: LspTextDocumentSync = {\n\t\tkind: \"none\",\n\t\topenClose: false,\n\t\tsave: false,\n\t\tsaveIncludeText: false,\n\t};\n\n\tconstructor(options: LspClientOptions) {\n\t\tthis.options = options;\n\t}\n\n\tget capturedStderr(): string {\n\t\treturn this.stderrTail.toString(\"utf8\");\n\t}\n\n\t/** Text-document synchronization negotiated during initialization. */\n\tget textDocumentSync(): LspTextDocumentSync {\n\t\treturn this.syncCapabilities;\n\t}\n\n\tonNotification(listener: (notification: LspNotification) => void): () => void {\n\t\tthis.notificationListeners.add(listener);\n\t\treturn () => this.notificationListeners.delete(listener);\n\t}\n\n\t/** Subscribe to the first terminal protocol or process failure. */\n\tonFailure(listener: (error: Error) => void): () => void {\n\t\tthis.failureListeners.add(listener);\n\t\tif (this.failure) listener(this.failure);\n\t\treturn () => this.failureListeners.delete(listener);\n\t}\n\n\tstart(): Promise<void> {\n\t\tif (this.failure) return Promise.reject(this.failure);\n\t\tif (this.state === \"closing\" || this.state === \"closed\") {\n\t\t\treturn Promise.reject(new Error(\"Language server client is disposed.\"));\n\t\t}\n\t\tif (!this.startPromise) {\n\t\t\tthis.state = \"starting\";\n\t\t\tthis.startPromise = this.initialize().catch(async (error) => {\n\t\t\t\tconst failure = normalizeError(error);\n\t\t\t\tthis.fail(failure);\n\t\t\t\tawait this.terminateChild();\n\t\t\t\tthrow failure;\n\t\t\t});\n\t\t}\n\t\treturn this.startPromise;\n\t}\n\n\tasync request(method: string, params?: unknown, signal?: AbortSignal): Promise<unknown> {\n\t\tawait this.start();\n\t\tif (this.state !== \"ready\") throw this.failure ?? new Error(\"Language server did not become ready.\");\n\t\treturn this.sendRequest(method, params, signal, this.requestTimeoutMs());\n\t}\n\n\tnotify(method: string, params?: unknown): void {\n\t\tif (this.failure) throw this.failure;\n\t\tconst exitFailure = this.childExitFailure();\n\t\tif (exitFailure) {\n\t\t\tthis.fail(exitFailure);\n\t\t\tthrow exitFailure;\n\t\t}\n\t\tif (this.state !== \"ready\") throw new Error(\"Language server is not ready.\");\n\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", method, ...(params === undefined ? {} : { params }) }).catch((error) => {\n\t\t\tthis.fail(normalizeError(error));\n\t\t});\n\t}\n\n\tdispose(): Promise<void> {\n\t\tif (!this.disposePromise) this.disposePromise = this.disposeProcess();\n\t\treturn this.disposePromise;\n\t}\n\n\tprivate initializationTimeoutMs(): number {\n\t\treturn validateTimeout(\n\t\t\tthis.options.initializationTimeoutMs,\n\t\t\tDEFAULT_INITIALIZATION_TIMEOUT_MS,\n\t\t\t\"initializationTimeoutMs\",\n\t\t);\n\t}\n\n\tprivate requestTimeoutMs(): number {\n\t\treturn validateTimeout(this.options.requestTimeoutMs, DEFAULT_REQUEST_TIMEOUT_MS, \"requestTimeoutMs\");\n\t}\n\n\tprivate async initialize(): Promise<void> {\n\t\tconst child = spawnProcess(this.options.command, [...(this.options.args ?? [])], {\n\t\t\tcwd: this.options.cwd,\n\t\t\tenv: this.options.env,\n\t\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t\t});\n\t\tif (!child.stdin || !child.stdout) {\n\t\t\tchild.kill();\n\t\t\tthrow new Error(\"Language server must expose piped stdin and stdout.\");\n\t\t}\n\t\tthis.child = child;\n\t\tthis.stdin = child.stdin;\n\t\tthis.stdout = child.stdout;\n\t\tthis.stdout.on(\"data\", (chunk: Buffer | string) => this.onData(chunk));\n\t\tchild.stderr?.on(\"data\", (chunk: Buffer | string) => this.captureStderr(chunk));\n\t\tchild.stdin.on(\"error\", (error) => {\n\t\t\tvoid this.writeFailure(error).then((failure) => this.fail(failure));\n\t\t});\n\t\tchild.once(\"error\", (error) => this.fail(error));\n\t\tchild.once(\"exit\", (code, signal) => {\n\t\t\tif (this.state !== \"closing\" && this.state !== \"closed\") {\n\t\t\t\tthis.fail(new Error(`Language server exited before shutdown (code=${code} signal=${signal}).`));\n\t\t\t}\n\t\t});\n\n\t\tconst initializeResult = await this.sendRequest(\n\t\t\t\"initialize\",\n\t\t\t{\n\t\t\t\tprocessId: process.pid,\n\t\t\t\tclientInfo: { name: \"Apex Code\" },\n\t\t\t\trootUri: pathToFileURL(this.options.cwd).href,\n\t\t\t\tcapabilities: {\n\t\t\t\t\tgeneral: { positionEncodings: [\"utf-16\"] },\n\t\t\t\t\tworkspace: { workspaceFolders: false },\n\t\t\t\t\ttextDocument: {\n\t\t\t\t\t\tdefinition: {},\n\t\t\t\t\t\treferences: {},\n\t\t\t\t\t\tdocumentSymbol: {},\n\t\t\t\t\t\tpublishDiagnostics: { versionSupport: true },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tworkspaceFolders: null,\n\t\t\t},\n\t\t\tundefined,\n\t\t\tthis.initializationTimeoutMs(),\n\t\t\t\"Language server initialize timed out\",\n\t\t);\n\t\tif (!isRecord(initializeResult) || !isRecord(initializeResult.capabilities)) {\n\t\t\tthrow new Error(\"Language server returned an invalid initialize result.\");\n\t\t}\n\t\tthis.syncCapabilities = parseTextDocumentSync(initializeResult.capabilities.textDocumentSync);\n\t\tif (this.state !== \"starting\") throw new Error(\"Language server initialization was interrupted.\");\n\t\tawait this.enqueueWrite({ jsonrpc: \"2.0\", method: \"initialized\", params: {} });\n\t\tthis.state = \"ready\";\n\t}\n\n\tprivate async disposeProcess(): Promise<void> {\n\t\tif (this.state === \"closed\") return;\n\t\tconst wasReady = this.state === \"ready\";\n\t\tthis.state = \"closing\";\n\t\tthis.rejectPending(new Error(\"Language server client is closing.\"));\n\n\t\tif (wasReady) {\n\t\t\ttry {\n\t\t\t\tawait this.sendRequest(\n\t\t\t\t\t\"shutdown\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tundefined,\n\t\t\t\t\tSHUTDOWN_TIMEOUT_MS,\n\t\t\t\t\t\"Language server shutdown timed out\",\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t\tawait this.enqueueWrite({ jsonrpc: \"2.0\", method: \"exit\" });\n\t\t\t} catch {\n\t\t\t\t// Bounded termination below is the fallback for an uncooperative server.\n\t\t\t}\n\t\t}\n\t\tawait this.terminateChild();\n\t\tthis.stdin?.end();\n\t\tthis.state = \"closed\";\n\t}\n\n\tprivate async terminateChild(): Promise<void> {\n\t\tconst child = this.child;\n\t\tif (!child || child.exitCode !== null || child.signalCode !== null) return;\n\t\tconst exited = new Promise<void>((resolve) => child.once(\"exit\", () => resolve()));\n\t\tconst graceful = await Promise.race([exited.then(() => true), delay(TERMINATE_GRACE_MS).then(() => false)]);\n\t\tif (graceful) return;\n\t\tchild.kill(\"SIGTERM\");\n\t\tconst terminated = await Promise.race([exited.then(() => true), delay(KILL_GRACE_MS).then(() => false)]);\n\t\tif (terminated) return;\n\t\tchild.kill(\"SIGKILL\");\n\t\tawait exited;\n\t}\n\n\tprivate sendRequest(\n\t\tmethod: string,\n\t\tparams?: unknown,\n\t\tsignal?: AbortSignal,\n\t\ttimeoutMs?: number,\n\t\ttimeoutMessage = `Language server request ${method} timed out`,\n\t\tallowClosing = false,\n\t): Promise<unknown> {\n\t\tif (this.failure && !allowClosing) return Promise.reject(this.failure);\n\t\tconst exitFailure = this.childExitFailure();\n\t\tif (exitFailure && !allowClosing) {\n\t\t\tthis.fail(exitFailure);\n\t\t\treturn Promise.reject(exitFailure);\n\t\t}\n\t\tif ((!allowClosing && (this.state === \"closing\" || this.state === \"closed\")) || this.state === \"failed\") {\n\t\t\treturn Promise.reject(this.failure ?? new Error(\"Language server client is disposed.\"));\n\t\t}\n\t\tconst id = this.nextRequestId++;\n\t\tif (!Number.isSafeInteger(id)) return Promise.reject(new Error(\"Language server request id space exhausted.\"));\n\t\tif (signal?.aborted)\n\t\t\treturn Promise.reject(normalizeError(signal.reason ?? new Error(\"Language server request aborted.\")));\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet timer: NodeJS.Timeout | undefined;\n\t\t\tconst settle = (fn: () => void) => {\n\t\t\t\tif (timer) clearTimeout(timer);\n\t\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\t\tfn();\n\t\t\t};\n\t\t\tconst abort = () => {\n\t\t\t\tif (!this.pending.delete(id)) return;\n\t\t\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", method: \"$/cancelRequest\", params: { id } }).catch(() => {});\n\t\t\t\tsettle(() => reject(normalizeError(signal?.reason ?? new Error(\"Language server request aborted.\"))));\n\t\t\t};\n\t\t\tthis.pending.set(id, {\n\t\t\t\tresolve: (value) => settle(() => resolve(value)),\n\t\t\t\treject: (error) => settle(() => reject(error)),\n\t\t\t});\n\t\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\tif (timeoutMs !== undefined) {\n\t\t\t\ttimer = setTimeout(() => {\n\t\t\t\t\tif (!this.pending.delete(id)) return;\n\t\t\t\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", method: \"$/cancelRequest\", params: { id } }).catch(() => {});\n\t\t\t\t\tsettle(() => reject(new Error(`${timeoutMessage} after ${timeoutMs}ms.`)));\n\t\t\t\t}, timeoutMs);\n\t\t\t}\n\t\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", id, method, ...(params === undefined ? {} : { params }) }).catch(\n\t\t\t\t(error) => {\n\t\t\t\t\tconst pending = this.pending.get(id);\n\t\t\t\t\tif (!pending) return;\n\t\t\t\t\tthis.pending.delete(id);\n\t\t\t\t\tpending.reject(normalizeError(error));\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate enqueueWrite(message: object): Promise<void> {\n\t\tconst body = Buffer.from(JSON.stringify(message), \"utf8\");\n\t\tif (body.length > LSP_MAX_MESSAGE_BYTES)\n\t\t\treturn Promise.reject(new Error(\"Language server message exceeds 8 MiB.\"));\n\t\tconst frame = Buffer.concat([Buffer.from(`Content-Length: ${body.length}\\r\\n\\r\\n`, \"ascii\"), body]);\n\t\tconst writing = this.writeChain.then(() => this.writeFrame(frame));\n\t\tthis.writeChain = writing.catch(() => {});\n\t\treturn writing;\n\t}\n\n\tprivate writeFrame(frame: Buffer): Promise<void> {\n\t\tconst stream = this.stdin;\n\t\tif (!stream || stream.destroyed || !stream.writable) {\n\t\t\treturn Promise.reject(new Error(\"Language server stdin is not writable.\"));\n\t\t}\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet waitingForDrain = false;\n\t\t\tconst cleanup = () => {\n\t\t\t\tstream.removeListener(\"error\", onError);\n\t\t\t\tstream.removeListener(\"drain\", onDrain);\n\t\t\t};\n\t\t\tconst onError = (error: Error) => {\n\t\t\t\tcleanup();\n\t\t\t\tvoid this.writeFailure(error).then(reject);\n\t\t\t};\n\t\t\tconst onDrain = () => {\n\t\t\t\twaitingForDrain = false;\n\t\t\t\tcleanup();\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tstream.once(\"error\", onError);\n\t\t\tconst accepted = stream.write(frame, (error) => {\n\t\t\t\tif (error) onError(error);\n\t\t\t\telse if (!waitingForDrain) {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (!accepted) {\n\t\t\t\twaitingForDrain = true;\n\t\t\t\tstream.once(\"drain\", onDrain);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate onData(chunk: Buffer | string): void {\n\t\tif (this.failure) return;\n\t\tthis.input = Buffer.concat([this.input, typeof chunk === \"string\" ? Buffer.from(chunk) : chunk]);\n\t\twhile (true) {\n\t\t\tconst headerEnd = this.input.indexOf(\"\\r\\n\\r\\n\");\n\t\t\tif (headerEnd < 0) {\n\t\t\t\tif (this.input.length > LSP_MAX_HEADER_BYTES) this.fail(new Error(\"Language server header exceeds 8 KiB.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (headerEnd > LSP_MAX_HEADER_BYTES) {\n\t\t\t\tthis.fail(new Error(\"Language server header exceeds 8 KiB.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst header = this.input.subarray(0, headerEnd).toString(\"ascii\");\n\t\t\tconst lengths = [...header.matchAll(/(?:^|\\r\\n)Content-Length:\\s*(\\d+)(?=\\r\\n|$)/gi)];\n\t\t\tif (lengths.length !== 1) {\n\t\t\t\tthis.fail(new Error(\"Language server frame must contain exactly one Content-Length header.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst contentLength = Number(lengths[0][1]);\n\t\t\tif (!Number.isSafeInteger(contentLength) || contentLength > LSP_MAX_MESSAGE_BYTES) {\n\t\t\t\tthis.fail(new Error(\"Language server message exceeds 8 MiB.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst bodyStart = headerEnd + 4;\n\t\t\tif (this.input.length < bodyStart + contentLength) return;\n\t\t\tconst body = this.input.subarray(bodyStart, bodyStart + contentLength).toString(\"utf8\");\n\t\t\tthis.input = this.input.subarray(bodyStart + contentLength);\n\t\t\ttry {\n\t\t\t\tconst parsed: unknown = JSON.parse(body);\n\t\t\t\tif (!isRecord(parsed)) throw new Error(\"Language server JSON-RPC message must be an object.\");\n\t\t\t\tthis.onMessage(parsed);\n\t\t\t} catch (error) {\n\t\t\t\tthis.fail(normalizeError(error));\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onMessage(message: JsonRpcMessage): void {\n\t\tif (message.jsonrpc !== \"2.0\") {\n\t\t\tthis.fail(new Error('Language server message must declare jsonrpc \"2.0\".'));\n\t\t\treturn;\n\t\t}\n\t\tif (typeof message.method === \"string\") {\n\t\t\tif (message.id !== undefined && message.id !== null) {\n\t\t\t\tvoid this.handleServerRequest(message);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst notification: LspNotification = {\n\t\t\t\tmethod: message.method,\n\t\t\t\t...(message.params === undefined ? {} : { params: message.params }),\n\t\t\t};\n\t\t\tfor (const listener of this.notificationListeners) listener(notification);\n\t\t\treturn;\n\t\t}\n\t\tif (typeof message.id !== \"number\" || !Number.isSafeInteger(message.id)) return;\n\t\tconst pending = this.pending.get(message.id);\n\t\tif (!pending) return;\n\t\tconst hasResult = Object.hasOwn(message, \"result\");\n\t\tconst hasError = Object.hasOwn(message, \"error\");\n\t\tif (hasResult === hasError) {\n\t\t\tthis.fail(new Error(\"Language server response must contain exactly one of result or error.\"));\n\t\t\treturn;\n\t\t}\n\t\tthis.pending.delete(message.id);\n\t\tif (hasError) {\n\t\t\tconst error = message.error;\n\t\t\tif (!isRecord(error) || !Number.isSafeInteger(error.code) || typeof error.message !== \"string\") {\n\t\t\t\tthis.fail(new Error(\"Language server returned an invalid JSON-RPC error.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpending.reject(new LspJsonRpcError({ code: error.code as number, message: error.message, data: error.data }));\n\t\t\treturn;\n\t\t}\n\t\tpending.resolve(message.result);\n\t}\n\n\tprivate async handleServerRequest(message: JsonRpcMessage): Promise<void> {\n\t\tif (!isJsonRpcId(message.id) || typeof message.method !== \"string\") return;\n\t\tlet result: unknown;\n\t\tlet error: { code: number; message: string } | undefined;\n\t\tswitch (message.method) {\n\t\t\tcase \"workspace/configuration\": {\n\t\t\t\tconst params = message.params;\n\t\t\t\tif (!isRecord(params) || !Array.isArray(params.items)) error = { code: -32602, message: \"Invalid params\" };\n\t\t\t\telse result = params.items.map(() => null);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"workspace/workspaceFolders\":\n\t\t\tcase \"window/showMessageRequest\":\n\t\t\t\tresult = null;\n\t\t\t\tbreak;\n\t\t\tcase \"client/registerCapability\":\n\t\t\tcase \"client/unregisterCapability\":\n\t\t\tcase \"window/workDoneProgress/create\":\n\t\t\tcase \"workspace/semanticTokens/refresh\":\n\t\t\tcase \"workspace/inlayHint/refresh\":\n\t\t\tcase \"workspace/diagnostic/refresh\":\n\t\t\tcase \"workspace/codeLens/refresh\":\n\t\t\t\tresult = null;\n\t\t\t\tbreak;\n\t\t\tcase \"workspace/applyEdit\":\n\t\t\t\tresult = { applied: false, failureReason: \"Apex Code does not accept server-initiated workspace edits.\" };\n\t\t\t\tbreak;\n\t\t\tcase \"window/showDocument\":\n\t\t\t\tresult = { success: false };\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\terror = { code: -32601, message: \"Method not found\" };\n\t\t}\n\t\tawait this.enqueueWrite({\n\t\t\tjsonrpc: \"2.0\",\n\t\t\tid: message.id,\n\t\t\t...(error ? { error } : { result }),\n\t\t}).catch((writeError) => this.fail(normalizeError(writeError)));\n\t}\n\n\tprivate captureStderr(chunk: Buffer | string): void {\n\t\tconst bytes = typeof chunk === \"string\" ? Buffer.from(chunk) : chunk;\n\t\tthis.stderrTail = Buffer.concat([this.stderrTail, bytes]);\n\t\tif (this.stderrTail.length > LSP_MAX_STDERR_TAIL_BYTES) {\n\t\t\tthis.stderrTail = this.stderrTail.subarray(this.stderrTail.length - LSP_MAX_STDERR_TAIL_BYTES);\n\t\t}\n\t}\n\n\tprivate rejectPending(error: Error): void {\n\t\tfor (const request of this.pending.values()) request.reject(error);\n\t\tthis.pending.clear();\n\t}\n\n\tprivate childExitFailure(): Error | undefined {\n\t\tconst child = this.child;\n\t\tif (!child || (child.exitCode === null && child.signalCode === null)) return undefined;\n\t\treturn new Error(`Language server exited before shutdown (code=${child.exitCode} signal=${child.signalCode}).`);\n\t}\n\n\tprivate async writeFailure(error: Error): Promise<Error> {\n\t\tconst exitFailure = this.childExitFailure();\n\t\tif (exitFailure || (error as NodeJS.ErrnoException).code !== \"EPIPE\" || !this.child) return exitFailure ?? error;\n\t\tawait Promise.race([new Promise<void>((resolve) => this.child?.once(\"exit\", () => resolve())), delay(1_000)]);\n\t\treturn this.childExitFailure() ?? error;\n\t}\n\n\tprivate fail(error: Error): void {\n\t\tif (this.state === \"closed\") return;\n\t\tconst firstFailure = this.failure === undefined;\n\t\tthis.failure ??= error;\n\t\tif (this.state !== \"closing\") this.state = \"failed\";\n\t\tthis.rejectPending(this.failure);\n\t\tif (firstFailure) for (const listener of this.failureListeners) listener(this.failure);\n\t}\n}\n"]}
@@ -126,6 +126,11 @@ export class LspClient {
126
126
  notify(method, params) {
127
127
  if (this.failure)
128
128
  throw this.failure;
129
+ const exitFailure = this.childExitFailure();
130
+ if (exitFailure) {
131
+ this.fail(exitFailure);
132
+ throw exitFailure;
133
+ }
129
134
  if (this.state !== "ready")
130
135
  throw new Error("Language server is not ready.");
131
136
  void this.enqueueWrite({ jsonrpc: "2.0", method, ...(params === undefined ? {} : { params }) }).catch((error) => {
@@ -158,7 +163,9 @@ export class LspClient {
158
163
  this.stdout = child.stdout;
159
164
  this.stdout.on("data", (chunk) => this.onData(chunk));
160
165
  child.stderr?.on("data", (chunk) => this.captureStderr(chunk));
161
- child.stdin.on("error", (error) => this.fail(error));
166
+ child.stdin.on("error", (error) => {
167
+ void this.writeFailure(error).then((failure) => this.fail(failure));
168
+ });
162
169
  child.once("error", (error) => this.fail(error));
163
170
  child.once("exit", (code, signal) => {
164
171
  if (this.state !== "closing" && this.state !== "closed") {
@@ -227,6 +234,11 @@ export class LspClient {
227
234
  sendRequest(method, params, signal, timeoutMs, timeoutMessage = `Language server request ${method} timed out`, allowClosing = false) {
228
235
  if (this.failure && !allowClosing)
229
236
  return Promise.reject(this.failure);
237
+ const exitFailure = this.childExitFailure();
238
+ if (exitFailure && !allowClosing) {
239
+ this.fail(exitFailure);
240
+ return Promise.reject(exitFailure);
241
+ }
230
242
  if ((!allowClosing && (this.state === "closing" || this.state === "closed")) || this.state === "failed") {
231
243
  return Promise.reject(this.failure ?? new Error("Language server client is disposed."));
232
244
  }
@@ -293,7 +305,7 @@ export class LspClient {
293
305
  };
294
306
  const onError = (error) => {
295
307
  cleanup();
296
- reject(error);
308
+ void this.writeFailure(error).then(reject);
297
309
  };
298
310
  const onDrain = () => {
299
311
  waitingForDrain = false;
@@ -453,6 +465,19 @@ export class LspClient {
453
465
  request.reject(error);
454
466
  this.pending.clear();
455
467
  }
468
+ childExitFailure() {
469
+ const child = this.child;
470
+ if (!child || (child.exitCode === null && child.signalCode === null))
471
+ return undefined;
472
+ return new Error(`Language server exited before shutdown (code=${child.exitCode} signal=${child.signalCode}).`);
473
+ }
474
+ async writeFailure(error) {
475
+ const exitFailure = this.childExitFailure();
476
+ if (exitFailure || error.code !== "EPIPE" || !this.child)
477
+ return exitFailure ?? error;
478
+ await Promise.race([new Promise((resolve) => this.child?.once("exit", () => resolve())), delay(1_000)]);
479
+ return this.childExitFailure() ?? error;
480
+ }
456
481
  fail(error) {
457
482
  if (this.state === "closed")
458
483
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/core/lsp/client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ChildProcess } from \"node:child_process\";\nimport type { Readable, Writable } from \"node:stream\";\nimport { pathToFileURL } from \"node:url\";\nimport { spawnProcess } from \"../../utils/child-process.ts\";\n\nexport const LSP_MAX_HEADER_BYTES = 8 * 1024;\nexport const LSP_MAX_MESSAGE_BYTES = 8 * 1024 * 1024;\nexport const LSP_MAX_STDERR_TAIL_BYTES = 64 * 1024;\n\nconst DEFAULT_INITIALIZATION_TIMEOUT_MS = 10_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nconst SHUTDOWN_TIMEOUT_MS = 2_000;\nconst TERMINATE_GRACE_MS = 500;\nconst KILL_GRACE_MS = 1_000;\n\nexport interface LspClientOptions {\n\treadonly command: string;\n\treadonly args?: readonly string[];\n\treadonly cwd: string;\n\treadonly env?: NodeJS.ProcessEnv;\n\treadonly initializationTimeoutMs?: number;\n\treadonly requestTimeoutMs?: number;\n}\n\nexport interface LspNotification {\n\treadonly method: string;\n\treadonly params?: unknown;\n}\n\nexport type LspTextDocumentSyncKind = \"none\" | \"full\" | \"incremental\";\n\nexport interface LspTextDocumentSync {\n\treadonly kind: LspTextDocumentSyncKind;\n\treadonly openClose: boolean;\n\treadonly save: boolean;\n\treadonly saveIncludeText: boolean;\n}\n\nexport class LspJsonRpcError extends Error {\n\treadonly code: number;\n\treadonly data?: unknown;\n\n\tconstructor(error: { code: number; message: string; data?: unknown }) {\n\t\tsuper(error.message);\n\t\tthis.name = \"LspJsonRpcError\";\n\t\tthis.code = error.code;\n\t\tthis.data = error.data;\n\t}\n}\n\ntype JsonRpcId = number;\ntype PendingRequest = {\n\tresolve(value: unknown): void;\n\treject(reason: Error): void;\n};\n\ntype ClientState = \"idle\" | \"starting\" | \"ready\" | \"closing\" | \"closed\" | \"failed\";\n\ntype JsonRpcMessage = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isJsonRpcId(value: unknown): value is string | number {\n\treturn typeof value === \"string\" || (typeof value === \"number\" && Number.isSafeInteger(value));\n}\n\nfunction normalizeError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction parseTextDocumentSync(value: unknown): LspTextDocumentSync {\n\tlet kind: LspTextDocumentSyncKind = \"none\";\n\tlet openClose = false;\n\tlet save = false;\n\tlet saveIncludeText = false;\n\tif (typeof value === \"number\") {\n\t\tkind = value === 1 ? \"full\" : value === 2 ? \"incremental\" : \"none\";\n\t} else if (isRecord(value)) {\n\t\topenClose = value.openClose === true;\n\t\tkind = value.change === 1 ? \"full\" : value.change === 2 ? \"incremental\" : \"none\";\n\t\tif (value.save === true) save = true;\n\t\telse if (isRecord(value.save)) {\n\t\t\tsave = true;\n\t\t\tsaveIncludeText = value.save.includeText === true;\n\t\t}\n\t}\n\treturn { kind, openClose, save, saveIncludeText };\n}\n\nfunction validateTimeout(value: number | undefined, fallback: number, label: string): number {\n\tconst timeout = value ?? fallback;\n\tif (!Number.isSafeInteger(timeout) || timeout < 1) throw new Error(`${label} must be a positive safe integer.`);\n\treturn timeout;\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** A bounded JSON-RPC 2.0 client for one language server's stdio. */\nexport class LspClient {\n\tprivate readonly options: LspClientOptions;\n\tprivate child: ChildProcess | undefined;\n\tprivate stdin: Writable | undefined;\n\tprivate stdout: Readable | undefined;\n\tprivate input = Buffer.alloc(0);\n\tprivate stderrTail = Buffer.alloc(0);\n\tprivate nextRequestId = 1;\n\tprivate readonly pending = new Map<JsonRpcId, PendingRequest>();\n\tprivate readonly notificationListeners = new Set<(notification: LspNotification) => void>();\n\tprivate readonly failureListeners = new Set<(error: Error) => void>();\n\tprivate startPromise: Promise<void> | undefined;\n\tprivate disposePromise: Promise<void> | undefined;\n\tprivate state: ClientState = \"idle\";\n\tprivate failure: Error | undefined;\n\tprivate writeChain: Promise<void> = Promise.resolve();\n\tprivate syncCapabilities: LspTextDocumentSync = {\n\t\tkind: \"none\",\n\t\topenClose: false,\n\t\tsave: false,\n\t\tsaveIncludeText: false,\n\t};\n\n\tconstructor(options: LspClientOptions) {\n\t\tthis.options = options;\n\t}\n\n\tget capturedStderr(): string {\n\t\treturn this.stderrTail.toString(\"utf8\");\n\t}\n\n\t/** Text-document synchronization negotiated during initialization. */\n\tget textDocumentSync(): LspTextDocumentSync {\n\t\treturn this.syncCapabilities;\n\t}\n\n\tonNotification(listener: (notification: LspNotification) => void): () => void {\n\t\tthis.notificationListeners.add(listener);\n\t\treturn () => this.notificationListeners.delete(listener);\n\t}\n\n\t/** Subscribe to the first terminal protocol or process failure. */\n\tonFailure(listener: (error: Error) => void): () => void {\n\t\tthis.failureListeners.add(listener);\n\t\tif (this.failure) listener(this.failure);\n\t\treturn () => this.failureListeners.delete(listener);\n\t}\n\n\tstart(): Promise<void> {\n\t\tif (this.failure) return Promise.reject(this.failure);\n\t\tif (this.state === \"closing\" || this.state === \"closed\") {\n\t\t\treturn Promise.reject(new Error(\"Language server client is disposed.\"));\n\t\t}\n\t\tif (!this.startPromise) {\n\t\t\tthis.state = \"starting\";\n\t\t\tthis.startPromise = this.initialize().catch(async (error) => {\n\t\t\t\tconst failure = normalizeError(error);\n\t\t\t\tthis.fail(failure);\n\t\t\t\tawait this.terminateChild();\n\t\t\t\tthrow failure;\n\t\t\t});\n\t\t}\n\t\treturn this.startPromise;\n\t}\n\n\tasync request(method: string, params?: unknown, signal?: AbortSignal): Promise<unknown> {\n\t\tawait this.start();\n\t\tif (this.state !== \"ready\") throw this.failure ?? new Error(\"Language server did not become ready.\");\n\t\treturn this.sendRequest(method, params, signal, this.requestTimeoutMs());\n\t}\n\n\tnotify(method: string, params?: unknown): void {\n\t\tif (this.failure) throw this.failure;\n\t\tif (this.state !== \"ready\") throw new Error(\"Language server is not ready.\");\n\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", method, ...(params === undefined ? {} : { params }) }).catch((error) => {\n\t\t\tthis.fail(normalizeError(error));\n\t\t});\n\t}\n\n\tdispose(): Promise<void> {\n\t\tif (!this.disposePromise) this.disposePromise = this.disposeProcess();\n\t\treturn this.disposePromise;\n\t}\n\n\tprivate initializationTimeoutMs(): number {\n\t\treturn validateTimeout(\n\t\t\tthis.options.initializationTimeoutMs,\n\t\t\tDEFAULT_INITIALIZATION_TIMEOUT_MS,\n\t\t\t\"initializationTimeoutMs\",\n\t\t);\n\t}\n\n\tprivate requestTimeoutMs(): number {\n\t\treturn validateTimeout(this.options.requestTimeoutMs, DEFAULT_REQUEST_TIMEOUT_MS, \"requestTimeoutMs\");\n\t}\n\n\tprivate async initialize(): Promise<void> {\n\t\tconst child = spawnProcess(this.options.command, [...(this.options.args ?? [])], {\n\t\t\tcwd: this.options.cwd,\n\t\t\tenv: this.options.env,\n\t\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t\t});\n\t\tif (!child.stdin || !child.stdout) {\n\t\t\tchild.kill();\n\t\t\tthrow new Error(\"Language server must expose piped stdin and stdout.\");\n\t\t}\n\t\tthis.child = child;\n\t\tthis.stdin = child.stdin;\n\t\tthis.stdout = child.stdout;\n\t\tthis.stdout.on(\"data\", (chunk: Buffer | string) => this.onData(chunk));\n\t\tchild.stderr?.on(\"data\", (chunk: Buffer | string) => this.captureStderr(chunk));\n\t\tchild.stdin.on(\"error\", (error) => this.fail(error));\n\t\tchild.once(\"error\", (error) => this.fail(error));\n\t\tchild.once(\"exit\", (code, signal) => {\n\t\t\tif (this.state !== \"closing\" && this.state !== \"closed\") {\n\t\t\t\tthis.fail(new Error(`Language server exited before shutdown (code=${code} signal=${signal}).`));\n\t\t\t}\n\t\t});\n\n\t\tconst initializeResult = await this.sendRequest(\n\t\t\t\"initialize\",\n\t\t\t{\n\t\t\t\tprocessId: process.pid,\n\t\t\t\tclientInfo: { name: \"Apex Code\" },\n\t\t\t\trootUri: pathToFileURL(this.options.cwd).href,\n\t\t\t\tcapabilities: {\n\t\t\t\t\tgeneral: { positionEncodings: [\"utf-16\"] },\n\t\t\t\t\tworkspace: { workspaceFolders: false },\n\t\t\t\t\ttextDocument: {\n\t\t\t\t\t\tdefinition: {},\n\t\t\t\t\t\treferences: {},\n\t\t\t\t\t\tdocumentSymbol: {},\n\t\t\t\t\t\tpublishDiagnostics: { versionSupport: true },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tworkspaceFolders: null,\n\t\t\t},\n\t\t\tundefined,\n\t\t\tthis.initializationTimeoutMs(),\n\t\t\t\"Language server initialize timed out\",\n\t\t);\n\t\tif (!isRecord(initializeResult) || !isRecord(initializeResult.capabilities)) {\n\t\t\tthrow new Error(\"Language server returned an invalid initialize result.\");\n\t\t}\n\t\tthis.syncCapabilities = parseTextDocumentSync(initializeResult.capabilities.textDocumentSync);\n\t\tif (this.state !== \"starting\") throw new Error(\"Language server initialization was interrupted.\");\n\t\tawait this.enqueueWrite({ jsonrpc: \"2.0\", method: \"initialized\", params: {} });\n\t\tthis.state = \"ready\";\n\t}\n\n\tprivate async disposeProcess(): Promise<void> {\n\t\tif (this.state === \"closed\") return;\n\t\tconst wasReady = this.state === \"ready\";\n\t\tthis.state = \"closing\";\n\t\tthis.rejectPending(new Error(\"Language server client is closing.\"));\n\n\t\tif (wasReady) {\n\t\t\ttry {\n\t\t\t\tawait this.sendRequest(\n\t\t\t\t\t\"shutdown\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tundefined,\n\t\t\t\t\tSHUTDOWN_TIMEOUT_MS,\n\t\t\t\t\t\"Language server shutdown timed out\",\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t\tawait this.enqueueWrite({ jsonrpc: \"2.0\", method: \"exit\" });\n\t\t\t} catch {\n\t\t\t\t// Bounded termination below is the fallback for an uncooperative server.\n\t\t\t}\n\t\t}\n\t\tawait this.terminateChild();\n\t\tthis.stdin?.end();\n\t\tthis.state = \"closed\";\n\t}\n\n\tprivate async terminateChild(): Promise<void> {\n\t\tconst child = this.child;\n\t\tif (!child || child.exitCode !== null || child.signalCode !== null) return;\n\t\tconst exited = new Promise<void>((resolve) => child.once(\"exit\", () => resolve()));\n\t\tconst graceful = await Promise.race([exited.then(() => true), delay(TERMINATE_GRACE_MS).then(() => false)]);\n\t\tif (graceful) return;\n\t\tchild.kill(\"SIGTERM\");\n\t\tconst terminated = await Promise.race([exited.then(() => true), delay(KILL_GRACE_MS).then(() => false)]);\n\t\tif (terminated) return;\n\t\tchild.kill(\"SIGKILL\");\n\t\tawait exited;\n\t}\n\n\tprivate sendRequest(\n\t\tmethod: string,\n\t\tparams?: unknown,\n\t\tsignal?: AbortSignal,\n\t\ttimeoutMs?: number,\n\t\ttimeoutMessage = `Language server request ${method} timed out`,\n\t\tallowClosing = false,\n\t): Promise<unknown> {\n\t\tif (this.failure && !allowClosing) return Promise.reject(this.failure);\n\t\tif ((!allowClosing && (this.state === \"closing\" || this.state === \"closed\")) || this.state === \"failed\") {\n\t\t\treturn Promise.reject(this.failure ?? new Error(\"Language server client is disposed.\"));\n\t\t}\n\t\tconst id = this.nextRequestId++;\n\t\tif (!Number.isSafeInteger(id)) return Promise.reject(new Error(\"Language server request id space exhausted.\"));\n\t\tif (signal?.aborted)\n\t\t\treturn Promise.reject(normalizeError(signal.reason ?? new Error(\"Language server request aborted.\")));\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet timer: NodeJS.Timeout | undefined;\n\t\t\tconst settle = (fn: () => void) => {\n\t\t\t\tif (timer) clearTimeout(timer);\n\t\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\t\tfn();\n\t\t\t};\n\t\t\tconst abort = () => {\n\t\t\t\tif (!this.pending.delete(id)) return;\n\t\t\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", method: \"$/cancelRequest\", params: { id } }).catch(() => {});\n\t\t\t\tsettle(() => reject(normalizeError(signal?.reason ?? new Error(\"Language server request aborted.\"))));\n\t\t\t};\n\t\t\tthis.pending.set(id, {\n\t\t\t\tresolve: (value) => settle(() => resolve(value)),\n\t\t\t\treject: (error) => settle(() => reject(error)),\n\t\t\t});\n\t\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\tif (timeoutMs !== undefined) {\n\t\t\t\ttimer = setTimeout(() => {\n\t\t\t\t\tif (!this.pending.delete(id)) return;\n\t\t\t\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", method: \"$/cancelRequest\", params: { id } }).catch(() => {});\n\t\t\t\t\tsettle(() => reject(new Error(`${timeoutMessage} after ${timeoutMs}ms.`)));\n\t\t\t\t}, timeoutMs);\n\t\t\t}\n\t\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", id, method, ...(params === undefined ? {} : { params }) }).catch(\n\t\t\t\t(error) => {\n\t\t\t\t\tconst pending = this.pending.get(id);\n\t\t\t\t\tif (!pending) return;\n\t\t\t\t\tthis.pending.delete(id);\n\t\t\t\t\tpending.reject(normalizeError(error));\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate enqueueWrite(message: object): Promise<void> {\n\t\tconst body = Buffer.from(JSON.stringify(message), \"utf8\");\n\t\tif (body.length > LSP_MAX_MESSAGE_BYTES)\n\t\t\treturn Promise.reject(new Error(\"Language server message exceeds 8 MiB.\"));\n\t\tconst frame = Buffer.concat([Buffer.from(`Content-Length: ${body.length}\\r\\n\\r\\n`, \"ascii\"), body]);\n\t\tconst writing = this.writeChain.then(() => this.writeFrame(frame));\n\t\tthis.writeChain = writing.catch(() => {});\n\t\treturn writing;\n\t}\n\n\tprivate writeFrame(frame: Buffer): Promise<void> {\n\t\tconst stream = this.stdin;\n\t\tif (!stream || stream.destroyed || !stream.writable) {\n\t\t\treturn Promise.reject(new Error(\"Language server stdin is not writable.\"));\n\t\t}\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet waitingForDrain = false;\n\t\t\tconst cleanup = () => {\n\t\t\t\tstream.removeListener(\"error\", onError);\n\t\t\t\tstream.removeListener(\"drain\", onDrain);\n\t\t\t};\n\t\t\tconst onError = (error: Error) => {\n\t\t\t\tcleanup();\n\t\t\t\treject(error);\n\t\t\t};\n\t\t\tconst onDrain = () => {\n\t\t\t\twaitingForDrain = false;\n\t\t\t\tcleanup();\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tstream.once(\"error\", onError);\n\t\t\tconst accepted = stream.write(frame, (error) => {\n\t\t\t\tif (error) onError(error);\n\t\t\t\telse if (!waitingForDrain) {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (!accepted) {\n\t\t\t\twaitingForDrain = true;\n\t\t\t\tstream.once(\"drain\", onDrain);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate onData(chunk: Buffer | string): void {\n\t\tif (this.failure) return;\n\t\tthis.input = Buffer.concat([this.input, typeof chunk === \"string\" ? Buffer.from(chunk) : chunk]);\n\t\twhile (true) {\n\t\t\tconst headerEnd = this.input.indexOf(\"\\r\\n\\r\\n\");\n\t\t\tif (headerEnd < 0) {\n\t\t\t\tif (this.input.length > LSP_MAX_HEADER_BYTES) this.fail(new Error(\"Language server header exceeds 8 KiB.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (headerEnd > LSP_MAX_HEADER_BYTES) {\n\t\t\t\tthis.fail(new Error(\"Language server header exceeds 8 KiB.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst header = this.input.subarray(0, headerEnd).toString(\"ascii\");\n\t\t\tconst lengths = [...header.matchAll(/(?:^|\\r\\n)Content-Length:\\s*(\\d+)(?=\\r\\n|$)/gi)];\n\t\t\tif (lengths.length !== 1) {\n\t\t\t\tthis.fail(new Error(\"Language server frame must contain exactly one Content-Length header.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst contentLength = Number(lengths[0][1]);\n\t\t\tif (!Number.isSafeInteger(contentLength) || contentLength > LSP_MAX_MESSAGE_BYTES) {\n\t\t\t\tthis.fail(new Error(\"Language server message exceeds 8 MiB.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst bodyStart = headerEnd + 4;\n\t\t\tif (this.input.length < bodyStart + contentLength) return;\n\t\t\tconst body = this.input.subarray(bodyStart, bodyStart + contentLength).toString(\"utf8\");\n\t\t\tthis.input = this.input.subarray(bodyStart + contentLength);\n\t\t\ttry {\n\t\t\t\tconst parsed: unknown = JSON.parse(body);\n\t\t\t\tif (!isRecord(parsed)) throw new Error(\"Language server JSON-RPC message must be an object.\");\n\t\t\t\tthis.onMessage(parsed);\n\t\t\t} catch (error) {\n\t\t\t\tthis.fail(normalizeError(error));\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onMessage(message: JsonRpcMessage): void {\n\t\tif (message.jsonrpc !== \"2.0\") {\n\t\t\tthis.fail(new Error('Language server message must declare jsonrpc \"2.0\".'));\n\t\t\treturn;\n\t\t}\n\t\tif (typeof message.method === \"string\") {\n\t\t\tif (message.id !== undefined && message.id !== null) {\n\t\t\t\tvoid this.handleServerRequest(message);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst notification: LspNotification = {\n\t\t\t\tmethod: message.method,\n\t\t\t\t...(message.params === undefined ? {} : { params: message.params }),\n\t\t\t};\n\t\t\tfor (const listener of this.notificationListeners) listener(notification);\n\t\t\treturn;\n\t\t}\n\t\tif (typeof message.id !== \"number\" || !Number.isSafeInteger(message.id)) return;\n\t\tconst pending = this.pending.get(message.id);\n\t\tif (!pending) return;\n\t\tconst hasResult = Object.hasOwn(message, \"result\");\n\t\tconst hasError = Object.hasOwn(message, \"error\");\n\t\tif (hasResult === hasError) {\n\t\t\tthis.fail(new Error(\"Language server response must contain exactly one of result or error.\"));\n\t\t\treturn;\n\t\t}\n\t\tthis.pending.delete(message.id);\n\t\tif (hasError) {\n\t\t\tconst error = message.error;\n\t\t\tif (!isRecord(error) || !Number.isSafeInteger(error.code) || typeof error.message !== \"string\") {\n\t\t\t\tthis.fail(new Error(\"Language server returned an invalid JSON-RPC error.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpending.reject(new LspJsonRpcError({ code: error.code as number, message: error.message, data: error.data }));\n\t\t\treturn;\n\t\t}\n\t\tpending.resolve(message.result);\n\t}\n\n\tprivate async handleServerRequest(message: JsonRpcMessage): Promise<void> {\n\t\tif (!isJsonRpcId(message.id) || typeof message.method !== \"string\") return;\n\t\tlet result: unknown;\n\t\tlet error: { code: number; message: string } | undefined;\n\t\tswitch (message.method) {\n\t\t\tcase \"workspace/configuration\": {\n\t\t\t\tconst params = message.params;\n\t\t\t\tif (!isRecord(params) || !Array.isArray(params.items)) error = { code: -32602, message: \"Invalid params\" };\n\t\t\t\telse result = params.items.map(() => null);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"workspace/workspaceFolders\":\n\t\t\tcase \"window/showMessageRequest\":\n\t\t\t\tresult = null;\n\t\t\t\tbreak;\n\t\t\tcase \"client/registerCapability\":\n\t\t\tcase \"client/unregisterCapability\":\n\t\t\tcase \"window/workDoneProgress/create\":\n\t\t\tcase \"workspace/semanticTokens/refresh\":\n\t\t\tcase \"workspace/inlayHint/refresh\":\n\t\t\tcase \"workspace/diagnostic/refresh\":\n\t\t\tcase \"workspace/codeLens/refresh\":\n\t\t\t\tresult = null;\n\t\t\t\tbreak;\n\t\t\tcase \"workspace/applyEdit\":\n\t\t\t\tresult = { applied: false, failureReason: \"Apex Code does not accept server-initiated workspace edits.\" };\n\t\t\t\tbreak;\n\t\t\tcase \"window/showDocument\":\n\t\t\t\tresult = { success: false };\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\terror = { code: -32601, message: \"Method not found\" };\n\t\t}\n\t\tawait this.enqueueWrite({\n\t\t\tjsonrpc: \"2.0\",\n\t\t\tid: message.id,\n\t\t\t...(error ? { error } : { result }),\n\t\t}).catch((writeError) => this.fail(normalizeError(writeError)));\n\t}\n\n\tprivate captureStderr(chunk: Buffer | string): void {\n\t\tconst bytes = typeof chunk === \"string\" ? Buffer.from(chunk) : chunk;\n\t\tthis.stderrTail = Buffer.concat([this.stderrTail, bytes]);\n\t\tif (this.stderrTail.length > LSP_MAX_STDERR_TAIL_BYTES) {\n\t\t\tthis.stderrTail = this.stderrTail.subarray(this.stderrTail.length - LSP_MAX_STDERR_TAIL_BYTES);\n\t\t}\n\t}\n\n\tprivate rejectPending(error: Error): void {\n\t\tfor (const request of this.pending.values()) request.reject(error);\n\t\tthis.pending.clear();\n\t}\n\n\tprivate fail(error: Error): void {\n\t\tif (this.state === \"closed\") return;\n\t\tconst firstFailure = this.failure === undefined;\n\t\tthis.failure ??= error;\n\t\tif (this.state !== \"closing\") this.state = \"failed\";\n\t\tthis.rejectPending(this.failure);\n\t\tif (firstFailure) for (const listener of this.failureListeners) listener(this.failure);\n\t}\n}\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/core/lsp/client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ChildProcess } from \"node:child_process\";\nimport type { Readable, Writable } from \"node:stream\";\nimport { pathToFileURL } from \"node:url\";\nimport { spawnProcess } from \"../../utils/child-process.ts\";\n\nexport const LSP_MAX_HEADER_BYTES = 8 * 1024;\nexport const LSP_MAX_MESSAGE_BYTES = 8 * 1024 * 1024;\nexport const LSP_MAX_STDERR_TAIL_BYTES = 64 * 1024;\n\nconst DEFAULT_INITIALIZATION_TIMEOUT_MS = 10_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nconst SHUTDOWN_TIMEOUT_MS = 2_000;\nconst TERMINATE_GRACE_MS = 500;\nconst KILL_GRACE_MS = 1_000;\n\nexport interface LspClientOptions {\n\treadonly command: string;\n\treadonly args?: readonly string[];\n\treadonly cwd: string;\n\treadonly env?: NodeJS.ProcessEnv;\n\treadonly initializationTimeoutMs?: number;\n\treadonly requestTimeoutMs?: number;\n}\n\nexport interface LspNotification {\n\treadonly method: string;\n\treadonly params?: unknown;\n}\n\nexport type LspTextDocumentSyncKind = \"none\" | \"full\" | \"incremental\";\n\nexport interface LspTextDocumentSync {\n\treadonly kind: LspTextDocumentSyncKind;\n\treadonly openClose: boolean;\n\treadonly save: boolean;\n\treadonly saveIncludeText: boolean;\n}\n\nexport class LspJsonRpcError extends Error {\n\treadonly code: number;\n\treadonly data?: unknown;\n\n\tconstructor(error: { code: number; message: string; data?: unknown }) {\n\t\tsuper(error.message);\n\t\tthis.name = \"LspJsonRpcError\";\n\t\tthis.code = error.code;\n\t\tthis.data = error.data;\n\t}\n}\n\ntype JsonRpcId = number;\ntype PendingRequest = {\n\tresolve(value: unknown): void;\n\treject(reason: Error): void;\n};\n\ntype ClientState = \"idle\" | \"starting\" | \"ready\" | \"closing\" | \"closed\" | \"failed\";\n\ntype JsonRpcMessage = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isJsonRpcId(value: unknown): value is string | number {\n\treturn typeof value === \"string\" || (typeof value === \"number\" && Number.isSafeInteger(value));\n}\n\nfunction normalizeError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction parseTextDocumentSync(value: unknown): LspTextDocumentSync {\n\tlet kind: LspTextDocumentSyncKind = \"none\";\n\tlet openClose = false;\n\tlet save = false;\n\tlet saveIncludeText = false;\n\tif (typeof value === \"number\") {\n\t\tkind = value === 1 ? \"full\" : value === 2 ? \"incremental\" : \"none\";\n\t} else if (isRecord(value)) {\n\t\topenClose = value.openClose === true;\n\t\tkind = value.change === 1 ? \"full\" : value.change === 2 ? \"incremental\" : \"none\";\n\t\tif (value.save === true) save = true;\n\t\telse if (isRecord(value.save)) {\n\t\t\tsave = true;\n\t\t\tsaveIncludeText = value.save.includeText === true;\n\t\t}\n\t}\n\treturn { kind, openClose, save, saveIncludeText };\n}\n\nfunction validateTimeout(value: number | undefined, fallback: number, label: string): number {\n\tconst timeout = value ?? fallback;\n\tif (!Number.isSafeInteger(timeout) || timeout < 1) throw new Error(`${label} must be a positive safe integer.`);\n\treturn timeout;\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** A bounded JSON-RPC 2.0 client for one language server's stdio. */\nexport class LspClient {\n\tprivate readonly options: LspClientOptions;\n\tprivate child: ChildProcess | undefined;\n\tprivate stdin: Writable | undefined;\n\tprivate stdout: Readable | undefined;\n\tprivate input = Buffer.alloc(0);\n\tprivate stderrTail = Buffer.alloc(0);\n\tprivate nextRequestId = 1;\n\tprivate readonly pending = new Map<JsonRpcId, PendingRequest>();\n\tprivate readonly notificationListeners = new Set<(notification: LspNotification) => void>();\n\tprivate readonly failureListeners = new Set<(error: Error) => void>();\n\tprivate startPromise: Promise<void> | undefined;\n\tprivate disposePromise: Promise<void> | undefined;\n\tprivate state: ClientState = \"idle\";\n\tprivate failure: Error | undefined;\n\tprivate writeChain: Promise<void> = Promise.resolve();\n\tprivate syncCapabilities: LspTextDocumentSync = {\n\t\tkind: \"none\",\n\t\topenClose: false,\n\t\tsave: false,\n\t\tsaveIncludeText: false,\n\t};\n\n\tconstructor(options: LspClientOptions) {\n\t\tthis.options = options;\n\t}\n\n\tget capturedStderr(): string {\n\t\treturn this.stderrTail.toString(\"utf8\");\n\t}\n\n\t/** Text-document synchronization negotiated during initialization. */\n\tget textDocumentSync(): LspTextDocumentSync {\n\t\treturn this.syncCapabilities;\n\t}\n\n\tonNotification(listener: (notification: LspNotification) => void): () => void {\n\t\tthis.notificationListeners.add(listener);\n\t\treturn () => this.notificationListeners.delete(listener);\n\t}\n\n\t/** Subscribe to the first terminal protocol or process failure. */\n\tonFailure(listener: (error: Error) => void): () => void {\n\t\tthis.failureListeners.add(listener);\n\t\tif (this.failure) listener(this.failure);\n\t\treturn () => this.failureListeners.delete(listener);\n\t}\n\n\tstart(): Promise<void> {\n\t\tif (this.failure) return Promise.reject(this.failure);\n\t\tif (this.state === \"closing\" || this.state === \"closed\") {\n\t\t\treturn Promise.reject(new Error(\"Language server client is disposed.\"));\n\t\t}\n\t\tif (!this.startPromise) {\n\t\t\tthis.state = \"starting\";\n\t\t\tthis.startPromise = this.initialize().catch(async (error) => {\n\t\t\t\tconst failure = normalizeError(error);\n\t\t\t\tthis.fail(failure);\n\t\t\t\tawait this.terminateChild();\n\t\t\t\tthrow failure;\n\t\t\t});\n\t\t}\n\t\treturn this.startPromise;\n\t}\n\n\tasync request(method: string, params?: unknown, signal?: AbortSignal): Promise<unknown> {\n\t\tawait this.start();\n\t\tif (this.state !== \"ready\") throw this.failure ?? new Error(\"Language server did not become ready.\");\n\t\treturn this.sendRequest(method, params, signal, this.requestTimeoutMs());\n\t}\n\n\tnotify(method: string, params?: unknown): void {\n\t\tif (this.failure) throw this.failure;\n\t\tconst exitFailure = this.childExitFailure();\n\t\tif (exitFailure) {\n\t\t\tthis.fail(exitFailure);\n\t\t\tthrow exitFailure;\n\t\t}\n\t\tif (this.state !== \"ready\") throw new Error(\"Language server is not ready.\");\n\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", method, ...(params === undefined ? {} : { params }) }).catch((error) => {\n\t\t\tthis.fail(normalizeError(error));\n\t\t});\n\t}\n\n\tdispose(): Promise<void> {\n\t\tif (!this.disposePromise) this.disposePromise = this.disposeProcess();\n\t\treturn this.disposePromise;\n\t}\n\n\tprivate initializationTimeoutMs(): number {\n\t\treturn validateTimeout(\n\t\t\tthis.options.initializationTimeoutMs,\n\t\t\tDEFAULT_INITIALIZATION_TIMEOUT_MS,\n\t\t\t\"initializationTimeoutMs\",\n\t\t);\n\t}\n\n\tprivate requestTimeoutMs(): number {\n\t\treturn validateTimeout(this.options.requestTimeoutMs, DEFAULT_REQUEST_TIMEOUT_MS, \"requestTimeoutMs\");\n\t}\n\n\tprivate async initialize(): Promise<void> {\n\t\tconst child = spawnProcess(this.options.command, [...(this.options.args ?? [])], {\n\t\t\tcwd: this.options.cwd,\n\t\t\tenv: this.options.env,\n\t\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t\t});\n\t\tif (!child.stdin || !child.stdout) {\n\t\t\tchild.kill();\n\t\t\tthrow new Error(\"Language server must expose piped stdin and stdout.\");\n\t\t}\n\t\tthis.child = child;\n\t\tthis.stdin = child.stdin;\n\t\tthis.stdout = child.stdout;\n\t\tthis.stdout.on(\"data\", (chunk: Buffer | string) => this.onData(chunk));\n\t\tchild.stderr?.on(\"data\", (chunk: Buffer | string) => this.captureStderr(chunk));\n\t\tchild.stdin.on(\"error\", (error) => {\n\t\t\tvoid this.writeFailure(error).then((failure) => this.fail(failure));\n\t\t});\n\t\tchild.once(\"error\", (error) => this.fail(error));\n\t\tchild.once(\"exit\", (code, signal) => {\n\t\t\tif (this.state !== \"closing\" && this.state !== \"closed\") {\n\t\t\t\tthis.fail(new Error(`Language server exited before shutdown (code=${code} signal=${signal}).`));\n\t\t\t}\n\t\t});\n\n\t\tconst initializeResult = await this.sendRequest(\n\t\t\t\"initialize\",\n\t\t\t{\n\t\t\t\tprocessId: process.pid,\n\t\t\t\tclientInfo: { name: \"Apex Code\" },\n\t\t\t\trootUri: pathToFileURL(this.options.cwd).href,\n\t\t\t\tcapabilities: {\n\t\t\t\t\tgeneral: { positionEncodings: [\"utf-16\"] },\n\t\t\t\t\tworkspace: { workspaceFolders: false },\n\t\t\t\t\ttextDocument: {\n\t\t\t\t\t\tdefinition: {},\n\t\t\t\t\t\treferences: {},\n\t\t\t\t\t\tdocumentSymbol: {},\n\t\t\t\t\t\tpublishDiagnostics: { versionSupport: true },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tworkspaceFolders: null,\n\t\t\t},\n\t\t\tundefined,\n\t\t\tthis.initializationTimeoutMs(),\n\t\t\t\"Language server initialize timed out\",\n\t\t);\n\t\tif (!isRecord(initializeResult) || !isRecord(initializeResult.capabilities)) {\n\t\t\tthrow new Error(\"Language server returned an invalid initialize result.\");\n\t\t}\n\t\tthis.syncCapabilities = parseTextDocumentSync(initializeResult.capabilities.textDocumentSync);\n\t\tif (this.state !== \"starting\") throw new Error(\"Language server initialization was interrupted.\");\n\t\tawait this.enqueueWrite({ jsonrpc: \"2.0\", method: \"initialized\", params: {} });\n\t\tthis.state = \"ready\";\n\t}\n\n\tprivate async disposeProcess(): Promise<void> {\n\t\tif (this.state === \"closed\") return;\n\t\tconst wasReady = this.state === \"ready\";\n\t\tthis.state = \"closing\";\n\t\tthis.rejectPending(new Error(\"Language server client is closing.\"));\n\n\t\tif (wasReady) {\n\t\t\ttry {\n\t\t\t\tawait this.sendRequest(\n\t\t\t\t\t\"shutdown\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tundefined,\n\t\t\t\t\tSHUTDOWN_TIMEOUT_MS,\n\t\t\t\t\t\"Language server shutdown timed out\",\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t\tawait this.enqueueWrite({ jsonrpc: \"2.0\", method: \"exit\" });\n\t\t\t} catch {\n\t\t\t\t// Bounded termination below is the fallback for an uncooperative server.\n\t\t\t}\n\t\t}\n\t\tawait this.terminateChild();\n\t\tthis.stdin?.end();\n\t\tthis.state = \"closed\";\n\t}\n\n\tprivate async terminateChild(): Promise<void> {\n\t\tconst child = this.child;\n\t\tif (!child || child.exitCode !== null || child.signalCode !== null) return;\n\t\tconst exited = new Promise<void>((resolve) => child.once(\"exit\", () => resolve()));\n\t\tconst graceful = await Promise.race([exited.then(() => true), delay(TERMINATE_GRACE_MS).then(() => false)]);\n\t\tif (graceful) return;\n\t\tchild.kill(\"SIGTERM\");\n\t\tconst terminated = await Promise.race([exited.then(() => true), delay(KILL_GRACE_MS).then(() => false)]);\n\t\tif (terminated) return;\n\t\tchild.kill(\"SIGKILL\");\n\t\tawait exited;\n\t}\n\n\tprivate sendRequest(\n\t\tmethod: string,\n\t\tparams?: unknown,\n\t\tsignal?: AbortSignal,\n\t\ttimeoutMs?: number,\n\t\ttimeoutMessage = `Language server request ${method} timed out`,\n\t\tallowClosing = false,\n\t): Promise<unknown> {\n\t\tif (this.failure && !allowClosing) return Promise.reject(this.failure);\n\t\tconst exitFailure = this.childExitFailure();\n\t\tif (exitFailure && !allowClosing) {\n\t\t\tthis.fail(exitFailure);\n\t\t\treturn Promise.reject(exitFailure);\n\t\t}\n\t\tif ((!allowClosing && (this.state === \"closing\" || this.state === \"closed\")) || this.state === \"failed\") {\n\t\t\treturn Promise.reject(this.failure ?? new Error(\"Language server client is disposed.\"));\n\t\t}\n\t\tconst id = this.nextRequestId++;\n\t\tif (!Number.isSafeInteger(id)) return Promise.reject(new Error(\"Language server request id space exhausted.\"));\n\t\tif (signal?.aborted)\n\t\t\treturn Promise.reject(normalizeError(signal.reason ?? new Error(\"Language server request aborted.\")));\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet timer: NodeJS.Timeout | undefined;\n\t\t\tconst settle = (fn: () => void) => {\n\t\t\t\tif (timer) clearTimeout(timer);\n\t\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\t\tfn();\n\t\t\t};\n\t\t\tconst abort = () => {\n\t\t\t\tif (!this.pending.delete(id)) return;\n\t\t\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", method: \"$/cancelRequest\", params: { id } }).catch(() => {});\n\t\t\t\tsettle(() => reject(normalizeError(signal?.reason ?? new Error(\"Language server request aborted.\"))));\n\t\t\t};\n\t\t\tthis.pending.set(id, {\n\t\t\t\tresolve: (value) => settle(() => resolve(value)),\n\t\t\t\treject: (error) => settle(() => reject(error)),\n\t\t\t});\n\t\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\tif (timeoutMs !== undefined) {\n\t\t\t\ttimer = setTimeout(() => {\n\t\t\t\t\tif (!this.pending.delete(id)) return;\n\t\t\t\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", method: \"$/cancelRequest\", params: { id } }).catch(() => {});\n\t\t\t\t\tsettle(() => reject(new Error(`${timeoutMessage} after ${timeoutMs}ms.`)));\n\t\t\t\t}, timeoutMs);\n\t\t\t}\n\t\t\tvoid this.enqueueWrite({ jsonrpc: \"2.0\", id, method, ...(params === undefined ? {} : { params }) }).catch(\n\t\t\t\t(error) => {\n\t\t\t\t\tconst pending = this.pending.get(id);\n\t\t\t\t\tif (!pending) return;\n\t\t\t\t\tthis.pending.delete(id);\n\t\t\t\t\tpending.reject(normalizeError(error));\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate enqueueWrite(message: object): Promise<void> {\n\t\tconst body = Buffer.from(JSON.stringify(message), \"utf8\");\n\t\tif (body.length > LSP_MAX_MESSAGE_BYTES)\n\t\t\treturn Promise.reject(new Error(\"Language server message exceeds 8 MiB.\"));\n\t\tconst frame = Buffer.concat([Buffer.from(`Content-Length: ${body.length}\\r\\n\\r\\n`, \"ascii\"), body]);\n\t\tconst writing = this.writeChain.then(() => this.writeFrame(frame));\n\t\tthis.writeChain = writing.catch(() => {});\n\t\treturn writing;\n\t}\n\n\tprivate writeFrame(frame: Buffer): Promise<void> {\n\t\tconst stream = this.stdin;\n\t\tif (!stream || stream.destroyed || !stream.writable) {\n\t\t\treturn Promise.reject(new Error(\"Language server stdin is not writable.\"));\n\t\t}\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet waitingForDrain = false;\n\t\t\tconst cleanup = () => {\n\t\t\t\tstream.removeListener(\"error\", onError);\n\t\t\t\tstream.removeListener(\"drain\", onDrain);\n\t\t\t};\n\t\t\tconst onError = (error: Error) => {\n\t\t\t\tcleanup();\n\t\t\t\tvoid this.writeFailure(error).then(reject);\n\t\t\t};\n\t\t\tconst onDrain = () => {\n\t\t\t\twaitingForDrain = false;\n\t\t\t\tcleanup();\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tstream.once(\"error\", onError);\n\t\t\tconst accepted = stream.write(frame, (error) => {\n\t\t\t\tif (error) onError(error);\n\t\t\t\telse if (!waitingForDrain) {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (!accepted) {\n\t\t\t\twaitingForDrain = true;\n\t\t\t\tstream.once(\"drain\", onDrain);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate onData(chunk: Buffer | string): void {\n\t\tif (this.failure) return;\n\t\tthis.input = Buffer.concat([this.input, typeof chunk === \"string\" ? Buffer.from(chunk) : chunk]);\n\t\twhile (true) {\n\t\t\tconst headerEnd = this.input.indexOf(\"\\r\\n\\r\\n\");\n\t\t\tif (headerEnd < 0) {\n\t\t\t\tif (this.input.length > LSP_MAX_HEADER_BYTES) this.fail(new Error(\"Language server header exceeds 8 KiB.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (headerEnd > LSP_MAX_HEADER_BYTES) {\n\t\t\t\tthis.fail(new Error(\"Language server header exceeds 8 KiB.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst header = this.input.subarray(0, headerEnd).toString(\"ascii\");\n\t\t\tconst lengths = [...header.matchAll(/(?:^|\\r\\n)Content-Length:\\s*(\\d+)(?=\\r\\n|$)/gi)];\n\t\t\tif (lengths.length !== 1) {\n\t\t\t\tthis.fail(new Error(\"Language server frame must contain exactly one Content-Length header.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst contentLength = Number(lengths[0][1]);\n\t\t\tif (!Number.isSafeInteger(contentLength) || contentLength > LSP_MAX_MESSAGE_BYTES) {\n\t\t\t\tthis.fail(new Error(\"Language server message exceeds 8 MiB.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst bodyStart = headerEnd + 4;\n\t\t\tif (this.input.length < bodyStart + contentLength) return;\n\t\t\tconst body = this.input.subarray(bodyStart, bodyStart + contentLength).toString(\"utf8\");\n\t\t\tthis.input = this.input.subarray(bodyStart + contentLength);\n\t\t\ttry {\n\t\t\t\tconst parsed: unknown = JSON.parse(body);\n\t\t\t\tif (!isRecord(parsed)) throw new Error(\"Language server JSON-RPC message must be an object.\");\n\t\t\t\tthis.onMessage(parsed);\n\t\t\t} catch (error) {\n\t\t\t\tthis.fail(normalizeError(error));\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onMessage(message: JsonRpcMessage): void {\n\t\tif (message.jsonrpc !== \"2.0\") {\n\t\t\tthis.fail(new Error('Language server message must declare jsonrpc \"2.0\".'));\n\t\t\treturn;\n\t\t}\n\t\tif (typeof message.method === \"string\") {\n\t\t\tif (message.id !== undefined && message.id !== null) {\n\t\t\t\tvoid this.handleServerRequest(message);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst notification: LspNotification = {\n\t\t\t\tmethod: message.method,\n\t\t\t\t...(message.params === undefined ? {} : { params: message.params }),\n\t\t\t};\n\t\t\tfor (const listener of this.notificationListeners) listener(notification);\n\t\t\treturn;\n\t\t}\n\t\tif (typeof message.id !== \"number\" || !Number.isSafeInteger(message.id)) return;\n\t\tconst pending = this.pending.get(message.id);\n\t\tif (!pending) return;\n\t\tconst hasResult = Object.hasOwn(message, \"result\");\n\t\tconst hasError = Object.hasOwn(message, \"error\");\n\t\tif (hasResult === hasError) {\n\t\t\tthis.fail(new Error(\"Language server response must contain exactly one of result or error.\"));\n\t\t\treturn;\n\t\t}\n\t\tthis.pending.delete(message.id);\n\t\tif (hasError) {\n\t\t\tconst error = message.error;\n\t\t\tif (!isRecord(error) || !Number.isSafeInteger(error.code) || typeof error.message !== \"string\") {\n\t\t\t\tthis.fail(new Error(\"Language server returned an invalid JSON-RPC error.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpending.reject(new LspJsonRpcError({ code: error.code as number, message: error.message, data: error.data }));\n\t\t\treturn;\n\t\t}\n\t\tpending.resolve(message.result);\n\t}\n\n\tprivate async handleServerRequest(message: JsonRpcMessage): Promise<void> {\n\t\tif (!isJsonRpcId(message.id) || typeof message.method !== \"string\") return;\n\t\tlet result: unknown;\n\t\tlet error: { code: number; message: string } | undefined;\n\t\tswitch (message.method) {\n\t\t\tcase \"workspace/configuration\": {\n\t\t\t\tconst params = message.params;\n\t\t\t\tif (!isRecord(params) || !Array.isArray(params.items)) error = { code: -32602, message: \"Invalid params\" };\n\t\t\t\telse result = params.items.map(() => null);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"workspace/workspaceFolders\":\n\t\t\tcase \"window/showMessageRequest\":\n\t\t\t\tresult = null;\n\t\t\t\tbreak;\n\t\t\tcase \"client/registerCapability\":\n\t\t\tcase \"client/unregisterCapability\":\n\t\t\tcase \"window/workDoneProgress/create\":\n\t\t\tcase \"workspace/semanticTokens/refresh\":\n\t\t\tcase \"workspace/inlayHint/refresh\":\n\t\t\tcase \"workspace/diagnostic/refresh\":\n\t\t\tcase \"workspace/codeLens/refresh\":\n\t\t\t\tresult = null;\n\t\t\t\tbreak;\n\t\t\tcase \"workspace/applyEdit\":\n\t\t\t\tresult = { applied: false, failureReason: \"Apex Code does not accept server-initiated workspace edits.\" };\n\t\t\t\tbreak;\n\t\t\tcase \"window/showDocument\":\n\t\t\t\tresult = { success: false };\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\terror = { code: -32601, message: \"Method not found\" };\n\t\t}\n\t\tawait this.enqueueWrite({\n\t\t\tjsonrpc: \"2.0\",\n\t\t\tid: message.id,\n\t\t\t...(error ? { error } : { result }),\n\t\t}).catch((writeError) => this.fail(normalizeError(writeError)));\n\t}\n\n\tprivate captureStderr(chunk: Buffer | string): void {\n\t\tconst bytes = typeof chunk === \"string\" ? Buffer.from(chunk) : chunk;\n\t\tthis.stderrTail = Buffer.concat([this.stderrTail, bytes]);\n\t\tif (this.stderrTail.length > LSP_MAX_STDERR_TAIL_BYTES) {\n\t\t\tthis.stderrTail = this.stderrTail.subarray(this.stderrTail.length - LSP_MAX_STDERR_TAIL_BYTES);\n\t\t}\n\t}\n\n\tprivate rejectPending(error: Error): void {\n\t\tfor (const request of this.pending.values()) request.reject(error);\n\t\tthis.pending.clear();\n\t}\n\n\tprivate childExitFailure(): Error | undefined {\n\t\tconst child = this.child;\n\t\tif (!child || (child.exitCode === null && child.signalCode === null)) return undefined;\n\t\treturn new Error(`Language server exited before shutdown (code=${child.exitCode} signal=${child.signalCode}).`);\n\t}\n\n\tprivate async writeFailure(error: Error): Promise<Error> {\n\t\tconst exitFailure = this.childExitFailure();\n\t\tif (exitFailure || (error as NodeJS.ErrnoException).code !== \"EPIPE\" || !this.child) return exitFailure ?? error;\n\t\tawait Promise.race([new Promise<void>((resolve) => this.child?.once(\"exit\", () => resolve())), delay(1_000)]);\n\t\treturn this.childExitFailure() ?? error;\n\t}\n\n\tprivate fail(error: Error): void {\n\t\tif (this.state === \"closed\") return;\n\t\tconst firstFailure = this.failure === undefined;\n\t\tthis.failure ??= error;\n\t\tif (this.state !== \"closing\") this.state = \"failed\";\n\t\tthis.rejectPending(this.failure);\n\t\tif (firstFailure) for (const listener of this.failureListeners) listener(this.failure);\n\t}\n}\n"]}
@@ -38,6 +38,7 @@ declare const ModelDefinitionSchema: Type.TObject<{
38
38
  supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
39
39
  supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
40
40
  supportsUsageInStreaming: Type.TOptional<Type.TBoolean>;
41
+ supportsFinishReason: Type.TOptional<Type.TBoolean>;
41
42
  maxTokensField: Type.TOptional<Type.TUnion<[Type.TLiteral<"max_completion_tokens">, Type.TLiteral<"max_tokens">]>>;
42
43
  requiresToolResultName: Type.TOptional<Type.TBoolean>;
43
44
  requiresAssistantAfterToolResult: Type.TOptional<Type.TBoolean>;
@@ -103,6 +104,7 @@ declare const ModelDefinitionSchema: Type.TObject<{
103
104
  supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
104
105
  supportsStrictMode: Type.TOptional<Type.TBoolean>;
105
106
  supportsOpenAIGrammarTools: Type.TOptional<Type.TBoolean>;
107
+ supportsAdditionalTools: Type.TOptional<Type.TBoolean>;
106
108
  supportsToolSearch: Type.TOptional<Type.TBoolean>;
107
109
  }>, Type.TObject<{
108
110
  supportsEagerToolInputStreaming: Type.TOptional<Type.TBoolean>;
@@ -151,6 +153,7 @@ declare const ModelOverrideSchema: Type.TObject<{
151
153
  supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
152
154
  supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
153
155
  supportsUsageInStreaming: Type.TOptional<Type.TBoolean>;
156
+ supportsFinishReason: Type.TOptional<Type.TBoolean>;
154
157
  maxTokensField: Type.TOptional<Type.TUnion<[Type.TLiteral<"max_completion_tokens">, Type.TLiteral<"max_tokens">]>>;
155
158
  requiresToolResultName: Type.TOptional<Type.TBoolean>;
156
159
  requiresAssistantAfterToolResult: Type.TOptional<Type.TBoolean>;
@@ -216,6 +219,7 @@ declare const ModelOverrideSchema: Type.TObject<{
216
219
  supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
217
220
  supportsStrictMode: Type.TOptional<Type.TBoolean>;
218
221
  supportsOpenAIGrammarTools: Type.TOptional<Type.TBoolean>;
222
+ supportsAdditionalTools: Type.TOptional<Type.TBoolean>;
219
223
  supportsToolSearch: Type.TOptional<Type.TBoolean>;
220
224
  }>, Type.TObject<{
221
225
  supportsEagerToolInputStreaming: Type.TOptional<Type.TBoolean>;
@@ -241,6 +245,7 @@ declare const ProviderConfigSchema: Type.TObject<{
241
245
  supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
242
246
  supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
243
247
  supportsUsageInStreaming: Type.TOptional<Type.TBoolean>;
248
+ supportsFinishReason: Type.TOptional<Type.TBoolean>;
244
249
  maxTokensField: Type.TOptional<Type.TUnion<[Type.TLiteral<"max_completion_tokens">, Type.TLiteral<"max_tokens">]>>;
245
250
  requiresToolResultName: Type.TOptional<Type.TBoolean>;
246
251
  requiresAssistantAfterToolResult: Type.TOptional<Type.TBoolean>;
@@ -306,6 +311,7 @@ declare const ProviderConfigSchema: Type.TObject<{
306
311
  supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
307
312
  supportsStrictMode: Type.TOptional<Type.TBoolean>;
308
313
  supportsOpenAIGrammarTools: Type.TOptional<Type.TBoolean>;
314
+ supportsAdditionalTools: Type.TOptional<Type.TBoolean>;
309
315
  supportsToolSearch: Type.TOptional<Type.TBoolean>;
310
316
  }>, Type.TObject<{
311
317
  supportsEagerToolInputStreaming: Type.TOptional<Type.TBoolean>;
@@ -357,6 +363,7 @@ declare const ProviderConfigSchema: Type.TObject<{
357
363
  supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
358
364
  supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
359
365
  supportsUsageInStreaming: Type.TOptional<Type.TBoolean>;
366
+ supportsFinishReason: Type.TOptional<Type.TBoolean>;
360
367
  maxTokensField: Type.TOptional<Type.TUnion<[Type.TLiteral<"max_completion_tokens">, Type.TLiteral<"max_tokens">]>>;
361
368
  requiresToolResultName: Type.TOptional<Type.TBoolean>;
362
369
  requiresAssistantAfterToolResult: Type.TOptional<Type.TBoolean>;
@@ -422,6 +429,7 @@ declare const ProviderConfigSchema: Type.TObject<{
422
429
  supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
423
430
  supportsStrictMode: Type.TOptional<Type.TBoolean>;
424
431
  supportsOpenAIGrammarTools: Type.TOptional<Type.TBoolean>;
432
+ supportsAdditionalTools: Type.TOptional<Type.TBoolean>;
425
433
  supportsToolSearch: Type.TOptional<Type.TBoolean>;
426
434
  }>, Type.TObject<{
427
435
  supportsEagerToolInputStreaming: Type.TOptional<Type.TBoolean>;
@@ -470,6 +478,7 @@ declare const ProviderConfigSchema: Type.TObject<{
470
478
  supportsDeveloperRole: Type.TOptional<Type.TBoolean>;
471
479
  supportsReasoningEffort: Type.TOptional<Type.TBoolean>;
472
480
  supportsUsageInStreaming: Type.TOptional<Type.TBoolean>;
481
+ supportsFinishReason: Type.TOptional<Type.TBoolean>;
473
482
  maxTokensField: Type.TOptional<Type.TUnion<[Type.TLiteral<"max_completion_tokens">, Type.TLiteral<"max_tokens">]>>;
474
483
  requiresToolResultName: Type.TOptional<Type.TBoolean>;
475
484
  requiresAssistantAfterToolResult: Type.TOptional<Type.TBoolean>;
@@ -535,6 +544,7 @@ declare const ProviderConfigSchema: Type.TObject<{
535
544
  supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
536
545
  supportsStrictMode: Type.TOptional<Type.TBoolean>;
537
546
  supportsOpenAIGrammarTools: Type.TOptional<Type.TBoolean>;
547
+ supportsAdditionalTools: Type.TOptional<Type.TBoolean>;
538
548
  supportsToolSearch: Type.TOptional<Type.TBoolean>;
539
549
  }>, Type.TObject<{
540
550
  supportsEagerToolInputStreaming: Type.TOptional<Type.TBoolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"model-config.d.ts","sourceRoot":"","sources":["../../src/core/model-config.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAGxD,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAwJ5C,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAczB,CAAC;AAEH,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBvB,CAAC;AAEH,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWxB,CAAC;AAEH,QAAA,MAAM,oBAAoB;IACzB,0EAA0E;;EAEzE,CAAC;AASH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACnE,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACzE,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACrE,MAAM,MAAM,wBAAwB,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAsB3E,yCAAyC;AACzC,qBAAa,WAAW;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0C;IACpE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyC;IAC/D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAE3C,OAAO,eAQN;IAED,OAAa,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CA6C1E;IAED,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAE9D;IAED,cAAc,IAAI,SAAS,MAAM,EAAE,CAElC;IAED,oFAAoF;IACpF,QAAQ,IAAI,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAEjD;IAED,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7B;CACD","sourcesContent":["/** Immutable, credential-blind models.json snapshot. */\n\nimport { readFile } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { Compile } from \"typebox/compile\";\nimport type { TLocalizedValidationError } from \"typebox/error\";\nimport { stripJsonComments } from \"../utils/json.ts\";\nimport { normalizePath } from \"../utils/paths.ts\";\n\nconst PercentileCutoffsSchema = Type.Object({\n\tp50: Type.Optional(Type.Number()),\n\tp75: Type.Optional(Type.Number()),\n\tp90: Type.Optional(Type.Number()),\n\tp99: Type.Optional(Type.Number()),\n});\n\nconst OpenRouterRoutingSchema = Type.Object({\n\tallow_fallbacks: Type.Optional(Type.Boolean()),\n\trequire_parameters: Type.Optional(Type.Boolean()),\n\tdata_collection: Type.Optional(Type.Union([Type.Literal(\"deny\"), Type.Literal(\"allow\")])),\n\tzdr: Type.Optional(Type.Boolean()),\n\tenforce_distillable_text: Type.Optional(Type.Boolean()),\n\torder: Type.Optional(Type.Array(Type.String())),\n\tonly: Type.Optional(Type.Array(Type.String())),\n\tignore: Type.Optional(Type.Array(Type.String())),\n\tquantizations: Type.Optional(Type.Array(Type.String())),\n\tsort: Type.Optional(\n\t\tType.Union([\n\t\t\tType.String(),\n\t\t\tType.Object({\n\t\t\t\tby: Type.Optional(Type.String()),\n\t\t\t\tpartition: Type.Optional(Type.Union([Type.String(), Type.Null()])),\n\t\t\t}),\n\t\t]),\n\t),\n\tmax_price: Type.Optional(\n\t\tType.Object({\n\t\t\tprompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\tcompletion: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\timage: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\taudio: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\trequest: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t}),\n\t),\n\tpreferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n\tpreferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n});\n\nconst VercelGatewayRoutingSchema = Type.Object({\n\tonly: Type.Optional(Type.Array(Type.String())),\n\torder: Type.Optional(Type.Array(Type.String())),\n});\n\nconst ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]);\nconst ThinkingLevelMapSchema = Type.Object({\n\toff: Type.Optional(ThinkingLevelMapValueSchema),\n\tminimal: Type.Optional(ThinkingLevelMapValueSchema),\n\tlow: Type.Optional(ThinkingLevelMapValueSchema),\n\tmedium: Type.Optional(ThinkingLevelMapValueSchema),\n\thigh: Type.Optional(ThinkingLevelMapValueSchema),\n\txhigh: Type.Optional(ThinkingLevelMapValueSchema),\n\tmax: Type.Optional(ThinkingLevelMapValueSchema),\n});\n\nconst ChatTemplateKwargScalarSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean(), Type.Null()]);\nconst ChatTemplateKwargVariableSchema = Type.Object({\n\t$var: Type.Union([Type.Literal(\"thinking.enabled\"), Type.Literal(\"thinking.effort\")]),\n\tomitWhenOff: Type.Optional(Type.Boolean()),\n});\nconst ChatTemplateKwargSchema = Type.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]);\n\nconst OpenAICompletionsCompatSchema = Type.Object({\n\tsupportsStore: Type.Optional(Type.Boolean()),\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsupportsReasoningEffort: Type.Optional(Type.Boolean()),\n\tsupportsUsageInStreaming: Type.Optional(Type.Boolean()),\n\tmaxTokensField: Type.Optional(Type.Union([Type.Literal(\"max_completion_tokens\"), Type.Literal(\"max_tokens\")])),\n\trequiresToolResultName: Type.Optional(Type.Boolean()),\n\trequiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),\n\trequiresThinkingAsText: Type.Optional(Type.Boolean()),\n\trequiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),\n\tthinkingFormat: Type.Optional(\n\t\tType.Union([\n\t\t\tType.Literal(\"openai\"),\n\t\t\tType.Literal(\"openrouter\"),\n\t\t\tType.Literal(\"together\"),\n\t\t\tType.Literal(\"baseten\"),\n\t\t\tType.Literal(\"deepseek\"),\n\t\t\tType.Literal(\"zai\"),\n\t\t\tType.Literal(\"qwen\"),\n\t\t\tType.Literal(\"chat-template\"),\n\t\t\tType.Literal(\"qwen-chat-template\"),\n\t\t\tType.Literal(\"string-thinking\"),\n\t\t\tType.Literal(\"ant-ling\"),\n\t\t]),\n\t),\n\tchatTemplateKwargs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tchatTemplateArgs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tcacheControlFormat: Type.Optional(Type.Literal(\"anthropic\")),\n\topenRouterRouting: Type.Optional(OpenRouterRoutingSchema),\n\tvercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tdeferredToolsMode: Type.Optional(Type.Literal(\"kimi\")),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n});\n\nconst OpenAIResponsesCompatSchema = Type.Object({\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsToolSearch: Type.Optional(Type.Boolean()),\n});\n\nconst AnthropicMessagesCompatSchema = Type.Object({\n\tsupportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tsupportsCacheControlOnTools: Type.Optional(Type.Boolean()),\n\tsupportsTemperature: Type.Optional(Type.Boolean()),\n\tforceAdaptiveThinking: Type.Optional(Type.Boolean()),\n\tallowEmptySignature: Type.Optional(Type.Boolean()),\n\tsupportsStrictTools: Type.Optional(Type.Boolean()),\n\tsupportsToolReferences: Type.Optional(Type.Boolean()),\n});\n\nconst ProviderCompatSchema = Type.Union([\n\tOpenAICompletionsCompatSchema,\n\tOpenAIResponsesCompatSchema,\n\tAnthropicMessagesCompatSchema,\n]);\n\nconst ModelCostRatesSchema = {\n\tinput: Type.Number(),\n\toutput: Type.Number(),\n\tcacheRead: Type.Number(),\n\tcacheWrite: Type.Number(),\n};\nconst ModelCostTierSchema = Type.Object({\n\tinputTokensAbove: Type.Number(),\n\t...ModelCostRatesSchema,\n});\nconst ModelCostSchema = Type.Object({\n\t...ModelCostRatesSchema,\n\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n});\n\nconst ModelDefinitionSchema = Type.Object({\n\tid: Type.String({ minLength: 1 }),\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(ModelCostSchema),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ModelOverrideSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(\n\t\tType.Object({\n\t\t\tinput: Type.Optional(Type.Number()),\n\t\t\toutput: Type.Optional(Type.Number()),\n\t\t\tcacheRead: Type.Optional(Type.Number()),\n\t\t\tcacheWrite: Type.Optional(Type.Number()),\n\t\t\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n\t\t}),\n\t),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ProviderConfigSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\tapiKey: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\toauth: Type.Optional(Type.Literal(\"radius\")),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n\tauthHeader: Type.Optional(Type.Boolean()),\n\tmodels: Type.Optional(Type.Array(ModelDefinitionSchema)),\n\tmodelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema)),\n});\n\nconst RoleDefinitionSchema = Type.Object({\n\t/** Ordered, non-empty list of canonical \"provider/modelId\" candidates. */\n\tmodels: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),\n});\n\nconst ModelsConfigSchema = Type.Object({\n\tproviders: Type.Record(Type.String(), ProviderConfigSchema),\n\t/** Additive, credential-blind role -> ordered model-candidate mapping. */\n\troles: Type.Optional(Type.Record(Type.String(), RoleDefinitionSchema)),\n});\nconst validateModelsConfig = Compile(ModelsConfigSchema);\n\nexport type ModelsJsonModel = Static<typeof ModelDefinitionSchema>;\nexport type ModelsJsonModelOverride = Static<typeof ModelOverrideSchema>;\nexport type ModelsJsonProvider = Static<typeof ProviderConfigSchema>;\nexport type ModelsJsonRoleDefinition = Static<typeof RoleDefinitionSchema>;\ntype ModelsJson = Static<typeof ModelsConfigSchema>;\n\nfunction formatValidationPath(error: TLocalizedValidationError): string {\n\tif (error.keyword === \"required\") {\n\t\tconst requiredProperties = (error.params as { requiredProperties?: string[] }).requiredProperties;\n\t\tconst requiredProperty = requiredProperties?.[0];\n\t\tif (requiredProperty) {\n\t\t\tconst basePath = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\t\t\treturn basePath ? `${basePath}.${requiredProperty}` : requiredProperty;\n\t\t}\n\t}\n\tconst path = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\treturn path || \"root\";\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n\tfor (const child of Object.values(value)) deepFreeze(child);\n\treturn Object.freeze(value);\n}\n\n/** One immutable load of models.json. */\nexport class ModelConfig {\n\tprivate readonly providers: ReadonlyMap<string, ModelsJsonProvider>;\n\tprivate readonly roles: ReadonlyMap<string, readonly string[]>;\n\tprivate readonly error: string | undefined;\n\n\tprivate constructor(\n\t\tproviders: ReadonlyMap<string, ModelsJsonProvider>,\n\t\troles: ReadonlyMap<string, readonly string[]> = new Map(),\n\t\terror?: string,\n\t) {\n\t\tthis.providers = providers;\n\t\tthis.roles = roles;\n\t\tthis.error = error;\n\t}\n\n\tstatic async load(modelsJsonPath: string | undefined): Promise<ModelConfig> {\n\t\tif (!modelsJsonPath) return new ModelConfig(new Map());\n\t\tconst path = normalizePath(modelsJsonPath);\n\t\tlet content: string;\n\t\ttry {\n\t\t\tcontent = await readFile(path, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return new ModelConfig(new Map());\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to load models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(stripJsonComments(content));\n\t\t} catch (error) {\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to parse models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tif (!validateModelsConfig.Check(parsed)) {\n\t\t\tconst errors =\n\t\t\t\tvalidateModelsConfig\n\t\t\t\t\t.Errors(parsed)\n\t\t\t\t\t.map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)\n\t\t\t\t\t.join(\"\\n\") || \"Unknown schema error\";\n\t\t\treturn new ModelConfig(new Map(), new Map(), `Invalid models.json schema:\\n${errors}\\n\\nFile: ${path}`);\n\t\t}\n\n\t\tconst config = parsed as ModelsJson;\n\t\tconst providers = new Map<string, ModelsJsonProvider>();\n\t\tfor (const [providerId, provider] of Object.entries(config.providers)) {\n\t\t\tproviders.set(providerId, deepFreeze(structuredClone(provider)));\n\t\t}\n\t\tconst roles = new Map<string, readonly string[]>();\n\t\tfor (const [roleName, role] of Object.entries(config.roles ?? {})) {\n\t\t\troles.set(roleName, Object.freeze([...role.models]));\n\t\t}\n\t\treturn new ModelConfig(providers, roles);\n\t}\n\n\tgetProvider(providerId: string): ModelsJsonProvider | undefined {\n\t\treturn this.providers.get(providerId);\n\t}\n\n\tgetProviderIds(): readonly string[] {\n\t\treturn [...this.providers.keys()];\n\t}\n\n\t/** Additive role -> ordered \"provider/modelId\" candidate references, unresolved. */\n\tgetRoles(): ReadonlyMap<string, readonly string[]> {\n\t\treturn this.roles;\n\t}\n\n\tgetError(): string | undefined {\n\t\treturn this.error;\n\t}\n}\n"]}
1
+ {"version":3,"file":"model-config.d.ts","sourceRoot":"","sources":["../../src/core/model-config.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAGxD,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AA2J5C,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAczB,CAAC;AAEH,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBvB,CAAC;AAEH,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWxB,CAAC;AAEH,QAAA,MAAM,oBAAoB;IACzB,0EAA0E;;EAEzE,CAAC;AASH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACnE,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACzE,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACrE,MAAM,MAAM,wBAAwB,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAsB3E,yCAAyC;AACzC,qBAAa,WAAW;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0C;IACpE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyC;IAC/D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAE3C,OAAO,eAQN;IAED,OAAa,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CA6C1E;IAED,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAE9D;IAED,cAAc,IAAI,SAAS,MAAM,EAAE,CAElC;IAED,oFAAoF;IACpF,QAAQ,IAAI,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAEjD;IAED,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7B;CACD","sourcesContent":["/** Immutable, credential-blind models.json snapshot. */\n\nimport { readFile } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { Compile } from \"typebox/compile\";\nimport type { TLocalizedValidationError } from \"typebox/error\";\nimport { stripJsonComments } from \"../utils/json.ts\";\nimport { normalizePath } from \"../utils/paths.ts\";\nimport { stripBom } from \"../utils/text.ts\";\n\nconst PercentileCutoffsSchema = Type.Object({\n\tp50: Type.Optional(Type.Number()),\n\tp75: Type.Optional(Type.Number()),\n\tp90: Type.Optional(Type.Number()),\n\tp99: Type.Optional(Type.Number()),\n});\n\nconst OpenRouterRoutingSchema = Type.Object({\n\tallow_fallbacks: Type.Optional(Type.Boolean()),\n\trequire_parameters: Type.Optional(Type.Boolean()),\n\tdata_collection: Type.Optional(Type.Union([Type.Literal(\"deny\"), Type.Literal(\"allow\")])),\n\tzdr: Type.Optional(Type.Boolean()),\n\tenforce_distillable_text: Type.Optional(Type.Boolean()),\n\torder: Type.Optional(Type.Array(Type.String())),\n\tonly: Type.Optional(Type.Array(Type.String())),\n\tignore: Type.Optional(Type.Array(Type.String())),\n\tquantizations: Type.Optional(Type.Array(Type.String())),\n\tsort: Type.Optional(\n\t\tType.Union([\n\t\t\tType.String(),\n\t\t\tType.Object({\n\t\t\t\tby: Type.Optional(Type.String()),\n\t\t\t\tpartition: Type.Optional(Type.Union([Type.String(), Type.Null()])),\n\t\t\t}),\n\t\t]),\n\t),\n\tmax_price: Type.Optional(\n\t\tType.Object({\n\t\t\tprompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\tcompletion: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\timage: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\taudio: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\trequest: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t}),\n\t),\n\tpreferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n\tpreferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n});\n\nconst VercelGatewayRoutingSchema = Type.Object({\n\tonly: Type.Optional(Type.Array(Type.String())),\n\torder: Type.Optional(Type.Array(Type.String())),\n});\n\nconst ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]);\nconst ThinkingLevelMapSchema = Type.Object({\n\toff: Type.Optional(ThinkingLevelMapValueSchema),\n\tminimal: Type.Optional(ThinkingLevelMapValueSchema),\n\tlow: Type.Optional(ThinkingLevelMapValueSchema),\n\tmedium: Type.Optional(ThinkingLevelMapValueSchema),\n\thigh: Type.Optional(ThinkingLevelMapValueSchema),\n\txhigh: Type.Optional(ThinkingLevelMapValueSchema),\n\tmax: Type.Optional(ThinkingLevelMapValueSchema),\n});\n\nconst ChatTemplateKwargScalarSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean(), Type.Null()]);\nconst ChatTemplateKwargVariableSchema = Type.Object({\n\t$var: Type.Union([Type.Literal(\"thinking.enabled\"), Type.Literal(\"thinking.effort\")]),\n\tomitWhenOff: Type.Optional(Type.Boolean()),\n});\nconst ChatTemplateKwargSchema = Type.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]);\n\nconst OpenAICompletionsCompatSchema = Type.Object({\n\tsupportsStore: Type.Optional(Type.Boolean()),\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsupportsReasoningEffort: Type.Optional(Type.Boolean()),\n\tsupportsUsageInStreaming: Type.Optional(Type.Boolean()),\n\tsupportsFinishReason: Type.Optional(Type.Boolean()),\n\tmaxTokensField: Type.Optional(Type.Union([Type.Literal(\"max_completion_tokens\"), Type.Literal(\"max_tokens\")])),\n\trequiresToolResultName: Type.Optional(Type.Boolean()),\n\trequiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),\n\trequiresThinkingAsText: Type.Optional(Type.Boolean()),\n\trequiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),\n\tthinkingFormat: Type.Optional(\n\t\tType.Union([\n\t\t\tType.Literal(\"openai\"),\n\t\t\tType.Literal(\"openrouter\"),\n\t\t\tType.Literal(\"together\"),\n\t\t\tType.Literal(\"baseten\"),\n\t\t\tType.Literal(\"deepseek\"),\n\t\t\tType.Literal(\"zai\"),\n\t\t\tType.Literal(\"qwen\"),\n\t\t\tType.Literal(\"chat-template\"),\n\t\t\tType.Literal(\"qwen-chat-template\"),\n\t\t\tType.Literal(\"string-thinking\"),\n\t\t\tType.Literal(\"ant-ling\"),\n\t\t]),\n\t),\n\tchatTemplateKwargs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tchatTemplateArgs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tcacheControlFormat: Type.Optional(Type.Literal(\"anthropic\")),\n\topenRouterRouting: Type.Optional(OpenRouterRoutingSchema),\n\tvercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tdeferredToolsMode: Type.Optional(Type.Literal(\"kimi\")),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n});\n\nconst OpenAIResponsesCompatSchema = Type.Object({\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsAdditionalTools: Type.Optional(Type.Boolean()),\n\tsupportsToolSearch: Type.Optional(Type.Boolean()),\n});\n\nconst AnthropicMessagesCompatSchema = Type.Object({\n\tsupportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tsupportsCacheControlOnTools: Type.Optional(Type.Boolean()),\n\tsupportsTemperature: Type.Optional(Type.Boolean()),\n\tforceAdaptiveThinking: Type.Optional(Type.Boolean()),\n\tallowEmptySignature: Type.Optional(Type.Boolean()),\n\tsupportsStrictTools: Type.Optional(Type.Boolean()),\n\tsupportsToolReferences: Type.Optional(Type.Boolean()),\n});\n\nconst ProviderCompatSchema = Type.Union([\n\tOpenAICompletionsCompatSchema,\n\tOpenAIResponsesCompatSchema,\n\tAnthropicMessagesCompatSchema,\n]);\n\nconst ModelCostRatesSchema = {\n\tinput: Type.Number(),\n\toutput: Type.Number(),\n\tcacheRead: Type.Number(),\n\tcacheWrite: Type.Number(),\n};\nconst ModelCostTierSchema = Type.Object({\n\tinputTokensAbove: Type.Number(),\n\t...ModelCostRatesSchema,\n});\nconst ModelCostSchema = Type.Object({\n\t...ModelCostRatesSchema,\n\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n});\n\nconst ModelDefinitionSchema = Type.Object({\n\tid: Type.String({ minLength: 1 }),\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(ModelCostSchema),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ModelOverrideSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(\n\t\tType.Object({\n\t\t\tinput: Type.Optional(Type.Number()),\n\t\t\toutput: Type.Optional(Type.Number()),\n\t\t\tcacheRead: Type.Optional(Type.Number()),\n\t\t\tcacheWrite: Type.Optional(Type.Number()),\n\t\t\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n\t\t}),\n\t),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ProviderConfigSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\tapiKey: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\toauth: Type.Optional(Type.Literal(\"radius\")),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n\tauthHeader: Type.Optional(Type.Boolean()),\n\tmodels: Type.Optional(Type.Array(ModelDefinitionSchema)),\n\tmodelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema)),\n});\n\nconst RoleDefinitionSchema = Type.Object({\n\t/** Ordered, non-empty list of canonical \"provider/modelId\" candidates. */\n\tmodels: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),\n});\n\nconst ModelsConfigSchema = Type.Object({\n\tproviders: Type.Record(Type.String(), ProviderConfigSchema),\n\t/** Additive, credential-blind role -> ordered model-candidate mapping. */\n\troles: Type.Optional(Type.Record(Type.String(), RoleDefinitionSchema)),\n});\nconst validateModelsConfig = Compile(ModelsConfigSchema);\n\nexport type ModelsJsonModel = Static<typeof ModelDefinitionSchema>;\nexport type ModelsJsonModelOverride = Static<typeof ModelOverrideSchema>;\nexport type ModelsJsonProvider = Static<typeof ProviderConfigSchema>;\nexport type ModelsJsonRoleDefinition = Static<typeof RoleDefinitionSchema>;\ntype ModelsJson = Static<typeof ModelsConfigSchema>;\n\nfunction formatValidationPath(error: TLocalizedValidationError): string {\n\tif (error.keyword === \"required\") {\n\t\tconst requiredProperties = (error.params as { requiredProperties?: string[] }).requiredProperties;\n\t\tconst requiredProperty = requiredProperties?.[0];\n\t\tif (requiredProperty) {\n\t\t\tconst basePath = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\t\t\treturn basePath ? `${basePath}.${requiredProperty}` : requiredProperty;\n\t\t}\n\t}\n\tconst path = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\treturn path || \"root\";\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n\tfor (const child of Object.values(value)) deepFreeze(child);\n\treturn Object.freeze(value);\n}\n\n/** One immutable load of models.json. */\nexport class ModelConfig {\n\tprivate readonly providers: ReadonlyMap<string, ModelsJsonProvider>;\n\tprivate readonly roles: ReadonlyMap<string, readonly string[]>;\n\tprivate readonly error: string | undefined;\n\n\tprivate constructor(\n\t\tproviders: ReadonlyMap<string, ModelsJsonProvider>,\n\t\troles: ReadonlyMap<string, readonly string[]> = new Map(),\n\t\terror?: string,\n\t) {\n\t\tthis.providers = providers;\n\t\tthis.roles = roles;\n\t\tthis.error = error;\n\t}\n\n\tstatic async load(modelsJsonPath: string | undefined): Promise<ModelConfig> {\n\t\tif (!modelsJsonPath) return new ModelConfig(new Map());\n\t\tconst path = normalizePath(modelsJsonPath);\n\t\tlet content: string;\n\t\ttry {\n\t\t\tcontent = await readFile(path, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return new ModelConfig(new Map());\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to load models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(stripJsonComments(stripBom(content)));\n\t\t} catch (error) {\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to parse models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tif (!validateModelsConfig.Check(parsed)) {\n\t\t\tconst errors =\n\t\t\t\tvalidateModelsConfig\n\t\t\t\t\t.Errors(parsed)\n\t\t\t\t\t.map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)\n\t\t\t\t\t.join(\"\\n\") || \"Unknown schema error\";\n\t\t\treturn new ModelConfig(new Map(), new Map(), `Invalid models.json schema:\\n${errors}\\n\\nFile: ${path}`);\n\t\t}\n\n\t\tconst config = parsed as ModelsJson;\n\t\tconst providers = new Map<string, ModelsJsonProvider>();\n\t\tfor (const [providerId, provider] of Object.entries(config.providers)) {\n\t\t\tproviders.set(providerId, deepFreeze(structuredClone(provider)));\n\t\t}\n\t\tconst roles = new Map<string, readonly string[]>();\n\t\tfor (const [roleName, role] of Object.entries(config.roles ?? {})) {\n\t\t\troles.set(roleName, Object.freeze([...role.models]));\n\t\t}\n\t\treturn new ModelConfig(providers, roles);\n\t}\n\n\tgetProvider(providerId: string): ModelsJsonProvider | undefined {\n\t\treturn this.providers.get(providerId);\n\t}\n\n\tgetProviderIds(): readonly string[] {\n\t\treturn [...this.providers.keys()];\n\t}\n\n\t/** Additive role -> ordered \"provider/modelId\" candidate references, unresolved. */\n\tgetRoles(): ReadonlyMap<string, readonly string[]> {\n\t\treturn this.roles;\n\t}\n\n\tgetError(): string | undefined {\n\t\treturn this.error;\n\t}\n}\n"]}
@@ -4,6 +4,7 @@ import { Type } from "typebox";
4
4
  import { Compile } from "typebox/compile";
5
5
  import { stripJsonComments } from "../utils/json.js";
6
6
  import { normalizePath } from "../utils/paths.js";
7
+ import { stripBom } from "../utils/text.js";
7
8
  const PercentileCutoffsSchema = Type.Object({
8
9
  p50: Type.Optional(Type.Number()),
9
10
  p75: Type.Optional(Type.Number()),
@@ -62,6 +63,7 @@ const OpenAICompletionsCompatSchema = Type.Object({
62
63
  supportsDeveloperRole: Type.Optional(Type.Boolean()),
63
64
  supportsReasoningEffort: Type.Optional(Type.Boolean()),
64
65
  supportsUsageInStreaming: Type.Optional(Type.Boolean()),
66
+ supportsFinishReason: Type.Optional(Type.Boolean()),
65
67
  maxTokensField: Type.Optional(Type.Union([Type.Literal("max_completion_tokens"), Type.Literal("max_tokens")])),
66
68
  requiresToolResultName: Type.Optional(Type.Boolean()),
67
69
  requiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),
@@ -98,6 +100,7 @@ const OpenAIResponsesCompatSchema = Type.Object({
98
100
  supportsLongCacheRetention: Type.Optional(Type.Boolean()),
99
101
  supportsStrictMode: Type.Optional(Type.Boolean()),
100
102
  supportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),
103
+ supportsAdditionalTools: Type.Optional(Type.Boolean()),
101
104
  supportsToolSearch: Type.Optional(Type.Boolean()),
102
105
  });
103
106
  const AnthropicMessagesCompatSchema = Type.Object({
@@ -229,7 +232,7 @@ export class ModelConfig {
229
232
  }
230
233
  let parsed;
231
234
  try {
232
- parsed = JSON.parse(stripJsonComments(content));
235
+ parsed = JSON.parse(stripJsonComments(stripBom(content)));
233
236
  }
234
237
  catch (error) {
235
238
  return new ModelConfig(new Map(), new Map(), `Failed to parse models.json: ${error instanceof Error ? error.message : error}\n\nFile: ${path}`);