@phnx-labs/agents-cli 1.22.39 → 1.22.41

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 (569) hide show
  1. package/CHANGELOG.md +316 -0
  2. package/README.md +116 -70
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +45 -27
  5. package/dist/browser.js +2 -2
  6. package/dist/cli/command-registry.d.ts +135 -0
  7. package/dist/cli/command-registry.js +259 -0
  8. package/dist/commands/accounts.d.ts +20 -0
  9. package/dist/commands/accounts.js +186 -25
  10. package/dist/commands/apply.d.ts +3 -3
  11. package/dist/commands/apply.js +20 -63
  12. package/dist/commands/browser.d.ts +15 -0
  13. package/dist/commands/browser.js +318 -131
  14. package/dist/commands/budget.d.ts +7 -6
  15. package/dist/commands/budget.js +8 -7
  16. package/dist/commands/cloud.js +17 -20
  17. package/dist/commands/commands.js +1 -1
  18. package/dist/commands/computer-actions.d.ts +1 -35
  19. package/dist/commands/computer-actions.js +13 -181
  20. package/dist/commands/computer.d.ts +28 -3
  21. package/dist/commands/computer.js +93 -65
  22. package/dist/commands/config.js +16 -3
  23. package/dist/commands/cost.d.ts +2 -1
  24. package/dist/commands/cost.js +7 -6
  25. package/dist/commands/daemon.js +151 -4
  26. package/dist/commands/detach.js +1 -1
  27. package/dist/commands/doctor.js +19 -11
  28. package/dist/commands/events.js +1 -1
  29. package/dist/commands/exec.d.ts +2 -50
  30. package/dist/commands/exec.js +160 -215
  31. package/dist/commands/factory.js +1 -1
  32. package/dist/commands/feed.d.ts +2 -2
  33. package/dist/commands/feed.js +12 -23
  34. package/dist/commands/fleet-capture.js +25 -27
  35. package/dist/commands/focus.d.ts +2 -3
  36. package/dist/commands/focus.js +34 -9
  37. package/dist/commands/go.js +15 -5
  38. package/dist/commands/harness.d.ts +3 -3
  39. package/dist/commands/harness.js +53 -5
  40. package/dist/commands/hooks.js +1 -1
  41. package/dist/commands/import.js +2 -2
  42. package/dist/commands/insights.d.ts +5 -5
  43. package/dist/commands/insights.js +15 -9
  44. package/dist/commands/inspect.d.ts +2 -3
  45. package/dist/commands/inspect.js +4 -16
  46. package/dist/commands/logs.d.ts +2 -2
  47. package/dist/commands/logs.js +9 -9
  48. package/dist/commands/mcp.js +2 -2
  49. package/dist/commands/memory.js +1 -1
  50. package/dist/commands/message.d.ts +1 -1
  51. package/dist/commands/message.js +7 -7
  52. package/dist/commands/mine.d.ts +11 -8
  53. package/dist/commands/mine.js +11 -10
  54. package/dist/commands/models.js +1 -1
  55. package/dist/commands/modes.js +1 -1
  56. package/dist/commands/monitors.js +23 -6
  57. package/dist/commands/output.d.ts +7 -6
  58. package/dist/commands/output.js +11 -10
  59. package/dist/commands/packages.js +4 -4
  60. package/dist/commands/perf.js +1 -1
  61. package/dist/commands/permissions.js +49 -32
  62. package/dist/commands/plugins.d.ts +1 -1
  63. package/dist/commands/plugins.js +3 -3
  64. package/dist/commands/profiles.d.ts +6 -9
  65. package/dist/commands/profiles.js +8 -321
  66. package/dist/commands/projects.d.ts +9 -0
  67. package/dist/commands/projects.js +140 -8
  68. package/dist/commands/prune.js +5 -13
  69. package/dist/commands/refresh-rules.js +1 -1
  70. package/dist/commands/repo.d.ts +5 -7
  71. package/dist/commands/repo.js +34 -18
  72. package/dist/commands/resource-view.js +4 -0
  73. package/dist/commands/resume.d.ts +11 -7
  74. package/dist/commands/resume.js +82 -98
  75. package/dist/commands/route.d.ts +12 -0
  76. package/dist/commands/route.js +261 -0
  77. package/dist/commands/routines.d.ts +2 -3
  78. package/dist/commands/routines.js +120 -145
  79. package/dist/commands/rules.js +1 -1
  80. package/dist/commands/run-account-picker.d.ts +1 -1
  81. package/dist/commands/run-account-picker.js +2 -2
  82. package/dist/commands/run-broadcast.d.ts +21 -0
  83. package/dist/commands/run-broadcast.js +89 -0
  84. package/dist/commands/run-cloud.js +1 -1
  85. package/dist/commands/secrets-vault.d.ts +10 -0
  86. package/dist/commands/{login.js → secrets-vault.js} +34 -14
  87. package/dist/commands/secrets.d.ts +4 -4
  88. package/dist/commands/secrets.js +158 -159
  89. package/dist/commands/sessions-backfill.js +1 -1
  90. package/dist/commands/sessions-browser.d.ts +1 -1
  91. package/dist/commands/sessions-browser.js +9 -5
  92. package/dist/commands/sessions-export.js +2 -2
  93. package/dist/commands/sessions-inject.js +4 -5
  94. package/dist/commands/sessions-migrate.js +16 -27
  95. package/dist/commands/sessions-picker.d.ts +14 -0
  96. package/dist/commands/sessions-picker.js +209 -13
  97. package/dist/commands/sessions-resume.d.ts +7 -3
  98. package/dist/commands/sessions-resume.js +81 -33
  99. package/dist/commands/sessions-share.d.ts +25 -0
  100. package/dist/commands/sessions-share.js +166 -0
  101. package/dist/commands/sessions-stats.js +2 -2
  102. package/dist/commands/sessions.d.ts +75 -68
  103. package/dist/commands/sessions.js +144 -180
  104. package/dist/commands/setup-browser.js +1 -1
  105. package/dist/commands/setup-computer.js +1 -1
  106. package/dist/commands/setup-fleet.js +3 -0
  107. package/dist/commands/setup-mine.d.ts +7 -3
  108. package/dist/commands/setup-mine.js +13 -8
  109. package/dist/commands/setup-preferences.js +2 -2
  110. package/dist/commands/setup-secrets.js +2 -2
  111. package/dist/commands/setup-watchdog.js +2 -2
  112. package/dist/commands/setup.js +7 -2
  113. package/dist/commands/share.d.ts +65 -0
  114. package/dist/commands/share.js +253 -20
  115. package/dist/commands/skills.js +3 -3
  116. package/dist/commands/snapshot.d.ts +2 -2
  117. package/dist/commands/snapshot.js +9 -9
  118. package/dist/commands/ssh.d.ts +1 -1
  119. package/dist/commands/ssh.js +186 -64
  120. package/dist/commands/subagents.js +1 -1
  121. package/dist/commands/sync.js +24 -9
  122. package/dist/commands/teams.d.ts +2 -2
  123. package/dist/commands/teams.js +9 -18
  124. package/dist/commands/tmux.js +5 -1
  125. package/dist/commands/trash.js +1 -1
  126. package/dist/commands/usage.d.ts +1 -1
  127. package/dist/commands/usage.js +2 -2
  128. package/dist/commands/utils.d.ts +4 -14
  129. package/dist/commands/utils.js +6 -27
  130. package/dist/commands/versions.js +2 -2
  131. package/dist/commands/view.d.ts +9 -77
  132. package/dist/commands/view.js +23 -8
  133. package/dist/commands/watchdog.js +1 -1
  134. package/dist/commands/webhook.js +25 -34
  135. package/dist/commands/workflows.js +1 -1
  136. package/dist/index.js +1 -1
  137. package/dist/lib/account-capabilities.d.ts +39 -0
  138. package/dist/lib/account-capabilities.js +59 -0
  139. package/dist/lib/account-catalog.js +1 -1
  140. package/dist/lib/account-registry.d.ts +66 -0
  141. package/dist/lib/account-registry.js +151 -5
  142. package/dist/lib/{rotate.d.ts → accounting/rotate.d.ts} +4 -4
  143. package/dist/lib/{rotate.js → accounting/rotate.js} +8 -8
  144. package/dist/lib/{usage.d.ts → accounting/usage.d.ts} +4 -4
  145. package/dist/lib/{usage.js → accounting/usage.js} +11 -11
  146. package/dist/lib/agent-spec/provider.js +1 -1
  147. package/dist/lib/agents.d.ts +72 -4
  148. package/dist/lib/agents.js +231 -199
  149. package/dist/lib/answer-router.d.ts +2 -2
  150. package/dist/lib/ask-classifier.d.ts +1 -1
  151. package/dist/lib/ask-classifier.js +1 -1
  152. package/dist/lib/audit/log.js +1 -1
  153. package/dist/lib/auth-health.d.ts +1 -1
  154. package/dist/lib/auth-health.js +2 -2
  155. package/dist/lib/brand.js +1 -1
  156. package/dist/lib/browser/caller-identity.d.ts +28 -0
  157. package/dist/lib/browser/caller-identity.js +156 -0
  158. package/dist/lib/browser/cdp.js +5 -1
  159. package/dist/lib/browser/chrome.js +12 -1
  160. package/dist/lib/browser/drivers/ssh.d.ts +1 -1
  161. package/dist/lib/browser/drivers/ssh.js +3 -2
  162. package/dist/lib/browser/hygiene.d.ts +10 -2
  163. package/dist/lib/browser/hygiene.js +7 -4
  164. package/dist/lib/browser/ipc.d.ts +22 -2
  165. package/dist/lib/browser/ipc.js +185 -21
  166. package/dist/lib/browser/profiles.d.ts +69 -5
  167. package/dist/lib/browser/profiles.js +135 -13
  168. package/dist/lib/browser/remote-control.d.ts +2 -2
  169. package/dist/lib/browser/remote-control.js +3 -3
  170. package/dist/lib/browser/runtime-state.d.ts +79 -0
  171. package/dist/lib/browser/runtime-state.js +119 -1
  172. package/dist/lib/browser/service.d.ts +137 -2
  173. package/dist/lib/browser/service.js +492 -54
  174. package/dist/lib/browser/sessions-list.d.ts +2 -1
  175. package/dist/lib/browser/sessions-list.js +4 -13
  176. package/dist/lib/browser/types.d.ts +19 -1
  177. package/dist/lib/budget/config.js +1 -1
  178. package/dist/lib/budget/ledger.js +1 -1
  179. package/dist/lib/byok-usage.js +1 -1
  180. package/dist/lib/capabilities.js +3 -15
  181. package/dist/lib/catchup.d.ts +1 -1
  182. package/dist/lib/catchup.js +1 -1
  183. package/dist/lib/cloud/dispatch.js +1 -1
  184. package/dist/lib/cloud/host.d.ts +3 -3
  185. package/dist/lib/cloud/host.js +5 -5
  186. package/dist/lib/cloud/rush.d.ts +9 -21
  187. package/dist/lib/cloud/rush.js +33 -120
  188. package/dist/lib/cloud/types.d.ts +2 -2
  189. package/dist/lib/commands.js +3 -13
  190. package/dist/lib/computer/actions.d.ts +36 -0
  191. package/dist/lib/computer/actions.js +162 -0
  192. package/dist/lib/computer/dispatch.d.ts +2 -2
  193. package/dist/lib/computer/dispatch.js +2 -2
  194. package/dist/lib/computer/sessions-list.d.ts +3 -3
  195. package/dist/lib/computer/sessions-list.js +2 -2
  196. package/dist/lib/config-keys.d.ts +2 -1
  197. package/dist/lib/config-keys.js +8 -4
  198. package/dist/lib/config-machine-keys.d.ts +4 -2
  199. package/dist/lib/config-machine-keys.js +5 -2
  200. package/dist/lib/crabbox/lease.js +9 -1
  201. package/dist/lib/crabbox/runtimes.d.ts +32 -7
  202. package/dist/lib/crabbox/runtimes.js +72 -30
  203. package/dist/lib/{daemon.d.ts → daemon/daemon.d.ts} +59 -1
  204. package/dist/lib/{daemon.js → daemon/daemon.js} +237 -49
  205. package/dist/lib/daemon-services.d.ts +1 -1
  206. package/dist/lib/daemon-services.js +5 -0
  207. package/dist/lib/daemon-ticks.d.ts +25 -0
  208. package/dist/lib/daemon-ticks.js +31 -1
  209. package/dist/lib/daemon-webhooks.d.ts +104 -0
  210. package/dist/lib/daemon-webhooks.js +215 -0
  211. package/dist/lib/device-config.d.ts +85 -75
  212. package/dist/lib/device-config.js +280 -142
  213. package/dist/lib/devices/config-migration.d.ts +29 -34
  214. package/dist/lib/devices/config-migration.js +209 -130
  215. package/dist/lib/devices/connect.d.ts +2 -2
  216. package/dist/lib/devices/connect.js +2 -2
  217. package/dist/lib/devices/discovery-policy.d.ts +30 -0
  218. package/dist/lib/devices/discovery-policy.js +101 -0
  219. package/dist/lib/devices/fleet-inventory.js +8 -3
  220. package/dist/lib/devices/harness-inventory.d.ts +1 -1
  221. package/dist/lib/devices/harness-inventory.js +12 -3
  222. package/dist/lib/devices/known-hosts.js +1 -1
  223. package/dist/lib/devices/pool.d.ts +10 -5
  224. package/dist/lib/devices/pool.js +5 -7
  225. package/dist/lib/devices/registry.d.ts +1 -1
  226. package/dist/lib/devices/registry.js +1 -1
  227. package/dist/lib/devices/resolve-profile.d.ts +2 -2
  228. package/dist/lib/devices/resolve-profile.js +2 -2
  229. package/dist/lib/devices/resolve-target.d.ts +1 -1
  230. package/dist/lib/devices/resolve-target.js +4 -4
  231. package/dist/lib/devices/self-host.d.ts +1 -1
  232. package/dist/lib/devices/self-host.js +3 -3
  233. package/dist/lib/devices/ssh-config.d.ts +1 -1
  234. package/dist/lib/devices/stats-cache.js +1 -1
  235. package/dist/lib/devices/sync.d.ts +3 -1
  236. package/dist/lib/devices/sync.js +3 -3
  237. package/dist/lib/doctor-diff.js +4 -4
  238. package/dist/lib/drift-sync.js +2 -2
  239. package/dist/lib/drift.js +2 -2
  240. package/dist/lib/event-families.d.ts +1 -1
  241. package/dist/lib/event-stream.d.ts +1 -1
  242. package/dist/lib/event-stream.js +2 -2
  243. package/dist/lib/events-ingest.js +2 -2
  244. package/dist/lib/exec.d.ts +4 -4
  245. package/dist/lib/exec.js +11 -11
  246. package/dist/lib/factory/snapshot.d.ts +1 -1
  247. package/dist/lib/factory/snapshot.js +1 -1
  248. package/dist/lib/{activity.d.ts → feed/activity.d.ts} +1 -1
  249. package/dist/lib/{activity.js → feed/activity.js} +7 -7
  250. package/dist/lib/{events.d.ts → feed/events.d.ts} +2 -2
  251. package/dist/lib/{events.js → feed/events.js} +5 -5
  252. package/dist/lib/{feed.js → feed/feed.js} +4 -4
  253. package/dist/lib/feed-outcome.d.ts +1 -1
  254. package/dist/lib/feed-policy.d.ts +1 -1
  255. package/dist/lib/feed-policy.js +1 -1
  256. package/dist/lib/feed-post.d.ts +1 -1
  257. package/dist/lib/feed-post.js +1 -1
  258. package/dist/lib/feed-ranking.d.ts +1 -1
  259. package/dist/lib/fleet/apply.d.ts +0 -6
  260. package/dist/lib/fleet/apply.js +18 -45
  261. package/dist/lib/fleet/auth-sync.d.ts +16 -35
  262. package/dist/lib/fleet/auth-sync.js +16 -75
  263. package/dist/lib/fleet/capture.js +8 -6
  264. package/dist/lib/fleet/manifest.js +23 -11
  265. package/dist/lib/fleet/types.d.ts +19 -7
  266. package/dist/lib/fleet-cache.d.ts +1 -1
  267. package/dist/lib/fleet-cache.js +1 -1
  268. package/dist/lib/format.d.ts +19 -0
  269. package/dist/lib/format.js +44 -1
  270. package/dist/lib/friction-heuristics.d.ts +1 -1
  271. package/dist/lib/git.d.ts +24 -1
  272. package/dist/lib/git.js +82 -38
  273. package/dist/lib/heal.js +3 -3
  274. package/dist/lib/hooks.d.ts +18 -0
  275. package/dist/lib/hooks.js +113 -1
  276. package/dist/lib/hosts/credentials.d.ts +30 -10
  277. package/dist/lib/hosts/credentials.js +38 -26
  278. package/dist/lib/hosts/dispatch.d.ts +3 -3
  279. package/dist/lib/hosts/dispatch.js +3 -3
  280. package/dist/lib/hosts/option.d.ts +3 -3
  281. package/dist/lib/hosts/option.js +7 -8
  282. package/dist/lib/hosts/passthrough.d.ts +17 -17
  283. package/dist/lib/hosts/passthrough.js +67 -50
  284. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  285. package/dist/lib/hosts/providers/devices.js +1 -1
  286. package/dist/lib/hosts/reconcile.d.ts +1 -1
  287. package/dist/lib/hosts/reconcile.js +1 -1
  288. package/dist/lib/hosts/reconnect.d.ts +1 -1
  289. package/dist/lib/hosts/reconnect.js +2 -2
  290. package/dist/lib/hosts/registry.d.ts +5 -5
  291. package/dist/lib/hosts/registry.js +5 -5
  292. package/dist/lib/hosts/remote-cmd.d.ts +10 -10
  293. package/dist/lib/hosts/remote-cmd.js +25 -18
  294. package/dist/lib/hosts/remote-os.d.ts +4 -4
  295. package/dist/lib/hosts/remote-os.js +4 -4
  296. package/dist/lib/hosts/remote-session-id.d.ts +2 -2
  297. package/dist/lib/hosts/remote-session-id.js +2 -2
  298. package/dist/lib/hosts/routing-flag.d.ts +3 -3
  299. package/dist/lib/hosts/routing-flag.js +4 -5
  300. package/dist/lib/hosts/run-target.d.ts +4 -4
  301. package/dist/lib/hosts/run-target.js +4 -4
  302. package/dist/lib/hosts/session-index.d.ts +2 -2
  303. package/dist/lib/hosts/session-index.js +1 -1
  304. package/dist/lib/hosts/session-marker.d.ts +1 -1
  305. package/dist/lib/hosts/session-marker.js +1 -1
  306. package/dist/lib/hosts/types.d.ts +2 -2
  307. package/dist/lib/hosts/types.js +2 -2
  308. package/dist/lib/import.js +1 -1
  309. package/dist/lib/{migrate.d.ts → installations/migrate.d.ts} +13 -1
  310. package/dist/lib/{migrate.js → installations/migrate.js} +160 -40
  311. package/dist/lib/installations/resolve.js +1 -1
  312. package/dist/lib/installations/strategies.js +1 -1
  313. package/dist/lib/installations/update.js +2 -2
  314. package/dist/lib/{versions.d.ts → installations/versions.d.ts} +12 -3
  315. package/dist/lib/{versions.js → installations/versions.js} +51 -31
  316. package/dist/lib/isolation-boundary-report.js +1 -1
  317. package/dist/lib/linear-projects.d.ts +28 -0
  318. package/dist/lib/linear-projects.js +30 -0
  319. package/dist/lib/loop.js +1 -1
  320. package/dist/lib/mailbox-gc.js +1 -1
  321. package/dist/lib/mailbox.js +1 -1
  322. package/dist/lib/mcp-registry.d.ts +62 -0
  323. package/dist/lib/mcp-registry.js +177 -0
  324. package/dist/lib/mcp.d.ts +5 -0
  325. package/dist/lib/mcp.js +124 -307
  326. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  327. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  328. package/dist/lib/menubar/install-menubar.d.ts +7 -0
  329. package/dist/lib/menubar/install-menubar.js +24 -6
  330. package/dist/lib/menubar/snapshot.d.ts +7 -0
  331. package/dist/lib/menubar/snapshot.js +8 -6
  332. package/dist/lib/models.js +1 -1
  333. package/dist/lib/monitors/config.d.ts +12 -0
  334. package/dist/lib/monitors/config.js +3 -0
  335. package/dist/lib/monitors/dispatch.js +26 -5
  336. package/dist/lib/monitors/engine.js +10 -0
  337. package/dist/lib/monitors/sources/webhook.d.ts +1 -1
  338. package/dist/lib/monitors/state.d.ts +42 -0
  339. package/dist/lib/monitors/state.js +30 -0
  340. package/dist/lib/notify.d.ts +1 -1
  341. package/dist/lib/observe-aliases.d.ts +3 -3
  342. package/dist/lib/observe-aliases.js +3 -21
  343. package/dist/lib/output/git-output.js +2 -2
  344. package/dist/lib/overdue.d.ts +1 -1
  345. package/dist/lib/overdue.js +1 -1
  346. package/dist/lib/permissions-registry.d.ts +65 -0
  347. package/dist/lib/permissions-registry.js +599 -0
  348. package/dist/lib/permissions.d.ts +24 -13
  349. package/dist/lib/permissions.js +52 -271
  350. package/dist/lib/picker.d.ts +16 -0
  351. package/dist/lib/picker.js +33 -3
  352. package/dist/lib/placement.d.ts +1 -1
  353. package/dist/lib/placement.js +4 -4
  354. package/dist/lib/platform/paths.d.ts +8 -0
  355. package/dist/lib/platform/paths.js +11 -0
  356. package/dist/lib/platform/posixpath.js +3 -3
  357. package/dist/lib/{plugin-marketplace.d.ts → plugins/plugin-marketplace.d.ts} +1 -1
  358. package/dist/lib/{plugin-marketplace.js → plugins/plugin-marketplace.js} +2 -2
  359. package/dist/lib/{plugins.d.ts → plugins/plugins.d.ts} +1 -1
  360. package/dist/lib/{plugins.js → plugins/plugins.js} +7 -7
  361. package/dist/lib/{skills.d.ts → plugins/skills.d.ts} +1 -1
  362. package/dist/lib/{skills.js → plugins/skills.js} +7 -7
  363. package/dist/lib/pricing/cost.d.ts +1 -1
  364. package/dist/lib/pricing/cost.js +1 -1
  365. package/dist/lib/profiles-presets.d.ts +1 -1
  366. package/dist/lib/profiles-presets.js +1 -1
  367. package/dist/lib/profiles.js +2 -2
  368. package/dist/lib/project-import.js +4 -1
  369. package/dist/lib/project-key.js +7 -0
  370. package/dist/lib/project-launch.d.ts +1 -1
  371. package/dist/lib/project-launch.js +3 -3
  372. package/dist/lib/project-pull.d.ts +128 -0
  373. package/dist/lib/project-pull.js +384 -0
  374. package/dist/lib/project-root.d.ts +2 -2
  375. package/dist/lib/project-root.js +2 -2
  376. package/dist/lib/project-status.js +1 -1
  377. package/dist/lib/projects.d.ts +23 -0
  378. package/dist/lib/projects.js +29 -6
  379. package/dist/lib/refresh.d.ts +12 -1
  380. package/dist/lib/refresh.js +16 -9
  381. package/dist/lib/registry.d.ts +9 -2
  382. package/dist/lib/registry.js +11 -4
  383. package/dist/lib/resources.d.ts +2 -2
  384. package/dist/lib/resources.js +2 -2
  385. package/dist/lib/routers.d.ts +81 -0
  386. package/dist/lib/routers.js +153 -0
  387. package/dist/lib/routine-context.d.ts +1 -0
  388. package/dist/lib/routine-context.js +7 -2
  389. package/dist/lib/routine-notify-owner.d.ts +1 -1
  390. package/dist/lib/routine-notify.d.ts +1 -1
  391. package/dist/lib/routine-notify.js +1 -1
  392. package/dist/lib/routine-process-cleanup.d.ts +1 -1
  393. package/dist/lib/routine-readiness.d.ts +1 -1
  394. package/dist/lib/routine-readiness.js +11 -4
  395. package/dist/lib/routines-placement.d.ts +12 -2
  396. package/dist/lib/routines-placement.js +20 -3
  397. package/dist/lib/routines-project.d.ts +1 -1
  398. package/dist/lib/routines-project.js +1 -1
  399. package/dist/lib/rules/compile.d.ts +1 -0
  400. package/dist/lib/rules/compile.js +10 -2
  401. package/dist/lib/rules/rules.js +1 -1
  402. package/dist/lib/run-notify.js +1 -1
  403. package/dist/lib/runner.d.ts +80 -2
  404. package/dist/lib/runner.js +261 -67
  405. package/dist/lib/sandbox.d.ts +1 -1
  406. package/dist/lib/scheduler.d.ts +1 -1
  407. package/dist/lib/scheduler.js +1 -1
  408. package/dist/lib/{routines.d.ts → scheduling/routines.d.ts} +54 -9
  409. package/dist/lib/{routines.js → scheduling/routines.js} +173 -14
  410. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  411. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  412. package/dist/lib/secrets/agent.js +2 -2
  413. package/dist/lib/secrets/audit.js +1 -1
  414. package/dist/lib/secrets/bundles.d.ts +4 -4
  415. package/dist/lib/secrets/bundles.js +8 -8
  416. package/dist/lib/secrets/headless.d.ts +16 -0
  417. package/dist/lib/secrets/headless.js +21 -0
  418. package/dist/lib/secrets/index.js +1 -1
  419. package/dist/lib/secrets/list-filter.d.ts +1 -1
  420. package/dist/lib/secrets/list-filter.js +2 -2
  421. package/dist/lib/secrets/push.d.ts +1 -1
  422. package/dist/lib/secrets/push.js +10 -12
  423. package/dist/lib/secrets/remote.d.ts +21 -17
  424. package/dist/lib/secrets/remote.js +39 -23
  425. package/dist/lib/secrets/vault.js +2 -2
  426. package/dist/lib/self-heal/checks/shadowing.js +1 -1
  427. package/dist/lib/self-heal/checks/shims.js +1 -1
  428. package/dist/lib/self-update.d.ts +39 -4
  429. package/dist/lib/self-update.js +78 -25
  430. package/dist/lib/serve/control.d.ts +1 -1
  431. package/dist/lib/serve/control.js +4 -4
  432. package/dist/lib/serve/data.d.ts +1 -1
  433. package/dist/lib/serve/data.js +1 -1
  434. package/dist/lib/serve/stream.js +1 -1
  435. package/dist/lib/service-manifest.d.ts +29 -0
  436. package/dist/lib/service-manifest.js +80 -0
  437. package/dist/lib/session/active.d.ts +59 -7
  438. package/dist/lib/session/active.js +158 -17
  439. package/dist/lib/session/bash-command.js +1 -1
  440. package/dist/lib/session/claude-accounts.d.ts +1 -1
  441. package/dist/lib/session/claude-accounts.js +1 -1
  442. package/dist/lib/session/db.d.ts +10 -2
  443. package/dist/lib/session/db.js +25 -6
  444. package/dist/lib/session/discover.d.ts +77 -0
  445. package/dist/lib/session/discover.js +130 -25
  446. package/dist/lib/session/fork.js +1 -1
  447. package/dist/lib/session/inject.d.ts +1 -1
  448. package/dist/lib/session/insights.d.ts +1 -1
  449. package/dist/lib/session/insights.js +1 -1
  450. package/dist/lib/session/live-metadata.d.ts +15 -0
  451. package/dist/lib/session/live-metadata.js +76 -0
  452. package/dist/lib/session/migrate-targets.d.ts +1 -1
  453. package/dist/lib/session/recovery.d.ts +1 -1
  454. package/dist/lib/session/recovery.js +2 -2
  455. package/dist/lib/session/remote-active.d.ts +10 -1
  456. package/dist/lib/session/remote-active.js +8 -3
  457. package/dist/lib/session/remote-bundle.d.ts +1 -1
  458. package/dist/lib/session/remote-bundle.js +2 -2
  459. package/dist/lib/session/remote-list.d.ts +15 -4
  460. package/dist/lib/session/remote-list.js +40 -3
  461. package/dist/lib/session/remote.d.ts +5 -5
  462. package/dist/lib/session/remote.js +13 -17
  463. package/dist/lib/session/resume-command.d.ts +3 -2
  464. package/dist/lib/session/resume-command.js +4 -3
  465. package/dist/lib/session/resume-owner.d.ts +3 -3
  466. package/dist/lib/session/resume-owner.js +3 -3
  467. package/dist/lib/session/session-cache.d.ts +12 -0
  468. package/dist/lib/session/session-cache.js +2 -0
  469. package/dist/lib/session/share-html.d.ts +55 -0
  470. package/dist/lib/session/share-html.js +319 -0
  471. package/dist/lib/session/shell-programs.js +1 -1
  472. package/dist/lib/session/state.js +5 -5
  473. package/dist/lib/session/team-filter.d.ts +1 -1
  474. package/dist/lib/session/team-filter.js +1 -1
  475. package/dist/lib/session/types.d.ts +3 -3
  476. package/dist/lib/session/width.d.ts +2 -2
  477. package/dist/lib/session/width.js +2 -2
  478. package/dist/lib/settings-manifest.d.ts +2 -0
  479. package/dist/lib/settings-manifest.js +81 -3
  480. package/dist/lib/share/delete.d.ts +21 -0
  481. package/dist/lib/share/delete.js +42 -0
  482. package/dist/lib/share/publish.d.ts +120 -0
  483. package/dist/lib/share/publish.js +243 -18
  484. package/dist/lib/share/worker-template.js +172 -9
  485. package/dist/lib/shims.js +35 -7
  486. package/dist/lib/smart-launch.d.ts +4 -4
  487. package/dist/lib/smart-launch.js +6 -4
  488. package/dist/lib/snapshot.d.ts +4 -4
  489. package/dist/lib/snapshot.js +2 -2
  490. package/dist/lib/ssh-exec.d.ts +1 -1
  491. package/dist/lib/ssh-exec.js +2 -2
  492. package/dist/lib/ssh-tunnel.d.ts +10 -10
  493. package/dist/lib/ssh-tunnel.js +12 -12
  494. package/dist/lib/staleness/checkers/hooks.d.ts +1 -1
  495. package/dist/lib/staleness/checkers/hooks.js +1 -1
  496. package/dist/lib/staleness/detectors/permissions.js +0 -23
  497. package/dist/lib/staleness/detectors/plugins.js +1 -1
  498. package/dist/lib/staleness/fingerprint.js +1 -1
  499. package/dist/lib/staleness/layers.d.ts +1 -1
  500. package/dist/lib/staleness/layers.js +1 -1
  501. package/dist/lib/staleness/writers/mcp.js +3 -1
  502. package/dist/lib/staleness/writers/plugins.js +1 -1
  503. package/dist/lib/staleness/writers/types.d.ts +8 -0
  504. package/dist/lib/startup/command-registry.d.ts +6 -147
  505. package/dist/lib/startup/command-registry.js +40 -303
  506. package/dist/lib/startup/dev-build.d.ts +0 -21
  507. package/dist/lib/startup/dev-build.js +29 -8
  508. package/dist/lib/state.d.ts +19 -1
  509. package/dist/lib/state.js +120 -51
  510. package/dist/lib/subagents.js +1 -1
  511. package/dist/lib/sync-status.js +1 -1
  512. package/dist/lib/sync-umbrella.d.ts +6 -1
  513. package/dist/lib/sync-umbrella.js +9 -4
  514. package/dist/lib/teams/agents.js +2 -2
  515. package/dist/lib/teams/registry.js +1 -1
  516. package/dist/lib/terminal/backends/vscodium-agent.js +1 -1
  517. package/dist/lib/terminal/engine.js +1 -1
  518. package/dist/lib/terminal/index.d.ts +4 -0
  519. package/dist/lib/terminal/index.js +3 -0
  520. package/dist/lib/terminal/inject.d.ts +2 -2
  521. package/dist/lib/terminal/inject.js +2 -2
  522. package/dist/lib/terminal/transport.js +1 -1
  523. package/dist/lib/tmux/index.d.ts +1 -1
  524. package/dist/lib/tmux/index.js +1 -1
  525. package/dist/lib/tmux/session.d.ts +21 -5
  526. package/dist/lib/tmux/session.js +76 -22
  527. package/dist/lib/triggers/handlers.d.ts +38 -3
  528. package/dist/lib/triggers/handlers.js +58 -7
  529. package/dist/lib/triggers/webhook.d.ts +113 -5
  530. package/dist/lib/triggers/webhook.js +223 -44
  531. package/dist/lib/types.d.ts +19 -7
  532. package/dist/lib/usage-fleet.d.ts +1 -1
  533. package/dist/lib/usage-fleet.js +1 -1
  534. package/dist/lib/usage-refresh.d.ts +1 -1
  535. package/dist/lib/usage-refresh.js +3 -3
  536. package/dist/lib/version-duplicates.js +2 -2
  537. package/dist/lib/view-types.d.ts +56 -0
  538. package/dist/lib/view-types.js +1 -0
  539. package/dist/lib/watchdog/rotate.d.ts +2 -2
  540. package/dist/lib/watchdog/rotate.js +3 -3
  541. package/dist/lib/watchdog/runner.d.ts +2 -3
  542. package/dist/lib/watchdog/runner.js +3 -4
  543. package/dist/lib/workflows.js +1 -1
  544. package/dist/lib/wrap.d.ts +33 -0
  545. package/dist/lib/wrap.js +70 -0
  546. package/package.json +2 -1
  547. package/scripts/postinstall.js +2 -2
  548. package/dist/commands/bench.d.ts +0 -2
  549. package/dist/commands/bench.js +0 -101
  550. package/dist/commands/cp.d.ts +0 -84
  551. package/dist/commands/cp.js +0 -231
  552. package/dist/commands/login.d.ts +0 -2
  553. package/dist/lib/resources/commands.d.ts +0 -46
  554. package/dist/lib/resources/commands.js +0 -211
  555. package/dist/lib/resources/hooks.d.ts +0 -16
  556. package/dist/lib/resources/hooks.js +0 -153
  557. package/dist/lib/resources/mcp.d.ts +0 -34
  558. package/dist/lib/resources/mcp.js +0 -250
  559. package/dist/lib/resources/memory.d.ts +0 -15
  560. package/dist/lib/resources/memory.js +0 -46
  561. package/dist/lib/resources/permissions.d.ts +0 -13
  562. package/dist/lib/resources/permissions.js +0 -202
  563. package/dist/lib/resources/rules.d.ts +0 -46
  564. package/dist/lib/resources/rules.js +0 -179
  565. package/dist/lib/resources/skills.d.ts +0 -37
  566. package/dist/lib/resources/skills.js +0 -247
  567. package/dist/lib/resources/subagents.d.ts +0 -46
  568. package/dist/lib/resources/subagents.js +0 -202
  569. /package/dist/lib/{feed.d.ts → feed/feed.d.ts} +0 -0
