@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,52 +0,0 @@
1
- interface ArcSpace {
2
- /** Stable UUID used for every native operation. */
3
- id: string;
4
- /** Display-only title; empty when the Space is untitled. Never part of identity. */
5
- title: string;
6
- }
7
- interface ArcProfile {
8
- /** Arc's profile directory basename: the stable profile identity. */
9
- profileId: string;
10
- /** Display-only profile name from Local State. */
11
- displayName: string;
12
- spaces: ArcSpace[];
13
- }
14
- type ArcDiscoveryResult = {
15
- ok: true;
16
- profiles: ArcProfile[];
17
- userDataDir: string;
18
- } | {
19
- ok: false;
20
- kind: 'unsupported' | 'not-installed' | 'invalid';
21
- reason: string;
22
- };
23
- interface SidebarSpace {
24
- id: string;
25
- title: string;
26
- profileId: string;
27
- }
28
- export declare function parseLocalStateProfiles(localStatePath: string): Map<string, string> | {
29
- error: string;
30
- };
31
- export declare function parseSidebarSpaces(sidebarPath: string): SidebarSpace[] | {
32
- error: string;
33
- };
34
- export declare function discoverArcProfilesAt(arcDir: string): ArcDiscoveryResult;
35
- export declare function discoverArcProfiles(): ArcDiscoveryResult;
36
- /** One Arc Space, flattened with the Arc profile it belongs to. */
37
- interface ArcSpaceProfile {
38
- /** The agents-cli profile name: `arc-<space-title-slug>`. */
39
- name: string;
40
- profileId: string;
41
- profileName: string;
42
- spaceId: string;
43
- spaceTitle: string;
44
- }
45
- /**
46
- * Flatten discovery into one agents-cli profile per Space (the concept agents
47
- * already know), named `arc-<space-title>`. Two Spaces with the same title get
48
- * the first six characters of their stable Space id appended, so the names
49
- * stay distinct without inventing a second selector.
50
- */
51
- export declare function arcSpaceProfiles(result: ArcDiscoveryResult): ArcSpaceProfile[];
52
- export {};
@@ -1,197 +0,0 @@
1
- /** Read-only Arc profile/Space discovery from Arc's native metadata. */
2
- import * as fs from 'node:fs';
3
- import * as os from 'node:os';
4
- import * as path from 'node:path';
5
- function isRecord(value) {
6
- return !!value && typeof value === 'object' && !Array.isArray(value);
7
- }
8
- /**
9
- * Arc's application-support root on this Mac. Arc keeps its Chromium `Local
10
- * State` under `<root>/User Data/` and its own sidebar model (Spaces and their
11
- * profile bindings) at `<root>/StorableSidebar.json` — two different levels,
12
- * so discovery is rooted here rather than at the Chromium user-data dir.
13
- * `AGENTS_ARC_DIR` points tests and non-default installs at another root.
14
- */
15
- function arcSupportDir() {
16
- const override = process.env.AGENTS_ARC_DIR;
17
- if (override)
18
- return path.resolve(override);
19
- if (process.platform !== 'darwin')
20
- return undefined;
21
- return path.join(os.homedir(), 'Library', 'Application Support', 'Arc');
22
- }
23
- export function parseLocalStateProfiles(localStatePath) {
24
- let parsed;
25
- try {
26
- parsed = JSON.parse(fs.readFileSync(localStatePath, 'utf8'));
27
- }
28
- catch (error) {
29
- return {
30
- error: error instanceof SyntaxError
31
- ? 'Arc Local State is not valid JSON'
32
- : `Cannot read Arc Local State: ${error instanceof Error ? error.message : String(error)}`,
33
- };
34
- }
35
- if (!isRecord(parsed) || !isRecord(parsed.profile) || !isRecord(parsed.profile.info_cache)) {
36
- return { error: 'Arc Local State has no profile.info_cache map' };
37
- }
38
- const profiles = new Map();
39
- for (const [profileId, value] of Object.entries(parsed.profile.info_cache)) {
40
- if (profileId === '__ARC_SYSTEM_PROFILE')
41
- continue;
42
- if (!isRecord(value) || typeof value.name !== 'string' || value.name.trim() === '') {
43
- return { error: `Arc Local State profile ${JSON.stringify(profileId)} has no non-empty name` };
44
- }
45
- profiles.set(profileId, value.name);
46
- }
47
- return profiles;
48
- }
49
- function parseProfileId(value, spaceId) {
50
- if (!isRecord(value)) {
51
- return { error: `Arc Space ${JSON.stringify(spaceId)} has no profile mapping` };
52
- }
53
- if (value.default === true && value.custom === undefined)
54
- return 'Default';
55
- if (!isRecord(value.custom)) {
56
- return { error: `Arc Space ${JSON.stringify(spaceId)} has an unknown profile mapping` };
57
- }
58
- const entries = Object.values(value.custom);
59
- if (entries.length !== 1 || !isRecord(entries[0])) {
60
- return { error: `Arc Space ${JSON.stringify(spaceId)} has an ambiguous custom profile mapping` };
61
- }
62
- const profileId = entries[0].directoryBasename;
63
- if (typeof profileId !== 'string' || profileId.trim() === '') {
64
- return { error: `Arc Space ${JSON.stringify(spaceId)} has no custom profile id` };
65
- }
66
- return profileId;
67
- }
68
- function parseTitle(value, spaceId) {
69
- if (value === undefined || value === null)
70
- return '';
71
- if (typeof value === 'string')
72
- return value;
73
- return { error: `Arc Space ${JSON.stringify(spaceId)} has a non-text title` };
74
- }
75
- export function parseSidebarSpaces(sidebarPath) {
76
- let parsed;
77
- try {
78
- parsed = JSON.parse(fs.readFileSync(sidebarPath, 'utf8'));
79
- }
80
- catch (error) {
81
- return {
82
- error: error instanceof SyntaxError
83
- ? 'Arc StorableSidebar.json is not valid JSON'
84
- : `Cannot read Arc StorableSidebar.json: ${error instanceof Error ? error.message : String(error)}`,
85
- };
86
- }
87
- if (!isRecord(parsed) || parsed.version !== 1) {
88
- const version = isRecord(parsed) ? parsed.version : undefined;
89
- return { error: `Unsupported StorableSidebar version: ${String(version)}` };
90
- }
91
- if (!isRecord(parsed.sidebar) || !Array.isArray(parsed.sidebar.containers)) {
92
- return { error: 'StorableSidebar.json has no sidebar.containers array' };
93
- }
94
- const spaces = [];
95
- const ids = new Set();
96
- for (const container of parsed.sidebar.containers) {
97
- if (!isRecord(container) || container.spaces === undefined)
98
- continue;
99
- if (!Array.isArray(container.spaces) || container.spaces.length % 2 !== 0) {
100
- return { error: 'StorableSidebar.json contains a malformed alternating spaces array' };
101
- }
102
- for (let i = 0; i < container.spaces.length; i += 2) {
103
- const encodedId = container.spaces[i];
104
- const value = container.spaces[i + 1];
105
- if (typeof encodedId !== 'string' || !isRecord(value)) {
106
- return { error: `StorableSidebar.json contains a malformed Space at index ${i}` };
107
- }
108
- if (typeof value.id !== 'string' || value.id !== encodedId) {
109
- return { error: `Arc Space key ${JSON.stringify(encodedId)} does not match its stable id` };
110
- }
111
- // Identity is the stable id and the profile binding. The title is
112
- // display-only: Arc omits it for an untitled Space, which must still be
113
- // listed (as `arc-space`) instead of taking every other Space down.
114
- const title = parseTitle(value.title, encodedId);
115
- if (typeof title !== 'string')
116
- return title;
117
- if (ids.has(encodedId)) {
118
- return { error: `Arc Space ${JSON.stringify(encodedId)} appears more than once` };
119
- }
120
- const profileId = parseProfileId(value.profile, encodedId);
121
- if (typeof profileId !== 'string')
122
- return profileId;
123
- ids.add(encodedId);
124
- spaces.push({ id: encodedId, title, profileId });
125
- }
126
- }
127
- return spaces;
128
- }
129
- export function discoverArcProfilesAt(arcDir) {
130
- const userDataDir = path.join(arcDir, 'User Data');
131
- if (!fs.existsSync(userDataDir)) {
132
- return { ok: false, kind: 'not-installed', reason: `Arc user data directory not found: ${userDataDir}` };
133
- }
134
- const profileNames = parseLocalStateProfiles(path.join(userDataDir, 'Local State'));
135
- if ('error' in profileNames)
136
- return { ok: false, kind: 'invalid', reason: profileNames.error };
137
- if (profileNames.size === 0) {
138
- return { ok: false, kind: 'invalid', reason: 'No Arc profiles found in Local State' };
139
- }
140
- const spaces = parseSidebarSpaces(path.join(arcDir, 'StorableSidebar.json'));
141
- if ('error' in spaces)
142
- return { ok: false, kind: 'invalid', reason: spaces.error };
143
- const profiles = new Map();
144
- for (const [profileId, displayName] of profileNames) {
145
- profiles.set(profileId, { profileId, displayName, spaces: [] });
146
- }
147
- for (const space of spaces) {
148
- const profile = profiles.get(space.profileId);
149
- if (!profile) {
150
- return {
151
- ok: false,
152
- kind: 'invalid',
153
- reason: `Arc Space ${JSON.stringify(space.id)} maps to unknown profile ${JSON.stringify(space.profileId)}`,
154
- };
155
- }
156
- profile.spaces.push({ id: space.id, title: space.title });
157
- }
158
- return { ok: true, profiles: [...profiles.values()], userDataDir };
159
- }
160
- export function discoverArcProfiles() {
161
- const arcDir = arcSupportDir();
162
- if (!arcDir) {
163
- return { ok: false, kind: 'unsupported', reason: 'Arc is not supported on this platform' };
164
- }
165
- return discoverArcProfilesAt(arcDir);
166
- }
167
- function slugify(value) {
168
- return value.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
169
- }
170
- /**
171
- * Flatten discovery into one agents-cli profile per Space (the concept agents
172
- * already know), named `arc-<space-title>`. Two Spaces with the same title get
173
- * the first six characters of their stable Space id appended, so the names
174
- * stay distinct without inventing a second selector.
175
- */
176
- export function arcSpaceProfiles(result) {
177
- if (!result.ok)
178
- return [];
179
- const flat = [];
180
- for (const profile of result.profiles) {
181
- for (const space of profile.spaces) {
182
- flat.push({
183
- name: `arc-${slugify(space.title) || 'space'}`,
184
- profileId: profile.profileId,
185
- profileName: profile.displayName,
186
- spaceId: space.id,
187
- spaceTitle: space.title,
188
- });
189
- }
190
- }
191
- const counts = new Map();
192
- for (const entry of flat)
193
- counts.set(entry.name, (counts.get(entry.name) ?? 0) + 1);
194
- return flat.map((entry) => (counts.get(entry.name) ?? 0) > 1
195
- ? { ...entry, name: `${entry.name}-${slugify(entry.spaceId).slice(0, 6)}` }
196
- : entry);
197
- }
@@ -1,14 +0,0 @@
1
- import type { RefNode, RefOpts } from './refs.js';
2
- /** Build one synchronous expression that reads DOM-backed refs from native Arc. */
3
- export declare function arcRefsExpression(opts?: RefOpts): string;
4
- export declare function parseArcRefsResult(value: unknown, opts?: RefOpts): {
5
- refs: string;
6
- nodeMap: Map<number, RefNode>;
7
- opts: {
8
- interactive: boolean;
9
- limit: number;
10
- };
11
- };
12
- export declare function arcClickExpression(selector: string): string;
13
- export declare function arcFillExpression(selector: string, text: string, clear?: boolean): string;
14
- export declare function arcScrollExpression(deltaX: number, deltaY: number): string;
@@ -1,121 +0,0 @@
1
- import { truncate } from '../format.js';
2
- const INTERACTIVE_SELECTOR = [
3
- 'a[href]', 'button', 'input', 'select', 'textarea', '[contenteditable="true"]',
4
- '[role="button"]', '[role="link"]', '[role="textbox"]', '[role="checkbox"]',
5
- '[role="radio"]', '[role="combobox"]', '[role="listbox"]', '[role="option"]',
6
- '[role="menuitem"]', '[role="tab"]', '[role="slider"]', '[role="spinbutton"]',
7
- '[role="searchbox"]', '[role="switch"]', '[role="treeitem"]',
8
- ].join(',');
9
- /** Build one synchronous expression that reads DOM-backed refs from native Arc. */
10
- export function arcRefsExpression(opts = {}) {
11
- const interactive = opts.interactive ?? true;
12
- const limit = opts.limit ?? 500;
13
- return `(() => {
14
- const selectorFor = (el) => {
15
- if (el.id) return '#' + CSS.escape(el.id);
16
- const parts = [];
17
- for (let node = el; node && node.nodeType === 1 && node !== document.documentElement; node = node.parentElement) {
18
- let part = node.localName;
19
- if (!part) return '';
20
- const siblings = node.parentElement ? Array.from(node.parentElement.children).filter((s) => s.localName === node.localName) : [];
21
- if (siblings.length > 1) part += ':nth-of-type(' + (siblings.indexOf(node) + 1) + ')';
22
- parts.unshift(part);
23
- }
24
- return parts.join(' > ');
25
- };
26
- const roleFor = (el) => {
27
- const explicit = el.getAttribute('role');
28
- if (explicit) return explicit.toLowerCase();
29
- if (el.matches('button')) return 'button';
30
- if (el.matches('a[href]')) return 'link';
31
- if (el.matches('textarea,[contenteditable="true"]')) return 'textbox';
32
- if (el.matches('select')) return 'combobox';
33
- if (el.matches('input')) {
34
- const type = (el.getAttribute('type') || 'text').toLowerCase();
35
- if (type === 'checkbox') return 'checkbox';
36
- if (type === 'radio') return 'radio';
37
- if (type === 'range') return 'slider';
38
- if (type === 'number') return 'spinbutton';
39
- return 'textbox';
40
- }
41
- return el.localName || 'generic';
42
- };
43
- const nameFor = (el) => el.getAttribute('aria-label') || el.getAttribute('title') ||
44
- (el.labels && el.labels[0] && el.labels[0].innerText) || el.innerText || el.value || el.getAttribute('placeholder') || '';
45
- const attrsFor = (el) => ['disabled','checked','selected','expanded','required','readonly','invalid']
46
- .filter((name) => el[name] === true || el.getAttribute('aria-' + name) === 'true');
47
- const editorFor = (el) => {
48
- for (let node = el, i = 0; node && i < 6; node = node.parentElement, i++) {
49
- if (node.hasAttribute('data-lexical-editor')) return 'lexical';
50
- if (node.classList.contains('ProseMirror')) return 'prosemirror';
51
- if (node.hasAttribute('data-slate-editor')) return 'slate';
52
- if (Array.from(node.classList).some((c) => /^DraftEditor-/.test(c))) return 'draft';
53
- if (node.classList.contains('ql-editor')) return 'quill';
54
- if (node.classList.contains('ck-editor__editable')) return 'ckeditor5';
55
- if (node.tagName === 'TRIX-EDITOR') return 'trix';
56
- }
57
- return undefined;
58
- };
59
- const source = ${interactive ? `document.querySelectorAll(${JSON.stringify(INTERACTIVE_SELECTOR)})` : `document.querySelectorAll('body *')`};
60
- const rows = [];
61
- for (const el of source) {
62
- if (rows.length >= ${JSON.stringify(limit)}) break;
63
- const selector = selectorFor(el);
64
- if (!selector) continue;
65
- const row = { role: roleFor(el), name: String(nameFor(el)).trim(), attrs: attrsFor(el), selector };
66
- const editor = editorFor(el);
67
- if (editor) row.editor = editor;
68
- rows.push(row);
69
- }
70
- return JSON.stringify(rows);
71
- })()`;
72
- }
73
- export function parseArcRefsResult(value, opts = {}) {
74
- const parsed = typeof value === 'string' ? JSON.parse(value) : value;
75
- if (!Array.isArray(parsed))
76
- throw new Error('Arc returned an invalid DOM ref listing.');
77
- const nodeMap = new Map();
78
- const lines = [];
79
- const compact = opts.compact ?? false;
80
- parsed.forEach((raw, index) => {
81
- const row = raw;
82
- if (typeof row.role !== 'string' || typeof row.name !== 'string' ||
83
- typeof row.selector !== 'string' || !Array.isArray(row.attrs) ||
84
- !row.attrs.every((attr) => typeof attr === 'string')) {
85
- throw new Error('Arc returned an invalid DOM ref entry.');
86
- }
87
- const ref = index + 1;
88
- const node = { ref, role: row.role, name: row.name, attrs: row.attrs, selector: row.selector };
89
- if (typeof row.editor === 'string')
90
- node.editor = row.editor;
91
- nodeMap.set(ref, node);
92
- const name = row.name ? ` "${truncate(row.name, 50)}"` : '';
93
- const attrs = row.attrs.length ? ` [${row.attrs.join('] [')}]` : '';
94
- const editor = row.editor ? ` [editor=${row.editor}]` : '';
95
- lines.push(`${compact ? '' : '- '}${row.role}${name} [ref=${ref}]${attrs}${editor}`);
96
- });
97
- return { refs: lines.join('\n'), nodeMap, opts: { interactive: opts.interactive ?? true, limit: opts.limit ?? 500 } };
98
- }
99
- export function arcClickExpression(selector) {
100
- return `(() => { const el = document.querySelector(${JSON.stringify(selector)}); if (!el) throw new Error('DOM ref is missing'); el.click(); return true; })()`;
101
- }
102
- export function arcFillExpression(selector, text, clear = true) {
103
- return `(() => {
104
- const el = document.querySelector(${JSON.stringify(selector)});
105
- if (!el) throw new Error('DOM ref is missing');
106
- const next = ${JSON.stringify(text)};
107
- if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
108
- const proto = el instanceof HTMLInputElement ? HTMLInputElement.prototype : HTMLTextAreaElement.prototype;
109
- const setter = Object.getOwnPropertyDescriptor(proto, 'value').set;
110
- setter.call(el, ${clear ? 'next' : 'el.value + next'});
111
- } else if (el.isContentEditable) {
112
- el.textContent = ${clear ? 'next' : '(el.textContent || "") + next'};
113
- } else throw new Error('DOM ref is not editable');
114
- el.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertText', data: next }));
115
- el.dispatchEvent(new Event('change', { bubbles: true }));
116
- return true;
117
- })()`;
118
- }
119
- export function arcScrollExpression(deltaX, deltaY) {
120
- return `(() => { window.scrollBy(${JSON.stringify(deltaX)}, ${JSON.stringify(deltaY)}); return true; })()`;
121
- }
@@ -1,40 +0,0 @@
1
- export interface CallerIdentity {
2
- actor: string;
3
- launchId?: string;
4
- sessionId?: string;
5
- /** Agent pid when identity came from the process-table anchor. */
6
- agentPid?: number;
7
- }
8
- /**
9
- * Resolve caller identity once per CLI process for browser IPC stamping.
10
- *
11
- * Starts from `process.ppid` — the shell or harness that launched this
12
- * `agents browser` invocation — and walks up until a state file or known
13
- * agent comm is found.
14
- */
15
- export declare function resolveCallerIdentity(env?: NodeJS.ProcessEnv): CallerIdentity;
16
- /**
17
- * The env a `browser --device` dispatch forwards so the HUB resolves the SAME
18
- * caller identity the worker would stamp locally. Without it a forwarded verb
19
- * lands on the hub with BLANK identity, and the daemon's no-identity task bucket
20
- * matches any other no-identity task — so a cold verb could attach to (or a
21
- * `done`/`stop` could close) an unrelated agent's or a human's browser. This is
22
- * the same surface-parity fix the `run --device` path already carries via
23
- * `--env AGENT_LAUNCH_ID` (remote-session-id.ts). Absent fields are omitted so a
24
- * genuinely-unidentifiable caller forwards nothing rather than an empty string
25
- * that would read as a real (blank) identity on the far side.
26
- */
27
- export declare function callerIdentityEnv(caller: Pick<CallerIdentity, 'sessionId' | 'launchId'>): Record<string, string>;
28
- /**
29
- * True when a live task belongs to this caller. Match on sessionId or
30
- * launchId — either is enough. A task with no recorded identity never
31
- * matches a caller that has one (and vice versa for the no-identity case
32
- * handled separately by the resolver).
33
- */
34
- export declare function taskMatchesCaller(task: {
35
- sessionId?: string;
36
- launchId?: string;
37
- }, caller: {
38
- sessionId?: string;
39
- launchId?: string;
40
- }): boolean;
@@ -1,175 +0,0 @@
1
- /**
2
- * Resolve the agent identity of whoever invoked `agents browser`.
3
- *
4
- * The browser daemon is shared and long-lived, so identity must be captured in
5
- * the CLI process and forwarded over IPC. Order:
6
- *
7
- * 1. Env already set by `agents run` (`AGENT_SESSION_ID` / `AGENT_LAUNCH_ID`)
8
- * 2. Session-tracker state file under `~/.agents/.cache/terminals/sessions/`
9
- * (and the deployed fleet path under `state/sessions/`), keyed by
10
- * process.ppid and walked up the ancestor chain
11
- * 3. Process-table anchor — nearest ancestor whose comm maps to a known
12
- * harness via `agentKindFromComm` (derived from SESSION_AGENTS)
13
- *
14
- * No per-harness env-var table: the state-file reader and the process-table
15
- * classifier cover every harness by construction.
16
- */
17
- import { execFileSync } from 'child_process';
18
- import { resolveActor } from '../actor.js';
19
- import { agentKindFromComm } from '../session/active.js';
20
- import { loadHookSessionIndex, readStateSessionRecord, } from '../session/hook-sessions.js';
21
- const MAX_ANCESTOR_WALK = 16;
22
- /**
23
- * Read pid→ppid→comm for one process. Returns null when the process is gone
24
- * or `ps` fails.
25
- */
26
- function readProc(pid) {
27
- if (!pid || pid <= 1)
28
- return null;
29
- try {
30
- const out = execFileSync('ps', ['-p', String(pid), '-o', 'pid=,ppid=,comm='], {
31
- encoding: 'utf8',
32
- timeout: 1000,
33
- }).trim();
34
- const m = out.match(/^(\d+)\s+(\d+)\s+(.+)$/);
35
- if (!m)
36
- return null;
37
- return {
38
- pid: parseInt(m[1], 10),
39
- ppid: parseInt(m[2], 10),
40
- comm: m[3].trim(),
41
- };
42
- }
43
- catch {
44
- return null;
45
- }
46
- }
47
- /**
48
- * Walk ancestors starting at `startPid` (inclusive). Yields each pid once.
49
- */
50
- function* ancestorPids(startPid) {
51
- let cur = startPid;
52
- const seen = new Set();
53
- for (let i = 0; i < MAX_ANCESTOR_WALK && cur > 1 && !seen.has(cur); i++) {
54
- seen.add(cur);
55
- yield cur;
56
- const proc = readProc(cur);
57
- if (!proc)
58
- return;
59
- cur = proc.ppid;
60
- }
61
- }
62
- /**
63
- * Look up a session-tracker / deployed-hook state record for `pid`.
64
- * Prefers the richer terminals/sessions index; falls back to the fleet
65
- * state/sessions path (RUSH-2007).
66
- */
67
- function stateForPid(pid, index) {
68
- const fromIndex = index.byPid.get(pid);
69
- if (fromIndex?.session_id)
70
- return fromIndex;
71
- return readStateSessionRecord(pid);
72
- }
73
- /**
74
- * Resolve caller identity once per CLI process for browser IPC stamping.
75
- *
76
- * Starts from `process.ppid` — the shell or harness that launched this
77
- * `agents browser` invocation — and walks up until a state file or known
78
- * agent comm is found.
79
- */
80
- export function resolveCallerIdentity(env = process.env) {
81
- const actor = resolveActor().id;
82
- let sessionId = env.AGENT_SESSION_ID || env.AGENTS_SESSION_ID || undefined;
83
- let launchId = env.AGENT_LAUNCH_ID || undefined;
84
- let agentPid;
85
- if (sessionId && launchId) {
86
- return { actor, sessionId, launchId };
87
- }
88
- // Start at ppid: when an agent runs a Bash tool call, the browser CLI's
89
- // parent is that shell (or the agent itself when launched directly).
90
- const startPid = typeof process.ppid === 'number' && process.ppid > 0 ? process.ppid : 0;
91
- if (startPid > 0) {
92
- let index;
93
- try {
94
- index = loadHookSessionIndex();
95
- }
96
- catch {
97
- index = undefined;
98
- }
99
- for (const pid of ancestorPids(startPid)) {
100
- if (index) {
101
- const rec = stateForPid(pid, index);
102
- if (rec?.session_id) {
103
- sessionId = sessionId || rec.session_id;
104
- launchId = launchId || rec.launch_id;
105
- agentPid = pid;
106
- break;
107
- }
108
- }
109
- else {
110
- const rec = readStateSessionRecord(pid);
111
- if (rec?.session_id) {
112
- sessionId = sessionId || rec.session_id;
113
- launchId = launchId || rec.launch_id;
114
- agentPid = pid;
115
- break;
116
- }
117
- }
118
- }
119
- // Process-table anchor: nearest ancestor whose comm is a known harness.
120
- // Covers harnesses with no SessionStart hook (and sessions the hook missed).
121
- //
122
- // IMPORTANT: stamp as launchId, NEVER as sessionId. A synthetic
123
- // `agent-pid:<n>` is not a real agent session UUID — if it lands in
124
- // sessionId, hygiene.taskOwnerIsGone treats it as a dead session (the
125
- // process-table session probe rejects non-UUID shapes) and reaps the
126
- // task mid-run. launchId-only tasks are never session-reaped
127
- // (hygiene.ts: launchId alone is not proof of death).
128
- if (!sessionId && !launchId) {
129
- for (const pid of ancestorPids(startPid)) {
130
- const proc = readProc(pid);
131
- if (!proc)
132
- continue;
133
- const kind = agentKindFromComm(proc.comm);
134
- if (kind) {
135
- launchId = `agent-pid:${pid}`;
136
- agentPid = pid;
137
- break;
138
- }
139
- }
140
- }
141
- }
142
- return { actor, sessionId, launchId, agentPid };
143
- }
144
- /**
145
- * The env a `browser --device` dispatch forwards so the HUB resolves the SAME
146
- * caller identity the worker would stamp locally. Without it a forwarded verb
147
- * lands on the hub with BLANK identity, and the daemon's no-identity task bucket
148
- * matches any other no-identity task — so a cold verb could attach to (or a
149
- * `done`/`stop` could close) an unrelated agent's or a human's browser. This is
150
- * the same surface-parity fix the `run --device` path already carries via
151
- * `--env AGENT_LAUNCH_ID` (remote-session-id.ts). Absent fields are omitted so a
152
- * genuinely-unidentifiable caller forwards nothing rather than an empty string
153
- * that would read as a real (blank) identity on the far side.
154
- */
155
- export function callerIdentityEnv(caller) {
156
- const env = {};
157
- if (caller.sessionId)
158
- env.AGENT_SESSION_ID = caller.sessionId;
159
- if (caller.launchId)
160
- env.AGENT_LAUNCH_ID = caller.launchId;
161
- return env;
162
- }
163
- /**
164
- * True when a live task belongs to this caller. Match on sessionId or
165
- * launchId — either is enough. A task with no recorded identity never
166
- * matches a caller that has one (and vice versa for the no-identity case
167
- * handled separately by the resolver).
168
- */
169
- export function taskMatchesCaller(task, caller) {
170
- if (caller.sessionId && task.sessionId && caller.sessionId === task.sessionId)
171
- return true;
172
- if (caller.launchId && task.launchId && caller.launchId === task.launchId)
173
- return true;
174
- return false;
175
- }
@@ -1,51 +0,0 @@
1
- import type { Readable, Writable } from 'stream';
2
- interface CDPPipeTransport {
3
- read: Readable;
4
- write: Writable;
5
- }
6
- type EventHandler = (params: Record<string, unknown>, sessionId?: string) => void;
7
- export declare function registerPipeTransport(transport: CDPPipeTransport): string;
8
- export declare class CDPClient {
9
- private ws;
10
- private pipe;
11
- private pipeBuffer;
12
- private transport;
13
- private messageId;
14
- private pending;
15
- private eventHandlers;
16
- private pipeDataHandler;
17
- private pipeErrorHandler;
18
- private pipeCloseHandler;
19
- connect(endpoint: string): Promise<void>;
20
- connectPipe(transport: CDPPipeTransport): void;
21
- send<T = unknown>(method: string, params?: Record<string, unknown>, sessionId?: string): Promise<T>;
22
- on(event: string, handler: EventHandler): void;
23
- off(event: string, handler: EventHandler): void;
24
- close(): void;
25
- get connected(): boolean;
26
- get isOpen(): boolean;
27
- private handlePipeData;
28
- private handleMessage;
29
- private handleClose;
30
- }
31
- export interface BrowserDiscovery {
32
- wsUrl: string;
33
- browser: string;
34
- }
35
- export declare class BrowserCdpConnectionError extends Error {
36
- readonly port: number;
37
- readonly profileName: string;
38
- readonly host: string;
39
- constructor(port: number, profileName?: string, host?: string);
40
- }
41
- export declare function formatBrowserCdpConnectionError(port: number, profileName?: string, host?: string): string;
42
- export declare function discoverBrowserWsUrl(port: number, host?: string, profileName?: string): Promise<BrowserDiscovery>;
43
- export declare function normalizeBrowserName(s: string): string;
44
- export declare function verifyBrowserIdentity(reported: string, expected: string, port: number, host?: string): void;
45
- export declare function listTargets(port: number, host?: string): Promise<Array<{
46
- id: string;
47
- type: string;
48
- title: string;
49
- url: string;
50
- }>>;
51
- export {};