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

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 (256) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/README.md +5 -0
  3. package/dist/cli/args.d.ts +3 -1
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +15 -0
  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.d.ts.map +1 -1
  12. package/dist/cli.js +1 -2
  13. package/dist/cli.js.map +1 -1
  14. package/dist/core/agent-session-services.d.ts.map +1 -1
  15. package/dist/core/agent-session-services.js +20 -0
  16. package/dist/core/agent-session-services.js.map +1 -1
  17. package/dist/core/agent-session.d.ts +15 -2
  18. package/dist/core/agent-session.d.ts.map +1 -1
  19. package/dist/core/agent-session.js +9 -6
  20. package/dist/core/agent-session.js.map +1 -1
  21. package/dist/core/auth-storage.d.ts +4 -1
  22. package/dist/core/auth-storage.d.ts.map +1 -1
  23. package/dist/core/auth-storage.js +6 -2
  24. package/dist/core/auth-storage.js.map +1 -1
  25. package/dist/core/bash-executor.d.ts.map +1 -1
  26. package/dist/core/bash-executor.js +10 -9
  27. package/dist/core/bash-executor.js.map +1 -1
  28. package/dist/core/experimental.d.ts +4 -0
  29. package/dist/core/experimental.d.ts.map +1 -1
  30. package/dist/core/experimental.js +4 -0
  31. package/dist/core/experimental.js.map +1 -1
  32. package/dist/core/extensions/types.d.ts +4 -0
  33. package/dist/core/extensions/types.d.ts.map +1 -1
  34. package/dist/core/extensions/types.js.map +1 -1
  35. package/dist/core/http-dispatcher.d.ts +1 -2
  36. package/dist/core/http-dispatcher.d.ts.map +1 -1
  37. package/dist/core/http-dispatcher.js +2 -17
  38. package/dist/core/http-dispatcher.js.map +1 -1
  39. package/dist/core/http-idle-timeout.d.ts +12 -0
  40. package/dist/core/http-idle-timeout.d.ts.map +1 -0
  41. package/dist/core/http-idle-timeout.js +27 -0
  42. package/dist/core/http-idle-timeout.js.map +1 -0
  43. package/dist/core/keybindings.d.ts +24 -0
  44. package/dist/core/keybindings.d.ts.map +1 -1
  45. package/dist/core/lsp/client.d.ts +2 -0
  46. package/dist/core/lsp/client.d.ts.map +1 -1
  47. package/dist/core/lsp/client.js +27 -2
  48. package/dist/core/lsp/client.js.map +1 -1
  49. package/dist/core/model-config.d.ts +5 -0
  50. package/dist/core/model-config.d.ts.map +1 -1
  51. package/dist/core/model-config.js +1 -0
  52. package/dist/core/model-config.js.map +1 -1
  53. package/dist/core/sandbox/child-entry.d.ts.map +1 -1
  54. package/dist/core/sandbox/child-entry.js +8 -1
  55. package/dist/core/sandbox/child-entry.js.map +1 -1
  56. package/dist/core/sandbox/cli-launch.d.ts +3 -0
  57. package/dist/core/sandbox/cli-launch.d.ts.map +1 -1
  58. package/dist/core/sandbox/cli-launch.js +25 -4
  59. package/dist/core/sandbox/cli-launch.js.map +1 -1
  60. package/dist/core/sandbox/cli-supervisor.d.ts.map +1 -1
  61. package/dist/core/sandbox/cli-supervisor.js +53 -13
  62. package/dist/core/sandbox/cli-supervisor.js.map +1 -1
  63. package/dist/core/sandbox/linux-backend.d.ts.map +1 -1
  64. package/dist/core/sandbox/linux-backend.js +15 -0
  65. package/dist/core/sandbox/linux-backend.js.map +1 -1
  66. package/dist/core/sandbox/macos-backend.d.ts.map +1 -1
  67. package/dist/core/sandbox/macos-backend.js +24 -1
  68. package/dist/core/sandbox/macos-backend.js.map +1 -1
  69. package/dist/core/sandbox/rpc/credential-client.d.ts +20 -0
  70. package/dist/core/sandbox/rpc/credential-client.d.ts.map +1 -0
  71. package/dist/core/sandbox/rpc/credential-client.js +170 -0
  72. package/dist/core/sandbox/rpc/credential-client.js.map +1 -0
  73. package/dist/core/sandbox/rpc/credential-proxy.d.ts +44 -0
  74. package/dist/core/sandbox/rpc/credential-proxy.d.ts.map +1 -0
  75. package/dist/core/sandbox/rpc/credential-proxy.js +381 -0
  76. package/dist/core/sandbox/rpc/credential-proxy.js.map +1 -0
  77. package/dist/core/sandbox/supervisor.d.ts +11 -0
  78. package/dist/core/sandbox/supervisor.d.ts.map +1 -1
  79. package/dist/core/sandbox/supervisor.js.map +1 -1
  80. package/dist/core/sandbox/terminal-size.d.ts +40 -0
  81. package/dist/core/sandbox/terminal-size.d.ts.map +1 -0
  82. package/dist/core/sandbox/terminal-size.js +105 -0
  83. package/dist/core/sandbox/terminal-size.js.map +1 -0
  84. package/dist/core/sdk.d.ts +6 -3
  85. package/dist/core/sdk.d.ts.map +1 -1
  86. package/dist/core/sdk.js +16 -4
  87. package/dist/core/sdk.js.map +1 -1
  88. package/dist/core/session-lease.d.ts +31 -0
  89. package/dist/core/session-lease.d.ts.map +1 -0
  90. package/dist/core/session-lease.js +138 -0
  91. package/dist/core/session-lease.js.map +1 -0
  92. package/dist/core/session-manager.d.ts +5 -0
  93. package/dist/core/session-manager.d.ts.map +1 -1
  94. package/dist/core/session-manager.js +3 -3
  95. package/dist/core/session-manager.js.map +1 -1
  96. package/dist/core/settings-manager.d.ts +26 -0
  97. package/dist/core/settings-manager.d.ts.map +1 -1
  98. package/dist/core/settings-manager.js +42 -3
  99. package/dist/core/settings-manager.js.map +1 -1
  100. package/dist/core/slash-commands.d.ts.map +1 -1
  101. package/dist/core/slash-commands.js +2 -0
  102. package/dist/core/slash-commands.js.map +1 -1
  103. package/dist/core/system-prompt.d.ts +2 -2
  104. package/dist/core/system-prompt.d.ts.map +1 -1
  105. package/dist/core/system-prompt.js +47 -62
  106. package/dist/core/system-prompt.js.map +1 -1
  107. package/dist/core/tools/bash.d.ts.map +1 -1
  108. package/dist/core/tools/bash.js +2 -0
  109. package/dist/core/tools/bash.js.map +1 -1
  110. package/dist/core/tools/delegate.d.ts.map +1 -1
  111. package/dist/core/tools/delegate.js +24 -0
  112. package/dist/core/tools/delegate.js.map +1 -1
  113. package/dist/core/tools/edit.d.ts.map +1 -1
  114. package/dist/core/tools/edit.js +2 -0
  115. package/dist/core/tools/edit.js.map +1 -1
  116. package/dist/core/tools/find.d.ts.map +1 -1
  117. package/dist/core/tools/find.js +1 -1
  118. package/dist/core/tools/find.js.map +1 -1
  119. package/dist/core/tools/grep.d.ts +2 -0
  120. package/dist/core/tools/grep.d.ts.map +1 -1
  121. package/dist/core/tools/grep.js +35 -10
  122. package/dist/core/tools/grep.js.map +1 -1
  123. package/dist/core/tools/ls.d.ts +2 -0
  124. package/dist/core/tools/ls.d.ts.map +1 -1
  125. package/dist/core/tools/ls.js +5 -1
  126. package/dist/core/tools/ls.js.map +1 -1
  127. package/dist/core/tools/read.d.ts.map +1 -1
  128. package/dist/core/tools/read.js +2 -0
  129. package/dist/core/tools/read.js.map +1 -1
  130. package/dist/core/tools/web-search-exa.d.ts +33 -0
  131. package/dist/core/tools/web-search-exa.d.ts.map +1 -0
  132. package/dist/core/tools/web-search-exa.js +128 -0
  133. package/dist/core/tools/web-search-exa.js.map +1 -0
  134. package/dist/core/tools/write.d.ts.map +1 -1
  135. package/dist/core/tools/write.js +2 -0
  136. package/dist/core/tools/write.js.map +1 -1
  137. package/dist/core/web-search-provider.d.ts +64 -0
  138. package/dist/core/web-search-provider.d.ts.map +1 -0
  139. package/dist/core/web-search-provider.js +149 -0
  140. package/dist/core/web-search-provider.js.map +1 -0
  141. package/dist/index.d.ts +1 -1
  142. package/dist/index.d.ts.map +1 -1
  143. package/dist/index.js.map +1 -1
  144. package/dist/main.d.ts +1 -0
  145. package/dist/main.d.ts.map +1 -1
  146. package/dist/main.js +20 -1
  147. package/dist/main.js.map +1 -1
  148. package/dist/modes/interactive/components/custom-editor.d.ts +23 -0
  149. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  150. package/dist/modes/interactive/components/custom-editor.js +105 -2
  151. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  152. package/dist/modes/interactive/components/dynamic-border.d.ts +7 -1
  153. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  154. package/dist/modes/interactive/components/dynamic-border.js +11 -2
  155. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  156. package/dist/modes/interactive/components/extension-selector.d.ts +4 -0
  157. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  158. package/dist/modes/interactive/components/extension-selector.js +24 -6
  159. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  160. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  161. package/dist/modes/interactive/components/first-time-setup.js +6 -3
  162. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  163. package/dist/modes/interactive/components/first-use-hints.d.ts +8 -0
  164. package/dist/modes/interactive/components/first-use-hints.d.ts.map +1 -0
  165. package/dist/modes/interactive/components/first-use-hints.js +22 -0
  166. package/dist/modes/interactive/components/first-use-hints.js.map +1 -0
  167. package/dist/modes/interactive/components/footer.d.ts +12 -0
  168. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  169. package/dist/modes/interactive/components/footer.js +128 -9
  170. package/dist/modes/interactive/components/footer.js.map +1 -1
  171. package/dist/modes/interactive/components/index.d.ts +1 -0
  172. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  173. package/dist/modes/interactive/components/index.js +1 -0
  174. package/dist/modes/interactive/components/index.js.map +1 -1
  175. package/dist/modes/interactive/components/model-selector.d.ts +2 -0
  176. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  177. package/dist/modes/interactive/components/model-selector.js +20 -5
  178. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  179. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  180. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  181. package/dist/modes/interactive/components/settings-selector.js +10 -0
  182. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  183. package/dist/modes/interactive/components/splash-header.d.ts +29 -4
  184. package/dist/modes/interactive/components/splash-header.d.ts.map +1 -1
  185. package/dist/modes/interactive/components/splash-header.js +58 -23
  186. package/dist/modes/interactive/components/splash-header.js.map +1 -1
  187. package/dist/modes/interactive/components/tool-execution.d.ts +14 -0
  188. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  189. package/dist/modes/interactive/components/tool-execution.js +113 -35
  190. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  191. package/dist/modes/interactive/components/tool-panel.d.ts +30 -0
  192. package/dist/modes/interactive/components/tool-panel.d.ts.map +1 -0
  193. package/dist/modes/interactive/components/tool-panel.js +130 -0
  194. package/dist/modes/interactive/components/tool-panel.js.map +1 -0
  195. package/dist/modes/interactive/interactive-mode.d.ts +44 -9
  196. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  197. package/dist/modes/interactive/interactive-mode.js +282 -70
  198. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  199. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  200. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  201. package/dist/modes/interactive/model-catalog-refresh.js +34 -0
  202. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  203. package/dist/modes/interactive/theme/apex.json +62 -63
  204. package/dist/modes/interactive/theme/dark.json +2 -0
  205. package/dist/modes/interactive/theme/light.json +2 -0
  206. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  207. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  208. package/dist/modes/interactive/theme/theme-controller.js +25 -11
  209. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  210. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  211. package/dist/modes/interactive/theme/theme.d.ts +14 -3
  212. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  213. package/dist/modes/interactive/theme/theme.js +55 -6
  214. package/dist/modes/interactive/theme/theme.js.map +1 -1
  215. package/dist/modes/json-event.d.ts +4 -1
  216. package/dist/modes/json-event.d.ts.map +1 -1
  217. package/dist/modes/json-event.js +5 -2
  218. package/dist/modes/json-event.js.map +1 -1
  219. package/dist/server/create-harness.d.ts.map +1 -1
  220. package/dist/server/create-harness.js +2 -0
  221. package/dist/server/create-harness.js.map +1 -1
  222. package/dist/themes/apex-logo.d.ts +36 -16
  223. package/dist/themes/apex-logo.d.ts.map +1 -1
  224. package/dist/themes/apex-logo.js +32 -28
  225. package/dist/themes/apex-logo.js.map +1 -1
  226. package/dist/utils/tools-manager.d.ts +10 -1
  227. package/dist/utils/tools-manager.d.ts.map +1 -1
  228. package/dist/utils/tools-manager.js +15 -20
  229. package/dist/utils/tools-manager.js.map +1 -1
  230. package/docs/compaction.md +3 -3
  231. package/docs/custom-provider.md +1 -1
  232. package/docs/environment-variables.md +1 -0
  233. package/docs/extensions.md +4 -0
  234. package/docs/json.md +6 -4
  235. package/docs/keybindings.md +8 -2
  236. package/docs/rpc.md +15 -4
  237. package/docs/sdk.md +9 -0
  238. package/docs/settings.md +63 -0
  239. package/docs/terminal-setup.md +23 -2
  240. package/docs/themes.md +24 -3
  241. package/docs/tui.md +2 -2
  242. package/docs/usage.md +3 -2
  243. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  244. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  245. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  246. package/examples/extensions/gondolin/package-lock.json +2 -2
  247. package/examples/extensions/gondolin/package.json +1 -1
  248. package/examples/extensions/sandbox/package-lock.json +2 -2
  249. package/examples/extensions/sandbox/package.json +1 -1
  250. package/examples/extensions/subagent/README.md +2 -0
  251. package/examples/extensions/subagent/agents.ts +40 -9
  252. package/examples/extensions/subagent/index.ts +21 -3
  253. package/examples/extensions/with-deps/package-lock.json +2 -2
  254. package/examples/extensions/with-deps/package.json +1 -1
  255. package/npm-shrinkwrap.json +27 -78
  256. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"keybindings.d.ts","sourceRoot":"","sources":["../../src/core/keybindings.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Keybinding,\n\ttype KeybindingDefinitions,\n\ttype KeybindingsConfig,\n\ttype KeyId,\n\tTUI_KEYBINDINGS,\n\tKeybindingsManager as TuiKeybindingsManager,\n} from \"@earendil-works/pi-tui\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { getAgentDir } from \"../config.ts\";\n\nexport interface AppKeybindings {\n\t\"app.interrupt\": true;\n\t\"app.clear\": true;\n\t\"app.exit\": true;\n\t\"app.suspend\": true;\n\t\"app.thinking.cycle\": true;\n\t\"app.model.cycleForward\": true;\n\t\"app.model.cycleBackward\": true;\n\t\"app.model.select\": true;\n\t\"app.tools.expand\": true;\n\t\"app.thinking.toggle\": true;\n\t\"app.session.toggleNamedFilter\": true;\n\t\"app.editor.external\": true;\n\t\"app.message.copy\": true;\n\t\"app.message.followUp\": true;\n\t\"app.message.dequeue\": true;\n\t\"app.clipboard.pasteImage\": true;\n\t\"app.session.new\": true;\n\t\"app.session.tree\": true;\n\t\"app.session.fork\": true;\n\t\"app.session.resume\": true;\n\t\"app.tree.foldOrUp\": true;\n\t\"app.tree.unfoldOrDown\": true;\n\t\"app.tree.editLabel\": true;\n\t\"app.tree.toggleLabelTimestamp\": true;\n\t\"app.session.togglePath\": true;\n\t\"app.session.toggleSort\": true;\n\t\"app.session.rename\": true;\n\t\"app.session.delete\": true;\n\t\"app.session.deleteNoninvasive\": true;\n\t\"app.models.save\": true;\n\t\"app.models.enableAll\": true;\n\t\"app.models.clearAll\": true;\n\t\"app.models.toggleProvider\": true;\n\t\"app.models.reorderUp\": true;\n\t\"app.models.reorderDown\": true;\n\t\"app.tree.filter.default\": true;\n\t\"app.tree.filter.noTools\": true;\n\t\"app.tree.filter.userOnly\": true;\n\t\"app.tree.filter.labeledOnly\": true;\n\t\"app.tree.filter.all\": true;\n\t\"app.tree.filter.cycleForward\": true;\n\t\"app.tree.filter.cycleBackward\": true;\n}\n\nexport type AppKeybinding = keyof AppKeybindings;\n\ndeclare module \"@earendil-works/pi-tui\" {\n\tinterface Keybindings extends AppKeybindings {}\n}\n\nexport const KEYBINDINGS = {\n\t...TUI_KEYBINDINGS,\n\t\"app.interrupt\": { defaultKeys: \"escape\", description: \"Cancel or abort\" },\n\t\"app.clear\": { defaultKeys: \"ctrl+c\", description: \"Clear editor\" },\n\t\"app.exit\": { defaultKeys: \"ctrl+d\", description: \"Exit when editor is empty\" },\n\t\"app.suspend\": {\n\t\tdefaultKeys: process.platform === \"win32\" ? [] : \"ctrl+z\",\n\t\tdescription: \"Suspend to background\",\n\t},\n\t\"app.thinking.cycle\": {\n\t\tdefaultKeys: \"shift+tab\",\n\t\tdescription: \"Cycle thinking level\",\n\t},\n\t\"app.model.cycleForward\": {\n\t\tdefaultKeys: \"ctrl+p\",\n\t\tdescription: \"Cycle to next model\",\n\t},\n\t\"app.model.cycleBackward\": {\n\t\tdefaultKeys: \"shift+ctrl+p\",\n\t\tdescription: \"Cycle to previous model\",\n\t},\n\t\"app.model.select\": { defaultKeys: \"ctrl+l\", description: \"Open model selector\" },\n\t\"app.tools.expand\": { defaultKeys: \"ctrl+o\", description: \"Toggle tool output\" },\n\t\"app.thinking.toggle\": {\n\t\tdefaultKeys: \"ctrl+t\",\n\t\tdescription: \"Toggle thinking blocks\",\n\t},\n\t\"app.session.toggleNamedFilter\": {\n\t\tdefaultKeys: \"ctrl+n\",\n\t\tdescription: \"Toggle named session filter\",\n\t},\n\t\"app.editor.external\": {\n\t\tdefaultKeys: \"ctrl+g\",\n\t\tdescription: \"Open external editor\",\n\t},\n\t\"app.message.copy\": {\n\t\tdefaultKeys: \"ctrl+x\",\n\t\tdescription: \"Copy message to clipboard\",\n\t},\n\t\"app.message.followUp\": {\n\t\tdefaultKeys: \"alt+enter\",\n\t\tdescription: \"Queue follow-up message\",\n\t},\n\t\"app.message.dequeue\": {\n\t\tdefaultKeys: \"alt+up\",\n\t\tdescription: \"Restore queued messages\",\n\t},\n\t\"app.clipboard.pasteImage\": {\n\t\tdefaultKeys: process.platform === \"win32\" ? \"alt+v\" : \"ctrl+v\",\n\t\tdescription: \"Paste image from clipboard (text fallback)\",\n\t},\n\t\"app.session.new\": { defaultKeys: [], description: \"Start a new session\" },\n\t\"app.session.tree\": { defaultKeys: [], description: \"Open session tree\" },\n\t\"app.session.fork\": { defaultKeys: [], description: \"Fork current session\" },\n\t\"app.session.resume\": { defaultKeys: [], description: \"Resume a session\" },\n\t\"app.tree.foldOrUp\": {\n\t\tdefaultKeys: process.platform === \"darwin\" ? [\"alt+left\", \"ctrl+left\"] : [\"ctrl+left\", \"alt+left\"],\n\t\tdescription: \"Fold tree branch or move up\",\n\t},\n\t\"app.tree.unfoldOrDown\": {\n\t\tdefaultKeys: process.platform === \"darwin\" ? [\"alt+right\", \"ctrl+right\"] : [\"ctrl+right\", \"alt+right\"],\n\t\tdescription: \"Unfold tree branch or move down\",\n\t},\n\t\"app.tree.editLabel\": {\n\t\tdefaultKeys: \"shift+l\",\n\t\tdescription: \"Edit tree label\",\n\t},\n\t\"app.tree.toggleLabelTimestamp\": {\n\t\tdefaultKeys: \"shift+t\",\n\t\tdescription: \"Toggle tree label timestamps\",\n\t},\n\t\"app.session.togglePath\": {\n\t\tdefaultKeys: \"ctrl+p\",\n\t\tdescription: \"Toggle session path display\",\n\t},\n\t\"app.session.toggleSort\": {\n\t\tdefaultKeys: \"ctrl+s\",\n\t\tdescription: \"Toggle session sort mode\",\n\t},\n\t\"app.session.rename\": {\n\t\tdefaultKeys: \"ctrl+r\",\n\t\tdescription: \"Rename session\",\n\t},\n\t\"app.session.delete\": {\n\t\tdefaultKeys: \"ctrl+d\",\n\t\tdescription: \"Delete session\",\n\t},\n\t\"app.session.deleteNoninvasive\": {\n\t\tdefaultKeys: \"ctrl+backspace\",\n\t\tdescription: \"Delete session when query is empty\",\n\t},\n\t\"app.models.save\": {\n\t\tdefaultKeys: \"ctrl+s\",\n\t\tdescription: \"Save model selection\",\n\t},\n\t\"app.models.enableAll\": {\n\t\tdefaultKeys: \"ctrl+a\",\n\t\tdescription: \"Enable all models\",\n\t},\n\t\"app.models.clearAll\": {\n\t\tdefaultKeys: \"ctrl+x\",\n\t\tdescription: \"Clear all models\",\n\t},\n\t\"app.models.toggleProvider\": {\n\t\tdefaultKeys: \"ctrl+p\",\n\t\tdescription: \"Toggle all models for provider\",\n\t},\n\t\"app.models.reorderUp\": {\n\t\tdefaultKeys: \"alt+up\",\n\t\tdescription: \"Move model up in order\",\n\t},\n\t\"app.models.reorderDown\": {\n\t\tdefaultKeys: \"alt+down\",\n\t\tdescription: \"Move model down in order\",\n\t},\n\t\"app.tree.filter.default\": {\n\t\tdefaultKeys: \"ctrl+d\",\n\t\tdescription: \"Tree filter: default view\",\n\t},\n\t\"app.tree.filter.noTools\": {\n\t\tdefaultKeys: \"ctrl+t\",\n\t\tdescription: \"Tree filter: hide tool results\",\n\t},\n\t\"app.tree.filter.userOnly\": {\n\t\tdefaultKeys: \"ctrl+u\",\n\t\tdescription: \"Tree filter: user messages only\",\n\t},\n\t\"app.tree.filter.labeledOnly\": {\n\t\tdefaultKeys: \"ctrl+l\",\n\t\tdescription: \"Tree filter: labeled entries only\",\n\t},\n\t\"app.tree.filter.all\": {\n\t\tdefaultKeys: \"ctrl+a\",\n\t\tdescription: \"Tree filter: show all entries\",\n\t},\n\t\"app.tree.filter.cycleForward\": {\n\t\tdefaultKeys: \"ctrl+o\",\n\t\tdescription: \"Tree filter: cycle forward\",\n\t},\n\t\"app.tree.filter.cycleBackward\": {\n\t\tdefaultKeys: \"shift+ctrl+o\",\n\t\tdescription: \"Tree filter: cycle backward\",\n\t},\n} as const satisfies KeybindingDefinitions;\n\nconst KEYBINDING_NAME_MIGRATIONS = {\n\tcursorUp: \"tui.editor.cursorUp\",\n\tcursorDown: \"tui.editor.cursorDown\",\n\tcursorLeft: \"tui.editor.cursorLeft\",\n\tcursorRight: \"tui.editor.cursorRight\",\n\tcursorWordLeft: \"tui.editor.cursorWordLeft\",\n\tcursorWordRight: \"tui.editor.cursorWordRight\",\n\tcursorLineStart: \"tui.editor.cursorLineStart\",\n\tcursorLineEnd: \"tui.editor.cursorLineEnd\",\n\tjumpForward: \"tui.editor.jumpForward\",\n\tjumpBackward: \"tui.editor.jumpBackward\",\n\tpageUp: \"tui.editor.pageUp\",\n\tpageDown: \"tui.editor.pageDown\",\n\tdeleteCharBackward: \"tui.editor.deleteCharBackward\",\n\tdeleteCharForward: \"tui.editor.deleteCharForward\",\n\tdeleteWordBackward: \"tui.editor.deleteWordBackward\",\n\tdeleteWordForward: \"tui.editor.deleteWordForward\",\n\tdeleteToLineStart: \"tui.editor.deleteToLineStart\",\n\tdeleteToLineEnd: \"tui.editor.deleteToLineEnd\",\n\tyank: \"tui.editor.yank\",\n\tyankPop: \"tui.editor.yankPop\",\n\tundo: \"tui.editor.undo\",\n\tnewLine: \"tui.input.newLine\",\n\tsubmit: \"tui.input.submit\",\n\ttab: \"tui.input.tab\",\n\tcopy: \"tui.input.copy\",\n\tselectUp: \"tui.select.up\",\n\tselectDown: \"tui.select.down\",\n\tselectPageUp: \"tui.select.pageUp\",\n\tselectPageDown: \"tui.select.pageDown\",\n\tselectConfirm: \"tui.select.confirm\",\n\tselectCancel: \"tui.select.cancel\",\n\tinterrupt: \"app.interrupt\",\n\tclear: \"app.clear\",\n\texit: \"app.exit\",\n\tsuspend: \"app.suspend\",\n\tcycleThinkingLevel: \"app.thinking.cycle\",\n\tcycleModelForward: \"app.model.cycleForward\",\n\tcycleModelBackward: \"app.model.cycleBackward\",\n\tselectModel: \"app.model.select\",\n\texpandTools: \"app.tools.expand\",\n\ttoggleThinking: \"app.thinking.toggle\",\n\ttoggleSessionNamedFilter: \"app.session.toggleNamedFilter\",\n\texternalEditor: \"app.editor.external\",\n\tfollowUp: \"app.message.followUp\",\n\tdequeue: \"app.message.dequeue\",\n\tpasteImage: \"app.clipboard.pasteImage\",\n\tnewSession: \"app.session.new\",\n\ttree: \"app.session.tree\",\n\tfork: \"app.session.fork\",\n\tresume: \"app.session.resume\",\n\ttreeFoldOrUp: \"app.tree.foldOrUp\",\n\ttreeUnfoldOrDown: \"app.tree.unfoldOrDown\",\n\ttreeEditLabel: \"app.tree.editLabel\",\n\ttreeToggleLabelTimestamp: \"app.tree.toggleLabelTimestamp\",\n\ttoggleSessionPath: \"app.session.togglePath\",\n\ttoggleSessionSort: \"app.session.toggleSort\",\n\trenameSession: \"app.session.rename\",\n\tdeleteSession: \"app.session.delete\",\n\tdeleteSessionNoninvasive: \"app.session.deleteNoninvasive\",\n} as const satisfies Record<string, Keybinding>;\n\nfunction isLegacyKeybindingName(key: string): key is keyof typeof KEYBINDING_NAME_MIGRATIONS {\n\treturn key in KEYBINDING_NAME_MIGRATIONS;\n}\n\nfunction toKeybindingsConfig(value: Record<string, unknown>): KeybindingsConfig {\n\tconst config: KeybindingsConfig = {};\n\tfor (const [key, binding] of Object.entries(value)) {\n\t\tif (typeof binding === \"string\") {\n\t\t\tconfig[key] = binding as KeyId;\n\t\t\tcontinue;\n\t\t}\n\t\tif (Array.isArray(binding) && binding.every((entry) => typeof entry === \"string\")) {\n\t\t\tconfig[key] = binding as KeyId[];\n\t\t}\n\t}\n\treturn config;\n}\n\nexport function migrateKeybindingsConfig(rawConfig: Record<string, unknown>): {\n\tconfig: Record<string, unknown>;\n\tmigrated: boolean;\n} {\n\tconst config: Record<string, unknown> = {};\n\tlet migrated = false;\n\n\tfor (const [key, value] of Object.entries(rawConfig)) {\n\t\tconst nextKey = isLegacyKeybindingName(key) ? KEYBINDING_NAME_MIGRATIONS[key] : key;\n\t\tif (nextKey !== key) {\n\t\t\tmigrated = true;\n\t\t}\n\t\tif (key !== nextKey && Object.hasOwn(rawConfig, nextKey)) {\n\t\t\tmigrated = true;\n\t\t\tcontinue;\n\t\t}\n\t\tconfig[nextKey] = value;\n\t}\n\n\treturn { config: orderKeybindingsConfig(config), migrated };\n}\n\nfunction orderKeybindingsConfig(config: Record<string, unknown>): Record<string, unknown> {\n\tconst ordered: Record<string, unknown> = {};\n\tfor (const keybinding of Object.keys(KEYBINDINGS)) {\n\t\tif (Object.hasOwn(config, keybinding)) {\n\t\t\tordered[keybinding] = config[keybinding];\n\t\t}\n\t}\n\n\tconst extras = Object.keys(config)\n\t\t.filter((key) => !Object.hasOwn(ordered, key))\n\t\t.sort();\n\tfor (const key of extras) {\n\t\tordered[key] = config[key];\n\t}\n\n\treturn ordered;\n}\n\nfunction loadRawConfig(path: string): Record<string, unknown> | undefined {\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(path, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null) return undefined;\n\t\treturn parsed as Record<string, unknown>;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport class KeybindingsManager extends TuiKeybindingsManager {\n\tprivate configPath: string | undefined;\n\n\tconstructor(userBindings: KeybindingsConfig = {}, configPath?: string) {\n\t\tsuper(KEYBINDINGS, userBindings);\n\t\tthis.configPath = configPath;\n\t}\n\n\tstatic create(agentDir: string = getAgentDir()): KeybindingsManager {\n\t\tconst configPath = join(agentDir, \"keybindings.json\");\n\t\tconst userBindings = KeybindingsManager.loadFromFile(configPath);\n\t\treturn new KeybindingsManager(userBindings, configPath);\n\t}\n\n\treload(): void {\n\t\tif (!this.configPath) return;\n\t\tthis.setUserBindings(KeybindingsManager.loadFromFile(this.configPath));\n\t}\n\n\tgetEffectiveConfig(): KeybindingsConfig {\n\t\treturn this.getResolvedBindings();\n\t}\n\n\tprivate static loadFromFile(path: string): KeybindingsConfig {\n\t\tconst rawConfig = loadRawConfig(path);\n\t\tif (!rawConfig) return {};\n\t\treturn toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config);\n\t}\n}\n\nexport type { Keybinding, KeyId, KeybindingsConfig };\n"]}
