codebase-onboarder 0.6.0 → 0.7.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 (448) hide show
  1. package/README.md +174 -46
  2. package/bin/build-if-source.js +23 -0
  3. package/cli/commands.d.ts +26 -0
  4. package/cli/commands.js +836 -811
  5. package/cli/commands.js.map +1 -0
  6. package/cli/explorer/advanced.d.ts +14 -0
  7. package/cli/explorer/advanced.js +321 -329
  8. package/cli/explorer/advanced.js.map +1 -0
  9. package/cli/explorer/app.d.ts +1 -0
  10. package/cli/explorer/app.js +384 -313
  11. package/cli/explorer/app.js.map +1 -0
  12. package/cli/explorer/assistant.d.ts +9 -0
  13. package/cli/explorer/assistant.js +58 -0
  14. package/cli/explorer/assistant.js.map +1 -0
  15. package/cli/explorer/commands.d.ts +17 -0
  16. package/cli/explorer/commands.js +368 -302
  17. package/cli/explorer/commands.js.map +1 -0
  18. package/cli/explorer/featureViews.d.ts +124 -0
  19. package/cli/explorer/featureViews.js +179 -0
  20. package/cli/explorer/featureViews.js.map +1 -0
  21. package/cli/explorer/github.d.ts +21 -0
  22. package/cli/explorer/github.js +42 -44
  23. package/cli/explorer/github.js.map +1 -0
  24. package/cli/explorer/graphs.d.ts +7 -0
  25. package/cli/explorer/graphs.js +90 -95
  26. package/cli/explorer/graphs.js.map +1 -0
  27. package/cli/explorer/picker.d.ts +22 -0
  28. package/cli/explorer/picker.js +150 -0
  29. package/cli/explorer/picker.js.map +1 -0
  30. package/cli/explorer/report.d.ts +85 -0
  31. package/cli/explorer/report.js +60 -0
  32. package/cli/explorer/report.js.map +1 -0
  33. package/cli/explorer/session.d.ts +449 -0
  34. package/cli/explorer/session.js +143 -144
  35. package/cli/explorer/session.js.map +1 -0
  36. package/cli/explorer/views.d.ts +19 -0
  37. package/cli/explorer/views.js +465 -482
  38. package/cli/explorer/views.js.map +1 -0
  39. package/cli/explorer/wrap.d.ts +1 -0
  40. package/cli/explorer/wrap.js +28 -44
  41. package/cli/explorer/wrap.js.map +1 -0
  42. package/cli/main.d.ts +1 -0
  43. package/cli/main.js +214 -161
  44. package/cli/main.js.map +1 -0
  45. package/cli/prompt.d.ts +5 -0
  46. package/cli/prompt.js +84 -80
  47. package/cli/prompt.js.map +1 -0
  48. package/cli/scanOptions.d.ts +2 -0
  49. package/cli/scanOptions.js +11 -0
  50. package/cli/scanOptions.js.map +1 -0
  51. package/cli/ui.d.ts +33 -0
  52. package/cli/ui.js +35 -44
  53. package/cli/ui.js.map +1 -0
  54. package/cli/wizard.d.ts +187 -0
  55. package/cli/wizard.js +304 -284
  56. package/cli/wizard.js.map +1 -0
  57. package/package.json +15 -4
  58. package/public/app.d.ts +1 -0
  59. package/public/app.js +1057 -1009
  60. package/public/app.js.map +1 -0
  61. package/public/browser.d.ts +68 -0
  62. package/public/browser.js +2 -0
  63. package/public/browser.js.map +1 -0
  64. package/public/index.html +30 -13
  65. package/public/js/about.d.ts +6 -0
  66. package/public/js/about.js +152 -172
  67. package/public/js/about.js.map +1 -0
  68. package/public/js/aiDraft.d.ts +3 -0
  69. package/public/js/aiDraft.js +116 -124
  70. package/public/js/aiDraft.js.map +1 -0
  71. package/public/js/analysisPanel.d.ts +7 -0
  72. package/public/js/analysisPanel.js +166 -166
  73. package/public/js/analysisPanel.js.map +1 -0
  74. package/public/js/analysisReport.d.ts +38 -0
  75. package/public/js/analysisReport.js +105 -110
  76. package/public/js/analysisReport.js.map +1 -0
  77. package/public/js/api.d.ts +26 -0
  78. package/public/js/api.js +176 -167
  79. package/public/js/api.js.map +1 -0
  80. package/public/js/atlas.d.ts +6 -0
  81. package/public/js/atlas.js +50 -58
  82. package/public/js/atlas.js.map +1 -0
  83. package/public/js/blameView.d.ts +2 -0
  84. package/public/js/blameView.js +36 -37
  85. package/public/js/blameView.js.map +1 -0
  86. package/public/js/codeTab.d.ts +3 -0
  87. package/public/js/codeTab.js +175 -180
  88. package/public/js/codeTab.js.map +1 -0
  89. package/public/js/codeViewer.d.ts +5 -0
  90. package/public/js/codeViewer.js +162 -150
  91. package/public/js/codeViewer.js.map +1 -0
  92. package/public/js/components/FileChip.d.ts +9 -0
  93. package/public/js/components/FileChip.js +45 -49
  94. package/public/js/components/FileChip.js.map +1 -0
  95. package/public/js/components/MetricSparkline.d.ts +7 -0
  96. package/public/js/components/MetricSparkline.js +35 -44
  97. package/public/js/components/MetricSparkline.js.map +1 -0
  98. package/public/js/components/RiskBadge.d.ts +9 -0
  99. package/public/js/components/RiskBadge.js +55 -63
  100. package/public/js/components/RiskBadge.js.map +1 -0
  101. package/public/js/deepAnalysisView.d.ts +99 -0
  102. package/public/js/deepAnalysisView.js +282 -302
  103. package/public/js/deepAnalysisView.js.map +1 -0
  104. package/public/js/diagramPane.d.ts +8 -0
  105. package/public/js/diagramPane.js +133 -135
  106. package/public/js/diagramPane.js.map +1 -0
  107. package/public/js/diffView.d.ts +6 -0
  108. package/public/js/diffView.js +222 -209
  109. package/public/js/diffView.js.map +1 -0
  110. package/public/js/docsView.d.ts +2 -0
  111. package/public/js/docsView.js +441 -442
  112. package/public/js/docsView.js.map +1 -0
  113. package/public/js/dom.d.ts +189 -0
  114. package/public/js/dom.js +5 -0
  115. package/public/js/dom.js.map +1 -0
  116. package/public/js/fileSourceBrowser.d.ts +5 -0
  117. package/public/js/fileSourceBrowser.js +33 -41
  118. package/public/js/fileSourceBrowser.js.map +1 -0
  119. package/public/js/flameGraph.d.ts +5 -0
  120. package/public/js/flameGraph.js +62 -72
  121. package/public/js/flameGraph.js.map +1 -0
  122. package/public/js/forceGraph.d.ts +10 -0
  123. package/public/js/forceGraph.js +581 -556
  124. package/public/js/forceGraph.js.map +1 -0
  125. package/public/js/heatmap.d.ts +4 -0
  126. package/public/js/heatmap.js +142 -164
  127. package/public/js/heatmap.js.map +1 -0
  128. package/public/js/highlight.d.ts +2 -0
  129. package/public/js/highlight.js +116 -107
  130. package/public/js/highlight.js.map +1 -0
  131. package/public/js/html.d.ts +2 -0
  132. package/public/js/html.js +14 -44
  133. package/public/js/html.js.map +1 -0
  134. package/public/js/insightsView.d.ts +5 -0
  135. package/public/js/insightsView.js +93 -111
  136. package/public/js/insightsView.js.map +1 -0
  137. package/public/js/inspector.d.ts +37 -0
  138. package/public/js/inspector.js +416 -445
  139. package/public/js/inspector.js.map +1 -0
  140. package/public/js/llm.d.ts +113 -0
  141. package/public/js/llm.js +233 -272
  142. package/public/js/llm.js.map +1 -0
  143. package/public/js/mapView.d.ts +3 -0
  144. package/public/js/mapView.js +121 -120
  145. package/public/js/mapView.js.map +1 -0
  146. package/public/js/markdown.d.ts +3 -0
  147. package/public/js/markdown.js +84 -91
  148. package/public/js/markdown.js.map +1 -0
  149. package/public/js/mindmap.d.ts +32 -0
  150. package/public/js/mindmap.js +244 -259
  151. package/public/js/mindmap.js.map +1 -0
  152. package/public/js/mobilePanels.d.ts +5 -0
  153. package/public/js/mobilePanels.js +50 -0
  154. package/public/js/mobilePanels.js.map +1 -0
  155. package/public/js/repoFiles.d.ts +12 -0
  156. package/public/js/repoFiles.js +28 -27
  157. package/public/js/repoFiles.js.map +1 -0
  158. package/public/js/reviewView.d.ts +28 -0
  159. package/public/js/reviewView.js +256 -0
  160. package/public/js/reviewView.js.map +1 -0
  161. package/public/js/sbomView.d.ts +3 -0
  162. package/public/js/sbomView.js +59 -67
  163. package/public/js/sbomView.js.map +1 -0
  164. package/public/js/scanCache.d.ts +16 -0
  165. package/public/js/scanCache.js +67 -65
  166. package/public/js/scanCache.js.map +1 -0
  167. package/public/js/search.d.ts +7 -0
  168. package/public/js/search.js +868 -800
  169. package/public/js/search.js.map +1 -0
  170. package/public/js/searchLocal.d.ts +42 -0
  171. package/public/js/searchLocal.js +87 -0
  172. package/public/js/searchLocal.js.map +1 -0
  173. package/public/js/serverSettings.d.ts +5 -0
  174. package/public/js/serverSettings.js +153 -164
  175. package/public/js/serverSettings.js.map +1 -0
  176. package/public/js/state.d.ts +798 -0
  177. package/public/js/state.js +114 -122
  178. package/public/js/state.js.map +1 -0
  179. package/public/js/tour.d.ts +6 -0
  180. package/public/js/tour.js +5 -7
  181. package/public/js/tour.js.map +1 -0
  182. package/public/js/transitions.d.ts +2 -0
  183. package/public/js/transitions.js +9 -10
  184. package/public/js/transitions.js.map +1 -0
  185. package/public/js/tree.d.ts +12 -0
  186. package/public/js/tree.js +157 -154
  187. package/public/js/tree.js.map +1 -0
  188. package/public/js/workflowsView.d.ts +3 -0
  189. package/public/js/workflowsView.js +15 -22
  190. package/public/js/workflowsView.js.map +1 -0
  191. package/public/search.css +495 -0
  192. package/public/styles.css +163 -346
  193. package/public/workbench.css +166 -0
  194. package/server/apiAuth.d.ts +3 -0
  195. package/server/apiAuth.js +18 -20
  196. package/server/apiAuth.js.map +1 -0
  197. package/server/apiDiff.d.ts +2 -0
  198. package/server/apiDiff.js +20 -18
  199. package/server/apiDiff.js.map +1 -0
  200. package/server/apiDocs.d.ts +2 -0
  201. package/server/apiDocs.js +38 -40
  202. package/server/apiDocs.js.map +1 -0
  203. package/server/apiFile.d.ts +1 -0
  204. package/server/apiFile.js +14 -17
  205. package/server/apiFile.js.map +1 -0
  206. package/server/apiGitBlame.d.ts +2 -0
  207. package/server/apiGitBlame.js +50 -51
  208. package/server/apiGitBlame.js.map +1 -0
  209. package/server/apiMcp.d.ts +4 -0
  210. package/server/apiMcp.js +64 -66
  211. package/server/apiMcp.js.map +1 -0
  212. package/server/apiReview.d.ts +2 -0
  213. package/server/apiReview.js +45 -0
  214. package/server/apiReview.js.map +1 -0
  215. package/server/apiScan.d.ts +5 -0
  216. package/server/apiScan.js +90 -71
  217. package/server/apiScan.js.map +1 -0
  218. package/server/apiSearch.d.ts +33 -0
  219. package/server/apiSearch.js +184 -200
  220. package/server/apiSearch.js.map +1 -0
  221. package/server/apiSettings.d.ts +4 -0
  222. package/server/apiSettings.js +84 -85
  223. package/server/apiSettings.js.map +1 -0
  224. package/server/apiTools.d.ts +3 -0
  225. package/server/apiTools.js +55 -56
  226. package/server/apiTools.js.map +1 -0
  227. package/server/auth.d.ts +5 -0
  228. package/server/auth.js +54 -51
  229. package/server/auth.js.map +1 -0
  230. package/server/config.d.ts +42 -0
  231. package/server/config.js +189 -194
  232. package/server/config.js.map +1 -0
  233. package/server/daemon.d.ts +12 -0
  234. package/server/daemon.js +124 -114
  235. package/server/daemon.js.map +1 -0
  236. package/server/fileSourceNode.d.ts +2 -0
  237. package/server/fileSourceNode.js +34 -36
  238. package/server/fileSourceNode.js.map +1 -0
  239. package/server/gitClone.d.ts +9 -0
  240. package/server/gitClone.js +59 -61
  241. package/server/gitClone.js.map +1 -0
  242. package/server/gitDiff.d.ts +36 -0
  243. package/server/gitDiff.js +271 -169
  244. package/server/gitDiff.js.map +1 -0
  245. package/server/gitHistory.d.ts +12 -0
  246. package/server/gitHistory.js +80 -80
  247. package/server/gitHistory.js.map +1 -0
  248. package/server/gitRemote.d.ts +12 -0
  249. package/server/gitRemote.js +37 -38
  250. package/server/gitRemote.js.map +1 -0
  251. package/server/htmlText.d.ts +4 -0
  252. package/server/htmlText.js +16 -23
  253. package/server/htmlText.js.map +1 -0
  254. package/server/http.d.ts +5 -0
  255. package/server/http.js +27 -30
  256. package/server/http.js.map +1 -0
  257. package/server/httpGuards.d.ts +2 -0
  258. package/server/httpGuards.js +47 -43
  259. package/server/httpGuards.js.map +1 -0
  260. package/server/https.d.ts +34 -0
  261. package/server/https.js +121 -111
  262. package/server/https.js.map +1 -0
  263. package/server/index.d.ts +40 -0
  264. package/server/index.js +139 -147
  265. package/server/index.js.map +1 -0
  266. package/server/layout.d.ts +26 -0
  267. package/server/layout.js +59 -64
  268. package/server/layout.js.map +1 -0
  269. package/server/llmProxy.d.ts +3 -0
  270. package/server/llmProxy.js +137 -135
  271. package/server/llmProxy.js.map +1 -0
  272. package/server/logger.d.ts +38 -0
  273. package/server/logger.js +198 -211
  274. package/server/logger.js.map +1 -0
  275. package/server/mcp/analysis.d.ts +29 -0
  276. package/server/mcp/analysis.js +99 -120
  277. package/server/mcp/analysis.js.map +1 -0
  278. package/server/mcp/http.d.ts +9 -0
  279. package/server/mcp/http.js +128 -137
  280. package/server/mcp/http.js.map +1 -0
  281. package/server/mcp/runner.d.ts +68 -0
  282. package/server/mcp/runner.js +208 -218
  283. package/server/mcp/runner.js.map +1 -0
  284. package/server/mcp/server.d.ts +29 -0
  285. package/server/mcp/server.js +166 -179
  286. package/server/mcp/server.js.map +1 -0
  287. package/server/mcp/standalone.d.ts +1 -0
  288. package/server/mcp/standalone.js +8 -10
  289. package/server/mcp/standalone.js.map +1 -0
  290. package/server/mcp/tools.d.ts +2020 -0
  291. package/server/mcp/tools.js +523 -574
  292. package/server/mcp/tools.js.map +1 -0
  293. package/server/paths.d.ts +3 -0
  294. package/server/paths.js +17 -15
  295. package/server/paths.js.map +1 -0
  296. package/server/pidfile.d.ts +9 -0
  297. package/server/pidfile.js +43 -45
  298. package/server/pidfile.js.map +1 -0
  299. package/server/review.d.ts +5 -0
  300. package/server/review.js +35 -0
  301. package/server/review.js.map +1 -0
  302. package/server/router.d.ts +33 -0
  303. package/server/router.js +191 -197
  304. package/server/router.js.map +1 -0
  305. package/server/scanRequest.d.ts +3 -0
  306. package/server/scanRequest.js +36 -0
  307. package/server/scanRequest.js.map +1 -0
  308. package/server/searchIndex.d.ts +17 -0
  309. package/server/searchIndex.js +83 -80
  310. package/server/searchIndex.js.map +1 -0
  311. package/server/sessions.d.ts +14 -0
  312. package/server/sessions.js +62 -70
  313. package/server/sessions.js.map +1 -0
  314. package/server/startup.d.ts +118 -0
  315. package/server/startup.js +143 -148
  316. package/server/startup.js.map +1 -0
  317. package/server/static.d.ts +6 -0
  318. package/server/static.js +28 -31
  319. package/server/static.js.map +1 -0
  320. package/server/tools/install.d.ts +4 -0
  321. package/server/tools/install.js +176 -185
  322. package/server/tools/install.js.map +1 -0
  323. package/server/tools/parse.d.ts +8 -0
  324. package/server/tools/parse.js +112 -114
  325. package/server/tools/parse.js.map +1 -0
  326. package/server/tools/platform.d.ts +9 -0
  327. package/server/tools/platform.js +49 -47
  328. package/server/tools/platform.js.map +1 -0
  329. package/server/tools/registry.d.ts +137 -0
  330. package/server/tools/registry.js +173 -172
  331. package/server/tools/registry.js.map +1 -0
  332. package/server/tools/scan.d.ts +34 -0
  333. package/server/tools/scan.js +89 -98
  334. package/server/tools/scan.js.map +1 -0
  335. package/server/tools.d.ts +34 -0
  336. package/server/tools.js +94 -107
  337. package/server/tools.js.map +1 -0
  338. package/server/tunnel.d.ts +29 -0
  339. package/server/tunnel.js +61 -66
  340. package/server/tunnel.js.map +1 -0
  341. package/shared/analyzer/docs.d.ts +16 -0
  342. package/shared/analyzer/docs.js +99 -93
  343. package/shared/analyzer/docs.js.map +1 -0
  344. package/shared/analyzer/explainLocal.d.ts +4 -0
  345. package/shared/analyzer/explainLocal.js +122 -142
  346. package/shared/analyzer/explainLocal.js.map +1 -0
  347. package/shared/analyzer/github.d.ts +37 -0
  348. package/shared/analyzer/github.js +41 -43
  349. package/shared/analyzer/github.js.map +1 -0
  350. package/shared/analyzer/graph.d.ts +41 -0
  351. package/shared/analyzer/graph.js +393 -400
  352. package/shared/analyzer/graph.js.map +1 -0
  353. package/shared/analyzer/health.d.ts +33 -0
  354. package/shared/analyzer/health.js +197 -193
  355. package/shared/analyzer/health.js.map +1 -0
  356. package/shared/analyzer/history.d.ts +29 -0
  357. package/shared/analyzer/history.js +110 -111
  358. package/shared/analyzer/history.js.map +1 -0
  359. package/shared/analyzer/jsonConfig.d.ts +2 -0
  360. package/shared/analyzer/jsonConfig.js +61 -0
  361. package/shared/analyzer/jsonConfig.js.map +1 -0
  362. package/shared/analyzer/languages/csharp.d.ts +26 -0
  363. package/shared/analyzer/languages/csharp.js +83 -88
  364. package/shared/analyzer/languages/csharp.js.map +1 -0
  365. package/shared/analyzer/languages/generic.d.ts +23 -0
  366. package/shared/analyzer/languages/generic.js +94 -105
  367. package/shared/analyzer/languages/generic.js.map +1 -0
  368. package/shared/analyzer/languages/go.d.ts +24 -0
  369. package/shared/analyzer/languages/go.js +45 -54
  370. package/shared/analyzer/languages/go.js.map +1 -0
  371. package/shared/analyzer/languages/index.d.ts +6 -0
  372. package/shared/analyzer/languages/index.js +19 -20
  373. package/shared/analyzer/languages/index.js.map +1 -0
  374. package/shared/analyzer/languages/java.d.ts +20 -0
  375. package/shared/analyzer/languages/java.js +73 -78
  376. package/shared/analyzer/languages/java.js.map +1 -0
  377. package/shared/analyzer/languages/javascript.d.ts +12 -0
  378. package/shared/analyzer/languages/javascript.js +258 -209
  379. package/shared/analyzer/languages/javascript.js.map +1 -0
  380. package/shared/analyzer/languages/python.d.ts +23 -0
  381. package/shared/analyzer/languages/python.js +92 -100
  382. package/shared/analyzer/languages/python.js.map +1 -0
  383. package/shared/analyzer/languages/rust.d.ts +17 -0
  384. package/shared/analyzer/languages/rust.js +96 -98
  385. package/shared/analyzer/languages/rust.js.map +1 -0
  386. package/shared/analyzer/languages/typescript.d.ts +11 -0
  387. package/shared/analyzer/languages/typescript.js +117 -116
  388. package/shared/analyzer/languages/typescript.js.map +1 -0
  389. package/shared/analyzer/licenses.d.ts +18 -0
  390. package/shared/analyzer/licenses.js +130 -133
  391. package/shared/analyzer/licenses.js.map +1 -0
  392. package/shared/analyzer/metrics.d.ts +20 -0
  393. package/shared/analyzer/metrics.js +112 -104
  394. package/shared/analyzer/metrics.js.map +1 -0
  395. package/shared/analyzer/pathUtil.d.ts +10 -0
  396. package/shared/analyzer/pathUtil.js +29 -35
  397. package/shared/analyzer/pathUtil.js.map +1 -0
  398. package/shared/analyzer/patterns.d.ts +11 -0
  399. package/shared/analyzer/patterns.js +231 -253
  400. package/shared/analyzer/patterns.js.map +1 -0
  401. package/shared/analyzer/scan.d.ts +62 -0
  402. package/shared/analyzer/scan.js +451 -442
  403. package/shared/analyzer/scan.js.map +1 -0
  404. package/shared/analyzer/scanControl.d.ts +11 -0
  405. package/shared/analyzer/scanControl.js +62 -0
  406. package/shared/analyzer/scanControl.js.map +1 -0
  407. package/shared/analyzer/security.d.ts +18 -0
  408. package/shared/analyzer/security.js +159 -159
  409. package/shared/analyzer/security.js.map +1 -0
  410. package/shared/analyzer/services.d.ts +5 -0
  411. package/shared/analyzer/services.js +141 -138
  412. package/shared/analyzer/services.js.map +1 -0
  413. package/shared/analyzer/stack.d.ts +6 -0
  414. package/shared/analyzer/stack.js +134 -141
  415. package/shared/analyzer/stack.js.map +1 -0
  416. package/shared/analyzer/tour.d.ts +2 -0
  417. package/shared/analyzer/tour.js +45 -53
  418. package/shared/analyzer/tour.js.map +1 -0
  419. package/shared/analyzer/util.d.ts +8 -0
  420. package/shared/analyzer/util.js +130 -76
  421. package/shared/analyzer/util.js.map +1 -0
  422. package/shared/analyzer/workflows.d.ts +8 -0
  423. package/shared/analyzer/workflows.js +139 -134
  424. package/shared/analyzer/workflows.js.map +1 -0
  425. package/shared/contracts.d.ts +250 -0
  426. package/shared/contracts.js +2 -0
  427. package/shared/contracts.js.map +1 -0
  428. package/shared/diagram/aiFacts.d.ts +35 -0
  429. package/shared/diagram/aiFacts.js +102 -105
  430. package/shared/diagram/aiFacts.js.map +1 -0
  431. package/shared/diagram/aiMermaid.d.ts +5 -0
  432. package/shared/diagram/aiMermaid.js +46 -45
  433. package/shared/diagram/aiMermaid.js.map +1 -0
  434. package/shared/diagram/atlas.d.ts +16 -0
  435. package/shared/diagram/atlas.js +51 -60
  436. package/shared/diagram/atlas.js.map +1 -0
  437. package/shared/diagram/mermaid.d.ts +43 -0
  438. package/shared/diagram/mermaid.js +348 -370
  439. package/shared/diagram/mermaid.js.map +1 -0
  440. package/shared/review/contracts.d.ts +95 -0
  441. package/shared/review/contracts.js +2 -0
  442. package/shared/review/contracts.js.map +1 -0
  443. package/shared/review/review.d.ts +10 -0
  444. package/shared/review/review.js +184 -0
  445. package/shared/review/review.js.map +1 -0
  446. package/shared/search/query.d.ts +32 -0
  447. package/shared/search/query.js +395 -388
  448. package/shared/search/query.js.map +1 -0
