@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
@@ -373,15 +373,14 @@ function overlayUserRoutineDevices(job, userJob) {
373
373
  /**
374
374
  * List all job configs, scanning project > user > system routine dirs.
375
375
  * Higher layers shadow lower ones of the same name (first-seen wins): a project
376
- * routine shadows a user routine, and a user routine shadows a built-in system
377
- * routine (`~/.agents/.system/routines/`, shipped via gh:phnx-labs/.agents-system).
376
+ * routine shadows a user routine, and a user routine shadows a system routine
377
+ * (`~/.agents/.system/routines/`, shipped via gh:phnx-labs/.agents-system).
378
378
  * When a same-name project routine wins for inspection, the user-layer
379
379
  * `devices` allowlist is overlaid only if the project routine does not declare
380
380
  * its own allowlist, so CWD project discovery cannot hide an operational fleet
381
381
  * pin or erase a project-authored one.
382
382
  * Project discovery is opt-in via `cwd`; the daemon (which calls `listJobs()`
383
- * with no argument) sees user + system routines, so a built-in routine fires for
384
- * every install unless the user overrides or disables it by name.
383
+ * with no argument) sees user + system routines.
385
384
  */
386
385
  export function listJobs(cwd) {
387
386
  ensureAgentsDir();
@@ -421,8 +420,7 @@ export function listJobs(cwd) {
421
420
  * the project routine does not declare its own allowlist, for the same reason
422
421
  * as listJobs().
423
422
  * Project discovery is opt-in via `cwd`; daemon callers pass no argument and
424
- * resolve user + system routines (a user routine of the same name shadows a
425
- * built-in system routine).
423
+ * resolve user + system routines.
426
424
  */
427
425
  export function readJob(name, cwd) {
428
426
  ensureAgentsDir();
@@ -458,29 +456,51 @@ function readJobFromDir(dir, name) {
458
456
  }
459
457
  return null;
460
458
  }
461
- function readJobFile(filePath) {
459
+ /**
460
+ * Read one routine file, preserving WHY it failed.
461
+ *
462
+ * `readJobFile` collapses all four fail-closed paths to `null`, which is right
463
+ * for the loaders (an inert routine must not run) but leaves a broken routine
464
+ * invisible in every view — the one routine an operator most needs to see. Same
465
+ * reading, reason kept, for diagnostic surfaces like `agents inspect --routines`.
466
+ */
467
+ export function readJobFileResult(filePath) {
468
+ let content;
462
469
  try {
463
- const content = fs.readFileSync(filePath, 'utf-8');
464
- const parsed = yaml.parse(content);
465
- if (!parsed || typeof parsed !== 'object')
466
- return null;
467
- // Fail closed on the legacy singular `device` key. A routine that still
468
- // carries it after v12 startup migration is unmigrated state and must be
469
- // treated as unavailable/inert rather than unrestricted.
470
- if (Object.prototype.hasOwnProperty.call(parsed, 'device'))
471
- return null;
472
- // Fail closed on a malformed `devices` too. Ownership treats a non-array as
473
- // "no pin", and the daemon's load path never calls validateJob — so a YAML
474
- // typo (`devices: yosemite-s0` instead of a list) would silently promote the
475
- // routine to fleet-wide and fire it on EVERY box. Inert-and-loud beats
476
- // unrestricted-and-silent.
477
- if (Object.prototype.hasOwnProperty.call(parsed, 'devices')
478
- && parsed.devices !== undefined
479
- && parsed.devices !== null
480
- && !Array.isArray(parsed.devices)) {
481
- return null;
482
- }
483
- return {
470
+ content = fs.readFileSync(filePath, 'utf-8');
471
+ }
472
+ catch (err) {
473
+ return { config: null, problem: `unreadable: ${err.message}` };
474
+ }
475
+ let parsed;
476
+ try {
477
+ parsed = yaml.parse(content);
478
+ }
479
+ catch (err) {
480
+ return { config: null, problem: `invalid YAML: ${err.message.split('\n')[0]}` };
481
+ }
482
+ if (!parsed || typeof parsed !== 'object') {
483
+ return { config: null, problem: 'not a YAML map' };
484
+ }
485
+ // Fail closed on the legacy singular `device` key. A routine that still
486
+ // carries it after v12 startup migration is unmigrated state and must be
487
+ // treated as unavailable/inert rather than unrestricted.
488
+ if (Object.prototype.hasOwnProperty.call(parsed, 'device')) {
489
+ return { config: null, problem: 'legacy `device:` key — inert until migrated to `devices:`' };
490
+ }
491
+ // Fail closed on a malformed `devices` too. Ownership treats a non-array as
492
+ // "no pin", and the daemon's load path never calls validateJob — so a YAML
493
+ // typo (`devices: yosemite-s0` instead of a list) would silently promote the
494
+ // routine to fleet-wide and fire it on EVERY box. Inert-and-loud beats
495
+ // unrestricted-and-silent.
496
+ if (Object.prototype.hasOwnProperty.call(parsed, 'devices')
497
+ && parsed.devices !== undefined
498
+ && parsed.devices !== null
499
+ && !Array.isArray(parsed.devices)) {
500
+ return { config: null, problem: '`devices:` must be a list — routine is inert' };
501
+ }
502
+ return {
503
+ config: {
484
504
  ...JOB_DEFAULTS,
485
505
  ...parsed,
486
506
  name: parsed.name || path.basename(filePath).replace(/\.ya?ml$/, ''),
@@ -488,11 +508,12 @@ function readJobFile(filePath) {
488
508
  // A new built-in definition with no `enabled:` field stays opt-in until
489
509
  // setup materializes this host's routines list.
490
510
  enabled: Object.prototype.hasOwnProperty.call(parsed, 'enabled') ? parsed.enabled !== false : false,
491
- };
492
- }
493
- catch {
494
- return null;
495
- }
511
+ },
512
+ problem: null,
513
+ };
514
+ }
515
+ function readJobFile(filePath) {
516
+ return readJobFileResult(filePath).config;
496
517
  }
497
518
  /** Write a job config to disk, omitting fields that match defaults.
498
519
  *
@@ -589,7 +610,12 @@ export function serializeJob(output, existingText) {
589
610
  if (!(key in output))
590
611
  doc.delete(key);
591
612
  }
592
- return doc.toString();
613
+ // `flowCollectionPadding: false` keeps a re-serialized flow sequence in the
614
+ // committed no-padding form (`[a, b]`, not `[ a, b ]`). Routine YAML lives in
615
+ // the same git-backed `~/.agents` repo as agents.yaml, so the same emitter
616
+ // padding would leave the tracked file dirty and block `agents repo pull`
617
+ // fleet-wide (RUSH-2505). Node styles are otherwise preserved.
618
+ return doc.toString({ flowCollectionPadding: false });
593
619
  }
594
620
  /** Delete a job config file by name. Returns true if the file existed. */
595
621
  export function deleteJob(name) {
@@ -617,6 +643,9 @@ export function setJobEnabled(name, enabled) {
617
643
  export function migrateLegacyRoutineActivation() {
618
644
  if (enabledRoutineNames() !== null)
619
645
  return false;
646
+ // Legacy activation migration preserves FILE-BACKED routines' old
647
+ // `enabled:`/`devices:` state into the device manifest. A box with zero
648
+ // routines never grows a manifest here (nothing enabled or pinned to seed).
620
649
  const jobs = listJobs();
621
650
  if (!jobs.some((job) => job.enabled || Array.isArray(job.devices)))
622
651
  return false;
@@ -1290,6 +1319,35 @@ export function discoverJobsFromRepo(repoPath) {
1290
1319
  export function jobExists(name) {
1291
1320
  return readJob(name) !== null;
1292
1321
  }
1322
+ /**
1323
+ * True when `sourcePath` already IS the canonical user-layer file for `name`.
1324
+ *
1325
+ * `agents routines add <file>` copies a definition into the routines dir, but
1326
+ * users routinely point it at the file that already lives there — the release
1327
+ * train's own `~/.agents/routines/release-train.yml`. `writeJob` would then
1328
+ * re-serialize that file in place and, per {@link serializeJob}, delete every
1329
+ * key absent from the canonical output — silently dropping the legacy
1330
+ * `devices:` pin from config tracked in the git-backed `~/.agents` repo
1331
+ * (RUSH-2517). Callers use this to skip the write when there is nothing to
1332
+ * copy.
1333
+ *
1334
+ * Compares real paths so a symlinked `~/.agents` (the normal layout) still
1335
+ * matches, and falls back to a resolved-path compare when either side cannot be
1336
+ * realpath'd.
1337
+ */
1338
+ export function isCanonicalRoutineSource(sourcePath, name) {
1339
+ const jobsDir = getRoutinesDir();
1340
+ const real = (p) => {
1341
+ try {
1342
+ return fs.realpathSync(p);
1343
+ }
1344
+ catch {
1345
+ return path.resolve(p);
1346
+ }
1347
+ };
1348
+ const source = real(sourcePath);
1349
+ return ['.yml', '.yaml'].some((ext) => real(safeJoin(jobsDir, name + ext)) === source);
1350
+ }
1293
1351
  /** Get the filesystem path of a job's YAML config file, or null if not found. */
1294
1352
  export function getJobPath(name) {
1295
1353
  const jobsDir = getRoutinesDir();
@@ -12,6 +12,7 @@
12
12
  * mode: plan
13
13
  */
14
14
  import type { AgentId, Mode, RunConfig, RunDefaults } from './types.js';
15
+ export declare const VERSION_RE: RegExp;
15
16
  export interface ParsedRunDefaultSelector {
16
17
  agent: AgentId;
17
18
  version: string;
@@ -42,4 +43,8 @@ export declare function formatRunDefaultEntry(entry: RunDefaultEntry): string;
42
43
  export declare function listRunDefaults(): RunDefaultEntry[];
43
44
  export declare function setRunDefault(selectorInput: string, defaultsInput: RunDefaultsInput): RunDefaultEntry;
44
45
  export declare function unsetRunDefault(selectorInput: string): boolean;
46
+ /** Convenience setters used by `agents config` for single-field updates. */
47
+ export declare function setRunDefaultModel(selectorInput: string, model: string): RunDefaultEntry;
48
+ export declare function setRunDefaultMode(selectorInput: string, mode: string): RunDefaultEntry;
49
+ export declare function setRunDefaultEffort(selectorInput: string, effort: string): RunDefaultEntry;
45
50
  export {};
@@ -16,7 +16,7 @@ import { AGENTS } from './agents.js';
16
16
  import { readMeta, updateMeta } from './state.js';
17
17
  import { getProjectRunConfigs } from './run-config.js';
18
18
  import chalk from 'chalk';
19
- const VERSION_RE = /^(?:\*|latest|(?!.*\.\.)[A-Za-z0-9._+-]{1,64})$/;
19
+ export const VERSION_RE = /^(?:\*|latest|(?!.*\.\.)[A-Za-z0-9._+-]{1,64})$/;
20
20
  const RUN_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max', 'auto'];
21
21
  function isAgentId(value) {
22
22
  return value in AGENTS;
@@ -208,3 +208,13 @@ export function unsetRunDefault(selectorInput) {
208
208
  });
209
209
  return removed;
210
210
  }
211
+ /** Convenience setters used by `agents config` for single-field updates. */
212
+ export function setRunDefaultModel(selectorInput, model) {
213
+ return setRunDefault(selectorInput, { model });
214
+ }
215
+ export function setRunDefaultMode(selectorInput, mode) {
216
+ return setRunDefault(selectorInput, { mode });
217
+ }
218
+ export function setRunDefaultEffort(selectorInput, effort) {
219
+ return setRunDefault(selectorInput, { effort });
220
+ }
@@ -14,10 +14,11 @@
14
14
  * fires once with the pre-flight pick).
15
15
  */
16
16
  import type { JobConfig, RunMeta } from './routines.js';
17
+ import { readMeta } from './state.js';
17
18
  import type { AgentId } from './types.js';
18
19
  import { type FallbackEntry } from './exec.js';
19
20
  import type { LoopDeps } from './loop.js';
20
- import { resolveRunVersion, type RotateResult } from './rotate.js';
21
+ import { resolveRunVersion, resolveAccountVersion, type RotateResult } from './rotate.js';
21
22
  /** Result of a completed job execution, including metadata and optional report. */
22
23
  export interface RunResult {
23
24
  meta: RunMeta;
@@ -43,7 +44,7 @@ export interface RoutineTrigger {
43
44
  */
44
45
  export declare function routineSpawnCwd(config: Pick<JobConfig, 'name' | 'project' | 'cwd' | 'agent' | 'workflow' | 'command'>): string;
45
46
  /** Build the full CLI argv for executing a job, applying mode, model, and permission flags. */
46
- export declare function buildJobCommand(config: JobConfig, resolvedPrompt: string): string[];
47
+ export declare function buildJobCommand(config: JobConfig, resolvedPrompt: string, forwardAccount?: boolean): string[];
47
48
  /**
48
49
  * Record every transcript file already present in the child's transcript dirs BEFORE
49
50
  * the run spawns. When the transcript lands in a shared per-version home, this baseline
@@ -61,6 +62,8 @@ export interface RoutineLaunchPlan {
61
62
  rotation: RotateResult | null;
62
63
  /** True when `config.version` pinned the target (no rotation). */
63
64
  pinned: boolean;
65
+ /** False when `account` names a harness-native login rather than a durable credential. */
66
+ forwardAccount?: boolean;
64
67
  }
65
68
  /**
66
69
  * Resolve the version/account chain for a routine the same way `agents run`
@@ -73,13 +76,12 @@ export interface RoutineLaunchPlan {
73
76
  */
74
77
  export declare function resolveRoutineLaunch(config: JobConfig, cwd?: string, deps?: {
75
78
  resolveRunVersion?: typeof resolveRunVersion;
76
- readAccountLabels?: () => {
77
- labels: Record<string, {
78
- agent: AgentId;
79
- fingerprint: string;
80
- }>;
79
+ resolveAccountVersion?: typeof resolveAccountVersion;
80
+ findCredentialAccount?: (name: string) => boolean;
81
+ readMeta?: typeof readMeta;
82
+ resolveCredentialAccount?: (name: string, host: AgentId) => {
83
+ env: Record<string, string>;
81
84
  };
82
- resolveAccountLabel?: (agent: AgentId, label: string) => Promise<string>;
83
85
  }): Promise<RoutineLaunchPlan>;
84
86
  /**
85
87
  * Rewrite `cmd[0]` to the absolute binary for `agent@version` when installed.
@@ -17,13 +17,15 @@ import { spawn, execFileSync } from 'child_process';
17
17
  import * as fs from 'fs';
18
18
  import * as path from 'path';
19
19
  import * as os from 'os';
20
+ import { getCliLaunch, getAgentsBinDir } from './cli-entry.js';
20
21
  import { resolveJobPrompt, parseTimeout, writeRunMeta, listRuns, getJobRunsDir, getRunDir, checkJobDeviceEligibility, finalizeRunMeta, resolveJobExecutionContext, slotRunId, claimRunSlot, readRunMeta, resolveHostStrategy, } from './routines.js';
21
- import { getRunsDir, getUserAgentsDir } from './state.js';
22
+ import { getRunsDir, getUserAgentsDir, readMeta } from './state.js';
22
23
  import { shortCodexHome } from './codex-home.js';
23
24
  import { prepareJobHome, buildSpawnEnv, getJobHomePath } from './sandbox.js';
24
25
  import { resolveModel, buildReasoningFlags } from './models.js';
25
- import { createTimer, redactPrompt } from './events.js';
26
+ import { createTimer, redactPrompt, emitRoutineEnd } from './events.js';
26
27
  import { codexEditWritableRoots, codexPolicyArgs } from './codex-policy.js';
28
+ import { applyAddDirs } from './add-dir.js';
27
29
  import { normalizeMode, resolveHeadlessMode, buildExecEnv, detectRateLimit, detectAuthFailure, isAuthFailureFromLog, authFailureReason, } from './exec.js';
28
30
  import { resolveActor } from './actor.js';
29
31
  import { loadTask as loadHostTask } from './hosts/tasks.js';
@@ -369,13 +371,15 @@ export function routineSpawnCwd(config) {
369
371
  return ctx.absoluteCwd ?? os.homedir();
370
372
  }
371
373
  /** Build the full CLI argv for executing a job, applying mode, model, and permission flags. */
372
- export function buildJobCommand(config, resolvedPrompt) {
374
+ export function buildJobCommand(config, resolvedPrompt, forwardAccount = true) {
373
375
  // Workflow branch: delegate to `agents run <workflow>` which handles subagent
374
376
  // injection, WORKFLOW.md orchestration, and model selection via frontmatter.
375
377
  // appendModelAndReasoning is intentionally skipped — the workflow frontmatter
376
378
  // owns model selection. No --timeout flag: the runner enforces its own SIGTERM/SIGKILL.
377
379
  if (config.workflow) {
378
380
  const cmd = ['agents', 'run', config.workflow, resolvedPrompt, '--mode', config.mode];
381
+ if (config.account && forwardAccount)
382
+ cmd.push('--account', config.account);
379
383
  return cmd;
380
384
  }
381
385
  // Past the workflow branch this is an agent (or resume) job — command jobs never
@@ -387,7 +391,10 @@ export function buildJobCommand(config, resolvedPrompt) {
387
391
  // so a self-scheduled wake (e.g. /hibernate) is handled by the session that scheduled
388
392
  // it, not a fresh, context-less agent that would refuse an "opaque" instruction.
389
393
  if (config.resume) {
390
- return ['agents', 'run', agent, '--resume', config.resume, resolvedPrompt, '--mode', config.mode];
394
+ const cmd = ['agents', 'run', agent, '--resume', config.resume, resolvedPrompt, '--mode', config.mode];
395
+ if (config.account && forwardAccount)
396
+ cmd.push('--account', config.account);
397
+ return cmd;
391
398
  }
392
399
  const template = AGENT_COMMANDS[agent];
393
400
  if (!template) {
@@ -413,18 +420,6 @@ export function buildJobCommand(config, resolvedPrompt) {
413
420
  if (pmIndex !== -1)
414
421
  cmd.splice(pmIndex, 2, '--dangerously-skip-permissions');
415
422
  }
416
- if (config.allow?.dirs) {
417
- for (const dir of config.allow.dirs) {
418
- // Reject leading '-' so a routine YAML can't smuggle an argv flag like
419
- // `--dangerously-skip-permissions` past the sandbox by hiding it as an
420
- // allow.dirs entry.
421
- if (dir.startsWith('-')) {
422
- throw new Error(`allow.dirs entries must not start with '-': ${JSON.stringify(dir)}`);
423
- }
424
- const resolved = dir.replace(/^~/, os.homedir());
425
- cmd.push('--add-dir', resolved);
426
- }
427
- }
428
423
  appendModelAndReasoning(cmd, config);
429
424
  }
430
425
  if (config.agent === 'codex') {
@@ -500,6 +495,20 @@ export function buildJobCommand(config, resolvedPrompt) {
500
495
  // edit: default on-request approval + sandbox
501
496
  appendModelAndReasoning(cmd, config);
502
497
  }
498
+ // allow.dirs → harness-specific grants. Codex is handled in its branch above
499
+ // (workspace_roots). Claude / Kimi / Cursor take --add-dir; Grok gets rules
500
+ // (+ sandbox widen when GROK_SANDBOX is on). Reject leading '-' so a routine
501
+ // YAML can't smuggle an argv flag past the sandbox as an allow.dirs entry.
502
+ if (config.allow?.dirs?.length && agent !== 'codex') {
503
+ for (const dir of config.allow.dirs) {
504
+ if (dir.startsWith('-')) {
505
+ throw new Error(`allow.dirs entries must not start with '-': ${JSON.stringify(dir)}`);
506
+ }
507
+ }
508
+ applyAddDirs(agent, cmd, config.allow.dirs, {
509
+ cwd: routineSpawnCwd(config),
510
+ });
511
+ }
503
512
  return cmd;
504
513
  }
505
514
  /**
@@ -676,17 +685,59 @@ function buildShellCommand(command) {
676
685
  * Real (un-sandboxed) environment for a command routine. Command routines do
677
686
  * `npm i -g` / `git pull` and need the actual $HOME / $PATH, not the sandbox
678
687
  * overlay. Only TZ is injected when the routine pins a timezone.
688
+ *
689
+ * The current binary's directory is prepended to PATH so bare `agents` invocations
690
+ * resolve to the same install on Windows (where shell-function injection is not
691
+ * available) and as a fallback on POSIX for invocations like `command agents`.
679
692
  */
680
693
  function commandSpawnEnv(config) {
681
694
  const env = { ...process.env };
682
695
  if (config.timezone)
683
696
  env.TZ = config.timezone;
697
+ const sep = process.platform === 'win32' ? ';' : ':';
698
+ const binDir = getAgentsBinDir();
699
+ const existing = env.PATH ?? '';
700
+ if (!existing.split(sep).includes(binDir)) {
701
+ env.PATH = existing ? `${binDir}${sep}${existing}` : binDir;
702
+ }
684
703
  return env;
685
704
  }
686
705
  /** POSIX single-quote a string so it is safe to embed in a `/bin/sh -c` script. */
687
706
  function shSingleQuote(s) {
688
707
  return `'${s.replace(/'/g, `'\\''`)}'`;
689
708
  }
709
+ /**
710
+ * Build a POSIX shell function that forwards `agents <sub...>` to the SAME binary
711
+ * currently running. Command routines shell out to the bare name `agents`
712
+ * (e.g. `agents repo pull system`); without this, the routine resolves `agents`
713
+ * through its inherited PATH, which can pick up a stale install in an nvm/system
714
+ * Node prefix that shadows the current binary (RUSH-2431).
715
+ *
716
+ * Uses getCliLaunch so the relaunch is correct for both JS installs
717
+ * (`node <entry> <sub...>`) and compiled standalone binaries (`<bin> <sub...>`).
718
+ */
719
+ function agentsShellFunction() {
720
+ const launch = getCliLaunch(['__ac_placeholder__']);
721
+ const parts = [launch.command];
722
+ // JS installs: getCliLaunch returns [node, entryScript, placeholder].
723
+ // Standalone: it returns [binary, placeholder].
724
+ if (launch.args.length > 0 && launch.args[0] !== '__ac_placeholder__' && fs.existsSync(launch.args[0])) {
725
+ parts.push(launch.args[0]);
726
+ }
727
+ const invocation = parts.map(shSingleQuote).join(' ');
728
+ return `agents() { ${invocation} "$@"; }`;
729
+ }
730
+ /**
731
+ * Wrap a command-routine shell string so any bare `agents` invocation resolves
732
+ * to the current binary. On POSIX this injects an `agents` shell function; on
733
+ * Windows it is left unchanged and commandSpawnEnv prepends the current binary's
734
+ * directory to PATH instead.
735
+ */
736
+ function wrapCommandRoutine(command) {
737
+ if (process.platform === 'win32')
738
+ return command;
739
+ return `${agentsShellFunction()}\n${command}`;
740
+ }
690
741
  /**
691
742
  * Detached command routines write their own exit code to `<runDir>/exit-code`
692
743
  * (see the wrapper in executeCommandJobDetached). `monitorRunningJobs` reads it
@@ -721,6 +772,31 @@ export async function resolveRoutineLaunch(config, cwd = process.cwd(), deps = {
721
772
  // resolveRoutineLaunch is only called for agent jobs (workflow returns above;
722
773
  // command jobs branch out of execute*Job before reaching this).
723
774
  const agent = config.agent;
775
+ const { findAccount, resolveAccountSelection, resolveCredentialAccount } = await import('./account-registry.js');
776
+ const explicitCredential = config.account
777
+ ? (deps.findCredentialAccount?.(config.account) ?? (deps.resolveCredentialAccount !== undefined || findAccount(config.account) !== null))
778
+ : false;
779
+ const selectedCredential = config.account
780
+ ? (explicitCredential ? config.account : undefined)
781
+ : resolveAccountSelection(undefined, agent, (deps.readMeta ?? readMeta)());
782
+ if (selectedCredential) {
783
+ (deps.resolveCredentialAccount ?? resolveCredentialAccount)(selectedCredential, agent);
784
+ }
785
+ if (config.account && !explicitCredential) {
786
+ const accountVersion = await (deps.resolveAccountVersion ?? resolveAccountVersion)(agent, config.account);
787
+ if (accountVersion) {
788
+ if (config.version && config.version !== accountVersion) {
789
+ throw new Error(`Routine '${config.name}' account '${config.account}' is signed in at ${agent}@${accountVersion}, not pinned ${agent}@${config.version}.`);
790
+ }
791
+ return {
792
+ chain: [{ agent, version: config.version ?? accountVersion }],
793
+ rotation: null,
794
+ pinned: true,
795
+ forwardAccount: false,
796
+ };
797
+ }
798
+ throw new Error(`Routine '${config.name}' account '${config.account}' is not signed in for ${agent}; refusing to rotate to another account.`);
799
+ }
724
800
  if (config.version) {
725
801
  const version = config.version;
726
802
  if (!isVersionInstalled(agent, version)) {
@@ -730,26 +806,9 @@ export async function resolveRoutineLaunch(config, cwd = process.cwd(), deps = {
730
806
  chain: [{ agent, version }],
731
807
  rotation: null,
732
808
  pinned: true,
809
+ ...(config.account ? { forwardAccount: explicitCredential } : {}),
733
810
  };
734
811
  }
735
- // Account pin: resolve the login identity to the version slot that holds it and
736
- // run pinned — no rotation, no failover onto other accounts — so concurrent
737
- // unattended routines never share (and mutually revoke) one single-use OAuth
738
- // credential (RUSH-1957). Falls through to the strategy only when the account
739
- // is not signed in on this box, with a loud warning rather than a silent stall.
740
- if (config.account) {
741
- const { readAccountLabels, resolveAccountLabel } = await import('./account-labels.js');
742
- if ((deps.readAccountLabels ?? readAccountLabels)().labels[config.account]) {
743
- const version = await (deps.resolveAccountLabel ?? resolveAccountLabel)(agent, config.account);
744
- return { chain: [{ agent, version }], rotation: null, pinned: true };
745
- }
746
- const version = await resolveAccountVersion(agent, config.account);
747
- if (version) {
748
- return { chain: [{ agent, version }], rotation: null, pinned: true };
749
- }
750
- process.stderr.write(`[agents] routine ${config.name}: account '${config.account}' is not signed in for ${agent}; ` +
751
- `falling back to strategy — pin a signed-in account to stop OAuth-rotation revocation\n`);
752
- }
753
812
  const strategy = getConfiguredRunStrategy(agent, cwd);
754
813
  let version;
755
814
  let rotation = null;
@@ -1051,6 +1110,14 @@ async function executeJobPlaced(config, deps, attempt) {
1051
1110
  // Use 'claude' as the effective agent for report extraction and metadata when workflow is set.
1052
1111
  // (command jobs branched out earlier, so config.agent is set on the non-workflow path.)
1053
1112
  const effectiveAgent = config.workflow ? 'claude' : config.agent;
1113
+ if (!dispatchesViaAgentsRun(config)) {
1114
+ const { findAccount, resolveAccountSelection, resolveCredentialAccount } = await import('./account-registry.js');
1115
+ const selectedAccount = config.account && !findAccount(config.account)
1116
+ ? undefined
1117
+ : resolveAccountSelection(config.account, effectiveAgent, readMeta());
1118
+ if (selectedAccount)
1119
+ Object.assign(baseEnv, resolveCredentialAccount(selectedAccount, effectiveAgent).env);
1120
+ }
1054
1121
  const meta = {
1055
1122
  jobName: config.name,
1056
1123
  runId,
@@ -1129,7 +1196,7 @@ async function executeJobPlaced(config, deps, attempt) {
1129
1196
  }
1130
1197
  // Single-shot path: build the command once, then walk the launch chain on
1131
1198
  // rate/usage-limit failures (same detectRateLimit patterns as agents run).
1132
- const baseCmd = buildJobCommand(config, resolvedPrompt);
1199
+ const baseCmd = buildJobCommand(config, resolvedPrompt, launch.forwardAccount !== false);
1133
1200
  const stdoutPath = path.join(runDir, 'stdout.log');
1134
1201
  // Truncate the log for a clean run; failover attempts append.
1135
1202
  fs.writeFileSync(stdoutPath, '', { mode: 0o600 });
@@ -1425,7 +1492,7 @@ async function executeCommandJobForeground(config, attempt) {
1425
1492
  };
1426
1493
  writeRunMeta(meta);
1427
1494
  const timeoutMs = parseTimeout(config.timeout) || 10 * 60 * 1000;
1428
- const cmd = buildShellCommand(config.command);
1495
+ const cmd = buildShellCommand(wrapCommandRoutine(config.command));
1429
1496
  const env = commandSpawnEnv(config);
1430
1497
  process.stderr.write(`[agents] routine ${config.name}: running command\n`);
1431
1498
  const result = await new Promise((resolve) => {
@@ -1508,10 +1575,14 @@ async function executeJobDetachedClaimed(config, attempt, hooks) {
1508
1575
  const target = resolvePlacementTarget(config);
1509
1576
  if (target.mode === 'host') {
1510
1577
  const { meta } = await executeJobOnHost({ ...config, host: target.host }, { detached: true }, attempt);
1578
+ if (meta.status !== 'running')
1579
+ emitRoutineEnd(meta);
1511
1580
  return meta;
1512
1581
  }
1513
1582
  if (target.mode === 'cloud') {
1514
1583
  const { meta } = await executeJobOnCloud(config, { detached: true }, attempt);
1584
+ if (meta.status !== 'running')
1585
+ emitRoutineEnd(meta);
1515
1586
  return meta;
1516
1587
  }
1517
1588
  }
@@ -1535,7 +1606,7 @@ async function executeJobDetachedClaimed(config, attempt, hooks) {
1535
1606
  schedule: config.schedule,
1536
1607
  });
1537
1608
  const resolvedPrompt = resolveJobPrompt(config);
1538
- let cmd = buildJobCommand(config, resolvedPrompt);
1609
+ let cmd = buildJobCommand(config, resolvedPrompt, launch.forwardAccount !== false);
1539
1610
  // workflow AND resume dispatch through `agents run` — never binary-pin them (pinning
1540
1611
  // rewrites cmd[0] to the agent binary → broken `<binary> run …`).
1541
1612
  if (!dispatchesViaAgentsRun(config) && version && config.agent) {
@@ -1555,6 +1626,14 @@ async function executeJobDetachedClaimed(config, attempt, hooks) {
1555
1626
  const baseEnv = injectRoutineActor(useSandbox
1556
1627
  ? buildSpawnEnv(overlayHome, config.env)
1557
1628
  : { ...process.env }, config);
1629
+ if (!dispatchesViaAgentsRun(config)) {
1630
+ const { findAccount, resolveAccountSelection, resolveCredentialAccount } = await import('./account-registry.js');
1631
+ const selectedAccount = config.account && !findAccount(config.account)
1632
+ ? undefined
1633
+ : resolveAccountSelection(config.account, config.agent, readMeta());
1634
+ if (selectedAccount)
1635
+ Object.assign(baseEnv, resolveCredentialAccount(selectedAccount, config.agent).env);
1636
+ }
1558
1637
  const spawnEnv = dispatchesViaAgentsRun(config)
1559
1638
  ? (() => {
1560
1639
  const e = { ...baseEnv };
@@ -1701,10 +1780,11 @@ function executeCommandJobDetached(config, attempt, hooks) {
1701
1780
  const exitCodePath = path.join(runDir, 'exit-code');
1702
1781
  // Run the command in a SUBSHELL `( … )` so that if it calls `exit`, only the
1703
1782
  // subshell exits — the outer shell still captures `$?` and writes the file.
1783
+ const wrappedCommand = wrapCommandRoutine(config.command);
1704
1784
  const cmd = process.platform === 'win32'
1705
- ? buildShellCommand(config.command)
1785
+ ? buildShellCommand(wrappedCommand)
1706
1786
  : ['/bin/sh', '-c',
1707
- `(\n${config.command}\n)\n__ac_rc=$?; printf '%s' "$__ac_rc" > ${shSingleQuote(exitCodePath)} 2>/dev/null; exit $__ac_rc`];
1787
+ `(\n${wrappedCommand}\n)\n__ac_rc=$?; printf '%s' "$__ac_rc" > ${shSingleQuote(exitCodePath)} 2>/dev/null; exit $__ac_rc`];
1708
1788
  const env = commandSpawnEnv(config);
1709
1789
  const meta = {
1710
1790
  jobName: config.name,
@@ -1905,6 +1985,7 @@ function finalizeHostRun(meta) {
1905
1985
  return;
1906
1986
  finalizeRunMeta(meta, healed.status, healed.exitCode ?? (healed.status === 'completed' ? 0 : 1), { completedAt: healed.finishedAt ?? undefined });
1907
1987
  writeRunMeta(meta);
1988
+ emitRoutineEnd(meta);
1908
1989
  }
1909
1990
  catch { /* unreachable host or unreadable sidecar — retry next sweep */ }
1910
1991
  }
@@ -2004,6 +2085,7 @@ export function monitorRunningJobs() {
2004
2085
  terminateRoutineTree(meta.pid);
2005
2086
  finalizeRunMeta(meta, 'timeout', null, { errorMessage: 'exceeded configured timeout' });
2006
2087
  writeRunMeta(meta);
2088
+ emitRoutineEnd(meta);
2007
2089
  if (!isCommandRun) {
2008
2090
  extractAndSaveReport(stdoutPath, meta.agent, runDirPath);
2009
2091
  archiveRoutineTranscripts(meta, runDirPath);
@@ -2030,6 +2112,7 @@ export function monitorRunningJobs() {
2030
2112
  }
2031
2113
  }
2032
2114
  writeRunMeta(meta);
2115
+ emitRoutineEnd(meta);
2033
2116
  if (!isCommandRun) {
2034
2117
  extractAndSaveReport(stdoutPath, meta.agent, runDirPath);
2035
2118
  archiveRoutineTranscripts(meta, runDirPath);
@@ -30,6 +30,12 @@ import { type SecretLease } from './lease.js';
30
30
  export { GLOBAL_HARNESS, bundleScopeChain };
31
31
  /** Default lifetime of an unlocked bundle when `--ttl` is not given. */
32
32
  export declare const DEFAULT_TTL_MS: number;
33
+ /**
34
+ * Whether the secrets broker service is enabled in the daemon service config.
35
+ * Off-darwin this is irrelevant (the broker is never used), but the helper is
36
+ * kept synchronous and safe everywhere so callers can fail loud without a prompt.
37
+ */
38
+ export declare function isSecretsBrokerEnabled(): boolean;
33
39
  /**
34
40
  * Reserved store-key prefix for the `secrets list` metadata snapshot cache.
35
41
  * The broker holds the resolved bundle-metadata array (names/policy/timestamps,
@@ -144,6 +150,7 @@ export type Request = {
144
150
  ttlMs: number;
145
151
  lease?: SecretLease;
146
152
  token?: string;
153
+ snapshotAt?: number;
147
154
  } | {
148
155
  cmd: 'lock';
149
156
  name?: string;
@@ -206,7 +213,7 @@ export type Response = {
206
213
  */
207
214
  export declare function realBundleCount(store: Map<string, StoredBundle>): number;
208
215
  export declare function scopedBundleKey(name: string, harness: string): string;
209
- export declare function handleAgentRequest(store: Map<string, StoredBundle>, req: Request, now?: number): Response;
216
+ export declare function handleAgentRequest(store: Map<string, StoredBundle>, req: Request, now?: number, evictedAt?: Map<string, number>): Response;
210
217
  /**
211
218
  * Decide whether a `watch-lock` helper line should wipe the in-memory store.
212
219
  * The helper emits `LOCK` on screen-lock / screensaver and `SLEEP` on system
@@ -451,7 +458,7 @@ export declare function clampHoldMs(v: unknown): number;
451
458
  * The worker reuses the robust `ensureAgentRunning` path (spawn-then-ping) rather
452
459
  * than a tight inline retry loop. Best-effort; never throws. macOS only.
453
460
  */
454
- export declare function agentAutoLoadSync(name: string, bundle: SecretsBundle, env: Record<string, string>, ttlMs: number, harness?: string, lease?: SecretLease): void;
461
+ export declare function agentAutoLoadSync(name: string, bundle: SecretsBundle, env: Record<string, string>, ttlMs: number, harness?: string, lease?: SecretLease, snapshotAt?: number): void;
455
462
  /**
456
463
  * Body of the hidden `secrets _agent-load` worker. Reads one `{name, bundle,
457
464
  * env, ttlMs}` payload from stdin, ensures the broker is up (robust, generous
@@ -466,7 +473,7 @@ export declare function agentAutoLoadSync(name: string, bundle: SecretsBundle, e
466
473
  */
467
474
  export declare function runAgentLoadFromStdin(): Promise<void>;
468
475
  /** Store a resolved bundle in the broker. Returns false on transport failure. */
469
- export declare function agentLoad(name: string, bundle: SecretsBundle, env: Record<string, string>, ttlMs: number, harness?: string, lease?: SecretLease): Promise<boolean>;
476
+ export declare function agentLoad(name: string, bundle: SecretsBundle, env: Record<string, string>, ttlMs: number, harness?: string, lease?: SecretLease, snapshotAt?: number): Promise<boolean>;
470
477
  /** Wipe one bundle (or all if name omitted) from the broker. Returns the count
471
478
  * wiped, or 0 when no broker is running. */
472
479
  export declare function agentLock(name?: string): Promise<number>;