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,116 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ import { createHash, randomUUID } from 'node:crypto';
5
+ import { agentHome } from '../agent/config.js';
6
+ import { repositoryFromRemote } from '../agent/github.js';
7
+ import { runProcess } from '../agent/process.js';
8
+ export function isRemoteSource(value) { return /^(?:https?:\/\/|ssh:\/\/|git@)/i.test(value); }
9
+ export function githubSource(value) {
10
+ const raw = value.trim(), repository = repositoryFromRemote(raw);
11
+ if (!repository)
12
+ throw new Error('Enter a GitHub repository URL: https://github.com/owner/repo or git@github.com:owner/repo.git.');
13
+ const url = `https://github.com/${repository}`;
14
+ const gitUrl = /^https:/i.test(raw) ? url + '.git' : `git@github.com:${repository}.git`;
15
+ return { repository, url, gitUrl };
16
+ }
17
+ /** Persistent checkouts keep conversations and agent worktrees usable after exit. */
18
+ export class ChatSources {
19
+ home;
20
+ options;
21
+ constructor(home = agentHome(), options = {}) {
22
+ this.home = home;
23
+ this.options = options;
24
+ }
25
+ get directory() { return path.join(this.home, 'repositories'); }
26
+ target(repository) {
27
+ const key = repository.toLowerCase();
28
+ return path.join(this.directory, key.split('/')[1].slice(0, 40) + '-' + createHash('sha256').update(key).digest('hex').slice(0, 16));
29
+ }
30
+ async git(args, signal, hooks) {
31
+ const env = this.options.env || process.env;
32
+ const result = await (this.options.execute || runProcess)('git', [
33
+ ...(hooks ? ['-c', `core.hooksPath=${hooks}`] : []), '-c', 'submodule.recurse=false', ...args,
34
+ ], { env: { ...env, GIT_TERMINAL_PROMPT: '0', GIT_SSH_COMMAND: env.GIT_SSH_COMMAND || 'ssh -oBatchMode=yes' }, signal, timeoutMs: 180000, maxBytes: 1024 * 1024 });
35
+ if (result.code !== 0)
36
+ throw new Error(`Could not open/update the repository. ${result.stderr.trim().slice(-1200) || 'Git exited with ' + result.code}. Private repositories require your existing Git credentials.`);
37
+ return result.stdout.trim();
38
+ }
39
+ async verify(target, repository, signal) {
40
+ const stat = await fs.lstat(target);
41
+ if (!stat.isDirectory() || stat.isSymbolicLink())
42
+ throw new Error('The saved repository path is not a regular directory.');
43
+ const root = await fs.realpath(target);
44
+ if (await fs.realpath(await this.git(['-C', root, 'rev-parse', '--show-toplevel'], signal)) !== root)
45
+ throw new Error('The saved checkout does not belong to this repository.');
46
+ const origin = await this.git(['-C', root, 'remote', 'get-url', 'origin'], signal);
47
+ if (repositoryFromRemote(origin)?.toLowerCase() !== repository.toLowerCase())
48
+ throw new Error('The saved checkout origin changed. Its files were preserved.');
49
+ return root;
50
+ }
51
+ async open(target, from = process.cwd(), signal, progress = () => { }) {
52
+ signal?.throwIfAborted();
53
+ if (!isRemoteSource(target)) {
54
+ const folder = target.replace(/^~(?=\/|$)/, os.homedir());
55
+ const root = await fs.realpath(path.resolve(from, folder));
56
+ if (!(await fs.stat(root)).isDirectory())
57
+ throw new Error('Choose a repository folder or GitHub URL.');
58
+ signal?.throwIfAborted();
59
+ return { root, reused: false };
60
+ }
61
+ const source = githubSource(target), destination = this.target(source.repository);
62
+ const existing = await fs.lstat(destination).then(() => true).catch(e => { if (e.code !== 'ENOENT')
63
+ throw e; return false; });
64
+ if (existing) {
65
+ const root = await this.verify(destination, source.repository, signal);
66
+ progress(`Using saved checkout of ${source.repository}. Use /pull to fetch the latest changes.`);
67
+ return { root, sourceUrl: source.url, reused: true };
68
+ }
69
+ await fs.mkdir(this.directory, { recursive: true, mode: 0o700 });
70
+ const staging = await fs.mkdtemp(path.join(this.directory, '.clone-'));
71
+ const hooks = path.join(staging, 'empty-hooks'), checkout = path.join(staging, 'checkout');
72
+ await fs.mkdir(hooks, { mode: 0o700 });
73
+ try {
74
+ progress(`Cloning ${source.repository}… Ctrl-C to stop.`);
75
+ await this.git(['clone', '--filter=blob:none', '--single-branch', '--', source.gitUrl, checkout], signal, hooks);
76
+ signal?.throwIfAborted();
77
+ await this.verify(checkout, source.repository, signal);
78
+ await fs.chmod(checkout, 0o700);
79
+ try {
80
+ await fs.rename(checkout, destination);
81
+ }
82
+ catch (e) {
83
+ // Two chats may clone the same URL concurrently. Reuse the complete
84
+ // winner, preserving it rather than replacing its existing contents.
85
+ if (!['EEXIST', 'ENOTEMPTY'].includes(e.code || ''))
86
+ throw e;
87
+ }
88
+ const root = await this.verify(destination, source.repository, signal);
89
+ progress(`Ready: ${source.repository}\nSaved checkout: ${root}\nAsk a question, or use /map to explore.`);
90
+ return { root, sourceUrl: source.url, reused: false };
91
+ }
92
+ finally {
93
+ await fs.rm(staging, { recursive: true, force: true });
94
+ }
95
+ }
96
+ async pull(root, signal, progress = () => { }) {
97
+ const origin = await this.git(['-C', root, 'remote', 'get-url', 'origin'], signal);
98
+ const repository = repositoryFromRemote(origin);
99
+ if (!repository || await fs.realpath(this.target(repository)).catch(() => null) !== root)
100
+ throw new Error('/pull updates a saved GitHub checkout. Open one with /repo <GitHub URL> first.');
101
+ await this.verify(root, repository, signal);
102
+ if (await this.git(['-C', root, 'status', '--porcelain', '--untracked-files=all'], signal))
103
+ throw new Error('The checkout has local changes. Preserve or commit them before /pull.');
104
+ const hooks = path.join(this.directory, '.pull-hooks-' + randomUUID());
105
+ await fs.mkdir(hooks, { mode: 0o700 });
106
+ try {
107
+ progress(`Pulling latest changes for ${repository}…`);
108
+ const result = await this.git(['-C', root, 'pull', '--ff-only', '--no-rebase'], signal, hooks);
109
+ return result || 'Repository is up to date.';
110
+ }
111
+ finally {
112
+ await fs.rm(hooks, { recursive: true, force: true });
113
+ }
114
+ }
115
+ }
116
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/cli/chat/source.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { createHash, randomUUID } from 'node:crypto';\nimport { agentHome } from '../agent/config.js';\nimport { repositoryFromRemote } from '../agent/github.js';\nimport { runProcess } from '../agent/process.js';\n\nexport interface ChatSource { root: string; sourceUrl?: string; reused: boolean }\ninterface SourceOptions { env?: NodeJS.ProcessEnv; execute?: typeof runProcess }\nexport function isRemoteSource(value: string): boolean { return /^(?:https?:\\/\\/|ssh:\\/\\/|git@)/i.test(value); }\nexport function githubSource(value: string): { repository: string; url: string; gitUrl: string } {\n const raw = value.trim(), repository = repositoryFromRemote(raw);\n if (!repository) throw new Error('Enter a GitHub repository URL: https://github.com/owner/repo or git@github.com:owner/repo.git.');\n const url = `https://github.com/${repository}`;\n const gitUrl = /^https:/i.test(raw) ? url + '.git' : `git@github.com:${repository}.git`;\n return { repository, url, gitUrl };\n}\n\n/** Persistent checkouts keep conversations and agent worktrees usable after exit. */\nexport class ChatSources {\n constructor(readonly home = agentHome(), private options: SourceOptions = {}) {}\n get directory() { return path.join(this.home, 'repositories'); }\n private target(repository: string) {\n const key = repository.toLowerCase();\n return path.join(this.directory, key.split('/')[1]!.slice(0, 40) + '-' + createHash('sha256').update(key).digest('hex').slice(0, 16));\n }\n private async git(args: string[], signal?: AbortSignal, hooks?: string) {\n const env = this.options.env || process.env;\n const result = await (this.options.execute || runProcess)('git', [\n ...(hooks ? ['-c', `core.hooksPath=${hooks}`] : []), '-c', 'submodule.recurse=false', ...args,\n ], { env: { ...env, GIT_TERMINAL_PROMPT: '0', GIT_SSH_COMMAND: env.GIT_SSH_COMMAND || 'ssh -oBatchMode=yes' }, signal, timeoutMs: 180000, maxBytes: 1024 * 1024 });\n if (result.code !== 0) throw new Error(`Could not open/update the repository. ${result.stderr.trim().slice(-1200) || 'Git exited with ' + result.code}. Private repositories require your existing Git credentials.`);\n return result.stdout.trim();\n }\n private async verify(target: string, repository: string, signal?: AbortSignal) {\n const stat = await fs.lstat(target);\n if (!stat.isDirectory() || stat.isSymbolicLink()) throw new Error('The saved repository path is not a regular directory.');\n const root = await fs.realpath(target);\n if (await fs.realpath(await this.git(['-C', root, 'rev-parse', '--show-toplevel'], signal)) !== root) throw new Error('The saved checkout does not belong to this repository.');\n const origin = await this.git(['-C', root, 'remote', 'get-url', 'origin'], signal);\n if (repositoryFromRemote(origin)?.toLowerCase() !== repository.toLowerCase()) throw new Error('The saved checkout origin changed. Its files were preserved.');\n return root;\n }\n async open(target: string, from = process.cwd(), signal?: AbortSignal, progress: (text: string) => void = () => {}): Promise<ChatSource> {\n signal?.throwIfAborted();\n if (!isRemoteSource(target)) {\n const folder = target.replace(/^~(?=\\/|$)/, os.homedir());\n const root = await fs.realpath(path.resolve(from, folder));\n if (!(await fs.stat(root)).isDirectory()) throw new Error('Choose a repository folder or GitHub URL.');\n signal?.throwIfAborted();\n return { root, reused: false };\n }\n const source = githubSource(target), destination = this.target(source.repository);\n const existing = await fs.lstat(destination).then(() => true).catch(e => { if (e.code !== 'ENOENT') throw e; return false; });\n if (existing) {\n const root = await this.verify(destination, source.repository, signal);\n progress(`Using saved checkout of ${source.repository}. Use /pull to fetch the latest changes.`);\n return { root, sourceUrl: source.url, reused: true };\n }\n await fs.mkdir(this.directory, { recursive: true, mode: 0o700 });\n const staging = await fs.mkdtemp(path.join(this.directory, '.clone-'));\n const hooks = path.join(staging, 'empty-hooks'), checkout = path.join(staging, 'checkout');\n await fs.mkdir(hooks, { mode: 0o700 });\n try {\n progress(`Cloning ${source.repository}… Ctrl-C to stop.`);\n await this.git(['clone', '--filter=blob:none', '--single-branch', '--', source.gitUrl, checkout], signal, hooks);\n signal?.throwIfAborted();\n await this.verify(checkout, source.repository, signal);\n await fs.chmod(checkout, 0o700);\n try { await fs.rename(checkout, destination); }\n catch (e) {\n // Two chats may clone the same URL concurrently. Reuse the complete\n // winner, preserving it rather than replacing its existing contents.\n if (!['EEXIST', 'ENOTEMPTY'].includes((e as NodeJS.ErrnoException).code || '')) throw e;\n }\n const root = await this.verify(destination, source.repository, signal);\n progress(`Ready: ${source.repository}\\nSaved checkout: ${root}\\nAsk a question, or use /map to explore.`);\n return { root, sourceUrl: source.url, reused: false };\n } finally { await fs.rm(staging, { recursive: true, force: true }); }\n }\n async pull(root: string, signal?: AbortSignal, progress: (text: string) => void = () => {}) {\n const origin = await this.git(['-C', root, 'remote', 'get-url', 'origin'], signal);\n const repository = repositoryFromRemote(origin);\n if (!repository || await fs.realpath(this.target(repository)).catch(() => null) !== root) throw new Error('/pull updates a saved GitHub checkout. Open one with /repo <GitHub URL> first.');\n await this.verify(root, repository, signal);\n if (await this.git(['-C', root, 'status', '--porcelain', '--untracked-files=all'], signal)) throw new Error('The checkout has local changes. Preserve or commit them before /pull.');\n const hooks = path.join(this.directory, '.pull-hooks-' + randomUUID());\n await fs.mkdir(hooks, { mode: 0o700 });\n try {\n progress(`Pulling latest changes for ${repository}…`);\n const result = await this.git(['-C', root, 'pull', '--ff-only', '--no-rebase'], signal, hooks);\n return result || 'Repository is up to date.';\n } finally { await fs.rm(hooks, { recursive: true, force: true }); }\n }\n}\n"]}
@@ -0,0 +1,43 @@
1
+ import { type AgentMode, type AgentResult } from '../agent/contracts.js';
2
+ export interface ChatSettings {
3
+ root: string;
4
+ sourceUrl?: string;
5
+ mode: AgentMode;
6
+ model?: string;
7
+ provider?: string;
8
+ checks: boolean;
9
+ github: boolean;
10
+ timeout: number;
11
+ maxTurns: number;
12
+ pr?: number;
13
+ issue?: number;
14
+ base?: string;
15
+ }
16
+ export interface ChatTurn {
17
+ at: string;
18
+ prompt: string;
19
+ answer: string;
20
+ run: string;
21
+ status: AgentResult['status'];
22
+ }
23
+ export interface ChatRecord {
24
+ schemaVersion: 1;
25
+ id: string;
26
+ createdAt: string;
27
+ updatedAt: string;
28
+ settings: ChatSettings;
29
+ lastRun: string | null;
30
+ turns: ChatTurn[];
31
+ }
32
+ export declare function newChat(settings: ChatSettings): ChatRecord;
33
+ export declare class ChatStore {
34
+ readonly home: string;
35
+ private env;
36
+ constructor(home?: string, env?: NodeJS.ProcessEnv);
37
+ get directory(): string;
38
+ save(record: ChatRecord): Promise<void>;
39
+ load(id: string): Promise<ChatRecord>;
40
+ list(root: string): Promise<ChatRecord[]>;
41
+ export(record: ChatRecord): Promise<string>;
42
+ }
43
+ export declare function historySummary(records: ChatRecord[]): string;
@@ -0,0 +1,94 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { AGENT_MODES } from '../agent/contracts.js';
5
+ import { agentHome } from '../agent/config.js';
6
+ import { runId } from '../agent/runner.js';
7
+ import { redact, terminalText } from '../agent/process.js';
8
+ import { repositoryFromRemote } from '../agent/github.js';
9
+ export function newChat(settings) {
10
+ const now = new Date().toISOString();
11
+ return { schemaVersion: 1, id: randomUUID(), createdAt: now, updatedAt: now, settings: { ...settings }, lastRun: null, turns: [] };
12
+ }
13
+ function validSettings(s) {
14
+ return !!s && typeof s.root === 'string' && path.isAbsolute(s.root) && AGENT_MODES.includes(s.mode) &&
15
+ typeof s.checks === 'boolean' && typeof s.github === 'boolean' && Number.isInteger(s.timeout) && s.timeout >= 15 && s.timeout <= 3600 &&
16
+ Number.isInteger(s.maxTurns) && s.maxTurns >= 1 && s.maxTurns <= 100 &&
17
+ [s.model, s.provider, s.base].every(v => v === undefined || typeof v === 'string' && v.length <= 512) &&
18
+ [s.pr, s.issue].every(v => v === undefined || Number.isSafeInteger(v) && v > 0) &&
19
+ (s.sourceUrl === undefined || typeof s.sourceUrl === 'string' && repositoryFromRemote(s.sourceUrl) !== null);
20
+ }
21
+ export class ChatStore {
22
+ home;
23
+ env;
24
+ constructor(home = agentHome(), env = process.env) {
25
+ this.home = home;
26
+ this.env = env;
27
+ }
28
+ get directory() { return path.join(this.home, 'chats'); }
29
+ async save(record) {
30
+ await fs.mkdir(this.directory, { recursive: true, mode: 0o700 });
31
+ const target = path.join(this.directory, runId(record.id) + '.json'), temp = target + '.' + randomUUID() + '.tmp';
32
+ const safe = { ...record, turns: record.turns.slice(-100).map(t => ({ ...t, prompt: redact(t.prompt, this.env), answer: redact(t.answer, this.env).slice(0, 32000) })) };
33
+ let encoded = JSON.stringify(safe, null, 2) + '\n';
34
+ // UTF-8 transcripts can use several bytes per character. Bound the stored
35
+ // bytes, rather than producing a conversation our own loader cannot read.
36
+ while (Buffer.byteLength(encoded) > 5 * 1024 * 1024 && safe.turns.length > 1) {
37
+ safe.turns.shift();
38
+ encoded = JSON.stringify(safe, null, 2) + '\n';
39
+ }
40
+ try {
41
+ await fs.writeFile(temp, encoded, { mode: 0o600, flag: 'wx' });
42
+ await fs.rename(temp, target);
43
+ }
44
+ finally {
45
+ await fs.rm(temp, { force: true });
46
+ }
47
+ }
48
+ async load(id) {
49
+ const file = path.join(this.directory, runId(id) + '.json');
50
+ if ((await fs.stat(file)).size > 6 * 1024 * 1024)
51
+ throw new Error('The saved conversation exceeds the size limit.');
52
+ const record = JSON.parse(await fs.readFile(file, 'utf8'));
53
+ if (record.schemaVersion !== 1 || record.id !== id || !validSettings(record.settings) ||
54
+ typeof record.createdAt !== 'string' || typeof record.updatedAt !== 'string' || !Array.isArray(record.turns) || record.turns.length > 100 ||
55
+ !(record.lastRun === null || typeof record.lastRun === 'string') || record.turns.some(t => !t || typeof t.at !== 'string' ||
56
+ typeof t.prompt !== 'string' || t.prompt.length > 16000 || typeof t.answer !== 'string' || t.answer.length > 32000 ||
57
+ typeof t.run !== 'string' || !['completed', 'failed', 'cancelled'].includes(t.status)))
58
+ throw new Error('The saved conversation is invalid.');
59
+ if (record.lastRun)
60
+ runId(record.lastRun);
61
+ for (const turn of record.turns)
62
+ runId(turn.run);
63
+ return record;
64
+ }
65
+ async list(root) {
66
+ const entries = await fs.readdir(this.directory, { withFileTypes: true }).catch(e => { if (e.code !== 'ENOENT')
67
+ throw e; return []; });
68
+ const records = [];
69
+ for (const entry of entries) {
70
+ if (!entry.isFile() || !/^[a-f\d-]{36}\.json$/i.test(entry.name))
71
+ continue;
72
+ try {
73
+ const record = await this.load(entry.name.slice(0, -5));
74
+ if (record.settings.root === root)
75
+ records.push(record);
76
+ }
77
+ catch { /* A damaged entry must not hide the others. */ }
78
+ }
79
+ return records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt)).slice(0, 30);
80
+ }
81
+ async export(record) {
82
+ const directory = path.join(this.home, 'exports');
83
+ await fs.mkdir(directory, { recursive: true, mode: 0o700 });
84
+ const file = path.join(directory, record.id + '-' + randomUUID().slice(0, 8) + '.md');
85
+ const text = ['# Onboarder conversation', '', `Repository: ${record.settings.sourceUrl || record.settings.root}`, `Conversation: ${record.id}`, '',
86
+ ...record.turns.flatMap(turn => ['## You', '', turn.prompt, '', `## Hermes (${turn.status})`, '', turn.answer, '', `Run: ${turn.run}`, ''])].join('\n');
87
+ await fs.writeFile(file, redact(text, this.env), { flag: 'wx', mode: 0o600 });
88
+ return file;
89
+ }
90
+ }
91
+ export function historySummary(records) {
92
+ return records.length ? records.map(r => `${r.id} ${r.settings.mode} ${r.turns.length} turns\n ${r.updatedAt} ${terminalText(r.turns[0]?.prompt || 'Empty conversation').replace(/\s+/g, ' ').slice(0, 100)}`).join('\n\n') : 'No saved conversations for this repository yet.';
93
+ }
94
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/cli/chat/store.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 { AGENT_MODES, type AgentMode, type AgentResult } from '../agent/contracts.js';\nimport { agentHome } from '../agent/config.js';\nimport { runId } from '../agent/runner.js';\nimport { redact, terminalText } from '../agent/process.js';\nimport { repositoryFromRemote } from '../agent/github.js';\n\nexport interface ChatSettings {\n root: string; sourceUrl?: string; mode: AgentMode; model?: string; provider?: string;\n checks: boolean; github: boolean; timeout: number; maxTurns: number; pr?: number; issue?: number; base?: string;\n}\nexport interface ChatTurn { at: string; prompt: string; answer: string; run: string; status: AgentResult['status'] }\nexport interface ChatRecord {\n schemaVersion: 1; id: string; createdAt: string; updatedAt: string;\n settings: ChatSettings; lastRun: string | null; turns: ChatTurn[];\n}\nexport function newChat(settings: ChatSettings): ChatRecord {\n const now = new Date().toISOString();\n return { schemaVersion: 1, id: randomUUID(), createdAt: now, updatedAt: now, settings: { ...settings }, lastRun: null, turns: [] };\n}\nfunction validSettings(s: ChatSettings): boolean {\n return !!s && typeof s.root === 'string' && path.isAbsolute(s.root) && AGENT_MODES.includes(s.mode) &&\n typeof s.checks === 'boolean' && typeof s.github === 'boolean' && Number.isInteger(s.timeout) && s.timeout >= 15 && s.timeout <= 3600 &&\n Number.isInteger(s.maxTurns) && s.maxTurns >= 1 && s.maxTurns <= 100 &&\n [s.model, s.provider, s.base].every(v => v === undefined || typeof v === 'string' && v.length <= 512) &&\n [s.pr, s.issue].every(v => v === undefined || Number.isSafeInteger(v) && v > 0) &&\n (s.sourceUrl === undefined || typeof s.sourceUrl === 'string' && repositoryFromRemote(s.sourceUrl) !== null);\n}\nexport class ChatStore {\n constructor(readonly home = agentHome(), private env: NodeJS.ProcessEnv = process.env) {}\n get directory() { return path.join(this.home, 'chats'); }\n async save(record: ChatRecord) {\n await fs.mkdir(this.directory, { recursive: true, mode: 0o700 });\n const target = path.join(this.directory, runId(record.id) + '.json'), temp = target + '.' + randomUUID() + '.tmp';\n const safe = { ...record, turns: record.turns.slice(-100).map(t => ({ ...t, prompt: redact(t.prompt, this.env), answer: redact(t.answer, this.env).slice(0, 32000) })) };\n let encoded = JSON.stringify(safe, null, 2) + '\\n';\n // UTF-8 transcripts can use several bytes per character. Bound the stored\n // bytes, rather than producing a conversation our own loader cannot read.\n while (Buffer.byteLength(encoded) > 5 * 1024 * 1024 && safe.turns.length > 1) {\n safe.turns.shift(); encoded = JSON.stringify(safe, null, 2) + '\\n';\n }\n try { await fs.writeFile(temp, encoded, { mode: 0o600, flag: 'wx' }); await fs.rename(temp, target); }\n finally { await fs.rm(temp, { force: true }); }\n }\n async load(id: string): Promise<ChatRecord> {\n const file = path.join(this.directory, runId(id) + '.json');\n if ((await fs.stat(file)).size > 6 * 1024 * 1024) throw new Error('The saved conversation exceeds the size limit.');\n const record = JSON.parse(await fs.readFile(file, 'utf8')) as ChatRecord;\n if (record.schemaVersion !== 1 || record.id !== id || !validSettings(record.settings) ||\n typeof record.createdAt !== 'string' || typeof record.updatedAt !== 'string' || !Array.isArray(record.turns) || record.turns.length > 100 ||\n !(record.lastRun === null || typeof record.lastRun === 'string') || record.turns.some(t => !t || typeof t.at !== 'string' ||\n typeof t.prompt !== 'string' || t.prompt.length > 16000 || typeof t.answer !== 'string' || t.answer.length > 32000 ||\n typeof t.run !== 'string' || !['completed', 'failed', 'cancelled'].includes(t.status))) throw new Error('The saved conversation is invalid.');\n if (record.lastRun) runId(record.lastRun);\n for (const turn of record.turns) runId(turn.run);\n return record;\n }\n async list(root: string): Promise<ChatRecord[]> {\n const entries = await fs.readdir(this.directory, { withFileTypes: true }).catch(e => { if (e.code !== 'ENOENT') throw e; return []; });\n const records: ChatRecord[] = [];\n for (const entry of entries) {\n if (!entry.isFile() || !/^[a-f\\d-]{36}\\.json$/i.test(entry.name)) continue;\n try { const record = await this.load(entry.name.slice(0, -5)); if (record.settings.root === root) records.push(record); } catch { /* A damaged entry must not hide the others. */ }\n }\n return records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt)).slice(0, 30);\n }\n async export(record: ChatRecord): Promise<string> {\n const directory = path.join(this.home, 'exports'); await fs.mkdir(directory, { recursive: true, mode: 0o700 });\n const file = path.join(directory, record.id + '-' + randomUUID().slice(0, 8) + '.md');\n const text = ['# Onboarder conversation', '', `Repository: ${record.settings.sourceUrl || record.settings.root}`, `Conversation: ${record.id}`, '',\n ...record.turns.flatMap(turn => ['## You', '', turn.prompt, '', `## Hermes (${turn.status})`, '', turn.answer, '', `Run: ${turn.run}`, ''])].join('\\n');\n await fs.writeFile(file, redact(text, this.env), { flag: 'wx', mode: 0o600 }); return file;\n }\n}\nexport function historySummary(records: ChatRecord[]): string {\n return records.length ? records.map(r => `${r.id} ${r.settings.mode} ${r.turns.length} turns\\n ${r.updatedAt} ${terminalText(r.turns[0]?.prompt || 'Empty conversation').replace(/\\s+/g, ' ').slice(0, 100)}`).join('\\n\\n') : 'No saved conversations for this repository yet.';\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export declare function graphemes(value: string): string[];
2
+ export declare function clusterCells(cluster: string): number;
3
+ export declare function cells(value: string): number;
4
+ export declare function clip(value: string, room: number, ellipsis?: boolean): string;
@@ -0,0 +1,27 @@
1
+ import { terminalText } from '../agent/process.js';
2
+ const segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
3
+ export function graphemes(value) { return [...segmenter.segment(value)].map(s => s.segment); }
4
+ export function clusterCells(cluster) {
5
+ if (/^[\p{Mark}\u200d\ufe0f]+$/u.test(cluster))
6
+ return 0;
7
+ return /\p{Extended_Pictographic}|[\u1100-\u115f\u2329\u232a\u2e80-\ua4cf\uac00-\ud7a3\uf900-\ufaff\ufe10-\ufe19\ufe30-\ufe6f\uff01-\uff60\uffe0-\uffe6\u{1f1e6}-\u{1f1ff}]/u.test(cluster) ? 2 : 1;
8
+ }
9
+ export function cells(value) {
10
+ return graphemes(terminalText(value)).reduce((total, cluster) => total + clusterCells(cluster), 0);
11
+ }
12
+ export function clip(value, room, ellipsis = true) {
13
+ const safe = terminalText(value).replace(/[\r\n\t]/g, ' ');
14
+ if (cells(safe) <= room)
15
+ return safe;
16
+ const limit = Math.max(0, room - (ellipsis && room > 0 ? 1 : 0));
17
+ let result = '', used = 0;
18
+ for (const g of graphemes(safe)) {
19
+ const size = clusterCells(g);
20
+ if (used + size > limit)
21
+ break;
22
+ result += g;
23
+ used += size;
24
+ }
25
+ return result + (ellipsis && room > 0 ? '…' : '');
26
+ }
27
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/cli/chat/text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;AAC7E,MAAM,UAAU,SAAS,CAAC,KAAa,IAAc,OAAO,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAChH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,IAAI,4BAA4B,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,CAAC,CAAC;IACzD,OAAO,sKAAsK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtM,CAAC;AACD,MAAM,UAAU,KAAK,CAAC,KAAa;IACjC,OAAO,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AACrG,CAAC;AACD,MAAM,UAAU,IAAI,CAAC,KAAa,EAAE,IAAY,EAAE,QAAQ,GAAG,IAAI;IAC/D,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAC3D,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,QAAQ,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,IAAI,MAAM,GAAG,EAAE,EAAE,IAAI,GAAG,CAAC,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAAC,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAAC,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;YAAE,MAAM;QAAC,MAAM,IAAI,CAAC,CAAC;QAAC,IAAI,IAAI,IAAI,CAAC;IAAC,CAAC;IAC7H,OAAO,MAAM,GAAG,CAAC,QAAQ,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACpD,CAAC","sourcesContent":["import { terminalText } from '../agent/process.js';\n\nconst segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });\nexport function graphemes(value: string): string[] { return [...segmenter.segment(value)].map(s => s.segment); }\nexport function clusterCells(cluster: string): number {\n if (/^[\\p{Mark}\\u200d\\ufe0f]+$/u.test(cluster)) return 0;\n return /\\p{Extended_Pictographic}|[\\u1100-\\u115f\\u2329\\u232a\\u2e80-\\ua4cf\\uac00-\\ud7a3\\uf900-\\ufaff\\ufe10-\\ufe19\\ufe30-\\ufe6f\\uff01-\\uff60\\uffe0-\\uffe6\\u{1f1e6}-\\u{1f1ff}]/u.test(cluster) ? 2 : 1;\n}\nexport function cells(value: string): number {\n return graphemes(terminalText(value)).reduce((total, cluster) => total + clusterCells(cluster), 0);\n}\nexport function clip(value: string, room: number, ellipsis = true): string {\n const safe = terminalText(value).replace(/[\\r\\n\\t]/g, ' ');\n if (cells(safe) <= room) return safe;\n const limit = Math.max(0, room - (ellipsis && room > 0 ? 1 : 0));\n let result = '', used = 0;\n for (const g of graphemes(safe)) { const size = clusterCells(g); if (used + size > limit) break; result += g; used += size; }\n return result + (ellipsis && room > 0 ? '…' : '');\n}\n"]}
@@ -0,0 +1,26 @@
1
+ export declare function runSetup({ flags, out, err, version }?: Record<string, any>): any;
2
+ export declare function serverDetails(started: any, { configFile, pid, mode, logFile }?: Record<string, any>): {
3
+ rows: {
4
+ label: string;
5
+ value: string;
6
+ }[];
7
+ urls: import("../shared/contracts.js").ServerUrls;
8
+ mode: any;
9
+ };
10
+ export declare function watchResize(render: any, stream?: NodeJS.WriteStream & {
11
+ fd: 1;
12
+ }): (..._args: unknown[]) => void;
13
+ export declare function runStart({ flags, out, err }?: Record<string, any>): any;
14
+ export declare function runStartBackground({ flags, out, err }?: Record<string, any>): any;
15
+ export declare function runStatus({ flags, out }?: Record<string, any>): Promise<number>;
16
+ export declare function humanDuration(ms: any): string;
17
+ export declare function runStop({ flags, out, err }?: Record<string, any>): Promise<0 | 1>;
18
+ export declare function runRestart(options?: Record<string, any>): Promise<any>;
19
+ export declare function runLogs({ flags, out, err }?: Record<string, any>): Promise<0 | 1 | 2>;
20
+ export declare function runStartup(action?: string, { flags, out, err }?: Record<string, any>): Promise<0 | 1>;
21
+ export declare function runConfig(sub: any, args: any, { flags, out }?: Record<string, any>): Promise<number>;
22
+ export declare function runConfigKey(action: any, args: any, { flags, out, err }?: Record<string, any>): Promise<number>;
23
+ export declare function runConfigReset({ flags, out, err }?: Record<string, any>): Promise<0 | 1>;
24
+ export declare function runDoctor({ flags, out }?: Record<string, any>): Promise<0 | 1>;
25
+ export declare function runHttps(action?: string, { flags, out, err }?: Record<string, any>): Promise<0 | 1>;
26
+ export declare function runTunnel(kind: any, { flags, out, err }?: Record<string, any>): Promise<unknown>;