@@ -11,32 +11,26 @@
11
11
  // shell, no user-supplied arguments — the one thing this runner executes is a
12
12
  // path built from this repository's own directory, so there is no injection
13
13
  // surface here even though the tool server can read any folder it is pointed at.
14
-
15
14
  import { spawn } from 'node:child_process';
16
15
  import path from 'node:path';
17
16
  import { fileURLToPath } from 'node:url';
18
-
19
17
  import { mcpStatus } from './tools.js';
20
-
21
18
  const here = path.dirname(fileURLToPath(import.meta.url));
22
19
  // server/mcp/ -> server/ -> repository root
23
20
  export const REPO_ROOT = path.resolve(here, '..', '..');
24
21
  export const ENTRY = path.join(here, 'standalone.js');
25
-
26
22
  // How long to wait for a graceful stop before killing. SIGTERM lets Node finish
27
23
  // what it is doing; a hard kill would be an acceptable fallback, but only after
28
24
  // this long, because a scan in progress deserves the chance to finish.
29
25
  const STOP_GRACE_MS = 1500;
30
-
31
26
  // The command a client is configured with, and the only one this file will ever
32
27
  // run. It is a function rather than a constant string in a template because a
33
28
  // client config is a promise about what is actually happening: the path in the
34
29
  // README, the path in the copy box, and the argv the runner builds all have to be
