@phnx-labs/agents-cli 1.22.117 → 1.22.119

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 (271) hide show
  1. package/CHANGELOG.md +301 -0
  2. package/dist/bootstrap.js +4 -11
  3. package/dist/commands/accounts.js +7 -4
  4. package/dist/commands/browser.d.ts +52 -70
  5. package/dist/commands/browser.js +192 -3562
  6. package/dist/commands/daemon.d.ts +39 -2
  7. package/dist/commands/daemon.js +72 -73
  8. package/dist/commands/events.js +1 -1
  9. package/dist/commands/exec.js +53 -1
  10. package/dist/commands/projects.js +92 -7
  11. package/dist/commands/repo.js +13 -49
  12. package/dist/commands/route.js +5 -5
  13. package/dist/commands/routines.js +39 -12
  14. package/dist/commands/sessions-render.d.ts +1 -1
  15. package/dist/commands/sessions-render.js +0 -1
  16. package/dist/commands/sessions.test-fixture.d.ts +0 -1
  17. package/dist/commands/sessions.test-fixture.js +0 -37
  18. package/dist/commands/setup-browser.d.ts +17 -12
  19. package/dist/commands/setup-browser.js +52 -87
  20. package/dist/commands/setup-preferences.d.ts +0 -17
  21. package/dist/commands/setup-preferences.js +18 -49
  22. package/dist/commands/setup.js +9 -9
  23. package/dist/commands/ssh.js +10 -1
  24. package/dist/commands/sync.js +6 -44
  25. package/dist/commands/teams.js +0 -1
  26. package/dist/commands/update.d.ts +19 -0
  27. package/dist/commands/update.js +34 -6
  28. package/dist/commands/view.d.ts +12 -1
  29. package/dist/commands/view.js +47 -2
  30. package/dist/index.js +107 -26
  31. package/dist/lib/account-capabilities.js +0 -2
  32. package/dist/lib/account-catalog.d.ts +38 -0
  33. package/dist/lib/account-catalog.js +110 -26
  34. package/dist/lib/account-provider-registry.js +1 -1
  35. package/dist/lib/account-registry.d.ts +1 -1
  36. package/dist/lib/account-registry.js +36 -2
  37. package/dist/lib/accounting/rotate.js +22 -8
  38. package/dist/lib/accounting/usage-ingest.d.ts +6 -1
  39. package/dist/lib/accounting/usage-ingest.js +115 -45
  40. package/dist/lib/accounting/usage-sync.d.ts +134 -31
  41. package/dist/lib/accounting/usage-sync.js +227 -66
  42. package/dist/lib/accounting/usage.d.ts +16 -3
  43. package/dist/lib/accounting/usage.js +26 -8
  44. package/dist/lib/accounts/add.d.ts +3 -1
  45. package/dist/lib/accounts/add.js +24 -13
  46. package/dist/lib/accounts/slots.d.ts +8 -0
  47. package/dist/lib/accounts/slots.js +17 -0
  48. package/dist/lib/add-dir.js +0 -1
  49. package/dist/lib/agent-cli-commands.js +0 -1
  50. package/dist/lib/agent-spec/agents.d.ts +6 -7
  51. package/dist/lib/agent-spec/agents.js +7 -60
  52. package/dist/lib/auth-health.d.ts +69 -1
  53. package/dist/lib/auth-health.js +133 -4
  54. package/dist/lib/browser/context.d.ts +82 -0
  55. package/dist/lib/browser/context.js +88 -0
  56. package/dist/lib/browser/paths.d.ts +25 -0
  57. package/dist/lib/browser/paths.js +51 -0
  58. package/dist/lib/browser/record.d.ts +38 -0
  59. package/dist/lib/browser/record.js +57 -0
  60. package/dist/lib/browser/sessions-list.js +1 -2
  61. package/dist/lib/browser-client.d.ts +158 -0
  62. package/dist/lib/browser-client.js +234 -0
  63. package/dist/lib/channels/owner-sink.d.ts +1 -18
  64. package/dist/lib/channels/owner-sink.js +29 -82
  65. package/dist/lib/channels/providers/rush.d.ts +7 -7
  66. package/dist/lib/channels/providers/rush.js +127 -57
  67. package/dist/lib/claude-account-token.d.ts +7 -1
  68. package/dist/lib/claude-account-token.js +26 -4
  69. package/dist/lib/claude-statusline.d.ts +1 -1
  70. package/dist/lib/claude-statusline.js +15 -3
  71. package/dist/lib/commands.js +1 -1
  72. package/dist/lib/crabbox/lease.js +1 -1
  73. package/dist/lib/crabbox/runtimes.js +1 -3
  74. package/dist/lib/daemon/account-state-daemon-service.js +1 -0
  75. package/dist/lib/daemon/auth-sync-service.d.ts +21 -18
  76. package/dist/lib/daemon/auth-sync-service.js +37 -43
  77. package/dist/lib/daemon/daemon.d.ts +25 -14
  78. package/dist/lib/daemon/daemon.js +92 -154
  79. package/dist/lib/daemon/runner.d.ts +2 -2
  80. package/dist/lib/daemon/runner.js +32 -9
  81. package/dist/lib/daemon/self-update-service.d.ts +35 -34
  82. package/dist/lib/daemon/self-update-service.js +40 -36
  83. package/dist/lib/daemon/service.d.ts +12 -8
  84. package/dist/lib/daemon/supervisor.d.ts +65 -54
  85. package/dist/lib/daemon/supervisor.js +136 -171
  86. package/dist/lib/daemon/testdata/process-view-start.js +5 -2
  87. package/dist/lib/daemon/usage-sync-service.d.ts +21 -30
  88. package/dist/lib/daemon/usage-sync-service.js +46 -78
  89. package/dist/lib/daemon-health.d.ts +22 -5
  90. package/dist/lib/daemon-health.js +47 -3
  91. package/dist/lib/daemon-services.d.ts +1 -1
  92. package/dist/lib/daemon-services.js +0 -10
  93. package/dist/lib/daemon-ticks.js +4 -2
  94. package/dist/lib/devices/doctor-findings.js +8 -11
  95. package/dist/lib/devices/harness-inventory.js +14 -5
  96. package/dist/lib/exec-account-home.js +5 -0
  97. package/dist/lib/exec.js +10 -13
  98. package/dist/lib/feed/events.js +0 -1
  99. package/dist/lib/feed/tool-activity.js +5 -2
  100. package/dist/lib/fleet-shared-state.d.ts +45 -0
  101. package/dist/lib/fleet-shared-state.js +78 -9
  102. package/dist/lib/fs-atomic.js +25 -0
  103. package/dist/lib/github/pr-mergeable.d.ts +4 -2
  104. package/dist/lib/github/pr-mergeable.js +5 -3
  105. package/dist/lib/github/project-prs.d.ts +58 -3
  106. package/dist/lib/github/project-prs.js +205 -7
  107. package/dist/lib/harness/adapters/cursor.js +14 -4
  108. package/dist/lib/harness-auth-capabilities.d.ts +4 -3
  109. package/dist/lib/harness-auth-capabilities.js +1 -2
  110. package/dist/lib/helper-versions.js +1 -1
  111. package/dist/lib/hooks/cache.d.ts +7 -0
  112. package/dist/lib/hooks/cache.js +27 -2
  113. package/dist/lib/hooks/install.js +7 -1
  114. package/dist/lib/hosts/ready.d.ts +38 -8
  115. package/dist/lib/hosts/ready.js +62 -14
  116. package/dist/lib/installations/active-check.d.ts +27 -0
  117. package/dist/lib/installations/active-check.js +61 -0
  118. package/dist/lib/installations/migrate.js +6 -3
  119. package/dist/lib/installations/shims.d.ts +1 -1
  120. package/dist/lib/installations/shims.js +32 -12
  121. package/dist/lib/installations/store.d.ts +9 -0
  122. package/dist/lib/installations/store.js +24 -0
  123. package/dist/lib/installations/update.js +21 -15
  124. package/dist/lib/installations/versions.js +15 -3
  125. package/dist/lib/manifest.js +1 -1
  126. package/dist/lib/models.js +0 -2
  127. package/dist/lib/open-url.js +28 -54
  128. package/dist/lib/profiles.js +0 -2
  129. package/dist/lib/projects.d.ts +16 -0
  130. package/dist/lib/projects.js +31 -0
  131. package/dist/lib/refresh.js +1 -1
  132. package/dist/lib/routine-readiness.d.ts +35 -0
  133. package/dist/lib/routine-readiness.js +74 -16
  134. package/dist/lib/rules/compile.js +6 -0
  135. package/dist/lib/sandbox.js +0 -2
  136. package/dist/lib/secrets-policy.d.ts +89 -11
  137. package/dist/lib/secrets-policy.js +175 -28
  138. package/dist/lib/session/active.d.ts +17 -6
  139. package/dist/lib/session/active.js +105 -49
  140. package/dist/lib/session/db.d.ts +1 -1
  141. package/dist/lib/session/db.js +65 -18
  142. package/dist/lib/session/discover.js +1 -283
  143. package/dist/lib/session/mirror.d.ts +4 -3
  144. package/dist/lib/session/mirror.js +4 -3
  145. package/dist/lib/session/parse.d.ts +0 -2
  146. package/dist/lib/session/parse.js +1 -138
  147. package/dist/lib/session/pid-registry.d.ts +6 -3
  148. package/dist/lib/session/pid-registry.js +18 -8
  149. package/dist/lib/session/remote/watch.d.ts +1 -1
  150. package/dist/lib/session/remote/watch.js +7 -3
  151. package/dist/lib/session/throughput.d.ts +1 -3
  152. package/dist/lib/session/throughput.js +0 -20
  153. package/dist/lib/session/types.d.ts +2 -2
  154. package/dist/lib/session/types.js +2 -2
  155. package/dist/lib/sessions-client.d.ts +60 -1
  156. package/dist/lib/sessions-client.js +227 -4
  157. package/dist/lib/setup-tool-status.js +5 -10
  158. package/dist/lib/signin-badge.d.ts +3 -2
  159. package/dist/lib/signin-badge.js +6 -3
  160. package/dist/lib/smart-launch.js +4 -1
  161. package/dist/lib/staleness/detectors/commands.d.ts +1 -1
  162. package/dist/lib/staleness/detectors/hooks.d.ts +1 -1
  163. package/dist/lib/staleness/detectors/mcp.d.ts +1 -1
  164. package/dist/lib/staleness/detectors/permissions.d.ts +1 -1
  165. package/dist/lib/staleness/detectors/plugins.d.ts +1 -1
  166. package/dist/lib/staleness/detectors/rules.d.ts +1 -1
  167. package/dist/lib/staleness/detectors/skills.d.ts +1 -1
  168. package/dist/lib/staleness/detectors/subagents.d.ts +1 -1
  169. package/dist/lib/staleness/detectors/workflows.d.ts +1 -1
  170. package/dist/lib/staleness/writers/commands.d.ts +1 -1
  171. package/dist/lib/staleness/writers/hooks.d.ts +1 -1
  172. package/dist/lib/staleness/writers/mcp.d.ts +1 -1
  173. package/dist/lib/staleness/writers/permissions.d.ts +1 -1
  174. package/dist/lib/staleness/writers/plugins.d.ts +1 -1
  175. package/dist/lib/staleness/writers/rules.d.ts +1 -1
  176. package/dist/lib/staleness/writers/skills.d.ts +1 -1
  177. package/dist/lib/staleness/writers/sources.js +5 -0
  178. package/dist/lib/staleness/writers/subagents.d.ts +1 -1
  179. package/dist/lib/staleness/writers/workflows.d.ts +1 -1
  180. package/dist/lib/state.d.ts +6 -4
  181. package/dist/lib/state.js +7 -17
  182. package/dist/lib/teams/parsers.d.ts +1 -1
  183. package/dist/lib/teams/parsers.js +1 -136
  184. package/dist/lib/teams/placement-probe.js +50 -15
  185. package/dist/lib/teams/scheduler.d.ts +7 -0
  186. package/dist/lib/types.d.ts +16 -1
  187. package/dist/lib/types.js +1 -1
  188. package/dist/lib/view-types.d.ts +32 -0
  189. package/dist/lib/watchdog/read.js +0 -1
  190. package/dist/lib/watchdog/rotate.js +1 -2
  191. package/dist/lib/watchdog/runner.js +2 -2
  192. package/dist/lib/watchdog/watchdog.d.ts +1 -1
  193. package/dist/lib/watchdog/watchdogTail.js +0 -31
  194. package/package.json +1 -1
  195. package/scripts/postinstall.js +8 -8
  196. package/dist/browser.d.ts +0 -2
  197. package/dist/browser.js +0 -17
  198. package/dist/commands/browser-picker.d.ts +0 -18
  199. package/dist/commands/browser-picker.js +0 -97
  200. package/dist/lib/browser/arc-discovery.d.ts +0 -52
  201. package/dist/lib/browser/arc-discovery.js +0 -197
  202. package/dist/lib/browser/arc-dom.d.ts +0 -14
  203. package/dist/lib/browser/arc-dom.js +0 -121
  204. package/dist/lib/browser/caller-identity.d.ts +0 -40
  205. package/dist/lib/browser/caller-identity.js +0 -175
  206. package/dist/lib/browser/cdp.d.ts +0 -51
  207. package/dist/lib/browser/cdp.js +0 -254
  208. package/dist/lib/browser/chrome.d.ts +0 -141
  209. package/dist/lib/browser/chrome.js +0 -704
  210. package/dist/lib/browser/chromium-discovery.d.ts +0 -28
  211. package/dist/lib/browser/chromium-discovery.js +0 -96
  212. package/dist/lib/browser/devices.d.ts +0 -34
  213. package/dist/lib/browser/devices.js +0 -61
  214. package/dist/lib/browser/domain-skills.d.ts +0 -71
  215. package/dist/lib/browser/domain-skills.js +0 -195
  216. package/dist/lib/browser/drivers/arc.d.ts +0 -40
  217. package/dist/lib/browser/drivers/arc.js +0 -276
  218. package/dist/lib/browser/drivers/firefox.d.ts +0 -99
  219. package/dist/lib/browser/drivers/firefox.js +0 -377
  220. package/dist/lib/browser/drivers/local.d.ts +0 -55
  221. package/dist/lib/browser/drivers/local.js +0 -266
  222. package/dist/lib/browser/drivers/ssh.d.ts +0 -120
  223. package/dist/lib/browser/drivers/ssh.js +0 -467
  224. package/dist/lib/browser/editor.d.ts +0 -3
  225. package/dist/lib/browser/editor.js +0 -50
  226. package/dist/lib/browser/ffmpeg.d.ts +0 -12
  227. package/dist/lib/browser/ffmpeg.js +0 -184
  228. package/dist/lib/browser/firefox-discovery.d.ts +0 -69
  229. package/dist/lib/browser/firefox-discovery.js +0 -162
  230. package/dist/lib/browser/har.d.ts +0 -85
  231. package/dist/lib/browser/har.js +0 -77
  232. package/dist/lib/browser/hygiene.d.ts +0 -97
  233. package/dist/lib/browser/hygiene.js +0 -153
  234. package/dist/lib/browser/index.d.ts +0 -5
  235. package/dist/lib/browser/index.js +0 -5
  236. package/dist/lib/browser/input.d.ts +0 -7
  237. package/dist/lib/browser/input.js +0 -92
  238. package/dist/lib/browser/ipc.d.ts +0 -204
  239. package/dist/lib/browser/ipc.js +0 -1453
  240. package/dist/lib/browser/login-detection.d.ts +0 -87
  241. package/dist/lib/browser/login-detection.js +0 -274
  242. package/dist/lib/browser/profiles.d.ts +0 -422
  243. package/dist/lib/browser/profiles.js +0 -1157
  244. package/dist/lib/browser/refs.d.ts +0 -89
  245. package/dist/lib/browser/refs.js +0 -191
  246. package/dist/lib/browser/registry.d.ts +0 -70
  247. package/dist/lib/browser/registry.js +0 -252
  248. package/dist/lib/browser/remote-control.d.ts +0 -59
  249. package/dist/lib/browser/remote-control.js +0 -85
  250. package/dist/lib/browser/resolve-target.d.ts +0 -66
  251. package/dist/lib/browser/resolve-target.js +0 -264
  252. package/dist/lib/browser/runtime-state.d.ts +0 -291
  253. package/dist/lib/browser/runtime-state.js +0 -584
  254. package/dist/lib/browser/secret-ref.d.ts +0 -10
  255. package/dist/lib/browser/secret-ref.js +0 -14
  256. package/dist/lib/browser/service.d.ts +0 -812
  257. package/dist/lib/browser/service.js +0 -4693
  258. package/dist/lib/browser/stream.d.ts +0 -17
  259. package/dist/lib/browser/stream.js +0 -72
  260. package/dist/lib/browser/task-index.d.ts +0 -78
  261. package/dist/lib/browser/task-index.js +0 -199
  262. package/dist/lib/browser/types.d.ts +0 -647
  263. package/dist/lib/browser/types.js +0 -61
  264. package/dist/lib/browser/upload.d.ts +0 -29
  265. package/dist/lib/browser/upload.js +0 -298
  266. package/dist/lib/daemon/browser-ipc-service.d.ts +0 -20
  267. package/dist/lib/daemon/browser-ipc-service.js +0 -46
  268. package/dist/lib/daemon/browser-task-reap-service.d.ts +0 -14
  269. package/dist/lib/daemon/browser-task-reap-service.js +0 -26
  270. package/dist/lib/fleet-shared-repo-sync.d.ts +0 -55
  271. package/dist/lib/fleet-shared-repo-sync.js +0 -490
