codebase-onboarder 0.6.0 → 1.0.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 (526) hide show
  1. package/README.md +284 -53
  2. package/bin/build-if-source.js +23 -0
  3. package/bin/onboarder.js +0 -0
  4. package/cli/agent/command.d.ts +71 -0
  5. package/cli/agent/command.js +177 -0
  6. package/cli/agent/command.js.map +1 -0
  7. package/cli/agent/config.d.ts +31 -0
  8. package/cli/agent/config.js +98 -0
  9. package/cli/agent/config.js.map +1 -0
  10. package/cli/agent/contracts.d.ts +77 -0
  11. package/cli/agent/contracts.js +2 -0
  12. package/cli/agent/contracts.js.map +1 -0
  13. package/cli/agent/files.d.ts +19 -0
  14. package/cli/agent/files.js +109 -0
  15. package/cli/agent/files.js.map +1 -0
  16. package/cli/agent/gitSource.d.ts +18 -0
  17. package/cli/agent/gitSource.js +69 -0
  18. package/cli/agent/gitSource.js.map +1 -0
  19. package/cli/agent/github.d.ts +21 -0
  20. package/cli/agent/github.js +94 -0
  21. package/cli/agent/github.js.map +1 -0
  22. package/cli/agent/mcp.d.ts +15 -0
  23. package/cli/agent/mcp.js +78 -0
  24. package/cli/agent/mcp.js.map +1 -0
  25. package/cli/agent/process.d.ts +18 -0
  26. package/cli/agent/process.js +118 -0
  27. package/cli/agent/process.js.map +1 -0
  28. package/cli/agent/protocol.d.ts +3 -0
  29. package/cli/agent/protocol.js +26 -0
  30. package/cli/agent/protocol.js.map +1 -0
  31. package/cli/agent/runner.d.ts +34 -0
  32. package/cli/agent/runner.js +152 -0
  33. package/cli/agent/runner.js.map +1 -0
  34. package/cli/agent/stdio.d.ts +1 -0
  35. package/cli/agent/stdio.js +62 -0
  36. package/cli/agent/stdio.js.map +1 -0
  37. package/cli/agent/tools.d.ts +7 -0
  38. package/cli/agent/tools.js +201 -0
  39. package/cli/agent/tools.js.map +1 -0
  40. package/cli/chat/app.d.ts +16 -0
  41. package/cli/chat/app.js +345 -0
  42. package/cli/chat/app.js.map +1 -0
  43. package/cli/chat/commands.d.ts +11 -0
  44. package/cli/chat/commands.js +120 -0
  45. package/cli/chat/commands.js.map +1 -0
  46. package/cli/chat/composer.d.ts +75 -0
  47. package/cli/chat/composer.js +467 -0
  48. package/cli/chat/composer.js.map +1 -0
  49. package/cli/chat/controller.d.ts +60 -0
  50. package/cli/chat/controller.js +393 -0
  51. package/cli/chat/controller.js.map +1 -0
  52. package/cli/chat/logo.d.ts +3 -0
  53. package/cli/chat/logo.js +14 -0
  54. package/cli/chat/logo.js.map +1 -0
  55. package/cli/chat/models.d.ts +18 -0
  56. package/cli/chat/models.js +88 -0
  57. package/cli/chat/models.js.map +1 -0
  58. package/cli/chat/profile.d.ts +5 -0
  59. package/cli/chat/profile.js +98 -0
  60. package/cli/chat/profile.js.map +1 -0
  61. package/cli/chat/render.d.ts +40 -0
  62. package/cli/chat/render.js +259 -0
  63. package/cli/chat/render.js.map +1 -0
  64. package/cli/chat/screen.d.ts +26 -0
  65. package/cli/chat/screen.js +117 -0
  66. package/cli/chat/screen.js.map +1 -0
  67. package/cli/chat/source.d.ts +29 -0
  68. package/cli/chat/source.js +116 -0
  69. package/cli/chat/source.js.map +1 -0
  70. package/cli/chat/store.d.ts +43 -0
  71. package/cli/chat/store.js +94 -0
  72. package/cli/chat/store.js.map +1 -0
  73. package/cli/chat/text.d.ts +4 -0
  74. package/cli/chat/text.js +27 -0
  75. package/cli/chat/text.js.map +1 -0
  76. package/cli/commands.d.ts +26 -0
  77. package/cli/commands.js +836 -811
  78. package/cli/commands.js.map +1 -0
  79. package/cli/explorer/advanced.d.ts +14 -0
  80. package/cli/explorer/advanced.js +321 -329
  81. package/cli/explorer/advanced.js.map +1 -0
  82. package/cli/explorer/app.d.ts +2 -0
  83. package/cli/explorer/app.js +404 -314
  84. package/cli/explorer/app.js.map +1 -0
  85. package/cli/explorer/assistant.d.ts +9 -0
  86. package/cli/explorer/assistant.js +58 -0
  87. package/cli/explorer/assistant.js.map +1 -0
  88. package/cli/explorer/commands.d.ts +17 -0
  89. package/cli/explorer/commands.js +373 -302
  90. package/cli/explorer/commands.js.map +1 -0
  91. package/cli/explorer/featureViews.d.ts +124 -0
  92. package/cli/explorer/featureViews.js +179 -0
  93. package/cli/explorer/featureViews.js.map +1 -0
  94. package/cli/explorer/github.d.ts +21 -0
  95. package/cli/explorer/github.js +42 -44
  96. package/cli/explorer/github.js.map +1 -0
  97. package/cli/explorer/graphs.d.ts +7 -0
  98. package/cli/explorer/graphs.js +90 -95
  99. package/cli/explorer/graphs.js.map +1 -0
  100. package/cli/explorer/picker.d.ts +22 -0
  101. package/cli/explorer/picker.js +150 -0
  102. package/cli/explorer/picker.js.map +1 -0
  103. package/cli/explorer/report.d.ts +85 -0
  104. package/cli/explorer/report.js +60 -0
  105. package/cli/explorer/report.js.map +1 -0
  106. package/cli/explorer/session.d.ts +449 -0
  107. package/cli/explorer/session.js +143 -144
  108. package/cli/explorer/session.js.map +1 -0
  109. package/cli/explorer/views.d.ts +19 -0
  110. package/cli/explorer/views.js +465 -482
  111. package/cli/explorer/views.js.map +1 -0
  112. package/cli/explorer/wrap.d.ts +1 -0
  113. package/cli/explorer/wrap.js +28 -44
  114. package/cli/explorer/wrap.js.map +1 -0
  115. package/cli/main.d.ts +1 -0
  116. package/cli/main.js +251 -164
  117. package/cli/main.js.map +1 -0
  118. package/cli/prompt.d.ts +5 -0
  119. package/cli/prompt.js +84 -80
  120. package/cli/prompt.js.map +1 -0
  121. package/cli/scanOptions.d.ts +2 -0
  122. package/cli/scanOptions.js +11 -0
  123. package/cli/scanOptions.js.map +1 -0
  124. package/cli/ui.d.ts +33 -0
  125. package/cli/ui.js +35 -44
  126. package/cli/ui.js.map +1 -0
  127. package/cli/wizard.d.ts +187 -0
  128. package/cli/wizard.js +304 -284
  129. package/cli/wizard.js.map +1 -0
  130. package/docs/HERMES_RESEARCH.md +51 -0
  131. package/package.json +16 -4
  132. package/public/app.d.ts +1 -0
  133. package/public/app.js +1133 -1011
  134. package/public/app.js.map +1 -0
  135. package/public/assets/onboarder-mark.svg +11 -0
  136. package/public/browser.d.ts +71 -0
  137. package/public/browser.js +2 -0
  138. package/public/browser.js.map +1 -0
  139. package/public/index.html +54 -20
  140. package/public/js/about.d.ts +6 -0
  141. package/public/js/about.js +152 -172
  142. package/public/js/about.js.map +1 -0
  143. package/public/js/aiDraft.d.ts +4 -0
  144. package/public/js/aiDraft.js +166 -125
  145. package/public/js/aiDraft.js.map +1 -0
  146. package/public/js/analysisPanel.d.ts +7 -0
  147. package/public/js/analysisPanel.js +166 -166
  148. package/public/js/analysisPanel.js.map +1 -0
  149. package/public/js/analysisReport.d.ts +38 -0
  150. package/public/js/analysisReport.js +105 -110
  151. package/public/js/analysisReport.js.map +1 -0
  152. package/public/js/api.d.ts +29 -0
  153. package/public/js/api.js +198 -166
  154. package/public/js/api.js.map +1 -0
  155. package/public/js/atlas.d.ts +6 -0
  156. package/public/js/atlas.js +50 -58
  157. package/public/js/atlas.js.map +1 -0
  158. package/public/js/blameView.d.ts +2 -0
  159. package/public/js/blameView.js +36 -37
  160. package/public/js/blameView.js.map +1 -0
  161. package/public/js/codeTab.d.ts +3 -0
  162. package/public/js/codeTab.js +175 -180
  163. package/public/js/codeTab.js.map +1 -0
  164. package/public/js/codeViewer.d.ts +5 -0
  165. package/public/js/codeViewer.js +162 -150
  166. package/public/js/codeViewer.js.map +1 -0
  167. package/public/js/components/FileChip.d.ts +9 -0
  168. package/public/js/components/FileChip.js +45 -49
  169. package/public/js/components/FileChip.js.map +1 -0
  170. package/public/js/components/MetricSparkline.d.ts +7 -0
  171. package/public/js/components/MetricSparkline.js +35 -44
  172. package/public/js/components/MetricSparkline.js.map +1 -0
  173. package/public/js/components/RiskBadge.d.ts +9 -0
  174. package/public/js/components/RiskBadge.js +55 -63
  175. package/public/js/components/RiskBadge.js.map +1 -0
  176. package/public/js/deepAnalysisView.d.ts +99 -0
  177. package/public/js/deepAnalysisView.js +282 -302
  178. package/public/js/deepAnalysisView.js.map +1 -0
  179. package/public/js/diagramPane.d.ts +9 -0
  180. package/public/js/diagramPane.js +138 -135
  181. package/public/js/diagramPane.js.map +1 -0
  182. package/public/js/diffView.d.ts +6 -0
  183. package/public/js/diffView.js +222 -209
  184. package/public/js/diffView.js.map +1 -0
  185. package/public/js/docsView.d.ts +2 -0
  186. package/public/js/docsView.js +441 -442
  187. package/public/js/docsView.js.map +1 -0
  188. package/public/js/dom.d.ts +197 -0
  189. package/public/js/dom.js +5 -0
  190. package/public/js/dom.js.map +1 -0
  191. package/public/js/fileSourceBrowser.d.ts +5 -0
  192. package/public/js/fileSourceBrowser.js +33 -41
  193. package/public/js/fileSourceBrowser.js.map +1 -0
  194. package/public/js/flameGraph.d.ts +5 -0
  195. package/public/js/flameGraph.js +62 -72
  196. package/public/js/flameGraph.js.map +1 -0
  197. package/public/js/forceGraph.d.ts +10 -0
  198. package/public/js/forceGraph.js +581 -556
  199. package/public/js/forceGraph.js.map +1 -0
  200. package/public/js/heatmap.d.ts +4 -0
  201. package/public/js/heatmap.js +142 -164
  202. package/public/js/heatmap.js.map +1 -0
  203. package/public/js/highlight.d.ts +2 -0
  204. package/public/js/highlight.js +116 -107
  205. package/public/js/highlight.js.map +1 -0
  206. package/public/js/html.d.ts +2 -0
  207. package/public/js/html.js +14 -44
  208. package/public/js/html.js.map +1 -0
  209. package/public/js/insightsView.d.ts +5 -0
  210. package/public/js/insightsView.js +93 -111
  211. package/public/js/insightsView.js.map +1 -0
  212. package/public/js/inspector.d.ts +37 -0
  213. package/public/js/inspector.js +416 -445
  214. package/public/js/inspector.js.map +1 -0
  215. package/public/js/llm.d.ts +115 -0
  216. package/public/js/llm.js +246 -278
  217. package/public/js/llm.js.map +1 -0
  218. package/public/js/mapView.d.ts +3 -0
  219. package/public/js/mapView.js +121 -120
  220. package/public/js/mapView.js.map +1 -0
  221. package/public/js/markdown.d.ts +3 -0
  222. package/public/js/markdown.js +84 -91
  223. package/public/js/markdown.js.map +1 -0
  224. package/public/js/mindmap.d.ts +32 -0
  225. package/public/js/mindmap.js +244 -259
  226. package/public/js/mindmap.js.map +1 -0
  227. package/public/js/mobilePanels.d.ts +5 -0
  228. package/public/js/mobilePanels.js +50 -0
  229. package/public/js/mobilePanels.js.map +1 -0
  230. package/public/js/repoFiles.d.ts +12 -0
  231. package/public/js/repoFiles.js +29 -28
  232. package/public/js/repoFiles.js.map +1 -0
  233. package/public/js/reviewView.d.ts +28 -0
  234. package/public/js/reviewView.js +256 -0
  235. package/public/js/reviewView.js.map +1 -0
  236. package/public/js/sbomView.d.ts +3 -0
  237. package/public/js/sbomView.js +59 -67
  238. package/public/js/sbomView.js.map +1 -0
  239. package/public/js/scanCache.d.ts +16 -0
  240. package/public/js/scanCache.js +67 -65
  241. package/public/js/scanCache.js.map +1 -0
  242. package/public/js/search.d.ts +7 -0
  243. package/public/js/search.js +868 -800
  244. package/public/js/search.js.map +1 -0
  245. package/public/js/searchLocal.d.ts +42 -0
  246. package/public/js/searchLocal.js +87 -0
  247. package/public/js/searchLocal.js.map +1 -0
  248. package/public/js/serverSettings.d.ts +5 -0
  249. package/public/js/serverSettings.js +153 -164
  250. package/public/js/serverSettings.js.map +1 -0
  251. package/public/js/state.d.ts +798 -0
  252. package/public/js/state.js +114 -122
  253. package/public/js/state.js.map +1 -0
  254. package/public/js/tour.d.ts +6 -0
  255. package/public/js/tour.js +5 -7
  256. package/public/js/tour.js.map +1 -0
  257. package/public/js/transitions.d.ts +2 -0
  258. package/public/js/transitions.js +9 -10
  259. package/public/js/transitions.js.map +1 -0
  260. package/public/js/tree.d.ts +12 -0
  261. package/public/js/tree.js +157 -154
  262. package/public/js/tree.js.map +1 -0
  263. package/public/js/workflowsView.d.ts +3 -0
  264. package/public/js/workflowsView.js +15 -22
  265. package/public/js/workflowsView.js.map +1 -0
  266. package/public/search.css +495 -0
  267. package/public/styles.css +188 -346
  268. package/public/workbench.css +166 -0
  269. package/server/apiAuth.d.ts +3 -0
  270. package/server/apiAuth.js +18 -20
  271. package/server/apiAuth.js.map +1 -0
  272. package/server/apiDiff.d.ts +2 -0
  273. package/server/apiDiff.js +20 -18
  274. package/server/apiDiff.js.map +1 -0
  275. package/server/apiDocs.d.ts +2 -0
  276. package/server/apiDocs.js +38 -40
  277. package/server/apiDocs.js.map +1 -0
  278. package/server/apiFile.d.ts +1 -0
  279. package/server/apiFile.js +14 -17
  280. package/server/apiFile.js.map +1 -0
  281. package/server/apiGitBlame.d.ts +2 -0
  282. package/server/apiGitBlame.js +50 -51
  283. package/server/apiGitBlame.js.map +1 -0
  284. package/server/apiMcp.d.ts +4 -0
  285. package/server/apiMcp.js +64 -66
  286. package/server/apiMcp.js.map +1 -0
  287. package/server/apiReview.d.ts +2 -0
  288. package/server/apiReview.js +45 -0
  289. package/server/apiReview.js.map +1 -0
  290. package/server/apiScan.d.ts +5 -0
  291. package/server/apiScan.js +90 -71
  292. package/server/apiScan.js.map +1 -0
  293. package/server/apiSearch.d.ts +33 -0
  294. package/server/apiSearch.js +184 -200
  295. package/server/apiSearch.js.map +1 -0
  296. package/server/apiSettings.d.ts +4 -0
  297. package/server/apiSettings.js +84 -85
  298. package/server/apiSettings.js.map +1 -0
  299. package/server/apiTools.d.ts +3 -0
  300. package/server/apiTools.js +55 -56
  301. package/server/apiTools.js.map +1 -0
  302. package/server/auth.d.ts +5 -0
  303. package/server/auth.js +54 -51
  304. package/server/auth.js.map +1 -0
  305. package/server/config.d.ts +42 -0
  306. package/server/config.js +189 -194
  307. package/server/config.js.map +1 -0
  308. package/server/daemon.d.ts +12 -0
  309. package/server/daemon.js +124 -114
  310. package/server/daemon.js.map +1 -0
  311. package/server/fileSourceNode.d.ts +2 -0
  312. package/server/fileSourceNode.js +34 -36
  313. package/server/fileSourceNode.js.map +1 -0
  314. package/server/gitClone.d.ts +9 -0
  315. package/server/gitClone.js +59 -61
  316. package/server/gitClone.js.map +1 -0
  317. package/server/gitDiff.d.ts +36 -0
  318. package/server/gitDiff.js +271 -169
  319. package/server/gitDiff.js.map +1 -0
  320. package/server/gitHistory.d.ts +12 -0
  321. package/server/gitHistory.js +80 -80
  322. package/server/gitHistory.js.map +1 -0
  323. package/server/gitRemote.d.ts +12 -0
  324. package/server/gitRemote.js +37 -38
  325. package/server/gitRemote.js.map +1 -0
  326. package/server/hermesChat.d.ts +13 -0
  327. package/server/hermesChat.js +145 -0
  328. package/server/hermesChat.js.map +1 -0
  329. package/server/htmlText.d.ts +4 -0
  330. package/server/htmlText.js +16 -23
  331. package/server/htmlText.js.map +1 -0
  332. package/server/http.d.ts +6 -0
  333. package/server/http.js +27 -34
  334. package/server/http.js.map +1 -0
  335. package/server/httpGuards.d.ts +2 -0
  336. package/server/httpGuards.js +47 -43
  337. package/server/httpGuards.js.map +1 -0
  338. package/server/https.d.ts +34 -0
  339. package/server/https.js +121 -111
  340. package/server/https.js.map +1 -0
  341. package/server/index.d.ts +40 -0
  342. package/server/index.js +139 -147
  343. package/server/index.js.map +1 -0
  344. package/server/layout.d.ts +26 -0
  345. package/server/layout.js +59 -64
  346. package/server/layout.js.map +1 -0
  347. package/server/llmProxy.d.ts +3 -0
  348. package/server/llmProxy.js +137 -135
  349. package/server/llmProxy.js.map +1 -0
  350. package/server/logger.d.ts +38 -0
  351. package/server/logger.js +198 -211
  352. package/server/logger.js.map +1 -0
  353. package/server/mcp/analysis.d.ts +29 -0
  354. package/server/mcp/analysis.js +99 -120
  355. package/server/mcp/analysis.js.map +1 -0
  356. package/server/mcp/http.d.ts +9 -0
  357. package/server/mcp/http.js +128 -137
  358. package/server/mcp/http.js.map +1 -0
  359. package/server/mcp/runner.d.ts +68 -0
  360. package/server/mcp/runner.js +208 -218
  361. package/server/mcp/runner.js.map +1 -0
  362. package/server/mcp/server.d.ts +29 -0
  363. package/server/mcp/server.js +167 -180
  364. package/server/mcp/server.js.map +1 -0
  365. package/server/mcp/standalone.d.ts +1 -0
  366. package/server/mcp/standalone.js +8 -10
  367. package/server/mcp/standalone.js.map +1 -0
  368. package/server/mcp/tools.d.ts +2020 -0
  369. package/server/mcp/tools.js +523 -574
  370. package/server/mcp/tools.js.map +1 -0
  371. package/server/paths.d.ts +3 -0
  372. package/server/paths.js +17 -15
  373. package/server/paths.js.map +1 -0
  374. package/server/pidfile.d.ts +9 -0
  375. package/server/pidfile.js +43 -45
  376. package/server/pidfile.js.map +1 -0
  377. package/server/review.d.ts +5 -0
  378. package/server/review.js +35 -0
  379. package/server/review.js.map +1 -0
  380. package/server/router.d.ts +33 -0
  381. package/server/router.js +195 -197
  382. package/server/router.js.map +1 -0
  383. package/server/scanRequest.d.ts +3 -0
  384. package/server/scanRequest.js +36 -0
  385. package/server/scanRequest.js.map +1 -0
  386. package/server/searchIndex.d.ts +17 -0
  387. package/server/searchIndex.js +83 -80
  388. package/server/searchIndex.js.map +1 -0
  389. package/server/sessions.d.ts +14 -0
  390. package/server/sessions.js +62 -70
  391. package/server/sessions.js.map +1 -0
  392. package/server/startup.d.ts +118 -0
  393. package/server/startup.js +143 -148
  394. package/server/startup.js.map +1 -0
  395. package/server/static.d.ts +6 -0
  396. package/server/static.js +28 -31
  397. package/server/static.js.map +1 -0
  398. package/server/tools/install.d.ts +4 -0
  399. package/server/tools/install.js +176 -185
  400. package/server/tools/install.js.map +1 -0
  401. package/server/tools/parse.d.ts +8 -0
  402. package/server/tools/parse.js +112 -114
  403. package/server/tools/parse.js.map +1 -0
  404. package/server/tools/platform.d.ts +9 -0
  405. package/server/tools/platform.js +49 -47
  406. package/server/tools/platform.js.map +1 -0
  407. package/server/tools/registry.d.ts +137 -0
  408. package/server/tools/registry.js +173 -172
  409. package/server/tools/registry.js.map +1 -0
  410. package/server/tools/scan.d.ts +34 -0
  411. package/server/tools/scan.js +89 -98
  412. package/server/tools/scan.js.map +1 -0
  413. package/server/tools.d.ts +34 -0
  414. package/server/tools.js +94 -107
  415. package/server/tools.js.map +1 -0
  416. package/server/tunnel.d.ts +29 -0
  417. package/server/tunnel.js +61 -66
  418. package/server/tunnel.js.map +1 -0
  419. package/shared/analyzer/docs.d.ts +16 -0
  420. package/shared/analyzer/docs.js +99 -93
  421. package/shared/analyzer/docs.js.map +1 -0
  422. package/shared/analyzer/explainLocal.d.ts +4 -0
  423. package/shared/analyzer/explainLocal.js +122 -142
  424. package/shared/analyzer/explainLocal.js.map +1 -0
  425. package/shared/analyzer/github.d.ts +37 -0
  426. package/shared/analyzer/github.js +41 -43
  427. package/shared/analyzer/github.js.map +1 -0
  428. package/shared/analyzer/graph.d.ts +41 -0
  429. package/shared/analyzer/graph.js +393 -400
  430. package/shared/analyzer/graph.js.map +1 -0
  431. package/shared/analyzer/health.d.ts +33 -0
  432. package/shared/analyzer/health.js +197 -193
  433. package/shared/analyzer/health.js.map +1 -0
  434. package/shared/analyzer/history.d.ts +29 -0
  435. package/shared/analyzer/history.js +110 -111
  436. package/shared/analyzer/history.js.map +1 -0
  437. package/shared/analyzer/jsonConfig.d.ts +2 -0
  438. package/shared/analyzer/jsonConfig.js +61 -0
  439. package/shared/analyzer/jsonConfig.js.map +1 -0
  440. package/shared/analyzer/languages/csharp.d.ts +26 -0
  441. package/shared/analyzer/languages/csharp.js +83 -88
  442. package/shared/analyzer/languages/csharp.js.map +1 -0
  443. package/shared/analyzer/languages/generic.d.ts +23 -0
  444. package/shared/analyzer/languages/generic.js +94 -105
  445. package/shared/analyzer/languages/generic.js.map +1 -0
  446. package/shared/analyzer/languages/go.d.ts +24 -0
  447. package/shared/analyzer/languages/go.js +45 -54
  448. package/shared/analyzer/languages/go.js.map +1 -0
  449. package/shared/analyzer/languages/index.d.ts +6 -0
  450. package/shared/analyzer/languages/index.js +19 -20
  451. package/shared/analyzer/languages/index.js.map +1 -0
  452. package/shared/analyzer/languages/java.d.ts +20 -0
  453. package/shared/analyzer/languages/java.js +73 -78
  454. package/shared/analyzer/languages/java.js.map +1 -0
  455. package/shared/analyzer/languages/javascript.d.ts +12 -0
  456. package/shared/analyzer/languages/javascript.js +258 -209
  457. package/shared/analyzer/languages/javascript.js.map +1 -0
  458. package/shared/analyzer/languages/python.d.ts +23 -0
  459. package/shared/analyzer/languages/python.js +92 -100
  460. package/shared/analyzer/languages/python.js.map +1 -0
  461. package/shared/analyzer/languages/rust.d.ts +17 -0
  462. package/shared/analyzer/languages/rust.js +96 -98
  463. package/shared/analyzer/languages/rust.js.map +1 -0
  464. package/shared/analyzer/languages/typescript.d.ts +11 -0
  465. package/shared/analyzer/languages/typescript.js +117 -116
  466. package/shared/analyzer/languages/typescript.js.map +1 -0
  467. package/shared/analyzer/licenses.d.ts +18 -0
  468. package/shared/analyzer/licenses.js +130 -133
  469. package/shared/analyzer/licenses.js.map +1 -0
  470. package/shared/analyzer/metrics.d.ts +20 -0
  471. package/shared/analyzer/metrics.js +112 -104
  472. package/shared/analyzer/metrics.js.map +1 -0
  473. package/shared/analyzer/pathUtil.d.ts +10 -0
  474. package/shared/analyzer/pathUtil.js +29 -35
  475. package/shared/analyzer/pathUtil.js.map +1 -0
  476. package/shared/analyzer/patterns.d.ts +11 -0
  477. package/shared/analyzer/patterns.js +231 -253
  478. package/shared/analyzer/patterns.js.map +1 -0
  479. package/shared/analyzer/scan.d.ts +62 -0
  480. package/shared/analyzer/scan.js +451 -442
  481. package/shared/analyzer/scan.js.map +1 -0
  482. package/shared/analyzer/scanControl.d.ts +11 -0
  483. package/shared/analyzer/scanControl.js +62 -0
  484. package/shared/analyzer/scanControl.js.map +1 -0
  485. package/shared/analyzer/security.d.ts +18 -0
  486. package/shared/analyzer/security.js +159 -159
  487. package/shared/analyzer/security.js.map +1 -0
  488. package/shared/analyzer/services.d.ts +5 -0
  489. package/shared/analyzer/services.js +141 -138
  490. package/shared/analyzer/services.js.map +1 -0
  491. package/shared/analyzer/stack.d.ts +6 -0
  492. package/shared/analyzer/stack.js +134 -141
  493. package/shared/analyzer/stack.js.map +1 -0
  494. package/shared/analyzer/tour.d.ts +2 -0
  495. package/shared/analyzer/tour.js +45 -53
  496. package/shared/analyzer/tour.js.map +1 -0
  497. package/shared/analyzer/util.d.ts +8 -0
  498. package/shared/analyzer/util.js +130 -76
  499. package/shared/analyzer/util.js.map +1 -0
  500. package/shared/analyzer/workflows.d.ts +8 -0
  501. package/shared/analyzer/workflows.js +139 -134
  502. package/shared/analyzer/workflows.js.map +1 -0
  503. package/shared/contracts.d.ts +250 -0
  504. package/shared/contracts.js +2 -0
  505. package/shared/contracts.js.map +1 -0
  506. package/shared/diagram/aiFacts.d.ts +35 -0
  507. package/shared/diagram/aiFacts.js +102 -105
  508. package/shared/diagram/aiFacts.js.map +1 -0
  509. package/shared/diagram/aiMermaid.d.ts +5 -0
  510. package/shared/diagram/aiMermaid.js +50 -46
  511. package/shared/diagram/aiMermaid.js.map +1 -0
  512. package/shared/diagram/atlas.d.ts +16 -0
  513. package/shared/diagram/atlas.js +51 -60
  514. package/shared/diagram/atlas.js.map +1 -0
  515. package/shared/diagram/mermaid.d.ts +43 -0
  516. package/shared/diagram/mermaid.js +348 -370
  517. package/shared/diagram/mermaid.js.map +1 -0
  518. package/shared/review/contracts.d.ts +95 -0
  519. package/shared/review/contracts.js +2 -0
  520. package/shared/review/contracts.js.map +1 -0
  521. package/shared/review/review.d.ts +10 -0
  522. package/shared/review/review.js +184 -0
  523. package/shared/review/review.js.map +1 -0
  524. package/shared/search/query.d.ts +32 -0
  525. package/shared/search/query.js +395 -388
  526. package/shared/search/query.js.map +1 -0
