@phnx-labs/agents-cli 1.22.47 → 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 (249) hide show
  1. package/CHANGELOG.md +401 -17
  2. package/README.md +66 -32
  3. package/dist/bootstrap.js +4 -2
  4. package/dist/cli/command-registry.d.ts +1 -0
  5. package/dist/cli/command-registry.js +2 -0
  6. package/dist/commands/accounts.d.ts +58 -0
  7. package/dist/commands/accounts.js +206 -32
  8. package/dist/commands/artifacts.js +7 -6
  9. package/dist/commands/attach.js +1 -1
  10. package/dist/commands/browser.js +501 -103
  11. package/dist/commands/config.d.ts +0 -1
  12. package/dist/commands/config.js +0 -20
  13. package/dist/commands/daemon.d.ts +21 -0
  14. package/dist/commands/daemon.js +147 -12
  15. package/dist/commands/exec.js +52 -15
  16. package/dist/commands/focus.d.ts +14 -0
  17. package/dist/commands/focus.js +48 -5
  18. package/dist/commands/go.d.ts +3 -0
  19. package/dist/commands/go.js +16 -3
  20. package/dist/commands/inspect.js +2 -2
  21. package/dist/commands/lease.d.ts +1 -1
  22. package/dist/commands/lease.js +4 -3
  23. package/dist/commands/mailboxes.js +4 -3
  24. package/dist/commands/menubar.js +11 -4
  25. package/dist/commands/projects.d.ts +16 -1
  26. package/dist/commands/projects.js +58 -64
  27. package/dist/commands/resume.js +1 -1
  28. package/dist/commands/route.js +4 -4
  29. package/dist/commands/routines.js +3 -2
  30. package/dist/commands/run-broadcast.d.ts +1 -1
  31. package/dist/commands/run-broadcast.js +1 -1
  32. package/dist/commands/sessions-picker.d.ts +22 -0
  33. package/dist/commands/sessions-picker.js +48 -9
  34. package/dist/commands/sessions-trace.js +1 -1
  35. package/dist/commands/sessions.js +1 -0
  36. package/dist/commands/setup-secrets.js +23 -0
  37. package/dist/commands/share.d.ts +20 -5
  38. package/dist/commands/share.js +152 -52
  39. package/dist/commands/ssh.js +54 -7
  40. package/dist/commands/traces.d.ts +2 -0
  41. package/dist/commands/traces.js +184 -0
  42. package/dist/commands/view.d.ts +1 -1
  43. package/dist/commands/view.js +17 -34
  44. package/dist/index.d.ts +1 -0
  45. package/dist/index.js +5 -0
  46. package/dist/lib/accounting/usage.d.ts +14 -3
  47. package/dist/lib/accounting/usage.js +64 -18
  48. package/dist/lib/agent-spec/agents.js +11 -9
  49. package/dist/lib/browser/drivers/ssh.d.ts +16 -2
  50. package/dist/lib/browser/drivers/ssh.js +36 -9
  51. package/dist/lib/browser/ipc.js +8 -3
  52. package/dist/lib/browser/profiles.d.ts +35 -101
  53. package/dist/lib/browser/profiles.js +130 -301
  54. package/dist/lib/browser/registry.d.ts +39 -0
  55. package/dist/lib/browser/registry.js +149 -0
  56. package/dist/lib/browser/remote-control.d.ts +8 -6
  57. package/dist/lib/browser/remote-control.js +8 -6
  58. package/dist/lib/browser/resolve-target.d.ts +68 -0
  59. package/dist/lib/browser/resolve-target.js +250 -0
  60. package/dist/lib/browser/runtime-state.d.ts +40 -16
  61. package/dist/lib/browser/runtime-state.js +92 -25
  62. package/dist/lib/browser/service.d.ts +28 -9
  63. package/dist/lib/browser/service.js +139 -62
  64. package/dist/lib/browser/task-index.d.ts +70 -0
  65. package/dist/lib/browser/task-index.js +180 -0
  66. package/dist/lib/byok-usage.js +2 -2
  67. package/dist/lib/claude-statusline.d.ts +29 -0
  68. package/dist/lib/claude-statusline.js +139 -0
  69. package/dist/lib/cloud/host.d.ts +1 -1
  70. package/dist/lib/cloud/host.js +1 -1
  71. package/dist/lib/cloud/rush.js +1 -1
  72. package/dist/lib/computer/computer-rpc.js +2 -2
  73. package/dist/lib/computer/download.d.ts +15 -15
  74. package/dist/lib/computer/download.js +35 -98
  75. package/dist/lib/computer/ssh-tunnel.d.ts +0 -3
  76. package/dist/lib/computer/ssh-tunnel.js +12 -22
  77. package/dist/lib/config-keys.d.ts +2 -8
  78. package/dist/lib/config-keys.js +2 -13
  79. package/dist/lib/crabbox/cli.d.ts +1 -1
  80. package/dist/lib/crabbox/cli.js +2 -2
  81. package/dist/lib/crabbox/lease.d.ts +9 -0
  82. package/dist/lib/crabbox/lease.js +70 -15
  83. package/dist/lib/crabbox/runtimes.js +1 -1
  84. package/dist/lib/daemon/account-state-daemon-service.d.ts +16 -0
  85. package/dist/lib/daemon/account-state-daemon-service.js +26 -0
  86. package/dist/lib/daemon/browser-ipc-service.d.ts +20 -0
  87. package/dist/lib/daemon/browser-ipc-service.js +46 -0
  88. package/dist/lib/daemon/daemon.d.ts +3 -0
  89. package/dist/lib/daemon/daemon.js +212 -444
  90. package/dist/lib/daemon/device-probe-service.d.ts +26 -0
  91. package/dist/lib/daemon/device-probe-service.js +47 -0
  92. package/dist/lib/daemon/keychain-reap-service.d.ts +17 -0
  93. package/dist/lib/daemon/keychain-reap-service.js +32 -0
  94. package/dist/lib/daemon/monitor-engine-service.d.ts +22 -0
  95. package/dist/lib/daemon/monitor-engine-service.js +29 -0
  96. package/dist/lib/daemon/secrets-broker-service.d.ts +20 -0
  97. package/dist/lib/daemon/secrets-broker-service.js +66 -0
  98. package/dist/lib/daemon/self-heal-service.d.ts +27 -0
  99. package/dist/lib/daemon/self-heal-service.js +48 -0
  100. package/dist/lib/daemon/service.d.ts +102 -0
  101. package/dist/lib/daemon/service.js +98 -0
  102. package/dist/lib/daemon/session-index-service.d.ts +22 -0
  103. package/dist/lib/daemon/session-index-service.js +40 -0
  104. package/dist/lib/daemon/state-dir-check-service.d.ts +43 -0
  105. package/dist/lib/daemon/state-dir-check-service.js +63 -0
  106. package/dist/lib/daemon/supervisor.d.ts +87 -0
  107. package/dist/lib/daemon/supervisor.js +298 -0
  108. package/dist/lib/daemon/watchdog-service.d.ts +19 -0
  109. package/dist/lib/daemon/watchdog-service.js +40 -0
  110. package/dist/lib/daemon-health.d.ts +15 -0
  111. package/dist/lib/daemon-health.js +29 -5
  112. package/dist/lib/daemon-services.d.ts +8 -1
  113. package/dist/lib/daemon-services.js +55 -0
  114. package/dist/lib/daemon-ticks.d.ts +13 -2
  115. package/dist/lib/daemon-ticks.js +20 -18
  116. package/dist/lib/device-config.d.ts +0 -2
  117. package/dist/lib/device-config.js +1 -23
  118. package/dist/lib/devices/registry.d.ts +1 -1
  119. package/dist/lib/devices/registry.js +1 -1
  120. package/dist/lib/devices/stats-cache.d.ts +20 -0
  121. package/dist/lib/devices/stats-cache.js +49 -5
  122. package/dist/lib/devices/worker-pick.d.ts +48 -0
  123. package/dist/lib/devices/worker-pick.js +113 -0
  124. package/dist/lib/exec.d.ts +67 -13
  125. package/dist/lib/exec.js +85 -29
  126. package/dist/lib/harness/adapters/cursor.js +8 -11
  127. package/dist/lib/helper-download.d.ts +108 -0
  128. package/dist/lib/helper-download.js +194 -0
  129. package/dist/lib/helper-versions.d.ts +52 -0
  130. package/dist/lib/helper-versions.js +58 -0
  131. package/dist/lib/hooks/cache.js +11 -0
  132. package/dist/lib/hooks/install.js +2 -2
  133. package/dist/lib/hosts/credentials.d.ts +1 -1
  134. package/dist/lib/hosts/credentials.js +1 -1
  135. package/dist/lib/hosts/dispatch.d.ts +7 -1
  136. package/dist/lib/hosts/dispatch.js +24 -5
  137. package/dist/lib/hosts/passthrough.d.ts +8 -15
  138. package/dist/lib/hosts/passthrough.js +19 -16
  139. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  140. package/dist/lib/hosts/providers/devices.js +1 -1
  141. package/dist/lib/hosts/reconnect.d.ts +179 -21
  142. package/dist/lib/hosts/reconnect.js +266 -45
  143. package/dist/lib/installations/migrate.d.ts +4 -5
  144. package/dist/lib/installations/migrate.js +6 -7
  145. package/dist/lib/installations/shims.d.ts +1 -1
  146. package/dist/lib/installations/shims.js +23 -13
  147. package/dist/lib/installations/versions.js +25 -2
  148. package/dist/lib/linear-autoclose.d.ts +1 -1
  149. package/dist/lib/linear-autoclose.js +1 -1
  150. package/dist/lib/loop.d.ts +2 -2
  151. package/dist/lib/loop.js +1 -1
  152. package/dist/lib/menubar/download-menubar.d.ts +47 -0
  153. package/dist/lib/menubar/download-menubar.js +60 -0
  154. package/dist/lib/menubar/install-menubar.d.ts +31 -7
  155. package/dist/lib/menubar/install-menubar.js +79 -21
  156. package/dist/lib/menubar/notify-desktop.d.ts +3 -3
  157. package/dist/lib/menubar/notify-desktop.js +6 -6
  158. package/dist/lib/model-tiers.d.ts +1 -1
  159. package/dist/lib/project-probe.d.ts +1 -1
  160. package/dist/lib/project-probe.js +1 -1
  161. package/dist/lib/project-pull.d.ts +1 -1
  162. package/dist/lib/project-pull.js +2 -2
  163. package/dist/lib/projects.d.ts +1 -1
  164. package/dist/lib/projects.js +1 -1
  165. package/dist/lib/sandbox.js +6 -7
  166. package/dist/lib/secrets/download-keychain.d.ts +47 -0
  167. package/dist/lib/secrets/download-keychain.js +70 -0
  168. package/dist/lib/secrets/install-helper.d.ts +20 -1
  169. package/dist/lib/secrets/install-helper.js +44 -3
  170. package/dist/lib/session/active.js +17 -1
  171. package/dist/lib/session/db.d.ts +11 -1
  172. package/dist/lib/session/db.js +138 -6
  173. package/dist/lib/session/discover.d.ts +21 -1
  174. package/dist/lib/session/discover.js +33 -5
  175. package/dist/lib/session/highlights.d.ts +49 -1
  176. package/dist/lib/session/highlights.js +95 -0
  177. package/dist/lib/session/host-link.d.ts +16 -2
  178. package/dist/lib/session/host-link.js +7 -1
  179. package/dist/lib/session/parse.js +33 -1
  180. package/dist/lib/session/remote/remote-list.d.ts +9 -0
  181. package/dist/lib/session/remote/remote-list.js +19 -2
  182. package/dist/lib/session/remote/watch.js +11 -2
  183. package/dist/lib/session/session-cache.d.ts +53 -0
  184. package/dist/lib/session/session-cache.js +88 -0
  185. package/dist/lib/session/state.js +1 -1
  186. package/dist/lib/session/tool-calls.d.ts +2 -0
  187. package/dist/lib/session/tool-calls.js +1 -1
  188. package/dist/lib/session/trajectory-html.d.ts +5 -1
  189. package/dist/lib/session/trajectory-html.js +42 -22
  190. package/dist/lib/session/trajectory-text.js +9 -2
  191. package/dist/lib/session/trajectory.js +53 -4
  192. package/dist/lib/session/types.d.ts +15 -0
  193. package/dist/lib/sha256-asset.d.ts +26 -0
  194. package/dist/lib/sha256-asset.js +41 -0
  195. package/dist/lib/share/backend.d.ts +95 -0
  196. package/dist/lib/share/backend.js +139 -0
  197. package/dist/lib/share/delete.d.ts +6 -2
  198. package/dist/lib/share/delete.js +8 -9
  199. package/dist/lib/share/html.d.ts +22 -0
  200. package/dist/lib/share/html.js +88 -0
  201. package/dist/lib/share/provision.d.ts +18 -4
  202. package/dist/lib/share/provision.js +38 -4
  203. package/dist/lib/share/publish.d.ts +39 -15
  204. package/dist/lib/share/publish.js +55 -26
  205. package/dist/lib/share/worker-template.js +171 -11
  206. package/dist/lib/sqlite.js +16 -3
  207. package/dist/lib/ssh-exec.d.ts +65 -0
  208. package/dist/lib/ssh-exec.js +120 -4
  209. package/dist/lib/startup/command-registry.js +1 -1
  210. package/dist/lib/startup/dev-build.js +3 -3
  211. package/dist/lib/state.d.ts +1 -1
  212. package/dist/lib/state.js +7 -3
  213. package/dist/lib/subagents-registry.js +1 -1
  214. package/dist/lib/terminal/index.d.ts +1 -1
  215. package/dist/lib/terminal/types.d.ts +1 -1
  216. package/dist/lib/terminal/types.js +1 -1
  217. package/dist/lib/tmux/orphan-reap.js +1 -1
  218. package/dist/lib/tmux/session.js +31 -0
  219. package/dist/lib/traces/backend.d.ts +29 -0
  220. package/dist/lib/traces/backend.js +46 -0
  221. package/dist/lib/traces/classify.d.ts +52 -0
  222. package/dist/lib/traces/classify.js +72 -0
  223. package/dist/lib/traces/config.d.ts +10 -0
  224. package/dist/lib/traces/config.js +2 -0
  225. package/dist/lib/traces/provision.d.ts +19 -0
  226. package/dist/lib/traces/provision.js +30 -0
  227. package/dist/lib/traces/sync.d.ts +150 -0
  228. package/dist/lib/traces/sync.js +447 -0
  229. package/dist/lib/traces/worker-template.d.ts +4 -0
  230. package/dist/lib/traces/worker-template.js +159 -0
  231. package/dist/lib/types.d.ts +18 -19
  232. package/dist/lib/types.js +14 -0
  233. package/dist/lib/usage-refresh.d.ts +1 -1
  234. package/dist/lib/usage-refresh.js +11 -8
  235. package/dist/lib/workflows.d.ts +1 -1
  236. package/package.json +4 -6
  237. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  238. package/dist/lib/menubar/MenubarHelper.app/Contents/Info.plist +0 -24
  239. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  240. package/dist/lib/menubar/MenubarHelper.app/Contents/Resources/AppIcon.icns +0 -0
  241. package/dist/lib/menubar/MenubarHelper.app/Contents/_CodeSignature/CodeResources +0 -128
  242. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  243. package/dist/lib/secrets/Agents CLI.app/Contents/Info.plist +0 -26
  244. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  245. package/dist/lib/secrets/Agents CLI.app/Contents/Resources/AppIcon.icns +0 -0
  246. package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +0 -135
  247. package/dist/lib/secrets/Agents CLI.app/Contents/embedded.provisionprofile +0 -0
  248. package/dist/lib/usage-fleet.d.ts +0 -32
  249. package/dist/lib/usage-fleet.js +0 -125
