@phnx-labs/agents-cli 1.22.35 → 1.22.38

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 (500) hide show
  1. package/CHANGELOG.md +708 -2
  2. package/README.md +83 -43
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.d.ts +15 -0
  5. package/dist/bootstrap.js +1212 -0
  6. package/dist/commands/accounts.d.ts +4 -11
  7. package/dist/commands/accounts.js +159 -27
  8. package/dist/commands/artifacts-setup.d.ts +53 -0
  9. package/dist/commands/artifacts-setup.js +161 -0
  10. package/dist/commands/artifacts.d.ts +18 -0
  11. package/dist/commands/artifacts.js +58 -0
  12. package/dist/commands/attach.js +17 -4
  13. package/dist/commands/audit.d.ts +8 -8
  14. package/dist/commands/audit.js +57 -47
  15. package/dist/commands/browser.js +17 -11
  16. package/dist/commands/cloud.js +1 -1
  17. package/dist/commands/commands.js +0 -11
  18. package/dist/commands/computer-actions.js +33 -0
  19. package/dist/commands/computer-sessions-picker.d.ts +21 -0
  20. package/dist/commands/computer-sessions-picker.js +141 -0
  21. package/dist/commands/computer.d.ts +16 -0
  22. package/dist/commands/computer.js +37 -0
  23. package/dist/commands/config.d.ts +17 -0
  24. package/dist/commands/config.js +401 -0
  25. package/dist/commands/cp.d.ts +84 -0
  26. package/dist/commands/cp.js +231 -0
  27. package/dist/commands/daemon.js +243 -14
  28. package/dist/commands/detach-core.d.ts +1 -1
  29. package/dist/commands/detach-core.js +12 -2
  30. package/dist/commands/detach.js +1 -1
  31. package/dist/commands/doctor.js +64 -5
  32. package/dist/commands/events.d.ts +24 -12
  33. package/dist/commands/events.js +144 -28
  34. package/dist/commands/exec.js +86 -42
  35. package/dist/commands/feed.d.ts +1 -1
  36. package/dist/commands/feed.js +16 -8
  37. package/dist/commands/focus.d.ts +33 -1
  38. package/dist/commands/focus.js +177 -17
  39. package/dist/commands/funnel.d.ts +1 -1
  40. package/dist/commands/go.js +9 -8
  41. package/dist/commands/harness-wizard.d.ts +1 -0
  42. package/dist/commands/harness-wizard.js +18 -20
  43. package/dist/commands/harness.d.ts +2 -0
  44. package/dist/commands/harness.js +59 -26
  45. package/dist/commands/hooks.js +0 -11
  46. package/dist/commands/inspect.d.ts +94 -1
  47. package/dist/commands/inspect.js +866 -40
  48. package/dist/commands/lease.d.ts +4 -4
  49. package/dist/commands/lease.js +6 -6
  50. package/dist/commands/login.js +0 -13
  51. package/dist/commands/logs.d.ts +2 -2
  52. package/dist/commands/logs.js +2 -2
  53. package/dist/commands/mcp.js +7 -2
  54. package/dist/commands/memory.js +7 -2
  55. package/dist/commands/message.d.ts +1 -1
  56. package/dist/commands/message.js +37 -6
  57. package/dist/commands/models.js +71 -0
  58. package/dist/commands/monitors.d.ts +0 -1
  59. package/dist/commands/monitors.js +199 -16
  60. package/dist/commands/open.d.ts +18 -0
  61. package/dist/commands/open.js +57 -0
  62. package/dist/commands/packages.js +2 -107
  63. package/dist/commands/plugins.js +6 -3
  64. package/dist/commands/profiles.d.ts +1 -0
  65. package/dist/commands/profiles.js +16 -160
  66. package/dist/commands/projects.d.ts +28 -0
  67. package/dist/commands/projects.js +125 -5
  68. package/dist/commands/reconnect.js +9 -3
  69. package/dist/commands/repo.js +42 -1
  70. package/dist/commands/resource-view.d.ts +17 -0
  71. package/dist/commands/resource-view.js +36 -14
  72. package/dist/commands/resume.js +9 -2
  73. package/dist/commands/routines.d.ts +0 -2
  74. package/dist/commands/routines.js +473 -289
  75. package/dist/commands/secrets.js +52 -9
  76. package/dist/commands/sessions-export.d.ts +47 -0
  77. package/dist/commands/sessions-export.js +116 -6
  78. package/dist/commands/sessions-import.d.ts +17 -0
  79. package/dist/commands/sessions-import.js +114 -6
  80. package/dist/commands/sessions-migrate.d.ts +27 -0
  81. package/dist/commands/sessions-migrate.js +50 -9
  82. package/dist/commands/sessions-picker.js +23 -4
  83. package/dist/commands/sessions-resume.d.ts +5 -3
  84. package/dist/commands/sessions-resume.js +30 -8
  85. package/dist/commands/sessions-watch.d.ts +2 -0
  86. package/dist/commands/sessions-watch.js +53 -0
  87. package/dist/commands/sessions.d.ts +66 -3
  88. package/dist/commands/sessions.js +298 -47
  89. package/dist/commands/setup-browser.js +2 -2
  90. package/dist/commands/setup-mine.js +0 -1
  91. package/dist/commands/setup-preferences.js +1 -1
  92. package/dist/commands/setup.d.ts +5 -0
  93. package/dist/commands/setup.js +31 -5
  94. package/dist/commands/share.d.ts +87 -7
  95. package/dist/commands/share.js +320 -58
  96. package/dist/commands/skills.js +0 -11
  97. package/dist/commands/snapshot.js +1 -1
  98. package/dist/commands/ssh.d.ts +18 -0
  99. package/dist/commands/ssh.js +549 -210
  100. package/dist/commands/sync.d.ts +5 -0
  101. package/dist/commands/sync.js +212 -32
  102. package/dist/commands/teams.d.ts +13 -0
  103. package/dist/commands/teams.js +187 -30
  104. package/dist/commands/tickets.d.ts +2 -0
  105. package/dist/commands/tickets.js +43 -0
  106. package/dist/commands/update.js +2 -4
  107. package/dist/commands/usage.js +5 -3
  108. package/dist/commands/versions.js +11 -5
  109. package/dist/commands/view.js +15 -7
  110. package/dist/commands/webhook.d.ts +2 -2
  111. package/dist/commands/webhook.js +7 -7
  112. package/dist/index.d.ts +18 -2
  113. package/dist/index.js +53 -1264
  114. package/dist/lib/account-catalog.d.ts +18 -0
  115. package/dist/lib/account-catalog.js +38 -0
  116. package/dist/lib/account-provider-registry.d.ts +18 -0
  117. package/dist/lib/account-provider-registry.js +59 -0
  118. package/dist/lib/account-registry.d.ts +40 -0
  119. package/dist/lib/account-registry.js +239 -0
  120. package/dist/lib/account-schema.d.ts +44 -0
  121. package/dist/lib/account-schema.js +91 -0
  122. package/dist/lib/account-state-service.d.ts +21 -0
  123. package/dist/lib/account-state-service.js +60 -0
  124. package/dist/lib/activity.d.ts +1 -1
  125. package/dist/lib/activity.js +8 -1
  126. package/dist/lib/add-dir.d.ts +80 -0
  127. package/dist/lib/add-dir.js +241 -0
  128. package/dist/lib/agent-cli-commands.d.ts +11 -0
  129. package/dist/lib/agent-cli-commands.js +30 -0
  130. package/dist/lib/agents.js +44 -36
  131. package/dist/lib/answer-router.js +1 -1
  132. package/dist/lib/audit/log.d.ts +10 -27
  133. package/dist/lib/audit/log.js +20 -33
  134. package/dist/lib/auth-health.d.ts +9 -2
  135. package/dist/lib/auth-health.js +42 -9
  136. package/dist/lib/auto-pull-worker.js +7 -3
  137. package/dist/lib/auto-pull.d.ts +44 -3
  138. package/dist/lib/auto-pull.js +88 -5
  139. package/dist/lib/binary-shadow.d.ts +28 -0
  140. package/dist/lib/binary-shadow.js +121 -0
  141. package/dist/lib/brand.js +9 -3
  142. package/dist/lib/browser/hygiene.d.ts +90 -0
  143. package/dist/lib/browser/hygiene.js +146 -0
  144. package/dist/lib/browser/ipc.d.ts +30 -0
  145. package/dist/lib/browser/ipc.js +93 -4
  146. package/dist/lib/browser/profiles.d.ts +3 -2
  147. package/dist/lib/browser/profiles.js +65 -22
  148. package/dist/lib/browser/service.d.ts +79 -1
  149. package/dist/lib/browser/service.js +231 -14
  150. package/dist/lib/browser/sessions-list.d.ts +22 -2
  151. package/dist/lib/browser/sessions-list.js +54 -6
  152. package/dist/lib/browser/stream.d.ts +2 -0
  153. package/dist/lib/browser/stream.js +1 -0
  154. package/dist/lib/browser/types.d.ts +63 -1
  155. package/dist/lib/byok-usage.d.ts +9 -2
  156. package/dist/lib/byok-usage.js +133 -31
  157. package/dist/lib/cli-entry.d.ts +11 -0
  158. package/dist/lib/cli-entry.js +46 -0
  159. package/dist/lib/cloud/host.d.ts +1 -1
  160. package/dist/lib/cloud/host.js +2 -2
  161. package/dist/lib/cloud/registry.js +1 -1
  162. package/dist/lib/cloud/types.d.ts +1 -1
  163. package/dist/lib/commands.d.ts +2 -0
  164. package/dist/lib/commands.js +2 -0
  165. package/dist/lib/computer/sessions-list.d.ts +150 -0
  166. package/dist/lib/computer/sessions-list.js +363 -0
  167. package/dist/lib/config-keys.d.ts +86 -0
  168. package/dist/lib/config-keys.js +193 -0
  169. package/dist/lib/config-machine-keys.d.ts +12 -0
  170. package/dist/lib/config-machine-keys.js +17 -0
  171. package/dist/lib/config-transfer.js +3 -4
  172. package/dist/lib/crabbox/cli.d.ts +2 -2
  173. package/dist/lib/crabbox/cli.js +3 -3
  174. package/dist/lib/daemon-health.d.ts +22 -0
  175. package/dist/lib/daemon-health.js +33 -3
  176. package/dist/lib/daemon-services.d.ts +50 -0
  177. package/dist/lib/daemon-services.js +147 -0
  178. package/dist/lib/daemon-ticks.d.ts +35 -66
  179. package/dist/lib/daemon-ticks.js +77 -159
  180. package/dist/lib/daemon.d.ts +72 -4
  181. package/dist/lib/daemon.js +792 -202
  182. package/dist/lib/deeplink/register.d.ts +49 -0
  183. package/dist/lib/deeplink/register.js +253 -0
  184. package/dist/lib/deeplink/url.d.ts +34 -0
  185. package/dist/lib/deeplink/url.js +78 -0
  186. package/dist/lib/device-config.d.ts +124 -29
  187. package/dist/lib/device-config.js +346 -141
  188. package/dist/lib/devices/config-migration.d.ts +42 -0
  189. package/dist/lib/devices/config-migration.js +203 -0
  190. package/dist/lib/devices/connect.js +14 -7
  191. package/dist/lib/devices/doctor-findings.d.ts +4 -1
  192. package/dist/lib/devices/doctor-findings.js +20 -1
  193. package/dist/lib/devices/harness-inventory.d.ts +11 -2
  194. package/dist/lib/devices/harness-inventory.js +0 -0
  195. package/dist/lib/devices/health.d.ts +1 -1
  196. package/dist/lib/devices/health.js +1 -1
  197. package/dist/lib/devices/pending.d.ts +22 -1
  198. package/dist/lib/devices/pending.js +67 -2
  199. package/dist/lib/devices/registry.d.ts +0 -25
  200. package/dist/lib/devices/registry.js +2 -83
  201. package/dist/lib/devices/resolve-profile.d.ts +20 -0
  202. package/dist/lib/devices/resolve-profile.js +44 -0
  203. package/dist/lib/devices/rollout-verify.d.ts +101 -0
  204. package/dist/lib/devices/rollout-verify.js +193 -0
  205. package/dist/lib/devices/ssh-config.js +10 -6
  206. package/dist/lib/event-families.d.ts +28 -0
  207. package/dist/lib/event-families.js +159 -0
  208. package/dist/lib/event-stream.d.ts +9 -1
  209. package/dist/lib/event-stream.js +26 -9
  210. package/dist/lib/events.d.ts +9 -1
  211. package/dist/lib/events.js +21 -6
  212. package/dist/lib/exec.d.ts +30 -0
  213. package/dist/lib/exec.js +219 -121
  214. package/dist/lib/feed-broadcast.d.ts +25 -0
  215. package/dist/lib/feed-broadcast.js +33 -0
  216. package/dist/lib/feed.d.ts +1 -1
  217. package/dist/lib/feed.js +12 -2
  218. package/dist/lib/fleet/capture.js +15 -0
  219. package/dist/lib/fleet/manifest.js +9 -0
  220. package/dist/lib/fleet/types.d.ts +9 -0
  221. package/dist/lib/fleet-status.js +10 -8
  222. package/dist/lib/git.d.ts +21 -7
  223. package/dist/lib/git.js +122 -18
  224. package/dist/lib/hosts/dispatch.d.ts +8 -3
  225. package/dist/lib/hosts/dispatch.js +29 -3
  226. package/dist/lib/hosts/logs.d.ts +2 -2
  227. package/dist/lib/hosts/logs.js +2 -2
  228. package/dist/lib/hosts/option.js +1 -1
  229. package/dist/lib/hosts/passthrough.d.ts +2 -3
  230. package/dist/lib/hosts/passthrough.js +10 -24
  231. package/dist/lib/hosts/progress.js +2 -2
  232. package/dist/lib/hosts/providers/devices.d.ts +3 -3
  233. package/dist/lib/hosts/providers/devices.js +18 -12
  234. package/dist/lib/hosts/ready.d.ts +5 -1
  235. package/dist/lib/hosts/ready.js +9 -3
  236. package/dist/lib/hosts/reconcile.d.ts +2 -2
  237. package/dist/lib/hosts/reconcile.js +2 -2
  238. package/dist/lib/hosts/registry.js +14 -9
  239. package/dist/lib/hosts/remote-cmd.js +1 -1
  240. package/dist/lib/hosts/remote-os.d.ts +9 -6
  241. package/dist/lib/hosts/remote-os.js +13 -6
  242. package/dist/lib/hosts/routing-flag.d.ts +23 -0
  243. package/dist/lib/hosts/routing-flag.js +41 -0
  244. package/dist/lib/hosts/run-target.js +1 -1
  245. package/dist/lib/hosts/session-index.js +1 -1
  246. package/dist/lib/hosts/tasks.d.ts +6 -6
  247. package/dist/lib/hosts/tasks.js +4 -4
  248. package/dist/lib/hosts/types.js +1 -2
  249. package/dist/lib/installations/resolve.js +2 -8
  250. package/dist/lib/isolation-boundary-report.js +0 -1
  251. package/dist/lib/linear-cache.d.ts +7 -0
  252. package/dist/lib/linear-cache.js +31 -4
  253. package/dist/lib/linear-project-counts.d.ts +1 -1
  254. package/dist/lib/linear-project-counts.js +2 -3
  255. package/dist/lib/linear-projects.js +1 -1
  256. package/dist/lib/loop.d.ts +2 -2
  257. package/dist/lib/loop.js +1 -1
  258. package/dist/lib/mailbox-target.d.ts +1 -1
  259. package/dist/lib/mailbox-target.js +1 -1
  260. package/dist/lib/manifest.js +7 -4
  261. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  262. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  263. package/dist/lib/menubar/snapshot.d.ts +3 -2
  264. package/dist/lib/menubar/snapshot.js +6 -2
  265. package/dist/lib/migrate-fold.d.ts +33 -0
  266. package/dist/lib/migrate-fold.js +130 -0
  267. package/dist/lib/migrate.d.ts +34 -34
  268. package/dist/lib/migrate.js +106 -128
  269. package/dist/lib/model-tier-overrides.d.ts +1 -1
  270. package/dist/lib/model-tier-overrides.js +15 -2
  271. package/dist/lib/monitors/config.d.ts +17 -3
  272. package/dist/lib/monitors/config.js +52 -18
  273. package/dist/lib/monitors/engine.d.ts +32 -1
  274. package/dist/lib/monitors/engine.js +94 -11
  275. package/dist/lib/monitors/fingerprint.d.ts +46 -0
  276. package/dist/lib/monitors/fingerprint.js +100 -0
  277. package/dist/lib/monitors/remote.d.ts +47 -0
  278. package/dist/lib/monitors/remote.js +81 -0
  279. package/dist/lib/monitors/state.d.ts +39 -0
  280. package/dist/lib/monitors/state.js +56 -0
  281. package/dist/lib/onepassword.d.ts +17 -0
  282. package/dist/lib/onepassword.js +52 -22
  283. package/dist/lib/open-url.js +1 -1
  284. package/dist/lib/picker.d.ts +14 -2
  285. package/dist/lib/picker.js +35 -13
  286. package/dist/lib/placement.d.ts +1 -1
  287. package/dist/lib/placement.js +1 -1
  288. package/dist/lib/pr-land-detach.d.ts +32 -0
  289. package/dist/lib/pr-land-detach.js +79 -0
  290. package/dist/lib/profiles-presets.js +13 -0
  291. package/dist/lib/profiles.d.ts +2 -0
  292. package/dist/lib/profiles.js +44 -1
  293. package/dist/lib/project-focus.d.ts +1 -1
  294. package/dist/lib/project-focus.js +1 -1
  295. package/dist/lib/project-probe.d.ts +4 -1
  296. package/dist/lib/project-probe.js +5 -4
  297. package/dist/lib/project-resources.js +2 -18
  298. package/dist/lib/project-root.d.ts +16 -0
  299. package/dist/lib/project-root.js +20 -2
  300. package/dist/lib/projects.d.ts +20 -1
  301. package/dist/lib/projects.js +78 -1
  302. package/dist/lib/refresh-coordinator.d.ts +24 -0
  303. package/dist/lib/refresh-coordinator.js +52 -0
  304. package/dist/lib/registry.d.ts +2 -2
  305. package/dist/lib/registry.js +1 -1
  306. package/dist/lib/resource-aliases.d.ts +13 -0
  307. package/dist/lib/resource-aliases.js +26 -0
  308. package/dist/lib/resources/types.d.ts +1 -1
  309. package/dist/lib/resources.d.ts +16 -0
  310. package/dist/lib/resources.js +66 -10
  311. package/dist/lib/rotate.d.ts +3 -4
  312. package/dist/lib/rotate.js +4 -5
  313. package/dist/lib/routine-activation.d.ts +22 -2
  314. package/dist/lib/routine-activation.js +63 -16
  315. package/dist/lib/routine-context.d.ts +9 -2
  316. package/dist/lib/routine-context.js +21 -6
  317. package/dist/lib/routines-project.d.ts +58 -48
  318. package/dist/lib/routines-project.js +190 -159
  319. package/dist/lib/routines.d.ts +44 -7
  320. package/dist/lib/routines.js +92 -34
  321. package/dist/lib/run-defaults.d.ts +5 -0
  322. package/dist/lib/run-defaults.js +11 -1
  323. package/dist/lib/runner.d.ts +10 -8
  324. package/dist/lib/runner.js +122 -39
  325. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  326. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  327. package/dist/lib/secrets/agent.d.ts +10 -3
  328. package/dist/lib/secrets/agent.js +43 -8
  329. package/dist/lib/secrets/bundles.d.ts +1 -0
  330. package/dist/lib/secrets/bundles.js +92 -80
  331. package/dist/lib/secrets/index.js +32 -9
  332. package/dist/lib/secrets/install-helper.d.ts +4 -4
  333. package/dist/lib/secrets/install-helper.js +4 -4
  334. package/dist/lib/secrets/push.d.ts +40 -6
  335. package/dist/lib/secrets/push.js +58 -11
  336. package/dist/lib/secrets/read-backoff.d.ts +1 -1
  337. package/dist/lib/secrets/read-backoff.js +1 -1
  338. package/dist/lib/secrets/remote.d.ts +24 -0
  339. package/dist/lib/secrets/remote.js +54 -4
  340. package/dist/lib/self-update.d.ts +108 -0
  341. package/dist/lib/self-update.js +276 -1
  342. package/dist/lib/session/active.d.ts +89 -5
  343. package/dist/lib/session/active.js +165 -10
  344. package/dist/lib/session/actor-sidecar.d.ts +1 -1
  345. package/dist/lib/session/actor-sidecar.js +2 -1
  346. package/dist/lib/session/db.d.ts +176 -2
  347. package/dist/lib/session/db.js +484 -17
  348. package/dist/lib/session/discover.js +27 -4
  349. package/dist/lib/session/hook-sessions.js +2 -2
  350. package/dist/lib/session/host-link.d.ts +2 -2
  351. package/dist/lib/session/host-link.js +2 -2
  352. package/dist/lib/session/pid-registry.d.ts +21 -0
  353. package/dist/lib/session/pid-registry.js +57 -0
  354. package/dist/lib/session/remote-active.js +15 -1
  355. package/dist/lib/session/remote.js +2 -2
  356. package/dist/lib/session/session-cache.d.ts +14 -7
  357. package/dist/lib/session/session-cache.js +51 -9
  358. package/dist/lib/session/state.d.ts +2 -2
  359. package/dist/lib/session/state.js +1 -1
  360. package/dist/lib/session/sync/config.d.ts +10 -10
  361. package/dist/lib/session/sync/config.js +10 -10
  362. package/dist/lib/session/sync/r2.d.ts +34 -0
  363. package/dist/lib/session/sync/r2.js +123 -0
  364. package/dist/lib/session/throughput.d.ts +1 -1
  365. package/dist/lib/session/throughput.js +1 -1
  366. package/dist/lib/session/types.d.ts +23 -1
  367. package/dist/lib/session/types.js +15 -0
  368. package/dist/lib/session/viewing-in.d.ts +1 -1
  369. package/dist/lib/session/viewing-in.js +1 -1
  370. package/dist/lib/session/watch.d.ts +101 -0
  371. package/dist/lib/session/watch.js +242 -0
  372. package/dist/lib/share/analytics.js +1 -1
  373. package/dist/lib/share/capture.d.ts +1 -1
  374. package/dist/lib/share/capture.js +3 -3
  375. package/dist/lib/share/config.d.ts +6 -2
  376. package/dist/lib/share/config.js +6 -5
  377. package/dist/lib/share/delete.js +3 -3
  378. package/dist/lib/share/provision.d.ts +38 -0
  379. package/dist/lib/share/provision.js +51 -1
  380. package/dist/lib/share/publish.d.ts +40 -1
  381. package/dist/lib/share/publish.js +119 -6
  382. package/dist/lib/share/worker-template.d.ts +12 -1
  383. package/dist/lib/share/worker-template.js +83 -7
  384. package/dist/lib/shims.d.ts +17 -3
  385. package/dist/lib/shims.js +98 -26
  386. package/dist/lib/signin-badge.js +3 -2
  387. package/dist/lib/skills.js +2 -0
  388. package/dist/lib/smart-launch.d.ts +8 -8
  389. package/dist/lib/smart-launch.js +80 -59
  390. package/dist/lib/ssh-exec.d.ts +1 -1
  391. package/dist/lib/ssh-exec.js +1 -1
  392. package/dist/lib/staleness/prune.d.ts +88 -0
  393. package/dist/lib/staleness/prune.js +69 -0
  394. package/dist/lib/staleness/registry.d.ts +1 -1
  395. package/dist/lib/staleness/writers/commands.js +34 -2
  396. package/dist/lib/staleness/writers/hooks.js +16 -0
  397. package/dist/lib/staleness/writers/kinds.d.ts +6 -0
  398. package/dist/lib/staleness/writers/skills.js +19 -0
  399. package/dist/lib/staleness/writers/subagents.d.ts +2 -3
  400. package/dist/lib/staleness/writers/subagents.js +0 -4
  401. package/dist/lib/staleness/writers/types.d.ts +32 -0
  402. package/dist/lib/startup/command-registry.d.ts +16 -14
  403. package/dist/lib/startup/command-registry.js +26 -37
  404. package/dist/lib/startup/dev-build.d.ts +10 -0
  405. package/dist/lib/startup/dev-build.js +13 -1
  406. package/dist/lib/startup/spellcheck.d.ts +18 -0
  407. package/dist/lib/startup/spellcheck.js +45 -0
  408. package/dist/lib/state.d.ts +36 -9
  409. package/dist/lib/state.js +96 -46
  410. package/dist/lib/subagents-registry.d.ts +0 -7
  411. package/dist/lib/subagents-registry.js +38 -65
  412. package/dist/lib/subagents.d.ts +0 -33
  413. package/dist/lib/subagents.js +0 -75
  414. package/dist/lib/sync-umbrella.js +1 -1
  415. package/dist/lib/teams/agents.d.ts +41 -1
  416. package/dist/lib/teams/agents.js +187 -9
  417. package/dist/lib/teams/api.d.ts +11 -1
  418. package/dist/lib/teams/api.js +11 -2
  419. package/dist/lib/teams/delivery.d.ts +41 -0
  420. package/dist/lib/teams/delivery.js +60 -0
  421. package/dist/lib/teams/registry.d.ts +14 -0
  422. package/dist/lib/teams/registry.js +51 -1
  423. package/dist/lib/teams/remoteWorktree.d.ts +19 -0
  424. package/dist/lib/teams/remoteWorktree.js +29 -0
  425. package/dist/lib/teams/scheduler.d.ts +1 -1
  426. package/dist/lib/teams/scheduler.js +1 -1
  427. package/dist/lib/teams/worktree.d.ts +24 -0
  428. package/dist/lib/teams/worktree.js +42 -0
  429. package/dist/lib/terminal/backends/vscodium-agent.d.ts +10 -1
  430. package/dist/lib/terminal/backends/vscodium-agent.js +16 -5
  431. package/dist/lib/terminal/engine.d.ts +4 -0
  432. package/dist/lib/terminal/engine.js +8 -2
  433. package/dist/lib/terminal/types.d.ts +21 -2
  434. package/dist/lib/testdata/refresh-coordinator-worker.d.ts +1 -0
  435. package/dist/lib/testdata/refresh-coordinator-worker.js +23 -0
  436. package/dist/lib/tickets/list.d.ts +53 -0
  437. package/dist/lib/tickets/list.js +153 -0
  438. package/dist/lib/tmux/orphan-reap.d.ts +316 -0
  439. package/dist/lib/tmux/orphan-reap.js +638 -0
  440. package/dist/lib/tmux/session.d.ts +68 -3
  441. package/dist/lib/tmux/session.js +96 -5
  442. package/dist/lib/triggers/handlers.d.ts +20 -0
  443. package/dist/lib/triggers/handlers.js +16 -1
  444. package/dist/lib/triggers/webhook.js +10 -0
  445. package/dist/lib/types.d.ts +47 -35
  446. package/dist/lib/usage-fleet.d.ts +32 -0
  447. package/dist/lib/usage-fleet.js +125 -0
  448. package/dist/lib/usage-refresh.d.ts +3 -3
  449. package/dist/lib/usage-refresh.js +19 -16
  450. package/dist/lib/usage.d.ts +51 -47
  451. package/dist/lib/usage.js +145 -153
  452. package/dist/lib/version-duplicates.js +2 -2
  453. package/dist/lib/versions.d.ts +56 -13
  454. package/dist/lib/versions.js +195 -45
  455. package/dist/lib/watchdog/log.d.ts +1 -1
  456. package/dist/lib/watchdog/log.js +3 -3
  457. package/dist/lib/watchdog/rotate.d.ts +6 -6
  458. package/dist/lib/watchdog/rotate.js +6 -6
  459. package/dist/lib/workflows.d.ts +1 -1
  460. package/dist/lib/yaml-io.d.ts +47 -0
  461. package/dist/lib/yaml-io.js +55 -0
  462. package/package.json +2 -1
  463. package/scripts/install-helper.js +2 -2
  464. package/scripts/postinstall.js +23 -20
  465. package/dist/commands/defaults.d.ts +0 -7
  466. package/dist/commands/defaults.js +0 -107
  467. package/dist/commands/export.d.ts +0 -11
  468. package/dist/commands/export.js +0 -215
  469. package/dist/commands/helper.d.ts +0 -12
  470. package/dist/commands/helper.js +0 -87
  471. package/dist/commands/hosts.d.ts +0 -11
  472. package/dist/commands/hosts.js +0 -330
  473. package/dist/commands/lock.d.ts +0 -12
  474. package/dist/commands/lock.js +0 -70
  475. package/dist/commands/pull.d.ts +0 -17
  476. package/dist/commands/pull.js +0 -39
  477. package/dist/commands/push.d.ts +0 -14
  478. package/dist/commands/push.js +0 -30
  479. package/dist/commands/set.d.ts +0 -15
  480. package/dist/commands/set.js +0 -79
  481. package/dist/commands/setup-share.d.ts +0 -17
  482. package/dist/commands/setup-share.js +0 -85
  483. package/dist/commands/wallet.d.ts +0 -20
  484. package/dist/commands/wallet.js +0 -216
  485. package/dist/commands/worktree.d.ts +0 -19
  486. package/dist/commands/worktree.js +0 -272
  487. package/dist/lib/account-labels.d.ts +0 -24
  488. package/dist/lib/account-labels.js +0 -72
  489. package/dist/lib/auto-dispatch-linear.d.ts +0 -18
  490. package/dist/lib/auto-dispatch-linear.js +0 -107
  491. package/dist/lib/auto-dispatch-provider.d.ts +0 -10
  492. package/dist/lib/auto-dispatch-provider.js +0 -30
  493. package/dist/lib/auto-dispatch.d.ts +0 -93
  494. package/dist/lib/auto-dispatch.js +0 -128
  495. package/dist/lib/export.d.ts +0 -72
  496. package/dist/lib/export.js +0 -269
  497. package/dist/lib/lock.d.ts +0 -93
  498. package/dist/lib/lock.js +0 -207
  499. package/dist/lib/wallet/index.d.ts +0 -78
  500. package/dist/lib/wallet/index.js +0 -253
