@phnx-labs/agents-cli 1.22.35 → 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 (487) hide show
  1. package/CHANGELOG.md +666 -2
  2. package/README.md +75 -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 +67 -0
  94. package/dist/commands/share.js +275 -12
  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/commands.d.ts +2 -0
  161. package/dist/lib/commands.js +2 -0
  162. package/dist/lib/computer/sessions-list.d.ts +150 -0
  163. package/dist/lib/computer/sessions-list.js +363 -0
  164. package/dist/lib/config-keys.d.ts +86 -0
  165. package/dist/lib/config-keys.js +193 -0
  166. package/dist/lib/config-machine-keys.d.ts +12 -0
  167. package/dist/lib/config-machine-keys.js +17 -0
  168. package/dist/lib/config-transfer.js +3 -4
  169. package/dist/lib/crabbox/cli.d.ts +2 -2
  170. package/dist/lib/crabbox/cli.js +3 -3
  171. package/dist/lib/daemon-health.d.ts +22 -0
  172. package/dist/lib/daemon-health.js +33 -3
  173. package/dist/lib/daemon-services.d.ts +50 -0
  174. package/dist/lib/daemon-services.js +147 -0
  175. package/dist/lib/daemon-ticks.d.ts +35 -66
  176. package/dist/lib/daemon-ticks.js +77 -159
  177. package/dist/lib/daemon.d.ts +72 -4
  178. package/dist/lib/daemon.js +792 -202
  179. package/dist/lib/deeplink/register.d.ts +49 -0
  180. package/dist/lib/deeplink/register.js +253 -0
  181. package/dist/lib/deeplink/url.d.ts +34 -0
  182. package/dist/lib/deeplink/url.js +78 -0
  183. package/dist/lib/device-config.d.ts +124 -29
  184. package/dist/lib/device-config.js +346 -141
  185. package/dist/lib/devices/config-migration.d.ts +42 -0
  186. package/dist/lib/devices/config-migration.js +203 -0
  187. package/dist/lib/devices/connect.js +14 -7
  188. package/dist/lib/devices/doctor-findings.d.ts +4 -1
  189. package/dist/lib/devices/doctor-findings.js +20 -1
  190. package/dist/lib/devices/harness-inventory.d.ts +11 -2
  191. package/dist/lib/devices/harness-inventory.js +0 -0
  192. package/dist/lib/devices/health.d.ts +1 -1
  193. package/dist/lib/devices/health.js +1 -1
  194. package/dist/lib/devices/pending.d.ts +22 -1
  195. package/dist/lib/devices/pending.js +67 -2
  196. package/dist/lib/devices/registry.d.ts +0 -25
  197. package/dist/lib/devices/registry.js +2 -83
  198. package/dist/lib/devices/resolve-profile.d.ts +20 -0
  199. package/dist/lib/devices/resolve-profile.js +44 -0
  200. package/dist/lib/devices/rollout-verify.d.ts +101 -0
  201. package/dist/lib/devices/rollout-verify.js +193 -0
  202. package/dist/lib/devices/ssh-config.js +10 -6
  203. package/dist/lib/event-families.d.ts +28 -0
  204. package/dist/lib/event-families.js +159 -0
  205. package/dist/lib/event-stream.d.ts +9 -1
  206. package/dist/lib/event-stream.js +26 -9
  207. package/dist/lib/events.d.ts +9 -1
  208. package/dist/lib/events.js +21 -6
  209. package/dist/lib/exec.d.ts +30 -0
  210. package/dist/lib/exec.js +219 -121
  211. package/dist/lib/feed-broadcast.d.ts +25 -0
  212. package/dist/lib/feed-broadcast.js +33 -0
  213. package/dist/lib/feed.d.ts +1 -1
  214. package/dist/lib/feed.js +12 -2
  215. package/dist/lib/fleet/capture.js +15 -0
  216. package/dist/lib/fleet/manifest.js +9 -0
  217. package/dist/lib/fleet/types.d.ts +9 -0
  218. package/dist/lib/fleet-status.js +10 -8
  219. package/dist/lib/git.d.ts +20 -6
  220. package/dist/lib/git.js +121 -17
  221. package/dist/lib/hosts/dispatch.d.ts +8 -3
  222. package/dist/lib/hosts/dispatch.js +29 -3
  223. package/dist/lib/hosts/logs.d.ts +2 -2
  224. package/dist/lib/hosts/logs.js +2 -2
  225. package/dist/lib/hosts/option.js +1 -1
  226. package/dist/lib/hosts/passthrough.d.ts +2 -3
  227. package/dist/lib/hosts/passthrough.js +10 -24
  228. package/dist/lib/hosts/progress.js +2 -2
  229. package/dist/lib/hosts/providers/devices.d.ts +3 -3
  230. package/dist/lib/hosts/providers/devices.js +18 -12
  231. package/dist/lib/hosts/ready.d.ts +5 -1
  232. package/dist/lib/hosts/ready.js +9 -3
  233. package/dist/lib/hosts/reconcile.d.ts +2 -2
  234. package/dist/lib/hosts/reconcile.js +2 -2
  235. package/dist/lib/hosts/registry.js +14 -9
  236. package/dist/lib/hosts/remote-cmd.js +1 -1
  237. package/dist/lib/hosts/remote-os.d.ts +9 -6
  238. package/dist/lib/hosts/remote-os.js +13 -6
  239. package/dist/lib/hosts/routing-flag.d.ts +23 -0
  240. package/dist/lib/hosts/routing-flag.js +41 -0
  241. package/dist/lib/hosts/run-target.js +1 -1
  242. package/dist/lib/hosts/session-index.js +1 -1
  243. package/dist/lib/hosts/tasks.d.ts +6 -6
  244. package/dist/lib/hosts/tasks.js +4 -4
  245. package/dist/lib/hosts/types.js +1 -2
  246. package/dist/lib/installations/resolve.js +2 -8
  247. package/dist/lib/isolation-boundary-report.js +0 -1
  248. package/dist/lib/linear-cache.d.ts +7 -0
  249. package/dist/lib/linear-cache.js +31 -4
  250. package/dist/lib/linear-project-counts.d.ts +1 -1
  251. package/dist/lib/linear-project-counts.js +2 -3
  252. package/dist/lib/linear-projects.js +1 -1
  253. package/dist/lib/loop.d.ts +2 -2
  254. package/dist/lib/loop.js +1 -1
  255. package/dist/lib/mailbox-target.d.ts +1 -1
  256. package/dist/lib/mailbox-target.js +1 -1
  257. package/dist/lib/manifest.js +7 -4
  258. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  259. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  260. package/dist/lib/menubar/snapshot.d.ts +3 -2
  261. package/dist/lib/menubar/snapshot.js +6 -2
  262. package/dist/lib/migrate-fold.d.ts +33 -0
  263. package/dist/lib/migrate-fold.js +130 -0
  264. package/dist/lib/migrate.d.ts +34 -34
  265. package/dist/lib/migrate.js +106 -128
  266. package/dist/lib/model-tier-overrides.d.ts +1 -1
  267. package/dist/lib/model-tier-overrides.js +15 -2
  268. package/dist/lib/monitors/config.d.ts +17 -3
  269. package/dist/lib/monitors/config.js +52 -18
  270. package/dist/lib/monitors/engine.d.ts +32 -1
  271. package/dist/lib/monitors/engine.js +94 -11
  272. package/dist/lib/monitors/fingerprint.d.ts +46 -0
  273. package/dist/lib/monitors/fingerprint.js +100 -0
  274. package/dist/lib/monitors/remote.d.ts +47 -0
  275. package/dist/lib/monitors/remote.js +81 -0
  276. package/dist/lib/monitors/state.d.ts +39 -0
  277. package/dist/lib/monitors/state.js +56 -0
  278. package/dist/lib/onepassword.d.ts +17 -0
  279. package/dist/lib/onepassword.js +52 -22
  280. package/dist/lib/open-url.js +1 -1
  281. package/dist/lib/picker.d.ts +14 -2
  282. package/dist/lib/picker.js +35 -13
  283. package/dist/lib/placement.d.ts +1 -1
  284. package/dist/lib/placement.js +1 -1
  285. package/dist/lib/pr-land-detach.d.ts +32 -0
  286. package/dist/lib/pr-land-detach.js +79 -0
  287. package/dist/lib/profiles-presets.js +13 -0
  288. package/dist/lib/profiles.d.ts +2 -0
  289. package/dist/lib/profiles.js +44 -1
  290. package/dist/lib/project-focus.d.ts +1 -1
  291. package/dist/lib/project-focus.js +1 -1
  292. package/dist/lib/project-probe.d.ts +4 -1
  293. package/dist/lib/project-probe.js +5 -4
  294. package/dist/lib/project-resources.js +2 -18
  295. package/dist/lib/project-root.d.ts +16 -0
  296. package/dist/lib/project-root.js +20 -2
  297. package/dist/lib/projects.d.ts +20 -1
  298. package/dist/lib/projects.js +78 -1
  299. package/dist/lib/refresh-coordinator.d.ts +24 -0
  300. package/dist/lib/refresh-coordinator.js +52 -0
  301. package/dist/lib/registry.d.ts +2 -2
  302. package/dist/lib/registry.js +1 -1
  303. package/dist/lib/resource-aliases.d.ts +13 -0
  304. package/dist/lib/resource-aliases.js +26 -0
  305. package/dist/lib/resources/types.d.ts +1 -1
  306. package/dist/lib/resources.d.ts +16 -0
  307. package/dist/lib/resources.js +66 -10
  308. package/dist/lib/rotate.d.ts +3 -4
  309. package/dist/lib/rotate.js +4 -5
  310. package/dist/lib/routine-activation.d.ts +22 -2
  311. package/dist/lib/routine-activation.js +63 -16
  312. package/dist/lib/routine-context.d.ts +9 -2
  313. package/dist/lib/routine-context.js +21 -6
  314. package/dist/lib/routines-project.d.ts +58 -48
  315. package/dist/lib/routines-project.js +190 -159
  316. package/dist/lib/routines.d.ts +41 -6
  317. package/dist/lib/routines.js +92 -34
  318. package/dist/lib/run-defaults.d.ts +5 -0
  319. package/dist/lib/run-defaults.js +11 -1
  320. package/dist/lib/runner.d.ts +10 -8
  321. package/dist/lib/runner.js +122 -39
  322. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  323. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  324. package/dist/lib/secrets/agent.d.ts +10 -3
  325. package/dist/lib/secrets/agent.js +43 -8
  326. package/dist/lib/secrets/bundles.d.ts +1 -0
  327. package/dist/lib/secrets/bundles.js +92 -80
  328. package/dist/lib/secrets/index.js +32 -9
  329. package/dist/lib/secrets/install-helper.d.ts +4 -4
  330. package/dist/lib/secrets/install-helper.js +4 -4
  331. package/dist/lib/secrets/push.d.ts +40 -6
  332. package/dist/lib/secrets/push.js +58 -11
  333. package/dist/lib/secrets/read-backoff.d.ts +1 -1
  334. package/dist/lib/secrets/read-backoff.js +1 -1
  335. package/dist/lib/secrets/remote.d.ts +24 -0
  336. package/dist/lib/secrets/remote.js +54 -4
  337. package/dist/lib/self-update.d.ts +108 -0
  338. package/dist/lib/self-update.js +276 -1
  339. package/dist/lib/session/active.d.ts +89 -5
  340. package/dist/lib/session/active.js +165 -10
  341. package/dist/lib/session/actor-sidecar.d.ts +1 -1
  342. package/dist/lib/session/actor-sidecar.js +2 -1
  343. package/dist/lib/session/db.d.ts +176 -2
  344. package/dist/lib/session/db.js +484 -17
  345. package/dist/lib/session/discover.js +27 -4
  346. package/dist/lib/session/hook-sessions.js +2 -2
  347. package/dist/lib/session/host-link.d.ts +2 -2
  348. package/dist/lib/session/host-link.js +2 -2
  349. package/dist/lib/session/pid-registry.d.ts +21 -0
  350. package/dist/lib/session/pid-registry.js +57 -0
  351. package/dist/lib/session/remote-active.js +15 -1
  352. package/dist/lib/session/remote.js +2 -2
  353. package/dist/lib/session/session-cache.d.ts +14 -7
  354. package/dist/lib/session/session-cache.js +51 -9
  355. package/dist/lib/session/state.d.ts +2 -2
  356. package/dist/lib/session/state.js +1 -1
  357. package/dist/lib/session/sync/config.d.ts +10 -10
  358. package/dist/lib/session/sync/config.js +10 -10
  359. package/dist/lib/session/sync/r2.d.ts +34 -0
  360. package/dist/lib/session/sync/r2.js +123 -0
  361. package/dist/lib/session/throughput.d.ts +1 -1
  362. package/dist/lib/session/throughput.js +1 -1
  363. package/dist/lib/session/types.d.ts +23 -1
  364. package/dist/lib/session/types.js +15 -0
  365. package/dist/lib/session/viewing-in.d.ts +1 -1
  366. package/dist/lib/session/viewing-in.js +1 -1
  367. package/dist/lib/session/watch.d.ts +101 -0
  368. package/dist/lib/session/watch.js +242 -0
  369. package/dist/lib/share/config.d.ts +4 -0
  370. package/dist/lib/share/config.js +1 -0
  371. package/dist/lib/share/provision.d.ts +38 -0
  372. package/dist/lib/share/provision.js +50 -0
  373. package/dist/lib/share/publish.d.ts +40 -1
  374. package/dist/lib/share/publish.js +116 -3
  375. package/dist/lib/share/worker-template.js +71 -6
  376. package/dist/lib/shims.d.ts +17 -3
  377. package/dist/lib/shims.js +98 -26
  378. package/dist/lib/signin-badge.js +3 -2
  379. package/dist/lib/skills.js +2 -0
  380. package/dist/lib/smart-launch.d.ts +8 -8
  381. package/dist/lib/smart-launch.js +80 -59
  382. package/dist/lib/ssh-exec.d.ts +1 -1
  383. package/dist/lib/ssh-exec.js +1 -1
  384. package/dist/lib/staleness/prune.d.ts +88 -0
  385. package/dist/lib/staleness/prune.js +69 -0
  386. package/dist/lib/staleness/registry.d.ts +1 -1
  387. package/dist/lib/staleness/writers/commands.js +34 -2
  388. package/dist/lib/staleness/writers/hooks.js +16 -0
  389. package/dist/lib/staleness/writers/kinds.d.ts +6 -0
  390. package/dist/lib/staleness/writers/skills.js +19 -0
  391. package/dist/lib/staleness/writers/subagents.d.ts +2 -3
  392. package/dist/lib/staleness/writers/subagents.js +0 -4
  393. package/dist/lib/staleness/writers/types.d.ts +32 -0
  394. package/dist/lib/startup/command-registry.d.ts +6 -12
  395. package/dist/lib/startup/command-registry.js +11 -31
  396. package/dist/lib/startup/dev-build.d.ts +10 -0
  397. package/dist/lib/startup/dev-build.js +13 -1
  398. package/dist/lib/startup/spellcheck.d.ts +18 -0
  399. package/dist/lib/startup/spellcheck.js +45 -0
  400. package/dist/lib/state.d.ts +36 -9
  401. package/dist/lib/state.js +96 -46
  402. package/dist/lib/subagents-registry.d.ts +0 -7
  403. package/dist/lib/subagents-registry.js +38 -65
  404. package/dist/lib/subagents.d.ts +0 -33
  405. package/dist/lib/subagents.js +0 -75
  406. package/dist/lib/sync-umbrella.js +1 -1
  407. package/dist/lib/teams/agents.d.ts +41 -1
  408. package/dist/lib/teams/agents.js +187 -9
  409. package/dist/lib/teams/api.d.ts +11 -1
  410. package/dist/lib/teams/api.js +11 -2
  411. package/dist/lib/teams/delivery.d.ts +41 -0
  412. package/dist/lib/teams/delivery.js +60 -0
  413. package/dist/lib/teams/registry.d.ts +14 -0
  414. package/dist/lib/teams/registry.js +51 -1
  415. package/dist/lib/teams/remoteWorktree.d.ts +19 -0
  416. package/dist/lib/teams/remoteWorktree.js +29 -0
  417. package/dist/lib/teams/scheduler.d.ts +1 -1
  418. package/dist/lib/teams/scheduler.js +1 -1
  419. package/dist/lib/teams/worktree.d.ts +24 -0
  420. package/dist/lib/teams/worktree.js +42 -0
  421. package/dist/lib/terminal/backends/vscodium-agent.d.ts +10 -1
  422. package/dist/lib/terminal/backends/vscodium-agent.js +16 -5
  423. package/dist/lib/terminal/engine.d.ts +4 -0
  424. package/dist/lib/terminal/engine.js +8 -2
  425. package/dist/lib/terminal/types.d.ts +21 -2
  426. package/dist/lib/testdata/refresh-coordinator-worker.d.ts +1 -0
  427. package/dist/lib/testdata/refresh-coordinator-worker.js +23 -0
  428. package/dist/lib/tickets/list.d.ts +53 -0
  429. package/dist/lib/tickets/list.js +153 -0
  430. package/dist/lib/tmux/orphan-reap.d.ts +320 -0
  431. package/dist/lib/tmux/orphan-reap.js +644 -0
  432. package/dist/lib/tmux/session.d.ts +68 -3
  433. package/dist/lib/tmux/session.js +95 -5
  434. package/dist/lib/triggers/handlers.d.ts +20 -0
  435. package/dist/lib/triggers/handlers.js +6 -1
  436. package/dist/lib/types.d.ts +46 -34
  437. package/dist/lib/usage-fleet.d.ts +32 -0
  438. package/dist/lib/usage-fleet.js +125 -0
  439. package/dist/lib/usage-refresh.d.ts +3 -3
  440. package/dist/lib/usage-refresh.js +19 -16
  441. package/dist/lib/usage.d.ts +51 -47
  442. package/dist/lib/usage.js +145 -153
  443. package/dist/lib/version-duplicates.js +2 -2
  444. package/dist/lib/versions.d.ts +56 -13
  445. package/dist/lib/versions.js +195 -45
  446. package/dist/lib/watchdog/log.d.ts +1 -1
  447. package/dist/lib/watchdog/log.js +3 -3
  448. package/dist/lib/watchdog/rotate.d.ts +6 -6
  449. package/dist/lib/watchdog/rotate.js +6 -6
  450. package/dist/lib/workflows.d.ts +1 -1
  451. package/dist/lib/yaml-io.d.ts +47 -0
  452. package/dist/lib/yaml-io.js +55 -0
  453. package/package.json +2 -1
  454. package/scripts/install-helper.js +2 -2
  455. package/scripts/postinstall.js +23 -20
  456. package/dist/commands/defaults.d.ts +0 -7
  457. package/dist/commands/defaults.js +0 -107
  458. package/dist/commands/export.d.ts +0 -11
  459. package/dist/commands/export.js +0 -215
  460. package/dist/commands/helper.d.ts +0 -12
  461. package/dist/commands/helper.js +0 -87
  462. package/dist/commands/hosts.d.ts +0 -11
  463. package/dist/commands/hosts.js +0 -330
  464. package/dist/commands/lock.d.ts +0 -12
  465. package/dist/commands/lock.js +0 -70
  466. package/dist/commands/pull.d.ts +0 -17
  467. package/dist/commands/pull.js +0 -39
  468. package/dist/commands/push.d.ts +0 -14
  469. package/dist/commands/push.js +0 -30
  470. package/dist/commands/wallet.d.ts +0 -20
  471. package/dist/commands/wallet.js +0 -216
  472. package/dist/commands/worktree.d.ts +0 -19
  473. package/dist/commands/worktree.js +0 -272
  474. package/dist/lib/account-labels.d.ts +0 -24
  475. package/dist/lib/account-labels.js +0 -72
  476. package/dist/lib/auto-dispatch-linear.d.ts +0 -18
  477. package/dist/lib/auto-dispatch-linear.js +0 -107
  478. package/dist/lib/auto-dispatch-provider.d.ts +0 -10
  479. package/dist/lib/auto-dispatch-provider.js +0 -30
  480. package/dist/lib/auto-dispatch.d.ts +0 -93
  481. package/dist/lib/auto-dispatch.js +0 -128
  482. package/dist/lib/export.d.ts +0 -72
  483. package/dist/lib/export.js +0 -269
  484. package/dist/lib/lock.d.ts +0 -93
  485. package/dist/lib/lock.js +0 -207
  486. package/dist/lib/wallet/index.d.ts +0 -78
  487. package/dist/lib/wallet/index.js +0 -253