@@ -16,13 +16,27 @@ export interface SSHConnection {
16
16
  * strings differ (no `&` backgrounding, no `lsof`, `.exe` instead of `.app`).
17
17
  */
18
18
  export type RemoteOs = 'windows' | 'posix';
19
+ export interface SSHConnectOptions {
20
+ /**
21
+ * Attach to a browser another device already declared (identity-bearing or
22
+ * a fungible name we don't declare here). Do not launch a fresh remote
23
+ * chrome-data, and do not kill that browser when the tunnel closes — it
24
+ * holds the logins the caller is trying to reach.
25
+ */
26
+ persistRemote?: boolean;
27
+ }
28
+ /** Lifecycle for a registry-driven tunnel vs a profile the daemon launched. */
29
+ export declare function persistRemoteLifecycle(persistRemote: boolean): {
30
+ launchRemote: boolean;
31
+ killOnCleanup: boolean;
32
+ };
19
33
  export declare function connectSSH(endpoint: string, profile: BrowserProfile,
20
34
  /**
21
- * Runtime key (`<profile>@<endpoint>`) this connection is stored under. It
35
+ * Runtime key (`<profile>@<device>`) this connection is stored under. It
22
36
  * keys the tunnel's runtime record; `profile.name` is the bare, user-facing
23
37
  * name and appears only in messages (RUSH-2709).
24
38
  */
25
- key: ConnectionKey): Promise<SSHConnection>;
39
+ key: ConnectionKey, opts?: SSHConnectOptions): Promise<SSHConnection>;
26
40
  /**
27
41
  * Wrap a PowerShell script as a `-EncodedCommand` invocation. Base64 of the
28
42
  * UTF-16LE bytes is a single quote-free token, so it rides through Node spawn
@@ -13,13 +13,19 @@ export { shellQuote };
13
13
  // driver's original foreground, stderr-captured behavior exactly.
14
14
  import { startSSHTunnel } from '../../computer/ssh-tunnel.js';
15
15
  import { encodePwshBase64 } from '../../pwsh.js';
16
+ /** Lifecycle for a registry-driven tunnel vs a profile the daemon launched. */
17
+ export function persistRemoteLifecycle(persistRemote) {
18
+ return persistRemote
19
+ ? { launchRemote: false, killOnCleanup: false }
20
+ : { launchRemote: true, killOnCleanup: true };
21
+ }
16
22
  export async function connectSSH(endpoint, profile,
17
23
  /**
18
- * Runtime key (`<profile>@<endpoint>`) this connection is stored under. It
24
+ * Runtime key (`<profile>@<device>`) this connection is stored under. It
19
25
  * keys the tunnel's runtime record; `profile.name` is the bare, user-facing
20
26
  * name and appears only in messages (RUSH-2709).
21
27
  */
22
- key) {
28
+ key, opts = {}) {
23
29
  const url = new URL(endpoint);
24
30
  if (url.protocol !== 'ssh:') {
25
31
  throw new Error(`Invalid SSH endpoint: ${endpoint}`);
@@ -59,7 +65,14 @@ key) {
59
65
  // (the launch backgrounds/WMI-spawns regardless), so this does not spuriously
60
66
  // fail the reconnect path — only genuine launch failures reach the caller
61
67
  // instead of being swallowed and mis-reported later as a tunnel timeout.
62
- await ensureRemoteBrowser(user, host, profile.browser, remotePort, remoteOs, profile.binary);
68
+ //
69
+ // persistRemote skips the launch: launching would mint a logged-out
70
+ // `--user-data-dir=/tmp/agents-browser-N` under a name that means a
71
+ // credentialed browser on the declaring device.
72
+ const lifecycle = persistRemoteLifecycle(Boolean(opts.persistRemote));
73
+ if (lifecycle.launchRemote) {
74
+ await ensureRemoteBrowser(user, host, profile.browser, remotePort, remoteOs, profile.binary);
75
+ }
63
76
  let tunnel;
64
77
  if (occupant) {
65
78
  // Reuse the existing tunnel rather than spawning a duplicate.
@@ -78,7 +91,19 @@ key) {
78
91
  tunnel.kill();
79
92
  throw new Error(`SSH tunnel failed to establish to ${host}`);
80
93
  }
81
- const { wsUrl, browser } = await discoverBrowserWsUrl(localPort, 'localhost', profile.name);
94
+ let wsUrl;
95
+ let browser;
96
+ try {
97
+ ({ wsUrl, browser } = await discoverBrowserWsUrl(localPort, 'localhost', profile.name));
98
+ }
99
+ catch (err) {
100
+ tunnel.kill();
101
+ if (opts.persistRemote) {
102
+ const why = err instanceof Error ? err.message : String(err);
103
+ throw new Error(`Browser profile "${profile.name}" is declared on ${host}, but nothing is speaking CDP on port ${remotePort}: ${why}`);
104
+ }
105
+ throw err;
106
+ }
82
107
  try {
83
108
  verifyBrowserIdentity(browser, profile.browser, remotePort, host);
84
109
  }
@@ -108,11 +133,13 @@ key) {
108
133
  pid: tunnelPid,
109
134
  cleanup: () => {
110
135
  cdp.close();
111
- // Kill the remote browser BEFORE tearing down the tunnel. It runs on a
112
- // separate ssh connection (independent of the tunnel we're about to
113
- // kill), so tunnel teardown can't cut it off. Fire-and-forget cleanup
114
- // stays synchronous, and killRemoteBrowser never rejects.
115
- killRemoteBrowser(user, host, remoteOs, remotePort).catch(() => { });
136
+ // Kill the remote browser BEFORE tearing down the tunnel but only
137
+ // when we launched it. persistRemote is an attach to someone else's
138
+ // declared browser; killing it would drop the logins the caller came
139
+ // for. Fire-and-forget cleanup stays synchronous.
140
+ if (lifecycle.killOnCleanup) {
141
+ killRemoteBrowser(user, host, remoteOs, remotePort).catch(() => { });
142
+ }
116
143
  tunnel.kill();
117
144
  clearProfileRuntime(key);
118
145
  },
@@ -398,6 +398,9 @@ export class BrowserIPCServer {
398
398
  };
399
399
  }
400
400
  request.task = resolved.task.name;
401
+ if (resolved.created && resolved.picked) {
402
+ request.picked = resolved.picked;
403
+ }
401
404
  return undefined;
402
405
  }