35
30
  // the same string, and this is the one place it is written.
36
31
  export function mcpCommand() {
37
- return path.relative(REPO_ROOT, ENTRY);
32
+ return path.relative(REPO_ROOT, ENTRY);
38
33
  }
39
-
40
34
  // The absolute form, for anything a client will execute.
41
35
  //
42
36
  // The runner can launch `server/mcp/standalone.js` relative to `cwd` because it
@@ -45,234 +39,230 @@ export function mcpCommand() {
45
39
  // that fails only after it has been pasted somewhere real. The copy box and the
46
40
  // README therefore both use this, and only the runner gets the relative one.
47
41
  export function mcpEntryPoint() {
48
- return ENTRY;
42
+ return ENTRY;
49
43
  }
50
-
51
44
  //
52
45
  // `override` exists so a test can substitute a command — one that exits at once,
53
46
  // one that answers the handshake wrong — without the production path growing a
54
47
  // test-only branch. It is the whole argument or nothing: a half-overridden config
55
48
  // would spawn something that is neither the real server nor the fake.
56
-
57
49
  export function mcpConfig(override) {
58
- if (override) {
50
+ if (override) {
51
+ return {
52
+ command: override.command,
53
+ args: override.args || [],
54
+ cwd: override.cwd || REPO_ROOT,
55
+ };
56
+ }
59
57
  return {
60
- command: override.command,
61
- args: override.args || [],
62
- cwd: override.cwd || REPO_ROOT,
58
+ command: process.execPath,
59
+ args: [ENTRY],
60
+ cwd: REPO_ROOT,
63
61
  };
64
- }
65
- return {
66
- command: process.execPath,
67
- args: [ENTRY],
68
- cwd: REPO_ROOT,
69
- };
70
62
  }
71
-
72
63
  export class McpRunner {
73
- get running() {
74
- return this.state === 'running' || this.state === 'starting';
75
- }
76
-
77
- note(line) {
78
- if (!line) return;
79
- const entry = { at: Date.now(), line };
80
- this.log.push(entry);
81
- // Bounded, because this is a status panel, not a log file.
82
- if (this.log.length > 100) this.log.shift();
83
- this.onLog(entry);
84
- }
85
-
86
- // `command`/`args`/`cwd` are the whole argv override, handed straight to
87
- // `mcpConfig`. Accepting them flat rather than as one nested object is what
88
- // every caller naturally reaches for — `new McpRunner({ command, args })` — and
89
- // the tests need it to point the runner at a fake child. The runner itself has
90
- // no idea what it is launching: a runner that knew would be a second place
91
- // where the entry point is written down, and the two could drift.
92
- constructor({ onLog, command, args, cwd } = {}) {
93
- this.commandOverride = command
94
- ? { command, args: args || [], ...(cwd ? { cwd } : {}) }
95
- : null;
96
- this.child = null;
97
- this.state = 'stopped'; // stopped | starting | running | stopping
98
- this.startedAt = null;
99
- this.lastError = null;
100
- // The tail of the child's output, kept for the UI. An MCP child that dies
101
- // usually says why just before it goes, and "it stopped" with no reason is
102
- // the single most annoying thing a status panel can tell you.
103
- this.log = [];
104
- this.onLog = onLog || (() => {});
105
- }
106
-
107
- async start() {
108
- if (this.running) return this.status();
109
- this.state = 'starting';
110
- this.lastError = null;
111
- this.log = [];
112
-
113
- // Built from the same function the config box shows. If those could differ,
114
- // the button would be reporting on a different server than the one a client
115
- // launches — which is worse than having no button.
116
- const cfg = mcpConfig(this.commandOverride);
117
- const child = spawn(cfg.command, cfg.args, {
118
- cwd: cfg.cwd,
119
- stdio: ['pipe', 'pipe', 'pipe'],
120
- env: { ...process.env, ONBOARDER_MCP: '1', LOG_LEVEL: 'warn' },
121
- // No shell: the command is a fixed argv, and a shell would only add a way
122
- // for something to be interpreted.
123
- shell: false,
124
- });
125
- this.child = child;
126
-
127
- child.stdout.setEncoding('utf8');
128
- child.stderr.setEncoding('utf8');
129
- // Only stderr is a log. stdout is the MCP protocol stream: logging it would
130
- // fill the panel with JSON-RPC frames, and the one that matters — the
131
- // handshake reply — is consumed by `handshake` below. The stream is drained
132
- // regardless, because a pipe nobody reads eventually blocks the writer.
133
- child.stdout.on('data', () => {});
134
- child.stderr.on('data', (chunk) => this.note(String(chunk).trimEnd()));
135
-
136
- const exited = new Promise((resolve) => {
137
- child.once('exit', (code, signal) => {
138
- const wasStopping = this.state === 'stopping';
64
+ commandOverride;
65
+ child;
66
+ state;
67
+ startedAt;
68
+ lastError;
69
+ log;
70
+ onLog;
71
+ get running() {
72
+ return this.state === 'running' || this.state === 'starting';
73
+ }
74
+ note(line) {
75
+ if (!line)
76
+ return;
77
+ const entry = { at: Date.now(), line };
78
+ this.log.push(entry);
79
+ // Bounded, because this is a status panel, not a log file.
80
+ if (this.log.length > 100)
81
+ this.log.shift();
82
+ this.onLog(entry);
83
+ }
84
+ // `command`/`args`/`cwd` are the whole argv override, handed straight to
85
+ // `mcpConfig`. Accepting them flat rather than as one nested object is what
86
+ // every caller naturally reaches for — `new McpRunner({ command, args })` — and
87
+ // the tests need it to point the runner at a fake child. The runner itself has
88
+ // no idea what it is launching: a runner that knew would be a second place
89
+ // where the entry point is written down, and the two could drift.
90
+ constructor({ onLog, command, args, cwd } = {}) {
91
+ this.commandOverride = command
92
+ ? { command, args: args || [], ...(cwd ? { cwd } : {}) }
93
+ : null;
139
94
  this.child = null;
140
- this.state = 'stopped';
95
+ this.state = 'stopped'; // stopped | starting | running | stopping
141
96
  this.startedAt = null;
142
- if (!wasStopping) {
143
- this.lastError = signal
144
- ? `Stopped unexpectedly (${signal}).`
145
- : `Stopped unexpectedly (exit code ${code}).`;
146
- this.note(this.lastError);
97
+ this.lastError = null;
98
+ // The tail of the child's output, kept for the UI. An MCP child that dies
99
+ // usually says why just before it goes, and "it stopped" with no reason is
100
+ // the single most annoying thing a status panel can tell you.
101
+ this.log = [];
102
+ this.onLog = onLog || ((..._args) => { });
103
+ }
104
+ async start() {
105
+ if (this.running)
106
+ return this.status();
107
+ this.state = 'starting';
108
+ this.lastError = null;
109
+ this.log = [];
110
+ // Built from the same function the config box shows. If those could differ,
111
+ // the button would be reporting on a different server than the one a client
112
+ // launches — which is worse than having no button.
113
+ const cfg = mcpConfig(this.commandOverride);
114
+ const child = spawn(cfg.command, cfg.args, {
115
+ cwd: cfg.cwd,
116
+ stdio: ['pipe', 'pipe', 'pipe'],
117
+ env: { ...process.env, ONBOARDER_MCP: '1', LOG_LEVEL: 'warn' },
118
+ // No shell: the command is a fixed argv, and a shell would only add a way
119
+ // for something to be interpreted.
120
+ shell: false,
121
+ });
122
+ this.child = child;
123
+ child.stdout.setEncoding('utf8');
124
+ child.stderr.setEncoding('utf8');
125
+ // Only stderr is a log. stdout is the MCP protocol stream: logging it would
126
+ // fill the panel with JSON-RPC frames, and the one that matters — the
127
+ // handshake reply — is consumed by `handshake` below. The stream is drained
128
+ // regardless, because a pipe nobody reads eventually blocks the writer.
129
+ child.stdout.on('data', (..._args) => { });
130
+ child.stderr.on('data', (chunk) => this.note(String(chunk).trimEnd()));
131
+ const exited = new Promise((resolve) => {
132
+ child.once('exit', (code, signal) => {
133
+ const wasStopping = this.state === 'stopping';
134
+ this.child = null;
135
+ this.state = 'stopped';
136
+ this.startedAt = null;
137
+ if (!wasStopping) {
138
+ this.lastError = signal
139
+ ? `Stopped unexpectedly (${signal}).`
140
+ : `Stopped unexpectedly (exit code ${code}).`;
141
+ this.note(this.lastError);
142
+ }
143
+ resolve({ code, signal });
144
+ });
145
+ });
146
+ child.once('error', (err) => {
147
+ this.lastError = `Could not start: ${err.message}`;
148
+ this.state = 'stopped';
149
+ this.child = null;
150
+ this.note(this.lastError);
151
+ });
152
+ // A handshake proves the server is not merely spawned but actually answering
153
+ // MCP. "running" that means the process exists is how a broken server ends up
154
+ // looking healthy in the UI.
155
+ const ok = await this.handshake(exited);
156
+ if (ok) {
157
+ this.state = 'running';
158
+ this.startedAt = Date.now();
159
+ this.note('MCP server ready on stdio.');
160
+ }
161
+ else if (this.child) {
162
+ await this.stop();
147
163
  }
148
- resolve({ code, signal });
149
- });
150
- });
151
-
152
- child.once('error', (err) => {
153
- this.lastError = `Could not start: ${err.message}`;
154
- this.state = 'stopped';
155
- this.child = null;
156
- this.note(this.lastError);
157
- });
158
-
159
- // A handshake proves the server is not merely spawned but actually answering
160
- // MCP. "running" that means the process exists is how a broken server ends up
161
- // looking healthy in the UI.
162
- const ok = await this.handshake(exited);
163
- if (ok) {
164
- this.state = 'running';
165
- this.startedAt = Date.now();
166
- this.note('MCP server ready on stdio.');
167
- } else if (this.child) {
168
- await this.stop();
169
- } else {
170
- this.state = 'stopped';
164
+ else {
165
+ this.state = 'stopped';
166
+ }
167
+ return this.status();
171
168
  }
172
- return this.status();
173
- }
174
-
175
- // The MCP handshake, spoken to our own child: initialize, then the
176
- // `notifications/initialized` the spec requires before ordinary traffic.
177
- async handshake(exited) {
178
- const child = this.child;
179
- if (!child) return false;
180
-
181
- return new Promise((resolve) => {
182
- let buffer = '';
183
- let settled = false;
184
- const finish = (ok) => {
185
- if (settled) return;
186
- settled = true;
187
- clearTimeout(timer);
188
- child.stdout.off('data', onData);
189
- // Resolve now, not on exit. The child is *supposed* to stay running, so
190
- // waiting for it to exit would mean this promise only ever settled when
191
- // something had already gone wrong.
192
- resolve(ok && this.child !== null);
193
- };
194
- const onData = (chunk) => {
195
- buffer += chunk;
196
- let nl;
197
- while ((nl = buffer.indexOf('\n')) !== -1) {
198
- const line = buffer.slice(0, nl).trim();
199
- buffer = buffer.slice(nl + 1);
200
- if (!line) continue;
201
- try {
202
- const msg = JSON.parse(line);
203
- if (msg?.id === 'onboarder-probe' && msg.result?.serverInfo?.name === 'onboarder') {
204
- child.stdin.write(JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized' }) + '\n');
205
- finish(true);
206
- return;
207
- }
208
- } catch {
209
- // A line that is not JSON during the handshake is a bug elsewhere —
210
- // something wrote to stdout that should not have. Keep reading: the
211
- // real initialize reply may still arrive.
212
- }
169
+ // The MCP handshake, spoken to our own child: initialize, then the
170
+ // `notifications/initialized` the spec requires before ordinary traffic.
171
+ async handshake(exited) {
172
+ const child = this.child;
173
+ if (!child)
174
+ return false;
175
+ return new Promise((resolve) => {
176
+ let buffer = '';
177
+ let settled = false;
178
+ const finish = (ok) => {
179
+ if (settled)
180
+ return;
181
+ settled = true;
182
+ clearTimeout(timer);
183
+ child.stdout.off('data', onData);
184
+ // Resolve now, not on exit. The child is *supposed* to stay running, so
185
+ // waiting for it to exit would mean this promise only ever settled when
186
+ // something had already gone wrong.
187
+ resolve(ok && this.child !== null);
188
+ };
189
+ const onData = (chunk) => {
190
+ buffer += chunk;
191
+ let nl;
192
+ while ((nl = buffer.indexOf('\n')) !== -1) {
193
+ const line = buffer.slice(0, nl).trim();
194
+ buffer = buffer.slice(nl + 1);
195
+ if (!line)
196
+ continue;
197
+ try {
198
+ const msg = JSON.parse(line);
199
+ if (msg?.id === 'onboarder-probe' && msg.result?.serverInfo?.name === 'onboarder') {
200
+ child.stdin.write(JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized' }) + '\n');
201
+ finish(true);
202
+ return;
203
+ }
204
+ }
205
+ catch {
206
+ // A line that is not JSON during the handshake is a bug elsewhere —
207
+ // something wrote to stdout that should not have. Keep reading: the
208
+ // real initialize reply may still arrive.
209
+ }
210
+ }
211
+ };
212
+ const timer = setTimeout(() => {
213
+ this.lastError = 'The MCP server did not answer its handshake within 5s.';
214
+ this.note(this.lastError);
215
+ finish(false);
216
+ }, 5000);
217
+ child.stdout.on('data', onData);
218
+ // If the child dies first, do not wait out the full timeout.
219
+ exited.then(() => finish(false));
220
+ child.stdin.write(JSON.stringify({
221
+ jsonrpc: '2.0',
222
+ id: 'onboarder-probe',
223
+ method: 'initialize',
224
+ params: {
225
+ protocolVersion: '2025-06-18',
226
+ capabilities: {},
227
+ clientInfo: { name: 'onboarder-ui', version: '1.0.0' },
228
+ },
229
+ }) + '\n');
230
+ });
231
+ }
232
+ async stop() {
233
+ const child = this.child;
234
+ if (!child) {
235
+ this.state = 'stopped';
236
+ return this.status();
213
237
  }
214
- };
215
-
216
- const timer = setTimeout(() => {
217
- this.lastError = 'The MCP server did not answer its handshake within 5s.';
218
- this.note(this.lastError);
219
- finish(false);
220
- }, 5000);
221
-
222
- child.stdout.on('data', onData);
223
- // If the child dies first, do not wait out the full timeout.
224
- exited.then(() => finish(false));
225
-
226
- child.stdin.write(JSON.stringify({
227
- jsonrpc: '2.0',
228
- id: 'onboarder-probe',
229
- method: 'initialize',
230
- params: {
231
- protocolVersion: '2025-06-18',
232
- capabilities: {},
233
- clientInfo: { name: 'onboarder-ui', version: '1.0.0' },
234
- },
235
- }) + '\n');
236
- });
237
- }
238
-
239
- async stop() {
240
- const child = this.child;
241
- if (!child) {
242
- this.state = 'stopped';
243
- return this.status();
238
+ this.state = 'stopping';
239
+ // Closing stdin is the polite shutdown: `serveMcp` drains what is queued and
240
+ // lets the loop empty, so a request in flight gets its answer.
241
+ const exited = new Promise((resolve) => child.once('exit', resolve));
242
+ child.stdin.end();
243
+ const timer = setTimeout(() => child.kill('SIGKILL'), STOP_GRACE_MS);
244
+ await exited;
245
+ clearTimeout(timer);
246
+ this.child = null;
247
+ this.state = 'stopped';
248
+ this.startedAt = null;
249
+ this.note('MCP server stopped.');
250
+ return this.status();
251
+ }
252
+ status() {
253
+ return {
254
+ ...mcpStatus(),
255
+ state: this.state,
256
+ running: this.running,
257
+ pid: this.child?.pid ?? null,
258
+ startedAt: this.startedAt,
259
+ uptimeMs: this.startedAt ? Date.now() - this.startedAt : 0,
260
+ lastError: this.lastError,
261
+ log: this.log.slice(-20),
262
+ };
244
263
  }
245
- this.state = 'stopping';
246
-
247
- // Closing stdin is the polite shutdown: `serveMcp` drains what is queued and
248
- // lets the loop empty, so a request in flight gets its answer.
249
- const exited = new Promise((resolve) => child.once('exit', resolve));
250
- child.stdin.end();
251
- const timer = setTimeout(() => child.kill('SIGKILL'), STOP_GRACE_MS);
252
-
253
- await exited;
254
- clearTimeout(timer);
255
- this.child = null;
256
- this.state = 'stopped';
257
- this.startedAt = null;
258
- this.note('MCP server stopped.');
259
- return this.status();
260
- }
261
-
262
- status() {
263
- return {
264
- ...mcpStatus(),
265
- state: this.state,
266
- running: this.running,
267
- pid: this.child?.pid ?? null,
268
- startedAt: this.startedAt,
269
- uptimeMs: this.startedAt ? Date.now() - this.startedAt : 0,
270
- lastError: this.lastError,
271
- log: this.log.slice(-20),
272
- };
273
- }
274
264
  }
275
-
276
265
  export function createMcpRunner(opts) {
277
- return new McpRunner(opts);
266
+ return new McpRunner(opts);
278
267
  }
268
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/server/mcp/runner.ts"],"names":[],"mappings":"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","sourcesContent":["// The process runner. The HTTP server owns one of these; the topbar button calls\n// `start` and `stop` on it.\n//\n// Why a child process rather than an HTTP endpoint: the MCP stdio transport *is*\n// the contract. A client config points at a command and speaks JSON-RPC to its\n// stdin/stdout. There is no port to connect to, and nothing to authenticate,\n// which is why this transport is the right one for a local-first tool and why it\n// must stay local if it is ever exposed at all.\n//\n// The child is deliberately plain: `node server/mcp/standalone.js`. No `npx`, no\n// shell, no user-supplied arguments — the one thing this runner executes is a\n// path built from this repository's own directory, so there is no injection\n// surface here even though the tool server can read any folder it is pointed at.\n\nimport { spawn } from 'node:child_process';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { mcpStatus } from './tools.js';\n\nconst here = path.dirname(fileURLToPath(import.meta.url));\n// server/mcp/ -> server/ -> repository root\nexport const REPO_ROOT = path.resolve(here, '..', '..');\nexport const ENTRY = path.join(here, 'standalone.js');\n\n// How long to wait for a graceful stop before killing. SIGTERM lets Node finish\n// what it is doing; a hard kill would be an acceptable fallback, but only after\n// this long, because a scan in progress deserves the chance to finish.\nconst STOP_GRACE_MS = 1500;\n\n// The command a client is configured with, and the only one this file will ever\n// run. It is a function rather than a constant string in a template because a\n// client config is a promise about what is actually happening: the path in the\n// README, the path in the copy box, and the argv the runner builds all have to be\n// the same string, and this is the one place it is written.\nexport function mcpCommand() {\n return path.relative(REPO_ROOT, ENTRY);\n}\n\n// The absolute form, for anything a client will execute.\n//\n// The runner can launch `server/mcp/standalone.js` relative to `cwd` because it\n// sets `cwd` itself. A client cannot: it spawns the command wherever the user's\n// harness happens to live, so a relative path in a copied config is a command\n// that fails only after it has been pasted somewhere real. The copy box and the\n// README therefore both use this, and only the runner gets the relative one.\nexport function mcpEntryPoint() {\n return ENTRY;\n}\n\n//\n// `override` exists so a test can substitute a command — one that exits at once,\n// one that answers the handshake wrong — without the production path growing a\n// test-only branch. It is the whole argument or nothing: a half-overridden config\n// would spawn something that is neither the real server nor the fake.\n\nexport function mcpConfig(override) {\n if (override) {\n return {\n command: override.command,\n args: override.args || [],\n cwd: override.cwd || REPO_ROOT,\n };\n }\n return {\n command: process.execPath,\n args: [ENTRY],\n cwd: REPO_ROOT,\n };\n}\n\nexport class McpRunner {\n commandOverride: any;\n child: any;\n state: string;\n startedAt: any;\n lastError: string;\n log: any[];\n onLog: any;\n\n get running() {\n return this.state === 'running' || this.state === 'starting';\n }\n\n note(line) {\n if (!line) return;\n const entry = { at: Date.now(), line };\n this.log.push(entry);\n // Bounded, because this is a status panel, not a log file.\n if (this.log.length > 100) this.log.shift();\n this.onLog(entry);\n }\n\n // `command`/`args`/`cwd` are the whole argv override, handed straight to\n // `mcpConfig`. Accepting them flat rather than as one nested object is what\n // every caller naturally reaches for — `new McpRunner({ command, args })` — and\n // the tests need it to point the runner at a fake child. The runner itself has\n // no idea what it is launching: a runner that knew would be a second place\n // where the entry point is written down, and the two could drift.\n constructor({ onLog, command, args, cwd }: Record<string, any> = {}) {\n this.commandOverride = command\n ? { command, args: args || [], ...(cwd ? { cwd } : {}) }\n : null;\n this.child = null;\n this.state = 'stopped'; // stopped | starting | running | stopping\n this.startedAt = null;\n this.lastError = null;\n // The tail of the child's output, kept for the UI. An MCP child that dies\n // usually says why just before it goes, and \"it stopped\" with no reason is\n // the single most annoying thing a status panel can tell you.\n this.log = [];\n this.onLog = onLog || ((..._args: unknown[]) => {});\n }\n\n async start() {\n if (this.running) return this.status();\n this.state = 'starting';\n this.lastError = null;\n this.log = [];\n\n // Built from the same function the config box shows. If those could differ,\n // the button would be reporting on a different server than the one a client\n // launches — which is worse than having no button.\n const cfg = mcpConfig(this.commandOverride);\n const child = spawn(cfg.command, cfg.args, {\n cwd: cfg.cwd,\n stdio: ['pipe', 'pipe', 'pipe'],\n env: { ...process.env, ONBOARDER_MCP: '1', LOG_LEVEL: 'warn' },\n // No shell: the command is a fixed argv, and a shell would only add a way\n // for something to be interpreted.\n shell: false,\n });\n this.child = child;\n\n child.stdout.setEncoding('utf8');\n child.stderr.setEncoding('utf8');\n // Only stderr is a log. stdout is the MCP protocol stream: logging it would\n // fill the panel with JSON-RPC frames, and the one that matters — the\n // handshake reply — is consumed by `handshake` below. The stream is drained\n // regardless, because a pipe nobody reads eventually blocks the writer.\n child.stdout.on('data', (..._args: unknown[]) => {});\n child.stderr.on('data', (chunk) => this.note(String(chunk).trimEnd()));\n\n const exited = new Promise((resolve) => {\n child.once('exit', (code, signal) => {\n const wasStopping = this.state === 'stopping';\n this.child = null;\n this.state = 'stopped';\n this.startedAt = null;\n if (!wasStopping) {\n this.lastError = signal\n ? `Stopped unexpectedly (${signal}).`\n : `Stopped unexpectedly (exit code ${code}).`;\n this.note(this.lastError);\n }\n resolve({ code, signal });\n });\n });\n\n child.once('error', (err) => {\n this.lastError = `Could not start: ${err.message}`;\n this.state = 'stopped';\n this.child = null;\n this.note(this.lastError);\n });\n\n // A handshake proves the server is not merely spawned but actually answering\n // MCP. \"running\" that means the process exists is how a broken server ends up\n // looking healthy in the UI.\n const ok = await this.handshake(exited);\n if (ok) {\n this.state = 'running';\n this.startedAt = Date.now();\n this.note('MCP server ready on stdio.');\n } else if (this.child) {\n await this.stop();\n } else {\n this.state = 'stopped';\n }\n return this.status();\n }\n\n // The MCP handshake, spoken to our own child: initialize, then the\n // `notifications/initialized` the spec requires before ordinary traffic.\n async handshake(exited) {\n const child = this.child;\n if (!child) return false;\n\n return new Promise((resolve) => {\n let buffer = '';\n let settled = false;\n const finish = (ok) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n child.stdout.off('data', onData);\n // Resolve now, not on exit. The child is *supposed* to stay running, so\n // waiting for it to exit would mean this promise only ever settled when\n // something had already gone wrong.\n resolve(ok && this.child !== null);\n };\n const onData = (chunk) => {\n buffer += chunk;\n let nl;\n while ((nl = buffer.indexOf('\\n')) !== -1) {\n const line = buffer.slice(0, nl).trim();\n buffer = buffer.slice(nl + 1);\n if (!line) continue;\n try {\n const msg = JSON.parse(line);\n if (msg?.id === 'onboarder-probe' && msg.result?.serverInfo?.name === 'onboarder') {\n child.stdin.write(JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized' }) + '\\n');\n finish(true);\n return;\n }\n } catch {\n // A line that is not JSON during the handshake is a bug elsewhere —\n // something wrote to stdout that should not have. Keep reading: the\n // real initialize reply may still arrive.\n }\n }\n };\n\n const timer = setTimeout(() => {\n this.lastError = 'The MCP server did not answer its handshake within 5s.';\n this.note(this.lastError);\n finish(false);\n }, 5000);\n\n child.stdout.on('data', onData);\n // If the child dies first, do not wait out the full timeout.\n exited.then(() => finish(false));\n\n child.stdin.write(JSON.stringify({\n jsonrpc: '2.0',\n id: 'onboarder-probe',\n method: 'initialize',\n params: {\n protocolVersion: '2025-06-18',\n capabilities: {},\n clientInfo: { name: 'onboarder-ui', version: '1.0.0' },\n },\n }) + '\\n');\n });\n }\n\n async stop() {\n const child = this.child;\n if (!child) {\n this.state = 'stopped';\n return this.status();\n }\n this.state = 'stopping';\n\n // Closing stdin is the polite shutdown: `serveMcp` drains what is queued and\n // lets the loop empty, so a request in flight gets its answer.\n const exited = new Promise((resolve) => child.once('exit', resolve));\n child.stdin.end();\n const timer = setTimeout(() => child.kill('SIGKILL'), STOP_GRACE_MS);\n\n await exited;\n clearTimeout(timer);\n this.child = null;\n this.state = 'stopped';\n this.startedAt = null;\n this.note('MCP server stopped.');\n return this.status();\n }\n\n status() {\n return {\n ...mcpStatus(),\n state: this.state,\n running: this.running,\n pid: this.child?.pid ?? null,\n startedAt: this.startedAt,\n uptimeMs: this.startedAt ? Date.now() - this.startedAt : 0,\n lastError: this.lastError,\n log: this.log.slice(-20),\n };\n }\n}\n\nexport function createMcpRunner(opts) {\n return new McpRunner(opts);\n}\n"]}
@@ -0,0 +1,29 @@
1
+ export declare const PROTOCOL_VERSION = "2025-06-18";
2
+ export declare const SERVER_INFO: {
3
+ name: string;
4
+ version: string;
5
+ title: string;
6
+ instructions: string;
7
+ };
8
+ export { handle };
9
+ declare function handle(msg: any): Promise<{
10
+ jsonrpc: string;
11
+ id: any;
12
+ result: any;
13
+ } | {
14
+ jsonrpc: string;
15
+ id: any;
16
+ error: {
17
+ code: number;
18
+ message: string;
19
+ data?: unknown;
20
+ };
21
+ }>;
22
+ /**
23
+ * Run the server until stdin closes. `input` and `output` are parameters so tests
24
+ * can drive a whole session through in-memory streams.
25
+ */
26
+ export declare function serveMcp({ input, output }?: Record<string, any>): {
27
+ stop(): void;
28
+ settled(): Promise<void>;
29
+ };