@@ -13,6 +13,21 @@ export const SESSION_AGENTS = ['claude', 'codex', 'gemini', 'antigravity', 'open
13
13
  * of {@link SESSION_AGENTS}). The single predicate every session-index writer
14
14
  * gates on, so "is this a trackable agent?" is decided in exactly one place.
15
15
  */
16
+ /**
17
+ * The tmux session name the CLI mints for an agent run: `ag-<agent>-<shortid>`.
18
+ *
19
+ * ONE definition. This shape was independently re-written as a regex literal in
20
+ * five places (focus's selector test, sessions-resume's direct-selector test,
21
+ * active's name parsers, actor-sidecar, and the deeplink parser); they drifted —
22
+ * focus accepted a 6+ hex suffix while the others required exactly 8 — which is
23
+ * how the same alias could be an "identity" to one code path and a keyword query
24
+ * to the next.
25
+ */
26
+ export const AG_TMUX_NAME_RE = /^ag-([a-z][a-z0-9-]*?)-([0-9a-f]{8})$/i;
27
+ /** Whether `name` is an `ag-<agent>-<shortid>` tmux session name. */
28
+ export function isAgentTmuxAlias(name) {
29
+ return AG_TMUX_NAME_RE.test(name);
30
+ }
16
31
  export function isSessionTrackedAgent(agent) {
17
32
  return SESSION_AGENTS.includes(agent);
18
33
  }