@@ -55,34 +55,13 @@ function syncMarketplacesForDefaults() {
55
55
  catch { /* best-effort */ }
56
56
  }
57
57
  }
58
- /** Write this device's account metadata before the user repo is committed. */
59
- async function publishUserRepoAccountState(provisionAuth) {
60
- const { publishUsageSnapshotToSharedStore } = await import('../lib/accounting/usage-sync.js');
61
- const usage = await publishUsageSnapshotToSharedStore();
62
- if (usage.error)
63
- console.error(chalk.yellow(`Usage snapshot: ${usage.error}`));
64
- if (provisionAuth) {
65
- const { syncReservedAuthBundle } = await import('../lib/secrets-policy.js');
66
- const auth = await syncReservedAuthBundle();
67
- if (auth.pushed.length > 0)
68
- console.log(chalk.gray(`Auth bundle: pushed to ${auth.pushed.join(', ')}`));
69
- for (const err of auth.errors)
70
- console.error(chalk.yellow(`Auth bundle: ${err.device}: ${err.message}`));
71
- return;
72
- }
73
- const { publishReservedAuthVerdict } = await import('../lib/secrets-policy.js');
74
- const auth = await publishReservedAuthVerdict();
75
- if (auth.error)
76
- console.error(chalk.yellow(`Auth verdict: ${auth.device}: ${auth.error}`));
77
- }
78
- /** Consume freshly pulled usage/auth metadata from the local user-repo checkout. */
79
- async function consumeUserRepoAccountState() {
80
- const { consumeUsageSnapshotsFromSharedStore } = await import('../lib/accounting/usage-sync.js');
81
- const usage = consumeUsageSnapshotsFromSharedStore();
82
- if (usage.merged > 0)
83
- console.log(chalk.gray(`Usage snapshot: merged ${usage.merged} row(s) from ${usage.sources.join(', ')}`));
84
- for (const err of usage.errors)
85
- console.error(chalk.yellow(`Usage snapshot: ${err.device}: ${err.message}`));
58
+ /**
59
+ * Push the reserved auth bundle to peers whose last-received verdict says
60
+ * `missing`. Daemon state (usage, verdicts, session digests) no longer rides the
61
+ * user repo — it moves over SSH on the usage-sync tick (PHNX-4116) — so a repo
62
+ * push/sync of human-authored resources only runs this credential half.
63
+ */
64
+ async function syncUserRepoAuthBundle() {
86
65
  const { syncReservedAuthBundle } = await import('../lib/secrets-policy.js');
87
66
  const auth = await syncReservedAuthBundle();
88
67
  if (auth.pushed.length > 0)
@@ -1085,7 +1064,7 @@ export function registerRepoCommands(program) {
1085
1064
  ].filter(Boolean);
1086
1065
  if (parts.length > 0)
1087
1066
  console.log(chalk.gray(`Device policy: ${parts.join(' · ')}`));
1088
- await consumeUserRepoAccountState();
1067
+ await syncUserRepoAuthBundle();
1089
1068
  }
1090
1069
  });
