@phnx-labs/agents-cli 1.22.38 → 1.22.40

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 (554) hide show
  1. package/CHANGELOG.md +302 -0
  2. package/README.md +111 -70
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +46 -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 +260 -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.js +206 -94
  13. package/dist/commands/budget.d.ts +7 -6
  14. package/dist/commands/budget.js +8 -7
  15. package/dist/commands/cloud.js +17 -20
  16. package/dist/commands/commands.js +1 -1
  17. package/dist/commands/computer-actions.d.ts +1 -35
  18. package/dist/commands/computer-actions.js +13 -181
  19. package/dist/commands/computer.d.ts +28 -3
  20. package/dist/commands/computer.js +93 -65
  21. package/dist/commands/config.js +47 -4
  22. package/dist/commands/cost.d.ts +2 -1
  23. package/dist/commands/cost.js +7 -6
  24. package/dist/commands/daemon.js +151 -4
  25. package/dist/commands/detach.js +1 -1
  26. package/dist/commands/doctor.js +19 -11
  27. package/dist/commands/events.js +1 -1
  28. package/dist/commands/exec.d.ts +2 -50
  29. package/dist/commands/exec.js +161 -216
  30. package/dist/commands/factory.js +1 -1
  31. package/dist/commands/feed.d.ts +2 -2
  32. package/dist/commands/feed.js +9 -12
  33. package/dist/commands/fleet-capture.js +25 -27
  34. package/dist/commands/focus.d.ts +2 -3
  35. package/dist/commands/focus.js +34 -9
  36. package/dist/commands/go.js +15 -5
  37. package/dist/commands/harness.d.ts +3 -3
  38. package/dist/commands/harness.js +53 -5
  39. package/dist/commands/hooks.js +1 -1
  40. package/dist/commands/import.js +2 -2
  41. package/dist/commands/insights.d.ts +5 -5
  42. package/dist/commands/insights.js +15 -9
  43. package/dist/commands/inspect.d.ts +2 -3
  44. package/dist/commands/inspect.js +4 -16
  45. package/dist/commands/logs.d.ts +2 -2
  46. package/dist/commands/logs.js +9 -9
  47. package/dist/commands/mcp.js +2 -2
  48. package/dist/commands/memory.js +1 -1
  49. package/dist/commands/message.d.ts +1 -1
  50. package/dist/commands/message.js +7 -7
  51. package/dist/commands/mine.d.ts +11 -8
  52. package/dist/commands/mine.js +11 -10
  53. package/dist/commands/models.js +1 -1
  54. package/dist/commands/modes.js +1 -1
  55. package/dist/commands/monitors.js +23 -6
  56. package/dist/commands/output.d.ts +7 -6
  57. package/dist/commands/output.js +11 -10
  58. package/dist/commands/packages.js +4 -4
  59. package/dist/commands/perf.js +1 -1
  60. package/dist/commands/permissions.js +49 -32
  61. package/dist/commands/plugins.d.ts +1 -1
  62. package/dist/commands/plugins.js +3 -3
  63. package/dist/commands/profiles.d.ts +6 -9
  64. package/dist/commands/profiles.js +8 -321
  65. package/dist/commands/projects.d.ts +9 -0
  66. package/dist/commands/projects.js +140 -8
  67. package/dist/commands/prune.js +5 -13
  68. package/dist/commands/refresh-rules.js +1 -1
  69. package/dist/commands/repo.d.ts +5 -7
  70. package/dist/commands/repo.js +34 -18
  71. package/dist/commands/resource-view.js +4 -0
  72. package/dist/commands/resume.d.ts +11 -7
  73. package/dist/commands/resume.js +82 -98
  74. package/dist/commands/route.d.ts +12 -0
  75. package/dist/commands/route.js +261 -0
  76. package/dist/commands/routines.d.ts +2 -3
  77. package/dist/commands/routines.js +120 -145
  78. package/dist/commands/rules.js +1 -1
  79. package/dist/commands/run-account-picker.d.ts +1 -1
  80. package/dist/commands/run-account-picker.js +2 -2
  81. package/dist/commands/run-broadcast.d.ts +21 -0
  82. package/dist/commands/run-broadcast.js +89 -0
  83. package/dist/commands/run-cloud.js +1 -1
  84. package/dist/commands/secrets-vault.d.ts +10 -0
  85. package/dist/commands/{login.js → secrets-vault.js} +34 -14
  86. package/dist/commands/secrets.d.ts +4 -4
  87. package/dist/commands/secrets.js +72 -63
  88. package/dist/commands/sessions-backfill.js +1 -1
  89. package/dist/commands/sessions-browser.d.ts +1 -1
  90. package/dist/commands/sessions-browser.js +9 -5
  91. package/dist/commands/sessions-export.js +2 -2
  92. package/dist/commands/sessions-inject.js +4 -5
  93. package/dist/commands/sessions-migrate.js +16 -27
  94. package/dist/commands/sessions-picker.d.ts +13 -0
  95. package/dist/commands/sessions-picker.js +182 -8
  96. package/dist/commands/sessions-resume.d.ts +7 -3
  97. package/dist/commands/sessions-resume.js +81 -33
  98. package/dist/commands/sessions-stats.js +2 -2
  99. package/dist/commands/sessions.d.ts +75 -68
  100. package/dist/commands/sessions.js +142 -180
  101. package/dist/commands/setup-computer.js +1 -1
  102. package/dist/commands/setup-fleet.js +3 -0
  103. package/dist/commands/setup-mine.d.ts +7 -3
  104. package/dist/commands/setup-mine.js +13 -8
  105. package/dist/commands/setup-secrets.js +2 -2
  106. package/dist/commands/setup-watchdog.js +2 -2
  107. package/dist/commands/setup.js +7 -2
  108. package/dist/commands/share.d.ts +65 -0
  109. package/dist/commands/share.js +253 -20
  110. package/dist/commands/skills.js +3 -3
  111. package/dist/commands/snapshot.d.ts +2 -2
  112. package/dist/commands/snapshot.js +9 -9
  113. package/dist/commands/ssh.d.ts +1 -1
  114. package/dist/commands/ssh.js +318 -48
  115. package/dist/commands/subagents.js +1 -1
  116. package/dist/commands/sync.js +24 -9
  117. package/dist/commands/teams.d.ts +2 -2
  118. package/dist/commands/teams.js +9 -18
  119. package/dist/commands/tmux.js +5 -1
  120. package/dist/commands/trash.js +1 -1
  121. package/dist/commands/usage.d.ts +1 -1
  122. package/dist/commands/usage.js +2 -2
  123. package/dist/commands/utils.d.ts +4 -14
  124. package/dist/commands/utils.js +6 -27
  125. package/dist/commands/versions.js +2 -2
  126. package/dist/commands/view.d.ts +9 -77
  127. package/dist/commands/view.js +23 -8
  128. package/dist/commands/watchdog.js +1 -1
  129. package/dist/commands/webhook.js +11 -25
  130. package/dist/commands/workflows.js +1 -1
  131. package/dist/index.js +1 -1
  132. package/dist/lib/account-capabilities.d.ts +39 -0
  133. package/dist/lib/account-capabilities.js +59 -0
  134. package/dist/lib/account-catalog.js +1 -1
  135. package/dist/lib/account-registry.d.ts +66 -0
  136. package/dist/lib/account-registry.js +151 -5
  137. package/dist/lib/{rotate.d.ts → accounting/rotate.d.ts} +4 -4
  138. package/dist/lib/{rotate.js → accounting/rotate.js} +8 -8
  139. package/dist/lib/{usage.d.ts → accounting/usage.d.ts} +4 -4
  140. package/dist/lib/{usage.js → accounting/usage.js} +11 -11
  141. package/dist/lib/agent-spec/provider.js +1 -1
  142. package/dist/lib/agents.d.ts +72 -4
  143. package/dist/lib/agents.js +231 -199
  144. package/dist/lib/answer-router.d.ts +2 -2
  145. package/dist/lib/ask-classifier.d.ts +1 -1
  146. package/dist/lib/ask-classifier.js +1 -1
  147. package/dist/lib/audit/log.js +1 -1
  148. package/dist/lib/auth-health.d.ts +1 -1
  149. package/dist/lib/auth-health.js +2 -2
  150. package/dist/lib/brand.js +1 -1
  151. package/dist/lib/browser/caller-identity.d.ts +28 -0
  152. package/dist/lib/browser/caller-identity.js +156 -0
  153. package/dist/lib/browser/cdp.js +1 -1
  154. package/dist/lib/browser/drivers/ssh.d.ts +1 -1
  155. package/dist/lib/browser/drivers/ssh.js +2 -2
  156. package/dist/lib/browser/hygiene.d.ts +10 -2
  157. package/dist/lib/browser/hygiene.js +7 -4
  158. package/dist/lib/browser/ipc.d.ts +22 -2
  159. package/dist/lib/browser/ipc.js +185 -21
  160. package/dist/lib/browser/profiles.d.ts +67 -3
  161. package/dist/lib/browser/profiles.js +129 -7
  162. package/dist/lib/browser/remote-control.d.ts +2 -2
  163. package/dist/lib/browser/remote-control.js +3 -3
  164. package/dist/lib/browser/runtime-state.d.ts +79 -0
  165. package/dist/lib/browser/runtime-state.js +119 -1
  166. package/dist/lib/browser/service.d.ts +113 -1
  167. package/dist/lib/browser/service.js +454 -40
  168. package/dist/lib/browser/sessions-list.d.ts +2 -1
  169. package/dist/lib/browser/sessions-list.js +4 -13
  170. package/dist/lib/browser/types.d.ts +18 -0
  171. package/dist/lib/budget/config.js +1 -1
  172. package/dist/lib/budget/ledger.js +1 -1
  173. package/dist/lib/byok-usage.js +1 -1
  174. package/dist/lib/capabilities.js +3 -15
  175. package/dist/lib/catchup.d.ts +1 -1
  176. package/dist/lib/catchup.js +1 -1
  177. package/dist/lib/cloud/dispatch.js +1 -1
  178. package/dist/lib/cloud/host.d.ts +3 -3
  179. package/dist/lib/cloud/host.js +5 -5
  180. package/dist/lib/cloud/rush.d.ts +9 -21
  181. package/dist/lib/cloud/rush.js +33 -120
  182. package/dist/lib/cloud/types.d.ts +2 -2
  183. package/dist/lib/commands.js +3 -13
  184. package/dist/lib/computer/actions.d.ts +36 -0
  185. package/dist/lib/computer/actions.js +162 -0
  186. package/dist/lib/computer/dispatch.d.ts +2 -2
  187. package/dist/lib/computer/dispatch.js +2 -2
  188. package/dist/lib/computer/sessions-list.d.ts +3 -3
  189. package/dist/lib/computer/sessions-list.js +2 -2
  190. package/dist/lib/config-keys.d.ts +12 -3
  191. package/dist/lib/config-keys.js +29 -6
  192. package/dist/lib/config-machine-keys.d.ts +4 -2
  193. package/dist/lib/config-machine-keys.js +6 -2
  194. package/dist/lib/crabbox/lease.js +9 -1
  195. package/dist/lib/crabbox/runtimes.d.ts +32 -7
  196. package/dist/lib/crabbox/runtimes.js +72 -30
  197. package/dist/lib/{daemon.d.ts → daemon/daemon.d.ts} +59 -1
  198. package/dist/lib/{daemon.js → daemon/daemon.js} +237 -49
  199. package/dist/lib/daemon-services.d.ts +1 -1
  200. package/dist/lib/daemon-services.js +5 -0
  201. package/dist/lib/daemon-ticks.d.ts +25 -0
  202. package/dist/lib/daemon-ticks.js +31 -1
  203. package/dist/lib/daemon-webhooks.d.ts +102 -0
  204. package/dist/lib/daemon-webhooks.js +210 -0
  205. package/dist/lib/device-config.d.ts +116 -72
  206. package/dist/lib/device-config.js +366 -132
  207. package/dist/lib/devices/config-migration.d.ts +29 -34
  208. package/dist/lib/devices/config-migration.js +209 -130
  209. package/dist/lib/devices/connect.d.ts +2 -2
  210. package/dist/lib/devices/connect.js +2 -2
  211. package/dist/lib/devices/discovery-policy.d.ts +30 -0
  212. package/dist/lib/devices/discovery-policy.js +101 -0
  213. package/dist/lib/devices/fleet-inventory.js +8 -3
  214. package/dist/lib/devices/harness-inventory.d.ts +1 -1
  215. package/dist/lib/devices/harness-inventory.js +12 -3
  216. package/dist/lib/devices/known-hosts.js +1 -1
  217. package/dist/lib/devices/pool.d.ts +61 -0
  218. package/dist/lib/devices/pool.js +83 -0
  219. package/dist/lib/devices/registry.d.ts +1 -1
  220. package/dist/lib/devices/registry.js +1 -1
  221. package/dist/lib/devices/resolve-profile.d.ts +2 -2
  222. package/dist/lib/devices/resolve-profile.js +2 -2
  223. package/dist/lib/devices/resolve-target.d.ts +1 -1
  224. package/dist/lib/devices/resolve-target.js +4 -4
  225. package/dist/lib/devices/self-host.d.ts +1 -1
  226. package/dist/lib/devices/self-host.js +3 -3
  227. package/dist/lib/devices/ssh-config.d.ts +1 -1
  228. package/dist/lib/devices/stats-cache.js +1 -1
  229. package/dist/lib/devices/sync.d.ts +3 -1
  230. package/dist/lib/devices/sync.js +3 -3
  231. package/dist/lib/doctor-diff.js +4 -4
  232. package/dist/lib/drift-sync.js +2 -2
  233. package/dist/lib/drift.js +2 -2
  234. package/dist/lib/event-families.d.ts +1 -1
  235. package/dist/lib/event-stream.d.ts +1 -1
  236. package/dist/lib/event-stream.js +2 -2
  237. package/dist/lib/events-ingest.js +2 -2
  238. package/dist/lib/exec.d.ts +8 -5
  239. package/dist/lib/exec.js +19 -13
  240. package/dist/lib/factory/snapshot.d.ts +1 -1
  241. package/dist/lib/factory/snapshot.js +1 -1
  242. package/dist/lib/{activity.d.ts → feed/activity.d.ts} +1 -1
  243. package/dist/lib/{activity.js → feed/activity.js} +7 -7
  244. package/dist/lib/{events.d.ts → feed/events.d.ts} +2 -2
  245. package/dist/lib/{events.js → feed/events.js} +5 -5
  246. package/dist/lib/{feed.js → feed/feed.js} +4 -4
  247. package/dist/lib/feed-outcome.d.ts +1 -1
  248. package/dist/lib/feed-policy.d.ts +1 -1
  249. package/dist/lib/feed-policy.js +1 -1
  250. package/dist/lib/feed-post.d.ts +1 -1
  251. package/dist/lib/feed-post.js +1 -1
  252. package/dist/lib/feed-ranking.d.ts +1 -1
  253. package/dist/lib/fleet/apply.d.ts +0 -6
  254. package/dist/lib/fleet/apply.js +18 -45
  255. package/dist/lib/fleet/auth-sync.d.ts +16 -35
  256. package/dist/lib/fleet/auth-sync.js +16 -75
  257. package/dist/lib/fleet/capture.js +8 -6
  258. package/dist/lib/fleet/manifest.js +23 -11
  259. package/dist/lib/fleet/types.d.ts +19 -7
  260. package/dist/lib/fleet-cache.d.ts +1 -1
  261. package/dist/lib/fleet-cache.js +1 -1
  262. package/dist/lib/format.d.ts +19 -0
  263. package/dist/lib/format.js +44 -1
  264. package/dist/lib/friction-heuristics.d.ts +1 -1
  265. package/dist/lib/git.d.ts +24 -1
  266. package/dist/lib/git.js +82 -38
  267. package/dist/lib/heal.js +3 -3
  268. package/dist/lib/hooks.d.ts +18 -0
  269. package/dist/lib/hooks.js +113 -1
  270. package/dist/lib/hosts/credentials.d.ts +30 -10
  271. package/dist/lib/hosts/credentials.js +38 -26
  272. package/dist/lib/hosts/dispatch.d.ts +3 -3
  273. package/dist/lib/hosts/dispatch.js +3 -3
  274. package/dist/lib/hosts/option.d.ts +3 -3
  275. package/dist/lib/hosts/option.js +7 -8
  276. package/dist/lib/hosts/passthrough.d.ts +17 -17
  277. package/dist/lib/hosts/passthrough.js +67 -50
  278. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  279. package/dist/lib/hosts/providers/devices.js +1 -1
  280. package/dist/lib/hosts/reconcile.d.ts +1 -1
  281. package/dist/lib/hosts/reconcile.js +1 -1
  282. package/dist/lib/hosts/reconnect.d.ts +1 -1
  283. package/dist/lib/hosts/reconnect.js +2 -2
  284. package/dist/lib/hosts/registry.d.ts +5 -5
  285. package/dist/lib/hosts/registry.js +5 -5
  286. package/dist/lib/hosts/remote-cmd.d.ts +10 -10
  287. package/dist/lib/hosts/remote-cmd.js +25 -18
  288. package/dist/lib/hosts/remote-os.d.ts +4 -4
  289. package/dist/lib/hosts/remote-os.js +4 -4
  290. package/dist/lib/hosts/remote-session-id.d.ts +2 -2
  291. package/dist/lib/hosts/remote-session-id.js +2 -2
  292. package/dist/lib/hosts/routing-flag.d.ts +3 -3
  293. package/dist/lib/hosts/routing-flag.js +4 -5
  294. package/dist/lib/hosts/run-target.d.ts +4 -4
  295. package/dist/lib/hosts/run-target.js +4 -4
  296. package/dist/lib/hosts/session-index.d.ts +2 -2
  297. package/dist/lib/hosts/session-index.js +1 -1
  298. package/dist/lib/hosts/session-marker.d.ts +1 -1
  299. package/dist/lib/hosts/session-marker.js +1 -1
  300. package/dist/lib/hosts/types.d.ts +2 -2
  301. package/dist/lib/hosts/types.js +2 -2
  302. package/dist/lib/import.js +1 -1
  303. package/dist/lib/{migrate.d.ts → installations/migrate.d.ts} +49 -1
  304. package/dist/lib/{migrate.js → installations/migrate.js} +265 -38
  305. package/dist/lib/installations/resolve.js +1 -1
  306. package/dist/lib/installations/strategies.js +1 -1
  307. package/dist/lib/installations/update.js +2 -2
  308. package/dist/lib/{versions.d.ts → installations/versions.d.ts} +12 -3
  309. package/dist/lib/{versions.js → installations/versions.js} +51 -31
  310. package/dist/lib/isolation-boundary-report.js +1 -1
  311. package/dist/lib/linear-projects.d.ts +28 -0
  312. package/dist/lib/linear-projects.js +30 -0
  313. package/dist/lib/loop.js +1 -1
  314. package/dist/lib/mailbox-gc.js +1 -1
  315. package/dist/lib/mailbox.js +1 -1
  316. package/dist/lib/mcp-registry.d.ts +62 -0
  317. package/dist/lib/mcp-registry.js +177 -0
  318. package/dist/lib/mcp.d.ts +5 -0
  319. package/dist/lib/mcp.js +124 -307
  320. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  321. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  322. package/dist/lib/menubar/install-menubar.d.ts +7 -0
  323. package/dist/lib/menubar/install-menubar.js +24 -6
  324. package/dist/lib/menubar/snapshot.d.ts +7 -0
  325. package/dist/lib/menubar/snapshot.js +8 -6
  326. package/dist/lib/models.js +1 -1
  327. package/dist/lib/monitors/config.d.ts +12 -0
  328. package/dist/lib/monitors/config.js +3 -0
  329. package/dist/lib/monitors/dispatch.js +26 -5
  330. package/dist/lib/monitors/engine.js +10 -0
  331. package/dist/lib/monitors/sources/webhook.d.ts +1 -1
  332. package/dist/lib/monitors/state.d.ts +42 -0
  333. package/dist/lib/monitors/state.js +30 -0
  334. package/dist/lib/notify.d.ts +1 -1
  335. package/dist/lib/observe-aliases.d.ts +2 -2
  336. package/dist/lib/observe-aliases.js +2 -11
  337. package/dist/lib/output/git-output.js +2 -2
  338. package/dist/lib/overdue.d.ts +1 -1
  339. package/dist/lib/overdue.js +1 -1
  340. package/dist/lib/permissions-registry.d.ts +65 -0
  341. package/dist/lib/permissions-registry.js +599 -0
  342. package/dist/lib/permissions.d.ts +24 -13
  343. package/dist/lib/permissions.js +52 -271
  344. package/dist/lib/picker.d.ts +16 -0
  345. package/dist/lib/picker.js +33 -3
  346. package/dist/lib/placement.d.ts +1 -1
  347. package/dist/lib/placement.js +4 -4
  348. package/dist/lib/platform/paths.d.ts +8 -0
  349. package/dist/lib/platform/paths.js +11 -0
  350. package/dist/lib/platform/posixpath.js +3 -3
  351. package/dist/lib/{plugin-marketplace.d.ts → plugins/plugin-marketplace.d.ts} +1 -1
  352. package/dist/lib/{plugin-marketplace.js → plugins/plugin-marketplace.js} +2 -2
  353. package/dist/lib/{plugins.d.ts → plugins/plugins.d.ts} +1 -1
  354. package/dist/lib/{plugins.js → plugins/plugins.js} +7 -7
  355. package/dist/lib/{skills.d.ts → plugins/skills.d.ts} +1 -1
  356. package/dist/lib/{skills.js → plugins/skills.js} +7 -7
  357. package/dist/lib/pricing/cost.d.ts +1 -1
  358. package/dist/lib/pricing/cost.js +1 -1
  359. package/dist/lib/profiles-presets.d.ts +1 -1
  360. package/dist/lib/profiles-presets.js +1 -1
  361. package/dist/lib/profiles.js +2 -2
  362. package/dist/lib/project-import.js +4 -1
  363. package/dist/lib/project-launch.d.ts +1 -1
  364. package/dist/lib/project-launch.js +3 -3
  365. package/dist/lib/project-pull.d.ts +128 -0
  366. package/dist/lib/project-pull.js +384 -0
  367. package/dist/lib/project-root.d.ts +2 -2
  368. package/dist/lib/project-root.js +2 -2
  369. package/dist/lib/project-status.js +1 -1
  370. package/dist/lib/projects.d.ts +23 -0
  371. package/dist/lib/projects.js +29 -6
  372. package/dist/lib/refresh.d.ts +12 -1
  373. package/dist/lib/refresh.js +16 -9
  374. package/dist/lib/registry.d.ts +9 -2
  375. package/dist/lib/registry.js +11 -4
  376. package/dist/lib/resources.d.ts +2 -2
  377. package/dist/lib/resources.js +2 -2
  378. package/dist/lib/routers.d.ts +81 -0
  379. package/dist/lib/routers.js +153 -0
  380. package/dist/lib/routine-context.d.ts +1 -0
  381. package/dist/lib/routine-context.js +7 -2
  382. package/dist/lib/routine-notify-owner.d.ts +1 -1
  383. package/dist/lib/routine-notify.d.ts +1 -1
  384. package/dist/lib/routine-notify.js +1 -1
  385. package/dist/lib/routine-process-cleanup.d.ts +1 -1
  386. package/dist/lib/routine-readiness.d.ts +1 -1
  387. package/dist/lib/routine-readiness.js +11 -4
  388. package/dist/lib/routines-placement.d.ts +12 -2
  389. package/dist/lib/routines-placement.js +20 -3
  390. package/dist/lib/routines-project.d.ts +1 -1
  391. package/dist/lib/routines-project.js +1 -1
  392. package/dist/lib/rules/compile.d.ts +1 -0
  393. package/dist/lib/rules/compile.js +10 -2
  394. package/dist/lib/rules/rules.js +1 -1
  395. package/dist/lib/run-notify.js +1 -1
  396. package/dist/lib/runner.d.ts +80 -2
  397. package/dist/lib/runner.js +241 -62
  398. package/dist/lib/sandbox.d.ts +1 -1
  399. package/dist/lib/scheduler.d.ts +1 -1
  400. package/dist/lib/scheduler.js +1 -1
  401. package/dist/lib/{routines.d.ts → scheduling/routines.d.ts} +54 -9
  402. package/dist/lib/{routines.js → scheduling/routines.js} +173 -14
  403. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  404. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  405. package/dist/lib/secrets/agent.js +2 -2
  406. package/dist/lib/secrets/audit.js +1 -1
  407. package/dist/lib/secrets/bundles.d.ts +3 -3
  408. package/dist/lib/secrets/bundles.js +7 -7
  409. package/dist/lib/secrets/index.js +1 -1
  410. package/dist/lib/secrets/list-filter.d.ts +1 -1
  411. package/dist/lib/secrets/list-filter.js +2 -2
  412. package/dist/lib/secrets/push.d.ts +1 -1
  413. package/dist/lib/secrets/push.js +10 -12
  414. package/dist/lib/secrets/remote.d.ts +12 -10
  415. package/dist/lib/secrets/remote.js +21 -14
  416. package/dist/lib/secrets/vault.js +2 -2
  417. package/dist/lib/self-heal/checks/shadowing.js +1 -1
  418. package/dist/lib/self-heal/checks/shims.js +1 -1
  419. package/dist/lib/self-update.d.ts +39 -4
  420. package/dist/lib/self-update.js +78 -25
  421. package/dist/lib/serve/control.d.ts +1 -1
  422. package/dist/lib/serve/control.js +4 -4
  423. package/dist/lib/serve/data.d.ts +1 -1
  424. package/dist/lib/serve/data.js +1 -1
  425. package/dist/lib/serve/stream.js +1 -1
  426. package/dist/lib/service-manifest.d.ts +29 -0
  427. package/dist/lib/service-manifest.js +80 -0
  428. package/dist/lib/session/active.d.ts +59 -7
  429. package/dist/lib/session/active.js +158 -17
  430. package/dist/lib/session/bash-command.js +1 -1
  431. package/dist/lib/session/claude-accounts.d.ts +1 -1
  432. package/dist/lib/session/claude-accounts.js +1 -1
  433. package/dist/lib/session/db.d.ts +10 -2
  434. package/dist/lib/session/db.js +25 -6
  435. package/dist/lib/session/discover.d.ts +77 -0
  436. package/dist/lib/session/discover.js +130 -25
  437. package/dist/lib/session/fork.js +1 -1
  438. package/dist/lib/session/inject.d.ts +1 -1
  439. package/dist/lib/session/insights.d.ts +1 -1
  440. package/dist/lib/session/insights.js +1 -1
  441. package/dist/lib/session/live-metadata.d.ts +15 -0
  442. package/dist/lib/session/live-metadata.js +76 -0
  443. package/dist/lib/session/migrate-targets.d.ts +1 -1
  444. package/dist/lib/session/recovery.d.ts +1 -1
  445. package/dist/lib/session/recovery.js +2 -2
  446. package/dist/lib/session/remote-active.d.ts +10 -1
  447. package/dist/lib/session/remote-active.js +8 -3
  448. package/dist/lib/session/remote-bundle.d.ts +1 -1
  449. package/dist/lib/session/remote-bundle.js +2 -2
  450. package/dist/lib/session/remote-list.d.ts +15 -4
  451. package/dist/lib/session/remote-list.js +40 -3
  452. package/dist/lib/session/remote.d.ts +5 -5
  453. package/dist/lib/session/remote.js +13 -17
  454. package/dist/lib/session/resume-command.d.ts +3 -2
  455. package/dist/lib/session/resume-command.js +4 -3
  456. package/dist/lib/session/resume-owner.d.ts +3 -3
  457. package/dist/lib/session/resume-owner.js +3 -3
  458. package/dist/lib/session/session-cache.d.ts +12 -0
  459. package/dist/lib/session/session-cache.js +2 -0
  460. package/dist/lib/session/shell-programs.js +1 -1
  461. package/dist/lib/session/state.js +5 -5
  462. package/dist/lib/session/team-filter.d.ts +1 -1
  463. package/dist/lib/session/team-filter.js +1 -1
  464. package/dist/lib/session/types.d.ts +3 -3
  465. package/dist/lib/session/width.d.ts +2 -2
  466. package/dist/lib/session/width.js +2 -2
  467. package/dist/lib/share/delete.d.ts +21 -0
  468. package/dist/lib/share/delete.js +42 -0
  469. package/dist/lib/share/publish.d.ts +82 -0
  470. package/dist/lib/share/publish.js +170 -18
  471. package/dist/lib/share/worker-template.js +172 -9
  472. package/dist/lib/shims.js +35 -7
  473. package/dist/lib/smart-launch.d.ts +36 -6
  474. package/dist/lib/smart-launch.js +65 -8
  475. package/dist/lib/snapshot.d.ts +4 -4
  476. package/dist/lib/snapshot.js +2 -2
  477. package/dist/lib/ssh-exec.d.ts +1 -1
  478. package/dist/lib/ssh-exec.js +2 -2
  479. package/dist/lib/ssh-tunnel.d.ts +10 -10
  480. package/dist/lib/ssh-tunnel.js +12 -12
  481. package/dist/lib/staleness/checkers/hooks.d.ts +1 -1
  482. package/dist/lib/staleness/checkers/hooks.js +1 -1
  483. package/dist/lib/staleness/detectors/permissions.js +0 -23
  484. package/dist/lib/staleness/detectors/plugins.js +1 -1
  485. package/dist/lib/staleness/fingerprint.js +1 -1
  486. package/dist/lib/staleness/layers.d.ts +1 -1
  487. package/dist/lib/staleness/layers.js +1 -1
  488. package/dist/lib/staleness/writers/mcp.js +3 -1
  489. package/dist/lib/staleness/writers/plugins.js +1 -1
  490. package/dist/lib/staleness/writers/types.d.ts +8 -0
  491. package/dist/lib/startup/command-registry.d.ts +5 -147
  492. package/dist/lib/startup/command-registry.js +38 -303
  493. package/dist/lib/startup/dev-build.d.ts +0 -21
  494. package/dist/lib/startup/dev-build.js +29 -8
  495. package/dist/lib/state.d.ts +19 -1
  496. package/dist/lib/state.js +120 -51
  497. package/dist/lib/subagents.js +1 -1
  498. package/dist/lib/sync-status.js +1 -1
  499. package/dist/lib/sync-umbrella.d.ts +6 -1
  500. package/dist/lib/sync-umbrella.js +9 -4
  501. package/dist/lib/teams/agents.js +2 -2
  502. package/dist/lib/teams/registry.js +1 -1
  503. package/dist/lib/terminal/backends/vscodium-agent.js +1 -1
  504. package/dist/lib/terminal/engine.js +1 -1
  505. package/dist/lib/terminal/index.d.ts +4 -0
  506. package/dist/lib/terminal/index.js +3 -0
  507. package/dist/lib/terminal/inject.d.ts +2 -2
  508. package/dist/lib/terminal/inject.js +2 -2
  509. package/dist/lib/terminal/transport.js +1 -1
  510. package/dist/lib/tmux/index.d.ts +1 -1
  511. package/dist/lib/tmux/index.js +1 -1
  512. package/dist/lib/tmux/session.d.ts +21 -5
  513. package/dist/lib/tmux/session.js +76 -22
  514. package/dist/lib/triggers/handlers.d.ts +1 -1
  515. package/dist/lib/triggers/handlers.js +2 -2
  516. package/dist/lib/triggers/webhook.d.ts +36 -2
  517. package/dist/lib/triggers/webhook.js +97 -42
  518. package/dist/lib/types.d.ts +18 -6
  519. package/dist/lib/usage-fleet.d.ts +1 -1
  520. package/dist/lib/usage-fleet.js +1 -1
  521. package/dist/lib/usage-refresh.d.ts +1 -1
  522. package/dist/lib/usage-refresh.js +3 -3
  523. package/dist/lib/version-duplicates.js +2 -2
  524. package/dist/lib/view-types.d.ts +56 -0
  525. package/dist/lib/view-types.js +1 -0
  526. package/dist/lib/watchdog/rotate.d.ts +2 -2
  527. package/dist/lib/watchdog/rotate.js +3 -3
  528. package/dist/lib/watchdog/runner.d.ts +2 -3
  529. package/dist/lib/watchdog/runner.js +3 -4
  530. package/dist/lib/workflows.js +1 -1
  531. package/package.json +2 -1
  532. package/scripts/postinstall.js +2 -2
  533. package/dist/commands/bench.d.ts +0 -2
  534. package/dist/commands/bench.js +0 -101
  535. package/dist/commands/cp.d.ts +0 -84
  536. package/dist/commands/cp.js +0 -231
  537. package/dist/commands/login.d.ts +0 -2
  538. package/dist/lib/resources/commands.d.ts +0 -46
  539. package/dist/lib/resources/commands.js +0 -211
  540. package/dist/lib/resources/hooks.d.ts +0 -16
  541. package/dist/lib/resources/hooks.js +0 -153
  542. package/dist/lib/resources/mcp.d.ts +0 -34
  543. package/dist/lib/resources/mcp.js +0 -250
  544. package/dist/lib/resources/memory.d.ts +0 -15
  545. package/dist/lib/resources/memory.js +0 -46
  546. package/dist/lib/resources/permissions.d.ts +0 -13
  547. package/dist/lib/resources/permissions.js +0 -202
  548. package/dist/lib/resources/rules.d.ts +0 -46
  549. package/dist/lib/resources/rules.js +0 -179
  550. package/dist/lib/resources/skills.d.ts +0 -37
  551. package/dist/lib/resources/skills.js +0 -247
  552. package/dist/lib/resources/subagents.d.ts +0 -46
  553. package/dist/lib/resources/subagents.js +0 -202
  554. /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();