@@ -10,9 +10,25 @@ export interface PublishEndpoint {
10
10
  }
11
11
  export interface PublishOptions {
12
12
  slug?: string;
13
- /** e.g. `30d`, `12h`, or an absolute date like `2026-08-01`. */
13
+ /**
14
+ * Auto-expire window. Relative (`30d`, `12h`), absolute (`2026-08-01`), or
15
+ * `never` / `none` / `permanent` for no expiry. When omitted, publishes default
16
+ * to {@link DEFAULT_SHARE_EXPIRE} so an accidental share decays instead of
17
+ * living forever (RUSH-2443).
18
+ */
14
19
  expire?: string;
15
20
  contentType?: string;
21
+ /**
22
+ * Hide this page from the public `/<user>` gallery and `agents artifacts share list`
23
+ * (metadata `visibility=unlisted`). The direct URL is still world-readable —
24
+ * unlisted, not secret (RUSH-2443). Alias of `--private` on the CLI.
25
+ */
26
+ unlisted?: boolean;
27
+ /**
28
+ * Bypass the pre-publish sensitive-content scan (emails / credential-shaped
29
+ * strings). Required when the page intentionally carries those patterns.
30
+ */
31
+ force?: boolean;
16
32
  /** Generate + attach an OG cover for HTML pages (default true). */
17
33
  cover?: boolean;
18
34
  /** Inject the Cloudflare Web Analytics beacon (default true for HTML). */
@@ -34,9 +50,32 @@ export interface PublishResult {
34
50
  url: string;
35
51
  expiresAt?: string;
36
52
  coverUrl?: string;
53
+ /** True when the page was published with `visibility=unlisted`. */
54
+ unlisted?: boolean;
37
55
  }
56
+ /** Default auto-expire for unflagged publishes — accidental links decay (RUSH-2443). */
57
+ export declare const DEFAULT_SHARE_EXPIRE = "30d";
38
58
  /** `30d` / `12h` / `2026-08-01` → an absolute ISO timestamp (or undefined). */
39
59
  export declare function parseExpire(spec: string | undefined): string | undefined;
60
+ /**
61
+ * Resolve the publish expiry. Omitted → {@link DEFAULT_SHARE_EXPIRE}. Explicit
62
+ * `never` / `none` / `permanent` → no expiry. Anything else → {@link parseExpire}.
63
+ */
64
+ export declare function resolveExpire(spec: string | undefined): string | undefined;
65
+ export type SensitiveHitKind = 'email' | 'credential';
66
+ export interface SensitiveHit {
67
+ kind: SensitiveHitKind;
68
+ /** Short redacted sample so the error names *what* was found without dumping it. */
69
+ sample: string;
70
+ }
71
+ /**
72
+ * Scan a text body for email addresses and credential-shaped strings. Returns
73
+ * the first few hits (deduped by kind+sample). Binary / non-text bodies yield
74
+ * nothing — the gate is for HTML/text reports, not screenshots.
75
+ */
76
+ export declare function scanShareContent(body: string | Buffer): SensitiveHit[];
77
+ /** Build the refuse message when the pre-publish scan finds sensitive content. */
78
+ export declare function formatSensitiveContentError(hits: SensitiveHit[]): string;
40
79
  /** Derive a URL-safe slug from a filename (or pass one through). */
41
80
  export declare function slugify(name: string): string;
42
81
  /** The project the file belongs to — git repo name, else the cwd's basename. */
@@ -1,4 +1,4 @@
1
- // The publish path for `agents share <file>` — an authed PUT to the Worker.
1
+ // The publish path for `agents artifacts share <file>` — an authed PUT to the Worker.
2
2
  // Pure logic (slug, expiry) is exported for tests; the network call is behind a DI seam.
3
3
  //
4
4
  // For HTML publishes it also captures a 1200×630 cover (the page's own hero) and
@@ -14,6 +14,8 @@ import { resolveGitHubUsername } from '../git.js';
14
14
  import { captureCover, OG_WIDTH, OG_HEIGHT, OG_SCALE } from './capture.js';
15
15
  import { deriveMeta, injectOgMeta } from './og.js';
16
16
  import { injectAnalyticsBeacon } from './analytics.js';
17
+ /** Default auto-expire for unflagged publishes — accidental links decay (RUSH-2443). */
18
+ export const DEFAULT_SHARE_EXPIRE = '30d';
17
19
  const UNIT_MS = { s: 1e3, m: 6e4, h: 36e5, d: 864e5, w: 6048e5 };
18
20
  /** `30d` / `12h` / `2026-08-01` → an absolute ISO timestamp (or undefined). */
19
21
  export function parseExpire(spec) {
@@ -26,7 +28,99 @@ export function parseExpire(spec) {
26
28
  const d = new Date(spec);
27
29
  if (!Number.isNaN(d.getTime()))
28
30
  return d.toISOString();
29
- throw new Error(`Bad --expire '${spec}'. Use e.g. 30d, 12h, or an absolute date like 2026-08-01.`);
31
+ throw new Error(`Bad --expire '${spec}'. Use e.g. 30d, 12h, an absolute date like 2026-08-01, or 'never' for no expiry.`);
32
+ }
33
+ /**
34
+ * Resolve the publish expiry. Omitted → {@link DEFAULT_SHARE_EXPIRE}. Explicit
35
+ * `never` / `none` / `permanent` → no expiry. Anything else → {@link parseExpire}.
36
+ */
37
+ export function resolveExpire(spec) {
38
+ if (spec === undefined)
39
+ return parseExpire(DEFAULT_SHARE_EXPIRE);
40
+ const trimmed = spec.trim().toLowerCase();
41
+ if (trimmed === 'never' || trimmed === 'none' || trimmed === 'permanent')
42
+ return undefined;
43
+ return parseExpire(spec);
44
+ }
45
+ /** Email addresses — the RUSH-2428 incident page carried seven of these. */
46
+ const EMAIL_RE = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
47
+ /**
48
+ * Credential-shaped strings that an agent routinely dumps into reports: GitHub
49
+ * PATs, OpenAI/Anthropic/etc. API keys, AWS access keys, Slack tokens, and a
50
+ * generic long `sk-…` / `Bearer …` form. Keep the set tight — false positives
51
+ * force `--force` and train agents to bypass the gate.
52
+ */
53
+ const CREDENTIAL_PATTERNS = [
54
+ { re: /\bghp_[A-Za-z0-9_]{20,}\b/g, label: 'ghp_…' },
55
+ { re: /\bgho_[A-Za-z0-9_]{20,}\b/g, label: 'gho_…' },
56
+ { re: /\bghu_[A-Za-z0-9_]{20,}\b/g, label: 'ghu_…' },
57
+ { re: /\bghs_[A-Za-z0-9_]{20,}\b/g, label: 'ghs_…' },
58
+ { re: /\bghr_[A-Za-z0-9_]{20,}\b/g, label: 'ghr_…' },
59
+ { re: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g, label: 'github_pat_…' },
60
+ { re: /\bsk-(?:ant|proj|live|test)?[_-]?[A-Za-z0-9]{16,}\b/g, label: 'sk-…' },
61
+ { re: /\bAKIA[0-9A-Z]{16}\b/g, label: 'AKIA…' },
62
+ { re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g, label: 'xox…' },
63
+ { re: /\bBearer\s+[A-Za-z0-9._\-+/=]{20,}\b/gi, label: 'Bearer …' },
64
+ ];
65
+ function redactSample(raw, max = 12) {
66
+ if (raw.length <= max)
67
+ return raw.slice(0, 4) + '…';
68
+ return raw.slice(0, Math.min(6, max)) + '…';
69
+ }
70
+ /**
71
+ * Scan a text body for email addresses and credential-shaped strings. Returns
72
+ * the first few hits (deduped by kind+sample). Binary / non-text bodies yield
73
+ * nothing — the gate is for HTML/text reports, not screenshots.
74
+ */
75
+ export function scanShareContent(body) {
76
+ // Skip clearly-binary content (null bytes in the first 1KB) so a PNG/MP4
77
+ // publish never false-positives on binary noise.
78
+ if (Buffer.isBuffer(body)) {
79
+ const head = body.subarray(0, Math.min(body.length, 1024));
80
+ if (head.includes(0))
81
+ return [];
82
+ }
83
+ const text = typeof body === 'string' ? body : body.toString('utf8');
84
+ const hits = [];
85
+ const seen = new Set();
86
+ for (const m of text.matchAll(EMAIL_RE)) {
87
+ const sample = redactSample(m[0]);
88
+ const key = `email:${sample}`;
89
+ if (seen.has(key))
90
+ continue;
91
+ seen.add(key);
92
+ hits.push({ kind: 'email', sample });
93
+ if (hits.length >= 5)
94
+ return hits;
95
+ }
96
+ for (const { re, label } of CREDENTIAL_PATTERNS) {
97
+ re.lastIndex = 0;
98
+ const m = re.exec(text);
99
+ if (!m)
100
+ continue;
101
+ const sample = label;
102
+ const key = `credential:${sample}`;
103
+ if (seen.has(key))
104
+ continue;
105
+ seen.add(key);
106
+ hits.push({ kind: 'credential', sample });
107
+ if (hits.length >= 5)
108
+ return hits;
109
+ }
110
+ return hits;
111
+ }
112
+ /** Build the refuse message when the pre-publish scan finds sensitive content. */
113
+ export function formatSensitiveContentError(hits) {
114
+ const kinds = Array.from(new Set(hits.map((h) => h.kind)));
115
+ const samples = hits.map((h) => h.sample).join(', ');
116
+ const what = kinds.length === 2
117
+ ? 'email addresses and credential-shaped strings'
118
+ : kinds[0] === 'email'
119
+ ? 'email addresses'
120
+ : 'credential-shaped strings';
121
+ return (`Refusing to publish: the file contains ${what} (${samples}). ` +
122
+ `Shares are world-readable by URL — pass --force to publish anyway, ` +
123
+ `or --unlisted --expire 12h to bound the blast radius.`);
30
124
  }
31
125
  /** Derive a URL-safe slug from a filename (or pass one through). */
32
126
  export function slugify(name) {
@@ -161,7 +255,7 @@ export function buildShareKey(username, slugPart) {
161
255
  export async function publishFile(filePath, opts = {}) {
162
256
  const cfg = opts.config ?? readShareConfig();
163
257
  if (!cfg) {
164
- throw new Error("Not set up yet. Run 'agents share setup' (provision your own endpoint) or 'agents share join' (use an existing one).");
258
+ throw new Error("Not set up yet. Run 'agents artifacts setup' (provision your own endpoint) or 'agents artifacts share join' (use an existing one).");
165
259
  }
166
260
  const token = opts.writeToken ?? readWriteToken();
167
261
  const username = await resolveShareUsername(opts);
@@ -176,7 +270,8 @@ export async function publishToEndpoint(filePath, endpoint, opts = {}) {
176
270
  const username = await resolveShareUsername(opts);
177
271
  const slugPart = (opts.slug ?? defaultSlug(filePath)).replace(/^\/+/, '');
178
272
  const key = buildShareKey(username, slugPart);
179
- const expiresAt = parseExpire(opts.expire);
273
+ const expiresAt = resolveExpire(opts.expire);
274
+ const unlisted = opts.unlisted === true;
180
275
  const pageUrl = `${endpoint.baseUrl.replace(/\/+$/, '')}/${key}`;
181
276
  const put = opts.uploader ??
182
277
  (async (u, b, h) => {
@@ -187,16 +282,29 @@ export async function publishToEndpoint(filePath, endpoint, opts = {}) {
187
282
  const h = { authorization: `Bearer ${endpoint.token}`, 'content-type': contentType };
188
283
  if (expiresAt)
189
284
  h['x-share-expires-at'] = expiresAt;
285
+ if (unlisted)
286
+ h['x-share-visibility'] = 'unlisted';
190
287
  return h;
191
288
  };
192
289
  let body = readFileSync(filePath);
193
290
  let coverUrl;
194
291
  const isHtml = /\.html?$/i.test(filePath);
292
+ // Pre-publish scan (RUSH-2443): refuse emails / credential-shaped strings
293
+ // unless --force. Runs on the raw file before analytics/cover mutation so a
294
+ // beacon injection never triggers a false positive. Binary media is a no-op.
295
+ if (opts.force !== true) {
296
+ const hits = scanShareContent(body);
297
+ if (hits.length > 0) {
298
+ throw new Error(formatSensitiveContentError(hits));
299
+ }
300
+ }
195
301
  // Analytics: cookieless CF Web Analytics beacon, injected for HTML by default.
196
302
  if (isHtml && opts.analytics !== false && opts.analyticsToken) {
197
303
  body = Buffer.from(injectAnalyticsBeacon(body.toString('utf8'), opts.analyticsToken), 'utf8');
198
304
  }
199
305
  // Cover: screenshot the page's hero → upload <slug>.png → inject og:image meta.
306
+ // Unlisted pages still get a cover (the direct URL is the capability), but the
307
+ // cover inherits visibility=unlisted so it is also omitted from the gallery.
200
308
  if (isHtml && opts.cover !== false) {
201
309
  const res = await attachOgCover(filePath, body, {
202
310
  pngUrl: `${pageUrl}.png`,
@@ -210,7 +318,12 @@ export async function publishToEndpoint(filePath, endpoint, opts = {}) {
210
318
  }
211
319
  const r = await put(pageUrl, body, authHeaders(opts.contentType ?? guessContentType(filePath)));
212
320
  if (!r.ok) {
213
- throw new Error(`Publish failed (${r.status}) for ${pageUrl}. Check the write token, or that 'agents share setup' completed.`);
321
+ throw new Error(`Publish failed (${r.status}) for ${pageUrl}. Check the write token, or that 'agents artifacts setup' completed.`);
214
322
  }
215
- return { url: r.url ?? pageUrl, expiresAt, coverUrl };
323
+ return {
324
+ url: r.url ?? pageUrl,
325
+ expiresAt,
326
+ coverUrl,
327
+ ...(unlisted ? { unlisted: true } : {}),
328
+ };
216
329
  }
@@ -1,2 +1,13 @@
1
- /** Render the Worker source. Pure — the R2 binding + token are wired at deploy time. */
1
+ /**
2
+ * Render the Worker source. Pure — the R2 binding + token are wired at deploy time.
3
+ *
4
+ * The literal below still spells the CLI `agents share` in its provenance comment,
5
+ * its root response, and its gallery title, even though the command is now
6
+ * `agents artifacts share` (RUSH-2580). That is deliberate: `hashWorkerScript` of
7
+ * this exact text is what `shareTemplateStatus` compares a provisioned endpoint's
8
+ * recorded `templateHash` against, so editing ANY byte here marks every already-
9
+ * deployed endpoint `outdated` — which makes `agents artifacts share list` refuse
10
+ * until its owner re-runs `agents artifacts share update`. Cosmetic renames are not
11
+ * worth that; change this text only alongside a real Worker behavior change.
12
+ */
2
13
  export declare function renderWorkerScript(): string;
@@ -7,14 +7,30 @@
7
7
  // - GET /<username>/<slug> — public; streams the object from R2, 410s (and lazily
8
8
  // deletes) once its expiry has passed. A bucket lifecycle rule is the durable
9
9
  // sweeper; this is the immediate gate.
10
- // - GET /<username> — public gallery of that user's shares.
10
+ // - GET /<username> — public gallery of that user's shares (HTML).
11
+ // - GET /<username>?format=json — public machine-readable listing of that user's
12
+ // ACTIVE shares (`agents artifacts share list`). Same single-segment path as the HTML
13
+ // gallery and gated on the SAME "does <username>/ hold any object" check, so it
14
+ // only intercepts a genuine namespace — a legacy flat slug with ?format=json
15
+ // still serves its real content, never a fake empty listing.
11
16
  // - GET /<slug> — backward-compat flat slug (legacy shares before
12
17
  // per-user namespaces).
13
18
  //
14
19
  // Emitted as a string (mirrors src/lib/serve/page.ts `renderPage()`), so it compiles
15
20
  // into `dist/**` and ships with no package.json#files change. `provision.ts` uploads
16
21
  // this verbatim as an ES-module Worker with a BUCKET (R2) binding + a WRITE_TOKEN secret.
17
- /** Render the Worker source. Pure — the R2 binding + token are wired at deploy time. */
22
+ /**
23
+ * Render the Worker source. Pure — the R2 binding + token are wired at deploy time.
24
+ *
25
+ * The literal below still spells the CLI `agents share` in its provenance comment,
26
+ * its root response, and its gallery title, even though the command is now
27
+ * `agents artifacts share` (RUSH-2580). That is deliberate: `hashWorkerScript` of
28
+ * this exact text is what `shareTemplateStatus` compares a provisioned endpoint's
29
+ * recorded `templateHash` against, so editing ANY byte here marks every already-
30
+ * deployed endpoint `outdated` — which makes `agents artifacts share list` refuse
31
+ * until its owner re-runs `agents artifacts share update`. Cosmetic renames are not
32
+ * worth that; change this text only alongside a real Worker behavior change.
33
+ */
18
34
  export function renderWorkerScript() {
19
35
  return `// GENERATED by agents-cli agents share setup — do not edit here; edit
20
36
  // src/lib/share/worker-template.ts and re-run setup.
@@ -35,22 +51,41 @@ export default {
35
51
  return json({ error: 'unauthorized' }, 401);
36
52
  }
37
53
  const expiresAt = request.headers.get('x-share-expires-at') || '';
54
+ // 'unlisted' hides the page from the public gallery + JSON listing while
55
+ // keeping the direct URL world-readable (capability URL, not secret).
56
+ const visibility = (request.headers.get('x-share-visibility') || '').toLowerCase();
38
57
  const contentType = request.headers.get('content-type') || 'text/html; charset=utf-8';
58
+ const customMetadata = {};
59
+ if (expiresAt) customMetadata['expires-at'] = expiresAt;
60
+ if (visibility === 'unlisted') customMetadata['visibility'] = 'unlisted';
39
61
  await env.BUCKET.put(path, request.body, {
40
62
  httpMetadata: { contentType },
41
- customMetadata: expiresAt ? { 'expires-at': expiresAt } : {},
63
+ customMetadata,
42
64
  });
43
- return json({ ok: true, url: url.origin + '/' + path, expiresAt: expiresAt || null }, 200);
65
+ return json({ ok: true, url: url.origin + '/' + path, expiresAt: expiresAt || null, unlisted: visibility === 'unlisted' }, 200);
44
66
  }
45
67
 
46
68
  if (request.method === 'GET' || request.method === 'HEAD') {
47
- // Single-segment path may be a user gallery OR a legacy flat slug.
69
+ // Single-segment path may be a user gallery/listing OR a legacy flat slug.
70
+ // The disambiguator is whether the <seg>/ prefix holds any object: only a
71
+ // genuine per-user namespace does. BOTH the HTML gallery and the
72
+ // machine-readable listing gate on it, so ?format=json on a legacy flat
73
+ // slug (an object stored at the bare key, before per-user namespaces) does
74
+ // NOT hijack it into a fake empty listing — it falls through to the object
75
+ // GET below and serves its real content, exactly as before.
48
76
  const segments = path.split('/').filter(Boolean);
49
77
  if (segments.length === 1) {
50
78
  const list = await env.BUCKET.list({ prefix: segments[0] + '/', limit: 1 });
51
- if (list.objects && list.objects.length > 0) {
52
- return renderGallery(env.BUCKET, url.origin, segments[0], request.method);
79
+ const isNamespace = list.objects && list.objects.length > 0;
80
+ if (isNamespace) {
81
+ return url.searchParams.get('format') === 'json'
82
+ ? renderListing(env.BUCKET, url.origin, segments[0], request.method)
83
+ : renderGallery(env.BUCKET, url.origin, segments[0], request.method);
53
84
  }
85
+ // Not a namespace: fall through. A legacy flat-slug object resolves to its
86
+ // real content; anything else 404s (an empty/nonexistent namespace, which
87
+ // agents share list reads as "nothing published" via the template-hash
88
+ // signal rather than a missing route).
54
89
  }
55
90
 
56
91
  const obj = await env.BUCKET.get(path);
@@ -90,6 +125,8 @@ async function renderGallery(bucket, origin, user, method) {
90
125
 
91
126
  const activeObjects = objects.filter(o => {
92
127
  if (o.key.endsWith('.png')) return false;
128
+ // Unlisted pages are reachable by direct URL only — never on the gallery.
129
+ if (o.customMetadata && o.customMetadata.visibility === 'unlisted') return false;
93
130
  const expiresAt = o.customMetadata && o.customMetadata['expires-at'];
94
131
  return !(expiresAt && Date.now() > Date.parse(expiresAt));
95
132
  });
@@ -124,6 +161,45 @@ async function renderGallery(bucket, origin, user, method) {
124
161
  return new Response(html, { status: 200, headers: { 'content-type': 'text/html; charset=utf-8', 'cache-control': 'public, max-age=60' } });
125
162
  }
126
163
 
164
+ async function renderListing(bucket, origin, user, method) {
165
+ const objects = [];
166
+ let cursor;
167
+ do {
168
+ const list = await bucket.list({ prefix: user + '/', limit: 1000, cursor, include: ['httpMetadata', 'customMetadata'] });
169
+ objects.push(...(list.objects || []));
170
+ cursor = list.truncated ? list.cursor : undefined;
171
+ } while (cursor);
172
+
173
+ const now = Date.now();
174
+ const items = objects
175
+ .filter(o => {
176
+ // Mirror the gallery: hide sibling .png OG covers, expired pages, and
177
+ // unlisted pages — the listing is the machine-readable public surface.
178
+ if (o.key.endsWith('.png')) return false;
179
+ if (o.customMetadata && o.customMetadata.visibility === 'unlisted') return false;
180
+ const expiresAt = o.customMetadata && o.customMetadata['expires-at'];
181
+ return !(expiresAt && now > Date.parse(expiresAt));
182
+ })
183
+ .map(o => ({
184
+ slug: o.key.slice(o.key.indexOf('/') + 1),
185
+ url: origin + '/' + o.key,
186
+ size: typeof o.size === 'number' ? o.size : 0,
187
+ contentType: (o.httpMetadata && o.httpMetadata.contentType) || null,
188
+ publishedAt: new Date(o.uploaded).toISOString(),
189
+ expiresAt: (o.customMetadata && o.customMetadata['expires-at']) || null,
190
+ }));
191
+ // Newest first, so the human table and any script reads the freshest share top.
192
+ items.sort((a, b) => (a.publishedAt < b.publishedAt ? 1 : a.publishedAt > b.publishedAt ? -1 : 0));
193
+
194
+ if (method === 'HEAD') {
195
+ return new Response(null, { status: 200, headers: { 'content-type': 'application/json; charset=utf-8' } });
196
+ }
197
+ return new Response(JSON.stringify({ user, count: items.length, objects: items }), {
198
+ status: 200,
199
+ headers: { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'public, max-age=30' },
200
+ });
201
+ }
202
+
127
203
  function escapeHtml(s) {
128
204
  return String(s)
129
205
  .replace(/&/g, '&amp;')
@@ -77,7 +77,7 @@ export interface ConflictInfo {
77
77
  * top-level entry add/remove — deep edits to plugin contents won't
78
78
  * trigger auto-resync, run `agents sync` for that.
79
79
  */
80
- export declare const SHIM_SCHEMA_VERSION = 29;
80
+ export declare const SHIM_SCHEMA_VERSION = 30;
81
81
  /**
82
82
  * Generate the full bash shim script for the given agent. The returned string
83
83
  * is written to ~/.agents/shims/{cliCommand} and made executable.
@@ -159,8 +159,22 @@ export declare function removeShim(agent: AgentId): boolean;
159
159
  * alias failed with "not installed" whenever the binary was staged into
160
160
  * the versioned home (installer run with GROK_HOME set, or grok
161
161
  * self-update under the shim).
162
- */
163
- export declare const VERSIONED_ALIAS_SCHEMA_VERSION = 15;
162
+ * v16 — RUSH-2459: two compounding grok binary-resolution bugs fixed. (1) The
163
+ * "exact version match" grep ran against `ls`'s FULL PATH output, and
164
+ * the versioned home's own path always contains the version string
165
+ * (.../versions/grok/<version>/...), so it matched every candidate
166
+ * unconditionally and silently degraded to "whatever ls sorts first" —
167
+ * now matched against each candidate's basename instead. (2) When no
168
+ * filename genuinely carries the version, the fallback no longer
169
+ * trusts whatever sorts first: it rejects any grok-* candidate under
170
+ * 1MB (real grok binaries are ~100MB+; a stray wrapper/alias script is
171
+ * a few hundred bytes) and prefers the most recently modified
172
+ * survivor. On yosemite-s0 both bugs fired together: a stale, unrelated
173
+ * grok-0.2.118-* file — a 99-byte wrapper that exec'd cursor-agent —
174
+ * sorted alphabetically before the real self-updated grok binary and
175
+ * was silently launched instead.
176
+ */
177
+ export declare const VERSIONED_ALIAS_SCHEMA_VERSION = 16;
164
178
  /**
165
179
  * Agents whose config directory can be relocated by an environment variable
166
180
  * (the per-agent `managedEnv` block in `generateVersionedAliasScript` below).
package/dist/lib/shims.js CHANGED
@@ -223,12 +223,79 @@ async function promptConflictStrategy(conflictInfos) {
223
223
  // The old dispatcher checked only the global dir, so a pinned grok that
224
224
  // installed into the versioned home fell through to the "not installed"
225
225
  // error.
226
- export const SHIM_SCHEMA_VERSION = 29;
226
+ // v30 RUSH-2459: two compounding grok binary-resolution bugs fixed. (1) The
227
+ // "exact version match" grep ran against `ls`'s FULL PATH output, and
228
+ // the versioned home's own path always contains the version string
229
+ // (.../versions/grok/<version>/...), so it matched every candidate
230
+ // unconditionally and silently degraded to "whatever ls sorts first" —
231
+ // now matched against each candidate's basename instead. (2) When no
232
+ // filename genuinely carries the version, the fallback no longer
233
+ // trusts whatever sorts first: it rejects any grok-* candidate under
234
+ // 1MB (real grok binaries are ~100MB+; a stray wrapper/alias script is
235
+ // a few hundred bytes) and prefers the most recently modified
236
+ // survivor. On yosemite-s0 both bugs fired together: a stale, unrelated
237
+ // grok-0.2.118-* file — a 99-byte wrapper that exec'd cursor-agent —
238
+ // sorted alphabetically before the real self-updated grok binary and
239
+ // was silently launched instead.
240
+ export const SHIM_SCHEMA_VERSION = 30;
227
241
  /** Internal marker string used to embed the schema version in shim scripts. */
228
242
  const SHIM_VERSION_MARKER = 'agents-shim-version:';
229
243
  function shellQuote(value) {
230
244
  return `'${value.replace(/'/g, `'\\''`)}'`;
231
245
  }
246
+ /**
247
+ * Bash function embedded in every generated grok binary-resolution block
248
+ * (the dispatcher shim's `generateShimScript` and the direct alias's
249
+ * `generateVersionedAliasScript`). Prints the path to use, or nothing.
250
+ *
251
+ * Prefers a `grok-*` FILENAME that carries the pinned version string —
252
+ * checked against `basename`, never the full path: `dir` is always
253
+ * `.../versions/grok/<version>/home/.grok/downloads`, so the version string
254
+ * is already a substring of every path in that directory regardless of the
255
+ * actual filename. The original `ls "$dir"/grok-* | grep -i "$version"`
256
+ * matched on the full line and so matched every candidate unconditionally,
257
+ * silently degrading to "whatever sorts first" — the versioned-home half of
258
+ * RUSH-2459, distinct from (and compounding) the missing-match fallback bug
259
+ * below.
260
+ *
261
+ * Grok self-updates its binary in place while running under the shim, so a
262
+ * version-home's downloads dir can accumulate several `grok-*` files whose
263
+ * names have drifted away from the version-home's pinned version — when no
264
+ * filename carries it, never trust whatever the directory listing returns
265
+ * first (RUSH-2459: a stale, unrelated 99-byte wrapper script matching the
266
+ * `grok-*` naming pattern sorted before the real ~127MB self-updated binary
267
+ * and was silently exec'd). Instead, reject anything under
268
+ * MIN_GROK_BINARY_BYTES — comfortably above any wrapper/alias artifact,
269
+ * comfortably below a real compiled binary — and among the survivors, pick
270
+ * the most recently modified: the file grok's self-updater actually wrote
271
+ * last. Mirrors the TS implementation, `resolveGrokFallbackBinary` in
272
+ * versions.ts (which reads bare filenames via `fs.readdirSync` and so never
273
+ * had the full-path-match bug).
274
+ */
275
+ const GROK_RESOLVE_BINARY_FN = `_resolve_grok_binary() {
276
+ local dir="$1" version_hint="$2"
277
+ local candidate base size mtime
278
+ for candidate in "$dir"/grok-*; do
279
+ [ -f "$candidate" ] || continue
280
+ base=$(basename "$candidate")
281
+ case "$base" in
282
+ *"$version_hint"*) printf '%s\\n' "$candidate"; return ;;
283
+ esac
284
+ done
285
+ local min_bytes=1000000
286
+ local best="" best_mtime=-1
287
+ for candidate in "$dir"/grok-*; do
288
+ [ -f "$candidate" ] || continue
289
+ size=$(wc -c < "$candidate" 2>/dev/null || echo 0)
290
+ [ "$size" -ge "$min_bytes" ] || continue
291
+ mtime=$(stat -c %Y "$candidate" 2>/dev/null || stat -f %m "$candidate" 2>/dev/null || echo -1)
292
+ if [ "$mtime" -gt "$best_mtime" ]; then
293
+ best_mtime="$mtime"
294
+ best="$candidate"
295
+ fi
296
+ done
297
+ printf '%s\\n' "$best"
298
+ }`;
232
299
  function codexShimLaunchArgs() {
233
300
  return [
234
301
  '-c',
@@ -538,27 +605,20 @@ VERSION_DIR="$AGENTS_USER_DIR/.history/versions/$AGENT/$VERSION"
538
605
  # for pre-fix installs, the global ~/.grok/downloads), not node_modules. We
539
606
  # still use the agents-cli version dir purely for GROK_HOME isolation.
540
607
  if [ "$AGENT" = "grok" ]; then
608
+ ${GROK_RESOLVE_BINARY_FN}
541
609
  # Check the versioned home first — this is where the binary lands when the
542
610
  # installer runs with GROK_HOME set (i.e. via the shim or a correct
543
611
  # \`agents add grok\`), or when grok self-updates from within the shim.
544
612
  GROK_DOWNLOADS="$VERSION_DIR/home/.grok/downloads"
545
613
  if [ -d "$GROK_DOWNLOADS" ]; then
546
- # Prefer a binary whose filename contains the exact version
547
- BINARY=$(ls "$GROK_DOWNLOADS"/grok-* 2>/dev/null | grep -i "$VERSION" | head -1)
548
- if [ -z "$BINARY" ]; then
549
- # Fallback to the "current" grok binary (symlink or latest)
550
- BINARY=$(ls "$GROK_DOWNLOADS"/grok-* 2>/dev/null | head -1)
551
- fi
614
+ BINARY=$(_resolve_grok_binary "$GROK_DOWNLOADS" "$VERSION")
552
615
  fi
553
616
  # Fall back to the global grok home (binary installed without GROK_HOME set,
554
617
  # e.g. an earlier \`agents add grok@latest\` before this resolution fix).
555
618
  if [ -z "$BINARY" ] || [ ! -x "$BINARY" ]; then
556
619
  GROK_DOWNLOADS="$HOME/.grok/downloads"
557
620
  if [ -d "$GROK_DOWNLOADS" ]; then
558
- BINARY=$(ls "$GROK_DOWNLOADS"/grok-* 2>/dev/null | grep -i "$VERSION" | head -1)
559
- if [ -z "$BINARY" ]; then
560
- BINARY=$(ls "$GROK_DOWNLOADS"/grok-* 2>/dev/null | head -1)
561
- fi
621
+ BINARY=$(_resolve_grok_binary "$GROK_DOWNLOADS" "$VERSION")
562
622
  fi
563
623
  fi
564
624
  if [ -z "$BINARY" ] || [ ! -x "$BINARY" ]; then
@@ -622,13 +682,12 @@ elif [ "$AGENT" = "muse" ]; then
622
682
  fi
623
683
  fi
624
684
  elif [ "$AGENT" = "warp" ]; then
625
- # Warp Agent CLI installs a global, self-updating oz binary (brew cask on
626
- # macOS, the oz-stable apt|yum|pacman package on Linux) -- a platform/package
627
- # specific location, not ~/.local/bin -- so resolve it from PATH with the same
628
- # shims-dir re-exec guard as droid/muse.
685
+ # Warp Agent CLI installs a global, self-updating warp binary at
686
+ # ~/.local/bin/warp (curl installer) -- like droid/muse -- so resolve it from
687
+ # PATH with the same shims-dir re-exec guard as droid/muse.
629
688
  BINARY=$(adopted_original_bin || echo "")
630
689
  if [ -z "$BINARY" ]; then
631
- BINARY=$(command -v oz 2>/dev/null || echo "")
690
+ BINARY=$(command -v warp 2>/dev/null || echo "")
632
691
  case "$(readlink -f "$BINARY" 2>/dev/null)" in
633
692
  "$AGENTS_USER_DIR/.cache/shims/"*) BINARY="" ;;
634
693
  esac
@@ -942,8 +1001,22 @@ export function removeShim(agent) {
942
1001
  * alias failed with "not installed" whenever the binary was staged into
943
1002
  * the versioned home (installer run with GROK_HOME set, or grok
944
1003
  * self-update under the shim).
945
- */
946
- export const VERSIONED_ALIAS_SCHEMA_VERSION = 15;
1004
+ * v16 — RUSH-2459: two compounding grok binary-resolution bugs fixed. (1) The
1005
+ * "exact version match" grep ran against `ls`'s FULL PATH output, and
1006
+ * the versioned home's own path always contains the version string
1007
+ * (.../versions/grok/<version>/...), so it matched every candidate
1008
+ * unconditionally and silently degraded to "whatever ls sorts first" —
1009
+ * now matched against each candidate's basename instead. (2) When no
1010
+ * filename genuinely carries the version, the fallback no longer
1011
+ * trusts whatever sorts first: it rejects any grok-* candidate under
1012
+ * 1MB (real grok binaries are ~100MB+; a stray wrapper/alias script is
1013
+ * a few hundred bytes) and prefers the most recently modified
1014
+ * survivor. On yosemite-s0 both bugs fired together: a stale, unrelated
1015
+ * grok-0.2.118-* file — a 99-byte wrapper that exec'd cursor-agent —
1016
+ * sorted alphabetically before the real self-updated grok binary and
1017
+ * was silently launched instead.
1018
+ */
1019
+ export const VERSIONED_ALIAS_SCHEMA_VERSION = 16;
947
1020
  /** Internal marker string used to embed the schema version in versioned alias scripts. */
948
1021
  const VERSIONED_ALIAS_VERSION_MARKER = 'agents-versioned-alias-version:';
949
1022
  // The version string is interpolated into a generated bash script and into
@@ -1062,18 +1135,17 @@ export XDG_CONFIG_HOME="$HOME/.agents/.history/versions/${agent}/${version}/home
1062
1135
  const binaryResolution = agent === 'grok'
1063
1136
  ? `# Grok ships its native binary in the versioned home's .grok/downloads (or,
1064
1137
  # for pre-fix installs, the global ~/.grok/downloads), not node_modules.
1138
+ ${GROK_RESOLVE_BINARY_FN}
1065
1139
  GROK_DOWNLOADS="${versionDir}/home/.grok/downloads"
1066
1140
  BINARY=""
1067
1141
  if [ -d "$GROK_DOWNLOADS" ]; then
1068
- BINARY=$(ls "$GROK_DOWNLOADS"/grok-* 2>/dev/null | grep -i "${version}" | head -1)
1069
- [ -n "$BINARY" ] || BINARY=$(ls "$GROK_DOWNLOADS"/grok-* 2>/dev/null | head -1)
1142
+ BINARY=$(_resolve_grok_binary "$GROK_DOWNLOADS" "${version}")
1070
1143
  fi
1071
1144
  # Fall back to the global grok home (binary installed without GROK_HOME set).
1072
1145
  if [ -z "$BINARY" ] || [ ! -x "$BINARY" ]; then
1073
1146
  GROK_GLOBAL_DOWNLOADS="$HOME/.grok/downloads"
1074
1147
  if [ -d "$GROK_GLOBAL_DOWNLOADS" ]; then
1075
- BINARY=$(ls "$GROK_GLOBAL_DOWNLOADS"/grok-* 2>/dev/null | grep -i "${version}" | head -1)
1076
- [ -n "$BINARY" ] || BINARY=$(ls "$GROK_GLOBAL_DOWNLOADS"/grok-* 2>/dev/null | head -1)
1148
+ BINARY=$(_resolve_grok_binary "$GROK_GLOBAL_DOWNLOADS" "${version}")
1077
1149
  fi
1078
1150
  fi
1079
1151
  # Refuse a PATH match under our own shims dir — it resolves to this alias's
@@ -1110,10 +1182,10 @@ else
1110
1182
  esac
1111
1183
  fi`
1112
1184
  : agent === 'warp'
1113
- ? `# Warp Agent CLI installs a global self-updating \`oz\` binary (brew cask on
1114
- # macOS, oz-stable apt|yum|pacman on Linux)a platform-specific location, not
1115
- # ~/.local/bin — so resolve it from PATH, refusing anything under our shims dir.
1116
- BINARY=$(command -v oz 2>/dev/null || echo "")
1185
+ ? `# Warp Agent CLI installs a global self-updating \`warp\` binary at
1186
+ # ~/.local/bin/warp (curl installer) like droid/muse so resolve it from
1187
+ # PATH, refusing anything under our shims dir.
1188
+ BINARY=$(command -v warp 2>/dev/null || echo "")
1117
1189
  case "$BINARY" in
1118
1190
  "$HOME/.agents/.cache/shims/"*) BINARY="" ;;
1119
1191
  esac`
@@ -24,11 +24,12 @@ export function loginHint(agentId) {
24
24
  return `${cli}, then /login`;
25
25
  case 'codex':
26
26
  case 'grok':
27
- // Warp Agent CLI: `oz login` opens a browser sign-in (or set WARP_API_KEY).
28
- case 'warp':
29
27
  return `${cli} login`;
30
28
  case 'opencode':
31
29
  return `${cli} auth login`;
30
+ // Warp Agent CLI has no `login` subcommand: running `warp` opens a browser
31
+ // sign-in on launch (or set WARP_API_KEY / pass --api-key), so the default
32
+ // bare-`warp` hint is correct.
32
33
  default:
33
34
  return cli;
34
35
  }
@@ -10,6 +10,7 @@ import * as fs from 'fs';
10
10
  import * as path from 'path';
11
11
  import * as os from 'os';
12
12
  import * as yaml from 'yaml';
13
+ import { normalizeAliases } from './resource-aliases.js';
13
14
  import { AGENTS, ensureSkillsDir, agentConfigDirName } from './agents.js';
14
15
  import { capableAgents, isCapable } from './capabilities.js';
15
16
  import { getUserSkillsDir, getSkillsDir as getSystemSkillsDir, getProjectAgentsDir, getEnabledExtraRepos, getTrashSkillsDir } from './state.js';
@@ -98,6 +99,7 @@ export function tryParseSkillMetadata(skillDir) {
98
99
  version: parsed.version,
99
100
  license: parsed.license,
100
101
  keywords: parsed.keywords,
102
+ aliases: normalizeAliases(parsed.aliases),
101
103
  },
102
104
  };
103
105
  }