@phnx-labs/agents-cli 1.22.34 → 1.22.37

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 (493) hide show
  1. package/CHANGELOG.md +672 -2
  2. package/README.md +82 -35
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.d.ts +15 -0
  5. package/dist/bootstrap.js +1211 -0
  6. package/dist/commands/accounts.d.ts +4 -11
  7. package/dist/commands/accounts.js +159 -27
  8. package/dist/commands/attach.js +17 -4
  9. package/dist/commands/audit.d.ts +8 -8
  10. package/dist/commands/audit.js +57 -47
  11. package/dist/commands/browser.js +15 -11
  12. package/dist/commands/cloud.js +1 -1
  13. package/dist/commands/commands.js +0 -11
  14. package/dist/commands/computer-actions.js +33 -0
  15. package/dist/commands/computer-sessions-picker.d.ts +21 -0
  16. package/dist/commands/computer-sessions-picker.js +141 -0
  17. package/dist/commands/computer.d.ts +16 -0
  18. package/dist/commands/computer.js +37 -0
  19. package/dist/commands/config.d.ts +17 -0
  20. package/dist/commands/config.js +401 -0
  21. package/dist/commands/cp.d.ts +84 -0
  22. package/dist/commands/cp.js +231 -0
  23. package/dist/commands/daemon.js +243 -14
  24. package/dist/commands/detach-core.d.ts +1 -1
  25. package/dist/commands/detach-core.js +12 -2
  26. package/dist/commands/detach.js +1 -1
  27. package/dist/commands/doctor.js +64 -5
  28. package/dist/commands/events.d.ts +24 -12
  29. package/dist/commands/events.js +144 -28
  30. package/dist/commands/exec.js +85 -41
  31. package/dist/commands/feed.d.ts +1 -1
  32. package/dist/commands/feed.js +16 -8
  33. package/dist/commands/focus.d.ts +33 -1
  34. package/dist/commands/focus.js +177 -17
  35. package/dist/commands/funnel.d.ts +1 -1
  36. package/dist/commands/go.js +9 -8
  37. package/dist/commands/harness-wizard.d.ts +1 -0
  38. package/dist/commands/harness-wizard.js +18 -20
  39. package/dist/commands/harness.d.ts +2 -0
  40. package/dist/commands/harness.js +59 -26
  41. package/dist/commands/hooks.js +0 -11
  42. package/dist/commands/inspect.d.ts +94 -1
  43. package/dist/commands/inspect.js +866 -40
  44. package/dist/commands/lease.d.ts +4 -4
  45. package/dist/commands/lease.js +6 -6
  46. package/dist/commands/login.js +0 -13
  47. package/dist/commands/logs.d.ts +2 -2
  48. package/dist/commands/logs.js +2 -2
  49. package/dist/commands/mcp.js +7 -2
  50. package/dist/commands/memory.js +7 -2
  51. package/dist/commands/message.d.ts +1 -1
  52. package/dist/commands/message.js +37 -6
  53. package/dist/commands/models.js +4 -0
  54. package/dist/commands/monitors.d.ts +0 -1
  55. package/dist/commands/monitors.js +199 -16
  56. package/dist/commands/open.d.ts +18 -0
  57. package/dist/commands/open.js +57 -0
  58. package/dist/commands/packages.js +2 -107
  59. package/dist/commands/plugins.js +6 -3
  60. package/dist/commands/profiles.d.ts +1 -0
  61. package/dist/commands/profiles.js +16 -160
  62. package/dist/commands/projects.d.ts +28 -0
  63. package/dist/commands/projects.js +125 -5
  64. package/dist/commands/reconnect.js +9 -3
  65. package/dist/commands/repo.js +42 -1
  66. package/dist/commands/resource-view.d.ts +17 -0
  67. package/dist/commands/resource-view.js +36 -14
  68. package/dist/commands/resume.js +9 -2
  69. package/dist/commands/routines.d.ts +0 -2
  70. package/dist/commands/routines.js +473 -289
  71. package/dist/commands/secrets.js +52 -9
  72. package/dist/commands/sessions-export.d.ts +47 -0
  73. package/dist/commands/sessions-export.js +116 -6
  74. package/dist/commands/sessions-import.d.ts +17 -0
  75. package/dist/commands/sessions-import.js +114 -6
  76. package/dist/commands/sessions-migrate.d.ts +27 -0
  77. package/dist/commands/sessions-migrate.js +50 -9
  78. package/dist/commands/sessions-picker.js +23 -4
  79. package/dist/commands/sessions-resume.d.ts +5 -3
  80. package/dist/commands/sessions-resume.js +30 -8
  81. package/dist/commands/sessions-watch.d.ts +2 -0
  82. package/dist/commands/sessions-watch.js +53 -0
  83. package/dist/commands/sessions.d.ts +66 -3
  84. package/dist/commands/sessions.js +298 -47
  85. package/dist/commands/set.d.ts +1 -1
  86. package/dist/commands/set.js +2 -2
  87. package/dist/commands/setup-browser.js +2 -2
  88. package/dist/commands/setup-mine.js +0 -1
  89. package/dist/commands/setup-preferences.js +1 -1
  90. package/dist/commands/setup-share.js +34 -4
  91. package/dist/commands/setup.d.ts +5 -0
  92. package/dist/commands/setup.js +26 -0
  93. package/dist/commands/share.d.ts +85 -0
  94. package/dist/commands/share.js +379 -8
  95. package/dist/commands/skills.js +0 -11
  96. package/dist/commands/snapshot.js +1 -1
  97. package/dist/commands/ssh.d.ts +18 -0
  98. package/dist/commands/ssh.js +549 -210
  99. package/dist/commands/sync.d.ts +5 -0
  100. package/dist/commands/sync.js +212 -32
  101. package/dist/commands/teams.d.ts +13 -0
  102. package/dist/commands/teams.js +187 -30
  103. package/dist/commands/tickets.d.ts +2 -0
  104. package/dist/commands/tickets.js +43 -0
  105. package/dist/commands/update.js +2 -4
  106. package/dist/commands/usage.js +5 -3
  107. package/dist/commands/versions.js +11 -5
  108. package/dist/commands/view.js +15 -7
  109. package/dist/commands/webhook.d.ts +2 -2
  110. package/dist/commands/webhook.js +7 -7
  111. package/dist/index.d.ts +18 -2
  112. package/dist/index.js +53 -1264
  113. package/dist/lib/account-catalog.d.ts +18 -0
  114. package/dist/lib/account-catalog.js +38 -0
  115. package/dist/lib/account-provider-registry.d.ts +18 -0
  116. package/dist/lib/account-provider-registry.js +59 -0
  117. package/dist/lib/account-registry.d.ts +40 -0
  118. package/dist/lib/account-registry.js +239 -0
  119. package/dist/lib/account-schema.d.ts +44 -0
  120. package/dist/lib/account-schema.js +91 -0
  121. package/dist/lib/account-state-service.d.ts +21 -0
  122. package/dist/lib/account-state-service.js +60 -0
  123. package/dist/lib/activity.d.ts +1 -1
  124. package/dist/lib/activity.js +8 -1
  125. package/dist/lib/add-dir.d.ts +80 -0
  126. package/dist/lib/add-dir.js +241 -0
  127. package/dist/lib/agent-cli-commands.d.ts +11 -0
  128. package/dist/lib/agent-cli-commands.js +30 -0
  129. package/dist/lib/agents.js +44 -36
  130. package/dist/lib/answer-router.js +1 -1
  131. package/dist/lib/audit/log.d.ts +10 -27
  132. package/dist/lib/audit/log.js +20 -33
  133. package/dist/lib/auth-health.d.ts +9 -2
  134. package/dist/lib/auth-health.js +42 -9
  135. package/dist/lib/auto-pull-worker.js +7 -3
  136. package/dist/lib/auto-pull.d.ts +44 -3
  137. package/dist/lib/auto-pull.js +88 -5
  138. package/dist/lib/binary-shadow.d.ts +28 -0
  139. package/dist/lib/binary-shadow.js +121 -0
  140. package/dist/lib/brand.js +9 -3
  141. package/dist/lib/browser/ipc.d.ts +30 -0
  142. package/dist/lib/browser/ipc.js +81 -4
  143. package/dist/lib/browser/profiles.d.ts +3 -2
  144. package/dist/lib/browser/profiles.js +65 -22
  145. package/dist/lib/browser/service.d.ts +4 -0
  146. package/dist/lib/browser/service.js +30 -3
  147. package/dist/lib/browser/sessions-list.d.ts +22 -2
  148. package/dist/lib/browser/sessions-list.js +54 -6
  149. package/dist/lib/browser/stream.d.ts +2 -0
  150. package/dist/lib/browser/stream.js +1 -0
  151. package/dist/lib/browser/types.d.ts +19 -0
  152. package/dist/lib/byok-usage.d.ts +9 -2
  153. package/dist/lib/byok-usage.js +133 -31
  154. package/dist/lib/cli-entry.d.ts +11 -0
  155. package/dist/lib/cli-entry.js +46 -0
  156. package/dist/lib/cloud/host.d.ts +1 -1
  157. package/dist/lib/cloud/host.js +2 -2
  158. package/dist/lib/cloud/registry.js +1 -1
  159. package/dist/lib/cloud/types.d.ts +1 -1
  160. package/dist/lib/codex-policy.d.ts +9 -1
  161. package/dist/lib/codex-policy.js +17 -2
  162. package/dist/lib/commands.d.ts +2 -0
  163. package/dist/lib/commands.js +2 -0
  164. package/dist/lib/computer/sessions-list.d.ts +150 -0
  165. package/dist/lib/computer/sessions-list.js +363 -0
  166. package/dist/lib/config-keys.d.ts +86 -0
  167. package/dist/lib/config-keys.js +193 -0
  168. package/dist/lib/config-machine-keys.d.ts +12 -0
  169. package/dist/lib/config-machine-keys.js +17 -0
  170. package/dist/lib/config-transfer.js +3 -4
  171. package/dist/lib/crabbox/cli.d.ts +2 -2
  172. package/dist/lib/crabbox/cli.js +3 -3
  173. package/dist/lib/daemon-health.d.ts +22 -0
  174. package/dist/lib/daemon-health.js +33 -3
  175. package/dist/lib/daemon-services.d.ts +50 -0
  176. package/dist/lib/daemon-services.js +147 -0
  177. package/dist/lib/daemon-ticks.d.ts +35 -66
  178. package/dist/lib/daemon-ticks.js +77 -159
  179. package/dist/lib/daemon.d.ts +72 -4
  180. package/dist/lib/daemon.js +792 -202
  181. package/dist/lib/deeplink/register.d.ts +49 -0
  182. package/dist/lib/deeplink/register.js +253 -0
  183. package/dist/lib/deeplink/url.d.ts +34 -0
  184. package/dist/lib/deeplink/url.js +78 -0
  185. package/dist/lib/device-config.d.ts +124 -29
  186. package/dist/lib/device-config.js +346 -141
  187. package/dist/lib/devices/config-migration.d.ts +42 -0
  188. package/dist/lib/devices/config-migration.js +203 -0
  189. package/dist/lib/devices/connect.js +14 -7
  190. package/dist/lib/devices/doctor-findings.d.ts +4 -1
  191. package/dist/lib/devices/doctor-findings.js +20 -1
  192. package/dist/lib/devices/harness-inventory.d.ts +11 -2
  193. package/dist/lib/devices/harness-inventory.js +0 -0
  194. package/dist/lib/devices/health.d.ts +1 -1
  195. package/dist/lib/devices/health.js +1 -1
  196. package/dist/lib/devices/pending.d.ts +22 -1
  197. package/dist/lib/devices/pending.js +67 -2
  198. package/dist/lib/devices/registry.d.ts +0 -25
  199. package/dist/lib/devices/registry.js +2 -83
  200. package/dist/lib/devices/resolve-profile.d.ts +20 -0
  201. package/dist/lib/devices/resolve-profile.js +44 -0
  202. package/dist/lib/devices/rollout-verify.d.ts +101 -0
  203. package/dist/lib/devices/rollout-verify.js +193 -0
  204. package/dist/lib/devices/ssh-config.js +10 -6
  205. package/dist/lib/event-families.d.ts +28 -0
  206. package/dist/lib/event-families.js +159 -0
  207. package/dist/lib/event-stream.d.ts +9 -1
  208. package/dist/lib/event-stream.js +26 -9
  209. package/dist/lib/events.d.ts +9 -1
  210. package/dist/lib/events.js +21 -6
  211. package/dist/lib/exec.d.ts +30 -0
  212. package/dist/lib/exec.js +220 -122
  213. package/dist/lib/feed-broadcast.d.ts +25 -0
  214. package/dist/lib/feed-broadcast.js +33 -0
  215. package/dist/lib/feed.d.ts +1 -1
  216. package/dist/lib/feed.js +12 -2
  217. package/dist/lib/fleet/capture.js +15 -0
  218. package/dist/lib/fleet/manifest.js +9 -0
  219. package/dist/lib/fleet/types.d.ts +9 -0
  220. package/dist/lib/fleet-status.js +10 -8
  221. package/dist/lib/git.d.ts +20 -6
  222. package/dist/lib/git.js +121 -17
  223. package/dist/lib/hosts/dispatch.d.ts +8 -3
  224. package/dist/lib/hosts/dispatch.js +29 -3
  225. package/dist/lib/hosts/logs.d.ts +2 -2
  226. package/dist/lib/hosts/logs.js +2 -2
  227. package/dist/lib/hosts/option.js +1 -1
  228. package/dist/lib/hosts/passthrough.d.ts +2 -3
  229. package/dist/lib/hosts/passthrough.js +10 -24
  230. package/dist/lib/hosts/progress.js +2 -2
  231. package/dist/lib/hosts/providers/devices.d.ts +3 -3
  232. package/dist/lib/hosts/providers/devices.js +18 -12
  233. package/dist/lib/hosts/ready.d.ts +5 -1
  234. package/dist/lib/hosts/ready.js +9 -3
  235. package/dist/lib/hosts/reconcile.d.ts +2 -2
  236. package/dist/lib/hosts/reconcile.js +2 -2
  237. package/dist/lib/hosts/registry.js +14 -9
  238. package/dist/lib/hosts/remote-cmd.js +1 -1
  239. package/dist/lib/hosts/remote-os.d.ts +9 -6
  240. package/dist/lib/hosts/remote-os.js +13 -6
  241. package/dist/lib/hosts/routing-flag.d.ts +23 -0
  242. package/dist/lib/hosts/routing-flag.js +41 -0
  243. package/dist/lib/hosts/run-target.js +1 -1
  244. package/dist/lib/hosts/session-index.js +1 -1
  245. package/dist/lib/hosts/tasks.d.ts +6 -6
  246. package/dist/lib/hosts/tasks.js +4 -4
  247. package/dist/lib/hosts/types.js +1 -2
  248. package/dist/lib/installations/resolve.js +2 -8
  249. package/dist/lib/isolation-boundary-report.js +0 -1
  250. package/dist/lib/linear-cache.d.ts +7 -0
  251. package/dist/lib/linear-cache.js +31 -4
  252. package/dist/lib/linear-project-counts.d.ts +1 -1
  253. package/dist/lib/linear-project-counts.js +2 -3
  254. package/dist/lib/linear-projects.js +1 -1
  255. package/dist/lib/loop.d.ts +2 -2
  256. package/dist/lib/loop.js +1 -1
  257. package/dist/lib/mailbox-target.d.ts +1 -1
  258. package/dist/lib/mailbox-target.js +1 -1
  259. package/dist/lib/manifest.js +7 -4
  260. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  261. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  262. package/dist/lib/menubar/snapshot.d.ts +3 -2
  263. package/dist/lib/menubar/snapshot.js +6 -2
  264. package/dist/lib/migrate-fold.d.ts +33 -0
  265. package/dist/lib/migrate-fold.js +130 -0
  266. package/dist/lib/migrate.d.ts +34 -34
  267. package/dist/lib/migrate.js +106 -128
  268. package/dist/lib/model-tier-overrides.d.ts +1 -1
  269. package/dist/lib/model-tier-overrides.js +15 -2
  270. package/dist/lib/monitors/config.d.ts +17 -3
  271. package/dist/lib/monitors/config.js +52 -18
  272. package/dist/lib/monitors/engine.d.ts +32 -1
  273. package/dist/lib/monitors/engine.js +94 -11
  274. package/dist/lib/monitors/fingerprint.d.ts +46 -0
  275. package/dist/lib/monitors/fingerprint.js +100 -0
  276. package/dist/lib/monitors/remote.d.ts +47 -0
  277. package/dist/lib/monitors/remote.js +81 -0
  278. package/dist/lib/monitors/state.d.ts +39 -0
  279. package/dist/lib/monitors/state.js +56 -0
  280. package/dist/lib/onepassword.d.ts +17 -0
  281. package/dist/lib/onepassword.js +52 -22
  282. package/dist/lib/open-url.js +1 -1
  283. package/dist/lib/picker.d.ts +14 -2
  284. package/dist/lib/picker.js +35 -13
  285. package/dist/lib/placement.d.ts +1 -1
  286. package/dist/lib/placement.js +1 -1
  287. package/dist/lib/pr-land-detach.d.ts +32 -0
  288. package/dist/lib/pr-land-detach.js +79 -0
  289. package/dist/lib/profiles-presets.js +13 -0
  290. package/dist/lib/profiles.d.ts +2 -0
  291. package/dist/lib/profiles.js +44 -1
  292. package/dist/lib/project-focus.d.ts +1 -1
  293. package/dist/lib/project-focus.js +1 -1
  294. package/dist/lib/project-key.d.ts +17 -0
  295. package/dist/lib/project-key.js +26 -0
  296. package/dist/lib/project-probe.d.ts +4 -1
  297. package/dist/lib/project-probe.js +5 -4
  298. package/dist/lib/project-resources.js +2 -18
  299. package/dist/lib/project-root.d.ts +16 -0
  300. package/dist/lib/project-root.js +20 -2
  301. package/dist/lib/projects.d.ts +20 -1
  302. package/dist/lib/projects.js +78 -1
  303. package/dist/lib/refresh-coordinator.d.ts +24 -0
  304. package/dist/lib/refresh-coordinator.js +52 -0
  305. package/dist/lib/registry.d.ts +2 -2
  306. package/dist/lib/registry.js +1 -1
  307. package/dist/lib/resource-aliases.d.ts +13 -0
  308. package/dist/lib/resource-aliases.js +26 -0
  309. package/dist/lib/resources/types.d.ts +1 -1
  310. package/dist/lib/resources.d.ts +16 -0
  311. package/dist/lib/resources.js +66 -10
  312. package/dist/lib/rotate.d.ts +3 -4
  313. package/dist/lib/rotate.js +4 -5
  314. package/dist/lib/routine-activation.d.ts +22 -2
  315. package/dist/lib/routine-activation.js +63 -16
  316. package/dist/lib/routine-context.d.ts +9 -2
  317. package/dist/lib/routine-context.js +21 -6
  318. package/dist/lib/routines-project.d.ts +58 -48
  319. package/dist/lib/routines-project.js +190 -159
  320. package/dist/lib/routines.d.ts +41 -6
  321. package/dist/lib/routines.js +92 -34
  322. package/dist/lib/run-defaults.d.ts +5 -0
  323. package/dist/lib/run-defaults.js +11 -1
  324. package/dist/lib/runner.d.ts +10 -8
  325. package/dist/lib/runner.js +122 -39
  326. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  327. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  328. package/dist/lib/secrets/agent.d.ts +10 -3
  329. package/dist/lib/secrets/agent.js +43 -8
  330. package/dist/lib/secrets/bundles.d.ts +1 -0
  331. package/dist/lib/secrets/bundles.js +92 -80
  332. package/dist/lib/secrets/index.js +32 -9
  333. package/dist/lib/secrets/install-helper.d.ts +4 -4
  334. package/dist/lib/secrets/install-helper.js +4 -4
  335. package/dist/lib/secrets/push.d.ts +40 -6
  336. package/dist/lib/secrets/push.js +58 -11
  337. package/dist/lib/secrets/read-backoff.d.ts +1 -1
  338. package/dist/lib/secrets/read-backoff.js +1 -1
  339. package/dist/lib/secrets/remote.d.ts +24 -0
  340. package/dist/lib/secrets/remote.js +54 -4
  341. package/dist/lib/self-update.d.ts +108 -0
  342. package/dist/lib/self-update.js +276 -1
  343. package/dist/lib/session/active.d.ts +89 -5
  344. package/dist/lib/session/active.js +165 -10
  345. package/dist/lib/session/actor-sidecar.d.ts +1 -1
  346. package/dist/lib/session/actor-sidecar.js +2 -1
  347. package/dist/lib/session/db.d.ts +176 -2
  348. package/dist/lib/session/db.js +484 -17
  349. package/dist/lib/session/discover.js +27 -4
  350. package/dist/lib/session/hook-sessions.js +2 -2
  351. package/dist/lib/session/host-link.d.ts +2 -2
  352. package/dist/lib/session/host-link.js +2 -2
  353. package/dist/lib/session/pid-registry.d.ts +21 -0
  354. package/dist/lib/session/pid-registry.js +57 -0
  355. package/dist/lib/session/remote-active.js +15 -1
  356. package/dist/lib/session/remote.js +2 -2
  357. package/dist/lib/session/session-cache.d.ts +14 -7
  358. package/dist/lib/session/session-cache.js +51 -9
  359. package/dist/lib/session/state.d.ts +2 -2
  360. package/dist/lib/session/state.js +1 -1
  361. package/dist/lib/session/sync/config.d.ts +10 -10
  362. package/dist/lib/session/sync/config.js +10 -10
  363. package/dist/lib/session/sync/r2.d.ts +34 -0
  364. package/dist/lib/session/sync/r2.js +123 -0
  365. package/dist/lib/session/throughput.d.ts +1 -1
  366. package/dist/lib/session/throughput.js +1 -1
  367. package/dist/lib/session/types.d.ts +23 -1
  368. package/dist/lib/session/types.js +15 -0
  369. package/dist/lib/session/viewing-in.d.ts +1 -1
  370. package/dist/lib/session/viewing-in.js +1 -1
  371. package/dist/lib/session/watch.d.ts +101 -0
  372. package/dist/lib/session/watch.js +242 -0
  373. package/dist/lib/share/config.d.ts +4 -0
  374. package/dist/lib/share/config.js +1 -0
  375. package/dist/lib/share/delete.d.ts +93 -0
  376. package/dist/lib/share/delete.js +127 -0
  377. package/dist/lib/share/provision.d.ts +38 -0
  378. package/dist/lib/share/provision.js +50 -0
  379. package/dist/lib/share/publish.d.ts +40 -1
  380. package/dist/lib/share/publish.js +116 -3
  381. package/dist/lib/share/worker-template.js +71 -6
  382. package/dist/lib/shims.d.ts +17 -3
  383. package/dist/lib/shims.js +136 -27
  384. package/dist/lib/signin-badge.js +3 -2
  385. package/dist/lib/skills.js +2 -0
  386. package/dist/lib/smart-launch.d.ts +8 -8
  387. package/dist/lib/smart-launch.js +80 -59
  388. package/dist/lib/ssh-exec.d.ts +1 -1
  389. package/dist/lib/ssh-exec.js +1 -1
  390. package/dist/lib/staleness/prune.d.ts +88 -0
  391. package/dist/lib/staleness/prune.js +69 -0
  392. package/dist/lib/staleness/registry.d.ts +1 -1
  393. package/dist/lib/staleness/writers/commands.js +34 -2
  394. package/dist/lib/staleness/writers/hooks.js +16 -0
  395. package/dist/lib/staleness/writers/kinds.d.ts +6 -0
  396. package/dist/lib/staleness/writers/skills.js +19 -0
  397. package/dist/lib/staleness/writers/subagents.d.ts +2 -3
  398. package/dist/lib/staleness/writers/subagents.js +0 -4
  399. package/dist/lib/staleness/writers/types.d.ts +32 -0
  400. package/dist/lib/startup/command-registry.d.ts +6 -12
  401. package/dist/lib/startup/command-registry.js +14 -31
  402. package/dist/lib/startup/dev-build.d.ts +10 -0
  403. package/dist/lib/startup/dev-build.js +13 -1
  404. package/dist/lib/startup/spellcheck.d.ts +18 -0
  405. package/dist/lib/startup/spellcheck.js +45 -0
  406. package/dist/lib/state.d.ts +36 -9
  407. package/dist/lib/state.js +96 -46
  408. package/dist/lib/subagents-registry.d.ts +0 -7
  409. package/dist/lib/subagents-registry.js +38 -65
  410. package/dist/lib/subagents.d.ts +0 -33
  411. package/dist/lib/subagents.js +0 -75
  412. package/dist/lib/sync-umbrella.js +1 -1
  413. package/dist/lib/teams/agents.d.ts +41 -1
  414. package/dist/lib/teams/agents.js +187 -9
  415. package/dist/lib/teams/api.d.ts +11 -1
  416. package/dist/lib/teams/api.js +11 -2
  417. package/dist/lib/teams/delivery.d.ts +41 -0
  418. package/dist/lib/teams/delivery.js +60 -0
  419. package/dist/lib/teams/registry.d.ts +14 -0
  420. package/dist/lib/teams/registry.js +51 -1
  421. package/dist/lib/teams/remoteWorktree.d.ts +19 -0
  422. package/dist/lib/teams/remoteWorktree.js +29 -0
  423. package/dist/lib/teams/scheduler.d.ts +1 -1
  424. package/dist/lib/teams/scheduler.js +1 -1
  425. package/dist/lib/teams/worktree.d.ts +24 -0
  426. package/dist/lib/teams/worktree.js +42 -0
  427. package/dist/lib/terminal/backends/vscodium-agent.d.ts +10 -1
  428. package/dist/lib/terminal/backends/vscodium-agent.js +16 -5
  429. package/dist/lib/terminal/engine.d.ts +4 -0
  430. package/dist/lib/terminal/engine.js +8 -2
  431. package/dist/lib/terminal/types.d.ts +21 -2
  432. package/dist/lib/testdata/refresh-coordinator-worker.d.ts +1 -0
  433. package/dist/lib/testdata/refresh-coordinator-worker.js +23 -0
  434. package/dist/lib/tickets/list.d.ts +53 -0
  435. package/dist/lib/tickets/list.js +153 -0
  436. package/dist/lib/tmux/orphan-reap.d.ts +320 -0
  437. package/dist/lib/tmux/orphan-reap.js +644 -0
  438. package/dist/lib/tmux/session.d.ts +68 -3
  439. package/dist/lib/tmux/session.js +95 -5
  440. package/dist/lib/triggers/handlers.d.ts +20 -0
  441. package/dist/lib/triggers/handlers.js +6 -1
  442. package/dist/lib/types.d.ts +46 -34
  443. package/dist/lib/usage-fleet.d.ts +32 -0
  444. package/dist/lib/usage-fleet.js +125 -0
  445. package/dist/lib/usage-refresh.d.ts +3 -3
  446. package/dist/lib/usage-refresh.js +19 -16
  447. package/dist/lib/usage.d.ts +51 -47
  448. package/dist/lib/usage.js +145 -153
  449. package/dist/lib/version-duplicates.js +2 -2
  450. package/dist/lib/versions.d.ts +56 -13
  451. package/dist/lib/versions.js +195 -45
  452. package/dist/lib/watchdog/log.d.ts +1 -1
  453. package/dist/lib/watchdog/log.js +3 -3
  454. package/dist/lib/watchdog/rotate.d.ts +6 -6
  455. package/dist/lib/watchdog/rotate.js +6 -6
  456. package/dist/lib/workflows.d.ts +1 -1
  457. package/dist/lib/yaml-io.d.ts +47 -0
  458. package/dist/lib/yaml-io.js +55 -0
  459. package/package.json +2 -1
  460. package/scripts/install-helper.js +2 -2
  461. package/scripts/postinstall.js +23 -20
  462. package/dist/commands/defaults.d.ts +0 -7
  463. package/dist/commands/defaults.js +0 -107
  464. package/dist/commands/export.d.ts +0 -11
  465. package/dist/commands/export.js +0 -215
  466. package/dist/commands/helper.d.ts +0 -12
  467. package/dist/commands/helper.js +0 -87
  468. package/dist/commands/hosts.d.ts +0 -11
  469. package/dist/commands/hosts.js +0 -330
  470. package/dist/commands/lock.d.ts +0 -12
  471. package/dist/commands/lock.js +0 -70
  472. package/dist/commands/pull.d.ts +0 -17
  473. package/dist/commands/pull.js +0 -39
  474. package/dist/commands/push.d.ts +0 -14
  475. package/dist/commands/push.js +0 -30
  476. package/dist/commands/wallet.d.ts +0 -20
  477. package/dist/commands/wallet.js +0 -216
  478. package/dist/commands/worktree.d.ts +0 -19
  479. package/dist/commands/worktree.js +0 -272
  480. package/dist/lib/account-labels.d.ts +0 -24
  481. package/dist/lib/account-labels.js +0 -72
  482. package/dist/lib/auto-dispatch-linear.d.ts +0 -18
  483. package/dist/lib/auto-dispatch-linear.js +0 -107
  484. package/dist/lib/auto-dispatch-provider.d.ts +0 -10
  485. package/dist/lib/auto-dispatch-provider.js +0 -30
  486. package/dist/lib/auto-dispatch.d.ts +0 -93
  487. package/dist/lib/auto-dispatch.js +0 -128
  488. package/dist/lib/export.d.ts +0 -72
  489. package/dist/lib/export.js +0 -269
  490. package/dist/lib/lock.d.ts +0 -93
  491. package/dist/lib/lock.js +0 -207
  492. package/dist/lib/wallet/index.d.ts +0 -78
  493. package/dist/lib/wallet/index.js +0 -253