package/cli/wizard.js CHANGED
@@ -9,199 +9,196 @@
9
9
  // config the server would refuse. `applyFlags` is the non-interactive twin of
10
10
  // the same fold. All three are pure: the tests drive them directly, and the
11
11
  // readline renderer in `prompt.js` is a thin shell over them.
12
-
13
12
  import os from 'node:os';
14
-
15
13
  import { DEFAULT_SETTINGS, generateAccessKey, isLoopbackHost, normalizeSettings } from '../server/config.js';
16
-
17
14
  // Provider presets for the AI account step. `none` is the honest default: the
18
15
  // app works fully offline, and the browser can still hold its own key.
19
16
  export const PROVIDER_PRESETS = {
20
- none: { label: 'Skip — set it later (the app works offline)', baseUrl: '' },
21
- 'openai-compatible': { label: 'OpenAI or any compatible endpoint', baseUrl: 'https://api.openai.com/v1' },
22
- ollama: { label: 'Ollama (local models)', baseUrl: 'http://localhost:11434/v1' },
23
- openrouter: { label: 'OpenRouter', baseUrl: 'https://openrouter.ai/api/v1' },
24
- custom: { label: 'Custom base URL', baseUrl: '' },
17
+ none: { label: 'Skip — set it later (the app works offline)', baseUrl: '' },
18
+ 'openai-compatible': { label: 'OpenAI or any compatible endpoint', baseUrl: 'https://api.openai.com/v1' },
19
+ ollama: { label: 'Ollama (local models)', baseUrl: 'http://localhost:11434/v1' },
20
+ openrouter: { label: 'OpenRouter', baseUrl: 'https://openrouter.ai/api/v1' },
21
+ custom: { label: 'Custom base URL', baseUrl: '' },
25
22
  };