@@ -0,0 +1,162 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { resolvePolicyPath } from '../computer-rpc.js';
5
+ import { COMPUTER_INPUT_GATED_VERBS, formatComputerPermissionGrantHint } from '../permissions.js';
6
+ import { emit as emitEvent } from '../feed/events.js';
7
+ import { recordComputerSession } from '../session/db.js';
8
+ import { resolveActor } from '../actor.js';
9
+ function isComputerInputVerb(verb) {
10
+ return typeof verb === 'string' && COMPUTER_INPUT_GATED_VERBS.includes(verb);
11
+ }
12
+ function computerSessionId(env = process.env) {
13
+ return env.CODEX_THREAD_ID
14
+ || env.CLAUDE_CODE_SESSION_ID
15
+ || env.CLAUDE_SESSION_ID
16
+ || env.AGENTS_SESSION_ID
17
+ || env.AGENTS_RUN_ID
18
+ || null;
19
+ }
20
+ function admissionCachePath(env = process.env) {
21
+ if (env.AGENTS_COMPUTER_ADMISSION_CACHE)
22
+ return env.AGENTS_COMPUTER_ADMISSION_CACHE;
23
+ return path.join(path.dirname(resolvePolicyPath()), 'computer-target-admissions.json');
24
+ }
25
+ function targetSelector(opts) {
26
+ return opts.bundle ? `bundle:${opts.bundle}` : 'frontmost';
27
+ }
28
+ function readAdmissionCache(filePath) {
29
+ try {
30
+ const parsed = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
31
+ return Array.isArray(parsed.admissions) ? parsed.admissions.filter(isAdmission) : [];
32
+ }
33
+ catch {
34
+ return [];
35
+ }
36
+ }
37
+ function isAdmission(v) {
38
+ if (!v || typeof v !== 'object')
39
+ return false;
40
+ const r = v;
41
+ return r.sessionId !== undefined
42
+ && typeof r.sessionId === 'string'
43
+ && typeof r.selector === 'string'
44
+ && r.gateClass === 'input'
45
+ && typeof r.pid === 'number'
46
+ && typeof r.bundle_id === 'string'
47
+ && typeof r.name === 'string'
48
+ && typeof r.admittedAtMs === 'number'
49
+ && isComputerInputVerb(r.admittedByVerb);
50
+ }
51
+ function rememberAdmission(app, opts) {
52
+ const sessionId = computerSessionId(opts.env);
53
+ if (!sessionId)
54
+ return;
55
+ const filePath = admissionCachePath(opts.env);
56
+ const admissions = readAdmissionCache(filePath);
57
+ const next = {
58
+ sessionId,
59
+ selector: opts.selector,
60
+ gateClass: 'input',
61
+ pid: app.pid,
62
+ bundle_id: app.bundle_id,
63
+ name: app.name,
64
+ admittedAtMs: opts.nowMs ?? Date.now(),
65
+ admittedByVerb: opts.verb,
66
+ };
67
+ const filtered = admissions.filter((a) => !(a.sessionId === sessionId && a.selector === opts.selector && a.gateClass === 'input'));
68
+ filtered.push(next);
69
+ try {
70
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
71
+ fs.writeFileSync(filePath, JSON.stringify({ admissions: filtered }, null, 2), { mode: 0o600 });
72
+ }
73
+ catch {
74
+ // Cache persistence is best-effort; the daemon remains the final gate.
75
+ }
76
+ }
77
+ function findAdmission(opts) {
78
+ const sessionId = computerSessionId(opts.env);
79
+ if (!sessionId)
80
+ return null;
81
+ const admissions = readAdmissionCache(admissionCachePath(opts.env));
82
+ const matches = admissions
83
+ .filter((a) => a.sessionId === sessionId && a.selector === opts.selector && a.gateClass === 'input')
84
+ .sort((a, b) => b.admittedAtMs - a.admittedAtMs);
85
+ return matches[0] ?? null;
86
+ }
87
+ export function pickTarget(list, opts) {
88
+ if (opts.pid != null) {
89
+ const app = list.find((a) => a.pid === opts.pid);
90
+ return { ok: true, app: app ?? { pid: opts.pid, name: '', bundle_id: '', active: false } };
91
+ }
92
+ if (opts.bundle) {
93
+ const app = list.find((a) => a.bundle_id === opts.bundle);
94
+ if (!app) {
95
+ return {
96
+ ok: false,
97
+ error: `bundle not in allow list (or not running): ${opts.bundle}\n${formatComputerPermissionGrantHint(opts.bundle)}`,
98
+ };
99
+ }
100
+ return { ok: true, app };
101
+ }
102
+ const active = list.find((a) => a.active);
103
+ if (!active) {
104
+ return {
105
+ ok: false,
106
+ error: `no active app found in allow list\n${formatComputerPermissionGrantHint()}`,
107
+ };
108
+ }
109
+ return { ok: true, app: active };
110
+ }
111
+ function unwrap(r) {
112
+ if (r.error) {
113
+ console.error(`error: ${r.error.code}: ${r.error.message}`);
114
+ process.exit(1);
115
+ }
116
+ return r.result ?? {};
117
+ }
118
+ export async function resolveTargetPidDecision(client, opts, gate) {
119
+ if (opts.pid != null)
120
+ return { ok: true, pid: opts.pid, source: 'pid' };
121
+ const apps = unwrap(await client.call('list_apps'));
122
+ const list = apps.apps || [];
123
+ const picked = pickTarget(list, opts);
124
+ const verb = gate?.verb;
125
+ const selector = targetSelector(opts);
126
+ if (picked.ok && isComputerInputVerb(verb)) {
127
+ rememberAdmission(picked.app, { selector, verb, env: gate?.env, nowMs: gate?.nowMs });
128
+ }
129
+ if (!picked.ok) {
130
+ if (isComputerInputVerb(verb)) {
131
+ const admitted = findAdmission({ selector, env: gate?.env });
132
+ if (admitted)
133
+ return { ok: true, pid: admitted.pid, source: 'session_admission' };
134
+ }
135
+ return { ok: false, error: picked.error };
136
+ }
137
+ return { ok: true, pid: picked.app.pid, source: 'list_apps' };
138
+ }
139
+ const COMPUTER_INVOCATION_ID = randomUUID();
140
+ export function emitComputerAction(verb, targetPid, opts, extra = {}) {
141
+ emitEvent('computer.action', {
142
+ command: verb,
143
+ invocationId: COMPUTER_INVOCATION_ID,
144
+ targetPid,
145
+ bundle: opts.bundle,
146
+ device: opts.device,
147
+ ...extra,
148
+ });
149
+ try {
150
+ recordComputerSession({
151
+ invocationId: COMPUTER_INVOCATION_ID,
152
+ sessionId: process.env.AGENT_SESSION_ID || process.env.AGENTS_SESSION_ID,
153
+ launchId: process.env.AGENT_LAUNCH_ID,
154
+ actor: resolveActor().id,
155
+ actionCount: 1,
156
+ taskPreview: typeof extra.task === 'string' ? extra.task : undefined,
157
+ });
158
+ }
159
+ catch {
160
+ // Recording is best-effort; the action and its event are already done.
161
+ }
162
+ }
@@ -1,10 +1,10 @@
1
1
  import type { ComputerClient } from '../computer-rpc.js';