@@ -3,6 +3,7 @@
3
3
  // lifecycle, uploads the Worker (with an R2 binding), sets the WRITE_TOKEN secret,
4
4
  // enables the free `*.workers.dev` subdomain, and — when the token owns the zone —
5
5
  // maps a custom domain.
6
+ import { createHash } from 'node:crypto';
6
7
  const CF_API = 'https://api.cloudflare.com/client/v4';
7
8
  export const SHARE_LIFECYCLE_RULE_ID = 'agents-share-expire-objects';
8
9
  export const SHARE_LIFECYCLE_RETENTION_DAYS = 366;
@@ -95,6 +96,55 @@ export async function deployWorker(apiToken, accountId, workerName, script, buck
95
96
  form,
96
97
  });
97
98
  }
99
+ /** sha256 of the rendered Worker script, so a deployed endpoint can be compared
100
+ * against the current `worker-template.ts` without redeploying to find out. */
101
+ export function hashWorkerScript(script) {
102
+ return createHash('sha256').update(script, 'utf8').digest('hex');
103
+ }
104
+ /**
105
+ * Re-deploy the Worker script against an ALREADY-provisioned endpoint (same
106
+ * account/worker/bucket `deployWorker` was first called with) and idempotently
107
+ * no-op when the template hasn't changed.
108
+ *
109
+ * Cloudflare's script-upload endpoint (`deployWorker`, above) replaces the
110
+ * Worker's bindings/secrets wholesale on every call — there is no documented,
111
+ * reliable way to tell it "keep the existing secret" (the `keep_bindings`
112
+ * metadata field some third-party guides mention is absent from Cloudflare's
113
+ * current Multipart upload metadata reference, and the community has reported
114
+ * it not preventing binding loss even when present:
115
+ * https://developers.cloudflare.com/workers/configuration/multipart-upload-metadata/,
116
+ * https://community.cloudflare.com/t/upload-worker-module-endpoint-removes-existing-bindings-despite-keep-bindings/766447).
117
+ * So instead this immediately re-applies WRITE_TOKEN via the documented Secrets
118
+ * API right after the upload — the same two-call sequence first-time
119
+ * provisioning already uses (`deployWorker` then `setWorkerSecret`), except
120
+ * `writeToken` here is the caller's EXISTING token, never a freshly generated
121
+ * one. Cloudflare's own docs describe exactly this "secrets survive a
122
+ * subsequent write" contract for the sibling `wrangler versions upload
123
+ * --secrets-file` flow ("Secrets not included in the file are preserved from
124
+ * the previous version" —
125
+ * https://developers.cloudflare.com/workers/configuration/secrets/#upload-secrets-alongside-code);
126
+ * re-setting the secret to its own value after every deploy gets the same
127
+ * outcome without depending on an unverified upload-time flag.
128
+ */
129
+ export async function updateWorker(apiToken, accountId, workerName, bucketName, script, writeToken, previousHash, opts = {}) {
130
+ const templateHash = hashWorkerScript(script);
131
+ if (!opts.force && previousHash === templateHash) {
132
+ return { templateHash, skipped: true };
133
+ }
134
+ await deployWorker(apiToken, accountId, workerName, script, bucketName, opts);
135
+ // Script upload clears bindings/secrets (see JSDoc above). If re-applying
136
+ // WRITE_TOKEN fails here, the live Worker has no write token — every
137
+ // `agents share` publish/delete 401s until a re-run of `agents share update`
138
+ // completes both steps. Surface that explicitly instead of the raw CF error.
139
+ try {
140
+ await setWorkerSecret(apiToken, accountId, workerName, writeToken, opts);
141
+ }
142
+ catch (e) {
143
+ const detail = e instanceof Error ? e.message : String(e);
144
+ throw new Error(`Worker deployed but the write token failed to re-apply — re-run \`agents share update\` to fix this before publishing/deleting anything. (${detail})`);
145
+ }
146
+ return { templateHash, skipped: false };
147
+ }
98
148
  /** Add/update the WRITE_TOKEN binding using Cloudflare's Workers Secrets API. */
