@oddessentials/agent-guild 0.1.0

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 (342) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +162 -0
  3. package/bin/agent-guild-report.mjs +134 -0
  4. package/bin/agent-guild.mjs +240 -0
  5. package/config/providers.default.json +124 -0
  6. package/examples/claude-code-settings.json +48 -0
  7. package/examples/codex-hooks.json +45 -0
  8. package/examples/gemini-settings.json +61 -0
  9. package/examples/grok-hooks.json +55 -0
  10. package/examples/providers.json +27 -0
  11. package/node_modules/@xterm/addon-fit/LICENSE +19 -0
  12. package/node_modules/@xterm/addon-fit/README.md +24 -0
  13. package/node_modules/@xterm/addon-fit/lib/addon-fit.js +2 -0
  14. package/node_modules/@xterm/addon-fit/lib/addon-fit.js.map +1 -0
  15. package/node_modules/@xterm/addon-fit/lib/addon-fit.mjs +18 -0
  16. package/node_modules/@xterm/addon-fit/lib/addon-fit.mjs.map +7 -0
  17. package/node_modules/@xterm/addon-fit/package.json +26 -0
  18. package/node_modules/@xterm/addon-fit/src/FitAddon.ts +92 -0
  19. package/node_modules/@xterm/addon-fit/typings/addon-fit.d.ts +55 -0
  20. package/node_modules/@xterm/addon-serialize/README.md +42 -0
  21. package/node_modules/@xterm/addon-serialize/lib/addon-serialize.js +2 -0
  22. package/node_modules/@xterm/addon-serialize/lib/addon-serialize.js.map +1 -0
  23. package/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs +19 -0
  24. package/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs.map +7 -0
  25. package/node_modules/@xterm/addon-serialize/package.json +29 -0
  26. package/node_modules/@xterm/addon-serialize/src/SerializeAddon.ts +695 -0
  27. package/node_modules/@xterm/addon-serialize/typings/addon-serialize.d.ts +116 -0
  28. package/node_modules/@xterm/addon-web-links/LICENSE +19 -0
  29. package/node_modules/@xterm/addon-web-links/README.md +21 -0
  30. package/node_modules/@xterm/addon-web-links/lib/addon-web-links.js +2 -0
  31. package/node_modules/@xterm/addon-web-links/lib/addon-web-links.js.map +1 -0
  32. package/node_modules/@xterm/addon-web-links/lib/addon-web-links.mjs +18 -0
  33. package/node_modules/@xterm/addon-web-links/lib/addon-web-links.mjs.map +7 -0
  34. package/node_modules/@xterm/addon-web-links/package.json +26 -0
  35. package/node_modules/@xterm/addon-web-links/src/WebLinkProvider.ts +199 -0
  36. package/node_modules/@xterm/addon-web-links/src/WebLinksAddon.ts +58 -0
  37. package/node_modules/@xterm/addon-web-links/typings/addon-web-links.d.ts +57 -0
  38. package/node_modules/@xterm/headless/README.md +31 -0
  39. package/node_modules/@xterm/headless/lib-headless/xterm-headless.js +2 -0
  40. package/node_modules/@xterm/headless/lib-headless/xterm-headless.js.map +1 -0
  41. package/node_modules/@xterm/headless/lib-headless/xterm-headless.mjs +46 -0
  42. package/node_modules/@xterm/headless/lib-headless/xterm-headless.mjs.map +7 -0
  43. package/node_modules/@xterm/headless/package.json +29 -0
  44. package/node_modules/@xterm/headless/typings/xterm-headless.d.ts +1385 -0
  45. package/node_modules/@xterm/xterm/LICENSE +21 -0
  46. package/node_modules/@xterm/xterm/README.md +243 -0
  47. package/node_modules/@xterm/xterm/css/xterm.css +285 -0
  48. package/node_modules/@xterm/xterm/lib/xterm.js +2 -0
  49. package/node_modules/@xterm/xterm/lib/xterm.js.map +1 -0
  50. package/node_modules/@xterm/xterm/lib/xterm.mjs +53 -0
  51. package/node_modules/@xterm/xterm/lib/xterm.mjs.map +7 -0
  52. package/node_modules/@xterm/xterm/package.json +111 -0
  53. package/node_modules/@xterm/xterm/src/browser/AccessibilityManager.ts +435 -0
  54. package/node_modules/@xterm/xterm/src/browser/Clipboard.ts +93 -0
  55. package/node_modules/@xterm/xterm/src/browser/ColorContrastCache.ts +34 -0
  56. package/node_modules/@xterm/xterm/src/browser/CoreBrowserTerminal.ts +1339 -0
  57. package/node_modules/@xterm/xterm/src/browser/Linkifier.ts +403 -0
  58. package/node_modules/@xterm/xterm/src/browser/LocalizableStrings.ts +23 -0
  59. package/node_modules/@xterm/xterm/src/browser/OscLinkProvider.ts +129 -0
  60. package/node_modules/@xterm/xterm/src/browser/RenderDebouncer.ts +84 -0
  61. package/node_modules/@xterm/xterm/src/browser/TimeBasedDebouncer.ts +86 -0
  62. package/node_modules/@xterm/xterm/src/browser/Types.ts +226 -0
  63. package/node_modules/@xterm/xterm/src/browser/Viewport.ts +192 -0
  64. package/node_modules/@xterm/xterm/src/browser/decorations/BufferDecorationRenderer.ts +139 -0
  65. package/node_modules/@xterm/xterm/src/browser/decorations/ColorZoneStore.ts +117 -0
  66. package/node_modules/@xterm/xterm/src/browser/decorations/OverviewRulerRenderer.ts +214 -0
  67. package/node_modules/@xterm/xterm/src/browser/input/CompositionHelper.ts +248 -0
  68. package/node_modules/@xterm/xterm/src/browser/input/Mouse.ts +54 -0
  69. package/node_modules/@xterm/xterm/src/browser/input/MoveToCell.ts +251 -0
  70. package/node_modules/@xterm/xterm/src/browser/public/Terminal.ts +275 -0
  71. package/node_modules/@xterm/xterm/src/browser/renderer/dom/DomRenderer.ts +542 -0
  72. package/node_modules/@xterm/xterm/src/browser/renderer/dom/DomRendererRowFactory.ts +546 -0
  73. package/node_modules/@xterm/xterm/src/browser/renderer/dom/WidthCache.ts +167 -0
  74. package/node_modules/@xterm/xterm/src/browser/renderer/shared/Constants.ts +6 -0
  75. package/node_modules/@xterm/xterm/src/browser/renderer/shared/RendererUtils.ts +95 -0
  76. package/node_modules/@xterm/xterm/src/browser/renderer/shared/SelectionRenderModel.ts +93 -0
  77. package/node_modules/@xterm/xterm/src/browser/renderer/shared/Types.ts +84 -0
  78. package/node_modules/@xterm/xterm/src/browser/selection/SelectionModel.ts +144 -0
  79. package/node_modules/@xterm/xterm/src/browser/selection/Types.ts +15 -0
  80. package/node_modules/@xterm/xterm/src/browser/services/CharSizeService.ts +127 -0
  81. package/node_modules/@xterm/xterm/src/browser/services/CharacterJoinerService.ts +339 -0
  82. package/node_modules/@xterm/xterm/src/browser/services/CoreBrowserService.ts +137 -0
  83. package/node_modules/@xterm/xterm/src/browser/services/LinkProviderService.ts +28 -0
  84. package/node_modules/@xterm/xterm/src/browser/services/MouseService.ts +46 -0
  85. package/node_modules/@xterm/xterm/src/browser/services/RenderService.ts +376 -0
  86. package/node_modules/@xterm/xterm/src/browser/services/SelectionService.ts +1039 -0
  87. package/node_modules/@xterm/xterm/src/browser/services/Services.ts +158 -0
  88. package/node_modules/@xterm/xterm/src/browser/services/ThemeService.ts +198 -0
  89. package/node_modules/@xterm/xterm/src/browser/shared/Constants.ts +8 -0
  90. package/node_modules/@xterm/xterm/src/common/CircularList.ts +241 -0
  91. package/node_modules/@xterm/xterm/src/common/Clone.ts +23 -0
  92. package/node_modules/@xterm/xterm/src/common/Color.ts +376 -0
  93. package/node_modules/@xterm/xterm/src/common/CoreTerminal.ts +283 -0
  94. package/node_modules/@xterm/xterm/src/common/InputHandler.ts +3495 -0
  95. package/node_modules/@xterm/xterm/src/common/MultiKeyMap.ts +42 -0
  96. package/node_modules/@xterm/xterm/src/common/Platform.ts +44 -0
  97. package/node_modules/@xterm/xterm/src/common/SortedList.ts +194 -0
  98. package/node_modules/@xterm/xterm/src/common/TaskQueue.ts +166 -0
  99. package/node_modules/@xterm/xterm/src/common/TypedArrayUtils.ts +17 -0
  100. package/node_modules/@xterm/xterm/src/common/Types.ts +552 -0
  101. package/node_modules/@xterm/xterm/src/common/WindowsMode.ts +27 -0
  102. package/node_modules/@xterm/xterm/src/common/buffer/AttributeData.ts +211 -0
  103. package/node_modules/@xterm/xterm/src/common/buffer/Buffer.ts +662 -0
  104. package/node_modules/@xterm/xterm/src/common/buffer/BufferLine.ts +551 -0
  105. package/node_modules/@xterm/xterm/src/common/buffer/BufferRange.ts +13 -0
  106. package/node_modules/@xterm/xterm/src/common/buffer/BufferReflow.ts +226 -0
  107. package/node_modules/@xterm/xterm/src/common/buffer/BufferSet.ts +134 -0
  108. package/node_modules/@xterm/xterm/src/common/buffer/CellData.ts +94 -0
  109. package/node_modules/@xterm/xterm/src/common/buffer/Constants.ts +157 -0
  110. package/node_modules/@xterm/xterm/src/common/buffer/Marker.ts +43 -0
  111. package/node_modules/@xterm/xterm/src/common/buffer/Types.ts +52 -0
  112. package/node_modules/@xterm/xterm/src/common/data/Charsets.ts +256 -0
  113. package/node_modules/@xterm/xterm/src/common/data/EscapeSequences.ts +153 -0
  114. package/node_modules/@xterm/xterm/src/common/input/Keyboard.ts +373 -0
  115. package/node_modules/@xterm/xterm/src/common/input/TextDecoder.ts +346 -0
  116. package/node_modules/@xterm/xterm/src/common/input/UnicodeV6.ts +145 -0
  117. package/node_modules/@xterm/xterm/src/common/input/WriteBuffer.ts +247 -0
  118. package/node_modules/@xterm/xterm/src/common/input/XParseColor.ts +80 -0
  119. package/node_modules/@xterm/xterm/src/common/parser/Constants.ts +58 -0
  120. package/node_modules/@xterm/xterm/src/common/parser/DcsParser.ts +192 -0
  121. package/node_modules/@xterm/xterm/src/common/parser/EscapeSequenceParser.ts +792 -0
  122. package/node_modules/@xterm/xterm/src/common/parser/OscParser.ts +238 -0
  123. package/node_modules/@xterm/xterm/src/common/parser/Params.ts +229 -0
  124. package/node_modules/@xterm/xterm/src/common/parser/Types.ts +275 -0
  125. package/node_modules/@xterm/xterm/src/common/public/AddonManager.ts +53 -0
  126. package/node_modules/@xterm/xterm/src/common/public/BufferApiView.ts +35 -0
  127. package/node_modules/@xterm/xterm/src/common/public/BufferLineApiView.ts +29 -0
  128. package/node_modules/@xterm/xterm/src/common/public/BufferNamespaceApi.ts +36 -0
  129. package/node_modules/@xterm/xterm/src/common/public/ParserApi.ts +37 -0
  130. package/node_modules/@xterm/xterm/src/common/public/UnicodeApi.ts +27 -0
  131. package/node_modules/@xterm/xterm/src/common/services/BufferService.ts +154 -0
  132. package/node_modules/@xterm/xterm/src/common/services/CharsetService.ts +34 -0
  133. package/node_modules/@xterm/xterm/src/common/services/CoreMouseService.ts +365 -0
  134. package/node_modules/@xterm/xterm/src/common/services/CoreService.ts +92 -0
  135. package/node_modules/@xterm/xterm/src/common/services/DecorationService.ts +140 -0
  136. package/node_modules/@xterm/xterm/src/common/services/InstantiationService.ts +85 -0
  137. package/node_modules/@xterm/xterm/src/common/services/LogService.ts +124 -0
  138. package/node_modules/@xterm/xterm/src/common/services/OptionsService.ts +212 -0
  139. package/node_modules/@xterm/xterm/src/common/services/OscLinkService.ts +115 -0
  140. package/node_modules/@xterm/xterm/src/common/services/ServiceRegistry.ts +49 -0
  141. package/node_modules/@xterm/xterm/src/common/services/Services.ts +396 -0
  142. package/node_modules/@xterm/xterm/src/common/services/UnicodeService.ts +111 -0
  143. package/node_modules/@xterm/xterm/src/vs/base/browser/browser.ts +141 -0
  144. package/node_modules/@xterm/xterm/src/vs/base/browser/canIUse.ts +49 -0
  145. package/node_modules/@xterm/xterm/src/vs/base/browser/dom.ts +2369 -0
  146. package/node_modules/@xterm/xterm/src/vs/base/browser/fastDomNode.ts +316 -0
  147. package/node_modules/@xterm/xterm/src/vs/base/browser/globalPointerMoveMonitor.ts +112 -0
  148. package/node_modules/@xterm/xterm/src/vs/base/browser/iframe.ts +135 -0
  149. package/node_modules/@xterm/xterm/src/vs/base/browser/keyboardEvent.ts +213 -0
  150. package/node_modules/@xterm/xterm/src/vs/base/browser/mouseEvent.ts +229 -0
  151. package/node_modules/@xterm/xterm/src/vs/base/browser/touch.ts +372 -0
  152. package/node_modules/@xterm/xterm/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +303 -0
  153. package/node_modules/@xterm/xterm/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +114 -0
  154. package/node_modules/@xterm/xterm/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +720 -0
  155. package/node_modules/@xterm/xterm/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +165 -0
  156. package/node_modules/@xterm/xterm/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +114 -0
  157. package/node_modules/@xterm/xterm/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +243 -0
  158. package/node_modules/@xterm/xterm/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +118 -0
  159. package/node_modules/@xterm/xterm/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +116 -0
  160. package/node_modules/@xterm/xterm/src/vs/base/browser/ui/widget.ts +57 -0
  161. package/node_modules/@xterm/xterm/src/vs/base/browser/window.ts +14 -0
  162. package/node_modules/@xterm/xterm/src/vs/base/common/arrays.ts +887 -0
  163. package/node_modules/@xterm/xterm/src/vs/base/common/arraysFind.ts +202 -0
  164. package/node_modules/@xterm/xterm/src/vs/base/common/assert.ts +71 -0
  165. package/node_modules/@xterm/xterm/src/vs/base/common/async.ts +1992 -0
  166. package/node_modules/@xterm/xterm/src/vs/base/common/cancellation.ts +148 -0
  167. package/node_modules/@xterm/xterm/src/vs/base/common/charCode.ts +450 -0
  168. package/node_modules/@xterm/xterm/src/vs/base/common/collections.ts +140 -0
  169. package/node_modules/@xterm/xterm/src/vs/base/common/decorators.ts +130 -0
  170. package/node_modules/@xterm/xterm/src/vs/base/common/equals.ts +146 -0
  171. package/node_modules/@xterm/xterm/src/vs/base/common/errors.ts +303 -0
  172. package/node_modules/@xterm/xterm/src/vs/base/common/event.ts +1778 -0
  173. package/node_modules/@xterm/xterm/src/vs/base/common/functional.ts +32 -0
  174. package/node_modules/@xterm/xterm/src/vs/base/common/hash.ts +316 -0
  175. package/node_modules/@xterm/xterm/src/vs/base/common/iterator.ts +159 -0
  176. package/node_modules/@xterm/xterm/src/vs/base/common/keyCodes.ts +526 -0
  177. package/node_modules/@xterm/xterm/src/vs/base/common/keybindings.ts +284 -0
  178. package/node_modules/@xterm/xterm/src/vs/base/common/lazy.ts +47 -0
  179. package/node_modules/@xterm/xterm/src/vs/base/common/lifecycle.ts +801 -0
  180. package/node_modules/@xterm/xterm/src/vs/base/common/linkedList.ts +142 -0
  181. package/node_modules/@xterm/xterm/src/vs/base/common/map.ts +202 -0
  182. package/node_modules/@xterm/xterm/src/vs/base/common/numbers.ts +98 -0
  183. package/node_modules/@xterm/xterm/src/vs/base/common/observable.ts +76 -0
  184. package/node_modules/@xterm/xterm/src/vs/base/common/observableInternal/api.ts +31 -0
  185. package/node_modules/@xterm/xterm/src/vs/base/common/observableInternal/autorun.ts +281 -0
  186. package/node_modules/@xterm/xterm/src/vs/base/common/observableInternal/base.ts +489 -0
  187. package/node_modules/@xterm/xterm/src/vs/base/common/observableInternal/debugName.ts +145 -0
  188. package/node_modules/@xterm/xterm/src/vs/base/common/observableInternal/derived.ts +428 -0
  189. package/node_modules/@xterm/xterm/src/vs/base/common/observableInternal/lazyObservableValue.ts +146 -0
  190. package/node_modules/@xterm/xterm/src/vs/base/common/observableInternal/logging.ts +328 -0
  191. package/node_modules/@xterm/xterm/src/vs/base/common/observableInternal/promise.ts +209 -0
  192. package/node_modules/@xterm/xterm/src/vs/base/common/observableInternal/utils.ts +610 -0
  193. package/node_modules/@xterm/xterm/src/vs/base/common/platform.ts +281 -0
  194. package/node_modules/@xterm/xterm/src/vs/base/common/scrollable.ts +522 -0
  195. package/node_modules/@xterm/xterm/src/vs/base/common/sequence.ts +34 -0
  196. package/node_modules/@xterm/xterm/src/vs/base/common/stopwatch.ts +43 -0
  197. package/node_modules/@xterm/xterm/src/vs/base/common/strings.ts +557 -0
  198. package/node_modules/@xterm/xterm/src/vs/base/common/symbols.ts +9 -0
  199. package/node_modules/@xterm/xterm/src/vs/base/common/uint.ts +59 -0
  200. package/node_modules/@xterm/xterm/src/vs/patches/nls.ts +90 -0
  201. package/node_modules/@xterm/xterm/src/vs/typings/base-common.d.ts +20 -0
  202. package/node_modules/@xterm/xterm/src/vs/typings/require.d.ts +42 -0
  203. package/node_modules/@xterm/xterm/src/vs/typings/vscode-globals-nls.d.ts +36 -0
  204. package/node_modules/@xterm/xterm/src/vs/typings/vscode-globals-product.d.ts +33 -0
  205. package/node_modules/@xterm/xterm/typings/xterm.d.ts +1957 -0
  206. package/node_modules/node-addon-api/LICENSE.md +9 -0
  207. package/node_modules/node-addon-api/README.md +319 -0
  208. package/node_modules/node-addon-api/common.gypi +20 -0
  209. package/node_modules/node-addon-api/except.gypi +25 -0
  210. package/node_modules/node-addon-api/index.js +12 -0
  211. package/node_modules/node-addon-api/napi-inl.deprecated.h +186 -0
  212. package/node_modules/node-addon-api/napi-inl.h +6607 -0
  213. package/node_modules/node-addon-api/napi.h +3201 -0
  214. package/node_modules/node-addon-api/node_addon_api.gyp +32 -0
  215. package/node_modules/node-addon-api/node_api.gyp +9 -0
  216. package/node_modules/node-addon-api/noexcept.gypi +26 -0
  217. package/node_modules/node-addon-api/nothing.c +0 -0
  218. package/node_modules/node-addon-api/package-support.json +21 -0
  219. package/node_modules/node-addon-api/package.json +480 -0
  220. package/node_modules/node-addon-api/tools/README.md +73 -0
  221. package/node_modules/node-addon-api/tools/check-napi.js +99 -0
  222. package/node_modules/node-addon-api/tools/clang-format.js +71 -0
  223. package/node_modules/node-addon-api/tools/conversion.js +301 -0
  224. package/node_modules/node-addon-api/tools/eslint-format.js +79 -0
  225. package/node_modules/node-pty/LICENSE +69 -0
  226. package/node_modules/node-pty/README.md +164 -0
  227. package/node_modules/node-pty/binding.gyp +150 -0
  228. package/node_modules/node-pty/lib/conpty_console_list_agent.js +25 -0
  229. package/node_modules/node-pty/lib/eventEmitter2.js +47 -0
  230. package/node_modules/node-pty/lib/index.js +52 -0
  231. package/node_modules/node-pty/lib/interfaces.js +7 -0
  232. package/node_modules/node-pty/lib/shared/conout.js +10 -0
  233. package/node_modules/node-pty/lib/terminal.js +190 -0
  234. package/node_modules/node-pty/lib/types.js +7 -0
  235. package/node_modules/node-pty/lib/unixTerminal.js +351 -0
  236. package/node_modules/node-pty/lib/utils.js +38 -0
  237. package/node_modules/node-pty/lib/windowsConoutConnection.js +131 -0
  238. package/node_modules/node-pty/lib/windowsPtyAgent.js +344 -0
  239. package/node_modules/node-pty/lib/windowsTerminal.js +209 -0
  240. package/node_modules/node-pty/lib/worker/conoutSocketWorker.js +22 -0
  241. package/node_modules/node-pty/package.json +66 -0
  242. package/node_modules/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
  243. package/node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
  244. package/node_modules/node-pty/prebuilds/darwin-x64/pty.node +0 -0
  245. package/node_modules/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
  246. package/node_modules/node-pty/prebuilds/linux-arm64/pty.node +0 -0
  247. package/node_modules/node-pty/prebuilds/linux-x64/pty.node +0 -0
  248. package/node_modules/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
  249. package/node_modules/node-pty/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
  250. package/node_modules/node-pty/prebuilds/win32-arm64/conpty.node +0 -0
  251. package/node_modules/node-pty/prebuilds/win32-arm64/conpty.pdb +0 -0
  252. package/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.node +0 -0
  253. package/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.pdb +0 -0
  254. package/node_modules/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
  255. package/node_modules/node-pty/prebuilds/win32-x64/conpty/conpty.dll +0 -0
  256. package/node_modules/node-pty/prebuilds/win32-x64/conpty.node +0 -0
  257. package/node_modules/node-pty/prebuilds/win32-x64/conpty.pdb +0 -0
  258. package/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.node +0 -0
  259. package/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.pdb +0 -0
  260. package/node_modules/node-pty/scripts/post-install.js +76 -0
  261. package/node_modules/node-pty/scripts/prebuild.js +34 -0
  262. package/node_modules/node-pty/src/unix/pty.cc +876 -0
  263. package/node_modules/node-pty/src/unix/spawn-helper.cc +23 -0
  264. package/node_modules/node-pty/src/win/conpty.cc +616 -0
  265. package/node_modules/node-pty/src/win/conpty.h +41 -0
  266. package/node_modules/node-pty/src/win/conpty_console_list.cc +44 -0
  267. package/node_modules/node-pty/src/win/path_util.cc +95 -0
  268. package/node_modules/node-pty/src/win/path_util.h +26 -0
  269. package/node_modules/node-pty/third_party/conpty/1.25.260303002/win10-arm64/OpenConsole.exe +0 -0
  270. package/node_modules/node-pty/third_party/conpty/1.25.260303002/win10-arm64/conpty.dll +0 -0
  271. package/node_modules/node-pty/third_party/conpty/1.25.260303002/win10-x64/OpenConsole.exe +0 -0
  272. package/node_modules/node-pty/third_party/conpty/1.25.260303002/win10-x64/conpty.dll +0 -0
  273. package/node_modules/node-pty/typings/node-pty.d.ts +215 -0
  274. package/node_modules/ws/LICENSE +20 -0
  275. package/node_modules/ws/README.md +548 -0
  276. package/node_modules/ws/browser.js +8 -0
  277. package/node_modules/ws/index.js +22 -0
  278. package/node_modules/ws/lib/buffer-util.js +131 -0
  279. package/node_modules/ws/lib/constants.js +19 -0
  280. package/node_modules/ws/lib/event-target.js +292 -0
  281. package/node_modules/ws/lib/extension.js +203 -0
  282. package/node_modules/ws/lib/limiter.js +55 -0
  283. package/node_modules/ws/lib/permessage-deflate.js +530 -0
  284. package/node_modules/ws/lib/receiver.js +743 -0
  285. package/node_modules/ws/lib/sender.js +607 -0
  286. package/node_modules/ws/lib/stream.js +161 -0
  287. package/node_modules/ws/lib/subprotocol.js +62 -0
  288. package/node_modules/ws/lib/validation.js +152 -0
  289. package/node_modules/ws/lib/websocket-server.js +562 -0
  290. package/node_modules/ws/lib/websocket.js +1421 -0
  291. package/node_modules/ws/package.json +74 -0
  292. package/node_modules/ws/wrapper.mjs +21 -0
  293. package/package.json +52 -0
  294. package/src/manager/command-resolver.mjs +140 -0
  295. package/src/manager/config.mjs +94 -0
  296. package/src/manager/install-channels.mjs +268 -0
  297. package/src/manager/main.mjs +136 -0
  298. package/src/manager/providers.mjs +601 -0
  299. package/src/manager/report-shims.mjs +104 -0
  300. package/src/manager/server.mjs +421 -0
  301. package/src/manager/session-manager.mjs +306 -0
  302. package/src/manager/session.mjs +531 -0
  303. package/src/manager/shell-env.mjs +150 -0
  304. package/src/manager/usage.mjs +535 -0
  305. package/src/manager/versions.mjs +62 -0
  306. package/src/report/hooks.mjs +150 -0
  307. package/web/app.js +916 -0
  308. package/web/art/art.css +186 -0
  309. package/web/art/characters/anthropic/idle.png +0 -0
  310. package/web/art/characters/anthropic/locked.png +0 -0
  311. package/web/art/characters/anthropic/working.png +0 -0
  312. package/web/art/characters/google/idle.png +0 -0
  313. package/web/art/characters/google/locked.png +0 -0
  314. package/web/art/characters/google/working.png +0 -0
  315. package/web/art/characters/openai/idle.png +0 -0
  316. package/web/art/characters/openai/locked.png +0 -0
  317. package/web/art/characters/openai/working.png +0 -0
  318. package/web/art/characters/shell/idle.png +0 -0
  319. package/web/art/characters/shell/locked.png +0 -0
  320. package/web/art/characters/shell/working.png +0 -0
  321. package/web/art/characters/xai/idle.png +0 -0
  322. package/web/art/characters/xai/locked.png +0 -0
  323. package/web/art/characters/xai/working.png +0 -0
  324. package/web/art/familiars/aether.png +0 -0
  325. package/web/art/familiars/flame.png +0 -0
  326. package/web/art/familiars/leaf.png +0 -0
  327. package/web/art/familiars/night.png +0 -0
  328. package/web/art/icons/anthropic.png +0 -0
  329. package/web/art/icons/google.png +0 -0
  330. package/web/art/icons/openai.png +0 -0
  331. package/web/art/icons/shell.png +0 -0
  332. package/web/art/icons/xai.png +0 -0
  333. package/web/art/page.png +0 -0
  334. package/web/art/ui/frame.png +0 -0
  335. package/web/art/ui/gem-mana.png +0 -0
  336. package/web/art/ui/gem-vitality.png +0 -0
  337. package/web/art/ui/guild-crest.png +0 -0
  338. package/web/art/ui/level-medallion.png +0 -0
  339. package/web/art/ui/padlock.png +0 -0
  340. package/web/icons/README.md +8 -0
  341. package/web/index.html +154 -0
  342. package/web/styles.css +226 -0