403
406
  catch (err) {
@@ -437,7 +440,7 @@ export class BrowserIPCServer {
437
440
  fleetRemote: request.fleetRemote,
438
441
  actor: request.actor,
439
442
  });
440
- return { ok: true, tabId: shown.tabId };
443
+ return { ok: true, tabId: shown.tabId, message: shown.picked };
441
444
  }
442
445
  case 'start': {
443
446
  if (!request.profile) {
@@ -461,10 +464,11 @@ export class BrowserIPCServer {
461
464
  tabId: result.tabId,
462
465
  windowTargetId: result.windowId,
463
466
  skill: result.skill,
467
+ message: result.picked,
464
468
  };
465
469
  }
466
470
  // The out-of-process seam onto the abandoned-task reaper: the daemon
467
- // owns the live BrowserService, so a CLI verb (`agents browser gc`) can
471
+ // owns the live BrowserService, so a CLI verb (`agents browser prune`) can
468
472
  // only reach `reapAbandoned` through IPC. The daemon's own periodic tick
469
473
  // calls the service method directly.
470
474
  case 'gc': {
@@ -533,7 +537,8 @@ export class BrowserIPCServer {
533
537
  };
534
538
  }
535
539
  const result = await this.service.navigate(request.task, request.url, request.profile);
536
- return { ok: true, tabId: result.tabId, task: request.task };
540
+ const picked = request.picked;
541
+ return { ok: true, tabId: result.tabId, task: request.task, message: picked };
537
542
  }