99
149
  export async function setWorkerSecret(apiToken, accountId, workerName, writeToken, opts = {}) {
100
150
  const request = opts.request ?? defaultCloudflareRequester;
@@ -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 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. */
@@ -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) {
@@ -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`,
@@ -212,5 +320,10 @@ export async function publishToEndpoint(filePath, endpoint, opts = {}) {
212
320
  if (!r.ok) {
213
321
  throw new Error(`Publish failed (${r.status}) for ${pageUrl}. Check the write token, or that 'agents share 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
  }
@@ -7,7 +7,12 @@
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 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
  //
@@ -35,22 +40,41 @@ export default {
35
40
  return json({ error: 'unauthorized' }, 401);
36
41
  }
37
42
  const expiresAt = request.headers.get('x-share-expires-at') || '';
43
+ // 'unlisted' hides the page from the public gallery + JSON listing while
44
+ // keeping the direct URL world-readable (capability URL, not secret).
45
+ const visibility = (request.headers.get('x-share-visibility') || '').toLowerCase();
38
46
  const contentType = request.headers.get('content-type') || 'text/html; charset=utf-8';
47
+ const customMetadata = {};
48
+ if (expiresAt) customMetadata['expires-at'] = expiresAt;
49
+ if (visibility === 'unlisted') customMetadata['visibility'] = 'unlisted';
39
50
  await env.BUCKET.put(path, request.body, {
40
51
  httpMetadata: { contentType },
41
- customMetadata: expiresAt ? { 'expires-at': expiresAt } : {},
52
+ customMetadata,
42
53
  });
