@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
@@ -7,7 +7,7 @@
7
7
  * launch inside (the directory ABOVE the git root) and cached in `agents.yaml`
8
8
  * so later runs resolve a bare slug from anywhere. It is stored home-relative
9
9
  * (`~/…`) when it sits under `$HOME`, so the SAME value resolves on a remote
10
- * host whose home differs (`/home/<user>` vs `/Users/<user>`): a `--host` run
10
+ * host whose home differs (`/home/<user>` vs `/Users/<user>`): a `--device` run
11
11
  * keeps the `~` and lets the remote login shell expand it (see `remoteCdPrefix`
12
12
  * in `hosts/dispatch.ts`), while a local run expands `~` against the local home.
13
13
  */
@@ -42,7 +42,7 @@ export declare function homeRemainder(p: string): string | null;
42
42
  * caller gave no `--cwd`/`--remote-cwd` (and for an interactive `agents ssh`
43
43
  * login with no command).
44
44
  *
45
- * Without this a `--host` run — or an `agents ssh <device>` login — lands in the
45
+ * Without this a `--device` run — or an `agents ssh <device>` login — lands in the
46
46
  * remote `$HOME`, so an agent launched from a repo starts with no project
47
47
  * context and the user has to `cd` by hand. Only a cwd under the LOCAL home is
