@phnx-labs/agents-cli 1.12.0 → 1.14.2

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 (496) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/README.md +308 -297
  3. package/dist/commands/alias.d.ts +11 -0
  4. package/dist/commands/alias.js +117 -0
  5. package/dist/commands/beta.d.ts +2 -0
  6. package/dist/commands/beta.js +53 -0
  7. package/dist/commands/cloud.d.ts +10 -0
  8. package/dist/commands/cloud.js +408 -0
  9. package/dist/commands/commands.d.ts +9 -1
  10. package/dist/commands/commands.js +24 -172
  11. package/dist/commands/daemon.d.ts +8 -1
  12. package/dist/commands/daemon.js +13 -5
  13. package/dist/commands/doctor.d.ts +15 -0
  14. package/dist/commands/doctor.js +132 -0
  15. package/dist/commands/drive.d.ts +8 -1
  16. package/dist/commands/drive.js +20 -3
  17. package/dist/commands/exec.d.ts +8 -1
  18. package/dist/commands/exec.js +207 -20
  19. package/dist/commands/factory.d.ts +19 -0
  20. package/dist/commands/factory.js +71 -0
  21. package/dist/commands/fork.d.ts +8 -1
  22. package/dist/commands/fork.js +11 -4
  23. package/dist/commands/hooks.d.ts +9 -1
  24. package/dist/commands/hooks.js +30 -182
  25. package/dist/commands/init.d.ts +15 -1
  26. package/dist/commands/init.js +168 -74
  27. package/dist/commands/mcp.d.ts +9 -1
  28. package/dist/commands/mcp.js +11 -7
  29. package/dist/commands/models.d.ts +8 -1
  30. package/dist/commands/models.js +45 -6
  31. package/dist/commands/packages.d.ts +8 -1
  32. package/dist/commands/packages.js +13 -7
  33. package/dist/commands/permissions.d.ts +9 -1
  34. package/dist/commands/permissions.js +3 -3
  35. package/dist/commands/plugins.d.ts +8 -1
  36. package/dist/commands/plugins.js +13 -2
  37. package/dist/commands/profiles.d.ts +11 -0
  38. package/dist/commands/profiles.js +291 -0
  39. package/dist/commands/prune.d.ts +22 -0
  40. package/dist/commands/prune.js +191 -0
  41. package/dist/commands/pty.d.ts +1 -1
  42. package/dist/commands/pty.js +2 -1
  43. package/dist/commands/pull.d.ts +8 -1
  44. package/dist/commands/pull.js +93 -129
  45. package/dist/commands/refresh-memory.d.ts +7 -1
  46. package/dist/commands/refresh-memory.js +7 -1
  47. package/dist/commands/repo.d.ts +15 -0
  48. package/dist/commands/repo.js +570 -0
  49. package/dist/commands/resource-view.d.ts +10 -3
  50. package/dist/commands/resource-view.js +18 -5
  51. package/dist/commands/routines.d.ts +8 -1
  52. package/dist/commands/routines.js +17 -4
  53. package/dist/commands/rules.d.ts +9 -1
  54. package/dist/commands/rules.js +16 -11
  55. package/dist/commands/secrets.d.ts +10 -0
  56. package/dist/commands/secrets.js +518 -0
  57. package/dist/commands/sessions-picker.d.ts +2 -1
  58. package/dist/commands/sessions-picker.js +88 -11
  59. package/dist/commands/sessions-tail.d.ts +19 -0
  60. package/dist/commands/sessions-tail.js +235 -0
  61. package/dist/commands/sessions.d.ts +2 -1
  62. package/dist/commands/sessions.js +288 -7
  63. package/dist/commands/skills.d.ts +9 -1
  64. package/dist/commands/skills.js +28 -178
  65. package/dist/commands/status.d.ts +7 -1
  66. package/dist/commands/status.js +7 -1
  67. package/dist/commands/subagents.d.ts +8 -1
  68. package/dist/commands/subagents.js +11 -1
  69. package/dist/commands/sync.d.ts +8 -1
  70. package/dist/commands/sync.js +8 -1
  71. package/dist/commands/teams-picker.d.ts +4 -1
  72. package/dist/commands/teams-picker.js +55 -3
  73. package/dist/commands/teams.d.ts +15 -1
  74. package/dist/commands/teams.js +323 -69
  75. package/dist/commands/usage.d.ts +11 -0
  76. package/dist/commands/usage.js +60 -0
  77. package/dist/commands/utils.d.ts +6 -1
  78. package/dist/commands/utils.js +6 -1
  79. package/dist/commands/versions.d.ts +8 -1
  80. package/dist/commands/versions.js +4 -3
  81. package/dist/commands/view.d.ts +47 -2
  82. package/dist/commands/view.js +353 -20
  83. package/dist/index.d.ts +7 -2
  84. package/dist/index.js +205 -38
  85. package/dist/lib/acp/client.d.ts +31 -0
  86. package/dist/lib/acp/client.js +117 -0
  87. package/dist/lib/acp/harnesses.d.ts +26 -0
  88. package/dist/lib/acp/harnesses.js +65 -0
  89. package/dist/lib/acp/run.d.ts +18 -0
  90. package/dist/lib/acp/run.js +39 -0
  91. package/dist/lib/agents.d.ts +74 -2
  92. package/dist/lib/agents.js +207 -23
  93. package/dist/lib/artifact-actions.d.ts +8 -4
  94. package/dist/lib/artifact-actions.js +8 -6
  95. package/dist/lib/auto-pull-worker.d.ts +11 -0
  96. package/dist/lib/auto-pull-worker.js +121 -0
  97. package/dist/lib/auto-pull.d.ts +31 -0
  98. package/dist/lib/auto-pull.js +97 -0
  99. package/dist/lib/beta.d.ts +23 -0
  100. package/dist/lib/beta.js +90 -0
  101. package/dist/lib/capabilities.d.ts +29 -0
  102. package/dist/lib/capabilities.js +74 -0
  103. package/dist/lib/cloud/codex.d.ts +25 -0
  104. package/dist/lib/cloud/codex.js +250 -0
  105. package/dist/lib/cloud/factory.d.ts +31 -0
  106. package/dist/lib/cloud/factory.js +53 -0
  107. package/dist/lib/cloud/registry.d.ts +15 -0
  108. package/dist/lib/cloud/registry.js +67 -0
  109. package/dist/lib/cloud/rush.d.ts +75 -0
  110. package/dist/lib/cloud/rush.js +438 -0
  111. package/dist/lib/cloud/store.d.ts +22 -0
  112. package/dist/lib/cloud/store.js +115 -0
  113. package/dist/lib/cloud/stream.d.ts +23 -0
  114. package/dist/lib/cloud/stream.js +194 -0
  115. package/dist/lib/cloud/types.d.ts +205 -0
  116. package/dist/lib/cloud/types.js +34 -0
  117. package/dist/lib/command-skills.d.ts +20 -0
  118. package/dist/lib/command-skills.js +142 -0
  119. package/dist/lib/commands.d.ts +22 -2
  120. package/dist/lib/commands.js +51 -11
  121. package/dist/lib/convert.d.ts +10 -1
  122. package/dist/lib/convert.js +9 -1
  123. package/dist/lib/daemon.d.ts +21 -1
  124. package/dist/lib/daemon.js +97 -4
  125. package/dist/lib/drive-sync.d.ts +18 -1
  126. package/dist/lib/drive-sync.js +57 -15
  127. package/dist/lib/exec.d.ts +25 -5
  128. package/dist/lib/exec.js +72 -27
  129. package/dist/lib/fs-walk.d.ts +2 -0
  130. package/dist/lib/fs-walk.js +40 -0
  131. package/dist/lib/fuzzy.d.ts +53 -0
  132. package/dist/lib/fuzzy.js +72 -0
  133. package/dist/lib/gemini-settings.d.ts +4 -0
  134. package/dist/lib/gemini-settings.js +33 -0
  135. package/dist/lib/git.d.ts +12 -2
  136. package/dist/lib/git.js +17 -6
  137. package/dist/lib/help.d.ts +20 -1
  138. package/dist/lib/help.js +45 -6
  139. package/dist/lib/hooks/match.d.ts +32 -0
  140. package/dist/lib/hooks/match.js +120 -0
  141. package/dist/lib/hooks.d.ts +17 -4
  142. package/dist/lib/hooks.js +191 -21
  143. package/dist/lib/manifest.d.ts +6 -1
  144. package/dist/lib/manifest.js +15 -4
  145. package/dist/lib/markdown.d.ts +0 -1
  146. package/dist/lib/markdown.js +6 -1
  147. package/dist/lib/mcp.d.ts +0 -1
  148. package/dist/lib/mcp.js +29 -33
  149. package/dist/lib/memory-compile.d.ts +13 -3
  150. package/dist/lib/memory-compile.js +31 -9
  151. package/dist/lib/memory.d.ts +14 -7
  152. package/dist/lib/memory.js +67 -38
  153. package/dist/lib/migrate.d.ts +8 -0
  154. package/dist/lib/migrate.js +85 -0
  155. package/dist/lib/models.d.ts +25 -11
  156. package/dist/lib/models.js +405 -16
  157. package/dist/lib/onepassword.d.ts +63 -0
  158. package/dist/lib/onepassword.js +186 -0
  159. package/dist/lib/paths.d.ts +8 -0
  160. package/dist/lib/paths.js +20 -0
  161. package/dist/lib/permissions.d.ts +24 -2
  162. package/dist/lib/permissions.js +117 -48
  163. package/dist/lib/picker.d.ts +10 -1
  164. package/dist/lib/picker.js +15 -1
  165. package/dist/lib/plugins.d.ts +7 -1
  166. package/dist/lib/plugins.js +10 -1
  167. package/dist/lib/profiles-presets.d.ts +24 -0
  168. package/dist/lib/profiles-presets.js +103 -0
  169. package/dist/lib/profiles.d.ts +69 -0
  170. package/dist/lib/profiles.js +144 -0
  171. package/dist/lib/pty-client.d.ts +1 -1
  172. package/dist/lib/pty-client.js +0 -1
  173. package/dist/lib/pty-server.d.ts +16 -2
  174. package/dist/lib/pty-server.js +92 -3
  175. package/dist/lib/registry.d.ts +23 -3
  176. package/dist/lib/registry.js +153 -8
  177. package/dist/lib/resources.d.ts +28 -1
  178. package/dist/lib/resources.js +79 -1
  179. package/dist/lib/rotate.d.ts +89 -0
  180. package/dist/lib/rotate.js +327 -0
  181. package/dist/lib/routines.d.ts +29 -1
  182. package/dist/lib/routines.js +32 -5
  183. package/dist/lib/runner.d.ts +14 -1
  184. package/dist/lib/runner.js +22 -3
  185. package/dist/lib/sandbox.d.ts +16 -1
  186. package/dist/lib/sandbox.js +39 -16
  187. package/dist/lib/scheduler.d.ts +8 -1
  188. package/dist/lib/scheduler.js +8 -1
  189. package/dist/lib/secrets/AgentsKeychain.app/Contents/CodeResources +0 -0
  190. package/dist/lib/secrets/AgentsKeychain.app/Contents/Info.plist +22 -0
  191. package/dist/lib/secrets/AgentsKeychain.app/Contents/MacOS/AgentsKeychain +0 -0
  192. package/dist/lib/secrets/AgentsKeychain.app/Contents/_CodeSignature/CodeResources +123 -0
  193. package/dist/lib/secrets/AgentsKeychain.app/Contents/embedded.provisionprofile +0 -0
  194. package/dist/lib/secrets/bundles.d.ts +39 -0
  195. package/dist/lib/secrets/bundles.js +189 -0
  196. package/dist/lib/secrets/index.d.ts +55 -0
  197. package/dist/lib/secrets/index.js +211 -0
  198. package/dist/lib/secrets/profiles.d.ts +10 -0
  199. package/dist/lib/secrets/profiles.js +13 -0
  200. package/dist/lib/session/active.d.ts +43 -0
  201. package/dist/lib/session/active.js +392 -0
  202. package/dist/lib/session/artifacts.d.ts +16 -0
  203. package/dist/lib/session/artifacts.js +95 -0
  204. package/dist/lib/session/cloud.d.ts +30 -0
  205. package/dist/lib/session/cloud.js +121 -0
  206. package/dist/lib/session/db.d.ts +23 -2
  207. package/dist/lib/session/db.js +76 -12
  208. package/dist/lib/session/discover.d.ts +19 -4
  209. package/dist/lib/session/discover.js +344 -48
  210. package/dist/lib/session/parse.d.ts +28 -1
  211. package/dist/lib/session/parse.js +267 -9
  212. package/dist/lib/session/prompt.d.ts +9 -1
  213. package/dist/lib/session/prompt.js +17 -3
  214. package/dist/lib/session/render.d.ts +13 -1
  215. package/dist/lib/session/render.js +20 -1
  216. package/dist/lib/session/team-filter.d.ts +9 -1
  217. package/dist/lib/session/team-filter.js +11 -2
  218. package/dist/lib/session/types.d.ts +24 -2
  219. package/dist/lib/session/types.js +10 -2
  220. package/dist/lib/shims.d.ts +93 -5
  221. package/dist/lib/shims.js +380 -67
  222. package/dist/lib/skills.d.ts +27 -2
  223. package/dist/lib/skills.js +127 -65
  224. package/dist/lib/sqlite.d.ts +43 -0
  225. package/dist/lib/sqlite.js +94 -0
  226. package/dist/lib/state.d.ts +114 -22
  227. package/dist/lib/state.js +323 -138
  228. package/dist/lib/subagents.d.ts +9 -1
  229. package/dist/lib/subagents.js +70 -63
  230. package/dist/lib/sync-manifest.d.ts +81 -0
  231. package/dist/lib/sync-manifest.js +450 -0
  232. package/dist/lib/teams/agents.d.ts +103 -5
  233. package/dist/lib/teams/agents.js +414 -91
  234. package/dist/lib/teams/api.d.ts +26 -3
  235. package/dist/lib/teams/api.js +63 -3
  236. package/dist/lib/teams/debug.d.ts +6 -1
  237. package/dist/lib/teams/debug.js +6 -1
  238. package/dist/lib/teams/file_ops.d.ts +7 -1
  239. package/dist/lib/teams/file_ops.js +7 -1
  240. package/dist/lib/teams/index.d.ts +15 -0
  241. package/dist/lib/teams/index.js +14 -0
  242. package/dist/lib/teams/parsers.d.ts +4 -1
  243. package/dist/lib/teams/parsers.js +11 -1
  244. package/dist/lib/teams/persistence.d.ts +15 -1
  245. package/dist/lib/teams/persistence.js +102 -20
  246. package/dist/lib/teams/registry.d.ts +12 -1
  247. package/dist/lib/teams/registry.js +116 -33
  248. package/dist/lib/teams/summarizer.d.ts +15 -1
  249. package/dist/lib/teams/summarizer.js +14 -1
  250. package/dist/lib/teams/supervisor.d.ts +48 -0
  251. package/dist/lib/teams/supervisor.js +73 -0
  252. package/dist/lib/template.d.ts +8 -6
  253. package/dist/lib/template.js +8 -6
  254. package/dist/lib/types.d.ts +147 -8
  255. package/dist/lib/types.js +26 -3
  256. package/dist/lib/usage.d.ts +48 -1
  257. package/dist/lib/usage.js +97 -16
  258. package/dist/lib/version-duplicates.d.ts +21 -0
  259. package/dist/lib/version-duplicates.js +90 -0
  260. package/dist/lib/versions.d.ts +39 -4
  261. package/dist/lib/versions.js +401 -111
  262. package/package.json +33 -18
  263. package/scripts/postinstall.js +126 -30
  264. package/dist/commands/__tests__/sessions.test.d.ts +0 -2
  265. package/dist/commands/__tests__/sessions.test.d.ts.map +0 -1
  266. package/dist/commands/__tests__/sessions.test.js +0 -636
  267. package/dist/commands/__tests__/sessions.test.js.map +0 -1
  268. package/dist/commands/commands.d.ts.map +0 -1
  269. package/dist/commands/commands.js.map +0 -1
  270. package/dist/commands/daemon.d.ts.map +0 -1
  271. package/dist/commands/daemon.js.map +0 -1
  272. package/dist/commands/drive.d.ts.map +0 -1
  273. package/dist/commands/drive.js.map +0 -1
  274. package/dist/commands/exec.d.ts.map +0 -1
  275. package/dist/commands/exec.js.map +0 -1
  276. package/dist/commands/fork.d.ts.map +0 -1
  277. package/dist/commands/fork.js.map +0 -1
  278. package/dist/commands/hooks.d.ts.map +0 -1
  279. package/dist/commands/hooks.js.map +0 -1
  280. package/dist/commands/init.d.ts.map +0 -1
  281. package/dist/commands/init.js.map +0 -1
  282. package/dist/commands/mcp.d.ts.map +0 -1
  283. package/dist/commands/mcp.js.map +0 -1
  284. package/dist/commands/models.d.ts.map +0 -1
  285. package/dist/commands/models.js.map +0 -1
  286. package/dist/commands/packages.d.ts.map +0 -1
  287. package/dist/commands/packages.js.map +0 -1
  288. package/dist/commands/permissions.d.ts.map +0 -1
  289. package/dist/commands/permissions.js.map +0 -1
  290. package/dist/commands/plugins.d.ts.map +0 -1
  291. package/dist/commands/plugins.js.map +0 -1
  292. package/dist/commands/pty.d.ts.map +0 -1
  293. package/dist/commands/pty.js.map +0 -1
  294. package/dist/commands/pull.d.ts.map +0 -1
  295. package/dist/commands/pull.js.map +0 -1
  296. package/dist/commands/push.d.ts +0 -3
  297. package/dist/commands/push.d.ts.map +0 -1
  298. package/dist/commands/push.js +0 -180
  299. package/dist/commands/push.js.map +0 -1
  300. package/dist/commands/refresh-memory.d.ts.map +0 -1
  301. package/dist/commands/refresh-memory.js.map +0 -1
  302. package/dist/commands/resource-view.d.ts.map +0 -1
  303. package/dist/commands/resource-view.js.map +0 -1
  304. package/dist/commands/routines.d.ts.map +0 -1
  305. package/dist/commands/routines.js.map +0 -1
  306. package/dist/commands/rules.d.ts.map +0 -1
  307. package/dist/commands/rules.js.map +0 -1
  308. package/dist/commands/sessions-picker.d.ts.map +0 -1
  309. package/dist/commands/sessions-picker.js.map +0 -1
  310. package/dist/commands/sessions.d.ts.map +0 -1
  311. package/dist/commands/sessions.js.map +0 -1
  312. package/dist/commands/skills.d.ts.map +0 -1
  313. package/dist/commands/skills.js.map +0 -1
  314. package/dist/commands/status.d.ts.map +0 -1
  315. package/dist/commands/status.js.map +0 -1
  316. package/dist/commands/subagents.d.ts.map +0 -1
  317. package/dist/commands/subagents.js.map +0 -1
  318. package/dist/commands/sync.d.ts.map +0 -1
  319. package/dist/commands/sync.js.map +0 -1
  320. package/dist/commands/teams-picker.d.ts.map +0 -1
  321. package/dist/commands/teams-picker.js.map +0 -1
  322. package/dist/commands/teams.d.ts.map +0 -1
  323. package/dist/commands/teams.js.map +0 -1
  324. package/dist/commands/utils.d.ts.map +0 -1
  325. package/dist/commands/utils.js.map +0 -1
  326. package/dist/commands/versions.d.ts.map +0 -1
  327. package/dist/commands/versions.js.map +0 -1
  328. package/dist/commands/view.d.ts.map +0 -1
  329. package/dist/commands/view.js.map +0 -1
  330. package/dist/index.d.ts.map +0 -1
  331. package/dist/index.js.map +0 -1
  332. package/dist/lib/__tests__/bugfixes.test.d.ts +0 -2
  333. package/dist/lib/__tests__/bugfixes.test.d.ts.map +0 -1
  334. package/dist/lib/__tests__/bugfixes.test.js +0 -192
  335. package/dist/lib/__tests__/bugfixes.test.js.map +0 -1
  336. package/dist/lib/__tests__/exec.test.d.ts +0 -2
  337. package/dist/lib/__tests__/exec.test.d.ts.map +0 -1
  338. package/dist/lib/__tests__/exec.test.js +0 -446
  339. package/dist/lib/__tests__/exec.test.js.map +0 -1
  340. package/dist/lib/__tests__/git-sync.test.d.ts +0 -2
  341. package/dist/lib/__tests__/git-sync.test.d.ts.map +0 -1
  342. package/dist/lib/__tests__/git-sync.test.js +0 -138
  343. package/dist/lib/__tests__/git-sync.test.js.map +0 -1
  344. package/dist/lib/__tests__/hooks.test.d.ts +0 -2
  345. package/dist/lib/__tests__/hooks.test.d.ts.map +0 -1
  346. package/dist/lib/__tests__/hooks.test.js +0 -203
  347. package/dist/lib/__tests__/hooks.test.js.map +0 -1
  348. package/dist/lib/__tests__/memory-compile.test.d.ts +0 -2
  349. package/dist/lib/__tests__/memory-compile.test.d.ts.map +0 -1
  350. package/dist/lib/__tests__/memory-compile.test.js +0 -95
  351. package/dist/lib/__tests__/memory-compile.test.js.map +0 -1
  352. package/dist/lib/__tests__/models.test.d.ts +0 -2
  353. package/dist/lib/__tests__/models.test.d.ts.map +0 -1
  354. package/dist/lib/__tests__/models.test.js +0 -184
  355. package/dist/lib/__tests__/models.test.js.map +0 -1
  356. package/dist/lib/__tests__/usage.test.d.ts +0 -2
  357. package/dist/lib/__tests__/usage.test.d.ts.map +0 -1
  358. package/dist/lib/__tests__/usage.test.js +0 -218
  359. package/dist/lib/__tests__/usage.test.js.map +0 -1
  360. package/dist/lib/agents.d.ts.map +0 -1
  361. package/dist/lib/agents.js.map +0 -1
  362. package/dist/lib/artifact-actions.d.ts.map +0 -1
  363. package/dist/lib/artifact-actions.js.map +0 -1
  364. package/dist/lib/commands.d.ts.map +0 -1
  365. package/dist/lib/commands.js.map +0 -1
  366. package/dist/lib/convert.d.ts.map +0 -1
  367. package/dist/lib/convert.js.map +0 -1
  368. package/dist/lib/daemon.d.ts.map +0 -1
  369. package/dist/lib/daemon.js.map +0 -1
  370. package/dist/lib/drive-sync.d.ts.map +0 -1
  371. package/dist/lib/drive-sync.js.map +0 -1
  372. package/dist/lib/exec.d.ts.map +0 -1
  373. package/dist/lib/exec.js.map +0 -1
  374. package/dist/lib/factory.d.ts +0 -57
  375. package/dist/lib/factory.d.ts.map +0 -1
  376. package/dist/lib/factory.js +0 -110
  377. package/dist/lib/factory.js.map +0 -1
  378. package/dist/lib/git.d.ts.map +0 -1
  379. package/dist/lib/git.js.map +0 -1
  380. package/dist/lib/help.d.ts.map +0 -1
  381. package/dist/lib/help.js.map +0 -1
  382. package/dist/lib/hooks.d.ts.map +0 -1
  383. package/dist/lib/hooks.js.map +0 -1
  384. package/dist/lib/manifest.d.ts.map +0 -1
  385. package/dist/lib/manifest.js.map +0 -1
  386. package/dist/lib/markdown.d.ts.map +0 -1
  387. package/dist/lib/markdown.js.map +0 -1
  388. package/dist/lib/mcp.d.ts.map +0 -1
  389. package/dist/lib/mcp.js.map +0 -1
  390. package/dist/lib/memory-compile.d.ts.map +0 -1
  391. package/dist/lib/memory-compile.js.map +0 -1
  392. package/dist/lib/memory.d.ts.map +0 -1
  393. package/dist/lib/memory.js.map +0 -1
  394. package/dist/lib/models.d.ts.map +0 -1
  395. package/dist/lib/models.js.map +0 -1
  396. package/dist/lib/permissions.d.ts.map +0 -1
  397. package/dist/lib/permissions.js.map +0 -1
  398. package/dist/lib/picker.d.ts.map +0 -1
  399. package/dist/lib/picker.js.map +0 -1
  400. package/dist/lib/plugins.d.ts.map +0 -1
  401. package/dist/lib/plugins.js.map +0 -1
  402. package/dist/lib/pty-client.d.ts.map +0 -1
  403. package/dist/lib/pty-client.js.map +0 -1
  404. package/dist/lib/pty-server.d.ts.map +0 -1
  405. package/dist/lib/pty-server.js.map +0 -1
  406. package/dist/lib/registry.d.ts.map +0 -1
  407. package/dist/lib/registry.js.map +0 -1
  408. package/dist/lib/resources.d.ts.map +0 -1
  409. package/dist/lib/resources.js.map +0 -1
  410. package/dist/lib/routines.d.ts.map +0 -1
  411. package/dist/lib/routines.js.map +0 -1
  412. package/dist/lib/runner.d.ts.map +0 -1
  413. package/dist/lib/runner.js.map +0 -1
  414. package/dist/lib/sandbox.d.ts.map +0 -1
  415. package/dist/lib/sandbox.js.map +0 -1
  416. package/dist/lib/scheduler.d.ts.map +0 -1
  417. package/dist/lib/scheduler.js.map +0 -1
  418. package/dist/lib/session/__tests__/db.test.d.ts +0 -2
  419. package/dist/lib/session/__tests__/db.test.d.ts.map +0 -1
  420. package/dist/lib/session/__tests__/db.test.js +0 -54
  421. package/dist/lib/session/__tests__/db.test.js.map +0 -1
  422. package/dist/lib/session/__tests__/discover.test.d.ts +0 -2
  423. package/dist/lib/session/__tests__/discover.test.d.ts.map +0 -1
  424. package/dist/lib/session/__tests__/discover.test.js +0 -63
  425. package/dist/lib/session/__tests__/discover.test.js.map +0 -1
  426. package/dist/lib/session/__tests__/prompt.test.d.ts +0 -2
  427. package/dist/lib/session/__tests__/prompt.test.d.ts.map +0 -1
  428. package/dist/lib/session/__tests__/prompt.test.js +0 -44
  429. package/dist/lib/session/__tests__/prompt.test.js.map +0 -1
  430. package/dist/lib/session/__tests__/render.test.d.ts +0 -2
  431. package/dist/lib/session/__tests__/render.test.d.ts.map +0 -1
  432. package/dist/lib/session/__tests__/render.test.js +0 -602
  433. package/dist/lib/session/__tests__/render.test.js.map +0 -1
  434. package/dist/lib/session/db.d.ts.map +0 -1
  435. package/dist/lib/session/db.js.map +0 -1
  436. package/dist/lib/session/discover.d.ts.map +0 -1
  437. package/dist/lib/session/discover.js.map +0 -1
  438. package/dist/lib/session/parse.d.ts.map +0 -1
  439. package/dist/lib/session/parse.js.map +0 -1
  440. package/dist/lib/session/prompt.d.ts.map +0 -1
  441. package/dist/lib/session/prompt.js.map +0 -1
  442. package/dist/lib/session/prompt.test.d.ts +0 -2
  443. package/dist/lib/session/prompt.test.d.ts.map +0 -1
  444. package/dist/lib/session/prompt.test.js +0 -57
  445. package/dist/lib/session/prompt.test.js.map +0 -1
  446. package/dist/lib/session/render.d.ts.map +0 -1
  447. package/dist/lib/session/render.js.map +0 -1
  448. package/dist/lib/session/team-filter.d.ts.map +0 -1
  449. package/dist/lib/session/team-filter.js.map +0 -1
  450. package/dist/lib/session/team-filter.test.d.ts +0 -2
  451. package/dist/lib/session/team-filter.test.d.ts.map +0 -1
  452. package/dist/lib/session/team-filter.test.js +0 -157
  453. package/dist/lib/session/team-filter.test.js.map +0 -1
  454. package/dist/lib/session/types.d.ts.map +0 -1
  455. package/dist/lib/session/types.js.map +0 -1
  456. package/dist/lib/shims.d.ts.map +0 -1
  457. package/dist/lib/shims.js.map +0 -1
  458. package/dist/lib/skills.d.ts.map +0 -1
  459. package/dist/lib/skills.js.map +0 -1
  460. package/dist/lib/state.d.ts.map +0 -1
  461. package/dist/lib/state.js.map +0 -1
  462. package/dist/lib/subagents.d.ts.map +0 -1
  463. package/dist/lib/subagents.js.map +0 -1
  464. package/dist/lib/teams/agents.d.ts.map +0 -1
  465. package/dist/lib/teams/agents.js.map +0 -1
  466. package/dist/lib/teams/api.d.ts.map +0 -1
  467. package/dist/lib/teams/api.js.map +0 -1
  468. package/dist/lib/teams/cloud.d.ts +0 -11
  469. package/dist/lib/teams/cloud.d.ts.map +0 -1
  470. package/dist/lib/teams/cloud.js +0 -169
  471. package/dist/lib/teams/cloud.js.map +0 -1
  472. package/dist/lib/teams/debug.d.ts.map +0 -1
  473. package/dist/lib/teams/debug.js.map +0 -1
  474. package/dist/lib/teams/file_ops.d.ts.map +0 -1
  475. package/dist/lib/teams/file_ops.js.map +0 -1
  476. package/dist/lib/teams/parsers.d.ts.map +0 -1
  477. package/dist/lib/teams/parsers.js.map +0 -1
  478. package/dist/lib/teams/persistence.d.ts.map +0 -1
  479. package/dist/lib/teams/persistence.js.map +0 -1
  480. package/dist/lib/teams/ralph.d.ts +0 -8
  481. package/dist/lib/teams/ralph.d.ts.map +0 -1
  482. package/dist/lib/teams/ralph.js +0 -59
  483. package/dist/lib/teams/ralph.js.map +0 -1
  484. package/dist/lib/teams/registry.d.ts.map +0 -1
  485. package/dist/lib/teams/registry.js.map +0 -1
  486. package/dist/lib/teams/summarizer.d.ts.map +0 -1
  487. package/dist/lib/teams/summarizer.js.map +0 -1
  488. package/dist/lib/template.d.ts.map +0 -1
  489. package/dist/lib/template.js.map +0 -1
  490. package/dist/lib/types.d.ts.map +0 -1
  491. package/dist/lib/types.js.map +0 -1
  492. package/dist/lib/usage.d.ts.map +0 -1
  493. package/dist/lib/usage.js.map +0 -1
  494. package/dist/lib/versions.d.ts.map +0 -1
  495. package/dist/lib/versions.js.map +0 -1
  496. package/scripts/rebuild-sqlite.sh +0 -46