43
- return json({ ok: true, url: url.origin + '/' + path, expiresAt: expiresAt || null }, 200);
54
+ return json({ ok: true, url: url.origin + '/' + path, expiresAt: expiresAt || null, unlisted: visibility === 'unlisted' }, 200);
44
55
  }
45
56
 
46
57
  if (request.method === 'GET' || request.method === 'HEAD') {
47
- // Single-segment path may be a user gallery OR a legacy flat slug.
58
+ // Single-segment path may be a user gallery/listing OR a legacy flat slug.
59
+ // The disambiguator is whether the <seg>/ prefix holds any object: only a
60
+ // genuine per-user namespace does. BOTH the HTML gallery and the
61
+ // machine-readable listing gate on it, so ?format=json on a legacy flat
62
+ // slug (an object stored at the bare key, before per-user namespaces) does
63
+ // NOT hijack it into a fake empty listing — it falls through to the object
64
+ // GET below and serves its real content, exactly as before.
48
65
  const segments = path.split('/').filter(Boolean);
49
66
  if (segments.length === 1) {
50
67
  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);
68
+ const isNamespace = list.objects && list.objects.length > 0;
69
+ if (isNamespace) {
70
+ return url.searchParams.get('format') === 'json'
71
+ ? renderListing(env.BUCKET, url.origin, segments[0], request.method)
72
+ : renderGallery(env.BUCKET, url.origin, segments[0], request.method);
53
73
  }
74
+ // Not a namespace: fall through. A legacy flat-slug object resolves to its
75
+ // real content; anything else 404s (an empty/nonexistent namespace, which
76
+ // agents share list reads as "nothing published" via the template-hash
77
+ // signal rather than a missing route).
54
78
  }
