@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
@@ -1,254 +0,0 @@
1
- // The `ws` client, NOT the platform (undici) WebSocket: undici enforces a
2
- // non-configurable max decompressed message size, and a CDP response carrying
3
- // a base64 screenshot of a content-rich page blows past it — the socket dies
4
- // with code 1006 ("Max decompressed message size exceeded") while the command
5
- // is pending. `ws` offers no permessage-deflate by default and takes an
6
- // explicit payload cap. (Reproduced live against a remote Edge over
7
- // `browser --device`: fresh blank newtab passed, reused content-rich newtab
8
- // failed on every Page.captureScreenshot.)
9
- import WSWebSocket from 'ws';
10
- const pipeTransports = new Map();
11
- export function registerPipeTransport(transport) {
12
- const id = `pipe://${process.pid}/${pipeTransports.size + 1}`;
13
- pipeTransports.set(id, transport);
14
- return id;
15
- }
16
- export class CDPClient {
17
- ws = null;
18
- pipe = null;
19
- pipeBuffer = Buffer.alloc(0);
20
- transport = null;
21
- messageId = 0;
22
- pending = new Map();
23
- eventHandlers = new Map();
24
- pipeDataHandler = null;
25
- pipeErrorHandler = null;
26
- pipeCloseHandler = null;
27
- async connect(endpoint) {
28
- if (endpoint.startsWith('pipe://')) {
29
- const transport = pipeTransports.get(endpoint);
30
- if (!transport) {
31
- throw new Error('CDP pipe transport is not available in this process');
32
- }
33
- pipeTransports.delete(endpoint);
34
- this.connectPipe(transport);
35
- return;
36
- }
37
- return new Promise((resolve, reject) => {
38
- this.ws = new WSWebSocket(endpoint, { maxPayload: 256 * 1024 * 1024 });
39
- this.transport = 'websocket';
40
- this.ws.onopen = () => resolve();
41
- this.ws.onerror = () => reject(new Error('WebSocket error'));
42
- this.ws.onclose = () => this.handleClose();
43
- this.ws.onmessage = (ev) => this.handleMessage(String(ev.data));
44
- });
45
- }
46
- connectPipe(transport) {
47
- this.pipe = transport;
48
- this.transport = 'pipe';
49
- this.pipeBuffer = Buffer.alloc(0);
50
- this.pipeDataHandler = (chunk) => this.handlePipeData(chunk);
51
- this.pipeErrorHandler = (err) => this.handleClose(err);
52
- this.pipeCloseHandler = () => this.handleClose();
53
- transport.read.on('data', this.pipeDataHandler);
54
- transport.read.on('error', this.pipeErrorHandler);
55
- transport.read.on('close', this.pipeCloseHandler);
56
- transport.write.on('error', this.pipeErrorHandler);
57
- transport.write.on('close', this.pipeCloseHandler);
58
- }
59
- async send(method, params, sessionId) {
60
- if (!this.isOpen) {
61
- // Reached when the underlying browser was killed externally between
62
- // the daemon establishing the connection and a CDP call going out.
63
- // The service-layer healthcheck normally catches this on the next
64
- // `start`, so seeing this in the wild means a request landed against
65
- // an in-flight conn that just died — tell the user how to recover.
66
- throw new Error('CDP connection not open — the browser was likely closed externally. ' +
67
- 'Run `agents browser stop --profile <name>` (or restart the daemon) and try again.');
68
- }
69
- const id = ++this.messageId;
70
- const message = sessionId
71
- ? JSON.stringify({ id, method, params, sessionId })
72
- : JSON.stringify({ id, method, params });
73
- return new Promise((resolve, reject) => {
74
- this.pending.set(id, { resolve: resolve, reject });
75
- if (this.transport === 'pipe') {
76
- this.pipe.write.write(message + '\0');
77
- }
78
- else {
79
- this.ws.send(message);
80
- }
81
- });
82
- }
83
- on(event, handler) {
84
- if (!this.eventHandlers.has(event)) {
85
- this.eventHandlers.set(event, new Set());
86
- }
87
- this.eventHandlers.get(event).add(handler);
88
- }
89
- off(event, handler) {
90
- this.eventHandlers.get(event)?.delete(handler);
91
- }
92
- close() {
93
- if (this.ws) {
94
- this.ws.close();
95
- this.ws = null;
96
- }
97
- if (this.pipe) {
98
- if (this.pipeDataHandler)
99
- this.pipe.read.off('data', this.pipeDataHandler);
100
- if (this.pipeErrorHandler) {
101
- this.pipe.read.off('error', this.pipeErrorHandler);
102
- this.pipe.write.off('error', this.pipeErrorHandler);
103
- }
104
- if (this.pipeCloseHandler) {
105
- this.pipe.read.off('close', this.pipeCloseHandler);
106
- this.pipe.write.off('close', this.pipeCloseHandler);
107
- }
108
- this.pipe.write.end();
109
- this.pipe = null;
110
- }
111
- this.transport = null;
112
- }
113
- get connected() {
114
- return ((this.ws !== null && this.ws.readyState === WSWebSocket.OPEN) ||
115
- (this.pipe !== null && !this.pipe.write.destroyed));
116
- }
117
- get isOpen() {
118
- return this.connected;
119
- }
120
- handlePipeData(chunk) {
121
- this.pipeBuffer = Buffer.concat([this.pipeBuffer, chunk]);
122
- let idx = this.pipeBuffer.indexOf(0);
123
- while (idx !== -1) {
124
- const frame = this.pipeBuffer.subarray(0, idx).toString('utf8');
125
- this.pipeBuffer = this.pipeBuffer.subarray(idx + 1);
126
- if (frame.length > 0)
127
- this.handleMessage(frame);
128
- idx = this.pipeBuffer.indexOf(0);
129
- }
130
- }
131
- handleMessage(data) {
132
- const msg = JSON.parse(data);
133
- if ('id' in msg) {
134
- const pending = this.pending.get(msg.id);
135
- if (pending) {
136
- this.pending.delete(msg.id);
137
- if ('error' in msg) {
138
- pending.reject(new Error(msg.error.message || 'CDP error'));
139
- }
140
- else {
141
- pending.resolve(msg.result);
142
- }
143
- }
144
- }
145
- else if ('method' in msg) {
146
- const handlers = this.eventHandlers.get(msg.method);
147
- if (handlers) {
148
- for (const handler of handlers) {
149
- handler(msg.params || {}, msg.sessionId);
150
- }
151
- }
152
- }
153
- }
154
- handleClose(err) {
155
- for (const pending of this.pending.values()) {
156
- pending.reject(err ?? new Error('CDP connection closed'));
157
- }
158
- this.pending.clear();
159
- this.ws = null;
160
- this.pipe = null;
161
- this.transport = null;
162
- }
163
- }
164
- export class BrowserCdpConnectionError extends Error {
165
- port;
166
- profileName;
167
- host;
168
- constructor(port, profileName = '<name>', host = 'localhost') {
169
- super(formatBrowserCdpConnectionError(port, profileName, host));
170
- this.port = port;
171
- this.profileName = profileName;
172
- this.host = host;
173
- this.name = 'BrowserCdpConnectionError';
174
- }
175
- }
176
- export function formatBrowserCdpConnectionError(port, profileName = '<name>', host = 'localhost') {
177
- const target = host === 'localhost' || host === '127.0.0.1'
178
- ? `port ${port}`
179
- : `${host}:${port}`;
180
- return [
181
- `Could not connect to Chrome on ${target}.`,
182
- `- Is Chrome running with --remote-debugging-port=${port}?`,
183
- `- Try: agents browser start --profile ${profileName}`,
184
- ].join('\n');
185
- }
186
- export async function discoverBrowserWsUrl(port, host = 'localhost', profileName = '<name>') {
187
- // Node's fetch has no default timeout — a port that ACKs the TCP connect
188
- // but never sends an HTTP response will hang here indefinitely. Bound the
189
- // discovery probe so the caller can surface an actionable error in seconds,
190
- // not minutes.
191
- const controller = new AbortController();
192
- const timer = setTimeout(() => controller.abort(), 3000);
193
- let response;
194
- try {
195
- response = await fetch(`http://${host}:${port}/json/version`, { signal: controller.signal });
196
- }
197
- catch {
198
- throw new BrowserCdpConnectionError(port, profileName, host);
199
- }
200
- finally {
201
- clearTimeout(timer);
202
- }
203
- if (!response.ok) {
204
- throw new BrowserCdpConnectionError(port, profileName, host);
205
- }
206
- const data = (await response.json());
207
- const browserField = data.Browser || data.Product || '';
208
- return {
209
- wsUrl: data.webSocketDebuggerUrl,
210
- browser: normalizeBrowserName(browserField),
211
- };
212
- }
213
- export function normalizeBrowserName(s) {
214
- if (!s)
215
- return 'unknown';
216
- return s.split('/')[0].trim().toLowerCase().replace(/\s+/g, '-');
217
- }
218
- export function verifyBrowserIdentity(reported, expected, port, host = 'localhost') {
219
- if (expected === 'custom')
220
- return;
221
- if (reported === 'unknown')
222
- return;
223
- const matches = {
224
- chrome: ['chrome', 'google-chrome', 'headlesschrome'],
225
- chromium: ['chromium', 'headlesschrome', 'chrome'],
226
- // Comet reports itself as plain "Chrome/<version>" in /json/version — it
227
- // doesn't override the Chromium branding. Accept chrome here so attaching
228
- // to a Comet instance doesn't trip a false "identity mismatch".
229
- comet: ['comet', 'chrome'],
230
- // Arc reports itself as plain "Chrome/<version>" in /json/version (verified
231
- // live: Arc 1.15x → "Chrome/151"), so accept chrome to avoid a false
232
- // identity mismatch when attaching to a real Arc.
233
- arc: ['arc', 'chrome'],
234
- brave: ['brave', 'brave-browser', 'chrome'],
235
- // Windows/Chromium Edge reports its /json/version "Browser" field as
236
- // "Edg/<version>" (the `Edg` token, not `Edge`), which normalizeBrowserName
237
- // reduces to "edg". Accept it so attaching to a real Edge doesn't trip a
238
- // false identity mismatch (the profile enum only allows "edge").
239
- edge: ['edge', 'edg', 'microsoft-edge', 'msedge', 'chrome'],
240
- };
241
- const accepted = matches[expected] || [expected];
242
- if (accepted.includes(reported))
243
- return;
244
- const target = host === 'localhost' || host === '127.0.0.1' ? `port ${port}` : `${host}:${port}`;
245
- throw new Error(`Browser identity mismatch: profile expects "${expected}" but ${target} is serving "${reported}". ` +
246
- `Stop the running browser (e.g. \`pkill -f ${reported}\`) or update the profile to browser=${reported}, then retry.`);
247
- }
248
- export async function listTargets(port, host = 'localhost') {
249
- const response = await fetch(`http://${host}:${port}/json`);
250
- if (!response.ok) {
251
- throw new Error(`Failed to list targets: ${response.status}`);
252
- }
253
- return response.json();
254
- }
@@ -1,141 +0,0 @@
1
- import type { ChromeOptions } from './types.js';
2
- import type { BrowserType } from './types.js';
3
- /**
4
- * True when `binaryPath` is a shebang script rather than a native browser
5
- * executable. The Linux distro launchers (`/usr/bin/brave-browser`, …) are such
6
- * scripts; `launchBrowser` can't drive one over `--remote-debugging-pipe` (see
7
- * resolveBrowserBinary). `profiles doctor` uses this to flag a profile whose
8
- * binary resolves to a wrapper we couldn't unwrap. Shebang scripts are a
9
- * Linux/Unix concept — returns false on Windows/macOS app bundles.
10
- */
11
- export declare function isLauncherScript(binaryPath: string): boolean;
12
- export declare function resolveBrowserBinary(binaryPath: string): string;
13
- export declare function findBrowserPath(browserType: BrowserType, customBinary?: string): string;
14
- /**
15
- * Walk the per-platform priority list and return the first browser that's
16
- * actually installed on disk. Returns null if none of them are present.
17
- *
18
- * This is the auto-pick the `agents browser start` command uses when the user
19
- * doesn't pass `--profile`. The intent matches "use whatever's preinstalled,"
20
- * but constrained to Chromium-family binaries so CDP works without a new
21
- * driver layer.
22
- */
23
- export declare function findFirstInstalledBrowser(platform?: string): {
24
- browserType: BrowserType;
25
- binary: string;
26
- } | null;
27
- /**
28
- * List every installed Chromium-family browser on this machine, in the platform
29
- * priority order. Used by `agents setup browser` to offer a pick when more than
30
- * one is present. Returns [] if none are installed.
31
- */
32
- export declare function listInstalledBrowsers(platform?: string): {
33
- browserType: BrowserType;
34
- binary: string;
35
- }[];
36
- export interface LaunchResult {
37
- pid: number;
38
- port: number;
39
- wsUrl: string;
40
- }
41
- /**
42
- * The process that holds a Chromium user-data dir, read from the `SingletonLock`
43
- * symlink Chromium keeps inside the dir on macOS and Linux (`<host>-<pid>`,
44
- * PHNX-4042). A live pid means a browser already owns that store: a launch on it
45
- * would only hand its arguments to the running instance and the requested debug
46
- * port would never bind. Windows keeps no lock file, so this reports null there
47
- * and `launchBrowser` catches the hand-off by the child's early exit instead.
48
- */
49
- export declare function storeOccupant(userDataDir: string): {
50
- pid: number;
51
- } | null;
52
- /**
53
- * The relaunch that makes a browser holding `userDataDir` attachable: the
54
- * ownership guard reads `--user-data-dir` off the running process, so the
55
- * owner's normal launch (no flag) can never be verified.
56
- */
57
- export declare function storeRelaunchCommand(browserType: BrowserType, port: number, userDataDir: string, profileDirectory?: string): string;
58
- /**
59
- * Resolve a browser-profile secrets bundle into an env map for the child, or an
60
- * EMPTY map when the bundle is absent, locked, or otherwise unreadable — never a
61
- * throw and never a prompt. Injecting profile secrets on launch is a BACKGROUND
62
- * read (the agent is spawning the browser, not a human at a Touch ID sheet), so
63
- * the read is `agentOnly` (SEC-13: never pop biometry on its own): a `never`/no-ACL
64
- * or broker-held bundle resolves silently; a locked `hold`/`always` bundle throws,
65
- * and we swallow it so the launch proceeds without those secrets (an agent that
66
- * needs them can `agents secrets unlock <bundle>`). Exported so the no-prompt
67
- * behavior is testable on the real keychain path without spawning a browser.
68
- */
69
- export declare function resolveProfileSecretsEnv(secrets?: string): Promise<Record<string, string>>;
70
- export declare function launchBrowser(profileName: string, browserType: BrowserType, port: number, options?: ChromeOptions, secrets?: string, customBinary?: string, isElectron?: boolean): Promise<LaunchResult>;
71
- export declare function killChrome(pid: number): void;
72
- export declare function getRunningChromeInfo(profileName: string): {
73
- pid: number;
74
- port: number;
75
- } | null;
76
- /**
77
- * Prepare `<userDataDir>/Default/Preferences` before launch.
78
- *
79
- * Two concerns, one write:
80
- * - First launch (file absent): stamp the agents-cli profile name so
81
- * Chromium's UI shows "<profile>" instead of its default "Person 1".
82
- * Cosmetic; existing files keep whatever Chrome wrote in the meantime.
83
- * - Every launch (when `persistSessionCookies`): pin
84
- * `session.restore_on_startup: 1` ("continue where you left off").
85
- * Chromium purges memory-only session cookies at startup UNLESS this
86
- * preference says the session will be restored — it keys the purge off
87
- * the pref, not off tabs actually reopening. Sites like idealista issue
88
- * login cookies with `expires=-1`, so without this every browser restart
89
- * silently logs the profile out. The visible tab-restore side effect is
90
- * suppressed separately via `--no-startup-window` (see launchBrowser).
91
- *
92
- * Runs only while the browser is down (called before spawn), so Chromium
93
- * can't overwrite the patch on exit. Best-effort: a malformed existing file
94
- * is left untouched (Chromium recovers its own state better than we can),
95
- * and any I/O hiccup is silently ignored.
96
- */
97
- export declare function ensureProfilePreferences(userDataDir: string, profileName: string, persistSessionCookies: boolean): void;
98
- /**
99
- * Is a TCP port currently bound? `lsof` on POSIX, `netstat -ano` on Windows
100
- * (lsof doesn't exist there). Returns false on any tooling error so port
101
- * allocation degrades to "assume free" rather than throwing.
102
- *
103
- * Exported as the canonical cross-platform probe — `findFreeProfilePort`
104
- * (profiles.ts) must use this rather than shelling out to lsof directly,
105
- * or every port scans as free on Windows.
106
- */
107
- export declare function isPortInUse(port: number): boolean;
108
- export declare function allocatePort(): number;
109
- /**
110
- * Read the `--user-data-dir` a running browser process was launched with, by
111
- * inspecting its command line (PHNX-3967). This is the ownership signal the
112
- * attach-only guard uses to tell the credentialed canonical browser apart from a
113
- * foreign port-squatter serving CDP on the same port (e.g. a logged-out
114
- * `/tmp/...` Comet). Returns null when the pid is gone, exposes no
115
- * `--user-data-dir`, or the platform probe fails.
116
- *
117
- * POSIX: `ps -ww -o command=` (full, un-truncated argv). Windows: the
118
- * `CommandLine` from `Win32_Process` via PowerShell. The value is captured up to
119
- * the next ` --<flag>` (or end of line) so a data dir that itself contains a
120
- * space is not truncated at the space.
121
- */
122
- export declare function getProcessUserDataDir(pid: number): string | null;
123
- /**
124
- * Extract the `--user-data-dir` value from a browser command line. Handles both
125
- * `--user-data-dir=<path>` and `--user-data-dir <path>` and stops the value at
126
- * the next ` --<flag>` so a path containing spaces survives. Exported for unit
127
- * testing without a live process.
128
- */
129
- export declare function parseUserDataDirFromCommandLine(cmdline: string): string | null;
130
- interface PortOccupant {
131
- pid: number;
132
- command: string;
133
- }
134
- /**
135
- * Identify the process listening on a TCP port. Returns null when nothing is bound.
136
- * Used for clearer error messages when a profile's configured port is taken by a
137
- * non-debug process (e.g. Comet running without --remote-debugging-port).
138
- * `lsof` on POSIX; `netstat -ano` + `tasklist` on Windows.
139
- */
140
- export declare function getPortOccupant(port: number): PortOccupant | null;
141
- export {};