@phnx-labs/agents-cli 1.22.35 → 1.22.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (500) hide show
  1. package/CHANGELOG.md +708 -2
  2. package/README.md +83 -43
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.d.ts +15 -0
  5. package/dist/bootstrap.js +1212 -0
  6. package/dist/commands/accounts.d.ts +4 -11
  7. package/dist/commands/accounts.js +159 -27
  8. package/dist/commands/artifacts-setup.d.ts +53 -0
  9. package/dist/commands/artifacts-setup.js +161 -0
  10. package/dist/commands/artifacts.d.ts +18 -0
  11. package/dist/commands/artifacts.js +58 -0
  12. package/dist/commands/attach.js +17 -4
  13. package/dist/commands/audit.d.ts +8 -8
  14. package/dist/commands/audit.js +57 -47
  15. package/dist/commands/browser.js +17 -11
  16. package/dist/commands/cloud.js +1 -1
  17. package/dist/commands/commands.js +0 -11
  18. package/dist/commands/computer-actions.js +33 -0
  19. package/dist/commands/computer-sessions-picker.d.ts +21 -0
  20. package/dist/commands/computer-sessions-picker.js +141 -0
  21. package/dist/commands/computer.d.ts +16 -0
  22. package/dist/commands/computer.js +37 -0
  23. package/dist/commands/config.d.ts +17 -0
  24. package/dist/commands/config.js +401 -0
  25. package/dist/commands/cp.d.ts +84 -0
  26. package/dist/commands/cp.js +231 -0
  27. package/dist/commands/daemon.js +243 -14
  28. package/dist/commands/detach-core.d.ts +1 -1
  29. package/dist/commands/detach-core.js +12 -2
  30. package/dist/commands/detach.js +1 -1
  31. package/dist/commands/doctor.js +64 -5
  32. package/dist/commands/events.d.ts +24 -12
  33. package/dist/commands/events.js +144 -28
  34. package/dist/commands/exec.js +86 -42
  35. package/dist/commands/feed.d.ts +1 -1
  36. package/dist/commands/feed.js +16 -8
  37. package/dist/commands/focus.d.ts +33 -1
  38. package/dist/commands/focus.js +177 -17
  39. package/dist/commands/funnel.d.ts +1 -1
  40. package/dist/commands/go.js +9 -8
  41. package/dist/commands/harness-wizard.d.ts +1 -0
  42. package/dist/commands/harness-wizard.js +18 -20
  43. package/dist/commands/harness.d.ts +2 -0
  44. package/dist/commands/harness.js +59 -26
  45. package/dist/commands/hooks.js +0 -11
  46. package/dist/commands/inspect.d.ts +94 -1
  47. package/dist/commands/inspect.js +866 -40
  48. package/dist/commands/lease.d.ts +4 -4
  49. package/dist/commands/lease.js +6 -6
  50. package/dist/commands/login.js +0 -13
  51. package/dist/commands/logs.d.ts +2 -2
  52. package/dist/commands/logs.js +2 -2
  53. package/dist/commands/mcp.js +7 -2
  54. package/dist/commands/memory.js +7 -2
  55. package/dist/commands/message.d.ts +1 -1
  56. package/dist/commands/message.js +37 -6
  57. package/dist/commands/models.js +71 -0
  58. package/dist/commands/monitors.d.ts +0 -1
  59. package/dist/commands/monitors.js +199 -16
  60. package/dist/commands/open.d.ts +18 -0
  61. package/dist/commands/open.js +57 -0
  62. package/dist/commands/packages.js +2 -107
  63. package/dist/commands/plugins.js +6 -3
  64. package/dist/commands/profiles.d.ts +1 -0
  65. package/dist/commands/profiles.js +16 -160
  66. package/dist/commands/projects.d.ts +28 -0
  67. package/dist/commands/projects.js +125 -5
  68. package/dist/commands/reconnect.js +9 -3
  69. package/dist/commands/repo.js +42 -1
  70. package/dist/commands/resource-view.d.ts +17 -0
  71. package/dist/commands/resource-view.js +36 -14
  72. package/dist/commands/resume.js +9 -2
  73. package/dist/commands/routines.d.ts +0 -2
  74. package/dist/commands/routines.js +473 -289
  75. package/dist/commands/secrets.js +52 -9
  76. package/dist/commands/sessions-export.d.ts +47 -0
  77. package/dist/commands/sessions-export.js +116 -6
  78. package/dist/commands/sessions-import.d.ts +17 -0
  79. package/dist/commands/sessions-import.js +114 -6
  80. package/dist/commands/sessions-migrate.d.ts +27 -0
  81. package/dist/commands/sessions-migrate.js +50 -9
  82. package/dist/commands/sessions-picker.js +23 -4
  83. package/dist/commands/sessions-resume.d.ts +5 -3
  84. package/dist/commands/sessions-resume.js +30 -8
  85. package/dist/commands/sessions-watch.d.ts +2 -0
  86. package/dist/commands/sessions-watch.js +53 -0
  87. package/dist/commands/sessions.d.ts +66 -3
  88. package/dist/commands/sessions.js +298 -47
  89. package/dist/commands/setup-browser.js +2 -2
  90. package/dist/commands/setup-mine.js +0 -1
  91. package/dist/commands/setup-preferences.js +1 -1
  92. package/dist/commands/setup.d.ts +5 -0
  93. package/dist/commands/setup.js +31 -5
  94. package/dist/commands/share.d.ts +87 -7
  95. package/dist/commands/share.js +320 -58
  96. package/dist/commands/skills.js +0 -11
  97. package/dist/commands/snapshot.js +1 -1
  98. package/dist/commands/ssh.d.ts +18 -0
  99. package/dist/commands/ssh.js +549 -210
  100. package/dist/commands/sync.d.ts +5 -0
  101. package/dist/commands/sync.js +212 -32
  102. package/dist/commands/teams.d.ts +13 -0
  103. package/dist/commands/teams.js +187 -30
  104. package/dist/commands/tickets.d.ts +2 -0
  105. package/dist/commands/tickets.js +43 -0
  106. package/dist/commands/update.js +2 -4
  107. package/dist/commands/usage.js +5 -3
  108. package/dist/commands/versions.js +11 -5
  109. package/dist/commands/view.js +15 -7
  110. package/dist/commands/webhook.d.ts +2 -2
  111. package/dist/commands/webhook.js +7 -7
  112. package/dist/index.d.ts +18 -2
  113. package/dist/index.js +53 -1264
  114. package/dist/lib/account-catalog.d.ts +18 -0
  115. package/dist/lib/account-catalog.js +38 -0
  116. package/dist/lib/account-provider-registry.d.ts +18 -0
  117. package/dist/lib/account-provider-registry.js +59 -0
  118. package/dist/lib/account-registry.d.ts +40 -0
  119. package/dist/lib/account-registry.js +239 -0
  120. package/dist/lib/account-schema.d.ts +44 -0
  121. package/dist/lib/account-schema.js +91 -0
  122. package/dist/lib/account-state-service.d.ts +21 -0
  123. package/dist/lib/account-state-service.js +60 -0
  124. package/dist/lib/activity.d.ts +1 -1
  125. package/dist/lib/activity.js +8 -1
  126. package/dist/lib/add-dir.d.ts +80 -0
  127. package/dist/lib/add-dir.js +241 -0
  128. package/dist/lib/agent-cli-commands.d.ts +11 -0
  129. package/dist/lib/agent-cli-commands.js +30 -0
  130. package/dist/lib/agents.js +44 -36
  131. package/dist/lib/answer-router.js +1 -1
  132. package/dist/lib/audit/log.d.ts +10 -27
  133. package/dist/lib/audit/log.js +20 -33
  134. package/dist/lib/auth-health.d.ts +9 -2
  135. package/dist/lib/auth-health.js +42 -9
  136. package/dist/lib/auto-pull-worker.js +7 -3
  137. package/dist/lib/auto-pull.d.ts +44 -3
  138. package/dist/lib/auto-pull.js +88 -5
  139. package/dist/lib/binary-shadow.d.ts +28 -0
  140. package/dist/lib/binary-shadow.js +121 -0
  141. package/dist/lib/brand.js +9 -3
  142. package/dist/lib/browser/hygiene.d.ts +90 -0
  143. package/dist/lib/browser/hygiene.js +146 -0
  144. package/dist/lib/browser/ipc.d.ts +30 -0
  145. package/dist/lib/browser/ipc.js +93 -4
  146. package/dist/lib/browser/profiles.d.ts +3 -2
  147. package/dist/lib/browser/profiles.js +65 -22
  148. package/dist/lib/browser/service.d.ts +79 -1
  149. package/dist/lib/browser/service.js +231 -14
  150. package/dist/lib/browser/sessions-list.d.ts +22 -2
  151. package/dist/lib/browser/sessions-list.js +54 -6
  152. package/dist/lib/browser/stream.d.ts +2 -0
  153. package/dist/lib/browser/stream.js +1 -0
  154. package/dist/lib/browser/types.d.ts +63 -1
  155. package/dist/lib/byok-usage.d.ts +9 -2
  156. package/dist/lib/byok-usage.js +133 -31
  157. package/dist/lib/cli-entry.d.ts +11 -0
  158. package/dist/lib/cli-entry.js +46 -0
  159. package/dist/lib/cloud/host.d.ts +1 -1
  160. package/dist/lib/cloud/host.js +2 -2
  161. package/dist/lib/cloud/registry.js +1 -1
  162. package/dist/lib/cloud/types.d.ts +1 -1
  163. package/dist/lib/commands.d.ts +2 -0
  164. package/dist/lib/commands.js +2 -0
  165. package/dist/lib/computer/sessions-list.d.ts +150 -0
  166. package/dist/lib/computer/sessions-list.js +363 -0
  167. package/dist/lib/config-keys.d.ts +86 -0
  168. package/dist/lib/config-keys.js +193 -0
  169. package/dist/lib/config-machine-keys.d.ts +12 -0
  170. package/dist/lib/config-machine-keys.js +17 -0
  171. package/dist/lib/config-transfer.js +3 -4
  172. package/dist/lib/crabbox/cli.d.ts +2 -2
  173. package/dist/lib/crabbox/cli.js +3 -3
  174. package/dist/lib/daemon-health.d.ts +22 -0
  175. package/dist/lib/daemon-health.js +33 -3
  176. package/dist/lib/daemon-services.d.ts +50 -0
  177. package/dist/lib/daemon-services.js +147 -0
  178. package/dist/lib/daemon-ticks.d.ts +35 -66
  179. package/dist/lib/daemon-ticks.js +77 -159
  180. package/dist/lib/daemon.d.ts +72 -4
  181. package/dist/lib/daemon.js +792 -202
  182. package/dist/lib/deeplink/register.d.ts +49 -0
  183. package/dist/lib/deeplink/register.js +253 -0
  184. package/dist/lib/deeplink/url.d.ts +34 -0
  185. package/dist/lib/deeplink/url.js +78 -0
  186. package/dist/lib/device-config.d.ts +124 -29
  187. package/dist/lib/device-config.js +346 -141
  188. package/dist/lib/devices/config-migration.d.ts +42 -0
  189. package/dist/lib/devices/config-migration.js +203 -0
  190. package/dist/lib/devices/connect.js +14 -7
  191. package/dist/lib/devices/doctor-findings.d.ts +4 -1
  192. package/dist/lib/devices/doctor-findings.js +20 -1
  193. package/dist/lib/devices/harness-inventory.d.ts +11 -2
  194. package/dist/lib/devices/harness-inventory.js +0 -0
  195. package/dist/lib/devices/health.d.ts +1 -1
  196. package/dist/lib/devices/health.js +1 -1
  197. package/dist/lib/devices/pending.d.ts +22 -1
  198. package/dist/lib/devices/pending.js +67 -2
  199. package/dist/lib/devices/registry.d.ts +0 -25
  200. package/dist/lib/devices/registry.js +2 -83
  201. package/dist/lib/devices/resolve-profile.d.ts +20 -0
  202. package/dist/lib/devices/resolve-profile.js +44 -0
  203. package/dist/lib/devices/rollout-verify.d.ts +101 -0
  204. package/dist/lib/devices/rollout-verify.js +193 -0
  205. package/dist/lib/devices/ssh-config.js +10 -6
  206. package/dist/lib/event-families.d.ts +28 -0
  207. package/dist/lib/event-families.js +159 -0
  208. package/dist/lib/event-stream.d.ts +9 -1
  209. package/dist/lib/event-stream.js +26 -9
  210. package/dist/lib/events.d.ts +9 -1
  211. package/dist/lib/events.js +21 -6
  212. package/dist/lib/exec.d.ts +30 -0
  213. package/dist/lib/exec.js +219 -121
  214. package/dist/lib/feed-broadcast.d.ts +25 -0
  215. package/dist/lib/feed-broadcast.js +33 -0
  216. package/dist/lib/feed.d.ts +1 -1
  217. package/dist/lib/feed.js +12 -2
  218. package/dist/lib/fleet/capture.js +15 -0
  219. package/dist/lib/fleet/manifest.js +9 -0
  220. package/dist/lib/fleet/types.d.ts +9 -0
  221. package/dist/lib/fleet-status.js +10 -8
  222. package/dist/lib/git.d.ts +21 -7
  223. package/dist/lib/git.js +122 -18
  224. package/dist/lib/hosts/dispatch.d.ts +8 -3
  225. package/dist/lib/hosts/dispatch.js +29 -3
  226. package/dist/lib/hosts/logs.d.ts +2 -2
  227. package/dist/lib/hosts/logs.js +2 -2
  228. package/dist/lib/hosts/option.js +1 -1
  229. package/dist/lib/hosts/passthrough.d.ts +2 -3
  230. package/dist/lib/hosts/passthrough.js +10 -24
  231. package/dist/lib/hosts/progress.js +2 -2
  232. package/dist/lib/hosts/providers/devices.d.ts +3 -3
  233. package/dist/lib/hosts/providers/devices.js +18 -12
  234. package/dist/lib/hosts/ready.d.ts +5 -1
  235. package/dist/lib/hosts/ready.js +9 -3
  236. package/dist/lib/hosts/reconcile.d.ts +2 -2
  237. package/dist/lib/hosts/reconcile.js +2 -2
  238. package/dist/lib/hosts/registry.js +14 -9
  239. package/dist/lib/hosts/remote-cmd.js +1 -1
  240. package/dist/lib/hosts/remote-os.d.ts +9 -6
  241. package/dist/lib/hosts/remote-os.js +13 -6
  242. package/dist/lib/hosts/routing-flag.d.ts +23 -0
  243. package/dist/lib/hosts/routing-flag.js +41 -0
  244. package/dist/lib/hosts/run-target.js +1 -1
  245. package/dist/lib/hosts/session-index.js +1 -1
  246. package/dist/lib/hosts/tasks.d.ts +6 -6
  247. package/dist/lib/hosts/tasks.js +4 -4
  248. package/dist/lib/hosts/types.js +1 -2
  249. package/dist/lib/installations/resolve.js +2 -8
  250. package/dist/lib/isolation-boundary-report.js +0 -1
  251. package/dist/lib/linear-cache.d.ts +7 -0
  252. package/dist/lib/linear-cache.js +31 -4
  253. package/dist/lib/linear-project-counts.d.ts +1 -1
  254. package/dist/lib/linear-project-counts.js +2 -3
  255. package/dist/lib/linear-projects.js +1 -1
  256. package/dist/lib/loop.d.ts +2 -2
  257. package/dist/lib/loop.js +1 -1
  258. package/dist/lib/mailbox-target.d.ts +1 -1
  259. package/dist/lib/mailbox-target.js +1 -1
  260. package/dist/lib/manifest.js +7 -4
  261. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  262. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  263. package/dist/lib/menubar/snapshot.d.ts +3 -2
  264. package/dist/lib/menubar/snapshot.js +6 -2
  265. package/dist/lib/migrate-fold.d.ts +33 -0
  266. package/dist/lib/migrate-fold.js +130 -0
  267. package/dist/lib/migrate.d.ts +34 -34
  268. package/dist/lib/migrate.js +106 -128
  269. package/dist/lib/model-tier-overrides.d.ts +1 -1
  270. package/dist/lib/model-tier-overrides.js +15 -2
  271. package/dist/lib/monitors/config.d.ts +17 -3
  272. package/dist/lib/monitors/config.js +52 -18
  273. package/dist/lib/monitors/engine.d.ts +32 -1
  274. package/dist/lib/monitors/engine.js +94 -11
  275. package/dist/lib/monitors/fingerprint.d.ts +46 -0
  276. package/dist/lib/monitors/fingerprint.js +100 -0
  277. package/dist/lib/monitors/remote.d.ts +47 -0
  278. package/dist/lib/monitors/remote.js +81 -0
  279. package/dist/lib/monitors/state.d.ts +39 -0
  280. package/dist/lib/monitors/state.js +56 -0
  281. package/dist/lib/onepassword.d.ts +17 -0
  282. package/dist/lib/onepassword.js +52 -22
  283. package/dist/lib/open-url.js +1 -1
  284. package/dist/lib/picker.d.ts +14 -2
  285. package/dist/lib/picker.js +35 -13
  286. package/dist/lib/placement.d.ts +1 -1
  287. package/dist/lib/placement.js +1 -1
  288. package/dist/lib/pr-land-detach.d.ts +32 -0
  289. package/dist/lib/pr-land-detach.js +79 -0
  290. package/dist/lib/profiles-presets.js +13 -0
  291. package/dist/lib/profiles.d.ts +2 -0
  292. package/dist/lib/profiles.js +44 -1
  293. package/dist/lib/project-focus.d.ts +1 -1
  294. package/dist/lib/project-focus.js +1 -1
  295. package/dist/lib/project-probe.d.ts +4 -1
  296. package/dist/lib/project-probe.js +5 -4
  297. package/dist/lib/project-resources.js +2 -18
  298. package/dist/lib/project-root.d.ts +16 -0
  299. package/dist/lib/project-root.js +20 -2
  300. package/dist/lib/projects.d.ts +20 -1
  301. package/dist/lib/projects.js +78 -1
  302. package/dist/lib/refresh-coordinator.d.ts +24 -0
  303. package/dist/lib/refresh-coordinator.js +52 -0
  304. package/dist/lib/registry.d.ts +2 -2
  305. package/dist/lib/registry.js +1 -1
  306. package/dist/lib/resource-aliases.d.ts +13 -0
  307. package/dist/lib/resource-aliases.js +26 -0
  308. package/dist/lib/resources/types.d.ts +1 -1
  309. package/dist/lib/resources.d.ts +16 -0
  310. package/dist/lib/resources.js +66 -10
  311. package/dist/lib/rotate.d.ts +3 -4
  312. package/dist/lib/rotate.js +4 -5
  313. package/dist/lib/routine-activation.d.ts +22 -2
  314. package/dist/lib/routine-activation.js +63 -16
  315. package/dist/lib/routine-context.d.ts +9 -2
  316. package/dist/lib/routine-context.js +21 -6
  317. package/dist/lib/routines-project.d.ts +58 -48
  318. package/dist/lib/routines-project.js +190 -159
  319. package/dist/lib/routines.d.ts +44 -7
  320. package/dist/lib/routines.js +92 -34
  321. package/dist/lib/run-defaults.d.ts +5 -0
  322. package/dist/lib/run-defaults.js +11 -1
  323. package/dist/lib/runner.d.ts +10 -8
  324. package/dist/lib/runner.js +122 -39
  325. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  326. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  327. package/dist/lib/secrets/agent.d.ts +10 -3
  328. package/dist/lib/secrets/agent.js +43 -8
  329. package/dist/lib/secrets/bundles.d.ts +1 -0
  330. package/dist/lib/secrets/bundles.js +92 -80
  331. package/dist/lib/secrets/index.js +32 -9
  332. package/dist/lib/secrets/install-helper.d.ts +4 -4
  333. package/dist/lib/secrets/install-helper.js +4 -4
  334. package/dist/lib/secrets/push.d.ts +40 -6
  335. package/dist/lib/secrets/push.js +58 -11
  336. package/dist/lib/secrets/read-backoff.d.ts +1 -1
  337. package/dist/lib/secrets/read-backoff.js +1 -1
  338. package/dist/lib/secrets/remote.d.ts +24 -0
  339. package/dist/lib/secrets/remote.js +54 -4
  340. package/dist/lib/self-update.d.ts +108 -0
  341. package/dist/lib/self-update.js +276 -1
  342. package/dist/lib/session/active.d.ts +89 -5
  343. package/dist/lib/session/active.js +165 -10
  344. package/dist/lib/session/actor-sidecar.d.ts +1 -1
  345. package/dist/lib/session/actor-sidecar.js +2 -1
  346. package/dist/lib/session/db.d.ts +176 -2
  347. package/dist/lib/session/db.js +484 -17
  348. package/dist/lib/session/discover.js +27 -4
  349. package/dist/lib/session/hook-sessions.js +2 -2
  350. package/dist/lib/session/host-link.d.ts +2 -2
  351. package/dist/lib/session/host-link.js +2 -2
  352. package/dist/lib/session/pid-registry.d.ts +21 -0
  353. package/dist/lib/session/pid-registry.js +57 -0
  354. package/dist/lib/session/remote-active.js +15 -1
  355. package/dist/lib/session/remote.js +2 -2
  356. package/dist/lib/session/session-cache.d.ts +14 -7
  357. package/dist/lib/session/session-cache.js +51 -9
  358. package/dist/lib/session/state.d.ts +2 -2
  359. package/dist/lib/session/state.js +1 -1
  360. package/dist/lib/session/sync/config.d.ts +10 -10
  361. package/dist/lib/session/sync/config.js +10 -10
  362. package/dist/lib/session/sync/r2.d.ts +34 -0
  363. package/dist/lib/session/sync/r2.js +123 -0
  364. package/dist/lib/session/throughput.d.ts +1 -1
  365. package/dist/lib/session/throughput.js +1 -1
  366. package/dist/lib/session/types.d.ts +23 -1
  367. package/dist/lib/session/types.js +15 -0
  368. package/dist/lib/session/viewing-in.d.ts +1 -1
  369. package/dist/lib/session/viewing-in.js +1 -1
  370. package/dist/lib/session/watch.d.ts +101 -0
  371. package/dist/lib/session/watch.js +242 -0
  372. package/dist/lib/share/analytics.js +1 -1
  373. package/dist/lib/share/capture.d.ts +1 -1
  374. package/dist/lib/share/capture.js +3 -3
  375. package/dist/lib/share/config.d.ts +6 -2
  376. package/dist/lib/share/config.js +6 -5
  377. package/dist/lib/share/delete.js +3 -3
  378. package/dist/lib/share/provision.d.ts +38 -0
  379. package/dist/lib/share/provision.js +51 -1
  380. package/dist/lib/share/publish.d.ts +40 -1
  381. package/dist/lib/share/publish.js +119 -6
  382. package/dist/lib/share/worker-template.d.ts +12 -1
  383. package/dist/lib/share/worker-template.js +83 -7
  384. package/dist/lib/shims.d.ts +17 -3
  385. package/dist/lib/shims.js +98 -26
  386. package/dist/lib/signin-badge.js +3 -2
  387. package/dist/lib/skills.js +2 -0
  388. package/dist/lib/smart-launch.d.ts +8 -8
  389. package/dist/lib/smart-launch.js +80 -59
  390. package/dist/lib/ssh-exec.d.ts +1 -1
  391. package/dist/lib/ssh-exec.js +1 -1
  392. package/dist/lib/staleness/prune.d.ts +88 -0
  393. package/dist/lib/staleness/prune.js +69 -0
  394. package/dist/lib/staleness/registry.d.ts +1 -1
  395. package/dist/lib/staleness/writers/commands.js +34 -2
  396. package/dist/lib/staleness/writers/hooks.js +16 -0
  397. package/dist/lib/staleness/writers/kinds.d.ts +6 -0
  398. package/dist/lib/staleness/writers/skills.js +19 -0
  399. package/dist/lib/staleness/writers/subagents.d.ts +2 -3
  400. package/dist/lib/staleness/writers/subagents.js +0 -4
  401. package/dist/lib/staleness/writers/types.d.ts +32 -0
  402. package/dist/lib/startup/command-registry.d.ts +16 -14
  403. package/dist/lib/startup/command-registry.js +26 -37
  404. package/dist/lib/startup/dev-build.d.ts +10 -0
  405. package/dist/lib/startup/dev-build.js +13 -1
  406. package/dist/lib/startup/spellcheck.d.ts +18 -0
  407. package/dist/lib/startup/spellcheck.js +45 -0
  408. package/dist/lib/state.d.ts +36 -9
  409. package/dist/lib/state.js +96 -46
  410. package/dist/lib/subagents-registry.d.ts +0 -7
  411. package/dist/lib/subagents-registry.js +38 -65
  412. package/dist/lib/subagents.d.ts +0 -33
  413. package/dist/lib/subagents.js +0 -75
  414. package/dist/lib/sync-umbrella.js +1 -1
  415. package/dist/lib/teams/agents.d.ts +41 -1
  416. package/dist/lib/teams/agents.js +187 -9
  417. package/dist/lib/teams/api.d.ts +11 -1
  418. package/dist/lib/teams/api.js +11 -2
  419. package/dist/lib/teams/delivery.d.ts +41 -0
  420. package/dist/lib/teams/delivery.js +60 -0
  421. package/dist/lib/teams/registry.d.ts +14 -0
  422. package/dist/lib/teams/registry.js +51 -1
  423. package/dist/lib/teams/remoteWorktree.d.ts +19 -0
  424. package/dist/lib/teams/remoteWorktree.js +29 -0
  425. package/dist/lib/teams/scheduler.d.ts +1 -1
  426. package/dist/lib/teams/scheduler.js +1 -1
  427. package/dist/lib/teams/worktree.d.ts +24 -0
  428. package/dist/lib/teams/worktree.js +42 -0
  429. package/dist/lib/terminal/backends/vscodium-agent.d.ts +10 -1
  430. package/dist/lib/terminal/backends/vscodium-agent.js +16 -5
  431. package/dist/lib/terminal/engine.d.ts +4 -0
  432. package/dist/lib/terminal/engine.js +8 -2
  433. package/dist/lib/terminal/types.d.ts +21 -2
  434. package/dist/lib/testdata/refresh-coordinator-worker.d.ts +1 -0
  435. package/dist/lib/testdata/refresh-coordinator-worker.js +23 -0
  436. package/dist/lib/tickets/list.d.ts +53 -0
  437. package/dist/lib/tickets/list.js +153 -0
  438. package/dist/lib/tmux/orphan-reap.d.ts +316 -0
  439. package/dist/lib/tmux/orphan-reap.js +638 -0
  440. package/dist/lib/tmux/session.d.ts +68 -3
  441. package/dist/lib/tmux/session.js +96 -5
  442. package/dist/lib/triggers/handlers.d.ts +20 -0
  443. package/dist/lib/triggers/handlers.js +16 -1
  444. package/dist/lib/triggers/webhook.js +10 -0
  445. package/dist/lib/types.d.ts +47 -35
  446. package/dist/lib/usage-fleet.d.ts +32 -0
  447. package/dist/lib/usage-fleet.js +125 -0
  448. package/dist/lib/usage-refresh.d.ts +3 -3
  449. package/dist/lib/usage-refresh.js +19 -16
  450. package/dist/lib/usage.d.ts +51 -47
  451. package/dist/lib/usage.js +145 -153
  452. package/dist/lib/version-duplicates.js +2 -2
  453. package/dist/lib/versions.d.ts +56 -13
  454. package/dist/lib/versions.js +195 -45
  455. package/dist/lib/watchdog/log.d.ts +1 -1
  456. package/dist/lib/watchdog/log.js +3 -3
  457. package/dist/lib/watchdog/rotate.d.ts +6 -6
  458. package/dist/lib/watchdog/rotate.js +6 -6
  459. package/dist/lib/workflows.d.ts +1 -1
  460. package/dist/lib/yaml-io.d.ts +47 -0
  461. package/dist/lib/yaml-io.js +55 -0
  462. package/package.json +2 -1
  463. package/scripts/install-helper.js +2 -2
  464. package/scripts/postinstall.js +23 -20
  465. package/dist/commands/defaults.d.ts +0 -7
  466. package/dist/commands/defaults.js +0 -107
  467. package/dist/commands/export.d.ts +0 -11
  468. package/dist/commands/export.js +0 -215
  469. package/dist/commands/helper.d.ts +0 -12
  470. package/dist/commands/helper.js +0 -87
  471. package/dist/commands/hosts.d.ts +0 -11
  472. package/dist/commands/hosts.js +0 -330
  473. package/dist/commands/lock.d.ts +0 -12
  474. package/dist/commands/lock.js +0 -70
  475. package/dist/commands/pull.d.ts +0 -17
  476. package/dist/commands/pull.js +0 -39
  477. package/dist/commands/push.d.ts +0 -14
  478. package/dist/commands/push.js +0 -30
  479. package/dist/commands/set.d.ts +0 -15
  480. package/dist/commands/set.js +0 -79
  481. package/dist/commands/setup-share.d.ts +0 -17
  482. package/dist/commands/setup-share.js +0 -85
  483. package/dist/commands/wallet.d.ts +0 -20
  484. package/dist/commands/wallet.js +0 -216
  485. package/dist/commands/worktree.d.ts +0 -19
  486. package/dist/commands/worktree.js +0 -272
  487. package/dist/lib/account-labels.d.ts +0 -24
  488. package/dist/lib/account-labels.js +0 -72
  489. package/dist/lib/auto-dispatch-linear.d.ts +0 -18
  490. package/dist/lib/auto-dispatch-linear.js +0 -107
  491. package/dist/lib/auto-dispatch-provider.d.ts +0 -10
  492. package/dist/lib/auto-dispatch-provider.js +0 -30
  493. package/dist/lib/auto-dispatch.d.ts +0 -93
  494. package/dist/lib/auto-dispatch.js +0 -128
  495. package/dist/lib/export.d.ts +0 -72
  496. package/dist/lib/export.js +0 -269
  497. package/dist/lib/lock.d.ts +0 -93
  498. package/dist/lib/lock.js +0 -207
  499. package/dist/lib/wallet/index.d.ts +0 -78
  500. package/dist/lib/wallet/index.js +0 -253