2
- import { type AppInfo } from '../../commands/computer-actions.js';
2
+ import { type AppInfo } from './actions.js';
3
3
  import type { VerbDispatcher } from './loop.js';
4
4
  declare function rpcMethodFor(verb: string): string;
5
5
  declare function toRpcParams(verb: string, input: Record<string, unknown>, pid?: number): Record<string, unknown>;
6
6
  export declare function makeVerbDispatcher(client: ComputerClient, context?: {
7
- host?: string;
7
+ device?: string;
8
8
  }): VerbDispatcher;
9
9
  export { rpcMethodFor, toRpcParams };
10
10
  export type { AppInfo };
@@ -5,7 +5,7 @@
5
5
  // it names the same RPC methods the explicit `agents computer <verb>` commands
6
6
  // call, so the external-agent verb surface is untouched. The daemon stays the
7
7
  // single authority on permissions and targeting.
8
- import { resolveTargetPidDecision, emitComputerAction } from '../../commands/computer-actions.js';
8
+ import { resolveTargetPidDecision, emitComputerAction } from './actions.js';
9
9
  // CLI verb -> daemon RPC method. Only the rename cases need listing; the rest
10
10
  // pass through by name.
11
11
  const RPC_METHOD = {
@@ -125,7 +125,7 @@ export function makeVerbDispatcher(client, context = {}) {
125
125
  const res = await client.call(method, params);
126
126
  if (res.error)
127
127
  return { ok: false, error: `${res.error.code}: ${res.error.message}` };
128
- emitComputerAction(verb, pid, { bundle: input.bundle, host: context.host });
128
+ emitComputerAction(verb, pid, { bundle: input.bundle, device: context.device });
129
129
  return { ok: true, result: res.result ?? {} };
130
130
  };
131
131
  }