@@ -0,0 +1,392 @@
1
+ /**
2
+ * Active-session detection across every context an agent can run in:
3
+ *
4
+ * - `terminal` — agents launched from VS Code / Cursor / Codium via the
5
+ * agents-cli extension. Published to `~/.agents-system/runtime/live-terminals.json`
6
+ * with PID + session UUID per entry.
7
+ * - `teams` — agents spawned by `agents teams add`, tracked in
8
+ * `~/.agents-system/teams/agents/<id>/meta.json` with a PID the manager polls.
9
+ * - `cloud` — dispatched to Rush / Codex Cloud / Factory, tracked in
10
+ * the SQLite cache at `~/.agents-system/cloud/tasks.db`.
11
+ * - `headless` — bare `claude` / `codex` / `gemini` / `cursor-agent` /
12
+ * `opencode` processes that don't belong to any of the above. Detected
13
+ * by `ps` minus the PIDs we've already attributed.
14
+ *
15
+ * `running` vs `idle` is a secondary classification within the alive set:
16
+ * the process is holding its session file, but the file's mtime is older
17
+ * than ACTIVE_MTIME_WINDOW_MS, so it's probably waiting on the user.
18
+ */
19
+ import * as fs from 'fs';
20
+ import * as path from 'path';
21
+ import * as os from 'os';
22
+ import { execFile } from 'child_process';
23
+ import { promisify } from 'util';
24
+ import { listActiveTasks } from '../cloud/store.js';
25
+ import { AgentManager } from '../teams/agents.js';
26
+ import { getAgentsDir } from '../state.js';
27
+ const execFileAsync = promisify(execFile);
28
+ const HOME = os.homedir();
29
+ const LIVE_TERMINALS_FILE = path.join(getAgentsDir(), 'runtime', 'live-terminals.json');
30
+ /**
31
+ * A process is classified `running` if its session file was touched in the
32
+ * last 2 minutes. Every Claude/Codex tool-call appends an event, so a
33
+ * healthy session writes several times a minute.
34
+ */
35
+ const ACTIVE_MTIME_WINDOW_MS = 2 * 60_000;
36
+ /** Executables we recognize as agent CLIs when scanning the process table. */
37
+ const AGENT_CLI_NAMES = {
38
+ claude: 'claude',
39
+ codex: 'codex',
40
+ gemini: 'gemini',
41
+ 'cursor-agent': 'cursor',
42
+ opencode: 'opencode',
43
+ };
44
+ function isPidAlive(pid) {
45
+ if (!pid || pid < 1)
46
+ return false;
47
+ try {
48
+ process.kill(pid, 0);
49
+ return true;
50
+ }
51
+ catch (err) {
52
+ return err?.code === 'EPERM';
53
+ }
54
+ }
55
+ /** Read the live-terminals registry, dedupe by sessionId, keep only pid-alive entries. */
56
+ function readLiveTerminals() {
57
+ let raw;
58
+ try {
59
+ raw = fs.readFileSync(LIVE_TERMINALS_FILE, 'utf8');
60
+ }
61
+ catch {
62
+ return [];
63
+ }
64
+ let parsed;
65
+ try {
66
+ parsed = JSON.parse(raw);
67
+ }
68
+ catch {
69
+ return [];
70
+ }
71
+ if (!parsed || typeof parsed !== 'object')
72
+ return [];
73
+ const merged = new Map();
74
+ for (const slice of Object.values(parsed)) {
75
+ for (const e of (slice?.entries ?? [])) {
76
+ if (!e?.sessionId || !isPidAlive(e.pid))
77
+ continue;
78
+ merged.set(e.sessionId, e);
79
+ }
80
+ }
81
+ return Array.from(merged.values());
82
+ }
83
+ /** Convert an absolute cwd to the Claude-project folder name (slashes → dashes). */
84
+ function claudeProjectDirName(cwd) {
85
+ return cwd.replace(/\//g, '-');
86
+ }
87
+ /**
88
+ * Locate the active Claude session file for a process. If we know the session
89
+ * UUID (from terminal env or team parent), prefer the exact match. Otherwise
90
+ * fall back to the most-recent-mtime .jsonl in the project's folder.
91
+ */
92
+ function findClaudeSessionFile(cwd, sessionId) {
93
+ const projectDir = path.join(HOME, '.claude', 'projects', claudeProjectDirName(cwd));
94
+ if (sessionId) {
95
+ const specific = path.join(projectDir, `${sessionId}.jsonl`);
96
+ if (fs.existsSync(specific))
97
+ return specific;
98
+ }
99
+ let files;
100
+ try {
101
+ files = fs.readdirSync(projectDir).filter(f => f.endsWith('.jsonl'));
102
+ }
103
+ catch {
104
+ return undefined;
105
+ }
106
+ let best = null;
107
+ for (const f of files) {
108
+ const p = path.join(projectDir, f);
109
+ try {
110
+ const m = fs.statSync(p).mtimeMs;
111
+ if (!best || m > best.mtime)
112
+ best = { path: p, mtime: m };
113
+ }
114
+ catch { /* file vanished between readdir and stat */ }
115
+ }
116
+ return best?.path;
117
+ }
118
+ function classifyActivity(sessionFile) {
119
+ if (!sessionFile)
120
+ return 'running';
121
+ try {
122
+ const mtimeMs = fs.statSync(sessionFile).mtimeMs;
123
+ return Date.now() - mtimeMs < ACTIVE_MTIME_WINDOW_MS ? 'running' : 'idle';
124
+ }
125
+ catch {
126
+ return 'running';
127
+ }
128
+ }
129
+ /** Live teams teammates. Reuses AgentManager which already polls PIDs via `kill -0`. */
130
+ export async function listTeamsActive() {
131
+ const mgr = new AgentManager();
132
+ const running = await mgr.listRunning();
133
+ return running.map((a) => {
134
+ const sessionId = a.parentSessionId ?? a.remoteSessionId ?? undefined;
135
+ const sessionFile = a.agentType === 'claude' && a.cwd
136
+ ? findClaudeSessionFile(a.cwd, sessionId ?? undefined)
137
+ : undefined;
138
+ return {
139
+ context: 'teams',
140
+ kind: a.agentType,
141
+ pid: a.pid ?? undefined,
142
+ sessionId,
143
+ cwd: a.cwd ?? undefined,
144
+ label: a.name ?? undefined,
145
+ sessionFile,
146
+ startedAtMs: a.startedAt.getTime(),
147
+ status: classifyActivity(sessionFile),
148
+ teamName: a.taskName,
149
+ agentId: a.agentId,
150
+ };
151
+ });
152
+ }
153
+ /** Live editor-terminal agents across every IDE window. */
154
+ export async function listTerminalsActive() {
155
+ const entries = readLiveTerminals();
156
+ if (entries.length === 0)
157
+ return [];
158
+ // Walk the shell PIDs through the process table once so we can name the host
159
+ // (code / cursor / codium) per entry rather than a generic 'terminal'.
160
+ const procByPid = new Map();
161
+ for (const r of await readProcessTable())
162
+ procByPid.set(r.pid, r);
163
+ return entries.map((t) => {
164
+ const sessionFile = t.kind === 'claude' && t.cwd
165
+ ? findClaudeSessionFile(t.cwd, t.sessionId)
166
+ : undefined;
167
+ return {
168
+ context: 'terminal',
169
+ kind: t.kind,
170
+ host: detectHost(t.pid, procByPid),
171
+ pid: t.pid,
172
+ sessionId: t.sessionId,
173
+ cwd: t.cwd ?? undefined,
174
+ label: t.label ?? undefined,
175
+ sessionFile,
176
+ startedAtMs: t.startedAtMs,
177
+ status: classifyActivity(sessionFile),
178
+ };
179
+ });
180
+ }
181
+ /** Cloud tasks still in a non-terminal state. `tasks.db` may not exist; that's fine. */
182
+ export function listCloudActive() {
183
+ let tasks;
184
+ try {
185
+ tasks = listActiveTasks();
186
+ }
187
+ catch {
188
+ return [];
189
+ }
190
+ return tasks.map((t) => ({
191
+ context: 'cloud',
192
+ kind: t.agent || 'cloud',
193
+ label: t.prompt.length > 60 ? t.prompt.slice(0, 57) + '...' : t.prompt,
194
+ startedAtMs: Date.parse(t.createdAt) || undefined,
195
+ status: t.status === 'running'
196
+ ? 'running'
197
+ : t.status === 'input_required'
198
+ ? 'input_required'
199
+ : 'queued',
200
+ cloudProvider: t.provider,
201
+ cloudTaskId: t.id,
202
+ cloudStatus: t.status,
203
+ }));
204
+ }
205
+ /**
206
+ * Ordered ancestor-process matchers. First match wins (most specific to least),
207
+ * so an IDE renderer is preferred over the terminal-app that launched the IDE,
208
+ * and a terminal-app is preferred over the multiplexer inside it.
209
+ */
210
+ const HOST_MATCHERS = [
211
+ // IDE renderers (Electron helper processes)
212
+ { host: 'code', tokens: ['Code Helper', 'Code - Insiders Helper'] },
213
+ { host: 'cursor', tokens: ['Cursor Helper'] },
214
+ { host: 'codium', tokens: ['VSCodium Helper'] },
215
+ { host: 'windsurf', tokens: ['Windsurf Helper'] },
216
+ // Native terminal apps
217
+ { host: 'iterm', tokens: ['iTerm2', 'iTermServer', 'iTerm'] },
218
+ { host: 'terminal', tokens: ['Terminal.app', '/Applications/Utilities/Terminal.app'] },
219
+ { host: 'warp', tokens: ['Warp.app', 'stable_'] },
220
+ { host: 'alacritty', tokens: ['alacritty', 'Alacritty'] },
221
+ { host: 'kitty', tokens: ['kitty'] },
222
+ { host: 'hyper', tokens: ['Hyper.app', 'Hyper Helper'] },
223
+ { host: 'wezterm', tokens: ['wezterm', 'WezTerm'] },
224
+ { host: 'ghostty', tokens: ['ghostty', 'Ghostty'] },
225
+ // Multiplexers (fallback — only if no UI found above them)
226
+ { host: 'tmux', tokens: ['tmux'] },
227
+ { host: 'screen', tokens: ['screen'] },
228
+ ];
229
+ /**
230
+ * Snapshot the whole process table in one `ps` call. Includes ppid so we can
231
+ * walk ancestry chains to attribute child processes to their terminal hosts.
232
+ * `comm` may be an absolute path for shim-launched agents, so basename before
233
+ * matching against AGENT_CLI_NAMES.
234
+ */
235
+ async function readProcessTable() {
236
+ let out;
237
+ try {
238
+ ({ stdout: out } = await execFileAsync('ps', ['-A', '-o', 'pid=,ppid=,comm='], { encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 }));
239
+ }
240
+ catch {
241
+ return [];
242
+ }
243
+ const rows = [];
244
+ for (const line of out.split('\n')) {
245
+ const m = line.trim().match(/^(\d+)\s+(\d+)\s+(.+)$/);
246
+ if (!m)
247
+ continue;
248
+ const pid = parseInt(m[1], 10);
249
+ const ppid = parseInt(m[2], 10);
250
+ if (!Number.isFinite(pid) || !Number.isFinite(ppid))
251
+ continue;
252
+ const commRaw = m[3].trim();
253
+ const kind = AGENT_CLI_NAMES[path.basename(commRaw)];
254
+ rows.push({ pid, ppid, comm: commRaw, kind });
255
+ }
256
+ return rows;
257
+ }
258
+ /**
259
+ * True when any ancestor in pid's parent chain is a known attributed PID.
260
+ * VS Code / Cursor terminals store the *shell* PID in live-terminals.json,
261
+ * while `ps` reports the *child* claude PID, so a direct set lookup misses.
262
+ */
263
+ function hasAttributedAncestor(pid, ppidMap, attributed) {
264
+ let cur = ppidMap.get(pid);
265
+ const seen = new Set();
266
+ while (cur && cur > 1 && !seen.has(cur)) {
267
+ if (attributed.has(cur))
268
+ return true;
269
+ seen.add(cur);
270
+ cur = ppidMap.get(cur);
271
+ }
272
+ return false;
273
+ }
274
+ /**
275
+ * Resolve a process's current working directory via `lsof`. The `-a` flag
276
+ * ANDs the filters; without it macOS treats `-p` and `-d` as a union and
277
+ * returns the cwd of every process on the system.
278
+ */
279
+ async function getCwdForPid(pid) {
280
+ let out;
281
+ try {
282
+ const res = await execFileAsync('lsof', ['-a', '-p', String(pid), '-d', 'cwd', '-Fn'], {
283
+ encoding: 'utf8',
284
+ });
285
+ out = res.stdout;
286
+ }
287
+ catch {
288
+ return undefined;
289
+ }
290
+ for (const line of out.split('\n')) {
291
+ if (line.startsWith('n'))
292
+ return line.slice(1);
293
+ }
294
+ return undefined;
295
+ }
296
+ /**
297
+ * Walk a pid's ancestor chain and return the most specific host app found.
298
+ * Checks each HOST_MATCHERS entry against every ancestor, returns the first
299
+ * host whose tokens match — so IDEs beat terminal apps, terminals beat
300
+ * multiplexers. Returns undefined if nothing is recognised (true headless).
301
+ */
302
+ function detectHost(pid, procByPid) {
303
+ const chain = [];
304
+ let cur = procByPid.get(pid)?.ppid;
305
+ const seen = new Set();
306
+ while (cur && cur > 1 && !seen.has(cur)) {
307
+ const row = procByPid.get(cur);
308
+ if (!row)
309
+ break;
310
+ chain.push(row.comm);
311
+ seen.add(cur);
312
+ cur = row.ppid;
313
+ }
314
+ for (const { host, tokens } of HOST_MATCHERS) {
315
+ if (chain.some(c => tokens.some(t => c.includes(t))))
316
+ return host;
317
+ }
318
+ return undefined;
319
+ }
320
+ /** IDE / terminal / multiplexer hosts all count as UI-hosted. Absence = truly headless. */
321
+ const UI_HOSTS = new Set([
322
+ 'code', 'cursor', 'codium', 'windsurf',
323
+ 'iterm', 'terminal', 'warp', 'alacritty', 'kitty', 'hyper', 'wezterm', 'ghostty',
324
+ 'tmux', 'screen',
325
+ ]);
326
+ /**
327
+ * Agent processes not attributed to a team or the runtime registry.
328
+ * Classified by walking the ppid chain: any recognised UI ancestor (IDE
329
+ * helper, terminal-app, or multiplexer) means `terminal`; nothing of the
330
+ * sort means `headless` (daemon, launchd-spawned, orphan).
331
+ */
332
+ export async function listUnattributedActive(attributed) {
333
+ const table = await readProcessTable();
334
+ const procByPid = new Map();
335
+ const ppidMap = new Map();
336
+ for (const r of table) {
337
+ procByPid.set(r.pid, r);
338
+ ppidMap.set(r.pid, r.ppid);
339
+ }
340
+ // Candidate PIDs first — we only shell out to lsof for these, not the whole table.
341
+ const candidates = [];
342
+ for (const { pid, kind } of table) {
343
+ if (!kind)
344
+ continue;
345
+ if (attributed.has(pid))
346
+ continue;
347
+ if (hasAttributedAncestor(pid, ppidMap, attributed))
348
+ continue;
349
+ candidates.push({ pid, kind });
350
+ }
351
+ // Run lsof probes in parallel so N spawns take one round-trip, not N.
352
+ const cwds = await Promise.all(candidates.map(c => getCwdForPid(c.pid)));
353
+ const out = [];
354
+ for (let i = 0; i < candidates.length; i++) {
355
+ const { pid, kind } = candidates[i];
356
+ const cwd = cwds[i];
357
+ const sessionFile = kind === 'claude' && cwd ? findClaudeSessionFile(cwd) : undefined;
358
+ const host = detectHost(pid, procByPid);
359
+ const context = host && UI_HOSTS.has(host) ? 'terminal' : 'headless';
360
+ out.push({
361
+ context,
362
+ kind,
363
+ host,
364
+ pid,
365
+ cwd,
366
+ sessionFile,
367
+ status: classifyActivity(sessionFile),
368
+ });
369
+ }
370
+ return out;
371
+ }
372
+ /**
373
+ * Union of all four sources. Teams and terminals spawn actual CLI processes
374
+ * that also show up in `ps`, so headless attribution runs last with the
375
+ * already-attributed PIDs removed.
376
+ */
377
+ export async function getActiveSessions(opts = {}) {
378
+ const [teams, terminals, cloud] = await Promise.all([
379
+ listTeamsActive().catch(() => []),
380
+ listTerminalsActive().catch(() => []),
381
+ Promise.resolve(listCloudActive()),
382
+ ]);
383
+ const knownPids = new Set();
384
+ for (const s of teams)
385
+ if (s.pid)
386
+ knownPids.add(s.pid);
387
+ for (const s of terminals)
388
+ if (s.pid)
389
+ knownPids.add(s.pid);
390
+ const unattributed = opts.skipHeadless ? [] : await listUnattributedActive(knownPids);
391
+ return [...teams, ...terminals, ...cloud, ...unattributed];
392
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Session artifact discovery and resolution.
3
+ *
4
+ * Scans parsed session events for file-write tool calls (Write, Edit, etc.)
5
+ * and returns metadata about each artifact: path, authoring tool, existence
6
+ * on disk, and file size. Used by the artifacts subcommand and session detail views.
7
+ */
8
+ import type { SessionMeta, SessionArtifact } from './types.js';
9
+ /** Parse a session and return metadata for every file written or edited during it. */
10
+ export declare function discoverArtifacts(meta: SessionMeta): SessionArtifact[];
11
+ /** Refuse to load artifact files larger than this. Returns '' silently above the cap. */
12
+ export declare const ARTIFACT_MAX_BYTES = 50000000;
13
+ /** Read the current contents of an artifact file from disk. Rejects symlinks. */
14
+ export declare function readArtifact(artifact: SessionArtifact): string;
15
+ /** Resolve a user-provided name to an artifact by exact path, basename, or path suffix. */
16
+ export declare function resolveArtifact(artifacts: SessionArtifact[], name: string): SessionArtifact | null;
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Session artifact discovery and resolution.
3
+ *
4
+ * Scans parsed session events for file-write tool calls (Write, Edit, etc.)
5
+ * and returns metadata about each artifact: path, authoring tool, existence
6
+ * on disk, and file size. Used by the artifacts subcommand and session detail views.
7
+ */
8
+ import * as fs from 'fs';
9
+ import * as path from 'path';
10
+ import { parseSession } from './parse.js';
11
+ /** Tool names that produce file artifacts (writes, edits, patches). */
12
+ const WRITE_TOOLS = new Set([
13
+ 'Write', 'Edit', 'write_file', 'edit_file', 'create_file', 'replace', 'patch',
14
+ ]);
15
+ /** Parse a session and return metadata for every file written or edited during it. */
16
+ export function discoverArtifacts(meta) {
17
+ let events;
18
+ try {
19
+ events = parseSession(meta.filePath, meta.agent);
20
+ }
21
+ catch {
22
+ return [];
23
+ }
24
+ // Map path -> last write event (later occurrence wins for dedup)
25
+ const latestByPath = new Map();
26
+ for (const event of events) {
27
+ if (event.type !== 'tool_use')
28
+ continue;
29
+ const tool = event.tool || '';
30
+ if (!WRITE_TOOLS.has(tool))
31
+ continue;
32
+ const p = event.path
33
+ || event.args?.file_path
34
+ || event.args?.path
35
+ || event.args?.filePath
36
+ || '';
37
+ if (!p)
38
+ continue;
39
+ latestByPath.set(p, { tool, timestamp: event.timestamp });
40
+ }
41
+ const artifacts = [];
42
+ for (const [p, { tool, timestamp }] of latestByPath) {
43
+ let exists = false;
44
+ let sizeBytes;
45
+ try {
46
+ const stat = fs.lstatSync(p);
47
+ if (stat.isFile()) {
48
+ exists = true;
49
+ sizeBytes = stat.size;
50
+ }
51
+ }
52
+ catch {
53
+ // file gone, inaccessible, or symlink/special file
54
+ }
55
+ artifacts.push({
56
+ path: p,
57
+ tool,
58
+ timestamp,
59
+ exists,
60
+ sizeBytes: exists ? sizeBytes : undefined,
61
+ sessionId: meta.id,
62
+ });
63
+ }
64
+ return artifacts;
65
+ }
66
+ /** Refuse to load artifact files larger than this. Returns '' silently above the cap. */
67
+ export const ARTIFACT_MAX_BYTES = 50_000_000;
68
+ /** Read the current contents of an artifact file from disk. Rejects symlinks. */
69
+ export function readArtifact(artifact) {
70
+ const stat = fs.lstatSync(artifact.path);
71
+ if (!stat.isFile()) {
72
+ throw new Error(`Refusing to read non-regular file: ${artifact.path}`);
73
+ }
74
+ if (stat.size > ARTIFACT_MAX_BYTES)
75
+ return '';
76
+ return fs.readFileSync(artifact.path, 'utf-8');
77
+ }
78
+ /** Resolve a user-provided name to an artifact by exact path, basename, or path suffix. */
79
+ export function resolveArtifact(artifacts, name) {
80
+ // Exact path match
81
+ const exact = artifacts.find(a => a.path === name);
82
+ if (exact)
83
+ return exact;
84
+ // Basename match
85
+ const byBase = artifacts.filter(a => path.basename(a.path) === name);
86
+ if (byBase.length === 1)
87
+ return byBase[0];
88
+ if (byBase.length > 1)
89
+ return byBase[0];
90
+ // Path suffix match (e.g. "src/foo.ts")
91
+ const bySuffix = artifacts.filter(a => a.path.endsWith('/' + name) || a.path === name);
92
+ if (bySuffix.length >= 1)
93
+ return bySuffix[0];
94
+ return null;
95
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Rush Cloud session source.
3
+ *
4
+ * Fetches cloud-captured sessions from halo/proxy (api.prix.dev) and caches
5
+ * them locally so the existing filesystem-based parse pipeline works unchanged.
6
+ *
7
+ * Endpoints consumed (implemented in halo/proxy/src/cloud-runs.ts):
8
+ * GET /api/v1/cloud-runs → list executions
9
+ * GET /api/v1/cloud-runs/:id → get one (used for meta)
10
+ * GET /api/v1/cloud-runs/:id/session.jsonl → raw captured jsonl
11
+ */
12
+ import type { SessionMeta } from './types.js';
13
+ /**
14
+ * List cloud executions the user has captured sessions for. Includes
15
+ * completed + needs_review + failed; an empty session_path means capture
16
+ * never ran, so those are silently dropped.
17
+ */
18
+ export declare function discoverCloudSessions(options?: {
19
+ limit?: number;
20
+ }): Promise<SessionMeta[]>;
21
+ /**
22
+ * Fetch the jsonl for one cloud execution and stash it in the local cache.
23
+ * Returns the local file path. Re-fetches on every call (cheap — executions
24
+ * are immutable once complete). Callers may pass an already-known filePath.
25
+ */
26
+ export declare function ensureCloudSessionCached(executionId: string, destPath?: string): Promise<string>;
27
+ /** True if filePath points into the cloud session cache dir. */
28
+ export declare function isCloudSessionPath(filePath: string): boolean;
29
+ /** Extract execution_id from a cloud cache path. */
30
+ export declare function executionIdFromCloudPath(filePath: string): string | null;
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Rush Cloud session source.
3
+ *
4
+ * Fetches cloud-captured sessions from halo/proxy (api.prix.dev) and caches
5
+ * them locally so the existing filesystem-based parse pipeline works unchanged.
6
+ *
7
+ * Endpoints consumed (implemented in halo/proxy/src/cloud-runs.ts):
8
+ * GET /api/v1/cloud-runs → list executions
9
+ * GET /api/v1/cloud-runs/:id → get one (used for meta)
10
+ * GET /api/v1/cloud-runs/:id/session.jsonl → raw captured jsonl
11
+ */
12
+ import * as fs from 'fs';
13
+ import * as path from 'path';
14
+ import * as os from 'os';
15
+ import * as yaml from 'yaml';
16
+ import { getAgentsDir } from '../state.js';
17
+ const PROXY_BASE = process.env.RUSH_PROXY_BASE ?? 'https://api.prix.dev';
18
+ const USER_YAML = path.join(os.homedir(), '.rush', 'user.yaml');
19
+ const CLOUD_CACHE_DIR = path.join(getAgentsDir(), 'cache', 'cloud-runs');
20
+ function readToken() {
21
+ if (!fs.existsSync(USER_YAML)) {
22
+ throw new Error('Not logged in to Rush. Run `rush login` first.');
23
+ }
24
+ const raw = fs.readFileSync(USER_YAML, 'utf-8');
25
+ const data = yaml.parse(raw);
26
+ const token = data?.session?.access_token;
27
+ if (!token) {
28
+ throw new Error('No session token in ~/.rush/user.yaml. Run `rush login` first.');
29
+ }
30
+ return token;
31
+ }
32
+ async function api(method, endpoint, token) {
33
+ return fetch(`${PROXY_BASE}${endpoint}`, {
34
+ method,
35
+ headers: { Authorization: `Bearer ${token}` },
36
+ });
37
+ }
38
+ /** Coerce the `agent` field on a cloud-run row to a SessionAgentId. */
39
+ function agentToFormat(agent) {
40
+ if (agent === 'claude')
41
+ return 'claude';
42
+ if (agent === 'codex')
43
+ return 'codex';
44
+ if (agent === 'rush')
45
+ return 'rush';
46
+ return null;
47
+ }
48
+ /**
49
+ * List cloud executions the user has captured sessions for. Includes
50
+ * completed + needs_review + failed; an empty session_path means capture
51
+ * never ran, so those are silently dropped.
52
+ */
53
+ export async function discoverCloudSessions(options) {
54
+ const token = readToken();
55
+ const limit = options?.limit ?? 50;
56
+ const res = await api('GET', `/api/v1/cloud-runs?limit=${limit}`, token);
57
+ if (!res.ok) {
58
+ throw new Error(`cloud-runs list failed (${res.status})`);
59
+ }
60
+ const data = (await res.json());
61
+ const rows = data.executions ?? [];
62
+ const out = [];
63
+ for (const row of rows) {
64
+ const agent = agentToFormat(row.agent);
65
+ if (!agent)
66
+ continue;
67
+ const id = row.execution_id;
68
+ const timestamp = row.updated_at || row.created_at || new Date().toISOString();
69
+ const project = row.repo_owner && row.repo_name ? `${row.repo_owner}/${row.repo_name}` : undefined;
70
+ // filePath doubles as the sink path for the cached jsonl. parseSession
71
+ // dispatches on detectAgent which recognizes the `session.<format>.jsonl`
72
+ // suffix — so the local cache file name must preserve it.
73
+ const filePath = path.join(CLOUD_CACHE_DIR, id, `session.${agent}.jsonl`);
74
+ out.push({
75
+ id,
76
+ shortId: id.slice(0, 8),
77
+ agent,
78
+ timestamp,
79
+ project,
80
+ filePath,
81
+ topic: row.prompt?.split('\n')[0]?.slice(0, 120),
82
+ label: `[cloud/${row.status}]${row.branch ? ` ${row.branch}` : ''}`,
83
+ });
84
+ }
85
+ out.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
86
+ return out;
87
+ }
88
+ /**
89
+ * Fetch the jsonl for one cloud execution and stash it in the local cache.
90
+ * Returns the local file path. Re-fetches on every call (cheap — executions
91
+ * are immutable once complete). Callers may pass an already-known filePath.
92
+ */
93
+ export async function ensureCloudSessionCached(executionId, destPath) {
94
+ const token = readToken();
95
+ const res = await api('GET', `/api/v1/cloud-runs/${encodeURIComponent(executionId)}/session.jsonl`, token);
96
+ if (!res.ok) {
97
+ const body = await res.text().catch(() => '');
98
+ throw new Error(`session.jsonl fetch ${res.status}: ${body.slice(0, 200)}`);
99
+ }
100
+ const format = (res.headers.get('X-Session-Format') || '').toLowerCase();
101
+ if (!['claude', 'codex', 'rush'].includes(format)) {
102
+ throw new Error(`Unknown X-Session-Format on cloud response: "${format}"`);
103
+ }
104
+ const finalPath = destPath ?? path.join(CLOUD_CACHE_DIR, executionId, `session.${format}.jsonl`);
105
+ fs.mkdirSync(path.dirname(finalPath), { recursive: true });
106
+ const body = Buffer.from(await res.arrayBuffer());
107
+ fs.writeFileSync(finalPath, body);
108
+ return finalPath;
109
+ }
110
+ /** True if filePath points into the cloud session cache dir. */
111
+ export function isCloudSessionPath(filePath) {
112
+ return filePath.startsWith(CLOUD_CACHE_DIR);
113
+ }
114
+ /** Extract execution_id from a cloud cache path. */
115
+ export function executionIdFromCloudPath(filePath) {
116
+ if (!isCloudSessionPath(filePath))
117
+ return null;
118
+ const rel = path.relative(CLOUD_CACHE_DIR, filePath);
119
+ const parts = rel.split(path.sep);
120
+ return parts[0] || null;
121
+ }