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
@@ -0,0 +1,177 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { spawn } from 'node:child_process';
5
+ import { parseArgs } from 'node:util';
6
+ import { AGENT_MODES } from './contracts.js';
7
+ import { agentHome, setupAgent, prepareAgentProfile, runtimePaths, hermesBinary, hermesEnvironment, HERMES_SOURCE, HERMES_REVISION } from './config.js';
8
+ import { runAgent, savedRun } from './runner.js';
9
+ import { runProcess, terminalText, redact } from './process.js';
10
+ import { githubToken } from './github.js';
11
+ export const AGENT_HELP = `
12
+ Onboarder agent — Hermes with repository and GitHub tools
13
+
14
+ onboarder agent setup Create a dedicated Hermes profile
15
+ onboarder chat [folder] Open the conversational harness with / commands
16
+ onboarder agent model Configure its model/provider interactively
17
+ onboarder agent doctor Check runtime and integration compatibility
18
+ onboarder agent source Fetch the researched official Hermes source
19
+ onboarder agent runs List saved runs
20
+ onboarder agent show <run-id> Inspect a saved result and workspace
21
+ onboarder agent <workflow> [folder] --task "..."
22
+
23
+ Workflows: ask, review, triage, implement, pr, github
24
+ --pr <number> Review/inspect a GitHub pull request
25
+ --issue <number> Work from an issue
26
+ --base <branch> PR target (default: origin HEAD, or current branch)
27
+ --allow-checks Allow npm install/test/typecheck/build (repository code)
28
+ --allow-github-writes Allow issue/review/comment updates and draft PR publishing
29
+ --max-turns <1–100> Agent turn limit (default: 24)
30
+ --timeout <seconds> Run limit, 15–3600 (default: 300)
31
+ --model <name> --provider <name> Override the dedicated Hermes model
32
+ --resume <run-id> Continue a session; repeat allowed permission flags
33
+ --dry-run Print the plan without a model call or worktree
34
+ --json One JSON result; progress goes to stderr
35
+
36
+ implement/pr use a new Git worktree at committed HEAD. Uncommitted source
37
+ changes are excluded. Without --allow-github-writes, pr prepares a draft locally.
38
+ GitHub uses the checkout's github.com origin and GITHUB_TOKEN or GH_TOKEN.
39
+ Hermes is an optional separate Python runtime: https://github.com/NousResearch/hermes-agent
40
+ Profile/history: ONBOARDER_AGENT_HOME (default: ~/.config/onboarder/agent).
41
+
42
+ onboarder agent ask . --task "Explain the authentication flow"
43
+ onboarder agent review . --pr 42 --task "Find correctness and security issues"
44
+ onboarder agent triage . --issue 12 --task "Investigate and propose a fix"
45
+ onboarder agent implement . --task "Fix issue 12" --issue 12 --allow-checks
46
+ onboarder agent pr . --task "Fix issue 12 and open a draft PR" --issue 12 --allow-checks --allow-github-writes
47
+ `;
48
+ export const AGENT_OPTIONS = {
49
+ task: { type: 'string' }, pr: { type: 'string' }, issue: { type: 'string' },
50
+ 'max-turns': { type: 'string' }, timeout: { type: 'string' }, resume: { type: 'string' },
51
+ 'allow-checks': { type: 'boolean' }, 'allow-github-writes': { type: 'boolean' }, 'dry-run': { type: 'boolean' },
52
+ model: { type: 'string' }, provider: { type: 'string' }, json: { type: 'boolean' }, help: { type: 'boolean', short: 'h' },
53
+ base: { type: 'string' },
54
+ };
55
+ export async function agentDoctor(home = agentHome(), env = process.env) {
56
+ const paths = runtimePaths(home, env);
57
+ let runtime = false, compatible = false, detail = '';
58
+ try {
59
+ const result = await runProcess(hermesBinary(env), ['chat', '--help'], { env: hermesEnvironment(home, env), timeoutMs: 30_000, maxBytes: 128000 });
60
+ runtime = result.code === 0;
61
+ compatible = runtime && ['--query-file', 'stream-json', '--toolsets', '--run-budget', '--ignore-rules', '--no-restore-cwd'].every(s => result.stdout.includes(s));
62
+ if (!compatible)
63
+ detail = result.code ? result.stderr.slice(-2000) || 'Hermes could not start.' : 'Update Hermes to a runtime supporting structured one-shot chat and MCP selection.';
64
+ }
65
+ catch (e) {
66
+ detail = redact(e instanceof Error ? e.message : String(e), env);
67
+ }
68
+ const server = await fs.access(paths.server).then(() => true).catch(() => false);
69
+ const profile = await fs.access(path.join(paths.profile, 'config.yaml')).then(() => true).catch(() => false);
70
+ return { runtime, compatible, server, profile, githubToken: Boolean(githubToken(env)), home, ready: runtime && compatible && server && profile, detail,
71
+ next: !runtime ? 'Install Hermes from its official repository, then agent setup and agent model.' : !profile ? 'Run onboarder agent setup, then onboarder agent model.' : 'Model credentials are checked by Hermes when a task runs; use agent model to configure them.' };
72
+ }
73
+ export async function fetchHermesSource(home = agentHome(), signal) {
74
+ const target = path.join(home, 'upstream', 'hermes-agent');
75
+ await fs.mkdir(path.dirname(target), { recursive: true, mode: 0o700 });
76
+ const git = async (args) => {
77
+ const output = await runProcess('git', ['-c', 'http.version=HTTP/1.1', ...args], { signal, timeoutMs: 120_000, maxBytes: 2 * 1024 * 1024 });
78
+ if (output.code)
79
+ throw new Error(`Hermes source fetch failed: ${output.stderr.slice(-1500)}`);
80
+ return output.stdout.trim();
81
+ };
82
+ if (!await fs.access(target).then(() => true).catch(() => false)) {
83
+ const staging = target + '-' + randomUUID();
84
+ try {
85
+ await git(['clone', '--depth', '1', '--no-checkout', '--', HERMES_SOURCE, staging]);
86
+ await fs.rename(staging, target);
87
+ }
88
+ finally {
89
+ await fs.rm(staging, { recursive: true, force: true });
90
+ }
91
+ }
92
+ if (await git(['-C', target, 'remote', 'get-url', 'origin']) !== HERMES_SOURCE)
93
+ throw new Error('The source cache origin is not the official Hermes repository.');
94
+ if (await git(['-C', target, 'status', '--porcelain']) && await fs.access(path.join(target, 'LICENSE')).then(() => true).catch(() => false))
95
+ throw new Error('The source cache contains edits. Preserve them before updating it.');
96
+ await git(['-C', target, 'fetch', '--depth', '1', 'origin', HERMES_REVISION]);
97
+ await git(['-C', target, '-c', 'core.hooksPath=' + path.join(home, 'empty-hooks'), 'checkout', '--detach', HERMES_REVISION]);
98
+ return { source: HERMES_SOURCE, revision: HERMES_REVISION, directory: target, license: 'MIT', installed: false };
99
+ }
100
+ export async function agentCommand(sub = 'help', positionals = [], flags = {}, options = {}) {
101
+ const out = options.out || console.log, err = options.err || console.error, home = agentHome();
102
+ const print = (value) => out(typeof value === 'string' ? value : JSON.stringify(value, null, 2));
103
+ if (flags.help || sub === 'help') {
104
+ out(AGENT_HELP);
105
+ return 0;
106
+ }
107
+ if (sub === 'setup') {
108
+ const result = await prepareAgentProfile(home, process.env, options.signal);
109
+ print(flags.json ? result : `Dedicated Hermes profile: ${result.profile}\n${result.created ? 'Created.' : 'Existing model settings preserved.'} Run onboarder agent model to configure its provider.\nRun onboarder agent doctor to check the integration.`);
110
+ return 0;
111
+ }
112
+ if (sub === 'doctor') {
113
+ const report = await agentDoctor(home);
114
+ print(report);
115
+ return report.ready ? 0 : 1;
116
+ }
117
+ if (sub === 'source') {
118
+ print(await fetchHermesSource(home, options.signal));
119
+ return 0;
120
+ }
121
+ if (sub === 'model') {
122
+ if (!process.stdin.isTTY)
123
+ throw new Error('Run onboarder agent model in an interactive terminal.');
124
+ await setupAgent(home);
125
+ return new Promise((resolve, reject) => {
126
+ const child = spawn(hermesBinary(), ['model'], { env: hermesEnvironment(home), stdio: 'inherit', shell: false, signal: options.signal });
127
+ child.on('error', reject);
128
+ child.on('close', code => resolve(code ?? 1));
129
+ });
130
+ }
131
+ if (sub === 'runs') {
132
+ const names = await fs.readdir(runtimePaths(home).runs).catch(e => { if (e.code !== 'ENOENT')
133
+ throw e; return []; });
134
+ const runs = (await Promise.all(names.filter(n => /^[a-f\d-]{36}$/.test(n)).map(async (id) => {
135
+ try {
136
+ const { manifest, result } = await savedRun(id, home);
137
+ return { id, mode: manifest.mode, status: result?.status || 'unfinished', startedAt: manifest.startedAt, workspace: manifest.root, repository: manifest.repository };
138
+ }
139
+ catch {
140
+ return { id, status: 'unreadable' };
141
+ }
142
+ }))).sort((a, b) => (b.startedAt || '').localeCompare(a.startedAt || ''));
143
+ print(runs);
144
+ return 0;
145
+ }
146
+ if (sub === 'show') {
147
+ print(await savedRun(positionals[0] || '', home));
148
+ return 0;
149
+ }
150
+ if (!AGENT_MODES.includes(sub))
151
+ throw new Error('Unknown agent workflow. Run onboarder agent --help.');
152
+ if (positionals.length > 1)
153
+ throw new Error('Use one repository folder and --task "your task".');
154
+ const task = flags.task || (sub === 'review' ? `Review ${flags.pr ? 'pull request ' + flags.pr : 'local changes'} for actionable correctness and security issues.` : sub === 'triage' ? `Investigate ${flags.issue ? 'issue ' + flags.issue : 'open issues'} and propose a prioritized plan.` : '');
155
+ const result = await runAgent({ mode: sub, root: positionals[0] || options.root || '.', task,
156
+ pr: flags.pr === undefined ? undefined : Number(flags.pr), issue: flags.issue === undefined ? undefined : Number(flags.issue),
157
+ maxTurns: flags.maxTurns === undefined ? flags['max-turns'] : flags.maxTurns, timeoutSeconds: flags.timeout,
158
+ allowChecks: flags.allowChecks || flags['allow-checks'], allowGithubWrites: flags.allowGithubWrites || flags['allow-github-writes'], dryRun: flags.dryRun || flags['dry-run'],
159
+ model: flags.model, provider: flags.provider, resume: flags.resume, base: flags.base }, { signal: options.signal,
160
+ onEvent: event => {
161
+ if (event.type === 'tool_use')
162
+ err(` ${terminalText(event.name || 'Tool')}…`);
163
+ if (event.type === 'tool_result' && event.is_error)
164
+ err(` ${terminalText(event.name || 'Tool')} reported an error.`);
165
+ } });
166
+ if ('dryRun' in result || flags.json)
167
+ print(result);
168
+ else
169
+ out(`${terminalText(result.answer)}\n\nRun: ${result.id} (${result.status})\nWorkspace: ${result.workspace}${result.branch ? '\nBranch: ' + result.branch : ''}`);
170
+ return 'dryRun' in result || result.status === 'completed' ? 0 : result.status === 'cancelled' ? 130 : 1;
171
+ }
172
+ export async function explorerAgent(args, root, signal, out, err) {
173
+ const parsed = parseArgs({ args, options: AGENT_OPTIONS, allowPositionals: true });
174
+ await agentCommand(parsed.positionals[0], parsed.positionals.slice(1), parsed.values, { root, signal, out, err });
175
+ return '';
176
+ }
177
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/cli/agent/command.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { spawn } from 'node:child_process';\nimport { parseArgs } from 'node:util';\nimport { AGENT_MODES, type AgentMode } from './contracts.js';\nimport { agentHome, setupAgent, prepareAgentProfile, runtimePaths, hermesBinary, hermesEnvironment, HERMES_SOURCE, HERMES_REVISION } from './config.js';\nimport { runAgent, savedRun } from './runner.js';\nimport { runProcess, terminalText, redact } from './process.js';\nimport { githubToken } from './github.js';\n\nexport const AGENT_HELP = `\n Onboarder agent — Hermes with repository and GitHub tools\n\n onboarder agent setup Create a dedicated Hermes profile\n onboarder chat [folder] Open the conversational harness with / commands\n onboarder agent model Configure its model/provider interactively\n onboarder agent doctor Check runtime and integration compatibility\n onboarder agent source Fetch the researched official Hermes source\n onboarder agent runs List saved runs\n onboarder agent show <run-id> Inspect a saved result and workspace\n onboarder agent <workflow> [folder] --task \"...\"\n\n Workflows: ask, review, triage, implement, pr, github\n --pr <number> Review/inspect a GitHub pull request\n --issue <number> Work from an issue\n --base <branch> PR target (default: origin HEAD, or current branch)\n --allow-checks Allow npm install/test/typecheck/build (repository code)\n --allow-github-writes Allow issue/review/comment updates and draft PR publishing\n --max-turns <1–100> Agent turn limit (default: 24)\n --timeout <seconds> Run limit, 15–3600 (default: 300)\n --model <name> --provider <name> Override the dedicated Hermes model\n --resume <run-id> Continue a session; repeat allowed permission flags\n --dry-run Print the plan without a model call or worktree\n --json One JSON result; progress goes to stderr\n\n implement/pr use a new Git worktree at committed HEAD. Uncommitted source\n changes are excluded. Without --allow-github-writes, pr prepares a draft locally.\n GitHub uses the checkout's github.com origin and GITHUB_TOKEN or GH_TOKEN.\n Hermes is an optional separate Python runtime: https://github.com/NousResearch/hermes-agent\n Profile/history: ONBOARDER_AGENT_HOME (default: ~/.config/onboarder/agent).\n\n onboarder agent ask . --task \"Explain the authentication flow\"\n onboarder agent review . --pr 42 --task \"Find correctness and security issues\"\n onboarder agent triage . --issue 12 --task \"Investigate and propose a fix\"\n onboarder agent implement . --task \"Fix issue 12\" --issue 12 --allow-checks\n onboarder agent pr . --task \"Fix issue 12 and open a draft PR\" --issue 12 --allow-checks --allow-github-writes\n`;\nexport const AGENT_OPTIONS = {\n task: { type: 'string' as const }, pr: { type: 'string' as const }, issue: { type: 'string' as const },\n 'max-turns': { type: 'string' as const }, timeout: { type: 'string' as const }, resume: { type: 'string' as const },\n 'allow-checks': { type: 'boolean' as const }, 'allow-github-writes': { type: 'boolean' as const }, 'dry-run': { type: 'boolean' as const },\n model: { type: 'string' as const }, provider: { type: 'string' as const }, json: { type: 'boolean' as const }, help: { type: 'boolean' as const, short: 'h' },\n base: { type: 'string' as const },\n};\nexport async function agentDoctor(home = agentHome(), env: NodeJS.ProcessEnv = process.env) {\n const paths = runtimePaths(home, env);\n let runtime = false, compatible = false, detail = '';\n try {\n const result = await runProcess(hermesBinary(env), ['chat', '--help'], { env: hermesEnvironment(home, env), timeoutMs: 30_000, maxBytes: 128000 });\n runtime = result.code === 0;\n compatible = runtime && ['--query-file', 'stream-json', '--toolsets', '--run-budget', '--ignore-rules', '--no-restore-cwd'].every(s => result.stdout.includes(s));\n if (!compatible) detail = result.code ? result.stderr.slice(-2000) || 'Hermes could not start.' : 'Update Hermes to a runtime supporting structured one-shot chat and MCP selection.';\n } catch (e) { detail = redact(e instanceof Error ? e.message : String(e), env); }\n const server = await fs.access(paths.server).then(() => true).catch(() => false);\n const profile = await fs.access(path.join(paths.profile, 'config.yaml')).then(() => true).catch(() => false);\n return { runtime, compatible, server, profile, githubToken: Boolean(githubToken(env)), home, ready: runtime && compatible && server && profile, detail,\n next: !runtime ? 'Install Hermes from its official repository, then agent setup and agent model.' : !profile ? 'Run onboarder agent setup, then onboarder agent model.' : 'Model credentials are checked by Hermes when a task runs; use agent model to configure them.' };\n}\nexport async function fetchHermesSource(home = agentHome(), signal?: AbortSignal) {\n const target = path.join(home, 'upstream', 'hermes-agent');\n await fs.mkdir(path.dirname(target), { recursive: true, mode: 0o700 });\n const git = async (args: string[]) => {\n const output = await runProcess('git', ['-c', 'http.version=HTTP/1.1', ...args], { signal, timeoutMs: 120_000, maxBytes: 2 * 1024 * 1024 });\n if (output.code) throw new Error(`Hermes source fetch failed: ${output.stderr.slice(-1500)}`);\n return output.stdout.trim();\n };\n if (!await fs.access(target).then(() => true).catch(() => false)) {\n const staging = target + '-' + randomUUID();\n try { await git(['clone', '--depth', '1', '--no-checkout', '--', HERMES_SOURCE, staging]); await fs.rename(staging, target); }\n finally { await fs.rm(staging, { recursive: true, force: true }); }\n }\n if (await git(['-C', target, 'remote', 'get-url', 'origin']) !== HERMES_SOURCE) throw new Error('The source cache origin is not the official Hermes repository.');\n if (await git(['-C', target, 'status', '--porcelain']) && await fs.access(path.join(target, 'LICENSE')).then(() => true).catch(() => false)) throw new Error('The source cache contains edits. Preserve them before updating it.');\n await git(['-C', target, 'fetch', '--depth', '1', 'origin', HERMES_REVISION]);\n await git(['-C', target, '-c', 'core.hooksPath=' + path.join(home, 'empty-hooks'), 'checkout', '--detach', HERMES_REVISION]);\n return { source: HERMES_SOURCE, revision: HERMES_REVISION, directory: target, license: 'MIT', installed: false };\n}\n\nexport async function agentCommand(sub = 'help', positionals: string[] = [], flags: Record<string, any> = {}, options: { root?: string; signal?: AbortSignal; out?: (text: string) => void; err?: (text: string) => void } = {}) {\n const out = options.out || console.log, err = options.err || console.error, home = agentHome();\n const print = (value: unknown) => out(typeof value === 'string' ? value : JSON.stringify(value, null, 2));\n if (flags.help || sub === 'help') { out(AGENT_HELP); return 0; }\n if (sub === 'setup') {\n const result = await prepareAgentProfile(home, process.env, options.signal);\n print(flags.json ? result : `Dedicated Hermes profile: ${result.profile}\\n${result.created ? 'Created.' : 'Existing model settings preserved.'} Run onboarder agent model to configure its provider.\\nRun onboarder agent doctor to check the integration.`); return 0;\n }\n if (sub === 'doctor') { const report = await agentDoctor(home); print(report); return report.ready ? 0 : 1; }\n if (sub === 'source') { print(await fetchHermesSource(home, options.signal)); return 0; }\n if (sub === 'model') {\n if (!process.stdin.isTTY) throw new Error('Run onboarder agent model in an interactive terminal.');\n await setupAgent(home);\n return new Promise<number>((resolve, reject) => {\n const child = spawn(hermesBinary(), ['model'], { env: hermesEnvironment(home), stdio: 'inherit', shell: false, signal: options.signal });\n child.on('error', reject); child.on('close', code => resolve(code ?? 1));\n });\n }\n if (sub === 'runs') {\n const names = await fs.readdir(runtimePaths(home).runs).catch(e => { if (e.code !== 'ENOENT') throw e; return []; });\n const runs = (await Promise.all(names.filter(n => /^[a-f\\d-]{36}$/.test(n)).map(async id => {\n try { const { manifest, result } = await savedRun(id, home); return { id, mode: manifest.mode, status: result?.status || 'unfinished', startedAt: manifest.startedAt, workspace: manifest.root, repository: manifest.repository }; }\n catch { return { id, status: 'unreadable' }; }\n }))).sort((a, b) => (b.startedAt || '').localeCompare(a.startedAt || ''));\n print(runs); return 0;\n }\n if (sub === 'show') { print(await savedRun(positionals[0] || '', home)); return 0; }\n if (!AGENT_MODES.includes(sub as AgentMode)) throw new Error('Unknown agent workflow. Run onboarder agent --help.');\n if (positionals.length > 1) throw new Error('Use one repository folder and --task \"your task\".');\n const task = flags.task || (sub === 'review' ? `Review ${flags.pr ? 'pull request ' + flags.pr : 'local changes'} for actionable correctness and security issues.` : sub === 'triage' ? `Investigate ${flags.issue ? 'issue ' + flags.issue : 'open issues'} and propose a prioritized plan.` : '');\n const result = await runAgent({ mode: sub as AgentMode, root: positionals[0] || options.root || '.', task,\n pr: flags.pr === undefined ? undefined : Number(flags.pr), issue: flags.issue === undefined ? undefined : Number(flags.issue),\n maxTurns: flags.maxTurns === undefined ? flags['max-turns'] : flags.maxTurns, timeoutSeconds: flags.timeout,\n allowChecks: flags.allowChecks || flags['allow-checks'], allowGithubWrites: flags.allowGithubWrites || flags['allow-github-writes'], dryRun: flags.dryRun || flags['dry-run'],\n model: flags.model, provider: flags.provider, resume: flags.resume, base: flags.base }, { signal: options.signal,\n onEvent: event => {\n if (event.type === 'tool_use') err(` ${terminalText(event.name || 'Tool')}…`);\n if (event.type === 'tool_result' && event.is_error) err(` ${terminalText(event.name || 'Tool')} reported an error.`);\n } });\n if ('dryRun' in result || flags.json) print(result);\n else out(`${terminalText(result.answer)}\\n\\nRun: ${result.id} (${result.status})\\nWorkspace: ${result.workspace}${result.branch ? '\\nBranch: ' + result.branch : ''}`);\n return 'dryRun' in result || result.status === 'completed' ? 0 : result.status === 'cancelled' ? 130 : 1;\n}\n\nexport async function explorerAgent(args: string[], root: string, signal: AbortSignal, out: (text: string) => void, err: (text: string) => void) {\n const parsed = parseArgs({ args, options: AGENT_OPTIONS, allowPositionals: true });\n await agentCommand(parsed.positionals[0], parsed.positionals.slice(1), parsed.values, { root, signal, out, err });\n return '';\n}\n"]}
@@ -0,0 +1,31 @@
1
+ export declare const HERMES_SOURCE = "https://github.com/NousResearch/hermes-agent.git";
2
+ export declare const HERMES_REVISION = "eb7e8620324b32424c06218f6a28094df2e921f8";
3
+ export declare function agentHome(env?: NodeJS.ProcessEnv): string;
4
+ export declare function hermesBinary(env?: NodeJS.ProcessEnv): string;
5
+ export declare function runtimePaths(home?: string, env?: NodeJS.ProcessEnv): {
6
+ home: string;
7
+ profile: string;
8
+ runs: string;
9
+ workspaces: string;
10
+ server: string;
11
+ };
12
+ export declare function hermesEnvironment(home?: string, env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
13
+ export declare function setupAgent(home?: string, env?: NodeJS.ProcessEnv): Promise<{
14
+ home: string;
15
+ profile: string;
16
+ runs: string;
17
+ workspaces: string;
18
+ server: string;
19
+ configFile: string;
20
+ created: boolean;
21
+ }>;
22
+ /** Refresh only harness-owned settings; retain the model wizard's provider/auth choices. */
23
+ export declare function prepareAgentProfile(home?: string, env?: NodeJS.ProcessEnv, signal?: AbortSignal): Promise<{
24
+ home: string;
25
+ profile: string;
26
+ runs: string;
27
+ workspaces: string;
28
+ server: string;
29
+ configFile: string;
30
+ created: boolean;
31
+ }>;
@@ -0,0 +1,98 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import { createHash } from 'node:crypto';
3
+ import path from 'node:path';
4
+ import os from 'node:os';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { randomUUID } from 'node:crypto';
7
+ import { runProcess } from './process.js';
8
+ export const HERMES_SOURCE = 'https://github.com/NousResearch/hermes-agent.git';
9
+ export const HERMES_REVISION = 'eb7e8620324b32424c06218f6a28094df2e921f8';
10
+ export function agentHome(env = process.env) {
11
+ return path.resolve(env.ONBOARDER_AGENT_HOME || path.join(env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config'), 'onboarder', 'agent'));
12
+ }
13
+ export function hermesBinary(env = process.env) {
14
+ return env.ONBOARDER_HERMES_BIN || 'hermes';
15
+ }
16
+ export function runtimePaths(home = agentHome(), env = process.env) {
17
+ const native = process.platform === 'win32' ? path.join(env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'), 'hermes') : path.join(os.homedir(), '.hermes');
18
+ const configured = env.HERMES_HOME ? (path.basename(path.dirname(env.HERMES_HOME)) === 'profiles' ? path.dirname(path.dirname(env.HERMES_HOME)) : env.HERMES_HOME) : native;
19
+ // Named profiles share the installation's Python store, but not its config,
20
+ // credentials, sessions, memory, or MCP server selection.
21
+ const name = 'onboarder-' + createHash('sha256').update(path.resolve(home)).digest('hex').slice(0, 12);
22
+ return { home, profile: path.join(configured, 'profiles', name), runs: path.join(home, 'runs'), workspaces: path.join(home, 'workspaces'), server: fileURLToPath(new URL('./stdio.js', import.meta.url)) };
23
+ }
24
+ export function hermesEnvironment(home = agentHome(), env = process.env) {
25
+ return { ...env, HERMES_HOME: runtimePaths(home, env).profile, OPENAI_API_KEY: env.ONBOARDER_AI_API_KEY || env.OPENAI_API_KEY,
26
+ PATH: [path.join(os.homedir(), '.local', 'bin'), env.PATH || ''].join(path.delimiter) };
27
+ }
28
+ export async function setupAgent(home = agentHome(), env = process.env) {
29
+ const paths = runtimePaths(home, env);
30
+ for (const dir of [paths.profile, paths.runs, paths.workspaces])
31
+ await fs.mkdir(dir, { recursive: true, mode: 0o700 });
32
+ const file = path.join(paths.profile, 'config.yaml');
33
+ const base = env.ONBOARDER_AI_BASE_URL || env.OPENAI_BASE_URL;
34
+ const model = env.ONBOARDER_AI_MODEL || env.OPENAI_MODEL;
35
+ // JSON is a YAML subset. Hermes can subsequently maintain this file with its own model wizard.
36
+ const config = {
37
+ ...(base && model ? { model: { provider: 'custom', base_url: base, default: model } } : {}),
38
+ agent: { max_turns: 24 }, memory: { memory_enabled: false, user_profile_enabled: false },
39
+ tools: { tool_search: { enabled: 'off' } },
40
+ mcp_servers: { onboarder: { command: process.execPath, args: [paths.server],
41
+ env: { ONBOARDER_AGENT_RUN: '${ONBOARDER_AGENT_RUN}', GITHUB_TOKEN: '${GITHUB_TOKEN}', GH_TOKEN: '${GH_TOKEN}' },
42
+ tools: { prompts: false, resources: false }, connect_timeout: 30, timeout: 150 } },
43
+ };
44
+ let created = false;
45
+ try {
46
+ await fs.writeFile(file, JSON.stringify(config, null, 2) + '\n', { mode: 0o600, flag: 'wx' });
47
+ created = true;
48
+ }
49
+ catch (error) {
50
+ if (error.code !== 'EEXIST')
51
+ throw error;
52
+ }
53
+ return { ...paths, configFile: file, created };
54
+ }
55
+ /** Refresh only harness-owned settings; retain the model wizard's provider/auth choices. */
56
+ export async function prepareAgentProfile(home = agentHome(), env = process.env, signal) {
57
+ const setup = await setupAgent(home, env);
58
+ if (setup.created)
59
+ return setup;
60
+ const server = { command: process.execPath, args: [setup.server],
61
+ env: { ONBOARDER_AGENT_RUN: '${ONBOARDER_AGENT_RUN}', GITHUB_TOKEN: '${GITHUB_TOKEN}', GH_TOKEN: '${GH_TOKEN}' },
62
+ tools: { prompts: false, resources: false }, connect_timeout: 30, timeout: 150 };
63
+ const source = await fs.readFile(setup.configFile, 'utf8');
64
+ let config = null;
65
+ try {
66
+ const value = JSON.parse(source);
67
+ if (value && typeof value === 'object' && !Array.isArray(value))
68
+ config = value;
69
+ }
70
+ catch { /* Hermes' model wizard writes native YAML. */ }
71
+ if (config) {
72
+ config.mcp_servers = { ...(config.mcp_servers || {}), onboarder: server };
73
+ config.tools = { ...(config.tools || {}), tool_search: { ...(config.tools?.tool_search || {}), enabled: 'off' } };
74
+ config.memory = { ...(config.memory || {}), memory_enabled: false, user_profile_enabled: false };
75
+ const next = JSON.stringify(config, null, 2) + '\n';
76
+ if (source !== next) {
77
+ const temporary = setup.configFile + '-' + randomUUID();
78
+ try {
79
+ await fs.writeFile(temporary, next, { flag: 'wx', mode: 0o600 });
80
+ await fs.rename(temporary, setup.configFile);
81
+ }
82
+ finally {
83
+ await fs.rm(temporary, { force: true });
84
+ }
85
+ }
86
+ }
87
+ else {
88
+ // Let Hermes parse/preserve its own YAML rather than adding a Node dependency
89
+ // or hand-editing the model wizard's configuration.
90
+ for (const [key, value] of [['mcp_servers.onboarder', JSON.stringify(server)], ['tools.tool_search.enabled', 'off'], ['memory.memory_enabled', 'false'], ['memory.user_profile_enabled', 'false']]) {
91
+ const result = await runProcess(hermesBinary(env), ['config', 'set', key, value], { env: hermesEnvironment(home, env), signal, timeoutMs: 30_000, maxBytes: 128000 });
92
+ if (result.code)
93
+ throw new Error(`Could not refresh the dedicated Hermes profile: ${result.stderr.slice(-1500) || result.stdout.slice(-1500)}`);
94
+ }
95
+ }
96
+ return setup;
97
+ }
98
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/cli/agent/config.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport { createHash } from 'node:crypto';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { fileURLToPath } from 'node:url';\nimport { randomUUID } from 'node:crypto';\nimport { runProcess } from './process.js';\n\nexport const HERMES_SOURCE = 'https://github.com/NousResearch/hermes-agent.git';\nexport const HERMES_REVISION = 'eb7e8620324b32424c06218f6a28094df2e921f8';\nexport function agentHome(env: NodeJS.ProcessEnv = process.env): string {\n return path.resolve(env.ONBOARDER_AGENT_HOME || path.join(env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config'), 'onboarder', 'agent'));\n}\nexport function hermesBinary(env: NodeJS.ProcessEnv = process.env): string {\n return env.ONBOARDER_HERMES_BIN || 'hermes';\n}\nexport function runtimePaths(home = agentHome(), env: NodeJS.ProcessEnv = process.env) {\n const native = process.platform === 'win32' ? path.join(env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'), 'hermes') : path.join(os.homedir(), '.hermes');\n const configured = env.HERMES_HOME ? (path.basename(path.dirname(env.HERMES_HOME)) === 'profiles' ? path.dirname(path.dirname(env.HERMES_HOME)) : env.HERMES_HOME) : native;\n // Named profiles share the installation's Python store, but not its config,\n // credentials, sessions, memory, or MCP server selection.\n const name = 'onboarder-' + createHash('sha256').update(path.resolve(home)).digest('hex').slice(0, 12);\n return { home, profile: path.join(configured, 'profiles', name), runs: path.join(home, 'runs'), workspaces: path.join(home, 'workspaces'), server: fileURLToPath(new URL('./stdio.js', import.meta.url)) };\n}\nexport function hermesEnvironment(home = agentHome(), env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {\n return { ...env, HERMES_HOME: runtimePaths(home, env).profile, OPENAI_API_KEY: env.ONBOARDER_AI_API_KEY || env.OPENAI_API_KEY,\n PATH: [path.join(os.homedir(), '.local', 'bin'), env.PATH || ''].join(path.delimiter) };\n}\nexport async function setupAgent(home = agentHome(), env: NodeJS.ProcessEnv = process.env) {\n const paths = runtimePaths(home, env);\n for (const dir of [paths.profile, paths.runs, paths.workspaces]) await fs.mkdir(dir, { recursive: true, mode: 0o700 });\n const file = path.join(paths.profile, 'config.yaml');\n const base = env.ONBOARDER_AI_BASE_URL || env.OPENAI_BASE_URL;\n const model = env.ONBOARDER_AI_MODEL || env.OPENAI_MODEL;\n // JSON is a YAML subset. Hermes can subsequently maintain this file with its own model wizard.\n const config = {\n ...(base && model ? { model: { provider: 'custom', base_url: base, default: model } } : {}),\n agent: { max_turns: 24 }, memory: { memory_enabled: false, user_profile_enabled: false },\n tools: { tool_search: { enabled: 'off' } },\n mcp_servers: { onboarder: { command: process.execPath, args: [paths.server],\n env: { ONBOARDER_AGENT_RUN: '${ONBOARDER_AGENT_RUN}', GITHUB_TOKEN: '${GITHUB_TOKEN}', GH_TOKEN: '${GH_TOKEN}' },\n tools: { prompts: false, resources: false }, connect_timeout: 30, timeout: 150 } },\n };\n let created = false;\n try { await fs.writeFile(file, JSON.stringify(config, null, 2) + '\\n', { mode: 0o600, flag: 'wx' }); created = true; }\n catch (error) { if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error; }\n return { ...paths, configFile: file, created };\n}\n\n/** Refresh only harness-owned settings; retain the model wizard's provider/auth choices. */\nexport async function prepareAgentProfile(home = agentHome(), env: NodeJS.ProcessEnv = process.env, signal?: AbortSignal) {\n const setup = await setupAgent(home, env);\n if (setup.created) return setup;\n const server = { command: process.execPath, args: [setup.server],\n env: { ONBOARDER_AGENT_RUN: '${ONBOARDER_AGENT_RUN}', GITHUB_TOKEN: '${GITHUB_TOKEN}', GH_TOKEN: '${GH_TOKEN}' },\n tools: { prompts: false, resources: false }, connect_timeout: 30, timeout: 150 };\n const source = await fs.readFile(setup.configFile, 'utf8');\n let config: Record<string, any> | null = null;\n try { const value = JSON.parse(source); if (value && typeof value === 'object' && !Array.isArray(value)) config = value; } catch { /* Hermes' model wizard writes native YAML. */ }\n if (config) {\n config.mcp_servers = { ...(config.mcp_servers || {}), onboarder: server };\n config.tools = { ...(config.tools || {}), tool_search: { ...(config.tools?.tool_search || {}), enabled: 'off' } };\n config.memory = { ...(config.memory || {}), memory_enabled: false, user_profile_enabled: false };\n const next = JSON.stringify(config, null, 2) + '\\n';\n if (source !== next) {\n const temporary = setup.configFile + '-' + randomUUID();\n try { await fs.writeFile(temporary, next, { flag: 'wx', mode: 0o600 }); await fs.rename(temporary, setup.configFile); }\n finally { await fs.rm(temporary, { force: true }); }\n }\n } else {\n // Let Hermes parse/preserve its own YAML rather than adding a Node dependency\n // or hand-editing the model wizard's configuration.\n for (const [key, value] of [['mcp_servers.onboarder', JSON.stringify(server)], ['tools.tool_search.enabled', 'off'], ['memory.memory_enabled', 'false'], ['memory.user_profile_enabled', 'false']]) {\n const result = await runProcess(hermesBinary(env), ['config', 'set', key, value], { env: hermesEnvironment(home, env), signal, timeoutMs: 30_000, maxBytes: 128000 });\n if (result.code) throw new Error(`Could not refresh the dedicated Hermes profile: ${result.stderr.slice(-1500) || result.stdout.slice(-1500)}`);\n }\n }\n return setup;\n}\n"]}
@@ -0,0 +1,77 @@
1
+ export declare const AGENT_MODES: readonly ['ask', 'review', 'triage', 'implement', 'pr', 'github'];
2
+ export type AgentMode = typeof AGENT_MODES[number];
3
+ export interface AgentRequest {
4
+ mode: AgentMode;
5
+ root: string;
6
+ task: string;
7
+ pr?: number;
8
+ issue?: number;
9
+ maxTurns?: number;
10
+ timeoutSeconds?: number;
11
+ allowChecks?: boolean;
12
+ allowGithubWrites?: boolean;
13
+ dryRun?: boolean;
14
+ model?: string;
15
+ provider?: string;
16
+ resume?: string;
17
+ base?: string;
18
+ }
19
+ export interface RunManifest {
20
+ schemaVersion: 1;
21
+ id: string;
22
+ mode: AgentMode;
23
+ sourceRoot: string;
24
+ root: string;
25
+ repository: string | null;
26
+ remote: string | null;
27
+ branch: string | null;
28
+ baseBranch: string | null;
29
+ task: string;
30
+ pr?: number;
31
+ issue?: number;
32
+ permissions: {
33
+ files: boolean;
34
+ checks: boolean;
35
+ github: boolean;
36
+ };
37
+ startedAt: string;
38
+ timeoutSeconds: number;
39
+ maxTurns: number;
40
+ auditFile: string;
41
+ }
42
+ export interface AgentEvent {
43
+ type: 'system' | 'text' | 'tool_use' | 'tool_result' | 'result';
44
+ subtype?: string;
45
+ name?: string;
46
+ text?: string;
47
+ session_id?: string;
48
+ exit_code?: number;
49
+ error?: string;
50
+ is_error?: boolean;
51
+ tokens?: Record<string, number>;
52
+ duration_ms?: number;
53
+ }
54
+ export interface AgentResult {
55
+ id: string;
56
+ status: 'completed' | 'failed' | 'cancelled';
57
+ mode: AgentMode;
58
+ answer: string;
59
+ sessionId: string | null;
60
+ workspace: string;
61
+ branch: string | null;
62
+ repository: string | null;
63
+ auditFile: string;
64
+ completedAt: string;
65
+ tokens?: Record<string, number>;
66
+ }
67
+ export interface AgentTool {
68
+ name: string;
69
+ description: string;
70
+ inputSchema: {
71
+ type: 'object';
72
+ properties: Record<string, unknown>;
73
+ required?: string[];
74
+ additionalProperties?: boolean;
75
+ };
76
+ run: (args: Record<string, unknown>) => Promise<unknown>;
77
+ }
@@ -0,0 +1,2 @@
1
+ export const AGENT_MODES = ['ask', 'review', 'triage', 'implement', 'pr', 'github'];
2
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/cli/agent/contracts.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,CAAU,CAAC","sourcesContent":["export const AGENT_MODES = ['ask', 'review', 'triage', 'implement', 'pr', 'github'] as const;\nexport type AgentMode = typeof AGENT_MODES[number];\nexport interface AgentRequest {\n mode: AgentMode;\n root: string;\n task: string;\n pr?: number;\n issue?: number;\n maxTurns?: number;\n timeoutSeconds?: number;\n allowChecks?: boolean;\n allowGithubWrites?: boolean;\n dryRun?: boolean;\n model?: string;\n provider?: string;\n resume?: string;\n base?: string;\n}\nexport interface RunManifest {\n schemaVersion: 1;\n id: string;\n mode: AgentMode;\n sourceRoot: string;\n root: string;\n repository: string | null;\n remote: string | null;\n branch: string | null;\n baseBranch: string | null;\n task: string;\n pr?: number;\n issue?: number;\n permissions: { files: boolean; checks: boolean; github: boolean };\n startedAt: string;\n timeoutSeconds: number;\n maxTurns: number;\n auditFile: string;\n}\nexport interface AgentEvent {\n type: 'system' | 'text' | 'tool_use' | 'tool_result' | 'result';\n subtype?: string;\n name?: string;\n text?: string;\n session_id?: string;\n exit_code?: number;\n error?: string;\n is_error?: boolean;\n tokens?: Record<string, number>;\n duration_ms?: number;\n}\nexport interface AgentResult {\n id: string;\n status: 'completed' | 'failed' | 'cancelled';\n mode: AgentMode;\n answer: string;\n sessionId: string | null;\n workspace: string;\n branch: string | null;\n repository: string | null;\n auditFile: string;\n completedAt: string;\n tokens?: Record<string, number>;\n}\nexport interface AgentTool {\n name: string;\n description: string;\n inputSchema: { type: 'object'; properties: Record<string, unknown>; required?: string[]; additionalProperties?: boolean };\n run: (args: Record<string, unknown>) => Promise<unknown>;\n}\n"]}
@@ -0,0 +1,19 @@
1
+ export declare const FILE_LIMIT: number;
2
+ export declare const hashText: (text: string) => string;
3
+ export declare function safeRelative(file: string): string;
4
+ export declare function scopedFile(root: string, file: string, createParents?: boolean): Promise<string>;
5
+ export declare function readAgentFile(root: string, file: string): Promise<{
6
+ file: string;
7
+ content: string;
8
+ sha256: string;
9
+ lines: number;
10
+ }>;
11
+ export declare function writeAgentFile(root: string, file: string, content: string, expected: string): Promise<{
12
+ file: string;
13
+ sha256: string;
14
+ bytes: number;
15
+ }>;
16
+ export declare function deleteAgentFile(root: string, file: string, expected: string): Promise<{
17
+ file: string;
18
+ deleted: boolean;
19
+ }>;
@@ -0,0 +1,109 @@
1
+ import { promises as fs, constants } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createHash, randomUUID } from 'node:crypto';
4
+ export const FILE_LIMIT = 128 * 1024;
5
+ export const hashText = (text) => createHash('sha256').update(text).digest('hex');
6
+ export function safeRelative(file) {
7
+ if (!file || file.length > 500 || path.isAbsolute(file) || file.includes('\\') || /[\x00-\x1f]/.test(file))
8
+ throw new Error('Use a relative repository file path.');
9
+ const parts = file.split('/');
10
+ if (parts.some(p => !p || p === '..' || p === '.' || ['.git', 'node_modules', '.ssh', '.aws', '.npmrc', '.pypirc', '.netrc', '.git-credentials'].includes(p) || /^\.env(?:\.|$)/.test(p) || /^(?:id_rsa|id_ed25519)$|\.(?:pem|key)$/i.test(p)))
11
+ throw new Error('This path is outside the agent source-file scope.');
12
+ return file;
13
+ }
14
+ export async function scopedFile(root, file, createParents = false) {
15
+ safeRelative(file);
16
+ const canonical = await fs.realpath(root);
17
+ const parts = file.split('/');
18
+ let current = canonical;
19
+ for (let i = 0; i < parts.length; i++) {
20
+ current = path.join(current, parts[i]);
21
+ let stat;
22
+ try {
23
+ stat = await fs.lstat(current);
24
+ }
25
+ catch (e) {
26
+ if (e.code !== 'ENOENT')
27
+ throw e;
28
+ if (createParents && i < parts.length - 1)
29
+ await fs.mkdir(current);
30
+ else if (i < parts.length - 1)
31
+ throw new Error('The parent directory does not exist.');
32
+ continue;
33
+ }
34
+ if (stat.isSymbolicLink())
35
+ throw new Error('Agent file tools do not follow symbolic links.');
36
+ if (i < parts.length - 1 && !stat.isDirectory())
37
+ throw new Error('The parent path is not a directory.');
38
+ if (i === parts.length - 1 && !stat.isFile())
39
+ throw new Error('The path is not a regular file.');
40
+ }
41
+ return current;
42
+ }
43
+ async function readBounded(file) {
44
+ const handle = await fs.open(file, constants.O_RDONLY | (constants.O_NOFOLLOW || 0));
45
+ try {
46
+ const stat = await handle.stat();
47
+ if (!stat.isFile() || stat.size > FILE_LIMIT)
48
+ throw new Error(`File must be text and at most ${FILE_LIMIT} bytes.`);
49
+ const buffer = Buffer.alloc(FILE_LIMIT + 1);
50
+ let bytesRead = 0;
51
+ while (bytesRead < buffer.length) {
52
+ const read = await handle.read(buffer, bytesRead, buffer.length - bytesRead, bytesRead);
53
+ if (!read.bytesRead)
54
+ break;
55
+ bytesRead += read.bytesRead;
56
+ }
57
+ if (bytesRead > FILE_LIMIT || buffer.subarray(0, bytesRead).includes(0))
58
+ throw new Error('File exceeds the text-file limit or contains binary data.');
59
+ return buffer.subarray(0, bytesRead).toString('utf8');
60
+ }
61
+ finally {
62
+ await handle.close();
63
+ }
64
+ }
65
+ export async function readAgentFile(root, file) {
66
+ const content = await readBounded(await scopedFile(root, file));
67
+ return { file, content, sha256: hashText(content), lines: content.split('\n').length };
68
+ }
69
+ export async function writeAgentFile(root, file, content, expected) {
70
+ if (Buffer.byteLength(content) > FILE_LIMIT || content.includes('\0'))
71
+ throw new Error('New content exceeds the text-file limit.');
72
+ const target = await scopedFile(root, file, true);
73
+ const check = async () => {
74
+ try {
75
+ const current = await readBounded(target);
76
+ if (expected === 'new' || hashText(current) !== expected)
77
+ throw new Error('The file changed. Read it again before writing.');
78
+ }
79
+ catch (e) {
80
+ if (e.code === 'ENOENT' && expected === 'new')
81
+ return;
82
+ throw e;
83
+ }
84
+ };
85
+ await check();
86
+ const mode = await fs.stat(target).then(s => s.mode & 0o777).catch(() => 0o644);
87
+ const temporary = path.join(path.dirname(target), `.onboarder-${randomUUID()}.tmp`);
88
+ try {
89
+ await fs.writeFile(temporary, content, { mode, flag: 'wx' });
90
+ await check();
91
+ if (expected === 'new')
92
+ await fs.link(temporary, target);
93
+ else
94
+ await fs.rename(temporary, target);
95
+ }
96
+ finally {
97
+ await fs.unlink(temporary).catch(() => { });
98
+ }
99
+ return { file, sha256: hashText(content), bytes: Buffer.byteLength(content) };
100
+ }
101
+ export async function deleteAgentFile(root, file, expected) {
102
+ const target = await scopedFile(root, file);
103
+ const current = await readBounded(target);
104
+ if (hashText(current) !== expected)
105
+ throw new Error('The file changed. Read it again before deleting.');
106
+ await fs.unlink(target);
107
+ return { file, deleted: true };
108
+ }
109
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/cli/agent/files.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs, constants } from 'node:fs';\nimport path from 'node:path';\nimport { createHash, randomUUID } from 'node:crypto';\n\nexport const FILE_LIMIT = 128 * 1024;\nexport const hashText = (text: string) => createHash('sha256').update(text).digest('hex');\nexport function safeRelative(file: string): string {\n if (!file || file.length > 500 || path.isAbsolute(file) || file.includes('\\\\') || /[\\x00-\\x1f]/.test(file)) throw new Error('Use a relative repository file path.');\n const parts = file.split('/');\n if (parts.some(p => !p || p === '..' || p === '.' || ['.git', 'node_modules', '.ssh', '.aws', '.npmrc', '.pypirc', '.netrc', '.git-credentials'].includes(p) || /^\\.env(?:\\.|$)/.test(p) || /^(?:id_rsa|id_ed25519)$|\\.(?:pem|key)$/i.test(p))) throw new Error('This path is outside the agent source-file scope.');\n return file;\n}\nexport async function scopedFile(root: string, file: string, createParents = false): Promise<string> {\n safeRelative(file);\n const canonical = await fs.realpath(root);\n const parts = file.split('/');\n let current = canonical;\n for (let i = 0; i < parts.length; i++) {\n current = path.join(current, parts[i]);\n let stat;\n try { stat = await fs.lstat(current); }\n catch (e) {\n if ((e as NodeJS.ErrnoException).code !== 'ENOENT') throw e;\n if (createParents && i < parts.length - 1) await fs.mkdir(current);\n else if (i < parts.length - 1) throw new Error('The parent directory does not exist.');\n continue;\n }\n if (stat.isSymbolicLink()) throw new Error('Agent file tools do not follow symbolic links.');\n if (i < parts.length - 1 && !stat.isDirectory()) throw new Error('The parent path is not a directory.');\n if (i === parts.length - 1 && !stat.isFile()) throw new Error('The path is not a regular file.');\n }\n return current;\n}\nasync function readBounded(file: string): Promise<string> {\n const handle = await fs.open(file, constants.O_RDONLY | (constants.O_NOFOLLOW || 0));\n try {\n const stat = await handle.stat();\n if (!stat.isFile() || stat.size > FILE_LIMIT) throw new Error(`File must be text and at most ${FILE_LIMIT} bytes.`);\n const buffer = Buffer.alloc(FILE_LIMIT + 1);\n let bytesRead = 0;\n while (bytesRead < buffer.length) {\n const read = await handle.read(buffer, bytesRead, buffer.length - bytesRead, bytesRead);\n if (!read.bytesRead) break;\n bytesRead += read.bytesRead;\n }\n if (bytesRead > FILE_LIMIT || buffer.subarray(0, bytesRead).includes(0)) throw new Error('File exceeds the text-file limit or contains binary data.');\n return buffer.subarray(0, bytesRead).toString('utf8');\n } finally { await handle.close(); }\n}\nexport async function readAgentFile(root: string, file: string) {\n const content = await readBounded(await scopedFile(root, file));\n return { file, content, sha256: hashText(content), lines: content.split('\\n').length };\n}\nexport async function writeAgentFile(root: string, file: string, content: string, expected: string) {\n if (Buffer.byteLength(content) > FILE_LIMIT || content.includes('\\0')) throw new Error('New content exceeds the text-file limit.');\n const target = await scopedFile(root, file, true);\n const check = async () => {\n try {\n const current = await readBounded(target);\n if (expected === 'new' || hashText(current) !== expected) throw new Error('The file changed. Read it again before writing.');\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === 'ENOENT' && expected === 'new') return;\n throw e;\n }\n };\n await check();\n const mode = await fs.stat(target).then(s => s.mode & 0o777).catch(() => 0o644);\n const temporary = path.join(path.dirname(target), `.onboarder-${randomUUID()}.tmp`);\n try {\n await fs.writeFile(temporary, content, { mode, flag: 'wx' });\n await check();\n if (expected === 'new') await fs.link(temporary, target);\n else await fs.rename(temporary, target);\n } finally { await fs.unlink(temporary).catch(() => {}); }\n return { file, sha256: hashText(content), bytes: Buffer.byteLength(content) };\n}\nexport async function deleteAgentFile(root: string, file: string, expected: string) {\n const target = await scopedFile(root, file);\n const current = await readBounded(target);\n if (hashText(current) !== expected) throw new Error('The file changed. Read it again before deleting.');\n await fs.unlink(target);\n return { file, deleted: true };\n}\n"]}