@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,812 +0,0 @@
|
|
|
1
|
-
import { CDPClient } from './cdp.js';
|
|
2
|
-
import { type DeviceProbe } from './resolve-target.js';
|
|
3
|
-
import { type ResolvedDomainSkill } from './domain-skills.js';
|
|
4
|
-
import { type Task, type TabInfo, type ProfileTabInfo, type ProfileStatus, type BrowserType, type HistoricalTask, type ReapResult, type ProfileName, type ConnectionKey } from './types.js';
|
|
5
|
-
import { type ReapOptions } from './hygiene.js';
|
|
6
|
-
import { type RefOpts, type RefNode } from './refs.js';
|
|
7
|
-
import type { TargetFilter, PageOpenResult, ArcNativeProfileIdentity, FirefoxProfileIdentity } from './types.js';
|
|
8
|
-
import { FirefoxBiDiClient } from './drivers/firefox.js';
|
|
9
|
-
type UploadMode = 'auto' | 'input' | 'drop' | 'chooser';
|
|
10
|
-
export declare function resolveScreenshotOutputPath(outputPath: string | undefined, automaticPath: string): string;
|
|
11
|
-
/**
|
|
12
|
-
* Parse a `targetFilter` string into its kind + value, or return `null`
|
|
13
|
-
* when the input is missing or malformed. Filter syntax:
|
|
14
|
-
* - `url:<substring>` — picks the first page target whose URL contains the substring
|
|
15
|
-
* - `title:<substring>` — picks the first page target whose title contains the substring
|
|
16
|
-
*
|
|
17
|
-
* The match is case-insensitive on both sides because Electron apps
|
|
18
|
-
* frequently lowercase or title-case their target metadata in unpredictable ways.
|
|
19
|
-
*/
|
|
20
|
-
export declare function parseTargetFilter(filter: string | undefined): TargetFilter | null;
|
|
21
|
-
/**
|
|
22
|
-
* Choose the CDP page target that represents the visible UI.
|
|
23
|
-
*
|
|
24
|
-
* Order:
|
|
25
|
-
* 1. If `filter` is set and parseable, narrow to page targets matching it
|
|
26
|
-
* (case-insensitive substring). Among matches, prefer one that is not in
|
|
27
|
-
* `INVISIBLE_URL_PATTERNS` — this is the tiebreaker that makes a coarse
|
|
28
|
-
* filter like `url:https://www.canva.com/` skip the background service
|
|
29
|
-
* (`https://www.canva.com/_desktop-background-service` *also* matches the
|
|
30
|
-
* substring). If every match is invisible, return the first match so the
|
|
31
|
-
* caller still gets something rather than silently falling through.
|
|
32
|
-
* An explicit filter that finds *no* match returns `undefined` — callers
|
|
33
|
-
* should surface this as an error rather than create an orphan window.
|
|
34
|
-
* 2. If `filter` is unset (or unparseable), apply the skip-invisible heuristic
|
|
35
|
-
* across all page targets.
|
|
36
|
-
* 3. As a last resort, return the first page target.
|
|
37
|
-
*/
|
|
38
|
-
export declare function pickWindowTarget<T extends {
|
|
39
|
-
type: string;
|
|
40
|
-
url?: string;
|
|
41
|
-
title?: string;
|
|
42
|
-
}>(targets: T[], filter: string | undefined): T | undefined;
|
|
43
|
-
/**
|
|
44
|
-
* Parse a `--since`/`--until` value. Accepts ISO-8601 absolute timestamps
|
|
45
|
-
* or relative offsets like `30s`, `5m`, `2h`, `1d`.
|
|
46
|
-
*/
|
|
47
|
-
export declare function parseSinceUntil(s: string): Date;
|
|
48
|
-
export declare function readNewestMatchingRemoteFileCommand(dir: string, prefix: string, tailLines: number): string;
|
|
49
|
-
export declare function readNewestMatchingFile(dir: string, prefix: string, tailLines: number): string;
|
|
50
|
-
interface BaseProfileConnection {
|
|
51
|
-
port: number;
|
|
52
|
-
pid: number;
|
|
53
|
-
electron?: boolean;
|
|
54
|
-
/**
|
|
55
|
-
* The profile's declared browser family. Load-bearing for Arc: Arc answers
|
|
56
|
-
* `Browser.getVersion` and DOES expose CDP page targets it honors `Page.navigate`
|
|
57
|
-
* on, but CRASHES on `Target.createTarget` (verified live, PR #2778), so any
|
|
58
|
-
* tab-CREATING path must refuse and drive an EXISTING tab instead rather than
|
|
59
|
-
* crash the user's Arc. See `createPageTarget` / `pickReusableTargetWithoutCreate`.
|
|
60
|
-
*/
|
|
61
|
-
browserType?: BrowserType;
|
|
62
|
-
/** Raw `url:<v>` / `title:<v>` filter copied from the profile config. */
|
|
63
|
-
targetFilter?: string;
|
|
64
|
-
/**
|
|
65
|
-
* The runtime key this connection is registered under in `this.connections`
|
|
66
|
-
* (`<profile>@<endpoint>`, plus `.<fork>` for an Electron fork; a bare name
|
|
67
|
-
* for a legacy pre-composite dir). Also keys the profile's runtime dir, so
|
|
68
|
-
* downloads and session captures land under `.cache/browser/<key>/`.
|
|
69
|
-
*/
|
|
70
|
-
key?: ConnectionKey;
|
|
71
|
-
/** The bare, user-facing profile name this connection belongs to. */
|
|
72
|
-
profile?: ProfileName;
|
|
73
|
-
forkedFrom?: ConnectionKey;
|
|
74
|
-
tasks: Map<string, Task>;
|
|
75
|
-
windowId?: string;
|
|
76
|
-
targetCache?: {
|
|
77
|
-
targets: TargetInfo[];
|
|
78
|
-
ts: number;
|
|
79
|
-
};
|
|
80
|
-
sessionCache: Map<string, string>;
|
|
81
|
-
/**
|
|
82
|
-
* Connection-specific teardown (e.g. killing the SSH tunnel for an ssh://
|
|
83
|
-
* profile). Must be called whenever the connection is removed from
|
|
84
|
-
* `this.connections`, otherwise the tunnel leaks across daemon restarts
|
|
85
|
-
* and hijacks future `cdp://127.0.0.1:N` profiles on the same local port.
|
|
86
|
-
*/
|
|
87
|
-
cleanup?: () => void;
|
|
88
|
-
}
|
|
89
|
-
interface CdpProfileConnection extends BaseProfileConnection {
|
|
90
|
-
/** Omitted only by legacy/in-process callers; absence means the CDP path. */
|
|
91
|
-
backend?: 'cdp';
|
|
92
|
-
cdp: CDPClient;
|
|
93
|
-
}
|
|
94
|
-
interface ArcProfileConnection extends BaseProfileConnection {
|
|
95
|
-
backend: 'arc-native';
|
|
96
|
-
browserType: 'arc';
|
|
97
|
-
arcProfile: ArcNativeProfileIdentity;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* A Firefox connection driven over WebDriver BiDi (PHNX-4043). No CDP socket:
|
|
101
|
-
* `bidi` is the live BiDi client, and `firefoxProfile` is the discovered
|
|
102
|
-
* profile identity. Task tab ids map to BiDi browsing-context ids.
|
|
103
|
-
*/
|
|
104
|
-
interface FirefoxProfileConnection extends BaseProfileConnection {
|
|
105
|
-
backend: 'bidi';
|
|
106
|
-
browserType: 'firefox';
|
|
107
|
-
bidi: FirefoxBiDiClient;
|
|
108
|
-
firefoxProfile: FirefoxProfileIdentity;
|
|
109
|
-
/** The BiDi session id from `session.new`. */
|
|
110
|
-
sessionId: string;
|
|
111
|
-
/** Absolute Firefox profile directory this connection is bound to. */
|
|
112
|
-
profileDir: string;
|
|
113
|
-
}
|
|
114
|
-
type ProfileConnection = CdpProfileConnection | ArcProfileConnection | FirefoxProfileConnection;
|
|
115
|
-
/** Join error lines so callers get a next command, not a dead-end message. */
|
|
116
|
-
export declare function actionable(...lines: string[]): string;
|
|
117
|
-
/**
|
|
118
|
-
* Arc DOES expose CDP page targets and honors `Page.navigate` on the ones the
|
|
119
|
-
* user already has open (measured live against Arc: 33 targets, PR #2786), so
|
|
120
|
-
* agents browser drives an attached Arc by reusing existing tabs. What it CANNOT
|
|
121
|
-
* survive is `Target.createTarget` — opening a brand-new tab crashes the user's
|
|
122
|
-
* Arc window (verified live, PR #2778). Tab creation is the one CDP-only op that
|
|
123
|
-
* fails clearly here (PHNX-2399): every tab-creating path throws this actionable
|
|
124
|
-
* error instead of crashing Arc, and steers the caller to reuse an existing
|
|
125
|
-
* tab/Space (via `--target-filter`) or to a Chromium-family browser for new tabs.
|
|
126
|
-
*/
|
|
127
|
-
export declare function arcNotDrivableError(profileName?: string): Error;
|
|
128
|
-
/** Derive a human label from an explicit title or a navigated URL. */
|
|
129
|
-
export declare function deriveTaskLabel(opts: {
|
|
130
|
-
title?: string;
|
|
131
|
-
url?: string;
|
|
132
|
-
existing?: string;
|
|
133
|
-
}): string;
|
|
134
|
-
type TargetInfo = {
|
|
135
|
-
targetId: string;
|
|
136
|
-
url?: string;
|
|
137
|
-
title?: string;
|
|
138
|
-
};
|
|
139
|
-
/** Describes a ref that was re-resolved from a drifted integer via its cached descriptor. */
|
|
140
|
-
interface HealInfo {
|
|
141
|
-
from: number;
|
|
142
|
-
to: number;
|
|
143
|
-
role: string;
|
|
144
|
-
name: string;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Resolve the identity stamped on a task at start: WHO (`owner`) and WHICH run
|
|
148
|
-
* (`launchId`). The forwarded values come from the caller's own CLI process and
|
|
149
|
-
* are authoritative — the browser daemon is shared and long-lived, so resolving
|
|
150
|
-
* the actor daemon-side (the RUSH-2020 bug) mis-attributes every task to the
|
|
151
|
-
* daemon's owner. `resolveLocalActor` is consulted ONLY when no actor was
|
|
152
|
-
* forwarded (a CLI that predates the field, mid-rollout) — never to override a
|
|
153
|
-
* forwarded one.
|
|
154
|
-
*/
|
|
155
|
-
export declare function resolveTaskIdentity(forwarded: {
|
|
156
|
-
actor?: string;
|
|
157
|
-
launchId?: string;
|
|
158
|
-
sessionId?: string;
|
|
159
|
-
}, resolveLocalActor: () => string): {
|
|
160
|
-
owner: string;
|
|
161
|
-
launchId?: string;
|
|
162
|
-
sessionId?: string;
|
|
163
|
-
};
|
|
164
|
-
interface StartOptions {
|
|
165
|
-
taskName?: string;
|
|
166
|
-
url?: string;
|
|
167
|
-
endpointName?: string;
|
|
168
|
-
skipDomainSkill?: boolean;
|
|
169
|
-
/** Always open a new tab, skipping the abandoned-task reclaim. */
|
|
170
|
-
fresh?: boolean;
|
|
171
|
-
/** Caller identity, forwarded from the CLI (see IPCRequest.actor/launchId). */
|
|
172
|
-
actor?: string;
|
|
173
|
-
launchId?: string;
|
|
174
|
-
/** Calling agent session, forwarded from the CLI (see IPCRequest.sessionId). */
|
|
175
|
-
sessionId?: string;
|
|
176
|
-
/** Whether the CALLER was dispatched here by a fleet `--device` hop. */
|
|
177
|
-
fleetRemote?: boolean;
|
|
178
|
-
/** Explicit human label (`--title`). */
|
|
179
|
-
title?: string;
|
|
180
|
-
/** Injected reachability probe — production uses ssh; tests pass a fake. */
|
|
181
|
-
probe?: DeviceProbe;
|
|
182
|
-
}
|
|
183
|
-
interface StartResult {
|
|
184
|
-
task: string;
|
|
185
|
-
name: string;
|
|
186
|
-
tabId?: string;
|
|
187
|
-
windowId?: string;
|
|
188
|
-
/** BARE profile name — what the caller asked for, never the runtime key. */
|
|
189
|
-
profile: ProfileName;
|
|
190
|
-
/** Runtime key the task actually landed on (`<profile>@<device>`). */
|
|
191
|
-
key: ConnectionKey;
|
|
192
|
-
/** Device the daemon connected to. */
|
|
193
|
-
device: string;
|
|
194
|
-
/** Set when the daemon picked a remote declaring device. */
|
|
195
|
-
picked?: string;
|
|
196
|
-
skill?: ResolvedDomainSkill;
|
|
197
|
-
/** A same-name start that matched an existing task and reused it (PHNX-2399). */
|
|
198
|
-
reused?: boolean;
|
|
199
|
-
/**
|
|
200
|
-
* The actual page operation the URL open performed (PHNX-2399), or undefined
|
|
201
|
-
* when start opened no URL. Carries created/refreshed/message truthfully:
|
|
202
|
-
* a fresh tab is `created`, a same-URL owned-tab reopen is `refreshed`, an
|
|
203
|
-
* adopted abandoned tab or a no-op reuse is neither.
|
|
204
|
-
*/
|
|
205
|
-
firstOpen?: PageOpenResult;
|
|
206
|
-
}
|
|
207
|
-
export declare function arcCreateMarker(): string;
|
|
208
|
-
export declare function isArcCreateMarker(url: string): boolean;
|
|
209
|
-
export declare class BrowserService {
|
|
210
|
-
private static readonly SOURCE_PREFIX;
|
|
211
|
-
/**
|
|
212
|
-
* Live browsers, keyed by {@link ConnectionKey} — NOT by profile name. The
|
|
213
|
-
* branded key type is what makes `connections.get(someProfileName)` (the
|
|
214
|
-
* RUSH-2709 miss that made `status --profile <name>` return empty for a
|
|
215
|
-
* running `<name>@<device>`) fail to compile. Keys are `<profile>@<device>`
|
|
216
|
-
* (legacy leftover `<profile>@endpoint-N` dirs are still recognized).
|
|
217
|
-
*/
|
|
218
|
-
private connections;
|
|
219
|
-
private forkingProfiles;
|
|
220
|
-
private consoleLogs;
|
|
221
|
-
private pageErrors;
|
|
222
|
-
private networkRequests;
|
|
223
|
-
private pendingDownloads;
|
|
224
|
-
private enabledSessions;
|
|
225
|
-
/** Profile -> when a `touchTask` last persisted tasks.json for it. */
|
|
226
|
-
private lastTouchPersist;
|
|
227
|
-
/** Coalescing window for the `touchTask` write. See {@link touchTask}. */
|
|
228
|
-
private static readonly TOUCH_PERSIST_INTERVAL_MS;
|
|
229
|
-
/**
|
|
230
|
-
* Serialization chains for the reopen/create critical section (PHNX-2399).
|
|
231
|
-
* Nothing else serializes IPC requests — `BrowserIPCServer` registers a
|
|
232
|
-
* per-connection `socket.on('data', async …)` that Node never awaits — so two
|
|
233
|
-
* concurrent `navigate`/`tab-add` requests, or two concurrent first-use
|
|
234
|
-
* creates for one caller, race the "is this URL already open?" lookup and each
|
|
235
|
-
* open a duplicate tab. Each key funnels its section through a promise chain so
|
|
236
|
-
* the second request sees the first's tab and refreshes it in place.
|
|
237
|
-
*
|
|
238
|
-
* Keys are DISJOINT by concern so a nested call can never wait on a lock its
|
|
239
|
-
* own outer frame holds: task-scoped work keys on `task:<key>:<name>`, first-
|
|
240
|
-
* use creation keys on `create:<callerId>`. `start()`'s Arc/Electron branch
|
|
241
|
-
* calls `navigate()` (a `task:` key) while the create path holds a `create:`
|
|
242
|
-
* key — different namespaces, so no re-entrant deadlock.
|
|
243
|
-
*/
|
|
244
|
-
private critical;
|
|
245
|
-
/**
|
|
246
|
-
* Run `fn` mutually exclusive against every other call sharing `key`. The
|
|
247
|
-
* chain never rejects (each link swallows its own settlement) so one failed
|
|
248
|
-
* section cannot wedge the queue; `fn`'s own result/throw is returned to THIS
|
|
249
|
-
* caller unchanged. The map entry is dropped once its tail settles with no
|
|
250
|
-
* newer waiter, so idle tasks/callers don't accumulate.
|
|
251
|
-
*/
|
|
252
|
-
private runExclusive;
|
|
253
|
-
/**
|
|
254
|
-
* The task's OWN tabs (excluding borrowed ones — a borrowed tab predates the
|
|
255
|
-
* task, see {@link Task.borrowedTabs}) that are still live in the browser AND
|
|
256
|
-
* whose current document canonically equals `url`. Deliberately scoped to THIS
|
|
257
|
-
* task: it is neither {@link adoptTabShowing} (reclaims OTHER abandoned tasks'
|
|
258
|
-
* tabs) nor {@link pickReusableTargetWithoutCreate} (borrows a USER tab on Arc)
|
|
259
|
-
* — the same-task reopen contract only ever touches a tab the task itself owns.
|
|
260
|
-
* A registered id with no live target (a tab closed out from under us) is
|
|
261
|
-
* skipped, so a stale mapping never masquerades as a reopenable tab.
|
|
262
|
-
*/
|
|
263
|
-
private findOwnedTabShowing;
|
|
264
|
-
/**
|
|
265
|
-
* Same-task reopen (PHNX-2399): the requested URL is already live in a tab this
|
|
266
|
-
* task owns, so RELOAD that same tab and keep its ids rather than opening a
|
|
267
|
-
* duplicate. Returns the retained short id, or undefined when no owned tab
|
|
268
|
-
* shows the URL (the caller then falls through to its normal navigate/create
|
|
269
|
-
* semantics — that no-match split is intentional and preserved).
|
|
270
|
-
*
|
|
271
|
-
* A real `Page.reload` is issued; a failed reload THROWS rather than reporting
|
|
272
|
-
* a phantom refresh (a stale target was already excluded by
|
|
273
|
-
* {@link findOwnedTabShowing}). The tab is marked current WITHOUT
|
|
274
|
-
* `Target.activateTarget` — reopen must not steal window focus.
|
|
275
|
-
*/
|
|
276
|
-
private reopenOwnedTab;
|
|
277
|
-
start(profileName: string, opts?: StartOptions): Promise<StartResult>;
|
|
278
|
-
private startBody;
|
|
279
|
-
/**
|
|
280
|
-
* Reclaim a live page already showing `url` from an ABANDONED task, instead
|
|
281
|
-
* of opening a second copy of the same page (RUSH-2622). Returns its CDP
|
|
282
|
-
* targetId, or undefined when there is nothing safe to reclaim.
|
|
283
|
-
*
|
|
284
|
-
* "Safe" is narrow on purpose, because both of the wider readings close a tab
|
|
285
|
-
* somebody is using:
|
|
286
|
-
*
|
|
287
|
-
* - An UNOWNED matching page is NOT taken. No task claims it, which most
|
|
288
|
-
* often means the user opened it themselves — and adopting it would make
|
|
289
|
-
* this task's `done` close the user's tab.
|
|
290
|
-
* - A page owned by a LIVE task is NOT taken. Stealing it would leave that
|
|
291
|
-
* agent's `screenshot`/`click` throwing "No tabs open for this task", its
|
|
292
|
-
* `navigate` silently opening the duplicate this feature exists to
|
|
293
|
-
* prevent, and any in-flight recording truncated when the new owner calls
|
|
294
|
-
* `done`.
|
|
295
|
-
*
|
|
296
|
-
* What is left is exactly the pile-up case: a page held by a task whose owner
|
|
297
|
-
* is provably gone. Liveness uses the reaper's own predicate
|
|
298
|
-
* (`taskOwnerIsGone`), so "dead" has one definition in this codebase rather
|
|
299
|
-
* than two that can drift. A task the reaper cannot prove dead keeps its tab
|
|
300
|
-
* and is closed later by the idle rule instead.
|
|
301
|
-
*
|
|
302
|
-
* Reclaiming transfers rather than shares: two tasks holding one targetId
|
|
303
|
-
* means the first `done` closes the other's tab. `start --fresh` skips this
|
|
304
|
-
* path entirely.
|
|
305
|
-
*
|
|
306
|
-
* URLs are compared canonically (`new URL(...).href`), so a requested
|
|
307
|
-
* `https://example.com` matches the `https://example.com/` Chrome reports. A
|
|
308
|
-
* page that has since redirected elsewhere simply does not match, and the
|
|
309
|
-
* caller opens a tab as before.
|
|
310
|
-
*/
|
|
311
|
-
/** Is this CDP target already registered to any task on the connection? */
|
|
312
|
-
private targetIsClaimed;
|
|
313
|
-
/**
|
|
314
|
-
* The CDP targets a task may CLOSE — its own tabs minus any it merely
|
|
315
|
-
* borrowed. A borrowed tab existed before the task did (see `Task.borrowedTabs`),
|
|
316
|
-
* so closing it would remove something the task never opened.
|
|
317
|
-
*/
|
|
318
|
-
private closeableTargetIds;
|
|
319
|
-
/**
|
|
320
|
-
* A page target that `navigate` may take over on a browser which cannot create
|
|
321
|
-
* tabs (Arc). Deliberately narrow: only a tab ALREADY showing the requested URL
|
|
322
|
-
* -- re-showing that document there is what the caller asked for -- or an empty
|
|
323
|
-
* new-tab page. A target any task already owns is left alone. Note the honest
|
|
324
|
-
* limit: reusing a matching tab still RELOADS it, discarding scroll position and
|
|
325
|
-
* unsaved form state. Arc cannot open a tab at all, so some intrusion is
|
|
326
|
-
* unavoidable to show the document; a reload is the smallest one, and the tab is
|
|
327
|
-
* borrowed rather than owned so it is never closed.
|
|
328
|
-
*/
|
|
329
|
-
private pickReusableTargetWithoutCreate;
|
|
330
|
-
private adoptTabShowing;
|
|
331
|
-
/**
|
|
332
|
-
* Every live task across every connected profile — the reaper's input
|
|
333
|
-
* (`hygiene.ts`). A read-only view: mutating a returned `Task` mutates the
|
|
334
|
-
* daemon's live state, so callers only read it and act through `stop`.
|
|
335
|
-
*/
|
|
336
|
-
listTasks(): Array<{
|
|
337
|
-
profile: ConnectionKey;
|
|
338
|
-
task: Task;
|
|
339
|
-
}>;
|
|
340
|
-
/**
|
|
341
|
-
* Close tasks whose owning agent session is gone, or that have sat untouched
|
|
342
|
-
* past the idle window. The entry point the daemon's periodic tick and
|
|
343
|
-
* `agents browser prune` both call; the policy lives in `hygiene.ts`.
|
|
344
|
-
*/
|
|
345
|
-
reapAbandoned(opts?: ReapOptions): Promise<ReapResult>;
|
|
346
|
-
stop(taskName: string): Promise<{
|
|
347
|
-
ok: boolean;
|
|
348
|
-
profile?: string;
|
|
349
|
-
}>;
|
|
350
|
-
done(taskName: string): Promise<{
|
|
351
|
-
ok: boolean;
|
|
352
|
-
profile?: string;
|
|
353
|
-
}>;
|
|
354
|
-
stopProfile(profileRef: ProfileName | ConnectionKey, opts?: {
|
|
355
|
-
fleetRemote?: boolean;
|
|
356
|
-
actor?: string;
|
|
357
|
-
}): Promise<void>;
|
|
358
|
-
navigate(taskId: string, url: string, profileRef?: ProfileName | ConnectionKey): Promise<{
|
|
359
|
-
tabId: string;
|
|
360
|
-
url: string;
|
|
361
|
-
created: boolean;
|
|
362
|
-
refreshed: boolean;
|
|
363
|
-
message?: string;
|
|
364
|
-
}>;
|
|
365
|
-
private navigateLocked;
|
|
366
|
-
tabAdd(taskId: string, url: string, profileRef?: ProfileName | ConnectionKey): Promise<{
|
|
367
|
-
tabId: string;
|
|
368
|
-
url: string;
|
|
369
|
-
created: boolean;
|
|
370
|
-
refreshed: boolean;
|
|
371
|
-
message?: string;
|
|
372
|
-
}>;
|
|
373
|
-
private tabAddLocked;
|
|
374
|
-
tabFocus(taskId: string, tabHint: string): Promise<{
|
|
375
|
-
tabId: string;
|
|
376
|
-
}>;
|
|
377
|
-
tabList(taskId: string): Promise<Array<{
|
|
378
|
-
id: string;
|
|
379
|
-
url: string;
|
|
380
|
-
title: string;
|
|
381
|
-
current: boolean;
|
|
382
|
-
}>>;
|
|
383
|
-
/**
|
|
384
|
-
* Every top-level tab open in the task's profile browser, the owner's tabs
|
|
385
|
-
* included (`agents browser tabs --all`). Read-only: nothing is focused,
|
|
386
|
-
* navigated, or closed. A tab an agents-cli task owns carries that task's
|
|
387
|
-
* name and short id (so it can be addressed); any other tab carries the
|
|
388
|
-
* browser's own id and no task. Same rows on every backend.
|
|
389
|
-
*/
|
|
390
|
-
profileTabs(taskId: string): Promise<ProfileTabInfo[]>;
|
|
391
|
-
private resolveTabHint;
|
|
392
|
-
private resolveCurrentTab;
|
|
393
|
-
private getCdpTargetId;
|
|
394
|
-
tabs(taskId?: string, profileRef?: ProfileName | ConnectionKey): Promise<TabInfo[]>;
|
|
395
|
-
tabClose(taskId: string, tabHint?: string): Promise<void>;
|
|
396
|
-
evaluate(taskId: string, tabHint: string | undefined, expression: string): Promise<unknown>;
|
|
397
|
-
screenshot(taskId: string, tabHint?: string, outputPath?: string, quality?: 'compressed' | 'raw'): Promise<{
|
|
398
|
-
path: string;
|
|
399
|
-
bytes: number;
|
|
400
|
-
width: number;
|
|
401
|
-
height: number;
|
|
402
|
-
}>;
|
|
403
|
-
/**
|
|
404
|
-
* Export the current tab as a PDF via CDP `Page.printToPDF`. Reuses the
|
|
405
|
-
* screenshot session + tab resolution so `--tab`, path sandboxing, and the
|
|
406
|
-
* auto-path (`sessions/<task>/<ts>.pdf`) all behave identically to
|
|
407
|
-
* `screenshot`. `printBackground: true` matches Chrome's default print flow
|
|
408
|
-
* — without it, dark-mode pages render on a blank sheet.
|
|
409
|
-
*/
|
|
410
|
-
printToPdf(taskId: string, tabHint?: string, outputPath?: string): Promise<{
|
|
411
|
-
path: string;
|
|
412
|
-
bytes: number;
|
|
413
|
-
}>;
|
|
414
|
-
private recordings;
|
|
415
|
-
recordStart(taskId: string, tabHint?: string, opts?: {
|
|
416
|
-
fps?: number;
|
|
417
|
-
duration?: number;
|
|
418
|
-
maxMb?: number;
|
|
419
|
-
}): Promise<{
|
|
420
|
-
path: string;
|
|
421
|
-
fps: number;
|
|
422
|
-
durationCapSec: number;
|
|
423
|
-
maxMb: number;
|
|
424
|
-
}>;
|
|
425
|
-
recordStop(taskId: string, reason?: 'manual' | 'duration-cap' | 'size-cap'): Promise<{
|
|
426
|
-
path: string;
|
|
427
|
-
bytes: number;
|
|
428
|
-
durationMs: number;
|
|
429
|
-
reason: string;
|
|
430
|
-
}>;
|
|
431
|
-
recordStatus(taskId: string): Promise<{
|
|
432
|
-
recording: boolean;
|
|
433
|
-
path?: string;
|
|
434
|
-
elapsedMs?: number;
|
|
435
|
-
}>;
|
|
436
|
-
refs(taskId: string, tabHint?: string, opts?: RefOpts): Promise<{
|
|
437
|
-
refs: string;
|
|
438
|
-
nodeMap: Map<number, RefNode>;
|
|
439
|
-
}>;
|
|
440
|
-
/** Record the last ref listing (descriptors + opts) for a tab into state. */
|
|
441
|
-
private cacheRefDescriptors;
|
|
442
|
-
/**
|
|
443
|
-
* Re-resolve a caller-supplied ref against a freshly-built node map, healing
|
|
444
|
-
* it back to the right element when the integer ref has drifted since the
|
|
445
|
-
* cached `refs` listing. Shared by `click` and `type` so both self-heal
|
|
446
|
-
* identically. Returns the ref to act on plus, when a heal occurred, the
|
|
447
|
-
* {@link HealInfo} to surface. Throws when the cached element is gone.
|
|
448
|
-
*/
|
|
449
|
-
private resolveHealedRef;
|
|
450
|
-
click(taskId: string, ref: number, tabHint?: string): Promise<{
|
|
451
|
-
healed?: HealInfo;
|
|
452
|
-
}>;
|
|
453
|
-
/**
|
|
454
|
-
* Click raw viewport coordinates, bypassing ref resolution entirely. Backs
|
|
455
|
-
* `browser click --at X,Y` — the escape hatch when the accessibility tree
|
|
456
|
-
* exposes no usable ref (canvas apps, custom-drawn UI) and the caller has
|
|
457
|
-
* located the target from a screenshot.
|
|
458
|
-
*/
|
|
459
|
-
clickAt(taskId: string, x: number, y: number, tabHint?: string): Promise<void>;
|
|
460
|
-
type(taskId: string, ref: number, text: string, tabHint?: string, clear?: boolean): Promise<void>;
|
|
461
|
-
press(taskId: string, key: string, tabHint?: string): Promise<void>;
|
|
462
|
-
hover(taskId: string, ref: number, tabHint?: string): Promise<void>;
|
|
463
|
-
scroll(taskId: string, deltaX: number, deltaY: number, atX?: number, atY?: number, tabHint?: string): Promise<void>;
|
|
464
|
-
upload(taskId: string, files: string[], options: {
|
|
465
|
-
ref?: number;
|
|
466
|
-
trigger?: number;
|
|
467
|
-
mode?: UploadMode;
|
|
468
|
-
tabHint?: string;
|
|
469
|
-
timeout?: number;
|
|
470
|
-
}): Promise<{
|
|
471
|
-
mode: 'input' | 'drop' | 'chooser';
|
|
472
|
-
}>;
|
|
473
|
-
stageUpload(source: string): {
|
|
474
|
-
path: string;
|
|
475
|
-
};
|
|
476
|
-
/**
|
|
477
|
-
* Status for one profile (bare name) or every live profile.
|
|
478
|
-
*
|
|
479
|
-
* `profileName` is a {@link ProfileName} — a BARE name, never a runtime key.
|
|
480
|
-
* Every candidate is selected by the one rule ({@link keyBelongsToProfile}),
|
|
481
|
-
* and a scoped query that finds no live connection falls through to disk, so
|
|
482
|
-
* `status --profile comet-local` reports the LIVE `comet-local@<device>`
|
|
483
|
-
* (and leftover `comet-local@endpoint-0` dirs) instead of the empty list
|
|
484
|
-
* it used to return (RUSH-2709).
|
|
485
|
-
*/
|
|
486
|
-
status(profileRef?: ProfileName | ConnectionKey): Promise<ProfileStatus[]>;
|
|
487
|
-
/**
|
|
488
|
-
* Rebuild a profile's status from its runtime dirs when no live connection is
|
|
489
|
-
* registered — a daemon that never connected this profile, or a browser
|
|
490
|
-
* started by an earlier daemon.
|
|
491
|
-
*
|
|
492
|
-
* Takes a BARE profile name and walks every runtime key that belongs to it
|
|
493
|
-
* ({@link listProfileCacheDirs}), including the legacy pre-composite dir named
|
|
494
|
-
* exactly the profile.
|
|
495
|
-
*/
|
|
496
|
-
private reconcileFromDisk;
|
|
497
|
-
private profileStatusFromDisk;
|
|
498
|
-
setViewport(taskId: string, width: number, height: number, options?: {
|
|
499
|
-
mobile?: boolean;
|
|
500
|
-
deviceScaleFactor?: number;
|
|
501
|
-
tabHint?: string;
|
|
502
|
-
}): Promise<void>;
|
|
503
|
-
setDevice(taskId: string, deviceName: string, tabHint?: string): Promise<void>;
|
|
504
|
-
private enableRuntimeForSession;
|
|
505
|
-
getConsoleLogs(taskId: string, options?: {
|
|
506
|
-
level?: string;
|
|
507
|
-
clear?: boolean;
|
|
508
|
-
tabHint?: string;
|
|
509
|
-
}): Promise<import('./types.js').ConsoleEntry[]>;
|
|
510
|
-
getErrors(taskId: string, options?: {
|
|
511
|
-
clear?: boolean;
|
|
512
|
-
tabHint?: string;
|
|
513
|
-
}): Promise<import('./types.js').ErrorEntry[]>;
|
|
514
|
-
private enableNetworkForSession;
|
|
515
|
-
getNetworkRequests(taskId: string, options?: {
|
|
516
|
-
filter?: string;
|
|
517
|
-
clear?: boolean;
|
|
518
|
-
tabHint?: string;
|
|
519
|
-
}): Promise<import('./types.js').NetworkRequest[]>;
|
|
520
|
-
getResponseBody(taskId: string, urlPattern: string, options?: {
|
|
521
|
-
timeout?: number;
|
|
522
|
-
maxChars?: number;
|
|
523
|
-
tabHint?: string;
|
|
524
|
-
}): Promise<string>;
|
|
525
|
-
getAppLogs(taskId: string, opts: {
|
|
526
|
-
lines?: number;
|
|
527
|
-
level?: string;
|
|
528
|
-
filter?: string;
|
|
529
|
-
message?: string;
|
|
530
|
-
source?: string;
|
|
531
|
-
since?: string;
|
|
532
|
-
until?: string;
|
|
533
|
-
}): Promise<any[]>;
|
|
534
|
-
wait(taskId: string, type: 'time' | 'selector' | 'url' | 'function' | 'load', value: string | number, options?: {
|
|
535
|
-
timeout?: number;
|
|
536
|
-
tabHint?: string;
|
|
537
|
-
}): Promise<void>;
|
|
538
|
-
/**
|
|
539
|
-
* Point the browser's default download destination at the profile's downloads
|
|
540
|
-
* dir, browser-global, at connect time. Without this a download the agent never
|
|
541
|
-
* explicitly routed (`browser download --path`) falls to Chromium's own default
|
|
542
|
-
* — for an attached user browser, wherever that browser was last configured,
|
|
543
|
-
* which is how downloads used to escape into random locations. Sent on the root
|
|
544
|
-
* session (no sessionId) so every current and future tab inherits it. Best
|
|
545
|
-
* effort: a remote CDP endpoint that doesn't expose the Browser domain must not
|
|
546
|
-
* fail the whole connect.
|
|
547
|
-
*/
|
|
548
|
-
private applyDefaultDownloadBehavior;
|
|
549
|
-
setDownloadPath(taskId: string, downloadPath?: string, tabHint?: string): Promise<string>;
|
|
550
|
-
waitForDownload(taskId: string, timeout?: number): Promise<string>;
|
|
551
|
-
private findTaskBySession;
|
|
552
|
-
shutdown(): Promise<void>;
|
|
553
|
-
private findAvailableFork;
|
|
554
|
-
private forkElectronProfile;
|
|
555
|
-
/**
|
|
556
|
-
* Connect to a profile at a specific endpoint preset. The caller has
|
|
557
|
-
* already resolved the endpoint and built the `effectiveProfile` with
|
|
558
|
-
* the per-endpoint binary/targetFilter overrides applied; we just use it.
|
|
559
|
-
*
|
|
560
|
-
* `key` is the runtime key (`<profile>@<device>`) and is what every on-disk
|
|
561
|
-
* lookup uses. It is a SEPARATE argument because `effectiveProfile.name`
|
|
562
|
-
* stays the bare, user-facing name (RUSH-2709).
|
|
563
|
-
*/
|
|
564
|
-
private connectProfile;
|
|
565
|
-
private connectEndpoint;
|
|
566
|
-
private enableDomains;
|
|
567
|
-
/**
|
|
568
|
-
* The single path that opens a new CDP page/window target. It exists so the
|
|
569
|
-
* Arc guard lives in exactly one place: `Target.createTarget` crashes Arc
|
|
570
|
-
* (verified, PR #2778), so an Arc connection throws a clear, actionable error
|
|
571
|
-
* here instead of every call site re-checking. Every drivable Chromium-family
|
|
572
|
-
* browser goes straight through.
|
|
573
|
-
*/
|
|
574
|
-
private createPageTarget;
|
|
575
|
-
private getOrCreateWindow;
|
|
576
|
-
private hasTaskNamed;
|
|
577
|
-
/** The (connection, task) a handle names anywhere, or undefined. */
|
|
578
|
-
private findTaskByHandle;
|
|
579
|
-
/**
|
|
580
|
-
* Same-name `start --task <name>` retry (PHNX-2399). When a task by that name
|
|
581
|
-
* already exists this REUSES it — reopening the URL in the same tab (same id,
|
|
582
|
-
* a real reload, the `Tab already open—refreshed` note) — but only after
|
|
583
|
-
* proving it is genuinely the same task: same bare profile, same endpoint, and
|
|
584
|
-
* a matching caller identity. A mismatch on any of those is a real conflict and
|
|
585
|
-
* throws, so a different caller/profile/endpoint can never silently acquire
|
|
586
|
-
* another task. Serialized by the `namedstart:` lock in {@link start}.
|
|
587
|
-
*/
|
|
588
|
-
private retryNamedStart;
|
|
589
|
-
/** Map key for a task on a connection (tasks are keyed by `name`). */
|
|
590
|
-
private taskMapKey;
|
|
591
|
-
/** Find a task by map key, id, or name on one connection. */
|
|
592
|
-
private lookupTaskOnConn;
|
|
593
|
-
private maybeUpdateLabelFromUrl;
|
|
594
|
-
/**
|
|
595
|
-
* Resolve a task for a page/close verb.
|
|
596
|
-
*
|
|
597
|
-
* - explicit `task` handle → look up (with disk rehydrate on RAM miss)
|
|
598
|
-
* - no handle, exactly one live task for this caller → use it
|
|
599
|
-
* - no handle, multiple for this caller → error listing them + `--task`
|
|
600
|
-
* - no handle, zero for this caller, createIfMissing → start a new task
|
|
601
|
-
* - no handle, zero, !createIfMissing → return null (caller reports "nothing to close")
|
|
602
|
-
*/
|
|
603
|
-
resolveOrCreateTask(opts: {
|
|
604
|
-
/** Whether the CALLER was dispatched here by a fleet `--device` hop. */
|
|
605
|
-
fleetRemote?: boolean;
|
|
606
|
-
task?: string;
|
|
607
|
-
profile?: string;
|
|
608
|
-
actor?: string;
|
|
609
|
-
launchId?: string;
|
|
610
|
-
sessionId?: string;
|
|
611
|
-
createIfMissing: boolean;
|
|
612
|
-
title?: string;
|
|
613
|
-
url?: string;
|
|
614
|
-
}): Promise<{
|
|
615
|
-
conn: ProfileConnection;
|
|
616
|
-
task: Task;
|
|
617
|
-
key: ConnectionKey;
|
|
618
|
-
created: boolean;
|
|
619
|
-
picked?: string;
|
|
620
|
-
device?: string;
|
|
621
|
-
/**
|
|
622
|
-
* When this call CREATED the task by starting a browser on `opts.url`, the
|
|
623
|
-
* page operation `start` already performed on that URL. The owning IPC
|
|
624
|
-
* handler reports it truthfully (adopt → created:false, Arc reuse →
|
|
625
|
-
* created:false, fresh tab → created:true) instead of re-running the
|
|
626
|
-
* navigate/tab-add (a duplicate execution) and assuming a create (PHNX-2399).
|
|
627
|
-
*/
|
|
628
|
-
firstOpen?: PageOpenResult;
|
|
629
|
-
} | null>;
|
|
630
|
-
private resolveOrCreateByIdentity;
|
|
631
|
-
private listTasksForCaller;
|
|
632
|
-
private currentUrlHint;
|
|
633
|
-
/**
|
|
634
|
-
* Mark a task as active, so the reaper's idle window measures time since the
|
|
635
|
-
* last real use rather than time since `start` (RUSH-2622).
|
|
636
|
-
*
|
|
637
|
-
* Called from `findTask` — the single funnel every task-scoped operation
|
|
638
|
-
* resolves through — rather than from each of the ~26 call sites, so a new
|
|
639
|
-
* action added later cannot forget to stamp it.
|
|
640
|
-
*
|
|
641
|
-
* The in-memory stamp is what the reaper reads: it runs inside the same
|
|
642
|
-
* daemon that owns these `Task` objects. The write to tasks.json exists only
|
|
643
|
-
* so a daemon RESTART does not inherit a stale stamp and reap a task an agent
|
|
644
|
-
* has been clicking through for the last half hour — `click`, `type`,
|
|
645
|
-
* `evaluate`, and `screenshot` never call `saveTaskState` on their own, so
|
|
646
|
-
* without this the on-disk stamp would sit at the last navigation. It is
|
|
647
|
-
* coalesced to at most one write per profile per minute so a screenshot loop
|
|
648
|
-
* does not become a write loop; the resulting on-disk stamp trails by at most
|
|
649
|
-
* a minute, well inside the 30-minute idle window.
|
|
650
|
-
*/
|
|
651
|
-
private touchTask;
|
|
652
|
-
private prepareTask;
|
|
653
|
-
private findTask;
|
|
654
|
-
/**
|
|
655
|
-
* Soft-attach to an already-running browser for a runtime dir.
|
|
656
|
-
*
|
|
657
|
-
* Never launches a browser and never clears pid/port files on failure —
|
|
658
|
-
* `connectProfile` does both, which made `status()` wipe disk state when
|
|
659
|
-
* CDP was unreachable (CI / post-reaper) and then return an empty list.
|
|
660
|
-
* Returns null when nothing is speaking CDP so callers can fall through
|
|
661
|
-
* to disk reconcile.
|
|
662
|
-
*/
|
|
663
|
-
private attachRunningProfile;
|
|
664
|
-
/**
|
|
665
|
-
* Reconnect every profile runtime dir that still has a live browser and
|
|
666
|
-
* tasks.json entries. Used before identity-based resolution so a daemon
|
|
667
|
-
* restart does not make the caller's tasks invisible.
|
|
668
|
-
*/
|
|
669
|
-
/**
|
|
670
|
-
* Register a freshly-rehydrated connection, unless a concurrent rehydrate won
|
|
671
|
-
* the race and already registered one for this key. `attachRunningProfile`
|
|
672
|
-
* awaits an ssh-tunnel spawn / CDP connect, so two commands landing right
|
|
673
|
-
* after a daemon restart can each build a connection for the same key; the
|
|
674
|
-
* loser must be released instead of silently overwriting the winner (whose
|
|
675
|
-
* `cleanup` would then never run).
|
|
676
|
-
*
|
|
677
|
-
* The subtlety is the SSH tunnel: when the loser's `connectSSH` landed after
|
|
678
|
-
* the winner's tunnel had already bound the local port, `isOwnTunnel` makes it
|
|
679
|
-
* **reuse** that same OS process (`drivers/ssh.ts`) — so both connections carry
|
|
680
|
-
* the same `pid`/`port`. Calling the loser's `cleanup()` then does
|
|
681
|
-
* `tunnel.kill()` on the SHARED process and breaks the winner's live CDP. So
|
|
682
|
-
* when the loser shares the winner's tunnel we close ONLY the loser's own CDP
|
|
683
|
-
* socket and leave the tunnel to the winner; only a loser that spawned its own
|
|
684
|
-
* distinct tunnel gets the full `cleanup()` (else it would leak). Returns the
|
|
685
|
-
* winning connection to use.
|
|
686
|
-
*/
|
|
687
|
-
private registerRehydratedConnection;
|
|
688
|
-
private rehydrateAllFromDisk;
|
|
689
|
-
/**
|
|
690
|
-
* On a RAM miss, scan profile runtime dirs for a tasks.json entry matching
|
|
691
|
-
* `taskId`, soft-attach when CDP is still up, and register the connection.
|
|
692
|
-
* Does not launch browsers or clear runtime files.
|
|
693
|
-
*/
|
|
694
|
-
private rehydrateTaskFromDisk;
|
|
695
|
-
private getTabsForTask;
|
|
696
|
-
/** Live status for ONE registered connection, addressed by its runtime key. */
|
|
697
|
-
private getProfileStatus;
|
|
698
|
-
private getTarget;
|
|
699
|
-
private getSessionId;
|
|
700
|
-
private invalidateTargetCache;
|
|
701
|
-
private saveTaskState;
|
|
702
|
-
private loadTaskState;
|
|
703
|
-
private saveToHistory;
|
|
704
|
-
/**
|
|
705
|
-
* The cached connection for `key`, or undefined — evicting it first if the
|
|
706
|
-
* browser died underneath us.
|
|
707
|
-
*
|
|
708
|
-
* A browser killed externally (Cmd-Q, crash, a user clearing the profile by
|
|
709
|
-
* hand) leaves a closed WebSocket in the map. Without this the next
|
|
710
|
-
* `cdp.send` throws "CDP connection not open" and there is no recovery short
|
|
711
|
-
* of killing the daemon.
|
|
712
|
-
*/
|
|
713
|
-
private reuseHealthyConnection;
|
|
714
|
-
/**
|
|
715
|
-
* Reuse a live connection for this profile: the new `<name>@<device>` key
|
|
716
|
-
* first, then any leftover `<name>@endpoint-N` key still in the map so a
|
|
717
|
-
* browser started before the key collapse is not abandoned.
|
|
718
|
-
*/
|
|
719
|
-
private reuseProfileConnection;
|
|
720
|
-
/**
|
|
721
|
-
* Bind a task to the profile's Space in the visible Arc window that holds it.
|
|
722
|
-
* The Space is the profile (PHNX-2399); only its live window id is looked up.
|
|
723
|
-
*/
|
|
724
|
-
private resolveArcSpace;
|
|
725
|
-
private requireArcTask;
|
|
726
|
-
private reconcileArcCreateIntents;
|
|
727
|
-
private createArcOwnedTab;
|
|
728
|
-
private navigateArcNative;
|
|
729
|
-
/**
|
|
730
|
-
* Execute JavaScript in a native Arc tab. Sync JS only, isolated world —
|
|
731
|
-
* async/promise evaluation fails honestly with an AppleScript error.
|
|
732
|
-
*/
|
|
733
|
-
private evaluateArcNative;
|
|
734
|
-
/**
|
|
735
|
-
* Resolve a task's owned Arc tabs against one shared snapshot of every
|
|
736
|
-
* window/space/tab, rather than asking Arc per tab as `listArcTaskTabs` does.
|
|
737
|
-
*
|
|
738
|
-
* Same ownership rule as the live path — `requireArcTask`, then the recorded
|
|
739
|
-
* ref must be present in its original window and Space. The snapshot changes
|
|
740
|
-
* how often Arc is asked, never what counts as owned. Actions keep the live
|
|
741
|
-
* path, because a snapshot can go stale before it is acted on.
|
|
742
|
-
*/
|
|
743
|
-
private listArcTaskTabsFromSnapshot;
|
|
744
|
-
private listArcTaskTabs;
|
|
745
|
-
/**
|
|
746
|
-
* Close native Arc tabs owned by a task. Only closes tabs the task created
|
|
747
|
-
* (not borrowed ones). Never kills Arc. Identifies tabs only by stable ids in
|
|
748
|
-
* the original window and Space.
|
|
749
|
-
*/
|
|
750
|
-
private closeArcNativeTabs;
|
|
751
|
-
/** The BiDi browsing-context id a task owns for `shortId`. */
|
|
752
|
-
private firefoxContext;
|
|
753
|
-
/** The context ids currently live in this Firefox (a killed tab drops out). */
|
|
754
|
-
private firefoxLiveContexts;
|
|
755
|
-
/**
|
|
756
|
-
* Same-task reopen for Firefox (mirrors {@link reopenOwnedTab}): the URL is
|
|
757
|
-
* already live in one of this task's own tabs → reload THAT tab in place and
|
|
758
|
-
* keep its id, rather than opening a duplicate. Borrowed tabs are excluded —
|
|
759
|
-
* Firefox never borrows, but the guard keeps parity. Returns the retained
|
|
760
|
-
* short id, or undefined when nothing matches.
|
|
761
|
-
*/
|
|
762
|
-
private reopenOwnedFirefoxTab;
|
|
763
|
-
private navigateFirefox;
|
|
764
|
-
private evaluateFirefox;
|
|
765
|
-
private listFirefoxTaskTabs;
|
|
766
|
-
/**
|
|
767
|
-
* Close every non-borrowed tab a Firefox task owns. Never kills the Firefox
|
|
768
|
-
* process (that is `stopProfile`'s job) — a killed browser would take the
|
|
769
|
-
* user's other tabs with it. A tab already gone is skipped.
|
|
770
|
-
*/
|
|
771
|
-
private closeFirefoxTabs;
|
|
772
|
-
/**
|
|
773
|
-
* Viewport-center coordinates of a selector-addressed element in a Firefox
|
|
774
|
-
* tab, scrolled into view first — the (x, y) `input.performActions` clicks.
|
|
775
|
-
* Throws when the element is gone or has zero size (off-screen / display:none).
|
|
776
|
-
*/
|
|
777
|
-
private firefoxRefCoords;
|
|
778
|
-
/**
|
|
779
|
-
* Screenshot a Firefox tab over BiDi. Same output contract as the CDP path:
|
|
780
|
-
* `raw` is a pixel-faithful PNG; the default is JPEG iteratively downscaled
|
|
781
|
-
* under 100 KB so chat-injected screenshots stay token-cheap.
|
|
782
|
-
*/
|
|
783
|
-
private screenshotFirefox;
|
|
784
|
-
/** Connect a profile at `target`, register it under `key`, and arm downloads. */
|
|
785
|
-
private openConnection;
|
|
786
|
-
/**
|
|
787
|
-
* Open a tab for a HUMAN to read, bound to no task.
|
|
788
|
-
*
|
|
789
|
-
* That is the entire difference from {@link start}, and it is the point. The
|
|
790
|
-
* abandoned-task reaper closes a task's tabs when the calling session dies or
|
|
791
|
-
* after the idle window, but it "deliberately never touches a tab that is not
|
|
792
|
-
* in `task.tabs`" (hygiene.ts) — so a viewer tab must not be in one, or the
|
|
793
|
-
* artifact the user is reading vanishes when the agent that rendered it exits.
|
|
794
|
-
*
|
|
795
|
-
* Consequently `stop`/`done` do not close it either, which is correct: it is
|
|
796
|
-
* the user's tab now.
|
|
797
|
-
*/
|
|
798
|
-
showUrl(profileName: ProfileName, url: string, opts?: {
|
|
799
|
-
endpointName?: string;
|
|
800
|
-
fleetRemote?: boolean;
|
|
801
|
-
actor?: string;
|
|
802
|
-
probe?: DeviceProbe;
|
|
803
|
-
}): Promise<{
|
|
804
|
-
profile: ProfileName;
|
|
805
|
-
key: ConnectionKey;
|
|
806
|
-
tabId: string;
|
|
807
|
-
device: string;
|
|
808
|
-
picked?: string;
|
|
809
|
-
}>;
|
|
810
|
-
getHistory(limit?: number): Promise<HistoricalTask[]>;
|
|
811
|
-
}
|
|
812
|
-
export {};
|