26
-
27
23
  export const TUNNEL_CHOICES = [
28
- { value: 'none', label: 'No tunnel', hint: 'reach the server directly' },
29
- { value: 'cloudflare', label: 'Cloudflare quick tunnel', hint: 'cloudflared — a public https://*.trycloudflare.com name' },
30
- { value: 'tailscale', label: 'Tailscale serve', hint: 'your devices only, https://machine.tailnet.ts.net' },
31
- { value: 'both', label: 'Both', hint: 'public via Cloudflare, private via tailnet' },
24
+ { value: 'none', label: 'No tunnel', hint: 'reach the server directly' },
25
+ { value: 'cloudflare', label: 'Cloudflare quick tunnel', hint: 'cloudflared — a public https://*.trycloudflare.com name' },
26
+ { value: 'tailscale', label: 'Tailscale serve', hint: 'your devices only, https://machine.tailnet.ts.net' },
27
+ { value: 'both', label: 'Both', hint: 'public via Cloudflare, private via tailnet' },
32
28
  ];
33
-
34
29
  export function validPort(value) {
35
- const n = Number(String(value).trim());
36
- if (!Number.isInteger(n) || n < 1 || n > 65535) return 'A whole number from 1 to 65535.';
37
- return null;
30
+ const n = Number(String(value).trim());
31
+ if (!Number.isInteger(n) || n < 1 || n > 65535)
32
+ return 'A whole number from 1 to 65535.';
33
+ return null;
38
34
  }