@@ -17,7 +17,7 @@ export interface ComputerAction {
17
17
  /** The driven app's pid, when resolved. */
18
18
  targetPid?: number;
19
19
  bundle?: string;
20
- /** `--host <device>` target when this action drove a remote daemon. */
20
+ /** `--device <device>` target when this action drove a remote daemon. */
21
21
  host?: string;
22
22
  /** Truncated `--task` text; only ever present on a `verb: 'run'` marker. */
23
23
  task?: string;
@@ -62,7 +62,7 @@ export interface ComputerRunRow {
62
62
  * the driven one (see `remoteHost`). */
63
63
  machine: string;
64
64
  machineId?: string;
65
- /** `--host <device>` target when the run drove a remote (Windows) daemon. */
65
+ /** `--device <device>` target when the run drove a remote (Windows) daemon. */
66
66
  remoteHost?: string;
67
67
  /** Best-known target app bundle across the run's actions. */
68
68
  bundle?: string;
@@ -90,7 +90,7 @@ export declare function groupIntoComputerRuns(actions: ComputerAction[], resolve
90
90
  /** Build task-first rows from the real ledger, resolving each row's owning
91
91
  * session against the live indexes. The interactive picker's (and the
92
92
  * flat/`--json` printer's) data source. `machine` narrows to rows whose
93
- * invoking hostname, machineId, or `--host` target contains the substring. */
93
+ * invoking hostname, machineId, or `--device` target contains the substring. */
94
94
  export declare function buildComputerSessionRows(opts?: {
95
95
  limit?: number;
96
96
  machine?: string;
@@ -58,7 +58,7 @@
58
58
  * `sessionId` doesn't resolve (a rotated/unindexed session) but `launchId`
59
59
  * still does via the more authoritative pid registry.
60
60
  */
61
- import { query, truncate } from '../events.js';
61
+ import { query, truncate } from '../feed/events.js';
62
62
  import { formatRelativeTime } from '../session/relative-time.js';
63
63
  import { getSessionById, listComputerSessionRecords, pruneToolSessions } from '../session/db.js';
64
64
  import { buildLaunchSessionIndex, resolveLaunchSession, } from '../browser/sessions-list.js';
@@ -237,7 +237,7 @@ function appendPrunedRunsFromDb(rows, limit) {
237
237
  /** Build task-first rows from the real ledger, resolving each row's owning
238
238
  * session against the live indexes. The interactive picker's (and the
239
239
  * flat/`--json` printer's) data source. `machine` narrows to rows whose
240
- * invoking hostname, machineId, or `--host` target contains the substring. */
240
+ * invoking hostname, machineId, or `--device` target contains the substring. */
241
241
  export function buildComputerSessionRows(opts = {}) {
242
242
  const actions = listComputerActions({ limit: opts.limit });
243
243
  const index = buildLaunchSessionIndex();
@@ -50,7 +50,7 @@ export interface ParsedDeviceConfigKey {
50
50
  property: DeviceConfigProperty;
51
51
  }
52
52
  export type ParsedConfigKey = ParsedRunConfigKey | ParsedInteractiveConfigKey | ParsedUsageConfigKey | ParsedAutoConfigKey | ParsedBrowserConfigKey | ParsedProjectConfigKey | ParsedDeviceConfigKey;
53
- export type DeviceConfigProperty = 'role' | 'max-agents' | 'scheduler' | 'daemon' | 'watchdog' | 'tmux' | 'browser.remote-control' | 'notes' | 'browser.profile';
53
+ export type DeviceConfigProperty = 'role' | 'max-agents' | 'scheduler' | 'daemon' | 'watchdog' | 'tmux' | 'browser.remote-control' | 'browser.task-idle-minutes' | 'notes' | 'browser.profile';
54
54
  /** Normalize agent@version to use `@` consistently. */
55
55
  export declare function formatAgentVersion(agent: AgentId, version: string): string;
56
56
  /**
@@ -73,6 +73,7 @@ export declare function formatAgentVersion(agent: AgentId, version: string): str
73
73
  * devices.<name>.watchdog
74
74
  * devices.<name>.tmux
75
75
  * devices.<name>.browser.remote-control
76
+ * devices.<name>.browser.task-idle-minutes
76
77
  * devices.<name>.notes
77
78
  * devices.<name>.browser.profile
78
79
  */
@@ -17,6 +17,7 @@ const DEVICE_CONFIG_PROPERTIES = [
17
17
  'watchdog',
18
18
  'tmux',
19
19
  'browser.remote-control',
20
+ 'browser.task-idle-minutes',
20
21
  'notes',
21
22
  'browser.profile',
22
23
  ];
@@ -57,6 +58,7 @@ export function formatAgentVersion(agent, version) {
57
58
  * devices.<name>.watchdog
58
59
  * devices.<name>.tmux
59
60
  * devices.<name>.browser.remote-control
61
+ * devices.<name>.browser.task-idle-minutes
60
62
  * devices.<name>.notes
61
63
  * devices.<name>.browser.profile
62
64
  */
@@ -89,7 +91,7 @@ export function parseConfigKey(key) {
89
91
  if (raw === 'project.root') {
90
92
  return { scope: 'project', property: 'root' };
91
93
  }
92
- const deviceMatch = raw.match(/^devices\.(.+)\.(role|max-agents|scheduler|daemon|watchdog|tmux|notes|browser\.remote-control|browser\.profile)$/);
94
+ const deviceMatch = raw.match(/^devices\.(.+)\.(role|max-agents|scheduler|daemon|watchdog|tmux|notes|browser\.remote-control|browser\.task-idle-minutes|browser\.profile)$/);
93
95
  if (deviceMatch) {
94
96
  return {
95
97
  scope: 'device',
@@ -177,6 +179,8 @@ export function devicePropertyToConfigName(property) {
177
179
  return 'tmux.enabled';
178
180
  case 'browser.remote-control':
179
181
  return 'browser.remote-control';
182
+ case 'browser.task-idle-minutes':
183
+ return 'browser.task-idle-minutes';
180
184
  case 'notes':
181
185
  return 'notes';
182
186
  case 'browser.profile':
@@ -202,11 +206,11 @@ export function configKeyStorageHint(parsed) {
202
206
  return 'config.autoPool';
203
207
  case 'browser':
204
208
  return parsed.device
205
- ? `fleet.devices.${parsed.device}.config.defaultBrowserProfile`
206
- : 'fleet.devices.<self>.config.defaultBrowserProfile';
209
+ ? `devices/${parsed.device}/agents.yaml config.defaultBrowserProfile`
210
+ : 'devices/<self>/agents.yaml config.defaultBrowserProfile';
207
211
  case 'project':
208
212
  return 'devices.<self>.projectRoot';
209
213
  case 'device':
210
- return `fleet.devices.${parsed.device}.config ${devicePropertyToConfigName(parsed.property)}`;
214
+ return `devices/${parsed.device}/agents.yaml config (${devicePropertyToConfigName(parsed.property)}; fleet default: fleet.defaults.config)`;
211
215
  }
212
216
  }
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * The YAML keys of every machine-visibility config key — the ones that live in
3
- * the owning box's own `devices/<machine>/agents.yaml` and must never reach the
4
- * fleet-shared `agents.yaml`.
3
+ * the owning box's own `devices/<machine>/agents.yaml` and cannot be read or
4
+ * set for a peer. A fleet default may still live under
5
+ * `fleet.defaults.config` (the shared default layer); the peer restriction
6
+ * is about targeting another device, not about fleet policy.
5
7
  *
6
8
  * This is a ZERO-DEPENDENCY leaf on purpose. The authority is `CONFIG_KEYS` in
7
9
  * `lib/device-config.ts`, but that module imports `devices/config-migration.ts`,
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * The YAML keys of every machine-visibility config key — the ones that live in
3
- * the owning box's own `devices/<machine>/agents.yaml` and must never reach the
4
- * fleet-shared `agents.yaml`.
3
+ * the owning box's own `devices/<machine>/agents.yaml` and cannot be read or
4
+ * set for a peer. A fleet default may still live under
5
+ * `fleet.defaults.config` (the shared default layer); the peer restriction
6
+ * is about targeting another device, not about fleet policy.
5
7
  *
6
8
  * This is a ZERO-DEPENDENCY leaf on purpose. The authority is `CONFIG_KEYS` in
7
9
  * `lib/device-config.ts`, but that module imports `devices/config-migration.ts`,
@@ -15,4 +17,5 @@ export const MACHINE_LOCAL_YAML_KEYS = new Set([
15
17
  'schedulerEnabled', // scheduler.enabled
16
18
  'daemonEnabled', // daemon.enabled
17
19
  'tmuxEnabled', // tmux.enabled — whether an interactive run is tmux-wrapped on THIS box
20
+ 'browserTaskIdleMinutes', // browser.task-idle-minutes — only THIS box's reaper reads it
18
21
  ]);
@@ -31,7 +31,7 @@
31
31
  */
32
32
  import { crabboxFind, crabboxList, crabboxStatusReady, crabboxWarmup, crabboxWaitReady, crabboxRunScript, crabboxStop, poolReusableBoxes } from './cli.js';
33
33
  import * as yaml from 'yaml';
34
- import { buildCredentialScript, buildHomeFileWriteScript, CLAUDE_TOKEN_REMOTE } from './runtimes.js';
34
+ import { assertNoNativeOAuthTransfer, buildCredentialScript, buildHomeFileWriteScript, CLAUDE_TOKEN_REMOTE } from './runtimes.js';
35
35
  import { LEASE_AGENT_MARKER, leasePhaseSentinel } from './progress.js';
36
36
  import { copySetupToBox } from './setup-copy.js';
37
37
  import { DEFAULT_CRABBOX_PROFILE } from './config.js';
@@ -262,6 +262,14 @@ function reapExpiredPoolStrays(opts, keepSlug) {
262
262
  return reaped;
263
263
  }
264
264
  export async function leaseAndRun(opts) {
265
+ // SING-1b, FAIL FAST: `buildBootstrapScript` below refuses to copy a native OAuth
266
+ // login (via `buildCredentialScript`), but that runs only AFTER a box has been
267
+ // leased — and a `--fresh` box would leak because the throw escapes the teardown
268
+ // `finally`. Refuse HERE, before any box is provisioned or paid for, mirroring how
269
+ // `--copy-creds` refuses before it opens an SSH connection.
270
+ assertNoNativeOAuthTransfer(opts.credentialRuntimes ?? opts.runtimes, opts.detected, {
271
+ claudeCredentialsJson: opts.claudeCredentialsJson,
272
+ });
265
273
  const startedAt = Date.now();
266
274
  let box;
267
275
  // A box this run did NOT provision — either the caller named it (`--box`) or
@@ -26,6 +26,10 @@ interface RuntimeCred {
26
26
  remote: string;
27
27
  }
28
28
  export declare const LEASE_RUNTIMES: RuntimeCred[];
29
+ /** True when `id` is a native OAuth / session login that MUST NOT be copied between devices (SING-1b). */
30
+ export declare function isNativeOAuthRuntime(id: AgentId): boolean;
31
+ /** The fail-loud message naming the forbidden runtimes and the portable path to use instead. */
32
+ export declare function nativeOAuthTransferRefusal(nativeRuntimes: AgentId[]): string;
29
33
  export interface DetectedRuntime {
30
34
  id: AgentId;
31
35
  label: string;
@@ -96,15 +100,36 @@ export declare function resolveClaudeCredentialsBlob(opts?: {
96
100
  accountEmail?: (home: string) => Promise<string | null>;
97
101
  }): Promise<string | null>;
98
102
  /**
99
- * Build a bash snippet that writes each picked runtime's token file to the box's
100
- * home-level config path (0600), from the token contents read locally. Returns
101
- * `''` when no runtimes were selected. The snippet is meant to be embedded in
102
- * the `--script-stdin` body (never argv).
103
+ * The credential-provisioning snippet for a `--lease` box.
103
104
  *
104
- * `extras.claudeCredentialsJson` (the raw wrapped payload from
105
- * `resolveClaudeCredentialsBlob`) is written to `~/.claude/.credentials.json` in
106
- * ADDITION to claude's `.claude.json` config without it the box is "Not logged in".
105
+ * Every runtime this could serialize is a native OAuth / session login
106
+ * (`LEASE_RUNTIMES`), and SING-1b forbids copying one to another device —
107
+ * including an ephemeral leased box, whose refresh of a shared rotating token
108
+ * invalidates every other holder. So this no longer writes a login: it REFUSES
109
+ * (throws, steering to the portable `agents accounts` path) whenever a picked
110
+ * runtime actually has a native credential to copy — signed in locally
111
+ * (`credPath`), or a Claude OAuth blob supplied. A picked runtime with nothing to
112
+ * copy is simply skipped, so `buildCredentialScript` returns `''` (a no-op box
113
+ * bootstrap) rather than throwing on a not-signed-in runtime.
107
114
  */
115
+ /**
116
+ * The native OAuth runtimes among `picked` that actually have a credential to copy
117
+ * — signed in locally (`credPath`) or a Claude OAuth blob supplied — i.e. the ones
118
+ * a transfer would leak. A picked runtime with nothing to copy is not refused.
119
+ */
120
+ export declare function refusedNativeOAuthRuntimes(picked: AgentId[], detected: DetectedRuntime[], extras?: {
121
+ claudeCredentialsJson?: string | null;
122
+ }): AgentId[];
123
+ /**
124
+ * Throw the SING-1b refusal if any picked runtime would transfer a native OAuth
125
+ * login. Callers should invoke this at a FAIL-FAST point — before any expensive or
126
+ * costly side effect (e.g. before `crabboxWarmup` leases a paid box) — so a refused
127
+ * `--lease` never leaks infra, mirroring how `--copy-creds` refuses before it opens
128
+ * an SSH connection.
129
+ */
130
+ export declare function assertNoNativeOAuthTransfer(picked: AgentId[], detected: DetectedRuntime[], extras?: {
131
+ claudeCredentialsJson?: string | null;
132
+ }): void;
108
133
  export declare function buildCredentialScript(picked: AgentId[], detected: DetectedRuntime[], extras?: {
109
134
  claudeCredentialsJson?: string | null;
110
135
  }): string;
@@ -17,8 +17,8 @@ import * as path from 'path';
17
17
  import * as fs from 'fs';
18
18
  import { getAccountInfo } from '../agents.js';
19
19
  import { getKeychainToken } from '../secrets/index.js';
20
- import { getClaudeKeychainService } from '../usage.js';
21
- import { listInstalledVersions, getVersionHomePath } from '../versions.js';
20
+ import { getClaudeKeychainService } from '../accounting/usage.js';
21
+ import { listInstalledVersions, getVersionHomePath } from '../installations/versions.js';
22
22
  import { readClaudeCredentialsBlob } from '../cloud/rush.js';
23
23
  export const LEASE_RUNTIMES = [
24
24
  { id: 'claude', label: 'Claude Code', localCandidates: ['.claude/.claude.json', '.claude.json'], remote: '.claude.json' },
@@ -26,6 +26,34 @@ export const LEASE_RUNTIMES = [
26
26
  { id: 'gemini', label: 'Gemini CLI', localCandidates: ['.gemini/google_accounts.json'], remote: '.gemini/google_accounts.json' },
27
27
  { id: 'grok', label: 'Grok CLI', localCandidates: ['.grok/auth.json'], remote: '.grok/auth.json' },
28
28
  ];
29
+ /**
30
+ * Every runtime whose login this module can serialize (`LEASE_RUNTIMES`) is a
31
+ * native, rotating OAuth / session credential (Claude OAuth token, codex/grok
32
+ * `auth.json`, gemini `google_accounts.json`). The fleet-auth contract forbids
33
+ * copying any of them between devices — including to an ephemeral leased box —
34
+ * because a shared refresh token rotates server-side on the next refresh and
35
+ * invalidates every other copy (`docs/specifications.md` SING-1b,
36
+ * `docs/credential-management.md` invariant 2). The set is derived from
37
+ * `LEASE_RUNTIMES` so a newly-added runtime can never be silently exempted. This
38
+ * is the single canonical predicate; `--copy-creds` (`hosts/credentials.ts`) and
39
+ * `--lease` (this module's `buildCredentialScript`) both refuse against it.
40
+ */
41
+ const NATIVE_OAUTH_RUNTIMES = new Set(LEASE_RUNTIMES.map((c) => c.id));
42
+ /** True when `id` is a native OAuth / session login that MUST NOT be copied between devices (SING-1b). */
43
+ export function isNativeOAuthRuntime(id) {
44
+ return NATIVE_OAUTH_RUNTIMES.has(id);
45
+ }
46
+ /** The fail-loud message naming the forbidden runtimes and the portable path to use instead. */
47
+ export function nativeOAuthTransferRefusal(nativeRuntimes) {
48
+ return (`Refusing to copy native OAuth / session credentials to another device: ${nativeRuntimes.join(', ')}.\n` +
49
+ `A rotating harness login copied across machines is invalidated on its next server-side token ` +
50
+ `refresh — it logs the rest of the fleet out — so agents-cli never stores or transfers a harness's ` +
51
+ `interactive login (docs/specifications.md SING-1b).\n` +
52
+ `Use a portable provider account instead — a long-lived, non-rotating API key / setup-token that is ` +
53
+ `safe to reuse on many devices:\n` +
54
+ ` agents accounts add <name> --provider <provider> --auth <api-key|setup-token>\n` +
55
+ ` agents accounts sync <name> --device <host>`);
56
+ }
29
57
  /** First existing candidate path under the real home, or null. */
30
58
  function findLocalCred(cred) {
31
59
  const home = process.env.AGENTS_REAL_HOME || os.homedir();
@@ -225,36 +253,50 @@ export async function resolveClaudeCredentialsBlob(opts) {
225
253
  return readClaudeCredentialsBlob(home);
226
254
  }
227
255
  /**
228
- * Build a bash snippet that writes each picked runtime's token file to the box's
229
- * home-level config path (0600), from the token contents read locally. Returns
230
- * `''` when no runtimes were selected. The snippet is meant to be embedded in
231
- * the `--script-stdin` body (never argv).
256
+ * The credential-provisioning snippet for a `--lease` box.
232
257
  *
233
- * `extras.claudeCredentialsJson` (the raw wrapped payload from
234
- * `resolveClaudeCredentialsBlob`) is written to `~/.claude/.credentials.json` in
235
- * ADDITION to claude's `.claude.json` config without it the box is "Not logged in".
258
+ * Every runtime this could serialize is a native OAuth / session login
259
+ * (`LEASE_RUNTIMES`), and SING-1b forbids copying one to another device —
260
+ * including an ephemeral leased box, whose refresh of a shared rotating token
261
+ * invalidates every other holder. So this no longer writes a login: it REFUSES
262
+ * (throws, steering to the portable `agents accounts` path) whenever a picked
263
+ * runtime actually has a native credential to copy — signed in locally
264
+ * (`credPath`), or a Claude OAuth blob supplied. A picked runtime with nothing to
265
+ * copy is simply skipped, so `buildCredentialScript` returns `''` (a no-op box
266
+ * bootstrap) rather than throwing on a not-signed-in runtime.
236
267
  */
237
- export function buildCredentialScript(picked, detected, extras) {
268
+ /**
269
+ * The native OAuth runtimes among `picked` that actually have a credential to copy
270
+ * — signed in locally (`credPath`) or a Claude OAuth blob supplied — i.e. the ones
271
+ * a transfer would leak. A picked runtime with nothing to copy is not refused.
272
+ */
273
+ export function refusedNativeOAuthRuntimes(picked, detected, extras) {
238
274
  const byId = new Map(detected.map((d) => [d.id, d]));
239
- const parts = [];
240
- for (const id of picked) {
241
- const d = byId.get(id);
242
- const cred = LEASE_RUNTIMES.find((c) => c.id === id);
243
- if (!d?.credPath || !cred)
244
- continue;
245
- let contents;
246
- try {
247
- contents = fs.readFileSync(d.credPath, 'utf-8');
248
- }
249
- catch {
250
- continue;
251
- }
252
- parts.push(buildHomeFileWriteScript(cred.remote, contents));
253
- // For claude the file above is config/state only; the OAuth token is a
254
- // second artifact without it the box comes up "Not logged in".
255
- if (id === 'claude' && extras?.claudeCredentialsJson) {
256
- parts.push(buildHomeFileWriteScript(CLAUDE_TOKEN_REMOTE, extras.claudeCredentialsJson));
257
- }
275
+ return picked.filter((id) => {
276
+ if (!isNativeOAuthRuntime(id))
277
+ return false;
278
+ const hasLocalFile = !!byId.get(id)?.credPath && LEASE_RUNTIMES.some((c) => c.id === id);
279
+ const hasClaudeToken = id === 'claude' && !!extras?.claudeCredentialsJson;
280
+ return hasLocalFile || hasClaudeToken;
281
+ });
282
+ }
283
+ /**
284
+ * Throw the SING-1b refusal if any picked runtime would transfer a native OAuth
285
+ * login. Callers should invoke this at a FAIL-FAST point — before any expensive or
286
+ * costly side effect (e.g. before `crabboxWarmup` leases a paid box) — so a refused
287
+ * `--lease` never leaks infra, mirroring how `--copy-creds` refuses before it opens
288
+ * an SSH connection.
289
+ */
290
+ export function assertNoNativeOAuthTransfer(picked, detected, extras) {
291
+ const refused = refusedNativeOAuthRuntimes(picked, detected, extras);
292
+ if (refused.length > 0) {
293
+ throw new Error(nativeOAuthTransferRefusal(refused));
258
294
  }
259
- return parts.join('\n');
295
+ }
296
+ export function buildCredentialScript(picked, detected, extras) {
297
+ assertNoNativeOAuthTransfer(picked, detected, extras);
298
+ // Past the refusal there is nothing to serialize — every runtime this handles is
299
+ // native OAuth, so a non-refused set has no credential to copy. (Always '' today;
300
+ // the shape stays general in case a non-native runtime is ever added.)
301
+ return '';
260
302
  }
@@ -6,7 +6,43 @@
6
6
  * (macOS), systemd (Linux), or as a plain detached process. PID tracking,
7
7
  * log output, reload (SIGHUP), and graceful shutdown are handled here.
8
8
  */
9
- import { getAgentsBinPath } from './cli-entry.js';
9
+ import { isolatedHomeSuffix } from '../service-manifest.js';
10
+ import { getAgentsBinPath } from '../cli-entry.js';
11
+ /**
12
+ * RUSH-2639 (residual): launchd/systemd route `unload`/`load`/`list` by the
13
+ * service identifier ALONE, never by the plist/unit file's path. Baking the
14
+ * caller's HOME into the plist content (the earlier RUSH-2639 fix, above)
15
+ * keeps the STARTED daemon inside its sandbox, but every hermetic-test
16
+ * instance and every real interactive install still share the one literal
17
+ * `PLIST_NAME`/`SYSTEMD_UNIT` string. `startDaemonLocked`'s own `unload`
18
+ * before `load` is written to be a no-op ("not loaded, expected") for a
19
+ * plist that has never been loaded — but confirmed on darwin: when a
20
+ * DIFFERENT plist is already loaded under that same label, `unload
21
+ * <this-instance's-own-never-loaded-path>` still tears down the OTHER job
22
+ * (verified directly against real launchctl with two throwaway plists
23
+ * sharing one label — the second job's own `unload` silently kills the
24
+ * first, still alive under a different path). On a machine running several
25
+ * hermetic test forks at once (CI) — or a developer's own suite next to
26
+ * their real always-on daemon — that "other job" is a live daemon with
27
+ * DIFFERENT baked-in state.
28
+ *
29
+ * Namespace the identifier itself whenever HOME has been redirected away
30
+ * from the account's real home. `os.userInfo().homedir` reads the OS/passwd
31
+ * record directly and ignores `$HOME` (unlike `os.homedir()`, which honors
32
+ * it), so comparing the two detects exactly this redirection — true for
33
+ * every hermetic test process, false for every real interactive/production
34
+ * invocation, so a real user's daemon keeps registering under the unchanged
35
+ * production identifier.
36
+ *
37
+ * The rule itself now lives in `service-manifest.ts` — the daemon was the first
38
+ * manifest to need it, not the only one — and is re-exported here because it is
39
+ * part of this module's published surface.
40
+ */
41
+ export { isolatedHomeSuffix };
42
+ /** launchd Label for this process's daemon — namespaced under a redirected HOME. */
43
+ export declare function daemonServiceLabel(): string;
44
+ /** systemd --user unit name for this process's daemon — namespaced under a redirected HOME. */
45
+ export declare function daemonSystemdUnitName(): string;
10
46
  /**
11
47
  * How many consecutive failed daemon starts disable the *implicit* auto-start
12
48
  * (`ensureDaemonStarted`). Matches `DAEMON_START_LIMIT_BURST` so the two layers
@@ -194,6 +230,21 @@ export declare function writeOwnerOnlyServiceManifest(filePath: string, content:
194
230
  * credential at all. Routine runs authenticate through the per-account
195
231
  * CLAUDE_CONFIG_DIR login on this device, exactly like an interactive
196
232
  * `agents run`, so no credential ever touches the service manifest.
233
+ *
234
+ * RUSH-2639: launchd does NOT inherit `launchctl load`'s caller's process
235
+ * environment — a spawned daemon only ever sees the login session's default
236
+ * env plus whatever this dict adds/overrides. Before this fix the dict carried
237
+ * only PATH, so HOME resolved to the launchd session's own value regardless of
238
+ * what HOME the process that generated (and loaded) the plist was running
239
+ * under. In production that's a no-op (the login session's HOME already is the
240
+ * real HOME), but under a hermetic test harness that redirects HOME to a
241
+ * fork-private sandbox, a launchd-started daemon silently escaped the sandbox
242
+ * and bootstrapped `~/.agents` (.cache/.history/.system/routines) in the
243
+ * developer's/runner's REAL home. Baking HOME (and the AGENTS_REAL_HOME seam
244
+ * every version-home consumer honors, see tests/setup.ts) into the plist at
245
+ * generation time makes the launchd child inherit the SAME home the caller
246
+ * resolved, exactly like the plain detached-spawn path already does via
247
+ * `env: {...process.env}`.
197
248
  */
198
249
  export declare function generateLaunchdPlist(agentsBin?: string): string;
199
250
  /**
@@ -203,6 +254,13 @@ export declare function generateLaunchdPlist(agentsBin?: string): string;
203
254
  * credential at all. Routine runs authenticate through the per-account
204
255
  * CLAUDE_CONFIG_DIR login on this device, exactly like an interactive
205
256
  * `agents run`, so no credential ever touches the unit file.
257
+ *
258
+ * RUSH-2639: same seam as `generateLaunchdPlist` — a systemd --user unit is
259
+ * started by the user's systemd instance, not the process that generated the
260
+ * unit, so HOME is whatever that session provides unless this file pins it.
261
+ * Baking HOME (and AGENTS_REAL_HOME) in at generation time keeps a
262
+ * hermetic-test-started unit inside its sandbox instead of resolving against
263
+ * the real account home.
206
264
  */
207
265
  export declare function generateSystemdUnit(agentsBin?: string): string;
208
266
  export { getAgentsBinPath };