@@ -9,7 +9,7 @@
9
9
  import type { AgentId } from './types.js';
10
10
  import { type ModelTier } from './model-tiers.js';
11
11
  /** The top-level scope of a unified config key. */
12
- export type ConfigScope = 'run' | 'interactive' | 'usage' | 'browser' | 'project' | 'device';
12
+ export type ConfigScope = 'run' | 'interactive' | 'usage' | 'auto' | 'browser' | 'project' | 'device';
13
13
  /** A run-time default key: model, mode, effort, or tier override. */
14
14
  export interface ParsedRunConfigKey {
15
15
  scope: 'run';
@@ -28,6 +28,11 @@ export interface ParsedUsageConfigKey {
28
28
  scope: 'usage';
29
29
  property: 'primary-host';
30
30
  }
31
+ /** Which devices automatic placement (`--device auto`) may pick. */
32
+ export interface ParsedAutoConfigKey {
33
+ scope: 'auto';
34
+ property: 'pool';
35
+ }
31
36
  /** The default browser profile (device-scope, self or peer). */
32
37
  export interface ParsedBrowserConfigKey {
33
38
  scope: 'browser';
@@ -44,8 +49,8 @@ export interface ParsedDeviceConfigKey {
44
49
  device: string;
45
50
  property: DeviceConfigProperty;
46
51
  }
47
- export type ParsedConfigKey = ParsedRunConfigKey | ParsedInteractiveConfigKey | ParsedUsageConfigKey | ParsedBrowserConfigKey | ParsedProjectConfigKey | ParsedDeviceConfigKey;
48
- export type DeviceConfigProperty = 'max-agents' | 'scheduler' | 'daemon' | 'watchdog' | 'browser.remote-control' | 'notes' | 'browser.profile';
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' | 'browser.task-idle-minutes' | 'notes' | 'browser.profile';
49
54
  /** Normalize agent@version to use `@` consistently. */
50
55
  export declare function formatAgentVersion(agent: AgentId, version: string): string;
51
56
  /**
@@ -58,13 +63,17 @@ export declare function formatAgentVersion(agent: AgentId, version: string): str
58
63
  * run.<agent@version>.tier.<cheap|default|best|ultra>
59
64
  * interactive.host
60
65
  * usage.primary-host
66
+ * auto.pool
61
67
  * browser.profile
62
68
  * project.root
69
+ * devices.<name>.role
63
70
  * devices.<name>.max-agents
64
71
  * devices.<name>.scheduler
65
72
  * devices.<name>.daemon
66
73
  * devices.<name>.watchdog
74
+ * devices.<name>.tmux
67
75
  * devices.<name>.browser.remote-control
76
+ * devices.<name>.browser.task-idle-minutes
68
77
  * devices.<name>.notes
69
78
  * devices.<name>.browser.profile
70
79
  */
@@ -10,11 +10,14 @@ import { AGENTS } from './agents.js';
10
10
  import { MODEL_TIERS } from './model-tiers.js';
11
11
  import { VERSION_RE } from './run-defaults.js';
12
12
  const DEVICE_CONFIG_PROPERTIES = [
13
+ 'role',
13
14
  'max-agents',
14
15
  'scheduler',
15
16
  'daemon',
16
17
  'watchdog',
18
+ 'tmux',
17
19
  'browser.remote-control',
20
+ 'browser.task-idle-minutes',
18
21
  'notes',
19
22
  'browser.profile',
20
23
  ];
@@ -45,13 +48,17 @@ export function formatAgentVersion(agent, version) {
45
48
  * run.<agent@version>.tier.<cheap|default|best|ultra>
46
49
  * interactive.host
47
50
  * usage.primary-host
51
+ * auto.pool
48
52
  * browser.profile
49
53
  * project.root
54
+ * devices.<name>.role
50
55
  * devices.<name>.max-agents
51
56
  * devices.<name>.scheduler
52
57
  * devices.<name>.daemon
53
58
  * devices.<name>.watchdog
59
+ * devices.<name>.tmux
54
60
  * devices.<name>.browser.remote-control
61
+ * devices.<name>.browser.task-idle-minutes
55
62
  * devices.<name>.notes
56
63
  * devices.<name>.browser.profile
57
64
  */
@@ -75,13 +82,16 @@ export function parseConfigKey(key) {
75
82
  if (raw === 'usage.primary-host') {
76
83
  return { scope: 'usage', property: 'primary-host' };
77
84
  }
85
+ if (raw === 'auto.pool') {
86
+ return { scope: 'auto', property: 'pool' };
87
+ }
78
88
  if (raw === 'browser.profile') {
79
89
  return { scope: 'browser', property: 'profile' };
80
90
  }
81
91
  if (raw === 'project.root') {
82
92
  return { scope: 'project', property: 'root' };
83
93
  }
84
- const deviceMatch = raw.match(/^devices\.(.+)\.(max-agents|scheduler|daemon|watchdog|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)$/);
85
95
  if (deviceMatch) {
86
96
  return {
87
97
  scope: 'device',
@@ -99,6 +109,9 @@ export function parseConfigKey(key) {
99
109
  if (raw.startsWith('usage.')) {
100
110
  throw new Error(`Invalid usage config key '${key}'. Use usage.primary-host.`);
101
111
  }
112
+ if (raw.startsWith('auto.')) {
113
+ throw new Error(`Invalid auto config key '${key}'. Use auto.pool.`);
114
+ }
102
115
  if (raw.startsWith('browser.')) {
103
116
  throw new Error(`Invalid browser config key '${key}'. Use browser.profile.`);
104
117
  }
@@ -108,7 +121,7 @@ export function parseConfigKey(key) {
108
121
  if (raw.startsWith('devices.')) {
109
122
  throw new Error(`Invalid device config key '${key}'. Expected devices.<name>.<${DEVICE_CONFIG_PROPERTIES.join('|')}>.`);
110
123
  }
111
- throw new Error(`Unknown config scope in '${key}'. Use one of: run, interactive, usage, browser, project, devices.`);
124
+ throw new Error(`Unknown config scope in '${key}'. Use one of: run, interactive, usage, auto, browser, project, devices.`);
112
125
  }
113
126
  /** Render a parsed key back to its canonical dotted string. */
114
127
  export function formatConfigKey(parsed) {
@@ -122,6 +135,8 @@ export function formatConfigKey(parsed) {
122
135
  return 'interactive.host';
123
136
  case 'usage':
124
137
  return 'usage.primary-host';
138
+ case 'auto':
139
+ return 'auto.pool';
125
140
  case 'browser':
126
141
  return parsed.device ? `devices.${parsed.device}.browser.profile` : 'browser.profile';
127
142
  case 'project':
@@ -137,7 +152,7 @@ export function listKnownConfigKeys() {
137
152
  for (const tier of MODEL_TIERS) {
138
153
  keys.push(`run.<agent@version>.tier.${tier}`);
139
154
  }
140
- keys.push('interactive.host', 'usage.primary-host', 'browser.profile', 'project.root');
155
+ keys.push('interactive.host', 'usage.primary-host', 'auto.pool', 'browser.profile', 'project.root');
141
156
  for (const prop of DEVICE_CONFIG_PROPERTIES) {
142
157
  keys.push(`devices.<name>.${prop}`);
143
158
  }
@@ -150,6 +165,8 @@ export function listKnownConfigKeys() {
150
165
  */
151
166
  export function devicePropertyToConfigName(property) {
152
167
  switch (property) {
168
+ case 'role':
169
+ return 'role';
153
170
  case 'max-agents':
154
171
  return 'agents.max-concurrent';
155
172
  case 'scheduler':
@@ -158,8 +175,12 @@ export function devicePropertyToConfigName(property) {
158
175
  return 'daemon.enabled';
159
176
  case 'watchdog':
160
177
  return 'watchdog.enabled';
178
+ case 'tmux':
179
+ return 'tmux.enabled';
161
180
  case 'browser.remote-control':
162
181
  return 'browser.remote-control';
182
+ case 'browser.task-idle-minutes':
183
+ return 'browser.task-idle-minutes';
163
184
  case 'notes':
164
185
  return 'notes';
165
186
  case 'browser.profile':
@@ -181,13 +202,15 @@ export function configKeyStorageHint(parsed) {
181
202
  return 'config.interactiveHost';
182
203
  case 'usage':
183
204
  return 'config.usagePrimaryHost';
205
+ case 'auto':
206
+ return 'config.autoPool';
184
207
  case 'browser':
185
208
  return parsed.device
186
- ? `fleet.devices.${parsed.device}.config.defaultBrowserProfile`
187
- : 'fleet.devices.<self>.config.defaultBrowserProfile';
209
+ ? `devices/${parsed.device}/agents.yaml config.defaultBrowserProfile`
210
+ : 'devices/<self>/agents.yaml config.defaultBrowserProfile';
188
211
  case 'project':
189
212
  return 'devices.<self>.projectRoot';
190
213
  case 'device':
191
- 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)`;
192
215
  }
193
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`,
@@ -14,4 +16,6 @@ export const MACHINE_LOCAL_YAML_KEYS = new Set([
14
16
  'browserRemoteControl', // browser.remote-control — a consent flag; syncing it is a leak
15
17
  'schedulerEnabled', // scheduler.enabled
16
18
  'daemonEnabled', // daemon.enabled
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
17
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
  }