@@ -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
+ }
@@ -1,4 +1,4 @@
1
- // Cloudflare Web Analytics injection for `agents share`.
1
+ // Cloudflare Web Analytics injection for `agents artifacts share`.
2
2
  //
3
3
  // The beacon is cookieless and privacy-first, which matters because a lot of shared
4
4
  // content (games, kid-facing pages) should avoid GA4-style tracking. The token is
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Render an HTML file to a 1200×630 PNG — the Open Graph cover for a shared plan.
3
3
  *
4
- * When `agents share plan.html` runs, we screenshot the plan's own hero and use it
4
+ * When `agents artifacts share plan.html` runs, we screenshot the plan's own hero and use it
5
5
  * as the `og:image`, so the link unfurls into a card in Slack / iMessage / Twitter /
6
6
  * Discord. No AI, no central render service: it's a headless screenshot on the
7
7
  * publisher's machine, so it works identically for us and for any user, and costs
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Render an HTML file to a 1200×630 PNG — the Open Graph cover for a shared plan.
3
3
  *
4
- * When `agents share plan.html` runs, we screenshot the plan's own hero and use it
4
+ * When `agents artifacts share plan.html` runs, we screenshot the plan's own hero and use it
5
5
  * as the `og:image`, so the link unfurls into a card in Slack / iMessage / Twitter /
