@phnx-labs/agents-cli 1.22.46 → 1.22.49

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 (348) hide show
  1. package/CHANGELOG.md +663 -0
  2. package/LICENSE +102 -182
  3. package/README.md +96 -49
  4. package/dist/bootstrap.js +4 -2
  5. package/dist/cli/command-registry.d.ts +2 -1
  6. package/dist/cli/command-registry.js +6 -2
  7. package/dist/commands/accounts.d.ts +58 -0
  8. package/dist/commands/accounts.js +243 -25
  9. package/dist/commands/artifacts.js +7 -6
  10. package/dist/commands/attach.js +1 -1
  11. package/dist/commands/auth.js +7 -5
  12. package/dist/commands/browser-sessions-picker.js +9 -7
  13. package/dist/commands/browser.js +711 -62
  14. package/dist/commands/config.d.ts +0 -1
  15. package/dist/commands/config.js +26 -24
  16. package/dist/commands/cost.d.ts +1 -1
  17. package/dist/commands/daemon.d.ts +21 -0
  18. package/dist/commands/daemon.js +147 -12
  19. package/dist/commands/detach.d.ts +13 -0
  20. package/dist/commands/detach.js +11 -8
  21. package/dist/commands/exec.js +107 -53
  22. package/dist/commands/feed-watch.d.ts +2 -0
  23. package/dist/commands/feed-watch.js +28 -0
  24. package/dist/commands/feed.js +27 -0
  25. package/dist/commands/feedback.js +3 -19
  26. package/dist/commands/focus.d.ts +14 -0
  27. package/dist/commands/focus.js +48 -5
  28. package/dist/commands/go.d.ts +3 -0
  29. package/dist/commands/go.js +16 -3
  30. package/dist/commands/insights.d.ts +1 -1
  31. package/dist/commands/insights.js +2 -2
  32. package/dist/commands/inspect.js +2 -2
  33. package/dist/commands/lease.d.ts +1 -1
  34. package/dist/commands/lease.js +7 -6
  35. package/dist/commands/mailboxes.js +4 -3
  36. package/dist/commands/menubar.js +11 -4
  37. package/dist/commands/projects.d.ts +16 -1
  38. package/dist/commands/projects.js +58 -64
  39. package/dist/commands/resume.js +1 -1
  40. package/dist/commands/route.js +4 -4
  41. package/dist/commands/routines.js +4 -3
  42. package/dist/commands/run-broadcast.d.ts +1 -1
  43. package/dist/commands/run-broadcast.js +1 -1
  44. package/dist/commands/sessions-picker-factory.d.ts +2 -1
  45. package/dist/commands/sessions-picker-factory.js +1 -1
  46. package/dist/commands/sessions-picker.d.ts +22 -0
  47. package/dist/commands/sessions-picker.js +48 -9
  48. package/dist/commands/sessions-stop.d.ts +24 -0
  49. package/dist/commands/sessions-stop.js +66 -0
  50. package/dist/commands/sessions-trace.d.ts +82 -0
  51. package/dist/commands/sessions-trace.js +387 -0
  52. package/dist/commands/sessions.js +5 -0
  53. package/dist/commands/setup-secrets.js +23 -0
  54. package/dist/commands/share.d.ts +20 -5
  55. package/dist/commands/share.js +152 -52
  56. package/dist/commands/ssh.d.ts +15 -0
  57. package/dist/commands/ssh.js +243 -18
  58. package/dist/commands/teams.js +34 -2
  59. package/dist/commands/traces.d.ts +2 -0
  60. package/dist/commands/traces.js +184 -0
  61. package/dist/commands/view.d.ts +2 -0
  62. package/dist/commands/view.js +32 -62
  63. package/dist/commands/watchdog.js +9 -14
  64. package/dist/index.d.ts +1 -0
  65. package/dist/index.js +5 -0
  66. package/dist/lib/account-capabilities.d.ts +4 -0
  67. package/dist/lib/account-capabilities.js +13 -9
  68. package/dist/lib/account-registry.d.ts +2 -0
  69. package/dist/lib/account-registry.js +30 -2
  70. package/dist/lib/accounting/rotate.d.ts +9 -0
  71. package/dist/lib/accounting/rotate.js +12 -2
  72. package/dist/lib/accounting/usage.d.ts +84 -6
  73. package/dist/lib/accounting/usage.js +293 -75
  74. package/dist/lib/agent-modes.js +29 -1
  75. package/dist/lib/agent-spec/agents.d.ts +4 -3
  76. package/dist/lib/agent-spec/agents.js +25 -15
  77. package/dist/lib/analytics/mix-commands.d.ts +1 -1
  78. package/dist/lib/analytics/mix-commands.js +2 -2
  79. package/dist/lib/auth-health.d.ts +13 -3
  80. package/dist/lib/auth-health.js +50 -8
  81. package/dist/lib/browser/devices.d.ts +19 -0
  82. package/dist/lib/browser/devices.js +23 -0
  83. package/dist/lib/browser/drivers/ssh.d.ts +16 -2
  84. package/dist/lib/browser/drivers/ssh.js +36 -9
  85. package/dist/lib/browser/ipc.d.ts +1 -1
  86. package/dist/lib/browser/ipc.js +40 -9
  87. package/dist/lib/browser/profiles.d.ts +104 -65
  88. package/dist/lib/browser/profiles.js +277 -165
  89. package/dist/lib/browser/registry.d.ts +39 -0
  90. package/dist/lib/browser/registry.js +149 -0
  91. package/dist/lib/browser/remote-control.d.ts +28 -2
  92. package/dist/lib/browser/remote-control.js +35 -3
  93. package/dist/lib/browser/resolve-target.d.ts +68 -0
  94. package/dist/lib/browser/resolve-target.js +250 -0
  95. package/dist/lib/browser/runtime-state.d.ts +44 -11
  96. package/dist/lib/browser/runtime-state.js +98 -15
  97. package/dist/lib/browser/service.d.ts +65 -9
  98. package/dist/lib/browser/service.js +196 -61
  99. package/dist/lib/browser/sessions-list.d.ts +1 -3
  100. package/dist/lib/browser/sessions-list.js +3 -16
  101. package/dist/lib/browser/task-index.d.ts +70 -0
  102. package/dist/lib/browser/task-index.js +180 -0
  103. package/dist/lib/browser/types.d.ts +12 -1
  104. package/dist/lib/byok-usage.js +2 -2
  105. package/dist/lib/claude-statusline.d.ts +29 -0
  106. package/dist/lib/claude-statusline.js +139 -0
  107. package/dist/lib/cloud/host.d.ts +1 -1
  108. package/dist/lib/cloud/host.js +1 -1
  109. package/dist/lib/cloud/rush.js +1 -1
  110. package/dist/lib/codex-policy.d.ts +11 -1
  111. package/dist/lib/codex-policy.js +20 -5
  112. package/dist/lib/computer/computer-rpc.js +2 -2
  113. package/dist/lib/computer/download.d.ts +15 -15
  114. package/dist/lib/computer/download.js +35 -98
  115. package/dist/lib/computer/ssh-tunnel.d.ts +0 -3
  116. package/dist/lib/computer/ssh-tunnel.js +12 -22
  117. package/dist/lib/config-keys.d.ts +6 -11
  118. package/dist/lib/config-keys.js +18 -19
  119. package/dist/lib/crabbox/cli.d.ts +1 -1
  120. package/dist/lib/crabbox/cli.js +2 -2
  121. package/dist/lib/crabbox/lease.d.ts +9 -0
  122. package/dist/lib/crabbox/lease.js +70 -15
  123. package/dist/lib/crabbox/runtimes.js +1 -1
  124. package/dist/lib/daemon/account-state-daemon-service.d.ts +16 -0
  125. package/dist/lib/daemon/account-state-daemon-service.js +26 -0
  126. package/dist/lib/daemon/browser-ipc-service.d.ts +20 -0
  127. package/dist/lib/daemon/browser-ipc-service.js +46 -0
  128. package/dist/lib/daemon/daemon.d.ts +3 -0
  129. package/dist/lib/daemon/daemon.js +212 -444
  130. package/dist/lib/daemon/device-probe-service.d.ts +26 -0
  131. package/dist/lib/daemon/device-probe-service.js +47 -0
  132. package/dist/lib/daemon/keychain-reap-service.d.ts +17 -0
  133. package/dist/lib/daemon/keychain-reap-service.js +32 -0
  134. package/dist/lib/daemon/monitor-engine-service.d.ts +22 -0
  135. package/dist/lib/daemon/monitor-engine-service.js +29 -0
  136. package/dist/lib/daemon/runner.js +15 -2
  137. package/dist/lib/daemon/secrets-broker-service.d.ts +20 -0
  138. package/dist/lib/daemon/secrets-broker-service.js +66 -0
  139. package/dist/lib/daemon/self-heal-service.d.ts +27 -0
  140. package/dist/lib/daemon/self-heal-service.js +48 -0
  141. package/dist/lib/daemon/service.d.ts +102 -0
  142. package/dist/lib/daemon/service.js +98 -0
  143. package/dist/lib/daemon/session-index-service.d.ts +22 -0
  144. package/dist/lib/daemon/session-index-service.js +40 -0
  145. package/dist/lib/daemon/state-dir-check-service.d.ts +43 -0
  146. package/dist/lib/daemon/state-dir-check-service.js +63 -0
  147. package/dist/lib/daemon/supervisor.d.ts +87 -0
  148. package/dist/lib/daemon/supervisor.js +298 -0
  149. package/dist/lib/daemon/watchdog-service.d.ts +19 -0
  150. package/dist/lib/daemon/watchdog-service.js +40 -0
  151. package/dist/lib/daemon-health.d.ts +15 -0
  152. package/dist/lib/daemon-health.js +29 -5
  153. package/dist/lib/daemon-services.d.ts +8 -1
  154. package/dist/lib/daemon-services.js +55 -0
  155. package/dist/lib/daemon-ticks.d.ts +13 -2
  156. package/dist/lib/daemon-ticks.js +22 -20
  157. package/dist/lib/device-config.d.ts +25 -10
  158. package/dist/lib/device-config.js +90 -39
  159. package/dist/lib/devices/config-migration.d.ts +7 -0
  160. package/dist/lib/devices/config-migration.js +67 -3
  161. package/dist/lib/devices/health.d.ts +27 -2
  162. package/dist/lib/devices/health.js +39 -9
  163. package/dist/lib/devices/interactive-host.d.ts +15 -0
  164. package/dist/lib/devices/interactive-host.js +53 -0
  165. package/dist/lib/devices/registry.d.ts +61 -4
  166. package/dist/lib/devices/registry.js +94 -38
  167. package/dist/lib/devices/stats-cache.d.ts +26 -0
  168. package/dist/lib/devices/stats-cache.js +59 -7
  169. package/dist/lib/devices/worker-pick.d.ts +48 -0
  170. package/dist/lib/devices/worker-pick.js +113 -0
  171. package/dist/lib/exec.d.ts +70 -14
  172. package/dist/lib/exec.js +110 -38
  173. package/dist/lib/feed/answer.d.ts +29 -0
  174. package/dist/lib/feed/answer.js +145 -0
  175. package/dist/lib/feed/attention.d.ts +83 -0
  176. package/dist/lib/feed/attention.js +0 -0
  177. package/dist/lib/feed/feed.d.ts +109 -0
  178. package/dist/lib/feed/feed.js +154 -3
  179. package/dist/lib/feed/pr-status.d.ts +14 -0
  180. package/dist/lib/feed/pr-status.js +47 -0
  181. package/dist/lib/feed/watch.d.ts +59 -0
  182. package/dist/lib/feed/watch.js +180 -0
  183. package/dist/lib/fleet/capture.js +6 -0
  184. package/dist/lib/fleet/remote-login.js +8 -3
  185. package/dist/lib/fleet/types.d.ts +17 -0
  186. package/dist/lib/harness/adapter.d.ts +11 -0
  187. package/dist/lib/harness/adapters/claude.js +38 -24
  188. package/dist/lib/harness/adapters/codex.js +2 -4
  189. package/dist/lib/harness/adapters/cursor.js +8 -11
  190. package/dist/lib/helper-download.d.ts +108 -0
  191. package/dist/lib/helper-download.js +194 -0
  192. package/dist/lib/helper-versions.d.ts +52 -0
  193. package/dist/lib/helper-versions.js +58 -0
  194. package/dist/lib/hooks/cache.js +19 -0
  195. package/dist/lib/hooks/install.js +2 -2
  196. package/dist/lib/hooks/match.d.ts +3 -0
  197. package/dist/lib/hooks/match.js +25 -0
  198. package/dist/lib/hosts/credentials.d.ts +1 -1
  199. package/dist/lib/hosts/credentials.js +1 -1
  200. package/dist/lib/hosts/dispatch.d.ts +7 -1
  201. package/dist/lib/hosts/dispatch.js +24 -5
  202. package/dist/lib/hosts/passthrough.d.ts +8 -15
  203. package/dist/lib/hosts/passthrough.js +35 -16
  204. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  205. package/dist/lib/hosts/providers/devices.js +1 -1
  206. package/dist/lib/hosts/reconnect.d.ts +179 -21
  207. package/dist/lib/hosts/reconnect.js +266 -45
  208. package/dist/lib/hosts/registry.js +7 -0
  209. package/dist/lib/installations/migrate.d.ts +4 -5
  210. package/dist/lib/installations/migrate.js +6 -7
  211. package/dist/lib/installations/shims.d.ts +1 -1
  212. package/dist/lib/installations/shims.js +23 -13
  213. package/dist/lib/installations/versions.js +25 -2
  214. package/dist/lib/linear-autoclose.d.ts +1 -1
  215. package/dist/lib/linear-autoclose.js +1 -1
  216. package/dist/lib/loop.d.ts +2 -2
  217. package/dist/lib/loop.js +1 -1
  218. package/dist/lib/menubar/download-menubar.d.ts +47 -0
  219. package/dist/lib/menubar/download-menubar.js +60 -0
  220. package/dist/lib/menubar/install-menubar.d.ts +44 -7
  221. package/dist/lib/menubar/install-menubar.js +105 -23
  222. package/dist/lib/menubar/notify-desktop.d.ts +3 -3
  223. package/dist/lib/menubar/notify-desktop.js +6 -6
  224. package/dist/lib/model-tiers.d.ts +1 -1
  225. package/dist/lib/open-url.d.ts +60 -2
  226. package/dist/lib/open-url.js +167 -12
  227. package/dist/lib/project-probe.d.ts +1 -1
  228. package/dist/lib/project-probe.js +1 -1
  229. package/dist/lib/project-pull.d.ts +1 -1
  230. package/dist/lib/project-pull.js +2 -2
  231. package/dist/lib/projects.d.ts +1 -1
  232. package/dist/lib/projects.js +1 -1
  233. package/dist/lib/refresh-coordinator.d.ts +1 -1
  234. package/dist/lib/refresh-coordinator.js +1 -1
  235. package/dist/lib/sandbox.js +6 -7
  236. package/dist/lib/secrets/download-keychain.d.ts +47 -0
  237. package/dist/lib/secrets/download-keychain.js +70 -0
  238. package/dist/lib/secrets/install-helper.d.ts +20 -1
  239. package/dist/lib/secrets/install-helper.js +44 -3
  240. package/dist/lib/session/active.d.ts +67 -0
  241. package/dist/lib/session/active.js +86 -2
  242. package/dist/lib/session/db.d.ts +11 -1
  243. package/dist/lib/session/db.js +142 -8
  244. package/dist/lib/session/discover.d.ts +23 -1
  245. package/dist/lib/session/discover.js +44 -10
  246. package/dist/lib/session/highlights.d.ts +49 -1
  247. package/dist/lib/session/highlights.js +95 -0
  248. package/dist/lib/session/host-link.d.ts +16 -2
  249. package/dist/lib/session/host-link.js +7 -1
  250. package/dist/lib/session/parse.js +33 -1
  251. package/dist/lib/session/prompt.d.ts +35 -0
  252. package/dist/lib/session/prompt.js +56 -0
  253. package/dist/lib/session/remote/remote-list.d.ts +9 -0
  254. package/dist/lib/session/remote/remote-list.js +19 -2
  255. package/dist/lib/session/remote/watch.d.ts +1 -1
  256. package/dist/lib/session/remote/watch.js +17 -3
  257. package/dist/lib/session/render.js +7 -3
  258. package/dist/lib/session/session-cache.d.ts +53 -0
  259. package/dist/lib/session/session-cache.js +93 -1
  260. package/dist/lib/session/state.js +1 -1
  261. package/dist/lib/session/tool-calls.d.ts +2 -0
  262. package/dist/lib/session/tool-calls.js +1 -1
  263. package/dist/lib/session/trajectory-compare.d.ts +47 -0
  264. package/dist/lib/session/trajectory-compare.js +116 -0
  265. package/dist/lib/session/trajectory-html.d.ts +19 -0
  266. package/dist/lib/session/trajectory-html.js +770 -0
  267. package/dist/lib/session/trajectory-lineage.d.ts +92 -0
  268. package/dist/lib/session/trajectory-lineage.js +195 -0
  269. package/dist/lib/session/trajectory-text.d.ts +37 -0
  270. package/dist/lib/session/trajectory-text.js +284 -0
  271. package/dist/lib/session/trajectory.d.ts +102 -0
  272. package/dist/lib/session/trajectory.js +384 -0
  273. package/dist/lib/session/types.d.ts +15 -0
  274. package/dist/lib/sha256-asset.d.ts +26 -0
  275. package/dist/lib/sha256-asset.js +41 -0
  276. package/dist/lib/share/backend.d.ts +95 -0
  277. package/dist/lib/share/backend.js +139 -0
  278. package/dist/lib/share/delete.d.ts +6 -2
  279. package/dist/lib/share/delete.js +8 -9
  280. package/dist/lib/share/html.d.ts +22 -0
  281. package/dist/lib/share/html.js +88 -0
  282. package/dist/lib/share/provision.d.ts +18 -4
  283. package/dist/lib/share/provision.js +38 -4
  284. package/dist/lib/share/publish.d.ts +39 -15
  285. package/dist/lib/share/publish.js +55 -26
  286. package/dist/lib/share/worker-template.js +171 -11
  287. package/dist/lib/sqlite.js +16 -3
  288. package/dist/lib/ssh-exec.d.ts +65 -0
  289. package/dist/lib/ssh-exec.js +120 -4
  290. package/dist/lib/startup/command-registry.d.ts +3 -1
  291. package/dist/lib/startup/command-registry.js +6 -3
  292. package/dist/lib/startup/dev-build.js +3 -3
  293. package/dist/lib/state.d.ts +2 -2
  294. package/dist/lib/state.js +11 -5
  295. package/dist/lib/subagents-registry.js +1 -1
  296. package/dist/lib/teams/agents.js +9 -0
  297. package/dist/lib/terminal/index.d.ts +1 -1
  298. package/dist/lib/terminal/inject.d.ts +19 -0
  299. package/dist/lib/terminal/inject.js +19 -9
  300. package/dist/lib/terminal/types.d.ts +1 -1
  301. package/dist/lib/terminal/types.js +1 -1
  302. package/dist/lib/tmux/orphan-reap.js +1 -1
  303. package/dist/lib/tmux/session.d.ts +46 -13
  304. package/dist/lib/tmux/session.js +204 -27
  305. package/dist/lib/traces/backend.d.ts +29 -0
  306. package/dist/lib/traces/backend.js +46 -0
  307. package/dist/lib/traces/classify.d.ts +52 -0
  308. package/dist/lib/traces/classify.js +72 -0
  309. package/dist/lib/traces/config.d.ts +10 -0
  310. package/dist/lib/traces/config.js +2 -0
  311. package/dist/lib/traces/provision.d.ts +19 -0
  312. package/dist/lib/traces/provision.js +30 -0
  313. package/dist/lib/traces/sync.d.ts +150 -0
  314. package/dist/lib/traces/sync.js +447 -0
  315. package/dist/lib/traces/worker-template.d.ts +4 -0
  316. package/dist/lib/traces/worker-template.js +159 -0
  317. package/dist/lib/types.d.ts +34 -19
  318. package/dist/lib/types.js +14 -0
  319. package/dist/lib/usage-backoff.d.ts +2 -1
  320. package/dist/lib/usage-backoff.js +60 -19
  321. package/dist/lib/usage-refresh.d.ts +18 -4
  322. package/dist/lib/usage-refresh.js +68 -19
  323. package/dist/lib/watchdog/log.d.ts +1 -1
  324. package/dist/lib/watchdog/log.js +1 -1
  325. package/dist/lib/watchdog/runner.d.ts +36 -45
  326. package/dist/lib/watchdog/runner.js +150 -119
  327. package/dist/lib/watchdog/service.d.ts +0 -1
  328. package/dist/lib/watchdog/service.js +0 -1
  329. package/dist/lib/watchdog/watchdog-agent.d.ts +38 -0
  330. package/dist/lib/watchdog/watchdog-agent.js +59 -0
  331. package/dist/lib/watchdog/watchdog.d.ts +11 -2
  332. package/dist/lib/watchdog/watchdog.js +37 -104
  333. package/dist/lib/workflows.d.ts +1 -1
  334. package/package.json +5 -7
  335. package/dist/commands/usage.d.ts +0 -27
  336. package/dist/commands/usage.js +0 -96
  337. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  338. package/dist/lib/menubar/MenubarHelper.app/Contents/Info.plist +0 -24
  339. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  340. package/dist/lib/menubar/MenubarHelper.app/Contents/Resources/AppIcon.icns +0 -0
  341. package/dist/lib/menubar/MenubarHelper.app/Contents/_CodeSignature/CodeResources +0 -128
  342. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  343. package/dist/lib/secrets/Agents CLI.app/Contents/Info.plist +0 -24
  344. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  345. package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +0 -123
  346. package/dist/lib/secrets/Agents CLI.app/Contents/embedded.provisionprofile +0 -0
  347. package/dist/lib/usage-fleet.d.ts +0 -32
  348. package/dist/lib/usage-fleet.js +0 -125
