@phnx-labs/agents-cli 1.22.117 → 1.22.118

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 (248) hide show
  1. package/CHANGELOG.md +235 -0
  2. package/dist/bootstrap.js +4 -11
  3. package/dist/commands/browser.d.ts +52 -70
  4. package/dist/commands/browser.js +192 -3562
  5. package/dist/commands/daemon.d.ts +39 -2
  6. package/dist/commands/daemon.js +72 -73
  7. package/dist/commands/events.js +1 -1
  8. package/dist/commands/exec.js +53 -1
  9. package/dist/commands/repo.js +13 -49
  10. package/dist/commands/route.js +5 -5
  11. package/dist/commands/routines.js +39 -12
  12. package/dist/commands/sessions-render.d.ts +1 -1
  13. package/dist/commands/sessions-render.js +0 -1
  14. package/dist/commands/sessions.test-fixture.d.ts +0 -1
  15. package/dist/commands/sessions.test-fixture.js +0 -37
  16. package/dist/commands/setup-browser.d.ts +17 -12
  17. package/dist/commands/setup-browser.js +52 -87
  18. package/dist/commands/setup-preferences.d.ts +0 -17
  19. package/dist/commands/setup-preferences.js +18 -49
  20. package/dist/commands/setup.js +9 -9
  21. package/dist/commands/ssh.js +10 -1
  22. package/dist/commands/sync.js +6 -44
  23. package/dist/commands/teams.js +0 -1
  24. package/dist/commands/update.d.ts +19 -0
  25. package/dist/commands/update.js +34 -6
  26. package/dist/commands/view.d.ts +12 -1
  27. package/dist/commands/view.js +47 -2
  28. package/dist/index.js +107 -26
  29. package/dist/lib/account-capabilities.js +0 -2
  30. package/dist/lib/account-catalog.d.ts +38 -0
  31. package/dist/lib/account-catalog.js +110 -26
  32. package/dist/lib/account-provider-registry.js +1 -1
  33. package/dist/lib/account-registry.d.ts +1 -1
  34. package/dist/lib/account-registry.js +36 -2
  35. package/dist/lib/accounting/rotate.js +22 -8
  36. package/dist/lib/accounting/usage-ingest.d.ts +6 -1
  37. package/dist/lib/accounting/usage-ingest.js +115 -45
  38. package/dist/lib/accounting/usage-sync.d.ts +134 -31
  39. package/dist/lib/accounting/usage-sync.js +227 -66
  40. package/dist/lib/accounting/usage.d.ts +16 -3
  41. package/dist/lib/accounting/usage.js +26 -8
  42. package/dist/lib/accounts/slots.d.ts +8 -0
  43. package/dist/lib/accounts/slots.js +17 -0
  44. package/dist/lib/add-dir.js +0 -1
  45. package/dist/lib/agent-cli-commands.js +0 -1
  46. package/dist/lib/agent-spec/agents.d.ts +6 -7
  47. package/dist/lib/agent-spec/agents.js +6 -60
  48. package/dist/lib/auth-health.d.ts +69 -1
  49. package/dist/lib/auth-health.js +133 -4
  50. package/dist/lib/browser/context.d.ts +82 -0
  51. package/dist/lib/browser/context.js +88 -0
  52. package/dist/lib/browser/paths.d.ts +25 -0
  53. package/dist/lib/browser/paths.js +51 -0
  54. package/dist/lib/browser/record.d.ts +38 -0
  55. package/dist/lib/browser/record.js +57 -0
  56. package/dist/lib/browser/sessions-list.js +1 -2
  57. package/dist/lib/browser-client.d.ts +158 -0
  58. package/dist/lib/browser-client.js +234 -0
  59. package/dist/lib/channels/owner-sink.d.ts +1 -18
  60. package/dist/lib/channels/owner-sink.js +29 -82
  61. package/dist/lib/channels/providers/rush.d.ts +7 -7
  62. package/dist/lib/channels/providers/rush.js +127 -57
  63. package/dist/lib/claude-statusline.d.ts +1 -1
  64. package/dist/lib/claude-statusline.js +15 -3
  65. package/dist/lib/commands.js +1 -1
  66. package/dist/lib/crabbox/lease.js +1 -1
  67. package/dist/lib/crabbox/runtimes.js +1 -3
  68. package/dist/lib/daemon/account-state-daemon-service.js +1 -0
  69. package/dist/lib/daemon/auth-sync-service.d.ts +21 -18
  70. package/dist/lib/daemon/auth-sync-service.js +37 -43
  71. package/dist/lib/daemon/daemon.d.ts +25 -14
  72. package/dist/lib/daemon/daemon.js +92 -154
  73. package/dist/lib/daemon/runner.d.ts +2 -2
  74. package/dist/lib/daemon/runner.js +32 -9
  75. package/dist/lib/daemon/self-update-service.d.ts +35 -34
  76. package/dist/lib/daemon/self-update-service.js +40 -36
  77. package/dist/lib/daemon/service.d.ts +12 -8
  78. package/dist/lib/daemon/supervisor.d.ts +65 -54
  79. package/dist/lib/daemon/supervisor.js +136 -171
  80. package/dist/lib/daemon/testdata/process-view-start.js +5 -2
  81. package/dist/lib/daemon/usage-sync-service.d.ts +21 -30
  82. package/dist/lib/daemon/usage-sync-service.js +46 -78
  83. package/dist/lib/daemon-health.d.ts +22 -5
  84. package/dist/lib/daemon-health.js +47 -3
  85. package/dist/lib/daemon-services.d.ts +1 -1
  86. package/dist/lib/daemon-services.js +0 -10
  87. package/dist/lib/daemon-ticks.js +4 -2
  88. package/dist/lib/devices/doctor-findings.js +8 -11
  89. package/dist/lib/devices/harness-inventory.js +14 -5
  90. package/dist/lib/exec-account-home.js +5 -0
  91. package/dist/lib/exec.js +0 -11
  92. package/dist/lib/feed/events.js +0 -1
  93. package/dist/lib/feed/tool-activity.js +5 -2
  94. package/dist/lib/fleet-shared-state.d.ts +45 -0
  95. package/dist/lib/fleet-shared-state.js +78 -9
  96. package/dist/lib/fs-atomic.js +25 -0
  97. package/dist/lib/harness-auth-capabilities.js +0 -1
  98. package/dist/lib/helper-versions.js +1 -1
  99. package/dist/lib/hooks/cache.d.ts +7 -0
  100. package/dist/lib/hooks/cache.js +27 -2
  101. package/dist/lib/hooks/install.js +7 -1
  102. package/dist/lib/hosts/ready.d.ts +38 -8
  103. package/dist/lib/hosts/ready.js +62 -14
  104. package/dist/lib/installations/active-check.d.ts +27 -0
  105. package/dist/lib/installations/active-check.js +61 -0
  106. package/dist/lib/installations/migrate.js +6 -3
  107. package/dist/lib/installations/shims.js +9 -7
  108. package/dist/lib/installations/update.js +21 -15
  109. package/dist/lib/installations/versions.js +12 -1
  110. package/dist/lib/manifest.js +1 -1
  111. package/dist/lib/models.js +0 -2
  112. package/dist/lib/open-url.js +28 -54
  113. package/dist/lib/profiles.js +0 -2
  114. package/dist/lib/refresh.js +1 -1
  115. package/dist/lib/routine-readiness.d.ts +35 -0
  116. package/dist/lib/routine-readiness.js +74 -16
  117. package/dist/lib/rules/compile.js +6 -0
  118. package/dist/lib/sandbox.js +0 -2
  119. package/dist/lib/secrets-policy.d.ts +89 -11
  120. package/dist/lib/secrets-policy.js +175 -28
  121. package/dist/lib/session/db.d.ts +1 -1
  122. package/dist/lib/session/db.js +65 -18
  123. package/dist/lib/session/discover.js +1 -283
  124. package/dist/lib/session/mirror.d.ts +4 -3
  125. package/dist/lib/session/mirror.js +4 -3
  126. package/dist/lib/session/parse.d.ts +0 -2
  127. package/dist/lib/session/parse.js +1 -138
  128. package/dist/lib/session/throughput.d.ts +1 -3
  129. package/dist/lib/session/throughput.js +0 -20
  130. package/dist/lib/session/types.d.ts +2 -2
  131. package/dist/lib/session/types.js +2 -2
  132. package/dist/lib/sessions-client.d.ts +60 -1
  133. package/dist/lib/sessions-client.js +227 -4
  134. package/dist/lib/setup-tool-status.js +5 -10
  135. package/dist/lib/signin-badge.d.ts +3 -2
  136. package/dist/lib/signin-badge.js +6 -3
  137. package/dist/lib/smart-launch.js +4 -1
  138. package/dist/lib/staleness/detectors/commands.d.ts +1 -1
  139. package/dist/lib/staleness/detectors/hooks.d.ts +1 -1
  140. package/dist/lib/staleness/detectors/mcp.d.ts +1 -1
  141. package/dist/lib/staleness/detectors/permissions.d.ts +1 -1
  142. package/dist/lib/staleness/detectors/plugins.d.ts +1 -1
  143. package/dist/lib/staleness/detectors/rules.d.ts +1 -1
  144. package/dist/lib/staleness/detectors/skills.d.ts +1 -1
  145. package/dist/lib/staleness/detectors/subagents.d.ts +1 -1
  146. package/dist/lib/staleness/detectors/workflows.d.ts +1 -1
  147. package/dist/lib/staleness/writers/commands.d.ts +1 -1
  148. package/dist/lib/staleness/writers/hooks.d.ts +1 -1
  149. package/dist/lib/staleness/writers/mcp.d.ts +1 -1
  150. package/dist/lib/staleness/writers/permissions.d.ts +1 -1
  151. package/dist/lib/staleness/writers/plugins.d.ts +1 -1
  152. package/dist/lib/staleness/writers/rules.d.ts +1 -1
  153. package/dist/lib/staleness/writers/skills.d.ts +1 -1
  154. package/dist/lib/staleness/writers/sources.js +5 -0
  155. package/dist/lib/staleness/writers/subagents.d.ts +1 -1
  156. package/dist/lib/staleness/writers/workflows.d.ts +1 -1
  157. package/dist/lib/state.d.ts +6 -4
  158. package/dist/lib/state.js +7 -17
  159. package/dist/lib/teams/parsers.d.ts +1 -1
  160. package/dist/lib/teams/parsers.js +1 -136
  161. package/dist/lib/teams/placement-probe.js +50 -15
  162. package/dist/lib/teams/scheduler.d.ts +7 -0
  163. package/dist/lib/types.d.ts +10 -1
  164. package/dist/lib/types.js +1 -1
  165. package/dist/lib/view-types.d.ts +32 -0
  166. package/dist/lib/watchdog/read.js +0 -1
  167. package/dist/lib/watchdog/rotate.js +1 -2
  168. package/dist/lib/watchdog/runner.js +2 -2
  169. package/dist/lib/watchdog/watchdog.d.ts +1 -1
  170. package/dist/lib/watchdog/watchdogTail.js +0 -31
  171. package/package.json +1 -1
  172. package/scripts/postinstall.js +8 -8
  173. package/dist/browser.d.ts +0 -2
  174. package/dist/browser.js +0 -17
  175. package/dist/commands/browser-picker.d.ts +0 -18
  176. package/dist/commands/browser-picker.js +0 -97
  177. package/dist/lib/browser/arc-discovery.d.ts +0 -52
  178. package/dist/lib/browser/arc-discovery.js +0 -197
  179. package/dist/lib/browser/arc-dom.d.ts +0 -14
  180. package/dist/lib/browser/arc-dom.js +0 -121
  181. package/dist/lib/browser/caller-identity.d.ts +0 -40
  182. package/dist/lib/browser/caller-identity.js +0 -175
  183. package/dist/lib/browser/cdp.d.ts +0 -51
  184. package/dist/lib/browser/cdp.js +0 -254
  185. package/dist/lib/browser/chrome.d.ts +0 -141
  186. package/dist/lib/browser/chrome.js +0 -704
  187. package/dist/lib/browser/chromium-discovery.d.ts +0 -28
  188. package/dist/lib/browser/chromium-discovery.js +0 -96
  189. package/dist/lib/browser/devices.d.ts +0 -34
  190. package/dist/lib/browser/devices.js +0 -61
  191. package/dist/lib/browser/domain-skills.d.ts +0 -71
  192. package/dist/lib/browser/domain-skills.js +0 -195
  193. package/dist/lib/browser/drivers/arc.d.ts +0 -40
  194. package/dist/lib/browser/drivers/arc.js +0 -276
  195. package/dist/lib/browser/drivers/firefox.d.ts +0 -99
  196. package/dist/lib/browser/drivers/firefox.js +0 -377
  197. package/dist/lib/browser/drivers/local.d.ts +0 -55
  198. package/dist/lib/browser/drivers/local.js +0 -266
  199. package/dist/lib/browser/drivers/ssh.d.ts +0 -120
  200. package/dist/lib/browser/drivers/ssh.js +0 -467
  201. package/dist/lib/browser/editor.d.ts +0 -3
  202. package/dist/lib/browser/editor.js +0 -50
  203. package/dist/lib/browser/ffmpeg.d.ts +0 -12
  204. package/dist/lib/browser/ffmpeg.js +0 -184
  205. package/dist/lib/browser/firefox-discovery.d.ts +0 -69
  206. package/dist/lib/browser/firefox-discovery.js +0 -162
  207. package/dist/lib/browser/har.d.ts +0 -85
  208. package/dist/lib/browser/har.js +0 -77
  209. package/dist/lib/browser/hygiene.d.ts +0 -97
  210. package/dist/lib/browser/hygiene.js +0 -153
  211. package/dist/lib/browser/index.d.ts +0 -5
  212. package/dist/lib/browser/index.js +0 -5
  213. package/dist/lib/browser/input.d.ts +0 -7
  214. package/dist/lib/browser/input.js +0 -92
  215. package/dist/lib/browser/ipc.d.ts +0 -204
  216. package/dist/lib/browser/ipc.js +0 -1453
  217. package/dist/lib/browser/login-detection.d.ts +0 -87
  218. package/dist/lib/browser/login-detection.js +0 -274
  219. package/dist/lib/browser/profiles.d.ts +0 -422
  220. package/dist/lib/browser/profiles.js +0 -1157
  221. package/dist/lib/browser/refs.d.ts +0 -89
  222. package/dist/lib/browser/refs.js +0 -191
  223. package/dist/lib/browser/registry.d.ts +0 -70
  224. package/dist/lib/browser/registry.js +0 -252
  225. package/dist/lib/browser/remote-control.d.ts +0 -59
  226. package/dist/lib/browser/remote-control.js +0 -85
  227. package/dist/lib/browser/resolve-target.d.ts +0 -66
  228. package/dist/lib/browser/resolve-target.js +0 -264
  229. package/dist/lib/browser/runtime-state.d.ts +0 -291
  230. package/dist/lib/browser/runtime-state.js +0 -584
  231. package/dist/lib/browser/secret-ref.d.ts +0 -10
  232. package/dist/lib/browser/secret-ref.js +0 -14
  233. package/dist/lib/browser/service.d.ts +0 -812
  234. package/dist/lib/browser/service.js +0 -4693
  235. package/dist/lib/browser/stream.d.ts +0 -17
  236. package/dist/lib/browser/stream.js +0 -72
  237. package/dist/lib/browser/task-index.d.ts +0 -78
  238. package/dist/lib/browser/task-index.js +0 -199
  239. package/dist/lib/browser/types.d.ts +0 -647
  240. package/dist/lib/browser/types.js +0 -61
  241. package/dist/lib/browser/upload.d.ts +0 -29
  242. package/dist/lib/browser/upload.js +0 -298
  243. package/dist/lib/daemon/browser-ipc-service.d.ts +0 -20
  244. package/dist/lib/daemon/browser-ipc-service.js +0 -46
  245. package/dist/lib/daemon/browser-task-reap-service.d.ts +0 -14
  246. package/dist/lib/daemon/browser-task-reap-service.js +0 -26
  247. package/dist/lib/fleet-shared-repo-sync.d.ts +0 -55
  248. 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 {};