6
6
  * Discord. No AI, no central render service: it's a headless screenshot on the
7
7
  * publisher's machine, so it works identically for us and for any user, and costs
@@ -112,7 +112,7 @@ export async function captureCover(htmlPath, timeoutMs = 15_000) {
112
112
  // A silently-dropped cover reads as "the CLI decided this page needs none",
113
113
  // when in fact no headless browser was found. Say so and point at the escape
114
114
  // hatch instead of leaving the publish coverless with no explanation.
115
- process.stderr.write('[agents share] no headless browser found for the OG cover — install Chrome/Chromium ' +
115
+ process.stderr.write('[agents artifacts share] no headless browser found for the OG cover — install Chrome/Chromium ' +
116
116
  'or set AGENTS_SHARE_BROWSER=/path/to/chrome. Publishing without a preview image.\n');
117
117
  return null;
118
118
  }
@@ -159,7 +159,7 @@ export async function captureCover(htmlPath, timeoutMs = 15_000) {
159
159
  }
160
160
  // Every candidate ran but none yielded a cover — surface the last reason so a
161
161
  // missing preview card is diagnosable (timeout, crash, bad binary) rather than silent.
162
- process.stderr.write(`[agents share] OG cover capture failed (${lastFailure || 'unknown error'}) — ` +
162
+ process.stderr.write(`[agents artifacts share] OG cover capture failed (${lastFailure || 'unknown error'}) — ` +
163
163
  'publishing without a preview image. Set AGENTS_SHARE_BROWSER to override.\n');
164
164
  return null;
165
165
  }
@@ -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";
@@ -18,7 +22,7 @@ export declare const DEFAULT_BUCKET_NAME = "agents-share";
18
22
  export declare const DEFAULT_SHARE_DOMAIN = "share.agents-cli.sh";
19
23
  /** The write token may be injected ephemerally into fleet/cloud agents. */
20
24
  export declare function readWriteTokenEnv(env?: NodeJS.ProcessEnv): string | null;
21
- /** Read the persisted endpoint config, or null if `agents share setup`/`join` never ran. */
25
+ /** Read the persisted endpoint config, or null if `agents artifacts setup` / `agents artifacts share join` never ran. */
22
26
  export declare function readShareConfig(): ShareConfig | null;
23
27
  /** Persist the endpoint config to `agents.yaml` (syncs across the fleet). */
24
28
  export declare function writeShareConfig(cfg: ShareConfig): void;
@@ -42,7 +46,7 @@ export declare function readWriteToken(): string;
42
46
  * launch. The read is now always `agentOnly` — it resolves the token only from the
43
47
  * injected env or an already-held / no-ACL bundle, and silently returns undefined
44
48
  * otherwise (the caller runs without auto-share; the agent can still publish via
45
- * its own `agents share`). To get zero-friction auto-share with no prompt: unlock
49
+ * its own `agents artifacts share`). To get zero-friction auto-share with no prompt: unlock
46
50
  * once (`agents secrets unlock share`) or make it no-ACL (`agents secrets policy
47
51
  * share never`). */