@@ -1,8 +1,55 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import { execFileSync } from 'child_process';
4
- import { getProfileRuntimeDir, getBrowserRuntimeDir, listProfilesWithScope, getConfiguredDefaultProfileName, isProfileLaunchableHere, deleteProfile, DEFAULT_BROWSER_PROFILE_NAME, LEGACY_DEFAULT_BROWSER_PROFILE_NAME, } from './profiles.js';
4
+ import { getProfileRuntimeDir, getBrowserRuntimeDir, getEndpointPresets, listProfiles, getConfiguredDefaultProfileName, isProfileLaunchableHere, deleteProfile, DEFAULT_BROWSER_PROFILE_NAME, LEGACY_DEFAULT_BROWSER_PROFILE_NAME, } from './profiles.js';
5
5
  import { keyBelongsToProfile } from './types.js';
6
+ import { declaringDevices, profileKind } from './registry.js';
7
+ import { machineId } from '../machine-id.js';
8
+ /**
9
+ * Detect an identity-bearing profile whose stored endpoint is loopback, viewed
10
+ * from a machine that is NOT the declaring device.
11
+ *
12
+ * That is the original `comet-local` bug: five real logins on the declaring
13
+ * box, a bare logged-out chromium answering to the same name on a worker
14
+ * because `cdp://localhost:N` is evaluated on the machine running the command.
15
+ * The daemon now tunnels that shape (`resolve-target.ts`); doctor still flags
16
+ * it so a worker does not report a green local binary/port for someone else's
17
+ * browser. Kind comes from the registry (exactly one declaring device), never
18
+ * from a stored field.
19
+ */
20
+ export function identityLoopbackMismatch(profile) {
21
+ if (profileKind(profile.name) !== 'identity')
22
+ return { misfiled: false };
23
+ const declaringDevice = declaringDevices(profile.name)[0];
24
+ if (!declaringDevice || declaringDevice === machineId())
25
+ return { misfiled: false };
26
+ const presets = getEndpointPresets(profile);
27
+ const chosen = profile.defaultEndpoint && presets[profile.defaultEndpoint]
28
+ ? profile.defaultEndpoint
29
+ : Object.keys(presets)[0];
30
+ if (!chosen)
31
+ return { misfiled: false };
32
+ const target = presets[chosen].target;
33
+ if (!target.startsWith('cdp://'))
34
+ return { misfiled: false };
35
+ let host;
36
+ try {
37
+ host = new URL(target).hostname;
38
+ }
39
+ catch {
40
+ return { misfiled: false };
41
+ }
42
+ if (host !== 'localhost' && host !== '127.0.0.1' && host !== '::1' && host !== '[::1]') {
43
+ return { misfiled: false };
44
+ }
45
+ const here = machineId();
46
+ return {
47
+ misfiled: true,
48
+ why: `identity-bearing profile declared on ${declaringDevice}, but "${target}" is a loopback endpoint — ` +
49
+ `on ${here} that address is this device's own browser, not ${declaringDevice}'s. ` +
50
+ `Diagnose the real browser on ${declaringDevice}: agents browser profiles doctor ${profile.name}`,
51
+ };
52
+ }
6
53
  const PID_FILE = 'pid';