@@ -41,7 +41,7 @@ export interface ViewingIn {
41
41
  * BOTH "no client attached" and "could not locate the pane", so the pane's resolved
42
42
  * `tmuxTarget` is what separates them: without it there is no evidence of absence,
43
43
  * only absence of evidence. Claiming `'detached'` there would invent an orphaned
44
- * session — and a consumer acts on that claim (Factory's picker pre-ticks every
44
+ * session — and a consumer acts on that claim (the ext's picker pre-ticks every
45
45
  * detached row for rescue), so the wrong answer resumes a session nobody asked for.
46
46
  *
47
47
  * Shared by the `--active` row renderer and the `--json` serializer so a machine
@@ -40,7 +40,7 @@ const execFileAsync = promisify(execFile);
40
40
  * BOTH "no client attached" and "could not locate the pane", so the pane's resolved
41
41
  * `tmuxTarget` is what separates them: without it there is no evidence of absence,
42
42
  * only absence of evidence. Claiming `'detached'` there would invent an orphaned
43
- * session — and a consumer acts on that claim (Factory's picker pre-ticks every
43
+ * session — and a consumer acts on that claim (the ext's picker pre-ticks every
44
44
  * detached row for rescue), so the wrong answer resumes a session nobody asked for.
45
45
  *
46
46
  * Shared by the `--active` row renderer and the `--json` serializer so a machine
@@ -0,0 +1,101 @@
1
+ import type { ActiveSession } from './active.js';
2
+ import { readActiveSessionsCache } from './session-cache.js';
3
+ export declare const SESSION_WATCH_VERSION: 1;
4
+ export declare const SESSION_WATCH_HEARTBEAT_MS = 15000;
5
+ export type SessionWatchScopeStatus = 'available' | 'unavailable';
6
+ export type SessionWatchEnvelope = {
7
+ version: 1;
8
+ type: 'reset';
9
+ streamId: string;
10
+ sequence: number;
11
+ capturedAt: number;
12
+ scope: string;
13
+ rows: SessionWatchRow[];
14
+ } | {
15
+ version: 1;
16
+ type: 'upsert';
17
+ streamId: string;
18
+ sequence: number;
19
+ capturedAt: number;
20
+ scope: string;
21
+ rowKey: string;
22
+ row: SessionWatchRow;
23
+ } | {
24
+ version: 1;
25
+ type: 'remove';
26
+ streamId: string;
27
+ sequence: number;
28
+ capturedAt: number;
29
+ scope: string;
30
+ rowKey: string;
31
+ } | {
32
+ version: 1;
33
+ type: 'scope';
34
+ streamId: string;
35
+ sequence: number;
36
+ capturedAt: number;
37
+ scope: string;
38
+ status: SessionWatchScopeStatus;
39
+ reason?: string;
40
+ } | {
41
+ version: 1;
42
+ type: 'heartbeat';
43
+ streamId: string;
44
+ sequence: number;
45
+ scope: string;
46
+ capturedAt: number;
47
+ };
48
+ export interface SessionWatchRow extends Omit<ActiveSession, 'viewingIn'> {
49
+ rowKey: string;
50
+ sourceDevice: string;
51
+ resumable: boolean;
52
+ unwatched: boolean;
53
+ viewingIn: string | null;
54
+ recovery: {
55
+ command: 'agents';
56
+ args: string[];
57
+ cwd?: string;
58
+ } | null;
59
+ }
60
+ /** Stable, opaque identity for one row within one device scope. */
61
+ export declare function sessionWatchRowKey(scope: string, row: ActiveSession): string;
62
+ export declare function toSessionWatchRow(scope: string, row: ActiveSession): SessionWatchRow;
63
+ /** Stream-local sequencer and convergent row diff. */
64
+ export declare class SessionWatchState {
65
+ readonly streamId: string;
66
+ private sequence;
67
+ private readonly rows;
68
+ constructor(streamId?: string);
69
+ private base;
70
+ reset(scope: string, sourceRows: ActiveSession[]): SessionWatchEnvelope;
71
+ update(scope: string, sourceRows: ActiveSession[]): SessionWatchEnvelope[];
72
+ patch(scope: string, upserts: ActiveSession[], removes: string[]): SessionWatchEnvelope[];
73
+ scope(scope: string, status: SessionWatchScopeStatus, reason?: string): SessionWatchEnvelope;
74
+ heartbeat(scope: string, capturedAt?: number): SessionWatchEnvelope;
75
+ }
76
+ export interface WatchLocalOptions {
77
+ scope: string;
78
+ signal: AbortSignal;
79
+ emit: (event: SessionWatchEnvelope) => void;
80
+ refreshMs?: number;
81
+ heartbeatMs?: number;
82
+ readCache?: typeof readActiveSessionsCache;
83
+ journalPath?: string;
84
+ journalPollMs?: number;
85
+ }
86
+ /**
87
+ * Keep one local subscription alive. Startup reads one canonical reset snapshot;
88
+ * steady state tails the canonical writer journal and never invokes a gather.
89
+ */
90
+ export declare function watchLocalSessions(options: WatchLocalOptions): Promise<void>;
91
+ export interface WatchFleetOptions {
92
+ signal: AbortSignal;
93
+ emit: (event: SessionWatchEnvelope) => void;
94
+ reconnectMs?: number;
95
+ }
96
+ /**
97
+ * Subscribe to every dialable compute device with one persistent SSH process.
98
+ * A peer disconnect emits `scope: unavailable` but no removes; reconnecting
99
+ * peer resets only its own scope. There is no recurring fleet list command.
100
+ */
101
+ export declare function watchFleetSessions(options: WatchFleetOptions): Promise<void>;
@@ -0,0 +1,242 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { spawn } from 'node:child_process';
3
+ import { createInterface } from 'node:readline';
4
+ import * as fs from 'node:fs';
5
+ import * as path from 'node:path';
6
+ import { loadDevices, isControlDevice, isDialableDevice } from '../devices/registry.js';
7
+ import { deviceIdentityArgs, sshTargetFor } from '../devices/connect.js';
8
+ import { machineId, normalizeHost } from '../machine-id.js';
9
+ import { SSH_OPTS, controlOpts, shellQuote } from '../ssh-exec.js';
10
+ import { buildWindowsAgentsCommand, remoteShellFor } from '../hosts/remote-cmd.js';
11
+ import { activeSessionsJournalPath, activeSessionJournalIdentity, readActiveSessionsCache, } from './session-cache.js';
12
+ export const SESSION_WATCH_VERSION = 1;
13
+ export const SESSION_WATCH_HEARTBEAT_MS = 15_000;
14
+ /** Stable, opaque identity for one row within one device scope. */
15
+ export function sessionWatchRowKey(scope, row) {
16
+ const identity = activeSessionJournalIdentity(row);
17
+ return createHash('sha256').update(`${scope}\0${identity}`).digest('base64url').slice(0, 22);
18
+ }
19
+ export function toSessionWatchRow(scope, row) {
20
+ const rowKey = sessionWatchRowKey(scope, row);
21
+ const resumable = Boolean(row.sessionId);
22
+ const viewingIn = row.viewingIn
23
+ ? [row.viewingIn.app, row.viewingIn.tab ? `tab ${row.viewingIn.tab}` : undefined].filter(Boolean).join(' ')
24
+ : null;
25
+ return {
26
+ ...row,
27
+ rowKey,
28
+ sourceDevice: scope,
29
+ resumable,
30
+ unwatched: !viewingIn,
31
+ viewingIn,
32
+ recovery: resumable
33
+ ? { command: 'agents', args: ['sessions', 'resume', row.sessionId, '--device', scope], ...(row.cwd ? { cwd: row.cwd } : {}) }
34
+ : null,
35
+ };
36
+ }
37
+ function sameRow(a, b) {
38
+ return JSON.stringify(a) === JSON.stringify(b);
39
+ }
40
+ /** Stream-local sequencer and convergent row diff. */
41
+ export class SessionWatchState {
42
+ streamId;
43
+ sequence = 0;
44
+ rows = new Map();
45
+ constructor(streamId = randomUUID()) { this.streamId = streamId; }
46
+ base(type) {
47
+ return { version: SESSION_WATCH_VERSION, type, streamId: this.streamId, sequence: ++this.sequence, capturedAt: Date.now() };
48
+ }
49
+ reset(scope, sourceRows) {
50
+ const rows = sourceRows.map((row) => toSessionWatchRow(scope, row));
51
+ this.rows.set(scope, new Map(rows.map((row) => [row.rowKey, row])));
52
+ return { ...this.base('reset'), scope, rows };
53
+ }
54
+ update(scope, sourceRows) {
55
+ const previous = this.rows.get(scope) ?? new Map();
56
+ const nextRows = sourceRows.map((row) => toSessionWatchRow(scope, row));
57
+ const next = new Map(nextRows.map((row) => [row.rowKey, row]));
58
+ const events = [];
59
+ for (const [rowKey, row] of next) {
60
+ if (!previous.has(rowKey) || !sameRow(previous.get(rowKey), row)) {
61
+ events.push({ ...this.base('upsert'), scope, rowKey, row });
62
+ }
63
+ }
64
+ for (const rowKey of previous.keys()) {
65
+ if (!next.has(rowKey))
66
+ events.push({ ...this.base('remove'), scope, rowKey });
67
+ }
68
+ this.rows.set(scope, next);
69
+ return events;
70
+ }
71
+ patch(scope, upserts, removes) {
72
+ const current = new Map(this.rows.get(scope) ?? []);
73
+ const events = [];
74
+ for (const source of upserts) {
75
+ const row = toSessionWatchRow(scope, source);
76
+ if (!current.has(row.rowKey) || !sameRow(current.get(row.rowKey), row)) {
77
+ current.set(row.rowKey, row);
78
+ events.push({ ...this.base('upsert'), scope, rowKey: row.rowKey, row });
79
+ }
80
+ }
81
+ for (const identity of removes) {
82
+ const rowKey = createHash('sha256').update(`${scope}\0${identity}`).digest('base64url').slice(0, 22);
83
+ if (current.delete(rowKey))
84
+ events.push({ ...this.base('remove'), scope, rowKey });
85
+ }
86
+ this.rows.set(scope, current);
87
+ return events;
88
+ }
89
+ scope(scope, status, reason) {
90
+ // Deliberately retain rows while unavailable. A reconnecting scope replaces
91
+ // them with a reset; transient fleet loss must not look like session death.
92
+ return { ...this.base('scope'), scope, status, ...(reason ? { reason } : {}) };
93
+ }
94
+ heartbeat(scope, capturedAt = Date.now()) {
95
+ return { ...this.base('heartbeat'), scope, capturedAt };
96
+ }
97
+ }
98
+ /**
99
+ * Keep one local subscription alive. Startup reads one canonical reset snapshot;
100
+ * steady state tails the canonical writer journal and never invokes a gather.
101
+ */
102
+ export async function watchLocalSessions(options) {
103
+ const state = new SessionWatchState();
104
+ const readCache = options.readCache ?? readActiveSessionsCache;
105
+ const journal = options.journalPath ?? activeSessionsJournalPath();
106
+ const heartbeatMs = options.heartbeatMs ?? SESSION_WATCH_HEARTBEAT_MS;
107
+ let offset = 0;
108
+ try {
109
+ offset = fs.statSync(journal).size;
110
+ }
111
+ catch { /* first publication */ }
112
+ const initial = readCache('local');
113
+ options.emit(state.reset(options.scope, initial?.sessions ?? []));
114
+ options.emit(state.scope(options.scope, initial ? 'available' : 'unavailable', initial ? undefined : 'awaiting publisher'));
115
+ if (options.signal.aborted)
116
+ return;
117
+ await new Promise((resolve) => {
118
+ let partial = '';
119
+ let reading = false;
120
+ const readAppended = () => {
121
+ if (reading || options.signal.aborted)
122
+ return;
123
+ reading = true;
124
+ try {
125
+ const size = fs.statSync(journal).size;
126
+ if (size < offset) {
127
+ offset = 0;
128
+ partial = '';
129
+ }
130
+ if (size === offset)
131
+ return;
132
+ const fd = fs.openSync(journal, 'r');
133
+ try {
134
+ const buffer = Buffer.alloc(size - offset);
135
+ fs.readSync(fd, buffer, 0, buffer.length, offset);
136
+ offset = size;
137
+ const lines = (partial + buffer.toString('utf8')).split('\n');
138
+ partial = lines.pop() ?? '';
139
+ for (const line of lines) {
140
+ if (!line)
141
+ continue;
142
+ try {
143
+ const record = JSON.parse(line);
144
+ if (record.version !== 1 || record.scope !== 'local' || !Array.isArray(record.upserts) || !Array.isArray(record.removes))
145
+ continue;
146
+ for (const event of state.patch(options.scope, record.upserts, record.removes))
147
+ options.emit(event);
148
+ options.emit(state.scope(options.scope, 'available'));
149
+ }
150
+ catch { /* partial/corrupt journal lines are not state */ }
151
+ }
152
+ }
153
+ finally {
154
+ fs.closeSync(fd);
155
+ }
156
+ }
157
+ catch { /* journal may not exist until the first publisher write */ }
158
+ finally {
159
+ reading = false;
160
+ }
161
+ };
162
+ fs.mkdirSync(path.dirname(journal), { recursive: true });
163
+ const journalListener = () => readAppended();
164
+ fs.watchFile(journal, { interval: options.journalPollMs ?? 250 }, journalListener);
165
+ const heartbeatTimer = setInterval(() => options.emit(state.heartbeat(options.scope)), heartbeatMs);
166
+ const stop = () => { fs.unwatchFile(journal, journalListener); clearInterval(heartbeatTimer); resolve(); };
167
+ options.signal.addEventListener('abort', stop, { once: true });
168
+ // Close the offset/read/watch handoff: a publisher may append after the
169
+ // startup offset is captured but before watchFile is registered.
170
+ readAppended();
171
+ });
172
+ }
173
+ function remoteWatchCommand(os) {
174
+ const args = ['sessions', 'watch', '--json', '--local'];
175
+ return remoteShellFor(os) === 'powershell'
176
+ ? buildWindowsAgentsCommand({ args })
177
+ : `bash -lc ${shellQuote(`agents ${args.map(shellQuote).join(' ')}`)}`;
178
+ }
179
+ /**
180
+ * Subscribe to every dialable compute device with one persistent SSH process.
181
+ * A peer disconnect emits `scope: unavailable` but no removes; reconnecting
182
+ * peer resets only its own scope. There is no recurring fleet list command.
183
+ */
184
+ export async function watchFleetSessions(options) {
185
+ const local = watchLocalSessions({ scope: machineId(), signal: options.signal, emit: options.emit });
186
+ let devices;
187
+ try {
188
+ devices = await loadDevices();
189
+ }
190
+ catch {
191
+ await local;
192
+ return;
193
+ }
194
+ const self = machineId();
195
+ const peers = Object.values(devices).filter((device) => isDialableDevice(device)
196
+ && !isControlDevice(device)
197
+ && normalizeHost(device.name) !== self
198
+ && ['windows', 'linux', 'macos'].includes(device.platform));
199
+ const reconnectMs = options.reconnectMs ?? 2_000;
200
+ const peerTasks = peers.map(async (device) => {
201
+ const scope = normalizeHost(device.name);
202
+ const state = new SessionWatchState();
203
+ while (!options.signal.aborted) {
204
+ let target;
205
+ try {
206
+ target = sshTargetFor(device);
207
+ }
208
+ catch (error) {
209
+ options.emit(state.scope(scope, 'unavailable', error instanceof Error ? error.message : String(error)));
210
+ break;
211
+ }
212
+ const child = spawn('ssh', [
213
+ ...SSH_OPTS, ...controlOpts(), ...deviceIdentityArgs(device), target, remoteWatchCommand(device.platform),
214
+ ], { stdio: ['ignore', 'pipe', 'ignore'] });
215
+ const stop = () => child.kill('SIGTERM');
216
+ options.signal.addEventListener('abort', stop, { once: true });
217
+ const reader = createInterface({ input: child.stdout });
218
+ reader.on('line', (line) => {
219
+ try {
220
+ const event = JSON.parse(line);
221
+ if (event.version === SESSION_WATCH_VERSION && typeof event.sequence === 'number')
222
+ options.emit(event);
223
+ }
224
+ catch { /* incomplete/non-protocol peer output is not state */ }
225
+ });
226
+ const code = await new Promise((resolve) => {
227
+ child.once('error', () => resolve(null));
228
+ child.once('close', resolve);
229
+ });
230
+ reader.close();
231
+ options.signal.removeEventListener('abort', stop);
232
+ if (options.signal.aborted)
233
+ break;
234
+ options.emit(state.scope(scope, 'unavailable', code === null ? 'ssh failed' : `ssh exited ${code}`));
235
+ await new Promise((resolve) => {
236
+ const timer = setTimeout(resolve, reconnectMs);
237
+ options.signal.addEventListener('abort', () => { clearTimeout(timer); resolve(); }, { once: true });
238
+ });
239
+ }
240
+ });
241
+ await Promise.all([local, ...peerTasks]);
242
+ }
@@ -8,6 +8,10 @@ export interface ShareConfig {
8
8
  domain?: string;
9
9
  /** Cloudflare Web Analytics token injected into published HTML pages. */
10
10
  analyticsToken?: string;
11
+ /** sha256 of the Worker script deployed at the last provision/update. Absent
12
+ * on any config written before this field existed — treat that as "unknown",
13
+ * never as "outdated" (there is nothing to compare against). */
14
+ templateHash?: string;
11
15
  }
12
16
  export declare const SHARE_BUNDLE = "share";
13
17
  export declare const SHARE_TOKEN_KEY = "WRITE_TOKEN";
@@ -35,6 +35,7 @@ export function readShareConfig() {
35
35
  bucketName: s.bucketName,
36
36
  domain: s.domain,
37
37
  analyticsToken: s.analyticsToken,
38
+ templateHash: s.templateHash,
38
39
  };
39
40
  }
40
41
  /** Persist the endpoint config to `agents.yaml` (syncs across the fleet). */
@@ -51,6 +51,44 @@ export declare function mergeShareLifecycleRule(existing?: R2LifecycleRule[], ru
51
51
  export declare function configureBucketLifecycle(apiToken: string, accountId: string, bucketName: string, opts?: ProvisionOptions): Promise<void>;
52
52
  /** Upload the module Worker with an R2 binding (`BUCKET`). Secrets are set via the Workers Secrets API. */
53
53
  export declare function deployWorker(apiToken: string, accountId: string, workerName: string, script: string, bucketName: string, opts?: ProvisionOptions): Promise<void>;
54
+ /** sha256 of the rendered Worker script, so a deployed endpoint can be compared
55
+ * against the current `worker-template.ts` without redeploying to find out. */
56
+ export declare function hashWorkerScript(script: string): string;
57
+ export interface UpdateWorkerResult {
58
+ /** sha256 of `script` (the hash the endpoint now matches, whether or not this
59
+ * call actually redeployed). */
60
+ templateHash: string;
61
+ /** True when the upload was skipped because `previousHash` already matched. */
62
+ skipped: boolean;
63
+ }
64
+ /**
65
+ * Re-deploy the Worker script against an ALREADY-provisioned endpoint (same
66
+ * account/worker/bucket `deployWorker` was first called with) and idempotently
67
+ * no-op when the template hasn't changed.
68
+ *
69
+ * Cloudflare's script-upload endpoint (`deployWorker`, above) replaces the
70
+ * Worker's bindings/secrets wholesale on every call — there is no documented,
71
+ * reliable way to tell it "keep the existing secret" (the `keep_bindings`
72
+ * metadata field some third-party guides mention is absent from Cloudflare's
73
+ * current Multipart upload metadata reference, and the community has reported
74
+ * it not preventing binding loss even when present:
75
+ * https://developers.cloudflare.com/workers/configuration/multipart-upload-metadata/,
76
+ * https://community.cloudflare.com/t/upload-worker-module-endpoint-removes-existing-bindings-despite-keep-bindings/766447).
77
+ * So instead this immediately re-applies WRITE_TOKEN via the documented Secrets
78
+ * API right after the upload — the same two-call sequence first-time
79
+ * provisioning already uses (`deployWorker` then `setWorkerSecret`), except
80
+ * `writeToken` here is the caller's EXISTING token, never a freshly generated
81
+ * one. Cloudflare's own docs describe exactly this "secrets survive a
82
+ * subsequent write" contract for the sibling `wrangler versions upload
83
+ * --secrets-file` flow ("Secrets not included in the file are preserved from
84
+ * the previous version" —
85
+ * https://developers.cloudflare.com/workers/configuration/secrets/#upload-secrets-alongside-code);
86
+ * re-setting the secret to its own value after every deploy gets the same
87
+ * outcome without depending on an unverified upload-time flag.
88
+ */
89
+ export declare function updateWorker(apiToken: string, accountId: string, workerName: string, bucketName: string, script: string, writeToken: string, previousHash: string | undefined, opts?: ProvisionOptions & {
90
+ force?: boolean;
91
+ }): Promise<UpdateWorkerResult>;
54
92
  /** Add/update the WRITE_TOKEN binding using Cloudflare's Workers Secrets API. */
55
93
  export declare function setWorkerSecret(apiToken: string, accountId: string, workerName: string, writeToken: string, opts?: ProvisionOptions): Promise<void>;
56
94
  /** Enable the free `*.workers.dev` route for the script, and return the account subdomain. */
@@ -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. */