1091
1070
  repoCmd
@@ -1121,10 +1100,8 @@ export function registerRepoCommands(program) {
1121
1100
  return;
1122
1101
  }
1123
1102
  for (const t of pushable) {
1124
- // Account snapshots must exist BEFORE commitAndPush or this push ships
1125
- // the previous tick's state and delays propagation by one repo cycle.
1126
1103
  if (t.alias === 'user')
1127
- await publishUserRepoAccountState(true);
1104
+ await syncUserRepoAuthBundle();
1128
1105
  const spinner = interruptibleSpinner(`Pushing ${formatRepoTarget(t.alias, t.dir)}...`).start();
1129
1106
  const result = await commitAndPush(t.dir, options.message);
1130
1107
  if (result.success) {
@@ -1193,23 +1170,10 @@ Examples:
1193
1170
  }
1194
1171
  }
1195
1172
  const push = t.alias !== 'system';
1196
- // syncRepoGit pulls then pushes. Seed our conflict-free owner file first
1197
- // so the same transaction carries it; consume peers after the pull.
1198
- if (t.alias === 'user')
1199
- await publishUserRepoAccountState(false);
1173
+ // A plain pull/rebase (+ push) of human-authored resources for every
1174
+ // alias, the user repo included: daemon state left git (PHNX-4116).
1200
1175
  const spinner = interruptibleSpinner(`Syncing ${formatRepoTarget(t.alias, t.dir)}...`).start();