1
+ {"version":3,"file":"keybindings.d.ts","sourceRoot":"","sources":["../../src/core/keybindings.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Keybinding,\n\ttype KeybindingDefinitions,\n\ttype KeybindingsConfig,\n\ttype KeyId,\n\tTUI_KEYBINDINGS,\n\tKeybindingsManager as TuiKeybindingsManager,\n} from \"@earendil-works/pi-tui\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { getAgentDir } from \"../config.ts\";\n\nexport interface AppKeybindings {\n\t\"app.interrupt\": true;\n\t\"app.clear\": true;\n\t\"app.exit\": true;\n\t\"app.suspend\": true;\n\t\"app.thinking.cycle\": true;\n\t\"app.model.cycleForward\": true;\n\t\"app.model.cycleBackward\": true;\n\t\"app.model.select\": true;\n\t\"app.tools.expand\": true;\n\t\"app.thinking.toggle\": true;\n\t\"app.session.toggleNamedFilter\": true;\n\t\"app.editor.external\": true;\n\t\"app.message.copy\": true;\n\t\"app.message.followUp\": true;\n\t\"app.message.dequeue\": true;\n\t\"app.clipboard.pasteImage\": true;\n\t\"app.session.new\": true;\n\t\"app.session.tree\": true;\n\t\"app.session.fork\": true;\n\t\"app.session.resume\": true;\n\t\"app.tree.foldOrUp\": true;\n\t\"app.tree.unfoldOrDown\": true;\n\t\"app.tree.editLabel\": true;\n\t\"app.tree.toggleLabelTimestamp\": true;\n\t\"app.session.togglePath\": true;\n\t\"app.session.toggleSort\": true;\n\t\"app.session.rename\": true;\n\t\"app.session.delete\": true;\n\t\"app.session.deleteNoninvasive\": true;\n\t\"app.models.save\": true;\n\t\"app.models.enableAll\": true;\n\t\"app.models.clearAll\": true;\n\t\"app.models.toggleProvider\": true;\n\t\"app.models.reorderUp\": true;\n\t\"app.models.reorderDown\": true;\n\t\"app.tree.filter.default\": true;\n\t\"app.tree.filter.noTools\": true;\n\t\"app.tree.filter.userOnly\": true;\n\t\"app.tree.filter.labeledOnly\": true;\n\t\"app.tree.filter.all\": true;\n\t\"app.tree.filter.cycleForward\": true;\n\t\"app.tree.filter.cycleBackward\": true;\n}\n\nexport type AppKeybinding = keyof AppKeybindings;\n\ndeclare module \"@earendil-works/pi-tui\" {\n\tinterface Keybindings extends AppKeybindings {}\n}\n\nexport const KEYBINDINGS = {\n\t...TUI_KEYBINDINGS,\n\t\"app.interrupt\": { defaultKeys: \"escape\", description: \"Cancel or abort\" },\n\t\"app.clear\": { defaultKeys: \"ctrl+c\", description: \"Clear editor\" },\n\t\"app.exit\": { defaultKeys: \"ctrl+d\", description: \"Exit when editor is empty\" },\n\t\"app.suspend\": {\n\t\tdefaultKeys: process.platform === \"win32\" ? [] : \"ctrl+z\",\n\t\tdescription: \"Suspend to background\",\n\t},\n\t\"app.thinking.cycle\": {\n\t\tdefaultKeys: \"shift+tab\",\n\t\tdescription: \"Cycle thinking level\",\n\t},\n\t\"app.model.cycleForward\": {\n\t\tdefaultKeys: \"ctrl+p\",\n\t\tdescription: \"Cycle to next model\",\n\t},\n\t\"app.model.cycleBackward\": {\n\t\tdefaultKeys: \"shift+ctrl+p\",\n\t\tdescription: \"Cycle to previous model\",\n\t},\n\t\"app.model.select\": { defaultKeys: \"ctrl+l\", description: \"Open model selector\" },\n\t\"app.tools.expand\": { defaultKeys: \"ctrl+o\", description: \"Toggle tool output\" },\n\t\"app.thinking.toggle\": {\n\t\tdefaultKeys: \"ctrl+t\",\n\t\tdescription: \"Toggle thinking blocks\",\n\t},\n\t\"app.session.toggleNamedFilter\": {\n\t\tdefaultKeys: \"ctrl+n\",\n\t\tdescription: \"Toggle named session filter\",\n\t},\n\t\"app.editor.external\": {\n\t\tdefaultKeys: \"ctrl+g\",\n\t\tdescription: \"Open external editor\",\n\t},\n\t\"app.message.copy\": {\n\t\tdefaultKeys: \"ctrl+x\",\n\t\tdescription: \"Copy message to clipboard\",\n\t},\n\t\"app.message.followUp\": {\n\t\tdefaultKeys: \"alt+enter\",\n\t\tdescription: \"Queue follow-up message\",\n\t},\n\t\"app.message.dequeue\": {\n\t\tdefaultKeys: \"alt+up\",\n\t\tdescription: \"Restore queued messages\",\n\t},\n\t\"app.clipboard.pasteImage\": {\n\t\tdefaultKeys: process.platform === \"win32\" ? \"alt+v\" : \"ctrl+v\",\n\t\tdescription: \"Paste image from clipboard (text fallback)\",\n\t},\n\t\"app.session.new\": { defaultKeys: [], description: \"Start a new session\" },\n\t\"app.session.tree\": { defaultKeys: [], description: \"Open session tree\" },\n\t\"app.session.fork\": { defaultKeys: [], description: \"Fork current session\" },\n\t\"app.session.resume\": { defaultKeys: [], description: \"Resume a session\" },\n\t\"app.tree.foldOrUp\": {\n\t\tdefaultKeys: process.platform === \"darwin\" ? [\"alt+left\", \"ctrl+left\"] : [\"ctrl+left\", \"alt+left\"],\n\t\tdescription: \"Fold tree branch or move up\",\n\t},\n\t\"app.tree.unfoldOrDown\": {\n\t\tdefaultKeys: process.platform === \"darwin\" ? [\"alt+right\", \"ctrl+right\"] : [\"ctrl+right\", \"alt+right\"],\n\t\tdescription: \"Unfold tree branch or move down\",\n\t},\n\t\"app.tree.editLabel\": {\n\t\tdefaultKeys: \"shift+l\",\n\t\tdescription: \"Edit tree label\",\n\t},\n\t\"app.tree.toggleLabelTimestamp\": {\n\t\tdefaultKeys: \"shift+t\",\n\t\tdescription: \"Toggle tree label timestamps\",\n\t},\n\t\"app.session.togglePath\": {\n\t\tdefaultKeys: \"ctrl+p\",\n\t\tdescription: \"Toggle session path display\",\n\t},\n\t\"app.session.toggleSort\": {\n\t\tdefaultKeys: \"ctrl+s\",\n\t\tdescription: \"Toggle session sort mode\",\n\t},\n\t\"app.session.rename\": {\n\t\tdefaultKeys: \"ctrl+r\",\n\t\tdescription: \"Rename session\",\n\t},\n\t\"app.session.delete\": {\n\t\tdefaultKeys: \"ctrl+d\",\n\t\tdescription: \"Delete session\",\n\t},\n\t\"app.session.deleteNoninvasive\": {\n\t\tdefaultKeys: \"ctrl+backspace\",\n\t\tdescription: \"Delete session when query is empty\",\n\t},\n\t\"app.models.save\": {\n\t\tdefaultKeys: \"ctrl+s\",\n\t\tdescription: \"Save model selection\",\n\t},\n\t\"app.models.enableAll\": {\n\t\tdefaultKeys: \"ctrl+a\",\n\t\tdescription: \"Enable all models\",\n\t},\n\t\"app.models.clearAll\": {\n\t\tdefaultKeys: \"ctrl+x\",\n\t\tdescription: \"Clear all models\",\n\t},\n\t\"app.models.toggleProvider\": {\n\t\tdefaultKeys: \"ctrl+p\",\n\t\tdescription: \"Toggle all models for provider\",\n\t},\n\t\"app.models.reorderUp\": {\n\t\tdefaultKeys: \"alt+up\",\n\t\tdescription: \"Move model up in order\",\n\t},\n\t\"app.models.reorderDown\": {\n\t\tdefaultKeys: \"alt+down\",\n\t\tdescription: \"Move model down in order\",\n\t},\n\t\"app.tree.filter.default\": {\n\t\tdefaultKeys: \"ctrl+d\",\n\t\tdescription: \"Tree filter: default view\",\n\t},\n\t\"app.tree.filter.noTools\": {\n\t\tdefaultKeys: \"ctrl+t\",\n\t\tdescription: \"Tree filter: hide tool results\",\n\t},\n\t\"app.tree.filter.userOnly\": {\n\t\tdefaultKeys: \"ctrl+u\",\n\t\tdescription: \"Tree filter: user messages only\",\n\t},\n\t\"app.tree.filter.labeledOnly\": {\n\t\tdefaultKeys: \"ctrl+l\",\n\t\tdescription: \"Tree filter: labeled entries only\",\n\t},\n\t\"app.tree.filter.all\": {\n\t\tdefaultKeys: \"ctrl+a\",\n\t\tdescription: \"Tree filter: show all entries\",\n\t},\n\t\"app.tree.filter.cycleForward\": {\n\t\tdefaultKeys: \"ctrl+o\",\n\t\tdescription: \"Tree filter: cycle forward\",\n\t},\n\t\"app.tree.filter.cycleBackward\": {\n\t\tdefaultKeys: \"shift+ctrl+o\",\n\t\tdescription: \"Tree filter: cycle backward\",\n\t},\n} as const satisfies KeybindingDefinitions;\n\nconst KEYBINDING_NAME_MIGRATIONS = {\n\tcursorUp: \"tui.editor.cursorUp\",\n\tcursorDown: \"tui.editor.cursorDown\",\n\tcursorLeft: \"tui.editor.cursorLeft\",\n\tcursorRight: \"tui.editor.cursorRight\",\n\tcursorWordLeft: \"tui.editor.cursorWordLeft\",\n\tcursorWordRight: \"tui.editor.cursorWordRight\",\n\tcursorLineStart: \"tui.editor.cursorLineStart\",\n\tcursorLineEnd: \"tui.editor.cursorLineEnd\",\n\tjumpForward: \"tui.editor.jumpForward\",\n\tjumpBackward: \"tui.editor.jumpBackward\",\n\tpageUp: \"tui.editor.pageUp\",\n\tpageDown: \"tui.editor.pageDown\",\n\tdeleteCharBackward: \"tui.editor.deleteCharBackward\",\n\tdeleteCharForward: \"tui.editor.deleteCharForward\",\n\tdeleteWordBackward: \"tui.editor.deleteWordBackward\",\n\tdeleteWordForward: \"tui.editor.deleteWordForward\",\n\tdeleteToLineStart: \"tui.editor.deleteToLineStart\",\n\tdeleteToLineEnd: \"tui.editor.deleteToLineEnd\",\n\tyank: \"tui.editor.yank\",\n\tyankPop: \"tui.editor.yankPop\",\n\tundo: \"tui.editor.undo\",\n\tnewLine: \"tui.input.newLine\",\n\tsubmit: \"tui.input.submit\",\n\ttab: \"tui.input.tab\",\n\tcopy: \"tui.input.copy\",\n\tselectUp: \"tui.select.up\",\n\tselectDown: \"tui.select.down\",\n\tselectPageUp: \"tui.select.pageUp\",\n\tselectPageDown: \"tui.select.pageDown\",\n\tselectConfirm: \"tui.select.confirm\",\n\tselectCancel: \"tui.select.cancel\",\n\tinterrupt: \"app.interrupt\",\n\tclear: \"app.clear\",\n\texit: \"app.exit\",\n\tsuspend: \"app.suspend\",\n\tcycleThinkingLevel: \"app.thinking.cycle\",\n\tcycleModelForward: \"app.model.cycleForward\",\n\tcycleModelBackward: \"app.model.cycleBackward\",\n\tselectModel: \"app.model.select\",\n\texpandTools: \"app.tools.expand\",\n\ttoggleThinking: \"app.thinking.toggle\",\n\ttoggleSessionNamedFilter: \"app.session.toggleNamedFilter\",\n\texternalEditor: \"app.editor.external\",\n\tfollowUp: \"app.message.followUp\",\n\tdequeue: \"app.message.dequeue\",\n\tpasteImage: \"app.clipboard.pasteImage\",\n\tnewSession: \"app.session.new\",\n\ttree: \"app.session.tree\",\n\tfork: \"app.session.fork\",\n\tresume: \"app.session.resume\",\n\ttreeFoldOrUp: \"app.tree.foldOrUp\",\n\ttreeUnfoldOrDown: \"app.tree.unfoldOrDown\",\n\ttreeEditLabel: \"app.tree.editLabel\",\n\ttreeToggleLabelTimestamp: \"app.tree.toggleLabelTimestamp\",\n\ttoggleSessionPath: \"app.session.togglePath\",\n\ttoggleSessionSort: \"app.session.toggleSort\",\n\trenameSession: \"app.session.rename\",\n\tdeleteSession: \"app.session.delete\",\n\tdeleteSessionNoninvasive: \"app.session.deleteNoninvasive\",\n} as const satisfies Record<string, Keybinding>;\n\nfunction isLegacyKeybindingName(key: string): key is keyof typeof KEYBINDING_NAME_MIGRATIONS {\n\treturn key in KEYBINDING_NAME_MIGRATIONS;\n}\n\nfunction toKeybindingsConfig(value: Record<string, unknown>): KeybindingsConfig {\n\tconst config: KeybindingsConfig = {};\n\tfor (const [key, binding] of Object.entries(value)) {\n\t\tif (typeof binding === \"string\") {\n\t\t\tconfig[key] = binding as KeyId;\n\t\t\tcontinue;\n\t\t}\n\t\tif (Array.isArray(binding) && binding.every((entry) => typeof entry === \"string\")) {\n\t\t\tconfig[key] = binding as KeyId[];\n\t\t}\n\t}\n\treturn config;\n}\n\nexport function migrateKeybindingsConfig(rawConfig: Record<string, unknown>): {\n\tconfig: Record<string, unknown>;\n\tmigrated: boolean;\n} {\n\tconst config: Record<string, unknown> = {};\n\tlet migrated = false;\n\n\tfor (const [key, value] of Object.entries(rawConfig)) {\n\t\tconst nextKey = isLegacyKeybindingName(key) ? KEYBINDING_NAME_MIGRATIONS[key] : key;\n\t\tif (nextKey !== key) {\n\t\t\tmigrated = true;\n\t\t}\n\t\tif (key !== nextKey && Object.hasOwn(rawConfig, nextKey)) {\n\t\t\tmigrated = true;\n\t\t\tcontinue;\n\t\t}\n\t\tconfig[nextKey] = value;\n\t}\n\n\treturn { config: orderKeybindingsConfig(config), migrated };\n}\n\nfunction orderKeybindingsConfig(config: Record<string, unknown>): Record<string, unknown> {\n\tconst ordered: Record<string, unknown> = {};\n\tfor (const keybinding of Object.keys(KEYBINDINGS)) {\n\t\tif (Object.hasOwn(config, keybinding)) {\n\t\t\tordered[keybinding] = config[keybinding];\n\t\t}\n\t}\n\n\tconst extras = Object.keys(config)\n\t\t.filter((key) => !Object.hasOwn(ordered, key))\n\t\t.sort();\n\tfor (const key of extras) {\n\t\tordered[key] = config[key];\n\t}\n\n\treturn ordered;\n}\n\nfunction loadRawConfig(path: string): Record<string, unknown> | undefined {\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(path, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null) return undefined;\n\t\treturn parsed as Record<string, unknown>;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport class KeybindingsManager extends TuiKeybindingsManager {\n\tprivate configPath: string | undefined;\n\n\tconstructor(userBindings: KeybindingsConfig = {}, configPath?: string) {\n\t\tsuper(KEYBINDINGS, userBindings);\n\t\tthis.configPath = configPath;\n\t}\n\n\tstatic create(agentDir: string = getAgentDir()): KeybindingsManager {\n\t\tconst configPath = join(agentDir, \"keybindings.json\");\n\t\tconst userBindings = KeybindingsManager.loadFromFile(configPath);\n\t\treturn new KeybindingsManager(userBindings, configPath);\n\t}\n\n\treload(): void {\n\t\tif (!this.configPath) return;\n\t\tthis.setUserBindings(KeybindingsManager.loadFromFile(this.configPath));\n\t}\n\n\tgetEffectiveConfig(): KeybindingsConfig {\n\t\treturn this.getResolvedBindings();\n\t}\n\n\tprivate static loadFromFile(path: string): KeybindingsConfig {\n\t\tconst rawConfig = loadRawConfig(path);\n\t\tif (!rawConfig) return {};\n\t\treturn toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config);\n\t}\n}\n\nexport type { Keybinding, KeyId, KeybindingsConfig };\n"]}
@@ -71,6 +71,8 @@ export declare class LspClient {
71
71
  private handleServerRequest;
72
72
  private captureStderr;
73
73
  private rejectPending;
74
+ private childExitFailure;
75
+ private writeFailure;
74
76
  private fail;
75
77
  }