7
54
  const PORT_FILE = 'port';
8
55
  const COMMAND_FILE = 'command';
@@ -96,7 +143,7 @@ export function clearProfileRuntime(profileName) {
96
143
  }
97
144
  /**
98
145
  * Recursively remove the whole profile cache (chrome-data, tasks.json,
99
- * everything). Used by `profiles delete` so an old profile name doesn't
146
+ * everything). Used by `profiles remove` so an old profile name doesn't
100
147
  * leak its history into a freshly-recreated one.
101
148
  */
102
149
  export function removeProfileCache(profileName) {
@@ -298,8 +345,6 @@ export const PRUNE_REASON_TEXT = {
298
345
  * - **the auto-detected profile** (`auto-chrome`, or the `default` an older
299
346
  * build wrote) — auto-regenerated by `ensureDefaultBrowserProfile`, so
300
347
  * pruning it is pure churn.
301
- * - **fleet-synced** — deleting one removes it from EVERY machine, so it takes
302
- * the explicit `includeFleet` opt-in.
303
348
  *
304
349
  * Known limitation: `BrowserProfileConfig` records no creation time, so a
305
350
  * profile created seconds ago and not yet started is indistinguishable from an
@@ -308,10 +353,17 @@ export const PRUNE_REASON_TEXT = {
308
353
  */
309
354
  export function planProfilePrune(profiles, opts = {}) {
310
355
  const plan = { candidates: [], kept: [] };
311
- for (const { name, scope, launchableHere } of profiles) {
312
- const keep = (why) => { plan.kept.push({ name, scope, why }); };
313
- if (scope === 'fleet' && !opts.includeFleet) {
314
- keep('fleet-synced (pass --fleet to include it)');
356
+ for (const { name, scope, launchableHere, misfiledWhy } of profiles) {
357
+ const keep = (why, misfiled = false) => {
358
+ plan.kept.push(misfiled ? { name, scope, why, misfiled } : { name, scope, why });
359
+ };
360
+ // Checked FIRST. A misfiled identity profile's defining symptom is that the
361
+ // browser is absent on whatever box you are standing on — pruning it would
362
+ // delete the declaring device's entry (or throw, for a peer declaration).
363
+ // The repair is to declare it only on the machine that owns the browser;
364
+ // an intentional delete is still available as `profiles remove`.
365
+ if (misfiledWhy) {
366
+ keep(`MISFILED — ${misfiledWhy}`, true);
315
367
  continue;
316
368
  }
317
369
  if (name === DEFAULT_BROWSER_PROFILE_NAME || name === LEGACY_DEFAULT_BROWSER_PROFILE_NAME) {
@@ -343,13 +395,44 @@ export function planProfilePrune(profiles, opts = {}) {
343
395
  * Build the prune plan from live config. Split from {@link planProfilePrune} so
344
396
  * the decision rules stay unit-testable without a configured machine.
345
397
  */
346
- export async function buildProfilePrunePlan(opts = {}) {
347
- const scoped = await listProfilesWithScope();
348
- return planProfilePrune(scoped.map(({ profile, scope }) => ({
349
- name: profile.name,
350
- scope,
351
- launchableHere: isProfileLaunchableHere(profile),
352
- })), { includeFleet: opts.includeFleet, configuredDefault: getConfiguredDefaultProfileName() });
398
+ export async function buildProfilePrunePlan() {
399
+ const current = machineId();
400
+ const profiles = await listProfiles();
401
+ const declaredHere = [];
402
+ const peerKept = [];
403
+ for (const profile of profiles) {
404
+ const scope = profile.devices.length > 1 ? 'fungible' : 'identity';
405
+ const misfiled = identityLoopbackMismatch(profile);
406
+ if (profile.devices.includes(current)) {
407
+ declaredHere.push({
408
+ name: profile.name,
409
+ scope,
410
+ launchableHere: isProfileLaunchableHere(profile),
411
+ misfiledWhy: misfiled.misfiled ? misfiled.why : undefined,
412
+ });
413
+ continue;
414
+ }
415
+ if (misfiled.misfiled) {
416
+ peerKept.push({
417
+ name: profile.name,
418
+ scope,
419
+ why: `MISFILED — ${misfiled.why}`,
420
+ misfiled: true,
421
+ });
422
+ }
423
+ else {
424
+ peerKept.push({
425
+ name: profile.name,
426
+ scope,
427
+ why: `declared on ${profile.devices.join(', ')}, not this device`,
428
+ });
429
+ }
430
+ }
431
+ const plan = planProfilePrune(declaredHere, {
432
+ configuredDefault: getConfiguredDefaultProfileName(),
433
+ });
434
+ plan.kept.push(...peerKept);
435
+ return plan;
353
436
  }
354
437
  /**
355
438
  * Execute a prune plan: drop each candidate's config entry and wipe its cache
@@ -1,4 +1,5 @@
1
1
  import { CDPClient } from './cdp.js';
2
+ import { type DeviceProbe } from './resolve-target.js';
2
3
  import { type ResolvedDomainSkill } from './domain-skills.js';
3
4
  import { type Task, type TabInfo, type ProfileStatus, type BrowserType, type HistoricalTask, type ReapResult, type ProfileName, type ConnectionKey } from './types.js';
4
5
  import { type ReapOptions } from './hygiene.js';
@@ -136,7 +137,8 @@ export declare class BrowserService {
136
137
  * Live browsers, keyed by {@link ConnectionKey} — NOT by profile name. The
137
138
  * branded key type is what makes `connections.get(someProfileName)` (the
138
139
  * RUSH-2709 miss that made `status --profile <name>` return empty for a
139
- * running `<name>@endpoint-0`) fail to compile.
140
+ * running `<name>@<device>`) fail to compile. Keys are `<profile>@<device>`
141
+ * (legacy leftover `<profile>@endpoint-N` dirs are still recognized).
140
142
  */
141
143
  private connections;
142
144
  private forkingProfiles;
@@ -161,8 +163,12 @@ export declare class BrowserService {
161
163
  launchId?: string;
162
164
  /** Calling agent session, forwarded from the CLI (see IPCRequest.sessionId). */
163
165
  sessionId?: string;
166
+ /** Whether the CALLER was dispatched here by a fleet `--device` hop. */
167
+ fleetRemote?: boolean;
164
168
  /** Explicit human label (`--title`). */
165
169
  title?: string;
170
+ /** Injected reachability probe — production uses ssh; tests pass a fake. */
171
+ probe?: DeviceProbe;
166
172
  }): Promise<{
167
173
  task: string;
168
174
  name: string;
@@ -170,8 +176,12 @@ export declare class BrowserService {
170
176
  windowId?: string;
171
177
  /** BARE profile name — what the caller asked for, never the runtime key. */
172
178
  profile: ProfileName;
173
- /** Runtime key the task actually landed on (`<profile>@<endpoint>`). */
179
+ /** Runtime key the task actually landed on (`<profile>@<device>`). */
174
180
  key: ConnectionKey;
181
+ /** Device the daemon connected to. */
182
+ device: string;
183
+ /** Set when the daemon picked a remote declaring device. */
184
+ picked?: string;
175
185
  skill?: ResolvedDomainSkill;
176
186
  }>;
177
187
  /**
@@ -238,7 +248,7 @@ export declare class BrowserService {
238
248
  /**
239
249
  * Close tasks whose owning agent session is gone, or that have sat untouched
240
250
  * past the idle window. The entry point the daemon's periodic tick and
241
- * `agents browser gc` both call; the policy lives in `hygiene.ts`.
251
+ * `agents browser prune` both call; the policy lives in `hygiene.ts`.
242
252
  */
243
253
  reapAbandoned(opts?: ReapOptions): Promise<ReapResult>;
244
254
  stop(taskName: string): Promise<{
@@ -359,8 +369,9 @@ export declare class BrowserService {
359
369
  * `profileName` is a {@link ProfileName} — a BARE name, never a runtime key.
360
370
  * Every candidate is selected by the one rule ({@link keyBelongsToProfile}),
361
371
  * and a scoped query that finds no live connection falls through to disk, so
362
- * `status --profile comet-local` reports the LIVE `comet-local@endpoint-0`
363
- * instead of the empty list it used to return (RUSH-2709).
372
+ * `status --profile comet-local` reports the LIVE `comet-local@<device>`
373
+ * (and leftover `comet-local@endpoint-0` dirs) instead of the empty list
374
+ * it used to return (RUSH-2709).
364
375
  */
365
376
  status(profileRef?: ProfileName | ConnectionKey): Promise<ProfileStatus[]>;
366
377
  /**
@@ -436,10 +447,9 @@ export declare class BrowserService {
436
447
  * already resolved the endpoint and built the `effectiveProfile` with
437
448
  * the per-endpoint binary/targetFilter overrides applied; we just use it.
438
449
  *
439
- * `key` is the runtime key (`<profile>@<endpoint>`) and is what every on-disk
440
- * lookup uses, so per-endpoint pid/port files don't collide when the same app
441
- * runs locally and remotely at the same time. It is a SEPARATE argument
442
- * because `effectiveProfile.name` stays the bare, user-facing name (RUSH-2709).
450
+ * `key` is the runtime key (`<profile>@<device>`) and is what every on-disk
451
+ * lookup uses. It is a SEPARATE argument because `effectiveProfile.name`
452
+ * stays the bare, user-facing name (RUSH-2709).
443
453
  */
444
454
  private connectProfile;
445
455
  private connectEndpoint;
@@ -469,6 +479,8 @@ export declare class BrowserService {
469
479
  * - no handle, zero, !createIfMissing → return null (caller reports "nothing to close")
470
480
  */
471
481
  resolveOrCreateTask(opts: {
482
+ /** Whether the CALLER was dispatched here by a fleet `--device` hop. */
483
+ fleetRemote?: boolean;
472
484
  task?: string;
473
485
  profile?: string;
474
486
  actor?: string;
@@ -482,6 +494,8 @@ export declare class BrowserService {
482
494
  task: Task;
483
495
  key: ConnectionKey;
484
496
  created: boolean;
497
+ picked?: string;
498
+ device?: string;
485
499
  } | null>;
486
500
  private listTasksForCaller;
487
501
  private currentUrlHint;
@@ -536,6 +550,48 @@ export declare class BrowserService {
536
550
  private saveTaskState;
537
551
  private loadTaskState;
538
552
  private saveToHistory;
553
+ /**
554
+ * The cached connection for `key`, or undefined — evicting it first if the
555
+ * browser died underneath us.
556
+ *
557
+ * A browser killed externally (Cmd-Q, crash, a user clearing the profile by
558
+ * hand) leaves a closed WebSocket in the map. Without this the next
559
+ * `cdp.send` throws "CDP connection not open" and there is no recovery short
560
+ * of killing the daemon.
561
+ */
562
+ private reuseHealthyConnection;
563
+ /**
564
+ * Reuse a live connection for this profile: the new `<name>@<device>` key
565
+ * first, then any leftover `<name>@endpoint-N` key still in the map so a
566
+ * browser started before the key collapse is not abandoned.
567
+ */
568
+ private reuseProfileConnection;
569
+ /** Connect a profile at `target`, register it under `key`, and arm downloads. */
570
+ private openConnection;
571
+ /**
572
+ * Open a tab for a HUMAN to read, bound to no task.
573
+ *
574
+ * That is the entire difference from {@link start}, and it is the point. The
575
+ * abandoned-task reaper closes a task's tabs when the calling session dies or
576
+ * after the idle window, but it "deliberately never touches a tab that is not
577
+ * in `task.tabs`" (hygiene.ts) — so a viewer tab must not be in one, or the
578
+ * artifact the user is reading vanishes when the agent that rendered it exits.
579
+ *
580
+ * Consequently `stop`/`done` do not close it either, which is correct: it is
581
+ * the user's tab now.
582
+ */
583
+ showUrl(profileName: ProfileName, url: string, opts?: {
584
+ endpointName?: string;
585
+ fleetRemote?: boolean;
586
+ actor?: string;
587
+ probe?: DeviceProbe;
588
+ }): Promise<{
589
+ profile: ProfileName;
590
+ key: ConnectionKey;
591
+ tabId: string;
592
+ device: string;
593
+ picked?: string;
594
+ }>;
539
595
  getHistory(limit?: number): Promise<HistoricalTask[]>;
540
596
  }
541
597
  export {};