55
79
 
56
80
  const obj = await env.BUCKET.get(path);
@@ -90,6 +114,8 @@ async function renderGallery(bucket, origin, user, method) {
90
114
 
91
115
  const activeObjects = objects.filter(o => {
92
116
  if (o.key.endsWith('.png')) return false;
117
+ // Unlisted pages are reachable by direct URL only — never on the gallery.
118
+ if (o.customMetadata && o.customMetadata.visibility === 'unlisted') return false;
93
119
  const expiresAt = o.customMetadata && o.customMetadata['expires-at'];
94
120
  return !(expiresAt && Date.now() > Date.parse(expiresAt));
95
121
  });
@@ -124,6 +150,45 @@ async function renderGallery(bucket, origin, user, method) {
124
150
  return new Response(html, { status: 200, headers: { 'content-type': 'text/html; charset=utf-8', 'cache-control': 'public, max-age=60' } });
125
151
  }
126
152
 
153
+ async function renderListing(bucket, origin, user, method) {
154
+ const objects = [];
155
+ let cursor;
156
+ do {
157
+ const list = await bucket.list({ prefix: user + '/', limit: 1000, cursor, include: ['httpMetadata', 'customMetadata'] });
158
+ objects.push(...(list.objects || []));
159
+ cursor = list.truncated ? list.cursor : undefined;
160
+ } while (cursor);
161
+
162
+ const now = Date.now();
163
+ const items = objects
164
+ .filter(o => {
165
+ // Mirror the gallery: hide sibling .png OG covers, expired pages, and
166
+ // unlisted pages — the listing is the machine-readable public surface.
167
+ if (o.key.endsWith('.png')) return false;
168
+ if (o.customMetadata && o.customMetadata.visibility === 'unlisted') return false;
169
+ const expiresAt = o.customMetadata && o.customMetadata['expires-at'];
170
+ return !(expiresAt && now > Date.parse(expiresAt));
171
+ })
172
+ .map(o => ({
173
+ slug: o.key.slice(o.key.indexOf('/') + 1),
174
+ url: origin + '/' + o.key,
175
+ size: typeof o.size === 'number' ? o.size : 0,
176
+ contentType: (o.httpMetadata && o.httpMetadata.contentType) || null,
177
+ publishedAt: new Date(o.uploaded).toISOString(),
178
+ expiresAt: (o.customMetadata && o.customMetadata['expires-at']) || null,
179
+ }));
180
+ // Newest first, so the human table and any script reads the freshest share top.
181
+ items.sort((a, b) => (a.publishedAt < b.publishedAt ? 1 : a.publishedAt > b.publishedAt ? -1 : 0));
182
+
183
+ if (method === 'HEAD') {
184
+ return new Response(null, { status: 200, headers: { 'content-type': 'application/json; charset=utf-8' } });
185
+ }
186
+ return new Response(JSON.stringify({ user, count: items.length, objects: items }), {
187
+ status: 200,
188
+ headers: { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'public, max-age=30' },
189
+ });
190
+ }
191
+
127
192
  function escapeHtml(s) {
128
193
  return String(s)
129
194
  .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).