@phnx-labs/agents-cli 1.22.117 → 1.22.119
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +301 -0
- package/dist/bootstrap.js +4 -11
- package/dist/commands/accounts.js +7 -4
- 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.js +53 -1
- package/dist/commands/projects.js +92 -7
- 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.js +9 -9
- 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/add.d.ts +3 -1
- package/dist/lib/accounts/add.js +24 -13
- 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 +7 -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-account-token.d.ts +7 -1
- package/dist/lib/claude-account-token.js +26 -4
- 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 +10 -13
- 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/github/pr-mergeable.d.ts +4 -2
- package/dist/lib/github/pr-mergeable.js +5 -3
- package/dist/lib/github/project-prs.d.ts +58 -3
- package/dist/lib/github/project-prs.js +205 -7
- package/dist/lib/harness/adapters/cursor.js +14 -4
- package/dist/lib/harness-auth-capabilities.d.ts +4 -3
- package/dist/lib/harness-auth-capabilities.js +1 -2
- 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/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.d.ts +1 -1
- package/dist/lib/installations/shims.js +32 -12
- package/dist/lib/installations/store.d.ts +9 -0
- package/dist/lib/installations/store.js +24 -0
- package/dist/lib/installations/update.js +21 -15
- package/dist/lib/installations/versions.js +15 -3
- 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/profiles.js +0 -2
- package/dist/lib/projects.d.ts +16 -0
- package/dist/lib/projects.js +31 -0
- 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/active.d.ts +17 -6
- package/dist/lib/session/active.js +105 -49
- 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/pid-registry.d.ts +6 -3
- package/dist/lib/session/pid-registry.js +18 -8
- package/dist/lib/session/remote/watch.d.ts +1 -1
- package/dist/lib/session/remote/watch.js +7 -3
- 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 +5 -10
- 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 +16 -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,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 {};
|