1201
- const result = t.alias === 'user'
1202
- ? await (async () => {
1203
- const { syncFleetSharedStateRepo } = await import('../lib/fleet-shared-repo-sync.js');
1204
- const synced = await syncFleetSharedStateRepo({ userAgentsDir: t.dir });
1205
- return {
1206
- success: synced.success,
1207
- commit: synced.commit ?? '',
1208
- pushed: synced.pushed,
1209
- error: synced.error ?? synced.skipped ?? undefined,
1210
- };
1211
- })()
1212
- : await syncRepoGit(t.dir, { push });
1176
+ const result = await syncRepoGit(t.dir, { push });
1213
1177
  if (result.success) {
1214
1178
  const pushed = result.pushed ? ' (pushed)' : '';
1215
1179
  spinner.succeed(`${formatRepoTarget(t.alias, t.dir)}: ${result.commit}${pushed}`);
@@ -1219,7 +1183,7 @@ Examples:
1219
1183
  recordUserRepoRemote(t.dir, u);
1220
1184
  const { reconcileDeviceDiscoveryPolicies } = await import('../lib/devices/discovery-policy.js');
1221
1185
  await reconcileDeviceDiscoveryPolicies();
1222
- await consumeUserRepoAccountState();
1186
+ await syncUserRepoAuthBundle();
1223
1187
  }
1224
1188
  }