39
-
40
35
  export function validDomain(value) {
41
- const domain = String(value || '').trim();
42
- if (!domain) return null; // optional in some flows; required ones check separately
43
- if (domain.length > 253 || /[\s/@\\]/.test(domain) || domain.startsWith('.') || !domain.includes('.')) {
44
- return 'A hostname such as map.example.com.';
45
- }
46
- return null;
36
+ const domain = String(value || '').trim();
37
+ if (!domain)
38
+ return null; // optional in some flows; required ones check separately
39
+ if (domain.length > 253 || /[\s/@\\]/.test(domain) || domain.startsWith('.') || !domain.includes('.')) {
40
+ return 'A hostname such as map.example.com.';
41
+ }
42
+ return null;
47
43
  }
48
-
49
44
  export function validEmail(value) {
50
- const email = String(value || '').trim();
51
- if (!email) return null; // optional
52
- return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email) ? null : 'That does not look like an email address.';
45
+ const email = String(value || '').trim();
46
+ if (!email)
47
+ return null; // optional
48
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email) ? null : 'That does not look like an email address.';
53
49
  }
54
-
55
50
  function providerOf(account) {
56
- if (!account?.baseUrl) return 'none';
57
- for (const [id, preset] of Object.entries(PROVIDER_PRESETS)) {
58
- if (id !== 'none' && id !== 'custom' && preset.baseUrl === account.baseUrl) return id;
59
- }
60
- return 'custom';
51
+ if (!account?.baseUrl)
52
+ return 'none';
53
+ for (const [id, preset] of Object.entries(PROVIDER_PRESETS)) {
54
+ if (id !== 'none' && id !== 'custom' && preset.baseUrl === account.baseUrl)
55
+ return id;
56
+ }
57
+ return 'custom';
61
58
  }
