@phnx-labs/agents-cli 1.22.116 → 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.
- package/CHANGELOG.md +247 -0
- package/dist/bootstrap.js +4 -11
- package/dist/commands/browser.d.ts +52 -70
- package/dist/commands/browser.js +192 -3562
- package/dist/commands/daemon.d.ts +39 -2
- package/dist/commands/daemon.js +72 -73
- package/dist/commands/events.js +1 -1
- package/dist/commands/exec.d.ts +18 -0
- package/dist/commands/exec.js +104 -12
- package/dist/commands/repo.js +13 -49
- package/dist/commands/route.js +5 -5
- package/dist/commands/routines.js +39 -12
- package/dist/commands/sessions-render.d.ts +1 -1
- package/dist/commands/sessions-render.js +0 -1
- package/dist/commands/sessions.test-fixture.d.ts +0 -1
- package/dist/commands/sessions.test-fixture.js +0 -37
- package/dist/commands/setup-browser.d.ts +17 -12
- package/dist/commands/setup-browser.js +52 -87
- package/dist/commands/setup-preferences.d.ts +0 -17
- package/dist/commands/setup-preferences.js +18 -49
- package/dist/commands/setup-term.d.ts +4 -3
- package/dist/commands/setup-term.js +5 -4
- package/dist/commands/setup.js +11 -11
- package/dist/commands/ssh.js +10 -1
- package/dist/commands/sync.js +6 -44
- package/dist/commands/teams.js +0 -1
- package/dist/commands/update.d.ts +19 -0
- package/dist/commands/update.js +34 -6
- package/dist/commands/view.d.ts +12 -1
- package/dist/commands/view.js +47 -2
- package/dist/index.js +107 -26
- package/dist/lib/account-capabilities.js +0 -2
- package/dist/lib/account-catalog.d.ts +38 -0
- package/dist/lib/account-catalog.js +110 -26
- package/dist/lib/account-provider-registry.js +1 -1
- package/dist/lib/account-registry.d.ts +1 -1
- package/dist/lib/account-registry.js +36 -2
- package/dist/lib/accounting/rotate.js +22 -8
- package/dist/lib/accounting/usage-ingest.d.ts +6 -1
- package/dist/lib/accounting/usage-ingest.js +115 -45
- package/dist/lib/accounting/usage-sync.d.ts +134 -31
- package/dist/lib/accounting/usage-sync.js +227 -66
- package/dist/lib/accounting/usage.d.ts +16 -3
- package/dist/lib/accounting/usage.js +26 -8
- package/dist/lib/accounts/slots.d.ts +8 -0
- package/dist/lib/accounts/slots.js +17 -0
- package/dist/lib/add-dir.js +0 -1
- package/dist/lib/agent-cli-commands.js +0 -1
- package/dist/lib/agent-spec/agents.d.ts +6 -7
- package/dist/lib/agent-spec/agents.js +6 -60
- package/dist/lib/auth-health.d.ts +69 -1
- package/dist/lib/auth-health.js +133 -4
- package/dist/lib/browser/context.d.ts +82 -0
- package/dist/lib/browser/context.js +88 -0
- package/dist/lib/browser/paths.d.ts +25 -0
- package/dist/lib/browser/paths.js +51 -0
- package/dist/lib/browser/record.d.ts +38 -0
- package/dist/lib/browser/record.js +57 -0
- package/dist/lib/browser/sessions-list.js +1 -2
- package/dist/lib/browser-client.d.ts +158 -0
- package/dist/lib/browser-client.js +234 -0
- package/dist/lib/channels/owner-sink.d.ts +1 -18
- package/dist/lib/channels/owner-sink.js +29 -82
- package/dist/lib/channels/providers/rush.d.ts +7 -7
- package/dist/lib/channels/providers/rush.js +127 -57
- package/dist/lib/claude-statusline.d.ts +1 -1
- package/dist/lib/claude-statusline.js +15 -3
- package/dist/lib/commands.js +1 -1
- package/dist/lib/crabbox/lease.js +1 -1
- package/dist/lib/crabbox/runtimes.js +1 -3
- package/dist/lib/daemon/account-state-daemon-service.js +1 -0
- package/dist/lib/daemon/auth-sync-service.d.ts +21 -18
- package/dist/lib/daemon/auth-sync-service.js +37 -43
- package/dist/lib/daemon/daemon.d.ts +25 -14
- package/dist/lib/daemon/daemon.js +92 -154
- package/dist/lib/daemon/runner.d.ts +2 -2
- package/dist/lib/daemon/runner.js +32 -9
- package/dist/lib/daemon/self-update-service.d.ts +35 -34
- package/dist/lib/daemon/self-update-service.js +40 -36
- package/dist/lib/daemon/service.d.ts +12 -8
- package/dist/lib/daemon/supervisor.d.ts +65 -54
- package/dist/lib/daemon/supervisor.js +136 -171
- package/dist/lib/daemon/testdata/process-view-start.js +5 -2
- package/dist/lib/daemon/usage-sync-service.d.ts +21 -30
- package/dist/lib/daemon/usage-sync-service.js +46 -78
- package/dist/lib/daemon-health.d.ts +22 -5
- package/dist/lib/daemon-health.js +47 -3
- package/dist/lib/daemon-services.d.ts +1 -1
- package/dist/lib/daemon-services.js +0 -10
- package/dist/lib/daemon-ticks.js +4 -2
- package/dist/lib/devices/doctor-findings.js +8 -11
- package/dist/lib/devices/harness-inventory.js +14 -5
- package/dist/lib/exec-account-home.js +5 -0
- package/dist/lib/exec.js +0 -11
- package/dist/lib/feed/events.js +0 -1
- package/dist/lib/feed/tool-activity.js +5 -2
- package/dist/lib/fleet-shared-state.d.ts +45 -0
- package/dist/lib/fleet-shared-state.js +78 -9
- package/dist/lib/fs-atomic.js +25 -0
- package/dist/lib/harness-auth-capabilities.js +0 -1
- package/dist/lib/helper-versions.js +1 -1
- package/dist/lib/hooks/cache.d.ts +7 -0
- package/dist/lib/hooks/cache.js +27 -2
- package/dist/lib/hooks/install.js +7 -1
- package/dist/lib/hosts/ready.d.ts +38 -8
- package/dist/lib/hosts/ready.js +62 -14
- package/dist/lib/hosts/remote-cmd.js +1 -0
- package/dist/lib/installations/active-check.d.ts +27 -0
- package/dist/lib/installations/active-check.js +61 -0
- package/dist/lib/installations/migrate.js +6 -3
- package/dist/lib/installations/shims.js +9 -7
- package/dist/lib/installations/update.js +21 -15
- package/dist/lib/installations/versions.js +12 -1
- package/dist/lib/manifest.js +1 -1
- package/dist/lib/models.js +0 -2
- package/dist/lib/open-url.js +28 -54
- package/dist/lib/placement.d.ts +2 -0
- package/dist/lib/placement.js +5 -0
- package/dist/lib/profiles.js +0 -2
- package/dist/lib/refresh.js +1 -1
- package/dist/lib/routine-readiness.d.ts +35 -0
- package/dist/lib/routine-readiness.js +74 -16
- package/dist/lib/rules/compile.js +6 -0
- package/dist/lib/sandbox.js +0 -2
- package/dist/lib/secrets-policy.d.ts +89 -11
- package/dist/lib/secrets-policy.js +175 -28
- package/dist/lib/session/db.d.ts +1 -1
- package/dist/lib/session/db.js +65 -18
- package/dist/lib/session/discover.js +1 -283
- package/dist/lib/session/mirror.d.ts +4 -3
- package/dist/lib/session/mirror.js +4 -3
- package/dist/lib/session/parse.d.ts +0 -2
- package/dist/lib/session/parse.js +1 -138
- package/dist/lib/session/throughput.d.ts +1 -3
- package/dist/lib/session/throughput.js +0 -20
- package/dist/lib/session/types.d.ts +2 -2
- package/dist/lib/session/types.js +2 -2
- package/dist/lib/sessions-client.d.ts +60 -1
- package/dist/lib/sessions-client.js +227 -4
- package/dist/lib/setup-tool-status.js +8 -12
- package/dist/lib/signin-badge.d.ts +3 -2
- package/dist/lib/signin-badge.js +6 -3
- package/dist/lib/smart-launch.js +4 -1
- package/dist/lib/staleness/detectors/commands.d.ts +1 -1
- package/dist/lib/staleness/detectors/hooks.d.ts +1 -1
- package/dist/lib/staleness/detectors/mcp.d.ts +1 -1
- package/dist/lib/staleness/detectors/permissions.d.ts +1 -1
- package/dist/lib/staleness/detectors/plugins.d.ts +1 -1
- package/dist/lib/staleness/detectors/rules.d.ts +1 -1
- package/dist/lib/staleness/detectors/skills.d.ts +1 -1
- package/dist/lib/staleness/detectors/subagents.d.ts +1 -1
- package/dist/lib/staleness/detectors/workflows.d.ts +1 -1
- package/dist/lib/staleness/writers/commands.d.ts +1 -1
- package/dist/lib/staleness/writers/hooks.d.ts +1 -1
- package/dist/lib/staleness/writers/mcp.d.ts +1 -1
- package/dist/lib/staleness/writers/permissions.d.ts +1 -1
- package/dist/lib/staleness/writers/plugins.d.ts +1 -1
- package/dist/lib/staleness/writers/rules.d.ts +1 -1
- package/dist/lib/staleness/writers/skills.d.ts +1 -1
- package/dist/lib/staleness/writers/sources.js +5 -0
- package/dist/lib/staleness/writers/subagents.d.ts +1 -1
- package/dist/lib/staleness/writers/workflows.d.ts +1 -1
- package/dist/lib/state.d.ts +6 -4
- package/dist/lib/state.js +7 -17
- package/dist/lib/teams/parsers.d.ts +1 -1
- package/dist/lib/teams/parsers.js +1 -136
- package/dist/lib/teams/placement-probe.js +50 -15
- package/dist/lib/teams/scheduler.d.ts +7 -0
- package/dist/lib/types.d.ts +10 -1
- package/dist/lib/types.js +1 -1
- package/dist/lib/view-types.d.ts +32 -0
- package/dist/lib/watchdog/read.js +0 -1
- package/dist/lib/watchdog/rotate.js +1 -2
- package/dist/lib/watchdog/runner.js +2 -2
- package/dist/lib/watchdog/watchdog.d.ts +1 -1
- package/dist/lib/watchdog/watchdogTail.js +0 -31
- package/package.json +1 -1
- package/scripts/postinstall.js +8 -8
- package/dist/browser.d.ts +0 -2
- package/dist/browser.js +0 -17
- package/dist/commands/browser-picker.d.ts +0 -18
- package/dist/commands/browser-picker.js +0 -97
- package/dist/lib/browser/arc-discovery.d.ts +0 -52
- package/dist/lib/browser/arc-discovery.js +0 -197
- package/dist/lib/browser/arc-dom.d.ts +0 -14
- package/dist/lib/browser/arc-dom.js +0 -121
- package/dist/lib/browser/caller-identity.d.ts +0 -40
- package/dist/lib/browser/caller-identity.js +0 -175
- package/dist/lib/browser/cdp.d.ts +0 -51
- package/dist/lib/browser/cdp.js +0 -254
- package/dist/lib/browser/chrome.d.ts +0 -141
- package/dist/lib/browser/chrome.js +0 -704
- package/dist/lib/browser/chromium-discovery.d.ts +0 -28
- package/dist/lib/browser/chromium-discovery.js +0 -96
- package/dist/lib/browser/devices.d.ts +0 -34
- package/dist/lib/browser/devices.js +0 -61
- package/dist/lib/browser/domain-skills.d.ts +0 -71
- package/dist/lib/browser/domain-skills.js +0 -195
- package/dist/lib/browser/drivers/arc.d.ts +0 -40
- package/dist/lib/browser/drivers/arc.js +0 -276
- package/dist/lib/browser/drivers/firefox.d.ts +0 -99
- package/dist/lib/browser/drivers/firefox.js +0 -377
- package/dist/lib/browser/drivers/local.d.ts +0 -55
- package/dist/lib/browser/drivers/local.js +0 -266
- package/dist/lib/browser/drivers/ssh.d.ts +0 -120
- package/dist/lib/browser/drivers/ssh.js +0 -467
- package/dist/lib/browser/editor.d.ts +0 -3
- package/dist/lib/browser/editor.js +0 -50
- package/dist/lib/browser/ffmpeg.d.ts +0 -12
- package/dist/lib/browser/ffmpeg.js +0 -184
- package/dist/lib/browser/firefox-discovery.d.ts +0 -69
- package/dist/lib/browser/firefox-discovery.js +0 -162
- package/dist/lib/browser/har.d.ts +0 -85
- package/dist/lib/browser/har.js +0 -77
- package/dist/lib/browser/hygiene.d.ts +0 -97
- package/dist/lib/browser/hygiene.js +0 -153
- package/dist/lib/browser/index.d.ts +0 -5
- package/dist/lib/browser/index.js +0 -5
- package/dist/lib/browser/input.d.ts +0 -7
- package/dist/lib/browser/input.js +0 -92
- package/dist/lib/browser/ipc.d.ts +0 -204
- package/dist/lib/browser/ipc.js +0 -1453
- package/dist/lib/browser/login-detection.d.ts +0 -87
- package/dist/lib/browser/login-detection.js +0 -274
- package/dist/lib/browser/profiles.d.ts +0 -422
- package/dist/lib/browser/profiles.js +0 -1157
- package/dist/lib/browser/refs.d.ts +0 -89
- package/dist/lib/browser/refs.js +0 -191
- package/dist/lib/browser/registry.d.ts +0 -70
- package/dist/lib/browser/registry.js +0 -252
- package/dist/lib/browser/remote-control.d.ts +0 -59
- package/dist/lib/browser/remote-control.js +0 -85
- package/dist/lib/browser/resolve-target.d.ts +0 -66
- package/dist/lib/browser/resolve-target.js +0 -264
- package/dist/lib/browser/runtime-state.d.ts +0 -291
- package/dist/lib/browser/runtime-state.js +0 -584
- package/dist/lib/browser/secret-ref.d.ts +0 -10
- package/dist/lib/browser/secret-ref.js +0 -14
- package/dist/lib/browser/service.d.ts +0 -812
- package/dist/lib/browser/service.js +0 -4693
- package/dist/lib/browser/stream.d.ts +0 -17
- package/dist/lib/browser/stream.js +0 -72
- package/dist/lib/browser/task-index.d.ts +0 -78
- package/dist/lib/browser/task-index.js +0 -199
- package/dist/lib/browser/types.d.ts +0 -647
- package/dist/lib/browser/types.js +0 -61
- package/dist/lib/browser/upload.d.ts +0 -29
- package/dist/lib/browser/upload.js +0 -298
- package/dist/lib/daemon/browser-ipc-service.d.ts +0 -20
- package/dist/lib/daemon/browser-ipc-service.js +0 -46
- package/dist/lib/daemon/browser-task-reap-service.d.ts +0 -14
- package/dist/lib/daemon/browser-task-reap-service.js +0 -26
- package/dist/lib/fleet-shared-repo-sync.d.ts +0 -55
- package/dist/lib/fleet-shared-repo-sync.js +0 -490
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interactive browser task picker with preview.
|
|
3
|
-
*
|
|
4
|
-
* Powers the fuzzy-searchable task list shown by `agents browser status` in a TTY.
|
|
5
|
-
* Shows task name, profile, domains, and tab count; preview pane shows full tab list.
|
|
6
|
-
*/
|
|
7
|
-
import chalk from 'chalk';
|
|
8
|
-
import { truncate, humanDuration } from '../lib/format.js';
|
|
9
|
-
import { itemPicker } from '../lib/picker.js';
|
|
10
|
-
const DOT = chalk.gray(' · ');
|
|
11
|
-
function formatAge(ms) {
|
|
12
|
-
return humanDuration(Date.now() - ms) + ' ago';
|
|
13
|
-
}
|
|
14
|
-
/** Build the preview pane for a browser task. */
|
|
15
|
-
function buildBrowserPreview(item) {
|
|
16
|
-
const { task, profile } = item;
|
|
17
|
-
const lines = [];
|
|
18
|
-
// Line 1: Task name (ID: xxx)
|
|
19
|
-
lines.push(chalk.bold.white(`Task: ${task.name}`) + chalk.gray(` (${task.id})`));
|
|
20
|
-
// Line 2: Profile info
|
|
21
|
-
const profileParts = [chalk.cyan(profile.name)];
|
|
22
|
-
if (profile.port)
|
|
23
|
-
profileParts.push(`port ${profile.port}`);
|
|
24
|
-
if (profile.pid)
|
|
25
|
-
profileParts.push(`pid ${profile.pid}`);
|
|
26
|
-
lines.push(chalk.gray('Profile: ') + profileParts.join(DOT));
|
|
27
|
-
// Line 3: Timing
|
|
28
|
-
const started = formatAge(task.createdAt);
|
|
29
|
-
const duration = humanDuration(Date.now() - task.createdAt);
|
|
30
|
-
lines.push(chalk.gray('Started: ') + chalk.white(started) + DOT + chalk.gray('Duration: ') + chalk.white(duration));
|
|
31
|
-
// Blank line
|
|
32
|
-
lines.push('');
|
|
33
|
-
// Tabs section
|
|
34
|
-
if (task.tabs && task.tabs.length > 0) {
|
|
35
|
-
lines.push(chalk.gray('Tabs:'));
|
|
36
|
-
const termWidth = process.stdout.columns || 80;
|
|
37
|
-
const urlMax = Math.max(30, termWidth - 16);
|
|
38
|
-
for (const tab of task.tabs) {
|
|
39
|
-
const marker = tab.current ? chalk.yellow('*') : ' ';
|
|
40
|
-
const id = chalk.gray(tab.id);
|
|
41
|
-
const url = truncate(tab.url, urlMax);
|
|
42
|
-
lines.push(` ${id} ${marker} ${chalk.white(url)}`);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
lines.push(chalk.gray('No tabs open'));
|
|
47
|
-
}
|
|
48
|
-
return lines.join('\n');
|
|
49
|
-
}
|
|
50
|
-
/** Build the list label for a browser task. */
|
|
51
|
-
function buildBrowserLabel(item, query) {
|
|
52
|
-
const { task, profile } = item;
|
|
53
|
-
const termWidth = process.stdout.columns || 80;
|
|
54
|
-
// Format: name profile tabs domains age
|
|
55
|
-
const name = task.name.padEnd(20);
|
|
56
|
-
const profileName = profile.name.padEnd(12);
|
|
57
|
-
const tabs = `${task.tabCount} tab${task.tabCount === 1 ? '' : 's'}`.padEnd(8);
|
|
58
|
-
const age = formatAge(task.createdAt);
|
|
59
|
-
// Domains - fill remaining space
|
|
60
|
-
const fixedWidth = 20 + 12 + 8 + 10; // name + profile + tabs + age
|
|
61
|
-
const domainsWidth = Math.max(10, termWidth - fixedWidth - 4);
|
|
62
|
-
const domains = task.domains?.length
|
|
63
|
-
? truncate(task.domains.join(', '), domainsWidth)
|
|
64
|
-
: chalk.gray('no sites');
|
|
65
|
-
// Highlight query matches
|
|
66
|
-
let label = `${name}${chalk.cyan(profileName)}${tabs}${domains.padEnd(domainsWidth)}${chalk.gray(age)}`;
|
|
67
|
-
if (query) {
|
|
68
|
-
const re = new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
|
|
69
|
-
label = label.replace(re, chalk.yellow.bold('$1'));
|
|
70
|
-
}
|
|
71
|
-
return label;
|
|
72
|
-
}
|
|
73
|
-
/** Show an interactive browser task picker. */
|
|
74
|
-
export async function browserTaskPicker(config) {
|
|
75
|
-
const picked = await itemPicker({
|
|
76
|
-
message: config.message,
|
|
77
|
-
items: config.tasks,
|
|
78
|
-
filter: (query) => {
|
|
79
|
-
if (!query)
|
|
80
|
-
return config.tasks;
|
|
81
|
-
const q = query.toLowerCase();
|
|
82
|
-
return config.tasks.filter((t) => t.task.name.toLowerCase().includes(q) ||
|
|
83
|
-
t.profile.name.toLowerCase().includes(q) ||
|
|
84
|
-
t.task.domains?.some((d) => d.toLowerCase().includes(q)));
|
|
85
|
-
},
|
|
86
|
-
labelFor: buildBrowserLabel,
|
|
87
|
-
buildPreview: buildBrowserPreview,
|
|
88
|
-
shortIdFor: (t) => t.task.name,
|
|
89
|
-
pageSize: config.pageSize ?? 10,
|
|
90
|
-
initialSearch: config.initialSearch,
|
|
91
|
-
emptyMessage: 'No browser tasks running.',
|
|
92
|
-
enterHint: 'view tabs',
|
|
93
|
-
});
|
|
94
|
-
if (!picked)
|
|
95
|
-
return null;
|
|
96
|
-
return { task: picked.item, action: 'view' };
|
|
97
|
-
}
|
|
@@ -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;
|