@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,28 +0,0 @@
1
- import type { BrowserType } from './types.js';
2
- interface ChromiumNativeProfile {
3
- browser: BrowserType;
4
- /** The agents-cli profile name: `<browser>-<display-name-slug>`. */
5
- name: string;
6
- /** The browser's user-data dir (its own, never a cache dir). */
7
- userDataDir: string;
8
- /** Profile directory basename inside the user-data dir. Authoritative id. */
9
- profileDirectory: string;
10
- /** Display-only name from Local State. */
11
- displayName: string;
12
- }
13
- type ChromiumDiscoveryResult = {
14
- ok: true;
15
- profiles: ChromiumNativeProfile[];
16
- userDataDir: string;
17
- } | {
18
- ok: false;
19
- kind: 'unsupported' | 'not-installed' | 'invalid';
20
- reason: string;
21
- };
22
- /** The browser's own user-data dir on this platform, or undefined where it does not ship. */
23
- export declare function chromiumUserDataDir(browser: BrowserType): string | undefined;
24
- export declare function discoverChromiumProfilesAt(browser: BrowserType, userDataDir: string): ChromiumDiscoveryResult;
25
- export declare function discoverChromiumProfiles(browser: BrowserType): ChromiumDiscoveryResult;
26
- /** Every browser whose native profiles agents-cli discovers on this platform. */
27
- export declare function discoverableChromiumBrowsers(): BrowserType[];
28
- export {};
@@ -1,96 +0,0 @@
1
- /**
2
- * Read-only discovery of a Chromium-family browser's OWN profiles (PHNX-4042).
3
- *
4
- * Chromium keeps its profiles under one user-data dir: `Local State` lists them
5
- * in `profile.info_cache` keyed by directory (`Default`, `Profile 1`, ...) with
6
- * the display name the user sees in the profile menu. Each entry becomes one
7
- * agents-cli profile (`comet-work`, ...) pinned to that dir and directory, so
8
- * the owner and agents share ONE window per profile instead of agents spawning
9
- * a rival instance under a cache dir. Nothing here writes to the browser's
10
- * files.
11
- */
12
- import * as fs from 'node:fs';
13
- import * as os from 'node:os';
14
- import * as path from 'node:path';
15
- /** Browsers whose native profiles are discovered, and the env var that points tests at another user-data dir. */
16
- const NATIVE_CHROMIUM = {
17
- comet: { dirName: 'Comet', envOverride: 'AGENTS_COMET_DIR' },
18
- };
19
- /** The browser's own user-data dir on this platform, or undefined where it does not ship. */
20
- export function chromiumUserDataDir(browser) {
21
- const entry = NATIVE_CHROMIUM[browser];
22
- if (!entry)
23
- return undefined;
24
- const override = process.env[entry.envOverride];
25
- if (override)
26
- return path.resolve(override);
27
- if (process.platform === 'darwin') {
28
- return path.join(os.homedir(), 'Library', 'Application Support', entry.dirName);
29
- }
30
- if (process.platform === 'win32') {
31
- const local = process.env.LOCALAPPDATA ?? path.join(os.homedir(), 'AppData', 'Local');
32
- return path.join(local, entry.dirName, 'User Data');
33
- }
34
- return undefined;
35
- }
36
- function isRecord(value) {
37
- return !!value && typeof value === 'object' && !Array.isArray(value);
38
- }
39
- function slugify(value) {
40
- return value.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
41
- }
42
- export function discoverChromiumProfilesAt(browser, userDataDir) {
43
- const localState = path.join(userDataDir, 'Local State');
44
- if (!fs.existsSync(localState)) {
45
- return { ok: false, kind: 'not-installed', reason: `${browser} Local State not found: ${localState}` };
46
- }
47
- let parsed;
48
- try {
49
- parsed = JSON.parse(fs.readFileSync(localState, 'utf8'));
50
- }
51
- catch (error) {
52
- return {
53
- ok: false,
54
- kind: 'invalid',
55
- reason: error instanceof SyntaxError
56
- ? `${browser} Local State is not valid JSON`
57
- : `Cannot read ${browser} Local State: ${error instanceof Error ? error.message : String(error)}`,
58
- };
59
- }
60
- if (!isRecord(parsed) || !isRecord(parsed.profile) || !isRecord(parsed.profile.info_cache)) {
61
- return { ok: false, kind: 'invalid', reason: `${browser} Local State has no profile.info_cache map` };
62
- }
63
- const rows = [];
64
- for (const [profileDirectory, value] of Object.entries(parsed.profile.info_cache)) {
65
- if (!isRecord(value) || typeof value.name !== 'string' || value.name.trim() === '') {
66
- return { ok: false, kind: 'invalid', reason: `${browser} Local State profile ${JSON.stringify(profileDirectory)} has no non-empty name` };
67
- }
68
- rows.push({
69
- browser,
70
- name: `${browser}-${slugify(value.name) || 'profile'}`,
71
- userDataDir,
72
- profileDirectory,
73
- displayName: value.name,
74
- });
75
- }
76
- // Two profiles with the same display name stay distinct by their directory.
77
- const counts = new Map();
78
- for (const row of rows)
79
- counts.set(row.name, (counts.get(row.name) ?? 0) + 1);
80
- return {
81
- ok: true,
82
- userDataDir,
83
- profiles: rows.map((row) => (counts.get(row.name) ?? 0) > 1 ? { ...row, name: `${row.name}-${slugify(row.profileDirectory)}` } : row),
84
- };
85
- }
86
- export function discoverChromiumProfiles(browser) {
87
- const userDataDir = chromiumUserDataDir(browser);
88
- if (!userDataDir) {
89
- return { ok: false, kind: 'unsupported', reason: `${browser} profiles are not discovered on this platform` };
90
- }
91
- return discoverChromiumProfilesAt(browser, userDataDir);
92
- }
93
- /** Every browser whose native profiles agents-cli discovers on this platform. */
94
- export function discoverableChromiumBrowsers() {
95
- return Object.keys(NATIVE_CHROMIUM).filter((browser) => chromiumUserDataDir(browser) !== undefined);
96
- }
@@ -1,34 +0,0 @@
1
- import type { DeviceDescriptor } from './types.js';
2
- /**
3
- * Default viewport for newly-created profiles. Matches Safari's logical
4
- * resolution on a 14-inch MacBook Pro (M1/M2/M3 Pro/Max) — the most common
5
- * shape this CLI sees in practice. Shared with the `MacBook Pro` device
6
- * preset below so both surfaces agree.
7
- */
8
- export declare const DEFAULT_VIEWPORT: {
9
- readonly width: 1512;
10
- readonly height: 982;
11
- readonly deviceScaleFactor: 2;
12
- };
13
- export declare const DEVICES: Record<string, DeviceDescriptor>;
14
- export declare function getDevice(name: string): DeviceDescriptor | undefined;
15
- export declare function listDevices(): string[];
16
- /**
17
- * Parse a `--window WxH` value. Returns null when the value is malformed, so
18
- * callers emit their own actionable error.
19
- *
20
- * Shared by `profiles create` and `profiles edit` — one regex, one test, no
21
- * drift between the two surfaces.
22
- */
23
- export declare function parseWindowSize(raw: string): {
24
- width: number;
25
- height: number;
26
- } | null;
27
- /**
28
- * Parse a `--position X,Y` value. Negative coordinates are valid — a window may
29
- * sit on a display left of or above the primary one.
30
- */
31
- export declare function parseWindowPosition(raw: string): {
32
- x: number;
33
- y: number;
34
- } | null;
@@ -1,61 +0,0 @@
1
- /**
2
- * Default viewport for newly-created profiles. Matches Safari's logical
3
- * resolution on a 14-inch MacBook Pro (M1/M2/M3 Pro/Max) — the most common
4
- * shape this CLI sees in practice. Shared with the `MacBook Pro` device
5
- * preset below so both surfaces agree.
6
- */
7
- export const DEFAULT_VIEWPORT = {
8
- width: 1512,
9
- height: 982,
10
- deviceScaleFactor: 2,
11
- };
12
- export const DEVICES = {
13
- 'iPhone 14': {
14
- width: 390,
15
- height: 844,
16
- deviceScaleFactor: 3,
17
- mobile: true,
18
- },
19
- 'iPad': {
20
- width: 768,
21
- height: 1024,
22
- deviceScaleFactor: 2,
23
- mobile: true,
24
- },
25
- 'MacBook Pro': {
26
- width: DEFAULT_VIEWPORT.width,
27
- height: DEFAULT_VIEWPORT.height,
28
- deviceScaleFactor: DEFAULT_VIEWPORT.deviceScaleFactor,
29
- mobile: false,
30
- },
31
- };
32
- export function getDevice(name) {
33
- const key = Object.keys(DEVICES).find((k) => k.toLowerCase() === name.toLowerCase());
34
- return key ? DEVICES[key] : undefined;
35
- }
36
- export function listDevices() {
37
- return Object.keys(DEVICES);
38
- }
39
- /**
40
- * Parse a `--window WxH` value. Returns null when the value is malformed, so
41
- * callers emit their own actionable error.
42
- *
43
- * Shared by `profiles create` and `profiles edit` — one regex, one test, no
44
- * drift between the two surfaces.
45
- */
46
- export function parseWindowSize(raw) {
47
- const m = String(raw).match(/^(\d+)x(\d+)$/);
48
- if (!m)
49
- return null;
50
- return { width: parseInt(m[1], 10), height: parseInt(m[2], 10) };
51
- }
52
- /**
53
- * Parse a `--position X,Y` value. Negative coordinates are valid — a window may
54
- * sit on a display left of or above the primary one.
55
- */
56
- export function parseWindowPosition(raw) {
57
- const m = String(raw).match(/^(-?\d+),(-?\d+)$/);
58
- if (!m)
59
- return null;
60
- return { x: parseInt(m[1], 10), y: parseInt(m[2], 10) };
61
- }
@@ -1,71 +0,0 @@
1
- /**
2
- * Domain-skill discovery for `agents browser start`.
3
- *
4
- * When a browser task opens a URL, look up a site-specific SKILL.md from
5
- * `skills/browser/domain-skills/<dir>/SKILL.md` in the layered DotAgents
6
- * repos — project > user > system, first layer with a match wins, the same
7
- * precedence `resolveResource` in `../resources.ts` applies — and surface its
8
- * contents so the calling agent gets per-site operating instructions
9
- * (selectors, gotchas, sign-in quirks) before it starts driving the page.
10
- *
11
- * Matching is intentionally simple: derive the hostname's second-level
12
- * label (e.g. `perplexity` from `perplexity.ai`, `slack` from `app.slack.com`)
13
- * and look for a directory of the same name. If the user wants a different
14
- * mapping (e.g. `mail.google.com` -> `gmail/`), they can pin it via a
15
- * `domains: [...]` array in the SKILL.md frontmatter; that override beats
16
- * the directory-name match.
17
- */
18
- /** Result of resolving a URL to a domain-skill. */
19
- export interface ResolvedDomainSkill {
20
- /** Skill identifier — the directory name under domain-skills/. */
21
- name: string;
22
- /** Absolute path to the SKILL.md that was matched. */
23
- path: string;
24
- /** Full SKILL.md contents (frontmatter included). */
25
- content: string;
26
- /** Hostname the match was made against (post-www strip). */
27
- hostname: string;
28
- }
29
- /**
30
- * Where domain-skills live, in precedence order: project > user > system >
31
- * extra repos — the same layering `resolveResource` applies. A layer whose
32
- * root does not exist is simply skipped at resolve time.
33
- *
34
- * The project layer resolves from `cwd` (default `process.cwd()`). The
35
- * browser daemon is shared and long-lived, and its IPC request does not yet
36
- * carry the calling CLI's cwd, so at that call site the project layer follows
37
- * the daemon's own cwd until the caller's cwd is threaded through
38
- * (RUSH-2996); user/system/extra-repo layers are cwd-independent.
39
- *
40
- * $AGENTS_BROWSER_DOMAIN_SKILLS_DIR overrides the whole list with a single
41
- * root, for tests.
42
- */
43
- export declare function domainSkillsRoots(cwd?: string): string[];
44
- /**
45
- * Derive match candidates from a hostname. Order matters — earlier candidates
46
- * are tried first.
47
- *
48
- * Examples:
49
- * perplexity.ai -> ['perplexity.ai', 'perplexity']
50
- * app.slack.com -> ['app.slack.com', 'slack.com', 'slack']
51
- * mail.google.com -> ['mail.google.com', 'google.com', 'google', 'mail']
52
- * higgsfield.ai -> ['higgsfield.ai', 'higgsfield']
53
- */
54
- export declare function hostnameMatchCandidates(hostname: string): string[];
55
- /**
56
- * Resolve a URL to its matching domain-skill, or null if none.
57
- *
58
- * Roots are searched in `domainSkillsRoots` order (project > user > system);
59
- * the first layer with a match wins outright — an earlier layer's
60
- * directory-name match beats a later layer's `domains:` pin, mirroring
61
- * `resolveResource`'s layer precedence. Within one layer, two passes:
62
- * 1. Index every SKILL.md in the root and read its `domains:` frontmatter.
63
- * If any pinned domain matches a candidate, return that skill.
64
- * 2. Fall back to directory-name match against the candidate list.
65
- *
66
- * Errors (missing root, unreadable file, invalid URL) are swallowed and
67
- * yield null — domain-skill discovery must never break browser start. A miss
68
- * logs the roots searched at debug level (AGENTS_DEBUG/DEBUG) so a skill
69
- * sitting in an unsearched layer is diagnosable rather than silent.
70
- */
71
- export declare function resolveDomainSkill(url: string, cwd?: string): ResolvedDomainSkill | null;
@@ -1,195 +0,0 @@
1
- /**
2
- * Domain-skill discovery for `agents browser start`.
3
- *
4
- * When a browser task opens a URL, look up a site-specific SKILL.md from
5
- * `skills/browser/domain-skills/<dir>/SKILL.md` in the layered DotAgents
6
- * repos — project > user > system, first layer with a match wins, the same
7
- * precedence `resolveResource` in `../resources.ts` applies — and surface its
8
- * contents so the calling agent gets per-site operating instructions
9
- * (selectors, gotchas, sign-in quirks) before it starts driving the page.
10
- *
11
- * Matching is intentionally simple: derive the hostname's second-level
12
- * label (e.g. `perplexity` from `perplexity.ai`, `slack` from `app.slack.com`)
13
- * and look for a directory of the same name. If the user wants a different
14
- * mapping (e.g. `mail.google.com` -> `gmail/`), they can pin it via a
15
- * `domains: [...]` array in the SKILL.md frontmatter; that override beats
16
- * the directory-name match.
17
- */
18
- import * as fs from 'fs';
19
- import * as path from 'path';
20
- import { getEnabledExtraRepos, getProjectAgentsDir, getSystemAgentsDir, getUserAgentsDir, } from '../state.js';
21
- /**
22
- * Where domain-skills live, in precedence order: project > user > system >
23
- * extra repos — the same layering `resolveResource` applies. A layer whose
24
- * root does not exist is simply skipped at resolve time.
25
- *
26
- * The project layer resolves from `cwd` (default `process.cwd()`). The
27
- * browser daemon is shared and long-lived, and its IPC request does not yet
28
- * carry the calling CLI's cwd, so at that call site the project layer follows
29
- * the daemon's own cwd until the caller's cwd is threaded through
30
- * (RUSH-2996); user/system/extra-repo layers are cwd-independent.
31
- *
32
- * $AGENTS_BROWSER_DOMAIN_SKILLS_DIR overrides the whole list with a single
33
- * root, for tests.
34
- */
35
- export function domainSkillsRoots(cwd) {
36
- const override = process.env.AGENTS_BROWSER_DOMAIN_SKILLS_DIR;
37
- if (override)
38
- return [override];
39
- const sub = ['skills', 'browser', 'domain-skills'];
40
- const roots = [];
41
- const projectDir = getProjectAgentsDir(cwd);
42
- if (projectDir)
43
- roots.push(path.join(projectDir, ...sub));
44
- roots.push(path.join(getUserAgentsDir(), ...sub));
45
- roots.push(path.join(getSystemAgentsDir(), ...sub));
46
- for (const extra of getEnabledExtraRepos()) {
47
- roots.push(path.join(extra.dir, ...sub));
48
- }
49
- return roots;
50
- }
51
- /**
52
- * Derive match candidates from a hostname. Order matters — earlier candidates
53
- * are tried first.
54
- *
55
- * Examples:
56
- * perplexity.ai -> ['perplexity.ai', 'perplexity']
57
- * app.slack.com -> ['app.slack.com', 'slack.com', 'slack']
58
- * mail.google.com -> ['mail.google.com', 'google.com', 'google', 'mail']
59
- * higgsfield.ai -> ['higgsfield.ai', 'higgsfield']
60
- */
61
- export function hostnameMatchCandidates(hostname) {
62
- const cleaned = hostname.toLowerCase().replace(/^www\./, '');
63
- if (!cleaned)
64
- return [];
65
- const parts = cleaned.split('.').filter(Boolean);
66
- const out = new Set();
67
- out.add(cleaned);
68
- // Progressive label-stripping from the left: app.slack.com -> slack.com.
69
- for (let i = 1; i < parts.length; i++) {
70
- out.add(parts.slice(i).join('.'));
71
- }
72
- // Second-level label without TLD: app.slack.com -> slack, perplexity.ai -> perplexity.
73
- if (parts.length >= 2) {
74
- out.add(parts[parts.length - 2]);
75
- }
76
- // First label too, so mail.google.com can resolve a `mail` dir if that's how
77
- // the user organized their skills. Last so explicit second-level wins.
78
- if (parts.length >= 2) {
79
- out.add(parts[0]);
80
- }
81
- return Array.from(out);
82
- }
83
- /** Parse a SKILL.md's frontmatter `domains:` list, if any. Best-effort, no schema. */
84
- function parseDomainsFrontmatter(content) {
85
- // Frontmatter must be at file start: ---\n...\n---\n
86
- if (!content.startsWith('---'))
87
- return [];
88
- const end = content.indexOf('\n---', 3);
89
- if (end < 0)
90
- return [];
91
- const fm = content.slice(3, end);
92
- // Inline array form: domains: [a, b, c]
93
- const inline = fm.match(/^domains:\s*\[([^\]]*)\]/m);
94
- if (inline) {
95
- return inline[1]
96
- .split(',')
97
- .map((s) => s.trim().replace(/^["']|["']$/g, '').toLowerCase())
98
- .filter(Boolean);
99
- }
100
- // Block list form:
101
- // domains:
102
- // - a
103
- // - b
104
- const block = fm.match(/^domains:\s*\n((?:\s+-\s+\S+\n?)+)/m);
105
- if (block) {
106
- return block[1]
107
- .split('\n')
108
- .map((line) => line.replace(/^\s*-\s*/, '').trim().replace(/^["']|["']$/g, '').toLowerCase())
109
- .filter(Boolean);
110
- }
111
- return [];
112
- }
113
- /** Stderr debug line, gated on AGENTS_DEBUG/DEBUG — same convention as `../teams/debug.ts`. */
114
- function debug(message) {
115
- if (process.env.AGENTS_DEBUG || process.env.DEBUG)
116
- console.error(message);
117
- }
118
- /**
119
- * Resolve a URL to its matching domain-skill, or null if none.
120
- *
121
- * Roots are searched in `domainSkillsRoots` order (project > user > system);
122
- * the first layer with a match wins outright — an earlier layer's
123
- * directory-name match beats a later layer's `domains:` pin, mirroring
124
- * `resolveResource`'s layer precedence. Within one layer, two passes:
125
- * 1. Index every SKILL.md in the root and read its `domains:` frontmatter.
126
- * If any pinned domain matches a candidate, return that skill.
127
- * 2. Fall back to directory-name match against the candidate list.
128
- *
129
- * Errors (missing root, unreadable file, invalid URL) are swallowed and
130
- * yield null — domain-skill discovery must never break browser start. A miss
131
- * logs the roots searched at debug level (AGENTS_DEBUG/DEBUG) so a skill
132
- * sitting in an unsearched layer is diagnosable rather than silent.
133
- */
134
- export function resolveDomainSkill(url, cwd) {
135
- let hostname;
136
- try {
137
- hostname = new URL(url).hostname;
138
- }
139
- catch {
140
- return null;
141
- }
142
- if (!hostname)
143
- return null;
144
- const candidates = hostnameMatchCandidates(hostname);
145
- if (candidates.length === 0)
146
- return null;
147
- const candidateSet = new Set(candidates);
148
- const roots = domainSkillsRoots(cwd);
149
- for (const root of roots) {
150
- let entries;
151
- try {
152
- entries = fs.readdirSync(root, { withFileTypes: true });
153
- }
154
- catch {
155
- continue;
156
- }
157
- const indexed = [];
158
- for (const e of entries) {
159
- if (!e.isDirectory())
160
- continue;
161
- const skillPath = path.join(root, e.name, 'SKILL.md');
162
- let content;
163
- try {
164
- content = fs.readFileSync(skillPath, 'utf-8');
165
- }
166
- catch {
167
- continue;
168
- }
169
- indexed.push({
170
- name: e.name,
171
- skillPath,
172
- content,
173
- pinned: parseDomainsFrontmatter(content),
174
- });
175
- }
176
- // Pass 1: explicit `domains:` overrides.
177
- for (const s of indexed) {
178
- for (const d of s.pinned) {
179
- if (candidateSet.has(d)) {
180
- return { name: s.name, path: s.skillPath, content: s.content, hostname };
181
- }
182
- }
183
- }
184
- // Pass 2: directory-name match, walking candidates in priority order.
185
- const byName = new Map(indexed.map((s) => [s.name.toLowerCase(), s]));
186
- for (const c of candidates) {
187
- const hit = byName.get(c);
188
- if (hit) {
189
- return { name: hit.name, path: hit.skillPath, content: hit.content, hostname };
190
- }
191
- }
192
- }
193
- debug(`[browser] no domain-skill for ${hostname}; searched: ${roots.join(', ')}`);
194
- return null;
195
- }
@@ -1,40 +0,0 @@
1
- export interface ArcNativeTabRef {
2
- windowId: string;
3
- spaceId: string;
4
- tabId: string;
5
- }
6
- interface ArcNativeTab extends ArcNativeTabRef {
7
- url: string;
8
- title: string;
9
- }
10
- export interface ArcEnumeratedSpace {
11
- windowId: string;
12
- spaceId: string;
13
- spaceTitle: string;
14
- activeTabId?: string;
15
- tabs: ArcNativeTab[];
16
- }
17
- export declare class ArcNativeCapabilityError extends Error {
18
- readonly capability: string;
19
- constructor(capability: string, message?: string);
20
- }
21
- export declare function isArcRunning(): Promise<boolean>;
22
- export declare function enumerateArcSpaces(): Promise<ArcEnumeratedSpace[]>;
23
- /** Caller durably records marker intent before calling; never use a real page URL as ownership. */
24
- export declare function createArcTab(target: Pick<ArcNativeTabRef, 'windowId' | 'spaceId'>, markerUrl: string): Promise<ArcNativeTab>;
25
- export declare function resolveArcTab(ref: ArcNativeTabRef): Promise<ArcNativeTab | null>;
26
- export declare function navigateArcTab(ref: ArcNativeTabRef, url: string): Promise<void>;
27
- /** Arc serializes a returned object once. JSON.stringify at the top level would double-encode. */
28
- export declare function executeJavaScript(ref: ArcNativeTabRef, expression: string): Promise<unknown>;
29
- export declare function closeArcTab(ref: ArcNativeTabRef): Promise<'closed' | 'missing'>;
30
- /** Explicit user-facing focus only. Evaluation and cleanup never invoke this. */
31
- export declare function selectArcTab(ref: ArcNativeTabRef): Promise<void>;
32
- /**
33
- * Select `tabId` wherever it lives in window `windowId` (any Space). Used to put
34
- * the owner back on their tab after a creation that failed mid-way, when there is
35
- * no owned tab to check against. Returns false when the tab is gone.
36
- */
37
- export declare function selectWindowTab(windowId: string, tabId: string): Promise<boolean>;
38
- /** Restore only while the task's new tab is still selected; preserve a later human choice. */
39
- export declare function restoreArcSelection(owned: ArcNativeTabRef, previousTabId: string): Promise<boolean>;
40
- export {};