1225
1189
  else {
@@ -95,13 +95,13 @@ export function registerRouteCommands(program) {
95
95
  setHelpSections(routeCmd, {
96
96
  examples: `
97
97
  # Create a router scoped to two harnesses, capped at a tier
98
- agents route add research --harness gemini,kimi --tier cheap,default
98
+ agents route add research --harness grok,kimi --tier cheap,default
99
99
 
100
100
  # Narrow one harness's model set
101
101
  agents route allow research kimi kimi-k2
102
102
 
103
103
  # Link accounts so routing under this router only ever picks them
104
- agents route link-account research gemini personal
104
+ agents route link-account research grok personal
105
105
  agents route link-account research kimi work
106
106
 
107
107
  # Inspect, rename, remove it
@@ -126,7 +126,7 @@ export function registerRouteCommands(program) {
126
126
  .command('add <name>')
127
127
  .alias('create')
128
128
  .description('Create a named router with an initial harness + tier allowlist.')
129
- .option('--harness <list>', 'Comma-separated harness ids to allow, e.g. gemini,kimi')
129
+ .option('--harness <list>', 'Comma-separated harness ids to allow, e.g. grok,kimi')
130
130
  .option('--tier <list>', 'Comma-separated tier tokens applied to every listed harness, e.g. cheap,default')
131
131
  .option('--task <type>', 'Free-text task type this router serves, e.g. research')
132
132
  .action((name, opts) => {
@@ -134,7 +134,7 @@ export function registerRouteCommands(program) {
134
134
  die(`Router '${name}' already exists. Use 'agents route allow ${name} <harness> <model|tier>...' to edit it.`);
135
135
  }
136
136
  if (!opts.harness) {
137
- die("Missing --harness. Example: agents route add research --harness gemini,kimi --tier cheap,default");
137
+ die("Missing --harness. Example: agents route add research --harness grok,kimi --tier cheap,default");
138
138
  }
139
139
  const harnesses = opts.harness.split(',').map((h) => h.trim()).filter(Boolean);
140
140
  const tiers = (opts.tier ?? '').split(',').map((t) => t.trim()).filter(Boolean);
@@ -170,7 +170,7 @@ export function registerRouteCommands(program) {
170
170
  }
171
171
  if (routers.length === 0) {
172
172
  console.log(chalk.gray('No routers configured.'));
173
- console.log(chalk.gray('Try: agents route add research --harness gemini,kimi --tier cheap,default'));
173
+ console.log(chalk.gray('Try: agents route add research --harness grok,kimi --tier cheap,default'));
174
174
  return;
175
175
  }
176
176
  for (const router of routers)
@@ -246,7 +246,7 @@ function renderRoutineRows({ jobs, scheduler, overdueSet, link, now, local = tru
246
246
  : lastStatus === 'missed' ? chalk.magenta
247
247
  : chalk.gray;
248
248
  const overdueTag = overdueSet.has(job.name) ? chalk.yellow(' (overdue)') : '';
249
- // Append the concrete reason a routine did not complete (auth_failed, wedged,
249
+ // Append the concrete reason a routine did not complete (auth_failed,
250
250
  // blocked, missed) right in the Last Status cell, so the list answers "why"
251
251
  // without a drill-in. Only for non-completed local runs; peer rows stay blank.
252
252
  const reason = latestRun ? runFailureReason(latestRun) : null;
@@ -650,12 +650,29 @@ function routineMatchesQuery(job, q) {
650
650
  .toLowerCase()
651
651
  .includes(q);
652
652
  }
653
- /** Friendly one-liners for the claim a `skipped` run lost. */
653
+ /**
654
+ * Friendly one-liners for the claim a `skipped` run lost — the reasons whose
655
+ * message is static. `active_run` is dynamic (it names the live run that owns
656
+ * the slot and when it started), built in {@link runFailureReason}: since
657
+ * PHNX-4116 there is no "wedged" daemon state, so an overlapping routine reads
658
+ * as `blocked` on the live run, not "wedged".
659
+ */
654
660
  const SKIP_REASON_LABEL = {
655
- active_run: 'wedged: a prior run is still active',
656
661
  duplicate_slot: 'duplicate slot (already fired)',
657
662
  wrong_owner: 'pinned to another device',
658
663
  };
664
+ /**
665
+ * A run id is an ISO timestamp with `:`/`.` replaced by `-` (`slotRunId` /
666
+ * `generateRunId`), so it reverses losslessly to the run's start time. Returns
667
+ * the ISO string, or null when the id is not that shape (a hand-set id).
668
+ */
669
+ function runIdToStartIso(runId) {
670
+ const m = /^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})-(\d{3})Z$/.exec(runId);
671
+ if (!m)
672
+ return null;
673
+ const iso = `${m[1]}T${m[2]}:${m[3]}:${m[4]}.${m[5]}Z`;
674
+ return Number.isFinite(Date.parse(iso)) ? iso : null;
675
+ }
659
676
  /**
660
677
  * The short, human reason a run did not simply complete — for inline display in
661
678
  * the list/detail so "why did it fail" needs no dig into the run dir. Prefers the
@@ -670,6 +687,21 @@ export function runFailureReason(run) {
670
687
  const one = s.replace(/\s+/g, ' ').trim();
671
688
  return one.length > 80 ? one.slice(0, 79) + '…' : one;
672
689
  };
690
+ // An overlap skip names the live run it lost to (PHNX-4116): `blocked: run
691
+ // <id> active since <t>`, not the removed "wedged" wording. The structured
692
+ // `activeRunId` is preferred; a legacy record without it falls back to the
693
+ // errorMessage (which embeds the same id) so nothing regresses to vaguer text.
694
+ if (run.skipReason === 'active_run') {
695
+ if (run.activeRunId) {
696
+ const since = runIdToStartIso(run.activeRunId);
697
+ return since
698
+ ? `blocked: run ${run.activeRunId} active since ${since}`
699
+ : `blocked: run ${run.activeRunId} still active`;
700
+ }
701
+ if (run.errorMessage)
702
+ return compact(run.errorMessage);
703
+ return 'blocked: a prior run is still active';
704
+ }
673
705
  if (run.errorMessage)
674
706
  return compact(run.errorMessage);
675
707
  if (run.status === 'blocked' && run.readiness) {
@@ -751,8 +783,8 @@ function buildRoutineDetail(job, scheduler, now) {
751
783
  : chalk.yellow(run.status);
752
784
  const dur = run.completedAt ? ` ${formatRunDuration(run.startedAt, run.completedAt)}` : '';
753
785
  // Surface WHY a run did not complete, inline, so "looking at status" does not
754
- // require digging into the run dir. auth_failed / OAuth-revoked, a wedged
755
- // active-run skip, or a readiness block all live on the RunMeta already.
786
+ // require digging into the run dir. auth_failed / OAuth-revoked, an
787
+ // active-run overlap skip, or a readiness block all live on the RunMeta already.
756
788
  const reason = runFailureReason(run);
757
789
  const why = reason ? chalk.gray(` — ${reason}`) : '';
758
790
  lines.push(` ${run.startedAt} ${status}${dur}${why}`);
@@ -1941,7 +1973,7 @@ export function registerRoutinesCommands(program) {
1941
1973
  chalk.gray(` ${run.startedAt}`) +
1942
1974
  chalk.gray(formatRunDuration(run.startedAt, run.completedAt)) +
1943
1975
  (run.exitCode !== null && run.exitCode !== undefined ? chalk.gray(` exit ${run.exitCode}`) : ''));
1944
- // The structured reason (auth_failed, blocked readiness, wedged skip) — the
1976
+ // The structured reason (auth_failed, blocked readiness, overlap skip) — the
1945
1977
  // report/stdout tail below often buries or omits it, so name it up front.
1946
1978
  const logsReason = runFailureReason(run);
1947
1979
  if (logsReason)
@@ -2300,9 +2332,7 @@ export function registerRoutinesCommands(program) {
2300
2332
  console.log(chalk.bold('Scheduler\n'));
2301
2333
  const stateLabel = schedulerState === 'running'
2302
2334
  ? chalk.green('running')
2303
- : schedulerState === 'wedged'
2304
- ? chalk.red('wedged')
2305
- : chalk.gray('stopped');
2335
+ : chalk.gray('stopped');
2306
2336
  console.log(` Status: ${stateLabel}`);
2307
2337
  console.log(` Daemon: ${status.running ? chalk.green('running') : chalk.gray('stopped')}`);
2308
2338
  if (status.pid)
@@ -2316,9 +2346,6 @@ export function registerRoutinesCommands(program) {
2316
2346
  const jobs = listAllJobs();
2317
2347
  const enabled = jobs.filter((j) => j.enabled);
2318
2348
  console.log(` Routines: ${enabled.length} enabled / ${jobs.length} total`);
2319
- if (status.state === 'wedged') {
2320
- console.log(chalk.red('\n The shared daemon is wedged (heartbeat stale). Restart deliberately with: agents daemon restart'));
2321
- }
2322
2349
  if (schedulerState === 'running' && enabled.length > 0) {
2323
2350
  const scheduler = new JobScheduler(async () => { });
2324
2351
  scheduler.loadAll();
@@ -1,6 +1,6 @@
1
1
  import type { Command } from 'commander';
2
2
  import type { SessionMeta } from '../lib/session/types.js';
3
- export declare const MARKDOWN_RENDER_AGENTS: readonly ["claude", "codex", "gemini", "antigravity", "opencode", "grok", "rush", "hermes", "kimi", "droid", "cursor"];
3
+ export declare const MARKDOWN_RENDER_AGENTS: readonly ["claude", "codex", "antigravity", "opencode", "grok", "rush", "hermes", "kimi", "droid", "cursor"];
4
4
  export type ReasoningMode = 'omit' | 'fold' | 'include';
5
5
  /** Build one shareable Markdown document from the canonical preview and event model. */
6
6
  export declare function renderSessionMarkdownDocument(session: SessionMeta, options?: {
@@ -14,7 +14,6 @@ import { selectSessions } from './sessions-export.js';
14
14
  export const MARKDOWN_RENDER_AGENTS = [
15
15
  'claude',
16
16
  'codex',
17
- 'gemini',
18
17
  'antigravity',
19
18
  'opencode',
20
19
  'grok',
@@ -15,7 +15,6 @@ export declare const tsxLoaderUrl: string;
15
15
  export declare function writeUpdateCache(tempHome: string): void;
16
16
  export declare function writeClaudeSession(tempHome: string, projectKey: string, sessionId: string, cwd: string, content: string, timestamp: string): void;
17
17
  export declare function writeCodexSession(tempHome: string, sessionId: string, cwd: string, prompt: string, timestamp: string): void;
18
- export declare function writeGeminiSession(tempHome: string, sessionId: string, cwd: string, prompt: string, timestamp: string, version?: string): void;
19
18
  export declare function writeOpenClawSetup(tempHome: string, version?: string): string;
20
19
  export declare function runAgents(args: string[], cwd: string, home: string, envOverrides?: Record<string, string>): import("node:child_process").SpawnSyncReturns<string>;
21
20
  export declare function outputOf(result: {
@@ -1,7 +1,6 @@
1
1
  import { describe } from 'vitest';
2
2
  import * as fs from 'fs';
3
3
  import * as path from 'path';
4
- import * as crypto from 'crypto';
5
4
  import { spawnSync } from 'child_process';
6
5
  import { createRequire } from 'node:module';
7
6
  import { pathToFileURL } from 'node:url';
@@ -121,42 +120,6 @@ export function writeCodexSession(tempHome, sessionId, cwd, prompt, timestamp) {
121
120
  ];
122
121
  fs.writeFileSync(filePath, lines.join('\n') + '\n', 'utf-8');
123
122
  }
124
- export function writeGeminiSession(tempHome, sessionId, cwd, prompt, timestamp, version = '0.29.5') {
125
- const versionHome = path.join(tempHome, '.agents', '.history', 'versions', 'gemini', version, 'home');
126
- const geminiHome = path.join(versionHome, '.gemini');
127
- const projectHash = crypto.createHash('sha256').update(cwd).digest('hex');
128
- const chatsDir = path.join(geminiHome, 'tmp', projectHash, 'chats');
129
- fs.mkdirSync(cwd, { recursive: true });
130
- fs.mkdirSync(chatsDir, { recursive: true });
131
- fs.mkdirSync(path.dirname(path.join(tempHome, '.gemini')), { recursive: true });
132
- const activeGeminiHome = path.join(tempHome, '.gemini');
133
- if (!fs.existsSync(activeGeminiHome)) {
134
- fs.symlinkSync(geminiHome, activeGeminiHome);
135
- }
136
- fs.writeFileSync(path.join(geminiHome, 'projects.json'), JSON.stringify({ projects: [cwd] }), 'utf-8');
137
- fs.writeFileSync(path.join(chatsDir, `session-${timestamp.replace(/[:.]/g, '-')}-${sessionId.slice(0, 8)}.json`), JSON.stringify({
138
- sessionId,
139
- projectHash,
140
- startTime: timestamp,
141
- lastUpdated: timestamp,
142
- messages: [
143
- {
144
- id: `${sessionId}-user`,
145
- timestamp,
146
- type: 'user',
147
- content: [{ text: prompt }],
148
- },
149
- {
150
- id: `${sessionId}-assistant`,
151
- timestamp,
152
- type: 'gemini',
153
- content: 'Investigating now.',
154
- model: 'gemini-3-flash-preview',
155
- tokens: { total: 1234 },
156
- },
157
- ],
158
- }, null, 2), 'utf-8');
159
- }
160
123
  export function writeOpenClawSetup(tempHome, version = '2026.3.8') {
161
124
  const managedHome = path.join(tempHome, '.agents', '.history', 'versions', 'openclaw', version, 'home', '.openclaw');
162
125
  fs.mkdirSync(managedHome, { recursive: true });
@@ -1,20 +1,25 @@
1
1
  /**
2
- * `agents setup browser` — interactive wizard to get `agents browser` working on
3
- * a fresh machine: detect an installed Chromium-family browser, create the
4
- * `default` profile pinned to it, optionally make it this machine's default, and
5
- * point the user at the one manual step we can't automate (first-run + sign-in).
2
+ * `agents setup browser` — get `agents browser` working on a fresh machine:
3
+ * install the standalone `browser` CLI (@phnx-labs/browser-cli), let it detect
4
+ * installed browsers and create machine-local profiles (`browser profiles seed`),
5
+ * then pick this machine's default (`browser use`).
6
6
  *
7
- * Idempotent: re-running shows the current default profile and offers to change
8
- * the pinned browser or re-point the device default.
7
+ * The engine owns profile declarations and browser detection now (PHNX-4101), so
8
+ * this wizard DELEGATES to it rather than crafting profiles itself. What stays
9
+ * agents-cli's is the onboarding flow and the readiness check over the shared
10
+ * `browser.profile` config key both CLIs read/write.
11
+ *
12
+ * Idempotent: `profiles seed` leaves existing profiles untouched, and `use`
13
+ * re-points the device default.
9
14
  */
10
15
  import type { Command } from 'commander';
11
16
  /**
12
- * Interactive browser setup. Returns true if a usable default profile exists
13
- * afterwards, false if none exists / the user backed out. Non-interactively it
14
- * only RECOGNIZES an existing profile — it never creates one (PHNX-3296), since
15
- * silently minting a logged-out `auto-chrome` on a headless box is the exact bug
16
- * that removed; a headless box gets its browser from the fleet hub. Never throws
17
- * on cancel — the `agents setup` hub relies on that.
17
+ * Interactive browser setup. Returns true if a default profile is configured
18
+ * afterwards, false if none is / the user backed out. Non-interactively it only
19
+ * RECOGNIZES an existing default — it never creates one (PHNX-3296), since
20
+ * silently minting a logged-out profile on a headless box is the exact bug that
21
+ * removed; a headless box gets its browser from the fleet hub. Never throws on
22
+ * cancel — the `agents setup` hub relies on that.
18
23
  */
19
24
  export declare function runBrowserWizard(): Promise<boolean>;
20
25
  /** Register `agents setup browser` under the parent `setup` command. */
@@ -1,124 +1,89 @@
1
1
  /**
2
- * `agents setup browser` — interactive wizard to get `agents browser` working on
3
- * a fresh machine: detect an installed Chromium-family browser, create the
4
- * `default` profile pinned to it, optionally make it this machine's default, and
5
- * point the user at the one manual step we can't automate (first-run + sign-in).
2
+ * `agents setup browser` — get `agents browser` working on a fresh machine:
3
+ * install the standalone `browser` CLI (@phnx-labs/browser-cli), let it detect
4
+ * installed browsers and create machine-local profiles (`browser profiles seed`),
5
+ * then pick this machine's default (`browser use`).
6
6
  *
7
- * Idempotent: re-running shows the current default profile and offers to change
8
- * the pinned browser or re-point the device default.
7
+ * The engine owns profile declarations and browser detection now (PHNX-4101), so
8
+ * this wizard DELEGATES to it rather than crafting profiles itself. What stays
9
+ * agents-cli's is the onboarding flow and the readiness check over the shared
10
+ * `browser.profile` config key both CLIs read/write.
11
+ *
12
+ * Idempotent: `profiles seed` leaves existing profiles untouched, and `use`
13
+ * re-points the device default.
9
14
  */
10
15
  import { openSetupTerminal } from './setup-terminal.js';
11
16
  import chalk from 'chalk';
12
- import { setConfigValue } from '../lib/device-config.js';
13
- import { listInstalledBrowsers } from '../lib/browser/chrome.js';
14
- import { DEFAULT_BROWSER_PROFILE_NAME, getAutoDetectedProfile, createProfile, findFreeProfilePort, getConfiguredDefaultProfileName, } from '../lib/browser/profiles.js';
15
- import { DEFAULT_VIEWPORT } from '../lib/browser/devices.js';
17
+ import { getConfigValue } from '../lib/device-config.js';
16
18
  import { isInteractiveTerminal, isPromptCancelled } from './utils.js';
17
- import { defaultBrowserChoice } from './setup-preferences.js';
18
19
  import { installSetupTool } from '../lib/setup-tool-install.js';
19
20
  import { refreshToolSetup } from '../lib/setup-tool-status.js';
20
- const INSTALL_HINT = 'Install one of: Google Chrome, Brave, Microsoft Edge, Chromium, Comet, or Arc, then re-run `agents setup browser`.\n' +
21
- '(This wizard picks a Chromium-family browser. An installed Firefox is not auto-picked here; its profiles are ' +
22
- 'discovered from profiles.ini and selected with `agents browser use firefox-<name>`. Safari is not supported.)';
21
+ import { browserInstalled, runBrowser } from '../lib/browser-client.js';
22
+ import { buildBrowserContext } from '../lib/browser/context.js';
23
+ /** The device-local default profile, as both agents-cli and browser-cli see it. */
24
+ function configuredDefaultProfile() {
25
+ return getConfigValue('browser.profile').value || undefined;
26
+ }
27
+ /** Run one standalone `browser` verb, inheriting the terminal, and return its exit code. */
28
+ async function runBrowserVerb(argv) {
29
+ const { exitCode } = await runBrowser({ argv, context: await buildBrowserContext() });
30
+ return exitCode;
31
+ }
23
32
  /**
24
- * Interactive browser setup. Returns true if a usable default profile exists
25
- * afterwards, false if none exists / the user backed out. Non-interactively it
26
- * only RECOGNIZES an existing profile — it never creates one (PHNX-3296), since
27
- * silently minting a logged-out `auto-chrome` on a headless box is the exact bug
28
- * that removed; a headless box gets its browser from the fleet hub. Never throws
29
- * on cancel — the `agents setup` hub relies on that.
33
+ * Interactive browser setup. Returns true if a default profile is configured
34
+ * afterwards, false if none is / the user backed out. Non-interactively it only
35
+ * RECOGNIZES an existing default — it never creates one (PHNX-3296), since
36
+ * silently minting a logged-out profile on a headless box is the exact bug that
37
+ * removed; a headless box gets its browser from the fleet hub. Never throws on
38
+ * cancel — the `agents setup` hub relies on that.
30
39
  */
31
40
  export async function runBrowserWizard() {
32
41
  if (!isInteractiveTerminal()) {
33
- // Non-interactive / headless: recognize an existing default, but NEVER mint
34
- // one. Silently auto-detecting an installed browser and creating an
35
- // `auto-chrome` here is exactly the bug PHNX-3296 removed — a headless box
36
- // gets its browser from the fleet hub (`browser.device`), or from an
37
- // interactive pick later.
38
- const existing = await getAutoDetectedProfile();
42
+ const existing = configuredDefaultProfile();
39
43
  if (existing) {
40
- console.log(chalk.dim(`Browser profile "${existing.name}" already exists.`));
44
+ console.log(chalk.dim(`Default browser profile "${existing}" already configured on this machine.`));
41
45
  return true;
42
46
  }
43
47
  console.log(chalk.dim('No default browser profile on this machine. Re-run `agents setup browser` in an ' +
44
48
  'interactive terminal to pick one, or use the fleet hub: agents config set browser.device <host>.'));
45
49
  return false;
46
50
  }
47
- const installed = listInstalledBrowsers();
48
- if (installed.length === 0) {
49
- console.error(chalk.red('No supported browser found on this machine.'));
50
- console.log(chalk.dim(INSTALL_HINT));
51
- return false;
52
- }
53
- const { confirm, select } = await import('@inquirer/prompts');
54
- // If a default profile already exists, this is a reconfigure.
55
- const existing = await getAutoDetectedProfile();
56
- if (existing) {
57
- console.log(chalk.dim(`Browser profile "${existing.name}" already exists (${existing.browser}${existing.binary ? ` · ${existing.binary}` : ''}).`));
58
- const change = await confirm({ message: 'Re-create it (e.g. to pin a different browser)?', default: false });
59
- if (!change) {
60
- await maybeSetDeviceDefault(existing.name, confirm);
61
- printOnboardingNextStep(existing.name);
62
- return true;
51
+ if (!browserInstalled()) {
52
+ console.log(chalk.dim('Installing the standalone Browser CLI (@phnx-labs/browser-cli)…'));
53
+ if (!(await installSetupTool('browser'))) {
54
+ console.error(chalk.red('Could not install @phnx-labs/browser-cli. Install it manually with `npm i -g @phnx-labs/browser-cli`, then re-run.'));
55
+ return false;
63
56
  }
64
- // Re-create: drop the old one so createProfile doesn't collide.
65
- const { deleteProfile } = await import('../lib/browser/profiles.js');
66
- await deleteProfile(existing.name);
67
57
  }
68
- // Pick which installed browser to pin (auto-select if only one). The picker
69
- // highlights the same browser auto-detect would win — choosing is an
70
- // override of the default, never a guess.
71
- let chosen = installed[0];
72
- if (installed.length > 1) {
73
- const value = await select({
74
- message: 'Which browser should the default profile use?',
75
- default: defaultBrowserChoice(installed) ?? undefined,
76
- choices: installed.map((b) => ({ name: `${b.browserType} ${chalk.dim(b.binary)}`, value: b.browserType })),
77
- });
78
- chosen = installed.find((b) => b.browserType === value) ?? installed[0];
58
+ // Let the engine detect installed browsers and create a machine-local profile
59
+ // for each (idempotent), then open its own picker to set this machine's default.
60
+ const seedCode = await runBrowserVerb(['profiles', 'seed']);
61
+ if (seedCode !== 0) {
62
+ console.error(chalk.red('`browser profiles seed` failed — see the output above.'));
63
+ return false;
79
64
  }
80
- const freePort = await findFreeProfilePort();
81
- const profile = {
82
- name: DEFAULT_BROWSER_PROFILE_NAME,
83
- description: `${chosen.browserType} profile (agents setup browser)`,
84
- browser: chosen.browserType,
85
- binary: chosen.binary,
86
- endpoints: [`cdp://127.0.0.1:${freePort}`],
87
- viewport: { width: DEFAULT_VIEWPORT.width, height: DEFAULT_VIEWPORT.height },
88
- };
89
- await createProfile(profile);
90
- console.log(chalk.green(`\nCreated browser profile "${profile.name}" → ${chosen.browserType} (CDP 127.0.0.1:${freePort}).`));
91
- await maybeSetDeviceDefault(profile.name, confirm);
92
- printOnboardingNextStep(profile.name);
93
- return true;
94
- }
95
- /** Offer to make `name` this machine's default browser profile (device-local). */
96
- async function maybeSetDeviceDefault(name, confirm) {
97
- const current = getConfiguredDefaultProfileName();
98
- if (current === name)
99
- return; // already the device default
100
- const set = await confirm({
101
- message: `Make "${name}" this machine's default browser profile?`,
102
- default: true,
103
- });
104
- if (set) {
105
- setConfigValue('browser.profile', name);
106
- console.log(chalk.dim(`Bare \`agents browser start\` will now use "${name}" on this machine.`));
65
+ await runBrowserVerb(['use']);
66
+ const chosen = configuredDefaultProfile();
67
+ if (!chosen) {
68
+ console.log(chalk.dim('No default profile chosen. Run `agents browser use <name>` later to set one.'));
69
+ return false;
107
70
  }
71
+ printOnboardingNextStep(chosen);
72
+ return true;
108
73
  }
109
- /** The one step we can't automate: Chrome's first-run + your own sign-in. */
74
+ /** The one step we can't automate: the browser's first-run + your own sign-in. */
110
75
  function printOnboardingNextStep(name) {
111
76
  console.log(chalk.bold('\nOne manual step left:'));
112
77
  console.log(' ' +
113
78
  chalk.cyan(`agents browser start --profile ${name}`) +
114
- chalk.dim(' # finish Chrome first-run + sign in to any sites you want automated'));
79
+ chalk.dim(' # finish the browser first-run + sign in to any sites you want automated'));
115
80
  console.log(chalk.dim(` Then check it's ready: agents browser profiles doctor ${name}`));
116
81
  }
117
82
  /** Register `agents setup browser` under the parent `setup` command. */
118
83
  export function registerSetupBrowserCommand(setupCmd) {
119
84
  setupCmd
120
85
  .command('browser')
121
- .description('Set up `agents browser` — detect an installed browser and create the default profile.')
86
+ .description('Set up `agents browser` — install the Browser CLI, seed profiles, and pick this machine\'s default.')
122
87
  .option('--install-only', 'Install the standalone Browser CLI without changing profiles or starting a browser')
123
88
  .option('--terminal [backend]', 'Open interactive setup in a detected or selected terminal')
124
89
  .action(async (options) => {
@@ -21,14 +21,6 @@ export declare function macDeviceNames(reg: DeviceRegistry): string[];
21
21
  * first candidate. null when there are no candidates.
22
22
  */
23
23
  export declare function defaultInteractiveHostChoice(candidates: string[], self?: string): string | null;
24
- /**
25
- * The browser picker's highlighted default — the same browser auto-detect
26
- * would win, since `listInstalledBrowsers` returns platform priority order
27
- * (macOS: chrome first). null when nothing is installed.
28
- */
29
- export declare function defaultBrowserChoice<T extends {
30
- browserType: string;
31
- }>(installed: T[]): T['browserType'] | null;
32
24
  /**
33
25
  * Offer to set the interactive host when none is configured and the registry
34
26
  * has more than one macOS device. Returns true when a host was set. Silent
@@ -53,15 +45,6 @@ export declare function maybePickInteractiveHost(): Promise<boolean>;
53
45
  export declare function maybePickBrowserProfile(deps?: {
54
46
  /** Force interactivity in a test; defaults to a real TTY probe. */
55
47
  interactive?: boolean;
56
- /** Inject the prompt so the pick is testable without a TTY. */
57
- select?: (config: {
58
- message: string;
59
- default?: string;
60
- choices: Array<{
61
- name: string;
62
- value: string;
63
- }>;
64
- }) => Promise<string>;
65
48
  }): Promise<boolean>;
66
49
  /**
67
50
  * The bare-`agents setup` preferences step: interactive host, then browser.