48
48
  * mirrored — that is the part with a meaningful remote analogue (`~/src/x`
@@ -7,7 +7,7 @@
7
7
  * launch inside (the directory ABOVE the git root) and cached in `agents.yaml`
8
8
  * so later runs resolve a bare slug from anywhere. It is stored home-relative
9
9
  * (`~/…`) when it sits under `$HOME`, so the SAME value resolves on a remote
10
- * host whose home differs (`/home/<user>` vs `/Users/<user>`): a `--host` run
10
+ * host whose home differs (`/home/<user>` vs `/Users/<user>`): a `--device` run
11
11
  * keeps the `~` and lets the remote login shell expand it (see `remoteCdPrefix`
12
12
  * in `hosts/dispatch.ts`), while a local run expands `~` against the local home.
13
13
  */
@@ -80,7 +80,7 @@ export function homeRemainder(p) {
80
80
  * caller gave no `--cwd`/`--remote-cwd` (and for an interactive `agents ssh`
81
81
  * login with no command).
82
82
  *
83
- * Without this a `--host` run — or an `agents ssh <device>` login — lands in the
83
+ * Without this a `--device` run — or an `agents ssh <device>` login — lands in the
84
84
  * remote `$HOME`, so an agent launched from a repo starts with no project
85
85
  * context and the user has to `cd` by hand. Only a cwd under the LOCAL home is
86
86
  * mirrored — that is the part with a meaningful remote analogue (`~/src/x`
@@ -15,7 +15,7 @@ import { execFile } from 'child_process';
15
15
  import { promisify } from 'util';
16
16
  import chalk from 'chalk';
17
17
  import { projectNameForCwd } from './projects.js';
18
- import { readRecentActivity } from './activity.js';
18
+ import { readRecentActivity } from './feed/activity.js';
19
19
  const execFileAsync = promisify(execFile);
20
20
  /**
21
21
  * How many recent merges `gh` is asked for. A repo busy enough that all of them
@@ -40,6 +40,18 @@ export interface ProjectRepo {
40
40
  */
41
41
  path?: string;
42
42
  }
43
+ /**
44
+ * One checkout target for `projects pull`: a home-relative path plus the
45
+ * expected GitHub slug so the pull step can verify the remote matches before
46
+ * fast-forwarding. `expectedSlug` is absent when a bound dir has no declared
47
+ * slug (the pull still fast-forwards; it just skips the slug check).
48
+ */
49
+ export interface ProjectRepoTarget {
50
+ /** Home-relative path — re-roots on each fleet device. */
51
+ path: string;
52
+ /** Expected GitHub slug (`owner/repo`) for the remote; absent = unchecked. */
53
+ expectedSlug?: string;
54
+ }
43
55
  /**
44
56
  * A described context anchor: a subdirectory plus what it is. Agents starting on
45
57
  * the project read `purpose` to know where to look — an indexed starting point,
@@ -151,6 +163,17 @@ export declare function removeProjectDef(name: string): boolean;
151
163
  * expanded against the local home. Returns undefined when neither is set.
152
164
  */
153
165
  export declare function projectBasePath(def: ProjectDef, forRemote: boolean): string | undefined;
166
+ /**
167
+ * All checkout targets for a project definition, each tagged with its expected
168
+ * GitHub slug. The primary root carries `def.repo`; each `repos[i].path`
169
+ * carries `repos[i].slug`. Paths are home-relative (re-root per fleet device)
170
+ * and include missing checkouts so a remote peer can answer `missing` for them.
171
+ *
172
+ * This is the single authoritative expansion for both `projects status` (via
173
+ * {@link projectProbeTargets}) and `projects pull`, so the two commands always
174
+ * operate on exactly the same set of directories.
175
+ */
176
+ export declare function projectRepoTargetsForDef(def: ProjectDef): ProjectRepoTarget[];
154
177
  /**
155
178
  * The directories `projects status` probes across the fleet: the repo root plus
156
179
  * every bound checkout, home-relative so each host re-roots them, and including
@@ -317,18 +317,41 @@ function projectDirList(def, opts) {
317
317
  }
318
318
  return out;
319
319
  }
320
+ /**
321
+ * All checkout targets for a project definition, each tagged with its expected
322
+ * GitHub slug. The primary root carries `def.repo`; each `repos[i].path`
323
+ * carries `repos[i].slug`. Paths are home-relative (re-root per fleet device)
324
+ * and include missing checkouts so a remote peer can answer `missing` for them.
325
+ *
326
+ * This is the single authoritative expansion for both `projects status` (via
327
+ * {@link projectProbeTargets}) and `projects pull`, so the two commands always
328
+ * operate on exactly the same set of directories.
329
+ */
330
+ export function projectRepoTargetsForDef(def) {
331
+ const targets = [];
332
+ const seen = new Set();
333
+ const addTarget = (rawPath, expectedSlug) => {
334
+ const abs = path.resolve(expandLocalHome(rawPath));
335
+ if (seen.has(abs))
336
+ return;
337
+ seen.add(abs);
338
+ targets.push({ path: toHomeRelative(abs), expectedSlug });
339
+ };
340
+ if (def.root && def.root.length > 0)
341
+ addTarget(def.root, def.repo);
342
+ for (const r of def.repos ?? []) {
343
+ if (r.path && r.path.length > 0)
344
+ addTarget(r.path, r.slug);
345
+ }
346
+ return targets;
347
+ }
320
348
  /**
321
349
  * The directories `projects status` probes across the fleet: the repo root plus
322
350
  * every bound checkout, home-relative so each host re-roots them, and including
323
351
  * directories absent here so a peer can still answer `✗ missing` for them.
324
352
  */
325
353
  export function projectProbeTargets(def) {
326
- return projectDirList(def, {
327
- primary: def.root,
328
- forRemote: true,
329
- keepMissing: true,
330
- joinSubpath: false,
331
- });
354
+ return projectRepoTargetsForDef(def).map((t) => t.path);
332
355
  }
333
356
  /**
334
357
  * The directories an agent spawned on this project should reach: the cwd first
@@ -30,4 +30,15 @@ export interface RefreshOptions {
30
30
  *
31
31
  * Idempotent — safe to run repeatedly. No network operations.
32
32
  */
33
- export declare function refresh(options?: RefreshOptions): Promise<void>;
33
+ /**
34
+ * What a reconcile pass refused to write, so callers can report it.
35
+ *
36
+ * `refresh` used to return void, so a resource agents-cli declined to write was
37
+ * visible only on the interactive path — `agents sync --yes` and the
38
+ * `--device all` fan-out reported a clean sync (RUSH-2700).
39
+ */
40
+ export interface RefreshResult {
41
+ /** User-facing sentences, one per refused resource, prefixed with the agent. */
42
+ declined: string[];
43
+ }
44
+ export declare function refresh(options?: RefreshOptions): Promise<RefreshResult>;
@@ -18,11 +18,11 @@ import { capableAgents } from './capabilities.js';
18
18
  import { AGENTS, MANAGED_AGENT_IDS, getAllCliStates, registerMcpToTargets, agentLabel, } from './agents.js';
19
19
  import { readManifest, MANIFEST_FILENAME } from './manifest.js';
20
20
  import { getUserAgentsDir } from './state.js';
21
- import { installVersion, listInstalledVersions, isVersionIsolated, getGlobalDefault, setGlobalDefault, getVersionHomePath, syncResourcesToVersion, getAvailableResources, getActuallySyncedResources, getNewResources, getProjectOnlyResources, hasNewResources, promptNewResourceSelection, promptResourceSelection, resolveConfiguredAgentTargets, } from './versions.js';
21
+ import { installVersion, listInstalledVersions, isVersionIsolated, getGlobalDefault, setGlobalDefault, getVersionHomePath, syncResourcesToVersion, getAvailableResources, getActuallySyncedResources, getNewResources, getProjectOnlyResources, hasNewResources, promptNewResourceSelection, promptResourceSelection, resolveConfiguredAgentTargets, } from './installations/versions.js';
22
22
  import { listCliStatus, installCli, describeMethod, describeCheck, selectInstallMethod, } from './cli-resources.js';
23
23
  import { ensureShimCurrent, isShimsInPath, addShimsToPath, getPathSetupInstructions, switchConfigSymlink, switchHomeFileSymlinks, } from './shims.js';
24
24
  import { parseHookManifest, registerHooksToSettings } from './hooks.js';
25
- import { isPromptCancelled } from '../commands/utils.js';
25
+ import { isPromptCancelled } from './format.js';
26
26
  /**
27
27
  * Old repo layout stored promptcuts under claude/promptcuts.yaml (agent-scoped).
28
28
  * The new layout is `~/.agents/.system/promptcuts.yaml` at the repo root — the
@@ -49,19 +49,15 @@ function migratePromptcutsToRoot(agentsDir, quiet = false) {
49
49
  }
50
50
  }
51
51
  }
52
- /**
53
- * Re-materialize local state from declared configuration: install CLI versions,
54
- * register MCP servers, sync resources to version homes, register hooks, add
55
- * shims to PATH, prompt for missing defaults, install declared host-CLIs.
56
- *
57
- * Idempotent — safe to run repeatedly. No network operations.
58
- */
59
52
  export async function refresh(options = {}) {
60
53
  const { agentFilter, skipPrompts = false, skipClis = false, quiet = false } = options;
61
54
  const agentsDir = getUserAgentsDir();
62
55
  // Gate every human progress line so --json / fleet fan-out can parse stdout.
63
56
  const log = (...args) => { if (!quiet)
64
57
  console.log(...args); };
58
+ // Resources this pass refused to write, surfaced by the caller. An empty
59
+ // synced list cannot also mean "declined and here is why" (RUSH-2700).
60
+ const declined = [];
65
61
  migratePromptcutsToRoot(agentsDir, quiet);
66
62
  const manifest = readManifest(agentsDir);
67
63
  if (!manifest) {
@@ -194,6 +190,9 @@ export async function refresh(options = {}) {
194
190
  kinds.add('mcp');
195
191
  if (syncResult.plugins.length > 0)
196
192
  kinds.add('plugins');
193
+ for (const reason of syncResult.declined) {
194
+ declined.push(`${agentLabel(agentId)}@${ver}: ${reason}`);
195
+ }
197
196
  }
198
197
  if (kinds.size > 0) {
199
198
  const verNote = versionsToSync.length > 1
@@ -347,4 +346,12 @@ export async function refresh(options = {}) {
347
346
  log(chalk.yellow(`CLI install skipped: ${err.message}`));
348
347
  }
349
348
  }
349
+ // A resource agents-cli refused to write is reported, never swallowed —
350
+ // an empty synced list on its own reads as "nothing to do" (RUSH-2700).
351
+ if (declined.length > 0) {
352
+ log(chalk.yellow('Not written:'));
353
+ for (const reason of declined)
354
+ log(` ${chalk.yellow(reason)}`);
355
+ }
356
+ return { declined };
350
357
  }
@@ -93,8 +93,15 @@ export declare function resolvePackage(identifier: string): Promise<ResolvedPack
93
93
  /** Lowercase hex sha256 of a file's bytes. Small files only (SKILL.md). */
94
94
  export declare function sha256OfFile(file: string): string;
95
95
  /**
96
- * Parse an 'owner/repo' slug from a git remote URL (https or scp-style ssh).
97
- * Returns null if the URL is not a recognizable GitHub-style remote.
96
+ * Parse an 'owner/repo' slug from a git remote URL (https or scp-style ssh) or
97
+ * a filesystem-path remote whose path is slug-shaped (`…/github.com/owner/repo`).
98
+ * Returns null if the remote is not a recognizable GitHub-style shape.
99
+ *
100
+ * Backslashes are folded to forward slashes first: a real git URL never
101
+ * contains one, but a local-path remote on Windows does
102
+ * (`C:\…\github.com\org\a.git`), and without the fold the same remote that
103
+ * parses as `org/a` on POSIX returns null on win32 — which made the
104
+ * projects-pull slug verification fail closed as `blocked` there (RUSH-2694).
98
105
  */
99
106
  export declare function parseOwnerRepoFromRemote(remoteUrl: string): string | null;
100
107
  /**
@@ -10,7 +10,7 @@ import * as path from 'path';
10
10
  import { createHash } from 'crypto';
11
11
  import { DEFAULT_REGISTRIES, SEEDED_REGISTRIES } from './types.js';
12
12
  import { readMeta, writeMeta } from './state.js';
13
- import { discoverSkillsFromRepo } from './skills.js';
13
+ import { discoverSkillsFromRepo } from './plugins/skills.js';
14
14
  const UNSAFE_PACKAGE_SPEC_CHARS = /[;&|`$\s\x00-\x1f\x7f]/;
15
15
  const NPM_SPEC_PATTERN = /^(@[a-z0-9][a-z0-9-_.]*\/)?[a-z0-9][a-z0-9-_.]*(@[A-Za-z0-9._+-]+)?$/;
16
16
  const PYPI_SPEC_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*(\[[A-Za-z0-9,_-]+\])?(==[A-Za-z0-9._-]+)?$/;
@@ -481,11 +481,18 @@ export function sha256OfFile(file) {
481
481
  return createHash('sha256').update(fs.readFileSync(file)).digest('hex');
482
482
  }
483
483
  /**
484
- * Parse an 'owner/repo' slug from a git remote URL (https or scp-style ssh).
485
- * Returns null if the URL is not a recognizable GitHub-style remote.
484
+ * Parse an 'owner/repo' slug from a git remote URL (https or scp-style ssh) or
485
+ * a filesystem-path remote whose path is slug-shaped (`…/github.com/owner/repo`).
486
+ * Returns null if the remote is not a recognizable GitHub-style shape.
487
+ *
488
+ * Backslashes are folded to forward slashes first: a real git URL never
489
+ * contains one, but a local-path remote on Windows does
490
+ * (`C:\…\github.com\org\a.git`), and without the fold the same remote that
491
+ * parses as `org/a` on POSIX returns null on win32 — which made the
492
+ * projects-pull slug verification fail closed as `blocked` there (RUSH-2694).
486
493
  */
487
494
  export function parseOwnerRepoFromRemote(remoteUrl) {
488
- const s = remoteUrl.trim().replace(/\.git$/, '');
495
+ const s = remoteUrl.trim().replace(/\\/g, '/').replace(/\.git$/, '');
489
496
  // https://github.com/owner/repo or git@github.com:owner/repo
490
497
  const m = s.match(/github\.com[/:]([^/]+\/[^/]+)$/);
491
498
  return m ? m[1] : null;
@@ -3,9 +3,9 @@
3
3
  * Scans filesystem (source of truth) to find all installed resources for an agent.
4
4
  */
5
5
  import type { AgentId } from './types.js';
6
- import { type SkillParseError } from './skills.js';
6
+ import { type SkillParseError } from './plugins/skills.js';
7
7
  /** Resource kind — matches the subdirectory name under each repo root. */
8
- export type ResourceKind = 'commands' | 'skills' | 'hooks' | 'rules' | 'mcp' | 'clis' | 'permissions' | 'subagents' | 'workflows' | 'profiles' | 'secrets';
8
+ export type ResourceKind = 'commands' | 'skills' | 'hooks' | 'rules' | 'mcp' | 'clis' | 'permissions' | 'subagents' | 'workflows' | 'profiles' | 'routers' | 'secrets';
9
9
  /** A resource resolved with its origin. */
10
10
  export interface ResolvedResource {
11
11
  name: string;
@@ -6,10 +6,10 @@ import * as fs from 'fs';
6
6
  import * as path from 'path';
7
7
  import { AGENTS, listInstalledMcpsWithScope } from './agents.js';
8
8
  import { listInstalledCommandsWithScope, parseCommandMetadata } from './commands.js';
9
- import { listInstalledSkillsWithScope, parseSkillMetadata } from './skills.js';
9
+ import { listInstalledSkillsWithScope, parseSkillMetadata } from './plugins/skills.js';
10
10
  import { listOnDiskHooks } from './resource-inventory.js';
11
11
  import { listInstalledInstructionsWithScope } from './rules/rules.js';
12
- import { getEffectiveHome } from './versions.js';
12
+ import { getEffectiveHome } from './installations/versions.js';
13
13
  import { listMcpServerConfigs } from './mcp.js';
14
14
  import { WorkflowsHandler } from './resources/workflows.js';
15
15
  import { isCapable } from './capabilities.js';
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Router management -- named, task-typed allowlists of (harness, model/tier,
3
+ * account) that constrain an Agent Router decision. A router is a
4
+ * generalization of a profile (a profile ≡ a router pinned to one harness and
5
+ * one account). Stored as YAML files under ~/.agents/routers/.
6
+ *
7
+ * Routers resolve as a layered resource (project > user > system, like other
8
+ * resources -- see resources.ts) but are always CREATED in the user layer,
9
+ * mirroring profiles.ts.
10
+ */
11
+ /** Per-harness allowlist inside a router: eligible models/tiers + linked accounts. */
12
+ export interface RouterHarnessAllowlist {
13
+ /** Concrete model ids and/or tier tokens (cheap|default|best|ultra) eligible under this router. */
14
+ models: string[];
15
+ /** Durable credential accounts eligible under this router. Routing is limited to these. */
16
+ accounts?: string[];
17
+ }
18
+ /** A named router: a reusable, task-typed allowlist of harnesses x models/tiers x accounts. */
19
+ export interface Router {
20
+ name: string;
21
+ /** Free-text task type this router serves (e.g. "research", "prod-refactor"). */
22
+ task?: string;
23
+ /** Allowlist -- only these harness x model/tier x account combos are eligible under this router. */
24
+ harnesses: Record<string, RouterHarnessAllowlist>;
25
+ /** Scoped policy weights, applied within the router (consumed by routing, a later ticket). */
26
+ weights?: {
27
+ cost?: number;
28
+ success?: number;
29
+ headroom?: number;
30
+ };
31
+ /** Opt-in re-route of a pinned target when it's exhausted (consumed by routing, a later ticket). */
32
+ hijack?: boolean;
33
+ }
34
+ /** Directory this machine writes router YAML files to (user layer). */
35
+ export declare function routersDir(): string;
36
+ /** Validate a router name against the allowed pattern. Throws on invalid input. */
37
+ export declare function validateRouterName(name: string): void;
38
+ /** Check whether a router resolves, project > user > system (like other resources). */
39
+ export declare function routerExists(name: string, cwd?: string): boolean;
40
+ /**
41
+ * The layer a router currently resolves from ('project' | 'user' | 'system' |
42
+ * an extra-repo alias), or null if it doesn't resolve. `writeRouter` and
43
+ * `deleteRouter` only ever touch the user layer, so a caller that edits or
44
+ * removes a router MUST check this first -- editing a router that resolves
45
+ * from a non-user layer would silently write to a user-layer file that stays
46
+ * permanently shadowed (the edit "succeeds" but is never read back).
47
+ */
48
+ export declare function routerSource(name: string, cwd?: string): string | null;
49
+ /** Read a router, resolved project > user > system. Throws if not found or malformed. */
50
+ export declare function readRouter(name: string, cwd?: string): Router;
51
+ /** Write a router to disk atomically (write-to-tmp then rename). Always writes the user layer. */
52
+ export declare function writeRouter(router: Router): void;
53
+ /** Delete a router from the user layer. Returns false if it did not exist there. */
54
+ export declare function deleteRouter(name: string): boolean;
55
+ /**
56
+ * Fail-loud token validation (E1 of the Agent Router spec): a router MUST NOT
57
+ * persist a harness id or model/tier token this machine cannot vouch for.
58
+ * Throws naming the first invalid token found; the caller (route.ts) never
59
+ * calls {@link writeRouter} when this throws, so an invalid `create`/`allow`
60
+ * writes nothing.
61
+ *
62
+ * A harness id must be a real, registered agent (`AGENTS` in agents.ts) --
63
+ * checked regardless of whether that harness is installed on this machine,
64
+ * since a router is fleet-wide config and the harness may only run
65
+ * elsewhere. A model/tier token is valid when it is one of the four
66
+ * cross-harness tier tokens (cheap|default|best|ultra, always installable-
67
+ * agnostic), OR a concrete model id this machine can actually verify: either
68
+ * one of the harness's resolved tier rungs (`resolveTierMap` -- covers
69
+ * curated/no-catalog harnesses like Droid with zero install required) or a
70
+ * member of its extracted catalog (`getModelCatalog`, when a version of that
71
+ * harness is installed here). A concrete id for a harness with neither --
72
+ * not installed here, no curated ladder -- cannot be verified and is
73
+ * rejected rather than accepted unverified.
74
+ */
75
+ export declare function validateRouter(router: Router): void;
76
+ /**
77
+ * List every router resolved project > user > system (deduplicated union,
78
+ * project wins on a name collision -- same precedence as {@link resolveResource}).
79
+ * Malformed files are silently skipped, surfaced via `agents route show <name>`.
80
+ */
81
+ export declare function listRouters(cwd?: string): Router[];
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Router management -- named, task-typed allowlists of (harness, model/tier,
3
+ * account) that constrain an Agent Router decision. A router is a
4
+ * generalization of a profile (a profile ≡ a router pinned to one harness and
5
+ * one account). Stored as YAML files under ~/.agents/routers/.
6
+ *
7
+ * Routers resolve as a layered resource (project > user > system, like other
8
+ * resources -- see resources.ts) but are always CREATED in the user layer,
9
+ * mirroring profiles.ts.
10
+ */
11
+ import * as fs from 'fs';
12
+ import * as path from 'path';
13
+ import * as yaml from 'yaml';
14
+ import { getUserAgentsDir } from './state.js';
15
+ import { resolveResource, listResources } from './resources.js';
16
+ import { ALL_AGENT_IDS } from './agents.js';
17
+ import { isTierToken, resolveTierMap, MODEL_TIERS } from './model-tiers.js';
18
+ import { getModelCatalog } from './models.js';
19
+ import { resolveVersion } from './installations/versions.js';
20
+ const ROUTER_NAME_PATTERN = /^[a-z0-9][a-z0-9-_]{0,48}$/i;
21
+ /** Directory this machine writes router YAML files to (user layer). */
22
+ export function routersDir() {
23
+ return path.join(getUserAgentsDir(), 'routers');
24
+ }
25
+ function routerPath(name) {
26
+ return path.join(routersDir(), `${name}.yml`);
27
+ }
28
+ /** Validate a router name against the allowed pattern. Throws on invalid input. */
29
+ export function validateRouterName(name) {
30
+ if (!ROUTER_NAME_PATTERN.test(name)) {
31
+ throw new Error(`Invalid router name '${name}'. Use letters, digits, dash, underscore (max 48 chars).`);
32
+ }
33
+ }
34
+ /** Check whether a router resolves, project > user > system (like other resources). */
35
+ export function routerExists(name, cwd) {
36
+ validateRouterName(name);
37
+ return resolveResource('routers', name, cwd) !== null;
38
+ }
39
+ /**
40
+ * The layer a router currently resolves from ('project' | 'user' | 'system' |
41
+ * an extra-repo alias), or null if it doesn't resolve. `writeRouter` and
42
+ * `deleteRouter` only ever touch the user layer, so a caller that edits or
43
+ * removes a router MUST check this first -- editing a router that resolves
44
+ * from a non-user layer would silently write to a user-layer file that stays
45
+ * permanently shadowed (the edit "succeeds" but is never read back).
46
+ */
47
+ export function routerSource(name, cwd) {
48
+ validateRouterName(name);
49
+ return resolveResource('routers', name, cwd)?.source ?? null;
50
+ }
51
+ function parseRouterFile(file, name) {
52
+ const raw = fs.readFileSync(file, 'utf-8');
53
+ const parsed = yaml.parse(raw);
54
+ if (!parsed || typeof parsed !== 'object') {
55
+ throw new Error(`Router '${name}' is malformed.`);
56
+ }
57
+ if (!parsed.name)
58
+ parsed.name = name;
59
+ if (!parsed.harnesses || typeof parsed.harnesses !== 'object')
60
+ parsed.harnesses = {};
61
+ return parsed;
62
+ }
63
+ /** Read a router, resolved project > user > system. Throws if not found or malformed. */
64
+ export function readRouter(name, cwd) {
65
+ validateRouterName(name);
66
+ const resolved = resolveResource('routers', name, cwd);
67
+ if (!resolved) {
68
+ throw new Error(`Router '${name}' not found.`);
69
+ }
70
+ return parseRouterFile(resolved.path, name);
71
+ }
72
+ /** Write a router to disk atomically (write-to-tmp then rename). Always writes the user layer. */
73
+ export function writeRouter(router) {
74
+ validateRouterName(router.name);
75
+ const dir = routersDir();
76
+ fs.mkdirSync(dir, { recursive: true });
77
+ const body = yaml.stringify(router);
78
+ const file = routerPath(router.name);
79
+ const tmp = `${file}.tmp-${process.pid}`;
80
+ fs.writeFileSync(tmp, body, 'utf-8');
81
+ fs.renameSync(tmp, file);
82
+ }
83
+ /** Delete a router from the user layer. Returns false if it did not exist there. */
84
+ export function deleteRouter(name) {
85
+ validateRouterName(name);
86
+ const file = routerPath(name);
87
+ if (!fs.existsSync(file))
88
+ return false;
89
+ fs.unlinkSync(file);
90
+ return true;
91
+ }
92
+ /**
93
+ * Fail-loud token validation (E1 of the Agent Router spec): a router MUST NOT
94
+ * persist a harness id or model/tier token this machine cannot vouch for.
95
+ * Throws naming the first invalid token found; the caller (route.ts) never
96
+ * calls {@link writeRouter} when this throws, so an invalid `create`/`allow`
97
+ * writes nothing.
98
+ *
99
+ * A harness id must be a real, registered agent (`AGENTS` in agents.ts) --
100
+ * checked regardless of whether that harness is installed on this machine,
101
+ * since a router is fleet-wide config and the harness may only run
102
+ * elsewhere. A model/tier token is valid when it is one of the four
103
+ * cross-harness tier tokens (cheap|default|best|ultra, always installable-
104
+ * agnostic), OR a concrete model id this machine can actually verify: either
105
+ * one of the harness's resolved tier rungs (`resolveTierMap` -- covers
106
+ * curated/no-catalog harnesses like Droid with zero install required) or a
107
+ * member of its extracted catalog (`getModelCatalog`, when a version of that
108
+ * harness is installed here). A concrete id for a harness with neither --
109
+ * not installed here, no curated ladder -- cannot be verified and is
110
+ * rejected rather than accepted unverified.
111
+ */
112
+ export function validateRouter(router) {
113
+ for (const [harness, allowlist] of Object.entries(router.harnesses)) {
114
+ if (!ALL_AGENT_IDS.includes(harness)) {
115
+ throw new Error(`router '${router.name}': unknown harness '${harness}'. Known harnesses: ${ALL_AGENT_IDS.join(', ')}.`);
116
+ }
117
+ const agent = harness;
118
+ for (const token of allowlist.models) {
119
+ if (isTierToken(token))
120
+ continue;
121
+ const version = resolveVersion(agent) ?? '0.0.0';
122
+ const tierMap = resolveTierMap(agent, version);
123
+ const tierRungIds = new Set(MODEL_TIERS.map((t) => tierMap[t].model).filter((m) => m !== null));
124
+ if (tierRungIds.has(token))
125
+ continue;
126
+ const catalog = getModelCatalog(agent, version);
127
+ const inCatalog = catalog
128
+ ? catalog.models.some((m) => m.id === token) || Boolean(catalog.aliases[token])
129
+ : false;
130
+ if (inCatalog)
131
+ continue;
132
+ throw new Error(`router '${router.name}': unknown model '${token}' for harness '${harness}'. ` +
133
+ `Use a tier token (${MODEL_TIERS.join('|')}) or a model id '${harness}' actually ships.`);
134
+ }
135
+ }
136
+ }
137
+ /**
138
+ * List every router resolved project > user > system (deduplicated union,
139
+ * project wins on a name collision -- same precedence as {@link resolveResource}).
140
+ * Malformed files are silently skipped, surfaced via `agents route show <name>`.
141
+ */
142
+ export function listRouters(cwd) {
143
+ const routers = [];
144
+ for (const resolved of listResources('routers', cwd)) {
145
+ try {
146
+ routers.push(parseRouterFile(resolved.path, resolved.name));
147
+ }
148
+ catch {
149
+ // Skip malformed router files.
150
+ }
151
+ }
152
+ return routers.sort((a, b) => a.name.localeCompare(b.name));
153
+ }
@@ -148,4 +148,5 @@ export interface RoutineReadinessResult {
148
148
  */
149
149
  export declare function evaluateRoutineReadiness(context: ResolvedExecutionContext, probes?: HarnessReadinessProbes, opts?: {
150
150
  agent?: string;
151
+ version?: string;
151
152
  }): RoutineReadinessResult;
@@ -253,10 +253,15 @@ export function evaluateRoutineReadiness(context, probes = {}, opts = {}) {
253
253
  });
254
254
  }
255
255
  if (probes.agentInstalled && !probes.agentInstalled()) {
256
+ // A pinned version names its exact miss — "no usable version" would send the
257
+ // operator hunting for a harness that IS installed, just not at the pin.
258
+ const pinned = opts.version && opts.agent ? `${opts.agent}@${opts.version}` : undefined;
256
259
  return withBlocker(context, {
257
260
  code: 'agent_unavailable',
258
- message: `no usable version of ${opts.agent ?? 'the agent'} is installed on the target`,
259
- repair: opts.agent ? `agents add ${opts.agent}@<version>` : undefined,
261
+ message: pinned
262
+ ? `pinned ${pinned} is not installed on the target`
263
+ : `no usable version of ${opts.agent ?? 'the agent'} is installed on the target`,
264
+ repair: pinned ? `agents add ${pinned}` : (opts.agent ? `agents add ${opts.agent}@<version>` : undefined),
260
265
  });
261
266
  }
262
267
  if (probes.codexTrusted && context.absoluteCwd && !probes.codexTrusted(context.absoluteCwd)) {
@@ -26,7 +26,7 @@
26
26
  * delivers.
27
27
  */
28
28
  import type { Meta } from './types.js';
29
- import type { JobConfig, RunMeta } from './routines.js';
29
+ import type { JobConfig, RunMeta } from './scheduling/routines.js';
30
30
  /**
31
31
  * Owner-phone text for a routine FINISH, or null when the run did NOT fail. Only
32
32
  * `failed` and `timeout` are failures worth an owner ping — a `completed` run
@@ -21,7 +21,7 @@
21
21
  * return `null` when the threshold says "don't notify", and are unit-tested; the
22
22
  * `notifyRoutine*` wrappers do the filesystem read + dispatch for the daemon.
23
23
  */
24
- import type { JobConfig, RunMeta } from './routines.js';
24
+ import type { JobConfig, RunMeta } from './scheduling/routines.js';
25
25
  import { type DesktopNotification } from './menubar/notify-desktop.js';
26
26
  type RoutineKind = 'agent' | 'workflow' | 'command';
27
27
  /** Which flavor of routine a config/meta describes — drives the notify threshold. */
@@ -23,7 +23,7 @@
23
23
  */
24
24
  import * as fs from 'fs';
25
25
  import * as path from 'path';
26
- import { getRunDir } from './routines.js';
26
+ import { getRunDir } from './scheduling/routines.js';
27
27
  import { notifyDesktop } from './menubar/notify-desktop.js';
28
28
  /** Which flavor of routine a config/meta describes — drives the notify threshold. */
29
29
  export function routineKind(r) {
@@ -1,4 +1,4 @@
1
- import type { RunMeta } from './routines.js';
1
+ import type { RunMeta } from './scheduling/routines.js';
2
2
  export interface RoutineProcessCleanupOptions {
3
3
  runsDir?: string;
4
4
  alive?: (pid: number) => boolean;
@@ -9,7 +9,7 @@
9
9
  * add/edit/doctor/resume additionally call the live variant below, which probes
10
10
  * authentication and Codex's native workspace-trust record before activation.
11
11
  */
12
- import type { JobConfig } from './routines.js';
12
+ import type { JobConfig } from './scheduling/routines.js';
13
13
  import { type RoutineReadinessResult } from './routine-context.js';
14
14
  /**
15
15
  * Evaluate whether a routine is ready to activate on this box. `probeAgent`
@@ -12,9 +12,9 @@
12
12
  import * as fs from 'fs';
13
13
  import * as path from 'path';
14
14
  import * as TOML from 'smol-toml';
15
- import { resolveJobExecutionContext, resolveHostStrategy } from './routines.js';
15
+ import { resolveJobExecutionContext, resolveHostStrategy } from './scheduling/routines.js';
16
16
  import { evaluateRoutineReadiness } from './routine-context.js';
17
- import { getVersionHomePath, resolveVersion } from './versions.js';
17
+ import { getVersionHomePath, isVersionInstalled, resolveVersion } from './installations/versions.js';
18
18
  import { probeLocalFleetAuth } from './auth-health.js';
19
19
  import { resolveHostRunTarget } from './hosts/run-target.js';
20
20
  import { hostIdentityArgs, sshTargetFor } from './hosts/types.js';
@@ -36,14 +36,21 @@ export function evaluateActivationReadiness(config, deps = {}) {
36
36
  mode,
37
37
  probe: mode === 'local' ? undefined : null,
38
38
  });
39
- const probeAgent = deps.probeAgent ?? ((agent) => resolveVersion(agent) !== undefined);
39
+ // A pinned version on LOCAL placement must exist here — accepting a routine
40
+ // whose exact pin is absent just moves the failure to fire time (RUSH-2719).
41
+ // Remote host/fleet targets defer the check: their installs are unreachable
42
+ // from this box until the RUSH-2290 execution-context-on-target resolver.
43
+ const pinnedLocally = mode === 'local' ? config.version : undefined;
44
+ const probeAgent = deps.probeAgent ?? ((agent) => pinnedLocally
45
+ ? isVersionInstalled(agent, pinnedLocally)
46
+ : resolveVersion(agent) !== undefined);
40
47
  return evaluateRoutineReadiness(context, {
41
48
  // Command routines have no agent to install; workflow routines dispatch
42
49
  // through `agents run` (claude under the hood) and are checked at run time.
43
50
  agentInstalled: config.agent && !config.workflow && !config.command
44
51
  ? () => probeAgent(config.agent)
45
52
  : undefined,
46
- }, { agent: config.agent });
53
+ }, { agent: config.agent, version: pinnedLocally });
47
54
  }
48
55
  /** One-line human summary of a blocked readiness result, with its repair. */
49
56
  export function formatReadinessBlocker(result) {