538
543
  case 'tab-add': {
539
544
  if (!request.task || !request.url) {
@@ -1,5 +1,6 @@
1
1
  import type { BrowserProfile, ProfileName } from './types.js';
2
2
  export type { BrowserProfile } from './types.js';
3
+ export { declaringDevices, profileKind, profileRegistry, type ProfileDeclaration, } from './registry.js';
3
4
  /**
4
5
  * Name of the profile `ensureDefaultBrowserProfile` auto-detects and pins.
5
6
  *
@@ -25,17 +26,9 @@ export declare const LEGACY_DEFAULT_BROWSER_PROFILE_NAME = "default";
25
26
  * wins, so no existing config breaks.
26
27
  */
27
28
  export declare const DEFAULT_PROFILE_ALIAS = "default";
28
- /**
29
- * Where a profile is stored, and therefore who sees it:
30
- * - `local` — this machine's `devices/<machine>/agents.yaml` (`deviceBrowser`)
31
- * - `fleet` — the synced `~/.agents/agents.yaml` (`browser`), visible on every box
32
- */
33
- export type ProfileScope = 'local' | 'fleet';
34
- /** A profile plus the store it actually lives in. */
35
- export interface ScopedBrowserProfile {
36
- profile: BrowserProfile;
37
- scope: ProfileScope;
38
- }
29
+ export type BrowserProfileWithDeclarations = BrowserProfile & {
30
+ devices: string[];
31
+ };
39
32
  /**
40
33
  * The device-local configured default profile name (set via
41
34
  * `agents browser use`), or undefined when unset. When set, it
@@ -60,14 +53,8 @@ export declare function getProfileDownloadsDir(name: string): string;
60
53
  * one-shot migration in migrate.ts folds old captures into here.
61
54
  */
62
55
  export declare function getProfileSessionsDir(name: string, task: string): string;
63
- export declare function listProfiles(): Promise<BrowserProfile[]>;
64
- /**
65
- * Every visible profile paired with the store it lives in. Same precedence as
66
- * {@link listProfiles} — a machine-local entry wins a name collision, so a name
67
- * present in both maps reports `local`, which is the copy that is actually used.
68
- */
69
- export declare function listProfilesWithScope(): Promise<ScopedBrowserProfile[]>;
70
- export declare function getProfile(name: string): Promise<BrowserProfile | null>;
56
+ export declare function listProfiles(): Promise<BrowserProfileWithDeclarations[]>;
57
+ export declare function getProfile(name: string): Promise<BrowserProfileWithDeclarations | null>;
71
58
  /**
72
59
  * True when `profile` can actually launch or attach on THIS machine.
73
60
  *
@@ -79,26 +66,6 @@ export declare function getProfile(name: string): Promise<BrowserProfile | null>
79
66
  * for the current machine.
80
67
  */
81
68
  export declare function isProfileLaunchableHere(profile: BrowserProfile): boolean;
82
- /**
83
- * Resolve the profile `agents browser start` uses when no `--profile` is given.
84
- *
85
- * Order: (1) the device-local configured default (`agents browser profiles
86
- * set-default <name>`) when it names an existing profile that can launch here;
87
- * (2) an existing `default` profile that can launch here; (3) auto-pick the
88
- * first installed Chromium-family browser per the platform priority list in
89
- * chrome.ts (macOS: chrome > brave > edge > chromium > comet > arc; Linux: chrome >
90
- * chromium > brave > edge; Windows: edge > chrome > brave > comet) and pin a
91
- * `default` profile to it. Throws an actionable error if none of those binaries
92
- * are installed.
93
- *
94
- * "Can launch here" matters because `agents.yaml` syncs across the fleet: a
95
- * `default` auto-created on macOS carries a `/Applications/...` binary path that
96
- * doesn't exist on a Linux box. Rather than hand that broken profile back (the
97
- * top browser roadblock — "Custom binary not found"), we re-detect and
98
- * regenerate the `default` for this machine. A configured or existing default
99
- * that no longer exists, or can't launch here, warns and falls through — never a
100
- * hard fail.
101
- */
102
69
  /**
103
70
  * The auto-detected profile this machine already carries, under either name —
104
71
  * the current `auto-chrome` or the `default` an older build wrote. Callers that
@@ -137,17 +104,36 @@ export declare function resolveProfileRef(ref?: string): Promise<string | undefi
137
104
  * `start`'s resolver. Same order as {@link resolveProfileRef} for an explicit
138
105
  * name, but the IMPLICIT path (no `--profile`, or the bare `default` alias with
139
106
  * no profile of that name) goes through {@link ensureDefaultBrowserProfile} —
140
- * which additionally verifies the resolved default can launch on THIS machine,
141
- * warns and falls through when it can't, and regenerates or creates one.
107
+ * which additionally verifies the resolved default can launch on THIS machine.
108
+ * An undeclared configured default is an error. A declared default whose
109
+ * browser isn't installed here warns and falls through to auto-detect.
142
110
  *
143
111
  * `start` is the only command that launches a browser, so it is the only one
144
112
  * that may do those things; routing a filter-only command through this would
145
113
  * warn about, and rewrite, config the user never asked it to touch.
146
114
  *
147
- * Throws when no profile exists and no supported browser is installed
148
- * `ensureDefaultBrowserProfile`'s actionable "install one of …" error.
115
+ * Throws when the configured default is undeclared, or when no profile exists
116
+ * and no supported browser is installed.
149
117
  */
150
118
  export declare function resolveProfileRefForStart(ref?: string): Promise<string>;
119
+ /**
120
+ * Resolve the profile a bare `agents browser start` uses.
121
+ *
122
+ * Order: (1) the device-local configured default (`agents browser use <name>`)
123
+ * when it names a profile that exists and can launch here; (2) an existing
124
+ * auto-detected profile that can launch here; (3) auto-pick the first installed
125
+ * Chromium-family browser and pin `auto-chrome` (or repair a stale legacy
126
+ * `default`) to it.
127
+ *
128
+ * Two failure modes at the configured-default step are not the same:
129
+ * - No device declares the name (including a leftover central `browser:`
130
+ * entry that was never claimed) → throw. Auto-creating `auto-chrome` would
131
+ * hand the agent a logged-out browser while `browser.profile` still names
132
+ * the credentialed one.
133
+ * - The name is declared, but its browser/binary is not installed HERE →
134
+ * warn and fall through. That is a missing binary on this box, not a
135
+ * missing identity; auto-detect is the existing repair.
136
+ */
151
137
  export declare function ensureDefaultBrowserProfile(): Promise<BrowserProfile>;
152
138
  /**
153
139
  * Compute the LOCAL port a profile will occupy at runtime:
@@ -181,46 +167,9 @@ export declare function findFreeProfilePort(): Promise<number>;
181
167
  export declare function assertLocalPortFree(profile: BrowserProfile, opts?: {
182
168
  ignore?: string;
183
169
  }): void;
184
- /**
185
- * Create a profile. **It lands in this machine's own store by default** — pass
186
- * `{ fleet: true }` (the CLI's `--fleet`) to put it in the synced `agents.yaml`
187
- * where every box will see it.
188
- *
189
- * Local-by-default is the RUSH-2716 fix. A profile is a local browser install
190
- * (`binary:` is an absolute path for one OS) bound to a locally chosen free port,
191
- * so the fleet-synced copy is wrong on every other machine to begin with; and
192
- * because agents mint throwaway profiles freely, every ad-hoc one was syncing to
193
- * every machine as junk that nothing cleaned up (`agents browser profiles prune`
194
- * is the other half of that fix). Opting in with `--fleet` is for a profile that
195
- * really is fleet config — a remote `ssh://` endpoint, or a named profile whose
196
- * shape you want on every box.
197
- *
198
- * Existing profiles are NOT migrated: this only decides where a NEW entry is
199
- * written, so a fleet profile created before this change keeps syncing.
200
- */
201
- export declare function createProfile(profile: BrowserProfile, opts?: {
202
- fleet?: boolean;
203
- }): Promise<void>;
170
+ /** Declare a profile on this device. The same name may be declared by peers. */
171
+ export declare function createProfile(profile: BrowserProfile): Promise<void>;
204
172
  export declare function updateProfile(profile: BrowserProfile): Promise<void>;
205
- /**
206
- * Flag a fleet-synced profile whose contents only make sense on ONE machine.
207
- *
208
- * A `cdp://` endpoint on loopback always connects on the machine EVALUATING the
209
- * profile, so a fleet-scope copy does not mean "that browser" — it means "port N
210
- * on whichever box ran the command". The name then silently resolves to a
211
- * different, usually logged-out browser on every other machine, which is the
212
- * worst possible failure for a profile that carries live logins.
213
- *
214
- * Reported by `profiles doctor` (a failing `scope` check) and noted in the
215
- * `kept` reason `profiles prune` prints for a fleet profile. The repair is
216
- * {@link moveProfileScope}, never an automatic rewrite of the synced doc.
217
- */
218
- export declare function misfiledFleetProfile(profile: BrowserProfile, scope: ProfileScope): {
219
- misfiled: false;
220
- } | {
221
- misfiled: true;
222
- why: string;
223
- };
224
173
  /** Fields an existing profile may be edited in place.
225
174
  *
226
175
  * Deliberately a SUBSET of {@link BrowserProfile}. `name` and `browser` are
@@ -231,17 +180,9 @@ export declare function misfiledFleetProfile(profile: BrowserProfile, scope: Pro
231
180
  export type EditableProfileFields = Partial<Pick<BrowserProfile, 'description' | 'binary' | 'electron' | 'targetFilter' | 'endpoints' | 'chrome' | 'secrets' | 'viewport'>>;
232
181
  export interface EditProfileResult {
233
182
  profile: BrowserProfile;
234
- scope: ProfileScope;
183
+ devices: string[];
235
184
  /** Field names that actually changed. Empty means the edit was a no-op. */
236
185
  changed: string[];
237
- /**
238
- * Set when the write landed machine-locally while a stale fleet copy remains.
239
- * Only reachable for {@link isMachineLocalProfile} names that an older version
240
- * wrote into the fleet store: {@link updateProfile} pins those local, so this
241
- * box sees the edit and every other box keeps the old value. Callers must say
242
- * so rather than reporting a clean success.
243
- */
244
- fleetCopyLeftStale?: boolean;
245
186
  }
246
187
  /**
247
188
  * Merge `patch` onto the stored profile and persist it in the store it already
@@ -279,7 +220,7 @@ export declare function assertRegistrableProfileName(name: string): void;
279
220
  * a running browser corrupts it.
280
221
  */
281
222
  export declare function renameProfile(from: ProfileName, to: ProfileName): Promise<{
282
- scope: ProfileScope;
223
+ devices: string[];
283
224
  movedDirs: string[];
284
225
  repointedDefault: boolean;
285
226
  repointedViewer: boolean;
@@ -289,10 +230,6 @@ export declare function renameProfile(from: ProfileName, to: ProfileName): Promi
289
230
  key: 'browser.profile' | 'browser.viewer';
290
231
  }>;
291
232
  }>;
