@phnx-labs/agents-cli 1.22.41 → 1.22.43
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 +86 -0
- package/README.md +10 -4
- package/dist/bin/agents +0 -0
- package/dist/bootstrap.js +25 -7
- package/dist/cli/command-registry.d.ts +2 -3
- package/dist/cli/command-registry.js +4 -8
- package/dist/commands/accounts.d.ts +29 -0
- package/dist/commands/accounts.js +220 -29
- package/dist/commands/alias.d.ts +7 -4
- package/dist/commands/alias.js +34 -9
- package/dist/commands/auth.d.ts +9 -0
- package/dist/commands/auth.js +108 -0
- package/dist/commands/browser-sessions-picker.js +42 -62
- package/dist/commands/browser.js +30 -38
- package/dist/commands/computer-actions.d.ts +1 -1
- package/dist/commands/computer-actions.js +1 -1
- package/dist/commands/computer-sessions-picker.js +32 -55
- package/dist/commands/computer.d.ts +1 -1
- package/dist/commands/computer.js +22 -8
- package/dist/commands/daemon.js +1 -1
- package/dist/commands/doctor.d.ts +5 -3
- package/dist/commands/doctor.js +23 -8
- package/dist/commands/exec.js +3 -2
- package/dist/commands/feed.js +2 -31
- package/dist/commands/harness.js +3 -3
- package/dist/commands/hooks.js +1 -1
- package/dist/commands/import.js +1 -1
- package/dist/commands/insights.js +163 -85
- package/dist/commands/inspect.js +2 -2
- package/dist/commands/mine.js +1 -1
- package/dist/commands/monitors.js +1 -1
- package/dist/commands/org.d.ts +6 -0
- package/dist/commands/org.js +175 -0
- package/dist/commands/packages.js +1 -1
- package/dist/commands/profiles.js +2 -2
- package/dist/commands/prune.js +1 -1
- package/dist/commands/routines.js +44 -26
- package/dist/commands/run-account-picker.d.ts +19 -0
- package/dist/commands/run-account-picker.js +81 -0
- package/dist/commands/sessions-picker-factory.d.ts +40 -0
- package/dist/commands/sessions-picker-factory.js +67 -0
- package/dist/commands/sessions-picker.js +124 -122
- package/dist/commands/setup-browser.js +4 -4
- package/dist/commands/setup-mine.js +1 -1
- package/dist/commands/setup-preferences.js +2 -2
- package/dist/commands/setup.js +10 -4
- package/dist/commands/snapshot.d.ts +1 -1
- package/dist/commands/snapshot.js +4 -4
- package/dist/commands/status.d.ts +4 -2
- package/dist/commands/status.js +10 -7
- package/dist/commands/sync.d.ts +1 -0
- package/dist/commands/sync.js +30 -3
- package/dist/commands/versions.js +1 -1
- package/dist/commands/view.js +7 -1
- package/dist/commands/webhook.js +1 -1
- package/dist/lib/account-capabilities.d.ts +10 -0
- package/dist/lib/account-capabilities.js +34 -0
- package/dist/lib/accounting/rotate.d.ts +5 -3
- package/dist/lib/accounting/rotate.js +36 -7
- package/dist/lib/accounting/usage.d.ts +18 -4
- package/dist/lib/accounting/usage.js +138 -27
- package/dist/lib/agent-spec/agents.d.ts +584 -0
- package/dist/lib/agent-spec/agents.js +3127 -0
- package/dist/lib/agent-spec/provider.js +1 -1
- package/dist/lib/agents.d.ts +2 -584
- package/dist/lib/agents.js +2 -3127
- package/dist/lib/browser/drivers/local.d.ts +8 -2
- package/dist/lib/browser/drivers/local.js +8 -2
- package/dist/lib/browser/drivers/ssh.d.ts +8 -2
- package/dist/lib/browser/drivers/ssh.js +10 -4
- package/dist/lib/browser/hygiene.d.ts +1 -1
- package/dist/lib/browser/hygiene.js +5 -1
- package/dist/lib/browser/profiles.d.ts +74 -1
- package/dist/lib/browser/profiles.js +114 -5
- package/dist/lib/browser/runtime-state.d.ts +11 -5
- package/dist/lib/browser/runtime-state.js +13 -9
- package/dist/lib/browser/service.d.ts +68 -30
- package/dist/lib/browser/service.js +305 -194
- package/dist/lib/browser/types.d.ts +95 -3
- package/dist/lib/browser/types.js +51 -0
- package/dist/lib/catchup.js +1 -1
- package/dist/lib/cloud/rush.d.ts +0 -15
- package/dist/lib/cloud/rush.js +0 -35
- package/dist/lib/computer/actions.d.ts +1 -1
- package/dist/lib/computer/actions.js +1 -1
- package/dist/lib/{computer-rpc.js → computer/computer-rpc.js} +5 -5
- package/dist/lib/computer/dispatch.d.ts +1 -1
- package/dist/lib/computer/download.d.ts +1 -1
- package/dist/lib/computer/download.js +3 -3
- package/dist/lib/{ssh-tunnel.d.ts → computer/ssh-tunnel.d.ts} +1 -1
- package/dist/lib/{ssh-tunnel.js → computer/ssh-tunnel.js} +12 -12
- package/dist/lib/crabbox/runtimes.d.ts +6 -2
- package/dist/lib/crabbox/runtimes.js +21 -5
- package/dist/lib/daemon/daemon.js +87 -59
- package/dist/lib/{runner.d.ts → daemon/runner.d.ts} +28 -11
- package/dist/lib/{runner.js → daemon/runner.js} +143 -123
- package/dist/lib/devices/doctor-findings.d.ts +1 -1
- package/dist/lib/devices/doctor-findings.js +4 -4
- package/dist/lib/devices/fleet-inventory.js +1 -1
- package/dist/lib/devices/harness-inventory.js +1 -1
- package/dist/lib/devices/health-report.js +1 -1
- package/dist/lib/devices/registry.js +4 -22
- package/dist/lib/doctor-diff.d.ts +1 -1
- package/dist/lib/doctor-diff.js +1 -1
- package/dist/lib/drift-sync.d.ts +1 -1
- package/dist/lib/drift-sync.js +2 -2
- package/dist/lib/drift.d.ts +1 -1
- package/dist/lib/drift.js +1 -1
- package/dist/lib/entitlement.d.ts +31 -0
- package/dist/lib/entitlement.js +137 -0
- package/dist/lib/exec.js +52 -205
- package/dist/lib/feed/feed.js +2 -8
- package/dist/lib/format.d.ts +9 -0
- package/dist/lib/format.js +16 -0
- package/dist/lib/fs-atomic.d.ts +7 -0
- package/dist/lib/fs-atomic.js +9 -0
- package/dist/lib/github/pr-mergeable.d.ts +49 -0
- package/dist/lib/github/pr-mergeable.js +157 -0
- package/dist/lib/github/pr-verdict.d.ts +67 -0
- package/dist/lib/github/pr-verdict.js +72 -0
- package/dist/lib/harness/adapter.d.ts +161 -0
- package/dist/lib/harness/adapter.js +47 -0
- package/dist/lib/harness/adapters/claude.d.ts +2 -0
- package/dist/lib/harness/adapters/claude.js +110 -0
- package/dist/lib/harness/adapters/codex.d.ts +2 -0
- package/dist/lib/harness/adapters/codex.js +83 -0
- package/dist/lib/harness/adapters/copilot.d.ts +2 -0
- package/dist/lib/harness/adapters/copilot.js +23 -0
- package/dist/lib/harness/adapters/cursor.d.ts +2 -0
- package/dist/lib/harness/adapters/cursor.js +38 -0
- package/dist/lib/harness/adapters/droid.d.ts +2 -0
- package/dist/lib/harness/adapters/droid.js +17 -0
- package/dist/lib/harness/adapters/grok.d.ts +2 -0
- package/dist/lib/harness/adapters/grok.js +14 -0
- package/dist/lib/harness/adapters/kimi.d.ts +2 -0
- package/dist/lib/harness/adapters/kimi.js +49 -0
- package/dist/lib/harness/adapters/muse.d.ts +2 -0
- package/dist/lib/harness/adapters/muse.js +44 -0
- package/dist/lib/harness/adapters/opencode.d.ts +2 -0
- package/dist/lib/harness/adapters/opencode.js +14 -0
- package/dist/lib/harness/exec-config-version.d.ts +8 -0
- package/dist/lib/harness/exec-config-version.js +22 -0
- package/dist/lib/harness/index.d.ts +1 -0
- package/dist/lib/harness/index.js +34 -0
- package/dist/lib/{hooks.d.ts → hooks/install.d.ts} +1 -1
- package/dist/lib/{hooks.js → hooks/install.js} +11 -11
- package/dist/lib/hosts/passthrough.d.ts +10 -0
- package/dist/lib/hosts/passthrough.js +28 -6
- package/dist/lib/hosts/session-index.js +1 -1
- package/dist/lib/import.js +1 -1
- package/dist/lib/installations/index.d.ts +4 -4
- package/dist/lib/installations/index.js +3 -4
- package/dist/lib/installations/migrate.js +6 -6
- package/dist/lib/{shims.d.ts → installations/shims.d.ts} +2 -2
- package/dist/lib/{shims.js → installations/shims.js} +13 -115
- package/dist/lib/installations/store.d.ts +141 -3
- package/dist/lib/installations/store.js +475 -5
- package/dist/lib/installations/versions.d.ts +40 -125
- package/dist/lib/installations/versions.js +57 -462
- package/dist/lib/isolation-boundary-report.d.ts +1 -1
- package/dist/lib/isolation-boundary-report.js +1 -1
- package/dist/lib/mailbox-gc.js +2 -3
- package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/install-menubar.js +19 -8
- package/dist/lib/monitors/config.d.ts +2 -2
- package/dist/lib/monitors/config.js +3 -2
- package/dist/lib/monitors/dispatch.d.ts +1 -1
- package/dist/lib/monitors/dispatch.js +2 -2
- package/dist/lib/monitors/state.d.ts +1 -1
- package/dist/lib/origin-machine.d.ts +18 -0
- package/dist/lib/origin-machine.js +34 -0
- package/dist/lib/perf/db.js +1 -1
- package/dist/lib/perf/spool.js +1 -1
- package/dist/lib/plugins/plugins.js +1 -1
- package/dist/lib/plugins/skills.js +1 -1
- package/dist/lib/prix-account.d.ts +158 -0
- package/dist/lib/prix-account.js +214 -0
- package/dist/lib/profiles.d.ts +7 -0
- package/dist/lib/profiles.js +26 -1
- package/dist/lib/project-key.js +2 -2
- package/dist/lib/project-launch.js +1 -1
- package/dist/lib/refresh.js +2 -2
- package/dist/lib/resource-inventory.d.ts +1 -1
- package/dist/lib/resource-inventory.js +1 -1
- package/dist/lib/rules/rules.js +1 -1
- package/dist/lib/sandbox.d.ts +24 -0
- package/dist/lib/sandbox.js +101 -0
- package/dist/lib/scheduling/routines.d.ts +18 -9
- package/dist/lib/scheduling/routines.js +17 -9
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/agent.js +9 -1
- package/dist/lib/secrets/index.js +1 -1
- package/dist/lib/secrets/list-filter.js +1 -1
- package/dist/lib/self-heal/checks/hook-runtime.js +1 -1
- package/dist/lib/self-heal/checks/path.js +1 -1
- package/dist/lib/self-heal/checks/shadowing.js +1 -1
- package/dist/lib/self-heal/checks/shims.js +1 -1
- package/dist/lib/service-manifest.d.ts +20 -0
- package/dist/lib/service-manifest.js +34 -0
- package/dist/lib/session/cloud.js +1 -1
- package/dist/lib/session/db.js +1 -1
- package/dist/lib/session/discover.d.ts +39 -0
- package/dist/lib/session/discover.js +3 -3
- package/dist/lib/session/fork.js +1 -1
- package/dist/lib/session/live-metadata.js +1 -1
- package/dist/lib/session/origin-machine.d.ts +1 -18
- package/dist/lib/session/origin-machine.js +4 -34
- package/dist/lib/session/parse.js +24 -42
- package/dist/lib/session/recovery.js +1 -1
- package/dist/lib/session/relative-time.d.ts +1 -44
- package/dist/lib/session/relative-time.js +4 -120
- package/dist/lib/session/remote-list.js +1 -1
- package/dist/lib/session/remote.js +2 -2
- package/dist/lib/session/short-id.d.ts +1 -17
- package/dist/lib/session/short-id.js +4 -20
- package/dist/lib/session/width.d.ts +1 -29
- package/dist/lib/session/width.js +4 -101
- package/dist/lib/snapshot.d.ts +2 -2
- package/dist/lib/snapshot.js +1 -1
- package/dist/lib/staleness/prune.d.ts +1 -1
- package/dist/lib/staleness/prune.js +1 -1
- package/dist/lib/staleness/writers/hooks.js +1 -1
- package/dist/lib/startup/command-registry.d.ts +4 -1
- package/dist/lib/startup/command-registry.js +12 -5
- package/dist/lib/teams/agents.js +2 -19
- package/dist/lib/teams/parsers.js +20 -26
- package/dist/lib/teams/placement-probe.js +1 -1
- package/dist/lib/teams/registry.js +2 -21
- package/dist/lib/teams/scheduler.js +1 -1
- package/dist/lib/text/relative-time.d.ts +44 -0
- package/dist/lib/text/relative-time.js +120 -0
- package/dist/lib/text/short-id.d.ts +17 -0
- package/dist/lib/text/short-id.js +20 -0
- package/dist/lib/text/width.d.ts +29 -0
- package/dist/lib/text/width.js +101 -0
- package/dist/lib/triggers/handlers.d.ts +7 -0
- package/dist/lib/triggers/handlers.js +9 -1
- package/dist/lib/triggers/webhook.d.ts +1 -0
- package/dist/lib/triggers/webhook.js +3 -2
- package/dist/lib/uninstall.js +1 -1
- package/dist/lib/version.d.ts +9 -2
- package/dist/lib/version.js +11 -9
- package/dist/lib/view-types.d.ts +4 -0
- package/package.json +1 -1
- package/dist/commands/tickets.d.ts +0 -2
- package/dist/commands/tickets.js +0 -43
- package/dist/lib/observe-aliases.d.ts +0 -30
- package/dist/lib/observe-aliases.js +0 -38
- package/dist/lib/tickets/list.d.ts +0 -53
- package/dist/lib/tickets/list.js +0 -153
- /package/dist/lib/{computer-rpc.d.ts → computer/computer-rpc.d.ts} +0 -0
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { CDPClient } from '../cdp.js';
|
|
2
|
-
import type { BrowserProfile } from '../types.js';
|
|
2
|
+
import type { BrowserProfile, ConnectionKey } from '../types.js';
|
|
3
3
|
export interface LocalConnection {
|
|
4
4
|
cdp: CDPClient;
|
|
5
5
|
port: number;
|
|
6
6
|
pid: number;
|
|
7
7
|
}
|
|
8
|
-
export declare function connectLocal(endpoint: string, profile: BrowserProfile
|
|
8
|
+
export declare function connectLocal(endpoint: string, profile: BrowserProfile,
|
|
9
|
+
/**
|
|
10
|
+
* Runtime key (`<profile>@<endpoint>`) the launched browser's user-data-dir,
|
|
11
|
+
* pid, and port files are stored under. Separate from `profile.name`, which
|
|
12
|
+
* stays the bare user-facing name and appears only in messages (RUSH-2709).
|
|
13
|
+
*/
|
|
14
|
+
key: ConnectionKey): Promise<LocalConnection>;
|
|
@@ -31,7 +31,13 @@ const TUNNEL_PROCESS_NAMES = new Set(['ssh', 'autossh', 'mosh-client', 'socat'])
|
|
|
31
31
|
function isTunnelProcess(command) {
|
|
32
32
|
return TUNNEL_PROCESS_NAMES.has(command.toLowerCase());
|
|
33
33
|
}
|
|
34
|
-
export async function connectLocal(endpoint, profile
|
|
34
|
+
export async function connectLocal(endpoint, profile,
|
|
35
|
+
/**
|
|
36
|
+
* Runtime key (`<profile>@<endpoint>`) the launched browser's user-data-dir,
|
|
37
|
+
* pid, and port files are stored under. Separate from `profile.name`, which
|
|
38
|
+
* stays the bare user-facing name and appears only in messages (RUSH-2709).
|
|
39
|
+
*/
|
|
40
|
+
key) {
|
|
35
41
|
const url = new URL(endpoint);
|
|
36
42
|
if (url.protocol !== 'cdp:') {
|
|
37
43
|
throw new Error(`Invalid local endpoint: ${endpoint}`);
|
|
@@ -91,7 +97,7 @@ export async function connectLocal(endpoint, profile) {
|
|
|
91
97
|
const chromeOpts = { ...profile.chrome, viewport: profile.viewport };
|
|
92
98
|
let launched;
|
|
93
99
|
try {
|
|
94
|
-
launched = await launchBrowser(
|
|
100
|
+
launched = await launchBrowser(key, profile.browser, newPort, chromeOpts, profile.secrets, profile.binary, profile.electron === true);
|
|
95
101
|
}
|
|
96
102
|
catch (launchErr) {
|
|
97
103
|
const reason = launchErr instanceof Error ? launchErr.message : String(launchErr);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CDPClient } from '../cdp.js';
|
|
2
|
-
import type { BrowserProfile } from '../types.js';
|
|
2
|
+
import type { BrowserProfile, ConnectionKey } from '../types.js';
|
|
3
3
|
import { shellQuote } from '../../ssh-exec.js';
|
|
4
4
|
export { shellQuote };
|
|
5
5
|
export interface SSHConnection {
|
|
@@ -16,7 +16,13 @@ export interface SSHConnection {
|
|
|
16
16
|
* strings differ (no `&` backgrounding, no `lsof`, `.exe` instead of `.app`).
|
|
17
17
|
*/
|
|
18
18
|
export type RemoteOs = 'windows' | 'posix';
|
|
19
|
-
export declare function connectSSH(endpoint: string, profile: BrowserProfile
|
|
19
|
+
export declare function connectSSH(endpoint: string, profile: BrowserProfile,
|
|
20
|
+
/**
|
|
21
|
+
* Runtime key (`<profile>@<endpoint>`) this connection is stored under. It
|
|
22
|
+
* keys the tunnel's runtime record; `profile.name` is the bare, user-facing
|
|
23
|
+
* name and appears only in messages (RUSH-2709).
|
|
24
|
+
*/
|
|
25
|
+
key: ConnectionKey): Promise<SSHConnection>;
|
|
20
26
|
/**
|
|
21
27
|
* Wrap a PowerShell script as a `-EncodedCommand` invocation. Base64 of the
|
|
22
28
|
* UTF-16LE bytes is a single quote-free token, so it rides through Node spawn
|
|
@@ -11,9 +11,15 @@ export { shellQuote };
|
|
|
11
11
|
// The `ssh -L` tunnel spawn is shared with `agents computer --device`; it lives in
|
|
12
12
|
// the single ssh-tunnel helper. Calling it with no options preserves this
|
|
13
13
|
// driver's original foreground, stderr-captured behavior exactly.
|
|
14
|
-
import { startSSHTunnel } from '../../ssh-tunnel.js';
|
|
14
|
+
import { startSSHTunnel } from '../../computer/ssh-tunnel.js';
|
|
15
15
|
import { encodePwshBase64 } from '../../pwsh.js';
|
|
16
|
-
export async function connectSSH(endpoint, profile
|
|
16
|
+
export async function connectSSH(endpoint, profile,
|
|
17
|
+
/**
|
|
18
|
+
* Runtime key (`<profile>@<endpoint>`) this connection is stored under. It
|
|
19
|
+
* keys the tunnel's runtime record; `profile.name` is the bare, user-facing
|
|
20
|
+
* name and appears only in messages (RUSH-2709).
|
|
21
|
+
*/
|
|
22
|
+
key) {
|
|
17
23
|
const url = new URL(endpoint);
|
|
18
24
|
if (url.protocol !== 'ssh:') {
|
|
19
25
|
throw new Error(`Invalid SSH endpoint: ${endpoint}`);
|
|
@@ -88,7 +94,7 @@ export async function connectSSH(endpoint, profile) {
|
|
|
88
94
|
// browser process.
|
|
89
95
|
const tunnelPid = tunnel.pid ?? 0;
|
|
90
96
|
if (tunnelPid > 0) {
|
|
91
|
-
writeProfileRuntime(
|
|
97
|
+
writeProfileRuntime(key, {
|
|
92
98
|
pid: 0,
|
|
93
99
|
port: localPort,
|
|
94
100
|
command: 'ssh',
|
|
@@ -108,7 +114,7 @@ export async function connectSSH(endpoint, profile) {
|
|
|
108
114
|
// stays synchronous, and killRemoteBrowser never rejects.
|
|
109
115
|
killRemoteBrowser(user, host, remoteOs, remotePort).catch(() => { });
|
|
110
116
|
tunnel.kill();
|
|
111
|
-
clearProfileRuntime(
|
|
117
|
+
clearProfileRuntime(key);
|
|
112
118
|
},
|
|
113
119
|
};
|
|
114
120
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type PidSessionEntry } from '../session/pid-registry.js';
|
|
2
|
-
import type
|
|
2
|
+
import { type ReapResult, type Task } from './types.js';
|
|
3
3
|
/** Default idle window before an untouched task is reaped. */
|
|
4
4
|
export declare const DEFAULT_IDLE_MS: number;
|
|
5
5
|
/**
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
*/
|
|
29
29
|
import { isPidAlive, isSessionIdLiveOnProcessTable } from '../session/active.js';
|
|
30
30
|
import { listPidSessionEntries, sessionIdFromLivePid } from '../session/pid-registry.js';
|
|
31
|
+
import { parseConnectionKey } from './types.js';
|
|
31
32
|
/** Default idle window before an untouched task is reaped. */
|
|
32
33
|
export const DEFAULT_IDLE_MS = 30 * 60_000;
|
|
33
34
|
/**
|
|
@@ -131,7 +132,10 @@ export async function reapAbandonedTasks(service, opts = {}) {
|
|
|
131
132
|
continue;
|
|
132
133
|
}
|
|
133
134
|
if (opts.dryRun) {
|
|
134
|
-
|
|
135
|
+
// Report the BARE profile, exactly as the real run does below — `profile`
|
|
136
|
+
// here is the runtime key from `listTasks()`, and printing the two shapes
|
|
137
|
+
// in one column made `gc --dry-run` and `gc` disagree (RUSH-2709).
|
|
138
|
+
closed.push({ task: task.name, profile: parseConnectionKey(profile).profile, reason });
|
|
135
139
|
continue;
|
|
136
140
|
}
|
|
137
141
|
const result = await service.stop(task.name);
|
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
import type { BrowserProfile } from './types.js';
|
|
2
2
|
export type { BrowserProfile } from './types.js';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Name of the profile `ensureDefaultBrowserProfile` auto-detects and pins.
|
|
5
|
+
*
|
|
6
|
+
* It is `auto-chrome`, NOT `default`, since RUSH-2709: `default` used to be
|
|
7
|
+
* both this concrete profile AND the alias meaning "whatever profile the user
|
|
8
|
+
* configured", so `--profile default` landed on a literal auto-detected Chrome
|
|
9
|
+
* on one command and on the user's configured Comet on another. The alias now
|
|
10
|
+
* lives alone in {@link DEFAULT_PROFILE_ALIAS} and resolves in exactly one
|
|
11
|
+
* place ({@link resolveProfileRef}).
|
|
12
|
+
*/
|
|
13
|
+
export declare const DEFAULT_BROWSER_PROFILE_NAME = "auto-chrome";
|
|
14
|
+
/**
|
|
15
|
+
* What older builds named the auto-detected profile. Still honored everywhere:
|
|
16
|
+
* a user whose machine already carries a `default` profile keeps using it (and
|
|
17
|
+
* its running browser + runtime dirs) rather than having a second one created
|
|
18
|
+
* beside it.
|
|
19
|
+
*/
|
|
20
|
+
export declare const LEGACY_DEFAULT_BROWSER_PROFILE_NAME = "default";
|
|
21
|
+
/**
|
|
22
|
+
* The reserved ALIAS. `--profile default` (and a `browser.profile` config value
|
|
23
|
+
* of `default`) means "the configured default profile", not a profile called
|
|
24
|
+
* `default` — unless a profile literally named `default` exists, which still
|
|
25
|
+
* wins, so no existing config breaks.
|
|
26
|
+
*/
|
|
27
|
+
export declare const DEFAULT_PROFILE_ALIAS = "default";
|
|
4
28
|
/**
|
|
5
29
|
* Where a profile is stored, and therefore who sees it:
|
|
6
30
|
* - `local` — this machine's `devices/<machine>/agents.yaml` (`deviceBrowser`)
|
|
@@ -75,6 +99,55 @@ export declare function isProfileLaunchableHere(profile: BrowserProfile): boolea
|
|
|
75
99
|
* that no longer exists, or can't launch here, warns and falls through — never a
|
|
76
100
|
* hard fail.
|
|
77
101
|
*/
|
|
102
|
+
/**
|
|
103
|
+
* The auto-detected profile this machine already carries, under either name —
|
|
104
|
+
* the current `auto-chrome` or the `default` an older build wrote. Callers that
|
|
105
|
+
* ask "is a default profile set up here?" MUST use this rather than probing one
|
|
106
|
+
* name, or a machine that predates the RUSH-2709 rename grows a second one.
|
|
107
|
+
*/
|
|
108
|
+
export declare function getAutoDetectedProfile(): Promise<BrowserProfile | null>;
|
|
109
|
+
/**
|
|
110
|
+
* Resolve what a caller typed after `--profile` to a real, BARE profile name.
|
|
111
|
+
* Every command — stop, status, navigate, tab, use, and (through
|
|
112
|
+
* {@link resolveProfileRefForStart}) start — routes through this one function,
|
|
113
|
+
* which is the whole point: before RUSH-2709 only `start` honored the reserved
|
|
114
|
+
* `default` alias, so `--profile default` meant three different profiles across
|
|
115
|
+
* three commands.
|
|
116
|
+
*
|
|
117
|
+
* Order:
|
|
118
|
+
* 1. A profile that literally bears the given name always wins — including
|
|
119
|
+
* one a user genuinely named `default`, which resolves to itself.
|
|
120
|
+
* 2. `default` (the alias) or no argument at all → the configured
|
|
121
|
+
* `browser.profile` for this machine, if it names a profile that exists.
|
|
122
|
+
* 3. → the auto-detected profile ({@link DEFAULT_BROWSER_PROFILE_NAME}), or
|
|
123
|
+
* its legacy `default`-named predecessor when that is what is on disk.
|
|
124
|
+
* 4. Otherwise the input is returned unchanged (so the caller reports its own
|
|
125
|
+
* `Profile "x" not found`), or `undefined` when nothing was passed.
|
|
126
|
+
*
|
|
127
|
+
* It never creates a profile, never warns, and never checks whether the profile
|
|
128
|
+
* can launch HERE. That is deliberate: for most callers `--profile` is a FILTER
|
|
129
|
+
* (`status`, `tasks`, `navigate --task`), where an absent flag means "no filter"
|
|
130
|
+
* and rewriting or warning about the user's config would be wrong. Note the
|
|
131
|
+
* corollary at those call sites — pass a ref only when the user gave one; do not
|
|
132
|
+
* resolve `undefined` into a concrete profile, or an unscoped listing silently
|
|
133
|
+
* becomes a scoped one.
|
|
134
|
+
*/
|
|
135
|
+
export declare function resolveProfileRef(ref?: string): Promise<string | undefined>;
|
|
136
|
+
/**
|
|
137
|
+
* `start`'s resolver. Same order as {@link resolveProfileRef} for an explicit
|
|
138
|
+
* name, but the IMPLICIT path (no `--profile`, or the bare `default` alias with
|
|
139
|
+
* no profile of that name) goes through {@link ensureDefaultBrowserProfile} —
|
|
140
|
+
* which additionally verifies the resolved default can launch on THIS machine,
|
|
141
|
+
* warns and falls through when it can't, and regenerates or creates one.
|
|
142
|
+
*
|
|
143
|
+
* `start` is the only command that launches a browser, so it is the only one
|
|
144
|
+
* that may do those things; routing a filter-only command through this would
|
|
145
|
+
* warn about, and rewrite, config the user never asked it to touch.
|
|
146
|
+
*
|
|
147
|
+
* Throws when no profile exists and no supported browser is installed —
|
|
148
|
+
* `ensureDefaultBrowserProfile`'s actionable "install one of …" error.
|
|
149
|
+
*/
|
|
150
|
+
export declare function resolveProfileRefForStart(ref?: string): Promise<string>;
|
|
78
151
|
export declare function ensureDefaultBrowserProfile(): Promise<BrowserProfile>;
|
|
79
152
|
/**
|
|
80
153
|
* Compute the LOCAL port a profile will occupy at runtime:
|
|
@@ -3,7 +3,31 @@ import { getBrowserRuntimeDir as getBrowserRuntimeDirRoot, readMeta, updateMeta,
|
|
|
3
3
|
import { getConfigValue } from '../device-config.js';
|
|
4
4
|
import { findBrowserPath, findFirstInstalledBrowser, isPortInUse } from './chrome.js';
|
|
5
5
|
import { DEFAULT_VIEWPORT } from './devices.js';
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Name of the profile `ensureDefaultBrowserProfile` auto-detects and pins.
|
|
8
|
+
*
|
|
9
|
+
* It is `auto-chrome`, NOT `default`, since RUSH-2709: `default` used to be
|
|
10
|
+
* both this concrete profile AND the alias meaning "whatever profile the user
|
|
11
|
+
* configured", so `--profile default` landed on a literal auto-detected Chrome
|
|
12
|
+
* on one command and on the user's configured Comet on another. The alias now
|
|
13
|
+
* lives alone in {@link DEFAULT_PROFILE_ALIAS} and resolves in exactly one
|
|
14
|
+
* place ({@link resolveProfileRef}).
|
|
15
|
+
*/
|
|
16
|
+
export const DEFAULT_BROWSER_PROFILE_NAME = 'auto-chrome';
|
|
17
|
+
/**
|
|
18
|
+
* What older builds named the auto-detected profile. Still honored everywhere:
|
|
19
|
+
* a user whose machine already carries a `default` profile keeps using it (and
|
|
20
|
+
* its running browser + runtime dirs) rather than having a second one created
|
|
21
|
+
* beside it.
|
|
22
|
+
*/
|
|
23
|
+
export const LEGACY_DEFAULT_BROWSER_PROFILE_NAME = 'default';
|
|
24
|
+
/**
|
|
25
|
+
* The reserved ALIAS. `--profile default` (and a `browser.profile` config value
|
|
26
|
+
* of `default`) means "the configured default profile", not a profile called
|
|
27
|
+
* `default` — unless a profile literally named `default` exists, which still
|
|
28
|
+
* wins, so no existing config breaks.
|
|
29
|
+
*/
|
|
30
|
+
export const DEFAULT_PROFILE_ALIAS = 'default';
|
|
7
31
|
/**
|
|
8
32
|
* True for a profile whose contents only make sense on THIS machine, so it must
|
|
9
33
|
* live in the per-machine doc rather than the fleet-synced agents.yaml.
|
|
@@ -21,7 +45,7 @@ export const DEFAULT_BROWSER_PROFILE_NAME = 'default';
|
|
|
21
45
|
* into central from being written back there by {@link updateProfile}.
|
|
22
46
|
*/
|
|
23
47
|
function isMachineLocalProfile(name) {
|
|
24
|
-
return name === DEFAULT_BROWSER_PROFILE_NAME;
|
|
48
|
+
return name === DEFAULT_BROWSER_PROFILE_NAME || name === LEGACY_DEFAULT_BROWSER_PROFILE_NAME;
|
|
25
49
|
}
|
|
26
50
|
/**
|
|
27
51
|
* The device-local configured default profile name (set via
|
|
@@ -178,9 +202,86 @@ export function isProfileLaunchableHere(profile) {
|
|
|
178
202
|
* that no longer exists, or can't launch here, warns and falls through — never a
|
|
179
203
|
* hard fail.
|
|
180
204
|
*/
|
|
205
|
+
/**
|
|
206
|
+
* The auto-detected profile this machine already carries, under either name —
|
|
207
|
+
* the current `auto-chrome` or the `default` an older build wrote. Callers that
|
|
208
|
+
* ask "is a default profile set up here?" MUST use this rather than probing one
|
|
209
|
+
* name, or a machine that predates the RUSH-2709 rename grows a second one.
|
|
210
|
+
*/
|
|
211
|
+
export async function getAutoDetectedProfile() {
|
|
212
|
+
return ((await getProfile(DEFAULT_BROWSER_PROFILE_NAME)) ??
|
|
213
|
+
(await getProfile(LEGACY_DEFAULT_BROWSER_PROFILE_NAME)));
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Resolve what a caller typed after `--profile` to a real, BARE profile name.
|
|
217
|
+
* Every command — stop, status, navigate, tab, use, and (through
|
|
218
|
+
* {@link resolveProfileRefForStart}) start — routes through this one function,
|
|
219
|
+
* which is the whole point: before RUSH-2709 only `start` honored the reserved
|
|
220
|
+
* `default` alias, so `--profile default` meant three different profiles across
|
|
221
|
+
* three commands.
|
|
222
|
+
*
|
|
223
|
+
* Order:
|
|
224
|
+
* 1. A profile that literally bears the given name always wins — including
|
|
225
|
+
* one a user genuinely named `default`, which resolves to itself.
|
|
226
|
+
* 2. `default` (the alias) or no argument at all → the configured
|
|
227
|
+
* `browser.profile` for this machine, if it names a profile that exists.
|
|
228
|
+
* 3. → the auto-detected profile ({@link DEFAULT_BROWSER_PROFILE_NAME}), or
|
|
229
|
+
* its legacy `default`-named predecessor when that is what is on disk.
|
|
230
|
+
* 4. Otherwise the input is returned unchanged (so the caller reports its own
|
|
231
|
+
* `Profile "x" not found`), or `undefined` when nothing was passed.
|
|
232
|
+
*
|
|
233
|
+
* It never creates a profile, never warns, and never checks whether the profile
|
|
234
|
+
* can launch HERE. That is deliberate: for most callers `--profile` is a FILTER
|
|
235
|
+
* (`status`, `tasks`, `navigate --task`), where an absent flag means "no filter"
|
|
236
|
+
* and rewriting or warning about the user's config would be wrong. Note the
|
|
237
|
+
* corollary at those call sites — pass a ref only when the user gave one; do not
|
|
238
|
+
* resolve `undefined` into a concrete profile, or an unscoped listing silently
|
|
239
|
+
* becomes a scoped one.
|
|
240
|
+
*/
|
|
241
|
+
export async function resolveProfileRef(ref) {
|
|
242
|
+
if (ref && ref !== DEFAULT_PROFILE_ALIAS) {
|
|
243
|
+
return ref;
|
|
244
|
+
}
|
|
245
|
+
if (ref === DEFAULT_PROFILE_ALIAS && (await getProfile(ref))) {
|
|
246
|
+
// A profile the user literally named `default` outranks the alias.
|
|
247
|
+
return ref;
|
|
248
|
+
}
|
|
249
|
+
const configured = getConfiguredDefaultProfileName();
|
|
250
|
+
if (configured && configured !== DEFAULT_PROFILE_ALIAS && (await getProfile(configured))) {
|
|
251
|
+
return configured;
|
|
252
|
+
}
|
|
253
|
+
if (await getProfile(DEFAULT_BROWSER_PROFILE_NAME))
|
|
254
|
+
return DEFAULT_BROWSER_PROFILE_NAME;
|
|
255
|
+
if (await getProfile(LEGACY_DEFAULT_BROWSER_PROFILE_NAME)) {
|
|
256
|
+
return LEGACY_DEFAULT_BROWSER_PROFILE_NAME;
|
|
257
|
+
}
|
|
258
|
+
return ref;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* `start`'s resolver. Same order as {@link resolveProfileRef} for an explicit
|
|
262
|
+
* name, but the IMPLICIT path (no `--profile`, or the bare `default` alias with
|
|
263
|
+
* no profile of that name) goes through {@link ensureDefaultBrowserProfile} —
|
|
264
|
+
* which additionally verifies the resolved default can launch on THIS machine,
|
|
265
|
+
* warns and falls through when it can't, and regenerates or creates one.
|
|
266
|
+
*
|
|
267
|
+
* `start` is the only command that launches a browser, so it is the only one
|
|
268
|
+
* that may do those things; routing a filter-only command through this would
|
|
269
|
+
* warn about, and rewrite, config the user never asked it to touch.
|
|
270
|
+
*
|
|
271
|
+
* Throws when no profile exists and no supported browser is installed —
|
|
272
|
+
* `ensureDefaultBrowserProfile`'s actionable "install one of …" error.
|
|
273
|
+
*/
|
|
274
|
+
export async function resolveProfileRefForStart(ref) {
|
|
275
|
+
if (ref && ref !== DEFAULT_PROFILE_ALIAS)
|
|
276
|
+
return ref;
|
|
277
|
+
// A profile the user literally named `default` still outranks the alias.
|
|
278
|
+
if (ref === DEFAULT_PROFILE_ALIAS && (await getProfile(ref)))
|
|
279
|
+
return ref;
|
|
280
|
+
return (await ensureDefaultBrowserProfile()).name;
|
|
281
|
+
}
|
|
181
282
|
export async function ensureDefaultBrowserProfile() {
|
|
182
283
|
const configured = getConfiguredDefaultProfileName();
|
|
183
|
-
if (configured) {
|
|
284
|
+
if (configured && configured !== DEFAULT_PROFILE_ALIAS) {
|
|
184
285
|
const chosen = await getProfile(configured);
|
|
185
286
|
if (chosen && isProfileLaunchableHere(chosen))
|
|
186
287
|
return chosen;
|
|
@@ -191,7 +292,12 @@ export async function ensureDefaultBrowserProfile() {
|
|
|
191
292
|
: `warning: configured default browser profile "${configured}" no longer exists; ` +
|
|
192
293
|
`falling back to auto-detect. Fix with: agents browser use <name> (or --unset)`);
|
|
193
294
|
}
|
|
194
|
-
|
|
295
|
+
// Prefer whichever auto-detected profile this machine already carries: the
|
|
296
|
+
// current `auto-chrome`, else the `default` an older build wrote. Reusing the
|
|
297
|
+
// legacy one is what keeps a currently-running browser (and its runtime dirs,
|
|
298
|
+
// keyed `default@endpoint-0`) attached after the rename.
|
|
299
|
+
const existing = (await getProfile(DEFAULT_BROWSER_PROFILE_NAME)) ??
|
|
300
|
+
(await getProfile(LEGACY_DEFAULT_BROWSER_PROFILE_NAME));
|
|
195
301
|
if (existing && isProfileLaunchableHere(existing))
|
|
196
302
|
return existing;
|
|
197
303
|
const detected = findFirstInstalledBrowser();
|
|
@@ -204,7 +310,10 @@ export async function ensureDefaultBrowserProfile() {
|
|
|
204
310
|
}
|
|
205
311
|
const freePort = await findFreeProfilePort();
|
|
206
312
|
const profile = {
|
|
207
|
-
name
|
|
313
|
+
// Regenerate under the name that is already on disk when there is one, so a
|
|
314
|
+
// stale legacy `default` is repaired in place instead of leaving the user
|
|
315
|
+
// with two auto-detected profiles.
|
|
316
|
+
name: existing?.name ?? DEFAULT_BROWSER_PROFILE_NAME,
|
|
208
317
|
description: `Auto-detected ${detected.browserType} profile`,
|
|
209
318
|
browser: detected.browserType,
|
|
210
319
|
binary: detected.binary,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ProfileScope } from './profiles.js';
|
|
2
|
+
import { type ProfileName } from './types.js';
|
|
2
3
|
/**
|
|
3
4
|
* Per-profile runtime files we persist under
|
|
4
5
|
* `~/.agents/.cache/browser/<composite>/`:
|
|
@@ -55,12 +56,16 @@ export declare function clearProfileRuntime(profileName: string): void;
|
|
|
55
56
|
*/
|
|
56
57
|
export declare function removeProfileCache(profileName: string): void;
|
|
57
58
|
/**
|
|
58
|
-
* Find every cache directory belonging to a given profile.
|
|
59
|
-
*
|
|
60
|
-
*
|
|
59
|
+
* Find every cache directory belonging to a given profile. A runtime dir name
|
|
60
|
+
* IS a connection key (`<name>@<endpoint>[.<fork>]`), so a single agents-cli
|
|
61
|
+
* profile can have several side by side; this finds them all, plus the legacy
|
|
61
62
|
* non-composite dir from older builds.
|
|
63
|
+
*
|
|
64
|
+
* Membership is decided by {@link keyBelongsToProfile} — the same single rule
|
|
65
|
+
* `status`, `stopProfile`, and `findTask` use (RUSH-2709), so a fork dir is no
|
|
66
|
+
* longer missed here while being matched there.
|
|
62
67
|
*/
|
|
63
|
-
export declare function listProfileCacheDirs(profileName:
|
|
68
|
+
export declare function listProfileCacheDirs(profileName: ProfileName): string[];
|
|
64
69
|
/**
|
|
65
70
|
* `process.kill(pid, 0)` answers "is a process with this id alive?" — but
|
|
66
71
|
* pid reuse is real on long-uptime machines, and a stale cache pointing
|
|
@@ -162,7 +167,8 @@ export declare const PRUNE_REASON_TEXT: Record<PruneReason, string>;
|
|
|
162
167
|
* - **in use** — a live browser, SSH tunnel, or open task on any of its dirs.
|
|
163
168
|
* - **the configured default** — this machine resolves a bare
|
|
164
169
|
* `agents browser start` to it; removing it breaks that command.
|
|
165
|
-
* -
|
|
170
|
+
* - **the auto-detected profile** (`auto-chrome`, or the `default` an older
|
|
171
|
+
* build wrote) — auto-regenerated by `ensureDefaultBrowserProfile`, so
|
|
166
172
|
* pruning it is pure churn.
|
|
167
173
|
* - **fleet-synced** — deleting one removes it from EVERY machine, so it takes
|
|
168
174
|
* the explicit `includeFleet` opt-in.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { execFileSync } from 'child_process';
|
|
4
|
-
import { getProfileRuntimeDir, getBrowserRuntimeDir, listProfilesWithScope, getConfiguredDefaultProfileName, isProfileLaunchableHere, deleteProfile, DEFAULT_BROWSER_PROFILE_NAME, } from './profiles.js';
|
|
4
|
+
import { getProfileRuntimeDir, getBrowserRuntimeDir, listProfilesWithScope, getConfiguredDefaultProfileName, isProfileLaunchableHere, deleteProfile, DEFAULT_BROWSER_PROFILE_NAME, LEGACY_DEFAULT_BROWSER_PROFILE_NAME, } from './profiles.js';
|
|
5
|
+
import { keyBelongsToProfile } from './types.js';
|
|
5
6
|
const PID_FILE = 'pid';
|
|
6
7
|
const PORT_FILE = 'port';
|
|
7
8
|
const COMMAND_FILE = 'command';
|
|
@@ -106,10 +107,14 @@ export function removeProfileCache(profileName) {
|
|
|
106
107
|
catch { /* gone */ }
|
|
107
108
|
}
|
|
108
109
|
/**
|
|
109
|
-
* Find every cache directory belonging to a given profile.
|
|
110
|
-
*
|
|
111
|
-
*
|
|
110
|
+
* Find every cache directory belonging to a given profile. A runtime dir name
|
|
111
|
+
* IS a connection key (`<name>@<endpoint>[.<fork>]`), so a single agents-cli
|
|
112
|
+
* profile can have several side by side; this finds them all, plus the legacy
|
|
112
113
|
* non-composite dir from older builds.
|
|
114
|
+
*
|
|
115
|
+
* Membership is decided by {@link keyBelongsToProfile} — the same single rule
|
|
116
|
+
* `status`, `stopProfile`, and `findTask` use (RUSH-2709), so a fork dir is no
|
|
117
|
+
* longer missed here while being matched there.
|
|
113
118
|
*/
|
|
114
119
|
export function listProfileCacheDirs(profileName) {
|
|
115
120
|
const root = getBrowserRuntimeDir();
|
|
@@ -117,9 +122,7 @@ export function listProfileCacheDirs(profileName) {
|
|
|
117
122
|
return [];
|
|
118
123
|
const matches = [];
|
|
119
124
|
for (const entry of fs.readdirSync(root)) {
|
|
120
|
-
if (entry
|
|
121
|
-
matches.push(path.join(root, entry));
|
|
122
|
-
else if (entry.startsWith(`${profileName}@`))
|
|
125
|
+
if (keyBelongsToProfile(entry, profileName))
|
|
123
126
|
matches.push(path.join(root, entry));
|
|
124
127
|
}
|
|
125
128
|
return matches;
|
|
@@ -292,7 +295,8 @@ export const PRUNE_REASON_TEXT = {
|
|
|
292
295
|
* - **in use** — a live browser, SSH tunnel, or open task on any of its dirs.
|
|
293
296
|
* - **the configured default** — this machine resolves a bare
|
|
294
297
|
* `agents browser start` to it; removing it breaks that command.
|
|
295
|
-
* -
|
|
298
|
+
* - **the auto-detected profile** (`auto-chrome`, or the `default` an older
|
|
299
|
+
* build wrote) — auto-regenerated by `ensureDefaultBrowserProfile`, so
|
|
296
300
|
* pruning it is pure churn.
|
|
297
301
|
* - **fleet-synced** — deleting one removes it from EVERY machine, so it takes
|
|
298
302
|
* the explicit `includeFleet` opt-in.
|
|
@@ -310,7 +314,7 @@ export function planProfilePrune(profiles, opts = {}) {
|
|
|
310
314
|
keep('fleet-synced (pass --fleet to include it)');
|
|
311
315
|
continue;
|
|
312
316
|
}
|
|
313
|
-
if (name === DEFAULT_BROWSER_PROFILE_NAME) {
|
|
317
|
+
if (name === DEFAULT_BROWSER_PROFILE_NAME || name === LEGACY_DEFAULT_BROWSER_PROFILE_NAME) {
|
|
314
318
|
keep('the auto-detected default profile');
|
|
315
319
|
continue;
|
|
316
320
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CDPClient } from './cdp.js';
|
|
2
2
|
import { type ResolvedDomainSkill } from './domain-skills.js';
|
|
3
|
-
import { type Task, type TabInfo, type ProfileStatus, type BrowserType, type HistoricalTask, type ReapResult } from './types.js';
|
|
3
|
+
import { type Task, type TabInfo, type ProfileStatus, type BrowserType, type HistoricalTask, type ReapResult, type ProfileName, type ConnectionKey } from './types.js';
|
|
4
4
|
import { type ReapOptions } from './hygiene.js';
|
|
5
5
|
import { type RefOpts, type RefNode } from './refs.js';
|
|
6
6
|
import type { TargetFilter } from './types.js';
|
|
@@ -60,19 +60,15 @@ interface ProfileConnection {
|
|
|
60
60
|
/** Raw `url:<v>` / `title:<v>` filter copied from the profile config. */
|
|
61
61
|
targetFilter?: string;
|
|
62
62
|
/**
|
|
63
|
-
* The
|
|
64
|
-
* (`<profile
|
|
65
|
-
*
|
|
66
|
-
* captures land under `.cache/browser/<
|
|
63
|
+
* The runtime key this connection is registered under in `this.connections`
|
|
64
|
+
* (`<profile>@<endpoint>`, plus `.<fork>` for an Electron fork; a bare name
|
|
65
|
+
* for a legacy pre-composite dir). Also keys the profile's runtime dir, so
|
|
66
|
+
* downloads and session captures land under `.cache/browser/<key>/`.
|
|
67
67
|
*/
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
* `comet-local@endpoint-0` without prefix-matching wrong browsers.
|
|
73
|
-
*/
|
|
74
|
-
bareName?: string;
|
|
75
|
-
forkedFrom?: string;
|
|
68
|
+
key?: ConnectionKey;
|
|
69
|
+
/** The bare, user-facing profile name this connection belongs to. */
|
|
70
|
+
profile?: ProfileName;
|
|
71
|
+
forkedFrom?: ConnectionKey;
|
|
76
72
|
tasks: Map<string, Task>;
|
|
77
73
|
windowId?: string;
|
|
78
74
|
targetCache?: {
|
|
@@ -104,12 +100,6 @@ export declare function deriveTaskLabel(opts: {
|
|
|
104
100
|
url?: string;
|
|
105
101
|
existing?: string;
|
|
106
102
|
}): string;
|
|
107
|
-
/**
|
|
108
|
-
* True when `key` is the bare profile name or one of its composite endpoint
|
|
109
|
-
* keys (`name@endpoint`). Used by status/stop so `comet-local` matches
|
|
110
|
-
* `comet-local@endpoint-0`.
|
|
111
|
-
*/
|
|
112
|
-
export declare function connectionKeyMatchesProfile(key: string, profileName: string): boolean;
|
|
113
103
|
type TargetInfo = {
|
|
114
104
|
targetId: string;
|
|
115
105
|
url?: string;
|
|
@@ -142,6 +132,12 @@ export declare function resolveTaskIdentity(forwarded: {
|
|
|
142
132
|
};
|
|
143
133
|
export declare class BrowserService {
|
|
144
134
|
private static readonly SOURCE_PREFIX;
|
|
135
|
+
/**
|
|
136
|
+
* Live browsers, keyed by {@link ConnectionKey} — NOT by profile name. The
|
|
137
|
+
* branded key type is what makes `connections.get(someProfileName)` (the
|
|
138
|
+
* RUSH-2709 miss that made `status --profile <name>` return empty for a
|
|
139
|
+
* running `<name>@endpoint-0`) fail to compile.
|
|
140
|
+
*/
|
|
145
141
|
private connections;
|
|
146
142
|
private forkingProfiles;
|
|
147
143
|
private consoleLogs;
|
|
@@ -172,7 +168,10 @@ export declare class BrowserService {
|
|
|
172
168
|
name: string;
|
|
173
169
|
tabId?: string;
|
|
174
170
|
windowId?: string;
|
|
175
|
-
profile
|
|
171
|
+
/** BARE profile name — what the caller asked for, never the runtime key. */
|
|
172
|
+
profile: ProfileName;
|
|
173
|
+
/** Runtime key the task actually landed on (`<profile>@<endpoint>`). */
|
|
174
|
+
key: ConnectionKey;
|
|
176
175
|
skill?: ResolvedDomainSkill;
|
|
177
176
|
}>;
|
|
178
177
|
/**
|
|
@@ -207,6 +206,25 @@ export declare class BrowserService {
|
|
|
207
206
|
* page that has since redirected elsewhere simply does not match, and the
|
|
208
207
|
* caller opens a tab as before.
|
|
209
208
|
*/
|
|
209
|
+
/** Is this CDP target already registered to any task on the connection? */
|
|
210
|
+
private targetIsClaimed;
|
|
211
|
+
/**
|
|
212
|
+
* The CDP targets a task may CLOSE — its own tabs minus any it merely
|
|
213
|
+
* borrowed. A borrowed tab existed before the task did (see `Task.borrowedTabs`),
|
|
214
|
+
* so closing it would remove something the task never opened.
|
|
215
|
+
*/
|
|
216
|
+
private closeableTargetIds;
|
|
217
|
+
/**
|
|
218
|
+
* A page target that `navigate` may take over on a browser which cannot create
|
|
219
|
+
* tabs (Arc). Deliberately narrow: only a tab ALREADY showing the requested URL
|
|
220
|
+
* -- re-showing that document there is what the caller asked for -- or an empty
|
|
221
|
+
* new-tab page. A target any task already owns is left alone. Note the honest
|
|
222
|
+
* limit: reusing a matching tab still RELOADS it, discarding scroll position and
|
|
223
|
+
* unsaved form state. Arc cannot open a tab at all, so some intrusion is
|
|
224
|
+
* unavoidable to show the document; a reload is the smallest one, and the tab is
|
|
225
|
+
* borrowed rather than owned so it is never closed.
|
|
226
|
+
*/
|
|
227
|
+
private pickReusableTargetWithoutCreate;
|
|
210
228
|
private adoptTabShowing;
|
|
211
229
|
/**
|
|
212
230
|
* Every live task across every connected profile — the reaper's input
|
|
@@ -214,7 +232,7 @@ export declare class BrowserService {
|
|
|
214
232
|
* daemon's live state, so callers only read it and act through `stop`.
|
|
215
233
|
*/
|
|
216
234
|
listTasks(): Array<{
|
|
217
|
-
profile:
|
|
235
|
+
profile: ConnectionKey;
|
|
218
236
|
task: Task;
|
|
219
237
|
}>;
|
|
220
238
|
/**
|
|
@@ -231,13 +249,13 @@ export declare class BrowserService {
|
|
|
231
249
|
ok: boolean;
|
|
232
250
|
profile?: string;
|
|
233
251
|
}>;
|
|
234
|
-
stopProfile(
|
|
235
|
-
navigate(taskId: string, url: string,
|
|
252
|
+
stopProfile(profileRef: ProfileName | ConnectionKey): Promise<void>;
|
|
253
|
+
navigate(taskId: string, url: string, profileRef?: ProfileName | ConnectionKey): Promise<{
|
|
236
254
|
tabId: string;
|
|
237
255
|
url: string;
|
|
238
256
|
created: boolean;
|
|
239
257
|
}>;
|
|
240
|
-
tabAdd(taskId: string, url: string,
|
|
258
|
+
tabAdd(taskId: string, url: string, profileRef?: ProfileName | ConnectionKey): Promise<{
|
|
241
259
|
tabId: string;
|
|
242
260
|
url: string;
|
|
243
261
|
}>;
|
|
@@ -253,7 +271,7 @@ export declare class BrowserService {
|
|
|
253
271
|
private resolveTabHint;
|
|
254
272
|
private resolveCurrentTab;
|
|
255
273
|
private getCdpTargetId;
|
|
256
|
-
tabs(taskId?: string,
|
|
274
|
+
tabs(taskId?: string, profileRef?: ProfileName | ConnectionKey): Promise<TabInfo[]>;
|
|
257
275
|
tabClose(taskId: string, tabHint?: string): Promise<void>;
|
|
258
276
|
evaluate(taskId: string, tabHint: string | undefined, expression: string): Promise<unknown>;
|
|
259
277
|
screenshot(taskId: string, tabHint?: string, outputPath?: string, quality?: 'compressed' | 'raw'): Promise<{
|
|
@@ -335,7 +353,25 @@ export declare class BrowserService {
|
|
|
335
353
|
stageUpload(source: string): {
|
|
336
354
|
path: string;
|
|
337
355
|
};
|
|
338
|
-
|
|
356
|
+
/**
|
|
357
|
+
* Status for one profile (bare name) or every live profile.
|
|
358
|
+
*
|
|
359
|
+
* `profileName` is a {@link ProfileName} — a BARE name, never a runtime key.
|
|
360
|
+
* Every candidate is selected by the one rule ({@link keyBelongsToProfile}),
|
|
361
|
+
* and a scoped query that finds no live connection falls through to disk, so
|
|
362
|
+
* `status --profile comet-local` reports the LIVE `comet-local@endpoint-0`
|
|
363
|
+
* instead of the empty list it used to return (RUSH-2709).
|
|
364
|
+
*/
|
|
365
|
+
status(profileRef?: ProfileName | ConnectionKey): Promise<ProfileStatus[]>;
|
|
366
|
+
/**
|
|
367
|
+
* Rebuild a profile's status from its runtime dirs when no live connection is
|
|
368
|
+
* registered — a daemon that never connected this profile, or a browser
|
|
369
|
+
* started by an earlier daemon.
|
|
370
|
+
*
|
|
371
|
+
* Takes a BARE profile name and walks every runtime key that belongs to it
|
|
372
|
+
* ({@link listProfileCacheDirs}), including the legacy pre-composite dir named
|
|
373
|
+
* exactly the profile.
|
|
374
|
+
*/
|
|
339
375
|
private reconcileFromDisk;
|
|
340
376
|
private profileStatusFromDisk;
|
|
341
377
|
setViewport(taskId: string, width: number, height: number, options?: {
|
|
@@ -400,9 +436,10 @@ export declare class BrowserService {
|
|
|
400
436
|
* already resolved the endpoint and built the `effectiveProfile` with
|
|
401
437
|
* the per-endpoint binary/targetFilter overrides applied; we just use it.
|
|
402
438
|
*
|
|
403
|
-
* `
|
|
404
|
-
* so per-endpoint pid/port files don't collide when the same app
|
|
405
|
-
* locally and remotely at the same time.
|
|
439
|
+
* `key` is the runtime key (`<profile>@<endpoint>`) and is what every on-disk
|
|
440
|
+
* lookup uses, so per-endpoint pid/port files don't collide when the same app
|
|
441
|
+
* runs locally and remotely at the same time. It is a SEPARATE argument
|
|
442
|
+
* because `effectiveProfile.name` stays the bare, user-facing name (RUSH-2709).
|
|
406
443
|
*/
|
|
407
444
|
private connectProfile;
|
|
408
445
|
private connectEndpoint;
|
|
@@ -443,7 +480,7 @@ export declare class BrowserService {
|
|
|
443
480
|
}): Promise<{
|
|
444
481
|
conn: ProfileConnection;
|
|
445
482
|
task: Task;
|
|
446
|
-
|
|
483
|
+
key: ConnectionKey;
|
|
447
484
|
created: boolean;
|
|
448
485
|
} | null>;
|
|
449
486
|
private listTasksForCaller;
|
|
@@ -491,6 +528,7 @@ export declare class BrowserService {
|
|
|
491
528
|
*/
|
|
492
529
|
private rehydrateTaskFromDisk;
|
|
493
530
|
private getTabsForTask;
|
|
531
|
+
/** Live status for ONE registered connection, addressed by its runtime key. */
|
|
494
532
|
private getProfileStatus;
|
|
495
533
|
private getTarget;
|
|
496
534
|
private getSessionId;
|