76
78
  //# sourceMappingURL=client.d.ts.map
@@ -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":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAG,IAAI,CAAC;AAC7C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AACrD,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,GAAG,IAAI,CAAC;AAEnD,MAAM,iCAAiC,GAAG,MAAM,CAAC;AACjD,MAAM,0BAA0B,GAAG,MAAM,CAAC;AAC1C,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAClC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAC/B,MAAM,aAAa,GAAG,KAAK,CAAC;AAyB5B,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAChC,IAAI,CAAS;IACb,IAAI,CAAW;IAExB,YAAY,KAAwD,EAAE;QACrE,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IAAA,CACvB;CACD;AAYD,SAAS,QAAQ,CAAC,KAAc,EAAoC;IACnE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAAA,CAC5E;AAED,SAAS,WAAW,CAAC,KAAc,EAA4B;IAC9D,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;AAAA,CAC/F;AAED,SAAS,cAAc,CAAC,KAAc,EAAS;IAC9C,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAAA,CACjE;AAED,SAAS,qBAAqB,CAAC,KAAc,EAAuB;IACnE,IAAI,IAAI,GAA4B,MAAM,CAAC;IAC3C,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC;IACpE,CAAC;SAAM,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,SAAS,GAAG,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC;QACrC,IAAI,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC;QACjF,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI;YAAE,IAAI,GAAG,IAAI,CAAC;aAChC,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,IAAI,GAAG,IAAI,CAAC;YACZ,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC;QACnD,CAAC;IACF,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;AAAA,CAClD;AAED,SAAS,eAAe,CAAC,KAAyB,EAAE,QAAgB,EAAE,KAAa,EAAU;IAC5F,MAAM,OAAO,GAAG,KAAK,IAAI,QAAQ,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,mCAAmC,CAAC,CAAC;IAChH,OAAO,OAAO,CAAC;AAAA,CACf;AAED,SAAS,KAAK,CAAC,EAAU,EAAiB;IACzC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAAA,CACzD;AAED,qEAAqE;AACrE,MAAM,OAAO,SAAS;IACJ,OAAO,CAAmB;IACnC,KAAK,CAA2B;IAChC,KAAK,CAAuB;IAC5B,MAAM,CAAuB;IAC7B,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxB,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,aAAa,GAAG,CAAC,CAAC;IACT,OAAO,GAAG,IAAI,GAAG,EAA6B,CAAC;IAC/C,qBAAqB,GAAG,IAAI,GAAG,EAA2C,CAAC;IAC3E,gBAAgB,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC9D,YAAY,CAA4B;IACxC,cAAc,CAA4B;IAC1C,KAAK,GAAgB,MAAM,CAAC;IAC5B,OAAO,CAAoB;IAC3B,UAAU,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAC9C,gBAAgB,GAAwB;QAC/C,IAAI,EAAE,MAAM;QACZ,SAAS,EAAE,KAAK;QAChB,IAAI,EAAE,KAAK;QACX,eAAe,EAAE,KAAK;KACtB,CAAC;IAEF,YAAY,OAAyB,EAAE;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAAA,CACvB;IAED,IAAI,cAAc,GAAW;QAC5B,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAAA,CACxC;IAED,sEAAsE;IACtE,IAAI,gBAAgB,GAAwB;QAC3C,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAAA,CAC7B;IAED,cAAc,CAAC,QAAiD,EAAc;QAC7E,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAAA,CACzD;IAED,mEAAmE;IACnE,SAAS,CAAC,QAAgC,EAAc;QACvD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,OAAO;YAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAAA,CACpD;IAED,KAAK,GAAkB;QACtB,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACzD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC,CAAC;QACzE,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACxB,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;YACxB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC5D,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;gBACtC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACnB,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;gBAC5B,MAAM,OAAO,CAAC;YAAA,CACd,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC;IAAA,CACzB;IAED,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,MAAgB,EAAE,MAAoB,EAAoB;QACvF,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO;YAAE,MAAM,IAAI,CAAC,OAAO,IAAI,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACrG,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAAA,CACzE;IAED,MAAM,CAAC,MAAc,EAAE,MAAgB,EAAQ;QAC9C,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,CAAC,OAAO,CAAC;QACrC,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC7E,KAAK,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;YAChH,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;QAAA,CACjC,CAAC,CAAC;IAAA,CACH;IAED,OAAO,GAAkB;QACxB,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC,cAAc,CAAC;IAAA,CAC3B;IAEO,uBAAuB,GAAW;QACzC,OAAO,eAAe,CACrB,IAAI,CAAC,OAAO,CAAC,uBAAuB,EACpC,iCAAiC,EACjC,yBAAyB,CACzB,CAAC;IAAA,CACF;IAEO,gBAAgB,GAAW;QAClC,OAAO,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,0BAA0B,EAAE,kBAAkB,CAAC,CAAC;IAAA,CACtG;IAEO,KAAK,CAAC,UAAU,GAAkB;QACzC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,EAAE;YAChF,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG;YACrB,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG;YACrB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAC/B,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAsB,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACvE,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAsB,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;QAChF,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACzD,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,gDAAgD,IAAI,WAAW,MAAM,IAAI,CAAC,CAAC,CAAC;YACjG,CAAC;QAAA,CACD,CAAC,CAAC;QAEH,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,WAAW,CAC9C,YAAY,EACZ;YACC,SAAS,EAAE,OAAO,CAAC,GAAG;YACtB,UAAU,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;YACjC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI;YAC7C,YAAY,EAAE;gBACb,OAAO,EAAE,EAAE,iBAAiB,EAAE,CAAC,QAAQ,CAAC,EAAE;gBAC1C,SAAS,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAE;gBACtC,YAAY,EAAE;oBACb,UAAU,EAAE,EAAE;oBACd,UAAU,EAAE,EAAE;oBACd,cAAc,EAAE,EAAE;oBAClB,kBAAkB,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE;iBAC5C;aACD;YACD,gBAAgB,EAAE,IAAI;SACtB,EACD,SAAS,EACT,IAAI,CAAC,uBAAuB,EAAE,EAC9B,sCAAsC,CACtC,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7E,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,qBAAqB,CAAC,gBAAgB,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QAC9F,IAAI,IAAI,CAAC,KAAK,KAAK,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QAClG,MAAM,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/E,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC;IAAA,CACrB;IAEO,KAAK,CAAC,cAAc,GAAkB;QAC7C,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ;YAAE,OAAO;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC;QACxC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAC;QAEpE,IAAI,QAAQ,EAAE,CAAC;YACd,IAAI,CAAC;gBACJ,MAAM,IAAI,CAAC,WAAW,CACrB,UAAU,EACV,SAAS,EACT,SAAS,EACT,mBAAmB,EACnB,oCAAoC,EACpC,IAAI,CACJ,CAAC;gBACF,MAAM,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YAC7D,CAAC;YAAC,MAAM,CAAC;gBACR,yEAAyE;YAC1E,CAAC;QACF,CAAC;QACD,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC;IAAA,CACtB;IAEO,KAAK,CAAC,cAAc,GAAkB;QAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;YAAE,OAAO;QAC3E,MAAM,MAAM,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACnF,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5G,IAAI,QAAQ;YAAE,OAAO;QACrB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtB,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzG,IAAI,UAAU;YAAE,OAAO;QACvB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtB,MAAM,MAAM,CAAC;IAAA,CACb;IAEO,WAAW,CAClB,MAAc,EACd,MAAgB,EAChB,MAAoB,EACpB,SAAkB,EAClB,cAAc,GAAG,2BAA2B,MAAM,YAAY,EAC9D,YAAY,GAAG,KAAK,EACD;QACnB,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,YAAY;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACzG,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC,CAAC;QACzF,CAAC;QACD,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAChC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC,CAAC;QAC/G,IAAI,MAAM,EAAE,OAAO;YAClB,OAAO,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC,CAAC;QAEvG,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;YACvC,IAAI,KAAiC,CAAC;YACtC,MAAM,MAAM,GAAG,CAAC,EAAc,EAAE,EAAE,CAAC;gBAClC,IAAI,KAAK;oBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;gBAC/B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBAC5C,EAAE,EAAE,CAAC;YAAA,CACL,CAAC;YACF,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC;gBACnB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;oBAAE,OAAO;gBACrC,KAAK,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC,CAAC;gBACtG,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,IAAI,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC,CAAC,CAAC;YAAA,CACtG,CAAC;YACF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE;gBACpB,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAChD,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;aAC9C,CAAC,CAAC;YACH,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACzD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC7B,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC;oBACxB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;wBAAE,OAAO;oBACrC,KAAK,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC,CAAC;oBACtG,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,cAAc,UAAU,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC;gBAAA,CAC3E,EAAE,SAAS,CAAC,CAAC;YACf,CAAC;YACD,KAAK,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CACxG,CAAC,KAAK,EAAE,EAAE,CAAC;gBACV,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACrC,IAAI,CAAC,OAAO;oBAAE,OAAO;gBACrB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACxB,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;YAAA,CACtC,CACD,CAAC;QAAA,CACF,CAAC,CAAC;IAAA,CACH;IAEO,YAAY,CAAC,OAAe,EAAiB;QACpD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;QAC1D,IAAI,IAAI,CAAC,MAAM,GAAG,qBAAqB;YACtC,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC,CAAC;QAC5E,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,MAAM,UAAU,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QACpG,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QACnE,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC,CAAC;QAC1C,OAAO,OAAO,CAAC;IAAA,CACf;IAEO,UAAU,CAAC,KAAa,EAAiB;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;YACvC,IAAI,eAAe,GAAG,KAAK,CAAC;YAC5B,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;gBACrB,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACxC,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAAA,CACxC,CAAC;YACF,MAAM,OAAO,GAAG,CAAC,KAAY,EAAE,EAAE,CAAC;gBACjC,OAAO,EAAE,CAAC;gBACV,MAAM,CAAC,KAAK,CAAC,CAAC;YAAA,CACd,CAAC;YACF,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;gBACrB,eAAe,GAAG,KAAK,CAAC;gBACxB,OAAO,EAAE,CAAC;gBACV,OAAO,EAAE,CAAC;YAAA,CACV,CAAC;YACF,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9B,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC/C,IAAI,KAAK;oBAAE,OAAO,CAAC,KAAK,CAAC,CAAC;qBACrB,IAAI,CAAC,eAAe,EAAE,CAAC;oBAC3B,OAAO,EAAE,CAAC;oBACV,OAAO,EAAE,CAAC;gBACX,CAAC;YAAA,CACD,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACf,eAAe,GAAG,IAAI,CAAC;gBACvB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC/B,CAAC;QAAA,CACD,CAAC,CAAC;IAAA,CACH;IAEO,MAAM,CAAC,KAAsB,EAAQ;QAC5C,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACjG,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACjD,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;gBACnB,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,oBAAoB;oBAAE,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;gBAC5G,OAAO;YACR,CAAC;YACD,IAAI,SAAS,GAAG,oBAAoB,EAAE,CAAC;gBACtC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;gBAC9D,OAAO;YACR,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACnE,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,+CAA+C,CAAC,CAAC,CAAC;YACtF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC,CAAC;gBAC9F,OAAO;YACR,CAAC;YACD,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,qBAAqB,EAAE,CAAC;gBACnF,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC,CAAC;gBAC/D,OAAO;YACR,CAAC;YACD,MAAM,SAAS,GAAG,SAAS,GAAG,CAAC,CAAC;YAChC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,GAAG,aAAa;gBAAE,OAAO;YAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,aAAa,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACxF,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,GAAG,aAAa,CAAC,CAAC;YAC5D,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACzC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;gBAC9F,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACxB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;gBACjC,OAAO;YACR,CAAC;QACF,CAAC;IAAA,CACD;IAEO,SAAS,CAAC,OAAuB,EAAQ;QAChD,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC/B,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC,CAAC;YAC5E,OAAO;QACR,CAAC;QACD,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACxC,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,IAAI,OAAO,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;gBACrD,KAAK,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;gBACvC,OAAO;YACR,CAAC;YACD,MAAM,YAAY,GAAoB;gBACrC,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;aACnE,CAAC;YACF,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,qBAAqB;gBAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;YAC1E,OAAO;QACR,CAAC;QACD,IAAI,OAAO,OAAO,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YAAE,OAAO;QAChF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACjD,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC,CAAC;YAC9F,OAAO;QACR,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,QAAQ,EAAE,CAAC;YACd,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YAC5B,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAChG,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC,CAAC;gBAC5E,OAAO;YACR,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAc,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC9G,OAAO;QACR,CAAC;QACD,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAAA,CAChC;IAEO,KAAK,CAAC,mBAAmB,CAAC,OAAuB,EAAiB;QACzE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO;QAC3E,IAAI,MAAe,CAAC;QACpB,IAAI,KAAoD,CAAC;QACzD,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC;YACxB,KAAK,yBAAyB,EAAE,CAAC;gBAChC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;gBAC9B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;oBAAE,KAAK,GAAG,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;;oBACtG,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;gBAC3C,MAAM;YACP,CAAC;YACD,KAAK,4BAA4B,CAAC;YAClC,KAAK,2BAA2B;gBAC/B,MAAM,GAAG,IAAI,CAAC;gBACd,MAAM;YACP,KAAK,2BAA2B,CAAC;YACjC,KAAK,6BAA6B,CAAC;YACnC,KAAK,gCAAgC,CAAC;YACtC,KAAK,kCAAkC,CAAC;YACxC,KAAK,6BAA6B,CAAC;YACnC,KAAK,8BAA8B,CAAC;YACpC,KAAK,4BAA4B;gBAChC,MAAM,GAAG,IAAI,CAAC;gBACd,MAAM;YACP,KAAK,qBAAqB;gBACzB,MAAM,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,6DAA6D,EAAE,CAAC;gBAC1G,MAAM;YACP,KAAK,qBAAqB;gBACzB,MAAM,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;gBAC5B,MAAM;YACP;gBACC,KAAK,GAAG,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;QACxD,CAAC;QACD,MAAM,IAAI,CAAC,YAAY,CAAC;YACvB,OAAO,EAAE,KAAK;YACd,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;SACnC,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAAA,CAChE;IAEO,aAAa,CAAC,KAAsB,EAAQ;QACnD,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACrE,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;QAC1D,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,yBAAyB,EAAE,CAAC;YACxD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,yBAAyB,CAAC,CAAC;QAChG,CAAC;IAAA,CACD;IAEO,aAAa,CAAC,KAAY,EAAQ;QACzC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IAAA,CACrB;IAEO,IAAI,CAAC,KAAY,EAAQ;QAChC,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ;YAAE,OAAO;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC;QAChD,IAAI,CAAC,OAAO,KAAK,KAAK,CAAC;QACvB,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC;QACpD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACjC,IAAI,YAAY;YAAE,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,gBAAgB;gBAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAAA,CACvF;CACD","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"]}
@@ -103,6 +103,7 @@ declare const ModelDefinitionSchema: Type.TObject<{
103
103
  supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
104
104
  supportsStrictMode: Type.TOptional<Type.TBoolean>;
105
105
  supportsOpenAIGrammarTools: Type.TOptional<Type.TBoolean>;
106
+ supportsAdditionalTools: Type.TOptional<Type.TBoolean>;
106
107
  supportsToolSearch: Type.TOptional<Type.TBoolean>;
107
108
  }>, Type.TObject<{
108
109
  supportsEagerToolInputStreaming: Type.TOptional<Type.TBoolean>;
@@ -216,6 +217,7 @@ declare const ModelOverrideSchema: Type.TObject<{
216
217
  supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
217
218
  supportsStrictMode: Type.TOptional<Type.TBoolean>;
218
219
  supportsOpenAIGrammarTools: Type.TOptional<Type.TBoolean>;
220
+ supportsAdditionalTools: Type.TOptional<Type.TBoolean>;
219
221
  supportsToolSearch: Type.TOptional<Type.TBoolean>;
220
222
  }>, Type.TObject<{
221
223
  supportsEagerToolInputStreaming: Type.TOptional<Type.TBoolean>;
@@ -306,6 +308,7 @@ declare const ProviderConfigSchema: Type.TObject<{
306
308
  supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
307
309
  supportsStrictMode: Type.TOptional<Type.TBoolean>;
308
310
  supportsOpenAIGrammarTools: Type.TOptional<Type.TBoolean>;
311
+ supportsAdditionalTools: Type.TOptional<Type.TBoolean>;
309
312
  supportsToolSearch: Type.TOptional<Type.TBoolean>;
310
313
  }>, Type.TObject<{
311
314
  supportsEagerToolInputStreaming: Type.TOptional<Type.TBoolean>;
@@ -422,6 +425,7 @@ declare const ProviderConfigSchema: Type.TObject<{
422
425
  supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
423
426
  supportsStrictMode: Type.TOptional<Type.TBoolean>;
424
427
  supportsOpenAIGrammarTools: Type.TOptional<Type.TBoolean>;
428
+ supportsAdditionalTools: Type.TOptional<Type.TBoolean>;
425
429
  supportsToolSearch: Type.TOptional<Type.TBoolean>;
426
430
  }>, Type.TObject<{
427
431
  supportsEagerToolInputStreaming: Type.TOptional<Type.TBoolean>;
@@ -535,6 +539,7 @@ declare const ProviderConfigSchema: Type.TObject<{
535
539
  supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
536
540
  supportsStrictMode: Type.TOptional<Type.TBoolean>;
537
541
  supportsOpenAIGrammarTools: Type.TOptional<Type.TBoolean>;
542
+ supportsAdditionalTools: Type.TOptional<Type.TBoolean>;
538
543
  supportsToolSearch: Type.TOptional<Type.TBoolean>;
539
544
  }>, Type.TObject<{
540
545
  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;AAyJ5C,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\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(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"]}
@@ -98,6 +98,7 @@ const OpenAIResponsesCompatSchema = Type.Object({
98
98
  supportsLongCacheRetention: Type.Optional(Type.Boolean()),
99
99
  supportsStrictMode: Type.Optional(Type.Boolean()),
100
100
  supportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),
101
+ supportsAdditionalTools: Type.Optional(Type.Boolean()),
101
102
  supportsToolSearch: Type.Optional(Type.Boolean()),
102
103
  });
103
104
  const AnthropicMessagesCompatSchema = Type.Object({