292
- export declare function moveProfileScope(name: string, to: ProfileScope): Promise<{
293
- from: ProfileScope;
294
- to: ProfileScope;
295
- }>;
296
233
  export declare function deleteProfile(name: string): Promise<void>;
297
234
  /**
298
235
  * Pad `text` to exactly `width` visible characters, truncating with an ellipsis
@@ -316,12 +253,9 @@ export declare function padColumn(text: string, width: number): string;
316
253
  * a leading column, explained by a legend line — so the name column carries just
317
254
  * the name and `default` in it always means the profile of that name.
318
255
  *
319
- * The SCOPE column is the RUSH-2716 companion: it says whether an entry lives on
320
- * this machine only (`local`) or in the fleet-synced `agents.yaml` (`fleet`), so
321
- * "why does this box have a profile I never made here?" is answerable at a
322
- * glance.
256
+ * WHERE lists the devices whose own files declare the name.
323
257
  */
324
- export declare function formatProfilesTable(rows: ScopedBrowserProfile[], configuredDefault?: string): string[];
258
+ export declare function formatProfilesTable(rows: BrowserProfileWithDeclarations[], configuredDefault?: string): string[];
325
259
  /**
326
260
  * Resolve a profile's endpoint presets into a normalized map regardless of
327
261
  * whether the YAML uses the legacy `string[]` shape or the new map shape.