48
52
  export declare function shareRuntimeEnv(): Record<string, string> | undefined;
@@ -1,4 +1,4 @@
1
- // Config + credential glue for `agents share`.
1
+ // Config + credential glue for `agents artifacts share`.
2
2
  //
3
3
  // - The endpoint config (base URL, account, worker/bucket names) lives in
4
4
  // `agents.yaml` under `share:` (Meta.share) so it syncs fleet-wide via
@@ -23,7 +23,7 @@ export function readWriteTokenEnv(env = process.env) {
23
23
  const token = env[SHARE_TOKEN_ENV_KEY]?.trim();
24
24
  return token ? token : null;
25
25
  }
26
- /** Read the persisted endpoint config, or null if `agents share setup`/`join` never ran. */
26
+ /** Read the persisted endpoint config, or null if `agents artifacts setup` / `agents artifacts share join` never ran. */
27
27
  export function readShareConfig() {
28
28
  const s = readMeta().share;
29
29
  if (!s?.baseUrl || !s.accountId || !s.workerName || !s.bucketName)
@@ -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). */
@@ -55,7 +56,7 @@ export function storeWriteToken(token) {
55
56
  catch {
56
57
  bundle = {
57
58
  name: SHARE_BUNDLE,
58
- description: 'agents share — write token for the R2 share endpoint',
59
+ description: 'agents artifacts share — write token for the R2 share endpoint',
59
60
  // A NEW share bundle defaults to the `never` tier (no biometry ACL). The R2
60
61
  // write token is low-sensitivity automation infra that is auto-read on EVERY
61
62
  // `agents run` (shareRuntimeEnv) — a biometry ACL there is what produced the
@@ -82,7 +83,7 @@ export function readWriteTokenFromBundle() {
82
83
  const token = env[SHARE_TOKEN_KEY];
83
84
  if (!token) {
84
85
  throw new Error(`No ${SHARE_TOKEN_KEY} in the '${SHARE_BUNDLE}' secrets bundle. ` +
85
- `Run 'agents share setup' (to provision your own endpoint) or 'agents share join' (to use an existing one).`);
86
+ `Run 'agents artifacts setup' (to provision your own endpoint) or 'agents artifacts share join' (to use an existing one).`);
86
87
  }
87
88
  return token;
88
89
  }
@@ -101,7 +102,7 @@ export function readWriteToken() {
101
102
  * launch. The read is now always `agentOnly` — it resolves the token only from the
102
103
  * injected env or an already-held / no-ACL bundle, and silently returns undefined
103
104
  * otherwise (the caller runs without auto-share; the agent can still publish via
104
- * its own `agents share`). To get zero-friction auto-share with no prompt: unlock
105
+ * its own `agents artifacts share`). To get zero-friction auto-share with no prompt: unlock
105
106
  * once (`agents secrets unlock share`) or make it no-ACL (`agents secrets policy
106
107
  * share never`). */
107
108
  export function shareRuntimeEnv() {
@@ -1,4 +1,4 @@
1
- // The delete path for `agents share delete` / `agents unshare` — an authed DELETE
1
+ // The delete path for `agents artifacts share delete` / `agents unshare` — an authed DELETE
2
2
  // to the Worker, which already implements it (worker-template.ts). Mirrors
3
3
  // publish.ts: pure target-resolution logic is exported for tests, the network
4
4
  // calls (a status check + a delete) sit behind an injectable DI seam.
@@ -76,7 +76,7 @@ export async function deleteObject(endpoint, key, opts = {}) {
76
76
  const existedBefore = before.status !== 404;
77
77
  const r = await del(url, { authorization: `Bearer ${endpoint.token}` });
78
78
  if (!r.ok) {
79
- throw new Error(`Delete failed (${r.status}) for ${url}. Check the write token, or that 'agents share setup' completed.`);
79
+ throw new Error(`Delete failed (${r.status}) for ${url}. Check the write token, or that 'agents artifacts setup' completed.`);
80
80
  }
81
81
  const after = await check(url);
82
82
  const verified404 = after.status === 404;
@@ -88,7 +88,7 @@ export async function deleteObject(endpoint, key, opts = {}) {
88
88
  export async function deleteShare(target, opts = {}) {
89
89
  const cfg = opts.config ?? readShareConfig();
90
90
  if (!cfg) {
91
- throw new Error("Not set up yet. Run 'agents share setup' (provision your own endpoint) or 'agents share join' (use an existing one).");
91
+ throw new Error("Not set up yet. Run 'agents artifacts setup' (provision your own endpoint) or 'agents artifacts share join' (use an existing one).");
92
92
  }
93
93
  const token = opts.writeToken ?? readWriteToken();
94
94
  const resolved = await resolveDeleteTarget(target, { githubUser: opts.githubUser });
@@ -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. */
@@ -1,8 +1,9 @@
1
- // Cloudflare provisioning for `agents share setup` — plain `fetch` against the CF
1
+ // Cloudflare provisioning for `agents artifacts setup` — plain `fetch` against the CF
2
2
  // REST API (the repo has no CF wrapper). Creates the R2 bucket, configures its
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 artifacts share` publish/delete 401s until a re-run of `agents artifacts 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 artifacts 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;