@@ -0,0 +1,601 @@
1
+ // Provider registry: which coding tools can be launched and how.
2
+ //
3
+ // Built-in defaults live in config/providers.default.json. Users customise
4
+ // them with providers.json in the data directory: entries are merged by `id`,
5
+ // new ids are appended, and `"enabled": false` hides a provider. Any field can
6
+ // be overridden per platform under a "win32", "darwin" or "linux" key.
7
+
8
+ import fs from 'node:fs';
9
+ import path from 'node:path';
10
+ import { EventEmitter } from 'node:events';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { resolveCommand, resolveAllCommands, pathKey, buildSpawnSpec, runSpec } from './command-resolver.mjs';
13
+ import { compareVersions, probeVersion, fetchManifest, latestVersion, DEFAULT_NPM_REGISTRY } from './versions.mjs';
14
+ import { CHANNEL_LABELS, classifyInstall, formatCommand, helpDescribes, knownLaunchers, listInstallations, platformDependency } from './install-channels.mjs';
15
+ import { weavePaths } from './shell-env.mjs';
16
+
17
+ const here = path.dirname(fileURLToPath(import.meta.url));
18
+ export const DEFAULTS_FILE = path.resolve(here, '../../config/providers.default.json');
19
+ const ID_RE = /^[a-z0-9][a-z0-9_-]{0,31}$/;
20
+ const PLATFORM_KEYS = ['win32', 'darwin', 'linux'];
21
+ const VERSION_TTL_MS = 60 * 60 * 1000;
22
+ const FAILED_PROBE_TTL_MS = 5 * 60 * 1000;
23
+ const PATH_REFRESH_MS = 60 * 1000;
24
+ const INSTALLS_TTL_MS = 30 * 1000;
25
+
26
+ function fileMtime(file) {
27
+ try { return fs.statSync(file).mtimeMs; } catch { return null; }
28
+ }
29
+
30
+ function refusal(status, code, message) {
31
+ return Object.assign(new Error(message), { status, code });
32
+ }
33
+
34
+ export function defaultShell(env = process.env, platform = process.platform) {
35
+ if (platform === 'win32') return 'powershell.exe';
36
+ return env.SHELL || (platform === 'darwin' ? '/bin/zsh' : '/bin/bash');
37
+ }
38
+
39
+ function readJson(file) {
40
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
41
+ }
42
+
43
+ /** Keep string, number and boolean values as strings; drop anything else. */
44
+ function normalizeEnv(env) {
45
+ if (!env || typeof env !== 'object' || Array.isArray(env)) return {};
46
+ const out = {};
47
+ for (const [key, value] of Object.entries(env)) {
48
+ if (['string', 'number', 'boolean'].includes(typeof value)) out[key] = String(value);
49
+ }
50
+ return out;
51
+ }
52
+
53
+ /** "claude", "codex", "gemini", a { command, args } that prints usage JSON, or null. */
54
+ function normalizeUsage(usage) {
55
+ if (usage === 'claude' || usage === 'codex' || usage === 'gemini') return usage;
56
+ if (usage && typeof usage === 'object' && typeof usage.command === 'string' && usage.command) {
57
+ return { command: usage.command, args: Array.isArray(usage.args) ? usage.args.map(String) : [] };
58
+ }
59
+ return null;
60
+ }
61
+
62
+ function stringList(value) {
63
+ return Array.isArray(value) ? value.map(String).filter(Boolean) : [];
64
+ }
65
+
66
+ function normalizeChannels(raw) {
67
+ const out = {};
68
+ if (!raw || typeof raw !== 'object') return out;
69
+ if (raw.native && typeof raw.native === 'object') {
70
+ out.native = {
71
+ paths: stringList(raw.native.paths),
72
+ update: stringList(raw.native.update),
73
+ uninstall: raw.native.uninstall ? String(raw.native.uninstall) : null,
74
+ sharedWithNpm: raw.native.sharedWithNpm === true,
75
+ };
76
+ }
77
+ if (raw.brew && typeof raw.brew === 'object') out.brew = { names: stringList(raw.brew.names) };
78
+ if (raw.winget && typeof raw.winget === 'object' && raw.winget.id) out.winget = { id: String(raw.winget.id) };
79
+ if (raw.legacy && typeof raw.legacy === 'object') {
80
+ out.legacy = {
81
+ paths: stringList(raw.legacy.paths),
82
+ guidance: raw.legacy.guidance ? String(raw.legacy.guidance) : null,
83
+ uninstall: raw.legacy.uninstall ? String(raw.legacy.uninstall) : null,
84
+ };
85
+ }
86
+ return out;
87
+ }
88
+
89
+ function httpsUrl(value, field, id, warnings) {
90
+ if (value === undefined || value === null || value === '') return null;
91
+ try {
92
+ const url = new URL(String(value));
93
+ if (url.protocol === 'https:') return url.href;
94
+ } catch { /* reported below */ }
95
+ warnings.push(`provider "${id}": ignored ${field} ${JSON.stringify(value)}; it must be an https:// URL`);
96
+ return null;
97
+ }
98
+
99
+ function normalize(raw, platform, warnings) {
100
+ const merged = { ...raw, ...(raw[platform] || {}) };
101
+ for (const key of PLATFORM_KEYS) delete merged[key];
102
+ return {
103
+ id: merged.id,
104
+ vendor: String(merged.vendor || merged.id),
105
+ tool: String(merged.tool || merged.command || ''),
106
+ command: String(merged.command || ''),
107
+ package: merged.package ? String(merged.package) : null,
108
+ versionArgs: Array.isArray(merged.versionArgs) && merged.versionArgs.length ? merged.versionArgs.map(String) : null,
109
+ usage: normalizeUsage(merged.usage),
110
+ modelPattern: merged.modelPattern ? String(merged.modelPattern) : null,
111
+ args: Array.isArray(merged.args) ? merged.args.map(String) : [],
112
+ resumeArgs: Array.isArray(merged.resumeArgs) ? merged.resumeArgs.map(String) : [],
113
+ env: normalizeEnv(merged.env),
114
+ color: String(merged.color || '#64748B'),
115
+ monogram: String(merged.monogram || String(merged.vendor || merged.id).charAt(0)).slice(0, 2),
116
+ icon: merged.icon ? String(merged.icon) : null,
117
+ install: String(merged.install || ''),
118
+ npmNote: merged.npmNote ? String(merged.npmNote) : null,
119
+ channels: normalizeChannels(merged.channels),
120
+ docs: String(merged.docs || ''),
121
+ usageUrl: httpsUrl(merged.usageUrl, 'usageUrl', merged.id, warnings),
122
+ billingUrl: httpsUrl(merged.billingUrl, 'billingUrl', merged.id, warnings),
123
+ enabled: merged.enabled !== false,
124
+ };
125
+ }
126
+
127
+ /**
128
+ * Load providers. Returns { providers, warnings } so a broken user file never
129
+ * prevents the manager from starting.
130
+ */
131
+ export function loadProviders({ userFile, platform = process.platform } = {}) {
132
+ const warnings = [];
133
+ const byId = new Map();
134
+ const order = [];
135
+ const add = (entry, source) => {
136
+ if (!entry || typeof entry !== 'object' || !ID_RE.test(entry.id || '')) {
137
+ warnings.push(`${source}: skipped provider with invalid id ${JSON.stringify(entry && entry.id)}`);
138
+ return;
139
+ }
140
+ if (byId.has(entry.id)) {
141
+ byId.set(entry.id, { ...byId.get(entry.id), ...entry });
142
+ } else {
143
+ byId.set(entry.id, { ...entry });
144
+ order.push(entry.id);
145
+ }
146
+ };
147
+
148
+ for (const entry of readJson(DEFAULTS_FILE).providers) add(entry, 'defaults');
149
+
150
+ if (userFile && fs.existsSync(userFile)) {
151
+ try {
152
+ const user = readJson(userFile);
153
+ const list = Array.isArray(user) ? user : user.providers;
154
+ if (!Array.isArray(list)) throw new Error('expected a "providers" array');
155
+ for (const entry of list) add(entry, userFile);
156
+ } catch (err) {
157
+ warnings.push(`${userFile}: ${err.message}; using built-in providers only`);
158
+ }
159
+ }
160
+
161
+ const providers = order.map((id) => normalize(byId.get(id), platform, warnings)).filter((p) => p.enabled);
162
+ return { providers, warnings };
163
+ }
164
+
165
+ export class ProviderRegistry extends EventEmitter {
166
+ /**
167
+ * @param {object} opts
168
+ * @param {string} [opts.userFile]
169
+ * @param {object} [opts.env]
170
+ * @param {string} [opts.platform]
171
+ * @param {string} [opts.iconDir]
172
+ * @param {string} [opts.registryUrl] npm registry for lookups and installs; default: npm's own configuration
173
+ * @param {boolean} [opts.checkUpdates] false skips registry lookups entirely
174
+ * @param {Function} [opts.fetchImpl]
175
+ */
176
+ constructor({ userFile, env, platform = process.platform, iconDir, registryUrl = null, checkUpdates = true, fetchImpl, pathReader = null } = {}) {
177
+ super();
178
+ this.userFile = userFile;
179
+ this.env = env || process.env;
180
+ this.platform = platform;
181
+ this.iconDir = iconDir;
182
+ this.registryUrl = registryUrl || null;
183
+ this.checkUpdates = checkUpdates;
184
+ this.fetchImpl = fetchImpl;
185
+ this.pathReader = pathReader;
186
+ this._pathReadAt = 0;
187
+ this._installs = new Map();
188
+ this.versions = new Map();
189
+ this._refreshing = null;
190
+ this._npmRegistry = null;
191
+ this.reload();
192
+ }
193
+
194
+ reload() {
195
+ const { providers, warnings } = loadProviders({ userFile: this.userFile, platform: this.platform });
196
+ this.providers = providers;
197
+ this.warnings = warnings;
198
+ this._npmRegistry = null;
199
+ this._installs.clear();
200
+ for (const w of warnings) console.warn(`[providers] ${w}`);
201
+ this.emit('updated');
202
+ }
203
+
204
+ /**
205
+ * The registry that installs use: the configured one, else npm's global
206
+ * configuration, which is what `npm install -g` reads (a project .npmrc
207
+ * in the launch directory does not apply to it).
208
+ */
209
+ npmRegistryUrl() {
210
+ if (this.registryUrl) return Promise.resolve(this.registryUrl);
211
+ this._npmRegistry ??= (async () => {
212
+ const npm = this.resolveNpm();
213
+ if (!npm) return DEFAULT_NPM_REGISTRY;
214
+ try {
215
+ const spec = buildSpawnSpec(npm, ['config', 'get', 'registry', '--global'], this.env, this.platform);
216
+ const url = (await runSpec(spec, { env: this.env, timeoutMs: 10000 })).stdout.trim();
217
+ return /^https?:\/\/\S+$/.test(url) ? url : DEFAULT_NPM_REGISTRY;
218
+ } catch {
219
+ return DEFAULT_NPM_REGISTRY;
220
+ }
221
+ })();
222
+ return this._npmRegistry;
223
+ }
224
+
225
+ /**
226
+ * Check installed and latest versions. Cheap when nothing changed: a
227
+ * tool is re-run only when its file changed, hourly, or a few minutes
228
+ * after a failed probe, and the registry is asked hourly, unless `force`.
229
+ * Emits "updated" when a version changed.
230
+ */
231
+ refreshVersions({ force = false, ids = null } = {}) {
232
+ const run = () => this._refreshVersions({ force, ids });
233
+ const pending = this._refreshing ? this._refreshing.then(run, run) : run();
234
+ this._refreshing = pending;
235
+ pending.finally(() => { if (this._refreshing === pending) this._refreshing = null; }).catch(() => {});
236
+ return pending;
237
+ }
238
+
239
+ async refreshPath({ force = false } = {}) {
240
+ if (!this.pathReader) return false;
241
+ const now = Date.now();
242
+ if (!force && now - this._pathReadAt < PATH_REFRESH_MS) return false;
243
+ this._pathReadAt = now;
244
+ const discovered = await Promise.resolve().then(() => this.pathReader()).catch(() => null);
245
+ if (!discovered) return false;
246
+ const key = pathKey(this.env, this.platform);
247
+ const next = weavePaths(this.env[key] || '', discovered, {
248
+ delimiter: this.platform === 'win32' ? ';' : ':',
249
+ caseInsensitive: this.platform === 'win32',
250
+ });
251
+ if (next === (this.env[key] || '')) return false;
252
+ this.env[key] = next;
253
+ this._installs.clear();
254
+ return true;
255
+ }
256
+
257
+ async _refreshVersions({ force, ids }) {
258
+ const now = Date.now();
259
+ let changed = await this.refreshPath({ force });
260
+ const providers = this.providers.filter((p) => !ids || ids.includes(p.id));
261
+ if (force) for (const provider of providers) this._installs.delete(provider.id);
262
+ const lookups = this.checkUpdates && providers.some((p) => p.package);
263
+ const registryUrl = lookups ? await this.npmRegistryUrl() : null;
264
+ await Promise.all(providers.map(async (provider) => {
265
+ const entry = this.versions.get(provider.id) || {
266
+ installed: null, versionStatus: null, versionError: null, installedPath: null, installedMtime: null, installedAt: 0,
267
+ latest: null, latestAt: 0, probePath: null, probeMtime: null, probeAt: 0, probeOk: null, lastInstall: null, copies: {},
268
+ };
269
+ const found = this.resolve(provider);
270
+ const channel = found ? this.channelFor(provider, found) : null;
271
+ if (channel?.probe) {
272
+ const mtime = fileMtime(found);
273
+ const ttl = entry.probeOk === true ? VERSION_TTL_MS : FAILED_PROBE_TTL_MS;
274
+ if (force || entry.probePath !== found || entry.probeMtime !== mtime || now - entry.probeAt > ttl) {
275
+ const spec = buildSpawnSpec(channel.update.file, [...channel.update.args, '--help'], this.env, this.platform);
276
+ const ok = await runSpec(spec, { env: { ...this.env, ...provider.env } })
277
+ .then(({ stdout, stderr }) => helpDescribes(`${stdout}\n${stderr}`, channel.update.args), () => false);
278
+ changed ||= ok !== entry.probeOk;
279
+ Object.assign(entry, { probePath: found, probeMtime: mtime, probeAt: now, probeOk: ok });
280
+ }
281
+ } else if (entry.probePath !== null) {
282
+ Object.assign(entry, { probePath: null, probeMtime: null, probeAt: 0, probeOk: null });
283
+ changed = true;
284
+ }
285
+ const resolved = provider.versionArgs ? found : null;
286
+ if (resolved) {
287
+ const mtime = fileMtime(resolved);
288
+ const ttl = entry.installed === null ? FAILED_PROBE_TTL_MS : VERSION_TTL_MS;
289
+ const stale = entry.installedPath !== resolved || entry.installedMtime !== mtime || now - entry.installedAt > ttl;
290
+ if (force || stale) {
291
+ const spec = buildSpawnSpec(resolved, provider.versionArgs, this.env, this.platform);
292
+ const probe = await probeVersion(spec, { env: { ...this.env, ...provider.env } });
293
+ const versionStatus = !probe.ok ? 'failed' : probe.version ? 'ok' : 'unavailable';
294
+ changed ||= probe.version !== entry.installed || versionStatus !== entry.versionStatus || probe.error !== entry.versionError;
295
+ Object.assign(entry, {
296
+ installed: probe.version, versionStatus, versionError: probe.error, installedPath: resolved, installedMtime: mtime, installedAt: now,
297
+ });
298
+ }
299
+ } else if (entry.installedPath !== null) {
300
+ Object.assign(entry, { installed: null, versionStatus: null, versionError: null, installedPath: null, installedMtime: null, installedAt: 0 });
301
+ changed = true;
302
+ }
303
+ const copies = {};
304
+ for (const other of provider.versionArgs ? this.installsFor(provider, found).filter((i) => i.resolvedPath !== found) : []) {
305
+ const file = other.resolvedPath;
306
+ const mtime = fileMtime(file);
307
+ const cached = entry.copies[file];
308
+ const ttl = cached?.version ? VERSION_TTL_MS : FAILED_PROBE_TTL_MS;
309
+ if (!force && cached && cached.mtime === mtime && now - cached.at <= ttl) {
310
+ copies[file] = cached;
311
+ continue;
312
+ }
313
+ const probe = await probeVersion(buildSpawnSpec(file, provider.versionArgs, this.env, this.platform), { env: { ...this.env, ...provider.env } });
314
+ const status = !probe.ok ? 'failed' : probe.version ? 'ok' : 'unavailable';
315
+ changed ||= !cached || cached.version !== probe.version || cached.status !== status;
316
+ copies[file] = { version: probe.version, status, mtime, at: now };
317
+ }
318
+ changed ||= Object.keys(entry.copies).length !== Object.keys(copies).length;
319
+ entry.copies = copies;
320
+ if (provider.package && lookups && (force || now - entry.latestAt > VERSION_TTL_MS)) {
321
+ const latest = await latestVersion(provider.package, { registryUrl, fetchImpl: this.fetchImpl });
322
+ changed ||= latest !== entry.latest;
323
+ Object.assign(entry, { latest, latestAt: now });
324
+ }
325
+ const last = entry.lastInstall;
326
+ if (last && (entry.installed !== last.after || entry.latest !== last.latest || entry.versionStatus !== last.verification)) {
327
+ entry.lastInstall = null;
328
+ changed = true;
329
+ }
330
+ this.versions.set(provider.id, entry);
331
+ }));
332
+ if (changed) this.emit('updated');
333
+ }
334
+
335
+ async finishInstall(id, { exitCode = null, kind = 'update' } = {}) {
336
+ const provider = this.get(id);
337
+ if (!provider) return;
338
+ const before = this.versions.get(id)?.installed ?? null;
339
+ this.emit('updated');
340
+ await this.refreshVersions({ force: true, ids: [id] });
341
+ const entry = this.versions.get(id);
342
+ if (!entry) return;
343
+ let outcome;
344
+ if (exitCode !== 0) outcome = 'failed';
345
+ else if (kind === 'install') outcome = this.resolve(provider) ? 'installed' : 'missing';
346
+ else if (entry.installed === null) outcome = 'done';
347
+ else outcome = entry.installed !== before ? 'updated' : 'unchanged';
348
+ entry.lastInstall = {
349
+ kind, outcome, exitCode, verification: entry.versionStatus, before, after: entry.installed, latest: entry.latest, at: Date.now(),
350
+ };
351
+ this.emit('updated');
352
+ }
353
+
354
+ async archFor(npm) {
355
+ const p = this.platform === 'win32' ? path.win32 : path.posix;
356
+ const node = p.join(p.dirname(npm), this.platform === 'win32' ? 'node.exe' : 'node');
357
+ if (!fs.existsSync(node)) return process.arch;
358
+ try {
359
+ const { stdout } = await runSpec({ file: node, args: ['-p', 'process.arch'] }, { env: this.env, timeoutMs: 5000 });
360
+ return stdout.trim() || process.arch;
361
+ } catch {
362
+ return process.arch;
363
+ }
364
+ }
365
+
366
+ async resolveRelease(provider, npm) {
367
+ if (!this.checkUpdates) return 'latest';
368
+ const registryUrl = await this.npmRegistryUrl();
369
+ const lookup = { registryUrl, fetchImpl: this.fetchImpl };
370
+ const { manifest, error } = await fetchManifest(provider.package, 'latest', lookup);
371
+ if (!manifest) {
372
+ throw refusal(503, 'release_unresolved', `Could not read the latest ${provider.tool} release from ${registryUrl}: ${error}. Nothing was changed.`);
373
+ }
374
+ const arch = await this.archFor(npm);
375
+ const build = platformDependency(manifest, provider.package, this.platform, arch);
376
+ if (build) {
377
+ const found = await fetchManifest(build.name, build.version, lookup);
378
+ if (!found.manifest) {
379
+ throw refusal(409, 'release_incomplete',
380
+ `${provider.tool} ${manifest.version} is published, but its ${this.platform}-${arch} build (${build.name}@${build.version}) is not available yet: ${found.error}. Nothing was changed. Try again shortly.`);
381
+ }
382
+ }
383
+ return manifest.version;
384
+ }
385
+
386
+ npmArgs(update, version) {
387
+ const args = [...update.args];
388
+ if (!update.package) return args;
389
+ args.push(`${update.package}@${version}`);
390
+ if (this.registryUrl) args.push('--registry', this.registryUrl);
391
+ return args;
392
+ }
393
+
394
+ channelFor(provider, resolvedPath = this.resolve(provider)) {
395
+ if (!resolvedPath) return null;
396
+ return classifyInstall({
397
+ resolvedPath,
398
+ provider,
399
+ env: { ...this.env, ...provider.env },
400
+ platform: this.platform,
401
+ npmOnPath: this.resolveNpm(),
402
+ wingetOnPath: this.resolveWinget(),
403
+ });
404
+ }
405
+
406
+ resolveWinget() {
407
+ return this.platform === 'win32' ? resolveCommand('winget', this.env, this.platform) : null;
408
+ }
409
+
410
+ installsFor(provider, resolvedPath = this.resolve(provider)) {
411
+ const cached = this._installs.get(provider.id);
412
+ if (cached && cached.resolvedPath === resolvedPath && Date.now() - cached.at < INSTALLS_TTL_MS) return cached.list;
413
+ const list = this.listInstalls(provider);
414
+ this._installs.set(provider.id, { list, resolvedPath, at: Date.now() });
415
+ return list;
416
+ }
417
+
418
+ listInstalls(provider) {
419
+ const env = { ...this.env, ...provider.env };
420
+ const command = this.commandFor(provider);
421
+ const tracked = Boolean(provider.package) || Object.keys(provider.channels).length > 0;
422
+ return listInstallations({
423
+ onPath: tracked ? resolveAllCommands(command, env, this.platform) : [this.resolve(provider)].filter(Boolean),
424
+ known: tracked ? knownLaunchers({ provider, command, env, platform: this.platform }) : [],
425
+ provider,
426
+ env,
427
+ platform: this.platform,
428
+ npmOnPath: this.resolveNpm(),
429
+ wingetOnPath: this.resolveWinget(),
430
+ });
431
+ }
432
+
433
+ installWarnings(provider, installs) {
434
+ const label = (i) => [CHANNEL_LABELS[i.channel], i.version && `v${i.version}`].filter(Boolean).join(' ');
435
+ const active = installs.find((i) => i.active);
436
+ if (!active) return installs.map((i) => `A copy of ${provider.tool} exists at ${i.path}, but its folder is not on PATH.`);
437
+ const warnings = [];
438
+ if (installs.length > 1) {
439
+ warnings.push(`${installs.length} copies of ${provider.tool} are installed. The one in use is ${label(active)} at ${active.path}.`);
440
+ }
441
+ const newer = installs.find((i) => i.newer);
442
+ if (newer) warnings.push(`An older copy comes first on PATH: ${label(active)} is in use while ${label(newer)} is installed at ${newer.path}.`);
443
+ return warnings;
444
+ }
445
+
446
+ updateFor(provider, channel = this.channelFor(provider)) {
447
+ if (!channel) return { file: null, args: [], command: null, guidance: null };
448
+ if (!channel.update) return { file: null, args: [], command: null, guidance: channel.guidance };
449
+ const args = this.npmArgs(channel.update, this.versions.get(provider.id)?.latest ?? 'latest');
450
+ const command = formatCommand(channel.update.file, args);
451
+ if (channel.probe) {
452
+ const probeOk = this.versions.get(provider.id)?.probeOk ?? null;
453
+ if (probeOk === null) return { file: null, args: [], command: null, guidance: null };
454
+ if (probeOk === false) {
455
+ return { file: null, args: [], command: null, guidance: `This copy of ${provider.tool} does not accept "${command}". Update it the way you installed it.` };
456
+ }
457
+ }
458
+ return { file: channel.update.file, args, command, guidance: null };
459
+ }
460
+
461
+ get(id) {
462
+ return this.providers.find((p) => p.id === id) || null;
463
+ }
464
+
465
+ commandFor(provider) {
466
+ return provider.command === '@shell' ? defaultShell(this.env, this.platform) : provider.command;
467
+ }
468
+
469
+ resolve(provider) {
470
+ return resolveCommand(this.commandFor(provider), { ...this.env, ...provider.env }, this.platform);
471
+ }
472
+
473
+ resolveNpm() {
474
+ return resolveCommand('npm', this.env, this.platform);
475
+ }
476
+
477
+ iconUrl(provider) {
478
+ if (provider.icon) return provider.icon;
479
+ if (this.iconDir && fs.existsSync(path.join(this.iconDir, `${provider.id}.svg`))) {
480
+ return `/icons/${provider.id}.svg`;
481
+ }
482
+ return null;
483
+ }
484
+
485
+ /** Public description, including whether the tool is installed. */
486
+ describe(provider) {
487
+ const resolvedPath = this.resolve(provider);
488
+ const versions = this.versions.get(provider.id);
489
+ const installed = resolvedPath ? versions?.installed ?? null : null;
490
+ const latest = versions?.latest ?? null;
491
+ const channel = this.channelFor(provider, resolvedPath);
492
+ const update = this.updateFor(provider, channel);
493
+ const installs = this.installsFor(provider, resolvedPath).map((install) => {
494
+ const active = install.resolvedPath === resolvedPath;
495
+ const copy = active ? { version: installed, status: versions?.versionStatus ?? null } : versions?.copies?.[install.resolvedPath];
496
+ return {
497
+ path: install.resolvedPath,
498
+ channel: install.channel,
499
+ version: copy?.version ?? null,
500
+ versionStatus: copy?.status ?? null,
501
+ active,
502
+ onPath: install.onPath,
503
+ removeCommand: install.removeCommand,
504
+ };
505
+ });
506
+ const inUse = installs.find((i) => i.active)?.version;
507
+ for (const install of installs) {
508
+ install.newer = Boolean(!install.active && inUse && install.version && compareVersions(install.version, inUse) > 0);
509
+ }
510
+ return {
511
+ id: provider.id,
512
+ vendor: provider.vendor,
513
+ tool: provider.tool,
514
+ command: this.commandFor(provider),
515
+ package: provider.package,
516
+ args: provider.args,
517
+ resumable: provider.resumeArgs.length > 0,
518
+ installable: Boolean(provider.package && this.resolveNpm()),
519
+ installedVersion: installed,
520
+ versionStatus: resolvedPath ? versions?.versionStatus ?? null : null,
521
+ versionError: resolvedPath ? versions?.versionError ?? null : null,
522
+ latestVersion: latest,
523
+ updateAvailable: Boolean(installed && latest && compareVersions(latest, installed) > 0),
524
+ installChannel: channel?.channel ?? null,
525
+ updateCommand: update.command,
526
+ updateGuidance: update.guidance,
527
+ lastInstall: versions?.lastInstall ?? null,
528
+ installs,
529
+ warnings: this.installWarnings(provider, installs),
530
+ npmNote: provider.npmNote,
531
+ usageSource: provider.usage === null ? null : typeof provider.usage === 'string' ? provider.usage : 'command',
532
+ modelPattern: provider.modelPattern,
533
+ color: provider.color,
534
+ monogram: provider.monogram,
535
+ iconUrl: this.iconUrl(provider),
536
+ install: provider.install,
537
+ docs: provider.docs,
538
+ usageUrl: provider.usageUrl,
539
+ billingUrl: provider.billingUrl,
540
+ available: Boolean(resolvedPath),
541
+ resolvedPath,
542
+ };
543
+ }
544
+
545
+ list() {
546
+ return this.providers.map((p) => this.describe(p));
547
+ }
548
+
549
+ /** Spawn spec for node-pty, or throws with a user-facing message. */
550
+ spawnSpec(provider, extraArgs = [], resume = null) {
551
+ const resolved = this.resolve(provider);
552
+ if (!resolved) {
553
+ const hint = provider.install ? ` ${provider.install}` : '';
554
+ const err = new Error(`${provider.tool} ("${this.commandFor(provider)}") was not found on PATH.${hint}`);
555
+ err.status = 409;
556
+ err.code = 'provider_unavailable';
557
+ throw err;
558
+ }
559
+ let resumeArgs = [];
560
+ if (resume !== null) {
561
+ if (provider.resumeArgs.length === 0) {
562
+ const err = new Error(`${provider.tool} has no resumeArgs configured, so an existing session cannot be resumed`);
563
+ err.status = 400;
564
+ err.code = 'resume_unsupported';
565
+ throw err;
566
+ }
567
+ resumeArgs = provider.resumeArgs.map((arg) => arg.replaceAll('{id}', resume));
568
+ }
569
+ return buildSpawnSpec(resolved, [...provider.args, ...resumeArgs, ...extraArgs], this.env, this.platform);
570
+ }
571
+
572
+ async updateSpec(provider) {
573
+ const channel = this.channelFor(provider);
574
+ const update = this.updateFor(provider, channel);
575
+ if (!update.command) {
576
+ throw refusal(400, 'not_updatable', update.guidance || `Still checking how ${provider.tool} was installed. Try again in a moment.`);
577
+ }
578
+ const args = channel.update.package
579
+ ? this.npmArgs(channel.update, await this.resolveRelease(provider, update.file))
580
+ : update.args;
581
+ return { spec: buildSpawnSpec(update.file, args, this.env, this.platform), channel: channel.channel };
582
+ }
583
+
584
+ async installSpec(provider) {
585
+ if (!provider.package) {
586
+ const err = new Error(`${provider.tool} has no npm package configured; install it by hand: ${provider.install || provider.docs || 'see its documentation'}`);
587
+ err.status = 400;
588
+ err.code = 'not_installable';
589
+ throw err;
590
+ }
591
+ const npm = this.resolveNpm();
592
+ if (!npm) {
593
+ const err = new Error('npm was not found on PATH. Install Node.js from https://nodejs.org and restart the session manager.');
594
+ err.status = 409;
595
+ err.code = 'npm_unavailable';
596
+ throw err;
597
+ }
598
+ const version = await this.resolveRelease(provider, npm);
599
+ return buildSpawnSpec(npm, this.npmArgs({ args: ['install', '-g'], package: provider.package }, version), this.env, this.platform);
600
+ }
601
+ }