62
-
63
59
  function tunnelChoiceOf(tunnel) {
64
- if (tunnel?.cloudflare && tunnel?.tailscale) return 'both';
65
- if (tunnel?.cloudflare) return 'cloudflare';
66
- if (tunnel?.tailscale) return 'tailscale';
67
- return 'none';
60
+ if (tunnel?.cloudflare && tunnel?.tailscale)
61
+ return 'both';
62
+ if (tunnel?.cloudflare)
63
+ return 'cloudflare';
64
+ if (tunnel?.tailscale)
65
+ return 'tailscale';
66
+ return 'none';
68
67
  }
69
-
70
68
  // The ordered question list. Every step's `when` reads the answers collected
71
69
  // so far, which is what makes the wizard a tree rather than a script: answer
72
70
  // "local" and the whole network/security branch never appears.
73
71
  export function buildSteps(current = DEFAULT_SETTINGS) {
74
- const account = current.account || DEFAULT_SETTINGS.account;
75
- return [
76
- {
77
- id: 'name', section: 'Profile', type: 'text',
78
- question: 'Your name',
79
- hint: 'shown in the settings drawer; never leaves this machine',
80
- default: account.name || safeUsername(),
81
- },
82
- {
83
- id: 'email', section: 'Profile', type: 'text',
84
- question: 'Your email (optional)',
85
- hint: 'for your own reference only',
86
- default: account.email || '',
87
- validate: validEmail,
88
- },
89
- {
90
- id: 'mode', section: 'Server', type: 'choice',
91
- question: 'How will you run Onboarder?',
92
- choices: [
93
- { value: 'local', label: 'Local — localhost only', hint: 'private by construction; nothing on the network can reach it' },
94
- { value: 'self-hosted', label: 'Self-hosted — domain, LAN, or tunnel', hint: 'reach it from other devices; every API call needs an access key' },
95
- ],
96
- default: current.mode,
97
- },
98
- {
99
- id: 'host', section: 'Server', type: 'choice',
100
- question: 'What should the server bind to?',
101
- choices: [
102
- { value: '127.0.0.1', label: 'Loopback only — behind Cloudflare or Tailscale', hint: 'safest remote layout; the tunnel/proxy connects to 127.0.0.1' },
103
- { value: '0.0.0.0', label: 'Every interface — direct public/LAN access', hint: 'accessible by server IP; recommended for a cloud VPS' },
104
- ],
105
- default: (answers) => {
106
- const currentHost = current.host;
107
- if (answers.host) return answers.host;
108
- if (current.mode === 'self-hosted' && ['127.0.0.1', 'localhost', '::1', '[::1]'].includes(currentHost)) return currentHost;
109
- return '0.0.0.0';
110
- },
111
- when: (a) => a.mode === 'self-hosted',
112
- },
113
- {
114
- id: 'port', section: 'Server', type: 'text',
115
- question: 'Port',
116
- default: String(current.port),
117
- validate: validPort,
118
- },
119
- {
120
- id: 'domain', section: 'Server', type: 'text',
121
- question: 'Domain (optional for direct IP or a tunnel)',
122
- hint: 'e.g. map.example.com — point an A/AAAA record to this VPS to enable trusted HTTPS',
123
- default: current.domain || '',
124
- validate: validDomain,
125
- when: (a) => a.mode === 'self-hosted',
126
- },
127
- {
128
- id: 'https', section: 'HTTPS', type: 'confirm',
129
- question: 'Set up automatic HTTPS with Caddy?',
130
- hint: 'Caddy obtains and renews the certificate, proxies 80/443, and sends traffic to this app',
131
- default: Boolean(current.domain && current.https),
132
- when: (a) => a.mode === 'self-hosted' && Boolean(a.domain),
133
- },
134
- {
135
- id: 'keyChoice', section: 'Security', type: 'choice',
136
- question: 'Access key — the one credential remote devices must hold',
137
- choices: [
138
- { value: 'generate', label: 'Generate a strong key (recommended)', hint: 'shown once at the end, stored in the config file' },
139
- ...(current.accessKey ? [{ value: 'keep', label: `Keep the existing key (${current.accessKey.slice(0, 6)}…)`, hint: '' }] : []),
140
- { value: 'enter', label: 'Enter my own', hint: '' },
141
- ],
142
- default: current.accessKey ? 'keep' : 'generate',
143
- when: (a) => a.mode === 'self-hosted',
144
- },
145
- {
146
- id: 'keyValue', section: 'Security', type: 'text',
147
- question: 'Your access key',
148
- hint: 'at least 16 characters; anyone holding it can drive the API',
149
- validate: (v) => (String(v || '').trim().length >= 16 ? null : 'At least 16 characters.'),
150
- when: (a) => a.mode === 'self-hosted' && a.keyChoice === 'enter',
151
- },
152
- {
153
- id: 'provider', section: 'AI provider (optional)', type: 'choice',
154
- question: 'Default AI provider for explain/chat features',
155
- choices: Object.entries(PROVIDER_PRESETS).map(([value, p]) => ({ value, label: p.label, hint: p.baseUrl })),
156
- default: providerOf(account),
157
- },
158
- {
159
- id: 'baseUrl', section: 'AI provider (optional)', type: 'text',
160
- question: 'Base URL',
161
- default: (a) => PROVIDER_PRESETS[a.provider]?.baseUrl || account.baseUrl || '',
162
- validate: (v) => (v && !/^https?:\/\//.test(v) ? 'An http(s) URL, e.g. https://api.openai.com/v1.' : null),
163
- when: (a) => a.provider && a.provider !== 'none',
164
- },
165
- {
166
- id: 'model', section: 'AI provider (optional)', type: 'text',
167
- question: 'Model (optional)',
168
- hint: 'e.g. gpt-4o-mini, llama3.1',
169
- default: account.model || '',
170
- when: (a) => a.provider && a.provider !== 'none',
171
- },
172
- {
173
- id: 'tunnelChoice', section: 'Remote access', type: 'choice',
174
- question: 'Expose it through a tunnel?',
175
- hint: 'the wizard prints the exact command afterwards; missing CLIs get an install hint',
176
- choices: TUNNEL_CHOICES,
177
- default: tunnelChoiceOf(current.tunnel),
178
- when: (a) => a.mode === 'self-hosted',
179
- },
180
- {
181
- id: 'autoOpen', section: 'Finish', type: 'confirm',
182
- question: 'Open the app in a browser when the server starts?',
183
- default: current.autoOpen !== false,
184
- },
185
- ];
72
+ const account = current.account || DEFAULT_SETTINGS.account;
73
+ return [
74
+ {
75
+ id: 'name', section: 'Profile', type: 'text',
76
+ question: 'Your name',
77
+ hint: 'shown in the settings drawer; never leaves this machine',
78
+ default: account.name || safeUsername(),
79
+ },
80
+ {
81
+ id: 'email', section: 'Profile', type: 'text',
82
+ question: 'Your email (optional)',
83
+ hint: 'for your own reference only',
84
+ default: account.email || '',
85
+ validate: validEmail,
86
+ },
87
+ {
88
+ id: 'mode', section: 'Server', type: 'choice',
89
+ question: 'How will you run Onboarder?',
90
+ choices: [
91
+ { value: 'local', label: 'Local — localhost only', hint: 'private by construction; nothing on the network can reach it' },
92
+ { value: 'self-hosted', label: 'Self-hosted — domain, LAN, or tunnel', hint: 'reach it from other devices; every API call needs an access key' },
93
+ ],
94
+ default: current.mode,
95
+ },
96
+ {
97
+ id: 'host', section: 'Server', type: 'choice',
98
+ question: 'What should the server bind to?',
99
+ choices: [
100
+ { value: '127.0.0.1', label: 'Loopback only — behind Cloudflare or Tailscale', hint: 'safest remote layout; the tunnel/proxy connects to 127.0.0.1' },
101
+ { value: '0.0.0.0', label: 'Every interface — direct public/LAN access', hint: 'accessible by server IP; recommended for a cloud VPS' },
102
+ ],
103
+ default: (answers) => {
104
+ const currentHost = current.host;
105
+ if (answers.host)
106
+ return answers.host;
107
+ if (current.mode === 'self-hosted' && ['127.0.0.1', 'localhost', '::1', '[::1]'].includes(currentHost))
108
+ return currentHost;
109
+ return '0.0.0.0';
110
+ },
111
+ when: (a) => a.mode === 'self-hosted',
112
+ },
113
+ {
114
+ id: 'port', section: 'Server', type: 'text',
115
+ question: 'Port',
116
+ default: String(current.port),
117
+ validate: validPort,
118
+ },
119
+ {
120
+ id: 'domain', section: 'Server', type: 'text',
121
+ question: 'Domain (optional for direct IP or a tunnel)',
122
+ hint: 'e.g. map.example.com — point an A/AAAA record to this VPS to enable trusted HTTPS',
123
+ default: current.domain || '',
124
+ validate: validDomain,
125
+ when: (a) => a.mode === 'self-hosted',
126
+ },
127
+ {
128
+ id: 'https', section: 'HTTPS', type: 'confirm',
129
+ question: 'Set up automatic HTTPS with Caddy?',
130
+ hint: 'Caddy obtains and renews the certificate, proxies 80/443, and sends traffic to this app',
131
+ default: Boolean(current.domain && current.https),
132
+ when: (a) => a.mode === 'self-hosted' && Boolean(a.domain),
133
+ },
134
+ {
135
+ id: 'keyChoice', section: 'Security', type: 'choice',
136
+ question: 'Access key — the one credential remote devices must hold',
137
+ choices: [
138
+ { value: 'generate', label: 'Generate a strong key (recommended)', hint: 'shown once at the end, stored in the config file' },
139
+ ...(current.accessKey ? [{ value: 'keep', label: `Keep the existing key (${current.accessKey.slice(0, 6)}…)`, hint: '' }] : []),
140
+ { value: 'enter', label: 'Enter my own', hint: '' },
141
+ ],
142
+ default: current.accessKey ? 'keep' : 'generate',
143
+ when: (a) => a.mode === 'self-hosted',
144
+ },
145
+ {
146
+ id: 'keyValue', section: 'Security', type: 'text',
147
+ question: 'Your access key',
148
+ hint: 'at least 16 characters; anyone holding it can drive the API',
149
+ validate: (v) => (String(v || '').trim().length >= 16 ? null : 'At least 16 characters.'),
150
+ when: (a) => a.mode === 'self-hosted' && a.keyChoice === 'enter',
151
+ },
152
+ {
153
+ id: 'provider', section: 'AI provider (optional)', type: 'choice',
154
+ question: 'Default AI provider for explain/chat features',
155
+ choices: Object.entries(PROVIDER_PRESETS).map(([value, p]) => ({ value, label: p.label, hint: p.baseUrl })),
156
+ default: providerOf(account),
157
+ },
158
+ {
159
+ id: 'baseUrl', section: 'AI provider (optional)', type: 'text',
160
+ question: 'Base URL',
161
+ default: (a) => PROVIDER_PRESETS[a.provider]?.baseUrl || account.baseUrl || '',
162
+ validate: (v) => (v && !/^https?:\/\//.test(v) ? 'An http(s) URL, e.g. https://api.openai.com/v1.' : null),
163
+ when: (a) => a.provider && a.provider !== 'none',
164
+ },
165
+ {
166
+ id: 'model', section: 'AI provider (optional)', type: 'text',
167
+ question: 'Model (optional)',
168
+ hint: 'e.g. gpt-4o-mini, llama3.1',
169
+ default: account.model || '',
170
+ when: (a) => a.provider && a.provider !== 'none',
171
+ },
172
+ {
173
+ id: 'tunnelChoice', section: 'Remote access', type: 'choice',
174
+ question: 'Expose it through a tunnel?',
175
+ hint: 'the wizard prints the exact command afterwards; missing CLIs get an install hint',
176
+ choices: TUNNEL_CHOICES,
177
+ default: tunnelChoiceOf(current.tunnel),
178
+ when: (a) => a.mode === 'self-hosted',
179
+ },
180
+ {
181
+ id: 'autoOpen', section: 'Finish', type: 'confirm',
182
+ question: 'Open the app in a browser when the server starts?',
183
+ default: current.autoOpen !== false,
184
+ },
185
+ ];
186
186
  }
187
-
188
-
189
187
  function safeUsername() {
190
- try {
191
- return os.userInfo().username || '';
192
- } catch {
193
- return '';
194
- }
188
+ try {
189
+ return os.userInfo().username || '';
190
+ }
191
+ catch {
192
+ return '';
193
+ }
195
194
  }
196
-
197
195
  // Steps for one run, given what is already answered: flags pre-answer questions
198
196
  // (a flagged question is never asked), and `when` prunes dead branches. The
199
197
  // answers object grows as the run proceeds, so a later step's `when` sees both
200
198
  // flag answers and typed answers through the same lens.
201
199
  export function pendingSteps(steps, answers = {}) {
202
- return steps.filter((s) => !(s.id in answers) && (!s.when || s.when(answers)));
200
+ return steps.filter((s) => !(s.id in answers) && (!s.when || s.when(answers)));
203
201
  }
204
-
205
202
  // Steps the flags did not answer, in order — and nothing more. Unlike
206
203
  // `pendingSteps` this never looks at `when`: conditions read answers that
207
204
  // only exist mid-run ("ask about the bind once mode is self-hosted"), so
@@ -209,147 +206,170 @@ export function pendingSteps(steps, answers = {}) {
209
206
  // would reopen. The renderer (`prompt.js#runSteps`) evaluates `when` live,
210
207
  // one question at a time, which is the only moment it can be answered truly.
211
208
  export function unansweredSteps(steps, answers = {}) {
212
- return steps.filter((s) => !(s.id in answers));
209
+ return steps.filter((s) => !(s.id in answers));
213
210
  }
214
-
215
211
  // Defaults may depend on earlier answers (`default` as a function).
216
212
  export function defaultOf(step, answers) {
217
- return typeof step.default === 'function' ? step.default(answers) : step.default;
213
+ return typeof step.default === 'function' ? step.default(answers) : step.default;
218
214
  }
219
-
220
215
  // Answers → settings. The key rule: this builds a plain object and hands it to
221
216
  // normalizeSettings, so an impossible combination (local mode on 0.0.0.0, a
222
217
  // LAN bind with no domain) fails with the schema's own sentence here, in the
223
218
  // API, and in `config set` — one law, three courts.
224
219
  export function answersToSettings(current, answers) {
225
- const selfHosted = answers.mode === 'self-hosted';
226
- const provider = answers.provider || 'none';
227
- const account = {
228
- name: answers.name ?? current.account?.name ?? '',
229
- email: answers.email ?? current.account?.email ?? '',
230
- provider: provider === 'none' ? 'openai-compatible' : provider,
231
- baseUrl: provider === 'none' ? '' : String(answers.baseUrl ?? '').trim().replace(/\/+$/, ''),
232
- model: provider === 'none' ? '' : String(answers.model ?? '').trim(),
233
- };
234
- let accessKey = current.accessKey || '';
235
- if (selfHosted) {
236
- if (answers.keyChoice === 'generate' || (!answers.keyChoice && !accessKey)) accessKey = generateAccessKey();
237
- else if (answers.keyChoice === 'enter') accessKey = String(answers.keyValue || '').trim();
238
- }
239
- const choice = answers.tunnelChoice || tunnelChoiceOf(current.tunnel);
240
- const tunnel = selfHosted
241
- ? { cloudflare: choice === 'cloudflare' || choice === 'both', tailscale: choice === 'tailscale' || choice === 'both' }
242
- : { ...(current.tunnel || DEFAULT_SETTINGS.tunnel) };
243
- return normalizeSettings({
244
- version: current.version,
245
- mode: selfHosted ? 'self-hosted' : 'local',
246
- host: selfHosted ? (answers.host || '0.0.0.0') : '127.0.0.1',
247
- port: Number(answers.port ?? current.port ?? DEFAULT_SETTINGS.port),
248
- domain: selfHosted ? String(answers.domain ?? current.domain ?? '').trim().toLowerCase() : '',
249
- https: selfHosted && Boolean(answers.domain) && Boolean(answers.https),
250
- accessKey,
251
- autoOpen: answers.autoOpen ?? current.autoOpen ?? false,
252
- account,
253
- tunnel,
254
- });
220
+ const selfHosted = answers.mode === 'self-hosted';
221
+ const provider = answers.provider || 'none';
222
+ const account = {
223
+ name: answers.name ?? current.account?.name ?? '',
224
+ email: answers.email ?? current.account?.email ?? '',
225
+ provider: provider === 'none' ? 'openai-compatible' : provider,
226
+ baseUrl: provider === 'none' ? '' : String(answers.baseUrl ?? '').trim().replace(/\/+$/, ''),
227
+ model: provider === 'none' ? '' : String(answers.model ?? '').trim(),
228
+ };
229
+ let accessKey = current.accessKey || '';
230
+ if (selfHosted) {
231
+ if (answers.keyChoice === 'generate' || (!answers.keyChoice && !accessKey))
232
+ accessKey = generateAccessKey();
233
+ else if (answers.keyChoice === 'enter')
234
+ accessKey = String(answers.keyValue || '').trim();
235
+ }
236
+ const choice = answers.tunnelChoice || tunnelChoiceOf(current.tunnel);
237
+ const tunnel = selfHosted
238
+ ? { cloudflare: choice === 'cloudflare' || choice === 'both', tailscale: choice === 'tailscale' || choice === 'both' }
239
+ : { ...(current.tunnel || DEFAULT_SETTINGS.tunnel) };
240
+ return normalizeSettings({
241
+ version: current.version,
242
+ mode: selfHosted ? 'self-hosted' : 'local',
243
+ host: selfHosted ? (answers.host || '0.0.0.0') : '127.0.0.1',
244
+ port: Number(answers.port ?? current.port ?? DEFAULT_SETTINGS.port),
245
+ domain: selfHosted ? String(answers.domain ?? current.domain ?? '').trim().toLowerCase() : '',
246
+ https: selfHosted && Boolean(answers.domain) && Boolean(answers.https),
247
+ accessKey,
248
+ autoOpen: answers.autoOpen ?? current.autoOpen ?? false,
249
+ account,
250
+ tunnel,
251
+ });
255
252
  }
256
-
257
-
258
253
  // The non-interactive twin: --flags become the same patch the wizard would
259
254
  // have collected. Anything unflagged falls back to the current settings, and
260
255
  // the whole result goes through the same normalizeSettings validation, so
261
256
  // `onboarder setup --non-interactive --mode self-hosted --port 8080` can never
262
257
  // produce a config the interactive wizard would refuse.
263
258
  export function applyFlags(current, flags = {}) {
264
- const patch = {};
265
- if (flags.mode !== undefined) {
266
- if (!['local', 'self-hosted'].includes(flags.mode)) throw new Error('--mode must be "local" or "self-hosted".');
267
- patch.mode = flags.mode;
268
- }
269
- const mode = patch.mode || current.mode;
270
- if (flags.host !== undefined) patch.host = flags.host;
271
- if (flags.port !== undefined) {
272
- const err = validPort(flags.port);
273
- if (err) throw new Error('--port: ' + err);
274
- patch.port = Number(flags.port);
275
- }
276
- if (flags.domain !== undefined) {
277
- const err = validDomain(flags.domain);
278
- if (err) throw new Error('--domain: ' + err);
279
- patch.domain = String(flags.domain).trim().toLowerCase();
280
- }
281
- if (flags.https !== undefined) patch.https = Boolean(flags.https);
282
- if (flags.accessKey === 'generate') patch.accessKey = generateAccessKey();
283
- else if (flags.accessKey !== undefined) {
284
- if (String(flags.accessKey).trim().length < 16) throw new Error('--access-key must be at least 16 characters, or "generate".');
285
- patch.accessKey = String(flags.accessKey).trim();
286
- } else if (mode === 'self-hosted' && !current.accessKey) {
287
- // Self-hosted without a key is a locked door with no handle — generate one
288
- // rather than write a config that refuses every call.
289
- patch.accessKey = generateAccessKey();
290
- }
291
- if (flags.autoOpen !== undefined) patch.autoOpen = Boolean(flags.autoOpen);
292
- const account = {};
293
- if (flags.name !== undefined) account.name = String(flags.name);
294
- if (flags.email !== undefined) {
295
- const err = validEmail(flags.email);
296
- if (err) throw new Error('--email: ' + err);
297
- account.email = String(flags.email);
298
- }
299
- if (flags.provider !== undefined) {
300
- if (!(flags.provider in PROVIDER_PRESETS)) throw new Error('--provider must be one of: ' + Object.keys(PROVIDER_PRESETS).join(', '));
301
- account.provider = flags.provider === 'none' ? 'openai-compatible' : flags.provider;
302
- account.baseUrl = PROVIDER_PRESETS[flags.provider]?.baseUrl || '';
303
- if (flags.provider === 'none') account.model = '';
304
- }
305
- if (flags.baseUrl !== undefined) account.baseUrl = String(flags.baseUrl).trim().replace(/\/+$/, '');
306
- if (flags.model !== undefined) account.model = String(flags.model).trim();
307
- if (Object.keys(account).length) patch.account = account;
308
- const tunnel = {};
309
- if (flags.cloudflare !== undefined) tunnel.cloudflare = Boolean(flags.cloudflare);
310
- if (flags.tailscale !== undefined) tunnel.tailscale = Boolean(flags.tailscale);
311
- if (Object.keys(tunnel).length) patch.tunnel = tunnel;
312
- const merged = {
313
- ...current, ...patch,
314
- account: { ...(current.account || DEFAULT_SETTINGS.account), ...account },
315
- tunnel: { ...(current.tunnel || DEFAULT_SETTINGS.tunnel), ...tunnel },
316
- };
317
- // A fresh self-hosted setup is direct-first for cloud/VPS use. Re-running setup
318
- // preserves an existing deliberate loopback choice for tunnels and Caddy.
319
- if (flags.mode === 'self-hosted' && flags.host === undefined && current.mode !== 'self-hosted') {
320
- merged.host = '0.0.0.0';
321
- }
322
- if (merged.mode === 'local') {
323
- if (!['127.0.0.1', 'localhost', '::1', '[::1]'].includes(merged.host)) merged.host = '127.0.0.1';
324
- if (flags.domain === undefined) merged.domain = '';
325
- if (flags.https === undefined) merged.https = false;
326
- }
327
- return { patch, settings: normalizeSettings(merged) };
259
+ const patch = {};
260
+ if (flags.mode !== undefined) {
261
+ if (!['local', 'self-hosted'].includes(flags.mode))
262
+ throw new Error('--mode must be "local" or "self-hosted".');
263
+ patch.mode = flags.mode;
264
+ }
265
+ const mode = patch.mode || current.mode;
266
+ if (flags.host !== undefined)
267
+ patch.host = flags.host;
268
+ if (flags.port !== undefined) {
269
+ const err = validPort(flags.port);
270
+ if (err)
271
+ throw new Error('--port: ' + err);
272
+ patch.port = Number(flags.port);
273
+ }
274
+ if (flags.domain !== undefined) {
275
+ const err = validDomain(flags.domain);
276
+ if (err)
277
+ throw new Error('--domain: ' + err);
278
+ patch.domain = String(flags.domain).trim().toLowerCase();
279
+ }
280
+ if (flags.https !== undefined)
281
+ patch.https = Boolean(flags.https);
282
+ if (flags.accessKey === 'generate')
283
+ patch.accessKey = generateAccessKey();
284
+ else if (flags.accessKey !== undefined) {
285
+ if (String(flags.accessKey).trim().length < 16)
286
+ throw new Error('--access-key must be at least 16 characters, or "generate".');
287
+ patch.accessKey = String(flags.accessKey).trim();
288
+ }
289
+ else if (mode === 'self-hosted' && !current.accessKey) {
290
+ // Self-hosted without a key is a locked door with no handle — generate one
291
+ // rather than write a config that refuses every call.
292
+ patch.accessKey = generateAccessKey();
293
+ }
294
+ if (flags.autoOpen !== undefined)
295
+ patch.autoOpen = Boolean(flags.autoOpen);
296
+ const account = {};
297
+ if (flags.name !== undefined)
298
+ account.name = String(flags.name);
299
+ if (flags.email !== undefined) {
300
+ const err = validEmail(flags.email);
301
+ if (err)
302
+ throw new Error('--email: ' + err);
303
+ account.email = String(flags.email);
304
+ }
305
+ if (flags.provider !== undefined) {
306
+ if (!(flags.provider in PROVIDER_PRESETS))
307
+ throw new Error('--provider must be one of: ' + Object.keys(PROVIDER_PRESETS).join(', '));
308
+ account.provider = flags.provider === 'none' ? 'openai-compatible' : flags.provider;
309
+ account.baseUrl = PROVIDER_PRESETS[flags.provider]?.baseUrl || '';
310
+ if (flags.provider === 'none')
311
+ account.model = '';
312
+ }
313
+ if (flags.baseUrl !== undefined)
314
+ account.baseUrl = String(flags.baseUrl).trim().replace(/\/+$/, '');
315
+ if (flags.model !== undefined)
316
+ account.model = String(flags.model).trim();
317
+ if (Object.keys(account).length)
318
+ patch.account = account;
319
+ const tunnel = {};
320
+ if (flags.cloudflare !== undefined)
321
+ tunnel.cloudflare = Boolean(flags.cloudflare);
322
+ if (flags.tailscale !== undefined)
323
+ tunnel.tailscale = Boolean(flags.tailscale);
324
+ if (Object.keys(tunnel).length)
325
+ patch.tunnel = tunnel;
326
+ const merged = {
327
+ ...current, ...patch,
328
+ account: { ...(current.account || DEFAULT_SETTINGS.account), ...account },
329
+ tunnel: { ...(current.tunnel || DEFAULT_SETTINGS.tunnel), ...tunnel },
330
+ };
331
+ // A fresh self-hosted setup is direct-first for cloud/VPS use. Re-running setup
332
+ // preserves an existing deliberate loopback choice for tunnels and Caddy.
333
+ if (flags.mode === 'self-hosted' && flags.host === undefined && current.mode !== 'self-hosted') {
334
+ merged.host = '0.0.0.0';
335
+ }
336
+ if (merged.mode === 'local') {
337
+ if (!['127.0.0.1', 'localhost', '::1', '[::1]'].includes(merged.host))
338
+ merged.host = '127.0.0.1';
339
+ if (flags.domain === undefined)
340
+ merged.domain = '';
341
+ if (flags.https === undefined)
342
+ merged.https = false;
343
+ }
344
+ return { patch, settings: normalizeSettings(merged) };
328
345
  }
329
-
330
346
  // What the wizard's last screen shows before writing. `reveal` is the one
331
347
  // moment the key is printed — rotation through the API has the same rule.
332
348
  export function summaryLines(settings, { revealKey = false } = {}) {
333
- const lines = [
334
- ['Mode', settings.mode],
335
- ['Bind', `${settings.host}:${settings.port}`],
336
- ];
337
- if (settings.domain) lines.push(['Domain', (settings.https ? 'https://' : 'http://') + settings.domain + (settings.https ? '' : ':' + settings.port)]);
338
- if (settings.mode === 'self-hosted') {
339
- lines.push(['Access key', revealKey
340
- ? settings.accessKey
341
- : (settings.accessKey ? settings.accessKey.slice(0, 6) + '… (hidden)' : '(none — the API will refuse every call)')]);
342
- if (isLoopbackHost(settings.host)) {
343
- lines.push(['Network', 'loopback only — use a tunnel or bind 0.0.0.0 for direct access']);
349
+ const lines = [
350
+ ['Mode', settings.mode],
351
+ ['Bind', `${settings.host}:${settings.port}`],
352
+ ];
353
+ if (settings.domain)
354
+ lines.push(['Domain', (settings.https ? 'https://' : 'http://') + settings.domain + (settings.https ? '' : ':' + settings.port)]);
355
+ if (settings.mode === 'self-hosted') {
356
+ lines.push(['Access key', revealKey
357
+ ? settings.accessKey
358
+ : (settings.accessKey ? settings.accessKey.slice(0, 6) + '… (hidden)' : '(none — the API will refuse every call)')]);
359
+ if (isLoopbackHost(settings.host)) {
360
+ lines.push(['Network', 'loopback only — use a tunnel or bind 0.0.0.0 for direct access']);
361
+ }
362
+ }
363
+ const who = [settings.account.name, settings.account.email].filter(Boolean).join(' · ');
364
+ if (who)
365
+ lines.push(['Profile', who]);
366
+ if (settings.account.baseUrl) {
367
+ lines.push(['AI', `${settings.account.provider} — ${settings.account.baseUrl}${settings.account.model ? ' — ' + settings.account.model : ''}`]);
344
368
  }
345
- }
346
- const who = [settings.account.name, settings.account.email].filter(Boolean).join(' · ');
347
- if (who) lines.push(['Profile', who]);
348
- if (settings.account.baseUrl) {
349
- lines.push(['AI', `${settings.account.provider} — ${settings.account.baseUrl}${settings.account.model ? ' — ' + settings.account.model : ''}`]);
350
- }
351
- const tunnels = [settings.tunnel.cloudflare && 'cloudflare', settings.tunnel.tailscale && 'tailscale'].filter(Boolean);
352
- if (tunnels.length) lines.push(['Tunnels', tunnels.join(' + ')]);
353
- lines.push(['Auto-open', settings.autoOpen ? 'yes' : 'no']);
354
- return lines;
369
+ const tunnels = [settings.tunnel.cloudflare && 'cloudflare', settings.tunnel.tailscale && 'tailscale'].filter(Boolean);
370
+ if (tunnels.length)
371
+ lines.push(['Tunnels', tunnels.join(' + ')]);
372
+ lines.push(['Auto-open', settings.autoOpen ? 'yes' : 'no']);
373
+ return lines;
355
374
  }
375
+ //# sourceMappingURL=wizard.js.map