@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,124 +1,89 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `agents setup browser` —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* `agents setup browser` — get `agents browser` working on a fresh machine:
|
|
3
|
+
* install the standalone `browser` CLI (@phnx-labs/browser-cli), let it detect
|
|
4
|
+
* installed browsers and create machine-local profiles (`browser profiles seed`),
|
|
5
|
+
* then pick this machine's default (`browser use`).
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* The engine owns profile declarations and browser detection now (PHNX-4101), so
|
|
8
|
+
* this wizard DELEGATES to it rather than crafting profiles itself. What stays
|
|
9
|
+
* agents-cli's is the onboarding flow and the readiness check over the shared
|
|
10
|
+
* `browser.profile` config key both CLIs read/write.
|
|
11
|
+
*
|
|
12
|
+
* Idempotent: `profiles seed` leaves existing profiles untouched, and `use`
|
|
13
|
+
* re-points the device default.
|
|
9
14
|
*/
|
|
10
15
|
import { openSetupTerminal } from './setup-terminal.js';
|
|
11
16
|
import chalk from 'chalk';
|
|
12
|
-
import {
|
|
13
|
-
import { listInstalledBrowsers } from '../lib/browser/chrome.js';
|
|
14
|
-
import { DEFAULT_BROWSER_PROFILE_NAME, getAutoDetectedProfile, createProfile, findFreeProfilePort, getConfiguredDefaultProfileName, } from '../lib/browser/profiles.js';
|
|
15
|
-
import { DEFAULT_VIEWPORT } from '../lib/browser/devices.js';
|
|
17
|
+
import { getConfigValue } from '../lib/device-config.js';
|
|
16
18
|
import { isInteractiveTerminal, isPromptCancelled } from './utils.js';
|
|
17
|
-
import { defaultBrowserChoice } from './setup-preferences.js';
|
|
18
19
|
import { installSetupTool } from '../lib/setup-tool-install.js';
|
|
19
20
|
import { refreshToolSetup } from '../lib/setup-tool-status.js';
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
import { browserInstalled, runBrowser } from '../lib/browser-client.js';
|
|
22
|
+
import { buildBrowserContext } from '../lib/browser/context.js';
|
|
23
|
+
/** The device-local default profile, as both agents-cli and browser-cli see it. */
|
|
24
|
+
function configuredDefaultProfile() {
|
|
25
|
+
return getConfigValue('browser.profile').value || undefined;
|
|
26
|
+
}
|
|
27
|
+
/** Run one standalone `browser` verb, inheriting the terminal, and return its exit code. */
|
|
28
|
+
async function runBrowserVerb(argv) {
|
|
29
|
+
const { exitCode } = await runBrowser({ argv, context: await buildBrowserContext() });
|
|
30
|
+
return exitCode;
|
|
31
|
+
}
|
|
23
32
|
/**
|
|
24
|
-
* Interactive browser setup. Returns true if a
|
|
25
|
-
* afterwards, false if none
|
|
26
|
-
*
|
|
27
|
-
* silently minting a logged-out
|
|
28
|
-
*
|
|
29
|
-
*
|
|
33
|
+
* Interactive browser setup. Returns true if a default profile is configured
|
|
34
|
+
* afterwards, false if none is / the user backed out. Non-interactively it only
|
|
35
|
+
* RECOGNIZES an existing default — it never creates one (PHNX-3296), since
|
|
36
|
+
* silently minting a logged-out profile on a headless box is the exact bug that
|
|
37
|
+
* removed; a headless box gets its browser from the fleet hub. Never throws on
|
|
38
|
+
* cancel — the `agents setup` hub relies on that.
|
|
30
39
|
*/
|
|
31
40
|
export async function runBrowserWizard() {
|
|
32
41
|
if (!isInteractiveTerminal()) {
|
|
33
|
-
|
|
34
|
-
// one. Silently auto-detecting an installed browser and creating an
|
|
35
|
-
// `auto-chrome` here is exactly the bug PHNX-3296 removed — a headless box
|
|
36
|
-
// gets its browser from the fleet hub (`browser.device`), or from an
|
|
37
|
-
// interactive pick later.
|
|
38
|
-
const existing = await getAutoDetectedProfile();
|
|
42
|
+
const existing = configuredDefaultProfile();
|
|
39
43
|
if (existing) {
|
|
40
|
-
console.log(chalk.dim(`
|
|
44
|
+
console.log(chalk.dim(`Default browser profile "${existing}" already configured on this machine.`));
|
|
41
45
|
return true;
|
|
42
46
|
}
|
|
43
47
|
console.log(chalk.dim('No default browser profile on this machine. Re-run `agents setup browser` in an ' +
|
|
44
48
|
'interactive terminal to pick one, or use the fleet hub: agents config set browser.device <host>.'));
|
|
45
49
|
return false;
|
|
46
50
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
const { confirm, select } = await import('@inquirer/prompts');
|
|
54
|
-
// If a default profile already exists, this is a reconfigure.
|
|
55
|
-
const existing = await getAutoDetectedProfile();
|
|
56
|
-
if (existing) {
|
|
57
|
-
console.log(chalk.dim(`Browser profile "${existing.name}" already exists (${existing.browser}${existing.binary ? ` · ${existing.binary}` : ''}).`));
|
|
58
|
-
const change = await confirm({ message: 'Re-create it (e.g. to pin a different browser)?', default: false });
|
|
59
|
-
if (!change) {
|
|
60
|
-
await maybeSetDeviceDefault(existing.name, confirm);
|
|
61
|
-
printOnboardingNextStep(existing.name);
|
|
62
|
-
return true;
|
|
51
|
+
if (!browserInstalled()) {
|
|
52
|
+
console.log(chalk.dim('Installing the standalone Browser CLI (@phnx-labs/browser-cli)…'));
|
|
53
|
+
if (!(await installSetupTool('browser'))) {
|
|
54
|
+
console.error(chalk.red('Could not install @phnx-labs/browser-cli. Install it manually with `npm i -g @phnx-labs/browser-cli`, then re-run.'));
|
|
55
|
+
return false;
|
|
63
56
|
}
|
|
64
|
-
// Re-create: drop the old one so createProfile doesn't collide.
|
|
65
|
-
const { deleteProfile } = await import('../lib/browser/profiles.js');
|
|
66
|
-
await deleteProfile(existing.name);
|
|
67
57
|
}
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
message: 'Which browser should the default profile use?',
|
|
75
|
-
default: defaultBrowserChoice(installed) ?? undefined,
|
|
76
|
-
choices: installed.map((b) => ({ name: `${b.browserType} ${chalk.dim(b.binary)}`, value: b.browserType })),
|
|
77
|
-
});
|
|
78
|
-
chosen = installed.find((b) => b.browserType === value) ?? installed[0];
|
|
58
|
+
// Let the engine detect installed browsers and create a machine-local profile
|
|
59
|
+
// for each (idempotent), then open its own picker to set this machine's default.
|
|
60
|
+
const seedCode = await runBrowserVerb(['profiles', 'seed']);
|
|
61
|
+
if (seedCode !== 0) {
|
|
62
|
+
console.error(chalk.red('`browser profiles seed` failed — see the output above.'));
|
|
63
|
+
return false;
|
|
79
64
|
}
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
binary: chosen.binary,
|
|
86
|
-
endpoints: [`cdp://127.0.0.1:${freePort}`],
|
|
87
|
-
viewport: { width: DEFAULT_VIEWPORT.width, height: DEFAULT_VIEWPORT.height },
|
|
88
|
-
};
|
|
89
|
-
await createProfile(profile);
|
|
90
|
-
console.log(chalk.green(`\nCreated browser profile "${profile.name}" → ${chosen.browserType} (CDP 127.0.0.1:${freePort}).`));
|
|
91
|
-
await maybeSetDeviceDefault(profile.name, confirm);
|
|
92
|
-
printOnboardingNextStep(profile.name);
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
/** Offer to make `name` this machine's default browser profile (device-local). */
|
|
96
|
-
async function maybeSetDeviceDefault(name, confirm) {
|
|
97
|
-
const current = getConfiguredDefaultProfileName();
|
|
98
|
-
if (current === name)
|
|
99
|
-
return; // already the device default
|
|
100
|
-
const set = await confirm({
|
|
101
|
-
message: `Make "${name}" this machine's default browser profile?`,
|
|
102
|
-
default: true,
|
|
103
|
-
});
|
|
104
|
-
if (set) {
|
|
105
|
-
setConfigValue('browser.profile', name);
|
|
106
|
-
console.log(chalk.dim(`Bare \`agents browser start\` will now use "${name}" on this machine.`));
|
|
65
|
+
await runBrowserVerb(['use']);
|
|
66
|
+
const chosen = configuredDefaultProfile();
|
|
67
|
+
if (!chosen) {
|
|
68
|
+
console.log(chalk.dim('No default profile chosen. Run `agents browser use <name>` later to set one.'));
|
|
69
|
+
return false;
|
|
107
70
|
}
|
|
71
|
+
printOnboardingNextStep(chosen);
|
|
72
|
+
return true;
|
|
108
73
|
}
|
|
109
|
-
/** The one step we can't automate:
|
|
74
|
+
/** The one step we can't automate: the browser's first-run + your own sign-in. */
|
|
110
75
|
function printOnboardingNextStep(name) {
|
|
111
76
|
console.log(chalk.bold('\nOne manual step left:'));
|
|
112
77
|
console.log(' ' +
|
|
113
78
|
chalk.cyan(`agents browser start --profile ${name}`) +
|
|
114
|
-
chalk.dim(' # finish
|
|
79
|
+
chalk.dim(' # finish the browser first-run + sign in to any sites you want automated'));
|
|
115
80
|
console.log(chalk.dim(` Then check it's ready: agents browser profiles doctor ${name}`));
|
|
116
81
|
}
|
|
117
82
|
/** Register `agents setup browser` under the parent `setup` command. */
|
|
118
83
|
export function registerSetupBrowserCommand(setupCmd) {
|
|
119
84
|
setupCmd
|
|
120
85
|
.command('browser')
|
|
121
|
-
.description('Set up `agents browser` —
|
|
86
|
+
.description('Set up `agents browser` — install the Browser CLI, seed profiles, and pick this machine\'s default.')
|
|
122
87
|
.option('--install-only', 'Install the standalone Browser CLI without changing profiles or starting a browser')
|
|
123
88
|
.option('--terminal [backend]', 'Open interactive setup in a detected or selected terminal')
|
|
124
89
|
.action(async (options) => {
|
|
@@ -21,14 +21,6 @@ export declare function macDeviceNames(reg: DeviceRegistry): string[];
|
|
|
21
21
|
* first candidate. null when there are no candidates.
|
|
22
22
|
*/
|
|
23
23
|
export declare function defaultInteractiveHostChoice(candidates: string[], self?: string): string | null;
|
|
24
|
-
/**
|
|
25
|
-
* The browser picker's highlighted default — the same browser auto-detect
|
|
26
|
-
* would win, since `listInstalledBrowsers` returns platform priority order
|
|
27
|
-
* (macOS: chrome first). null when nothing is installed.
|
|
28
|
-
*/
|
|
29
|
-
export declare function defaultBrowserChoice<T extends {
|
|
30
|
-
browserType: string;
|
|
31
|
-
}>(installed: T[]): T['browserType'] | null;
|
|
32
24
|
/**
|
|
33
25
|
* Offer to set the interactive host when none is configured and the registry
|
|
34
26
|
* has more than one macOS device. Returns true when a host was set. Silent
|
|
@@ -53,15 +45,6 @@ export declare function maybePickInteractiveHost(): Promise<boolean>;
|
|
|
53
45
|
export declare function maybePickBrowserProfile(deps?: {
|
|
54
46
|
/** Force interactivity in a test; defaults to a real TTY probe. */
|
|
55
47
|
interactive?: boolean;
|
|
56
|
-
/** Inject the prompt so the pick is testable without a TTY. */
|
|
57
|
-
select?: (config: {
|
|
58
|
-
message: string;
|
|
59
|
-
default?: string;
|
|
60
|
-
choices: Array<{
|
|
61
|
-
name: string;
|
|
62
|
-
value: string;
|
|
63
|
-
}>;
|
|
64
|
-
}) => Promise<string>;
|
|
65
48
|
}): Promise<boolean>;
|
|
66
49
|
/**
|
|
67
50
|
* The bare-`agents setup` preferences step: interactive host, then browser.
|
|
@@ -13,9 +13,8 @@
|
|
|
13
13
|
* partial state.
|
|
14
14
|
*/
|
|
15
15
|
import chalk from 'chalk';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import { DEFAULT_VIEWPORT } from '../lib/browser/devices.js';
|
|
16
|
+
import { browserInstalled, runBrowser } from '../lib/browser-client.js';
|
|
17
|
+
import { buildBrowserContext } from '../lib/browser/context.js';
|
|
19
18
|
import { getConfigValue, setConfigValue } from '../lib/device-config.js';
|
|
20
19
|
import { loadDevices } from '../lib/devices/registry.js';
|
|
21
20
|
import { machineId } from '../lib/machine-id.js';
|
|
@@ -38,14 +37,6 @@ export function defaultInteractiveHostChoice(candidates, self = machineId()) {
|
|
|
38
37
|
return null;
|
|
39
38
|
return candidates.includes(self) ? self : candidates[0];
|
|
40
39
|
}
|
|
41
|
-
/**
|
|
42
|
-
* The browser picker's highlighted default — the same browser auto-detect
|
|
43
|
-
* would win, since `listInstalledBrowsers` returns platform priority order
|
|
44
|
-
* (macOS: chrome first). null when nothing is installed.
|
|
45
|
-
*/
|
|
46
|
-
export function defaultBrowserChoice(installed) {
|
|
47
|
-
return installed.length > 0 ? installed[0].browserType : null;
|
|
48
|
-
}
|
|
49
40
|
/**
|
|
50
41
|
* Offer to set the interactive host when none is configured and the registry
|
|
51
42
|
* has more than one macOS device. Returns true when a host was set. Silent
|
|
@@ -94,48 +85,26 @@ export async function maybePickBrowserProfile(deps = {}) {
|
|
|
94
85
|
const interactive = deps.interactive ?? isInteractiveTerminal();
|
|
95
86
|
if (!interactive)
|
|
96
87
|
return false;
|
|
97
|
-
|
|
88
|
+
// Already chosen (by an earlier setup, `agents browser use`, or browser-cli
|
|
89
|
+
// directly) — never re-pin behind the user's back.
|
|
90
|
+
if (getConfigValue('browser.profile').value)
|
|
98
91
|
return false;
|
|
99
|
-
|
|
92
|
+
// The engine owns detection and profile creation (PHNX-4101); it is optional,
|
|
93
|
+
// so skip the pick quietly when it is not installed rather than nagging.
|
|
94
|
+
if (!browserInstalled())
|
|
100
95
|
return false;
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
// Let the engine detect installed browsers and create a machine-local profile
|
|
97
|
+
// for each (idempotent), then open its own picker to set this machine's default.
|
|
98
|
+
const context = await buildBrowserContext();
|
|
99
|
+
const seed = await runBrowser({ argv: ['profiles', 'seed'], context });
|
|
100
|
+
if (seed.exitCode !== 0)
|
|
103
101
|
return false;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
choices: [
|
|
108
|
-
...installed.map((b) => ({ name: `${b.browserType} ${chalk.dim(b.binary)}`, value: b.browserType })),
|
|
109
|
-
{ name: `None ${chalk.dim('— this box uses the fleet hub (agents config set browser.device <host>)')}`, value: SKIP },
|
|
110
|
-
],
|
|
111
|
-
};
|
|
112
|
-
// The prompt is the only non-testable boundary here, so it is injectable —
|
|
113
|
-
// everything after (createProfile, setConfigValue) runs for real.
|
|
114
|
-
let picked;
|
|
115
|
-
if (deps.select) {
|
|
116
|
-
picked = await deps.select(config);
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
const { select } = await import('@inquirer/prompts');
|
|
120
|
-
picked = await select(config);
|
|
121
|
-
}
|
|
122
|
-
if (picked === SKIP)
|
|
102
|
+
await runBrowser({ argv: ['use'], context });
|
|
103
|
+
const chosen = getConfigValue('browser.profile').value;
|
|
104
|
+
if (!chosen)
|
|
123
105
|
return false;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const profile = {
|
|
127
|
-
name: DEFAULT_BROWSER_PROFILE_NAME,
|
|
128
|
-
description: `${chosen.browserType} profile (chosen during setup)`,
|
|
129
|
-
browser: chosen.browserType,
|
|
130
|
-
binary: chosen.binary,
|
|
131
|
-
endpoints: [`cdp://127.0.0.1:${freePort}`],
|
|
132
|
-
viewport: { width: DEFAULT_VIEWPORT.width, height: DEFAULT_VIEWPORT.height },
|
|
133
|
-
};
|
|
134
|
-
await createProfile(profile);
|
|
135
|
-
// The same key `agents browser use` writes (device-local).
|
|
136
|
-
setConfigValue('browser.profile', profile.name);
|
|
137
|
-
console.log(chalk.green(`Browser: '${chosen.browserType}'`) +
|
|
138
|
-
chalk.dim(` — profile "${profile.name}" is this machine's default (agents browser use to change).`));
|
|
106
|
+
console.log(chalk.green(`Browser: '${chosen}'`) +
|
|
107
|
+
chalk.dim(' — this machine\'s default (agents browser use to change).'));
|
|
139
108
|
return true;
|
|
140
109
|
}
|
|
141
110
|
/**
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* `agents setup term` — install the standalone `term` CLI if missing (PHNX-4092).
|
|
3
3
|
*
|
|
4
4
|
* The PTY engine lives in `@phnx-labs/term-cli` (extracted PHNX-4091);
|
|
5
|
-
* agents-cli never rebundles it. The
|
|
6
|
-
*
|
|
7
|
-
* absent, so onboarding installs it here
|
|
5
|
+
* agents-cli never rebundles it. The setup-token mint behind `agents accounts
|
|
6
|
+
* add` / `agents accounts login` (auth-mint.ts → term-driver.ts) spawns `term`
|
|
7
|
+
* on demand and fails loud when it is absent, so onboarding installs it here
|
|
8
|
+
* like every other standalone tool.
|
|
8
9
|
*
|
|
9
10
|
* Unlike browser/computer/secrets there is nothing to configure — no profile,
|
|
10
11
|
* no OS permission, no migrate step. A missing binary is a routine install
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* `agents setup term` — install the standalone `term` CLI if missing (PHNX-4092).
|
|
3
3
|
*
|
|
4
4
|
* The PTY engine lives in `@phnx-labs/term-cli` (extracted PHNX-4091);
|
|
5
|
-
* agents-cli never rebundles it. The
|
|
6
|
-
*
|
|
7
|
-
* absent, so onboarding installs it here
|
|
5
|
+
* agents-cli never rebundles it. The setup-token mint behind `agents accounts
|
|
6
|
+
* add` / `agents accounts login` (auth-mint.ts → term-driver.ts) spawns `term`
|
|
7
|
+
* on demand and fails loud when it is absent, so onboarding installs it here
|
|
8
|
+
* like every other standalone tool.
|
|
8
9
|
*
|
|
9
10
|
* Unlike browser/computer/secrets there is nothing to configure — no profile,
|
|
10
11
|
* no OS permission, no migrate step. A missing binary is a routine install
|
|
@@ -45,7 +46,7 @@ export async function runTermWizard() {
|
|
|
45
46
|
export function registerSetupTermCommand(setupCmd) {
|
|
46
47
|
setupCmd
|
|
47
48
|
.command('term')
|
|
48
|
-
.description('Install the standalone `term` CLI (the PTY engine
|
|
49
|
+
.description('Install the standalone `term` CLI (the PTY engine `agents accounts add`/`login` spawn) if missing.')
|
|
49
50
|
.option('--install-only', 'Install the standalone term CLI (identical to the wizard; term needs no further setup)')
|
|
50
51
|
.option('--terminal [backend]', 'Open interactive setup in a detected or selected terminal')
|
|
51
52
|
.action(async (options) => {
|
package/dist/commands/setup.js
CHANGED
|
@@ -31,8 +31,7 @@ import { registerAliasCommand } from './alias.js';
|
|
|
31
31
|
import { registerBetaCommands } from './beta.js';
|
|
32
32
|
import { addUrlSchemeSubcommands } from './open.js';
|
|
33
33
|
import { runPreferencesStep } from './setup-preferences.js';
|
|
34
|
-
import {
|
|
35
|
-
import { listInstalledBrowsers } from '../lib/browser/chrome.js';
|
|
34
|
+
import { browserInstalled } from '../lib/browser-client.js';
|
|
36
35
|
import { probeComputerTrust } from './computer.js';
|
|
37
36
|
import { loadDevices } from '../lib/devices/registry.js';
|
|
38
37
|
import { getConfigValue } from '../lib/device-config.js';
|
|
@@ -269,12 +268,13 @@ export async function ensureInitialized(program) {
|
|
|
269
268
|
await runSetup(program, { suppressFooter: true });
|
|
270
269
|
}
|
|
271
270
|
export async function getSetupStatus() {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
const
|
|
277
|
-
const
|
|
271
|
+
// Browser readiness is now config + standalone presence (PHNX-4101): the engine
|
|
272
|
+
// (@phnx-labs/browser-cli) owns profile declarations and launchability, so
|
|
273
|
+
// agents-cli reads the shared default-profile key it and browser-cli both write
|
|
274
|
+
// rather than resolving a profile through a deleted in-repo engine.
|
|
275
|
+
const browserCliInstalled = browserInstalled();
|
|
276
|
+
const configuredBrowserProfile = getConfigValue('browser.profile').value;
|
|
277
|
+
const browserReady = browserCliInstalled && !!configuredBrowserProfile;
|
|
278
278
|
const computerState = process.platform === 'darwin' ? (await probeComputerTrust() ? 'ready' : 'missing') : 'n/a';
|
|
279
279
|
const devices = await loadDevices();
|
|
280
280
|
const coreReady = isGitRepo(getAgentsDir());
|
|
@@ -286,10 +286,10 @@ export async function getSetupStatus() {
|
|
|
286
286
|
const defaultBrowser = getConfigValue('browser.profile').value;
|
|
287
287
|
return [
|
|
288
288
|
{ phase: 'core', state: coreReady ? 'ready' : 'missing', detail: coreReady ? 'system repo ready' : 'system repo missing' },
|
|
289
|
-
{ phase: 'browser', state: browserReady ? 'ready' : 'missing', detail: browserReady ? `profile ${
|
|
289
|
+
{ phase: 'browser', state: browserReady ? 'ready' : 'missing', detail: browserReady ? `profile ${configuredBrowserProfile}` : !browserCliInstalled ? 'browser CLI not installed (npm i -g @phnx-labs/browser-cli)' : 'no default profile (agents setup browser)' },
|
|
290
290
|
{ phase: 'computer', state: computerState, detail: computerState === 'ready' ? 'helper trusted' : computerState === 'n/a' ? 'macOS local setup only' : 'helper not running or not trusted' },
|
|
291
291
|
{ phase: 'secrets', state: secretsReady ? 'ready' : 'missing', detail: secretsReady ? 'defaults chosen' : 'defaults not chosen' },
|
|
292
|
-
{ phase: 'term', state: termReady ? 'ready' : 'missing', detail: termReady ? 'installed' : 'not installed (
|
|
292
|
+
{ phase: 'term', state: termReady ? 'ready' : 'missing', detail: termReady ? 'installed' : 'not installed (accounts add/login spawn it)' },
|
|
293
293
|
{ phase: 'accounts', state: minted.ready ? 'ready' : 'missing', detail: minted.detail },
|
|
294
294
|
{ phase: 'fleet', state: Object.keys(devices).length ? 'ready' : 'missing', detail: Object.keys(devices).length ? `${Object.keys(devices).length} device${Object.keys(devices).length === 1 ? '' : 's'} registered` : 'no devices registered' },
|
|
295
295
|
{ phase: 'watchdog', state: watchdogEnabled ? 'ready' : 'missing', detail: watchdogEnabled ? 'enabled on this device' : 'disabled on this device' },
|
|
@@ -462,7 +462,7 @@ export function registerSetupCommand(program) {
|
|
|
462
462
|
agents setup browser # detect a browser + create the default profile
|
|
463
463
|
agents setup computer # install the signed macOS helper + grant permissions
|
|
464
464
|
agents setup secrets # choose secrets backend/policy defaults + import
|
|
465
|
-
agents setup term # install the standalone term CLI (PTY engine
|
|
465
|
+
agents setup term # install the standalone term CLI (PTY engine agents accounts add/login spawn)
|
|
466
466
|
agents setup accounts # mint a Claude setup-token for unattended usage/probe
|
|
467
467
|
agents setup fleet # discover Tailscale devices + configure SSH access
|
|
468
468
|
agents setup watchdog # choose which devices run the daemon watchdog pass
|
package/dist/commands/ssh.js
CHANGED
|
@@ -789,7 +789,16 @@ async function runFleetPing(opts) {
|
|
|
789
789
|
if (opts.local) {
|
|
790
790
|
const { authRows: rows } = await refreshLocalFleetAuthState({ force: true });
|
|
791
791
|
if (opts.json) {
|
|
792
|
-
|
|
792
|
+
// Per-agent launchability from the SAME run-router path the local readiness
|
|
793
|
+
// check uses (`collectRunCandidates`/`isLaunchableSignedIn`), so a consumer
|
|
794
|
+
// can tell a box that simply could not probe — a worker's setup-token box,
|
|
795
|
+
// or a headed box that spent its usage-endpoint budget, both DROP their
|
|
796
|
+
// `no_evidence` row — from a box with no credential at all. From `rows`
|
|
797
|
+
// alone the two are indistinguishable, which broke `--host` routine
|
|
798
|
+
// readiness on every worker (PHNX-4116).
|
|
799
|
+
const { collectRunCandidates } = await import('../lib/accounting/rotate.js');
|
|
800
|
+
const launchable = (await Promise.all(ALL_AGENT_IDS.map(async (agent) => (await collectRunCandidates(agent)).some((candidate) => candidate.signedIn) ? agent : null))).filter((agent) => agent !== null);
|
|
801
|
+
console.log(JSON.stringify({ host: self, rows, launchable }));
|
|
793
802
|
}
|
|
794
803
|
else {
|
|
795
804
|
for (const line of renderAuthMatrix([{ host: self, rows }], { verbose: opts.verbose }))
|
package/dist/commands/sync.js
CHANGED
|
@@ -35,8 +35,6 @@ import { Option } from 'commander';
|
|
|
35
35
|
import chalk from 'chalk';
|
|
36
36
|
import { resolveSyncPassphraseFromEnv } from '../lib/sync-passphrase.js';
|
|
37
37
|
import { agentLabel, resolveAgentName, MANAGED_AGENT_IDS, isAgentHardDeprecated, hardDeprecationError } from '../lib/agents.js';
|
|
38
|
-
import { autoEvictCentralBrowserProfiles } from '../lib/browser/registry.js';
|
|
39
|
-
import { shouldAutoClaimCentralProfile } from '../lib/browser/profiles.js';
|
|
40
38
|
import { isVersionInstalled, syncResourcesToVersion, parseAgentSpec, resolveVersion, resolveVersionAlias, listInstalledVersions, healDanglingVersionPointers, getAvailableResources, getActuallySyncedResources, getProjectOnlyResources, getNewResources, hasNewResources, promptResourceSelection, promptNewResourceSelection, buildSelection, mergeRepoScopedSelections, listRepoNames, getVersionHomePath, } from '../lib/installations/versions.js';
|
|
41
39
|
import { capableAgents } from '../lib/capabilities.js';
|
|
42
40
|
import { parseHookManifest, registerHooksToSettings } from '../lib/hooks/install.js';
|
|
@@ -397,12 +395,9 @@ async function runInteractiveReconcile(opts, outLog, errLog) {
|
|
|
397
395
|
else
|
|
398
396
|
outLog(chalk.yellow(` ! ${repo}: ${(res.error ?? 'pull failed').split('\n')[0]}`));
|
|
399
397
|
}
|
|
400
|
-
//
|
|
401
|
-
//
|
|
402
|
-
//
|
|
403
|
-
// already migrated (which would flip that profile's kind identity->fungible).
|
|
404
|
-
// The interactive path is always non-quiet, non-json.
|
|
405
|
-
evictCentralBrowserProfilesForSync(false, false, outLog, errLog);
|
|
398
|
+
// Central browser-profile claiming is the standalone `browser` CLI's now
|
|
399
|
+
// (PHNX-4101): `browser profiles claim` / `browser profiles prune` own it.
|
|
400
|
+
// agents-cli no longer evicts central `browser:` tombstones on sync.
|
|
406
401
|
// 2. One selection spanning the chosen repos.
|
|
407
402
|
const selection = mergeRepoScopedSelections(repos, cwd);
|
|
408
403
|
const hasResources = selection.memory === 'all' || Object.entries(selection).some(([kind, v]) => kind !== 'memory' && Array.isArray(v) && v.length > 0);
|
|
@@ -443,36 +438,6 @@ async function runInteractiveReconcile(opts, outLog, errLog) {
|
|
|
443
438
|
if (repairHadFailures(umbrellaRepair))
|
|
444
439
|
process.exitCode = 1;
|
|
445
440
|
}
|
|
446
|
-
/**
|
|
447
|
-
* Drain the legacy central `browser:` tombstone during `agents sync` (PHNX-3315).
|
|
448
|
-
* New profiles write the per-device doc, but profiles created before the
|
|
449
|
-
* device-scoped store lingered in the shared top-level `agents.yaml` and churned
|
|
450
|
-
* every fleet pull until someone ran `agents browser profiles claim` by hand.
|
|
451
|
-
* Fold the ones THIS box can host into its device doc — host-gated, and the
|
|
452
|
-
* selection is computed under the meta lock (see autoEvictCentralBrowserProfiles)
|
|
453
|
-
* so it never races itself. Callers MUST invoke this AFTER the repo pull: acting
|
|
454
|
-
* on a pre-pull view of central risks re-claiming a profile a peer already
|
|
455
|
-
* drained, which would flip its kind identity->fungible. Non-fatal so a hiccup
|
|
456
|
-
* can never wedge the sync.
|
|
457
|
-
*/
|
|
458
|
-
function evictCentralBrowserProfilesForSync(quiet, json, outLog, errLog) {
|
|
459
|
-
try {
|
|
460
|
-
// Auto-claim ONLY remote (ssh://) tombstones — they are fungible by design,
|
|
461
|
-
// so a concurrent cross-machine double-claim is harmless. Local/cdp profiles
|
|
462
|
-
// have no per-machine ownership signal and are left central for an explicit
|
|
463
|
-
// `agents browser profiles claim` (PHNX-3315 review). See
|
|
464
|
-
// shouldAutoClaimCentralProfile.
|
|
465
|
-
const result = autoEvictCentralBrowserProfiles(shouldAutoClaimCentralProfile);
|
|
466
|
-
if (!quiet && !json && result.claimed.length > 0) {
|
|
467
|
-
outLog(chalk.gray(` Claimed ${result.claimed.length} central browser profile(s) into this device: ${result.claimed.join(', ')}`));
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
catch (err) {
|
|
471
|
-
if (!quiet && !json) {
|
|
472
|
-
errLog(chalk.yellow(` ! browser profile eviction skipped: ${err.message}`));
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
441
|
/**
|
|
477
442
|
* The umbrella verb: bare `agents sync` (no agent) makes this machine current.
|
|
478
443
|
* Resolves the flags + a secrets passphrase (env-only for now; tokenized auth
|
|
@@ -550,12 +515,9 @@ async function runUmbrella(opts, quiet, outLog, errLog, json = false) {
|
|
|
550
515
|
log: (msg) => { if (!quiet && !json)
|
|
551
516
|
outLog(chalk.gray(` ${msg}`)); },
|
|
552
517
|
});
|
|
553
|
-
//
|
|
554
|
-
//
|
|
555
|
-
//
|
|
556
|
-
// --cloud (fetch-only, no local reconcile).
|
|
557
|
-
if (!opts.cloud && !kindSelection)
|
|
558
|
-
evictCentralBrowserProfilesForSync(quiet, json, outLog, errLog);
|
|
518
|
+
// Central browser-profile claiming moved to the standalone `browser` CLI
|
|
519
|
+
// (PHNX-4101: `browser profiles claim` / `prune`), so `agents sync` no longer
|
|
520
|
+
// drains the central `browser:` tombstone.
|
|
559
521
|
// Post-reconcile verification (PHNX-3186): re-read every version the reconcile
|
|
560
522
|
// wrote into and confirm it now matches source. Without this the umbrella
|
|
561
523
|
// printed `✓ sync: reconciled` unconditionally, the exact false-success the
|
package/dist/commands/teams.js
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import type { Command } from 'commander';
|
|
2
2
|
import type { AgentId } from '../lib/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Split `<agent>[@<selector>]`. The selector names an INSTALLATION — its frozen
|
|
5
|
+
* label, or the release it currently carries — never a release to install; that
|
|
6
|
+
* is `--to`. Keeping them separate is what lets `agents update claude@2.0.65
|
|
7
|
+
* --to 2.0.71` read unambiguously.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* `<agent>[@<installed-version>][#<account>]`. The `#<account>` form is the
|
|
11
|
+
* same selector `agents run claude#work` takes: accounts run on the harness's
|
|
12
|
+
* one managed installation (PHNX-3940), so it names WHICH login the user means
|
|
13
|
+
* and resolves to that installation. Refusing it as "Unknown agent
|
|
14
|
+
* 'claude#work'" sent operators hunting for a per-account install that does
|
|
15
|
+
* not exist.
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseTarget(raw: string): {
|
|
18
|
+
agent: AgentId;
|
|
19
|
+
selector?: string;
|
|
20
|
+
account?: string;
|
|
21
|
+
};
|
|
3
22
|
/**
|
|
4
23
|
* One line naming the installations a bare `agents update <agent>` did NOT
|
|
5
24
|
* touch — isolated (`--isolated`) copies and legacy pre-v2 per-version homes —
|
package/dist/commands/update.js
CHANGED
|
@@ -3,23 +3,48 @@ import { AGENTS, formatAgentError, resolveAgentName } from '../lib/agents.js';
|
|
|
3
3
|
import { setHelpSections } from '../lib/help.js';
|
|
4
4
|
import { describeInstallation, listInstallations, planAutoUpdates, resolveInstallation, runAutoUpdatePass, selectUpdateStrategy, supportsPinnedUpdate, updateInstallation, } from '../lib/installations/index.js';
|
|
5
5
|
import { resolveManagedInstallation } from '../lib/installations/index.js';
|
|
6
|
+
import { findUnifiedAccount } from '../lib/account-registry.js';
|
|
7
|
+
import { readMeta } from '../lib/state.js';
|
|
6
8
|
/**
|
|
7
9
|
* Split `<agent>[@<selector>]`. The selector names an INSTALLATION — its frozen
|
|
8
10
|
* label, or the release it currently carries — never a release to install; that
|
|
9
11
|
* is `--to`. Keeping them separate is what lets `agents update claude@2.0.65
|
|
10
12
|
* --to 2.0.71` read unambiguously.
|
|
11
13
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* `<agent>[@<installed-version>][#<account>]`. The `#<account>` form is the
|
|
16
|
+
* same selector `agents run claude#work` takes: accounts run on the harness's
|
|
17
|
+
* one managed installation (PHNX-3940), so it names WHICH login the user means
|
|
18
|
+
* and resolves to that installation. Refusing it as "Unknown agent
|
|
19
|
+
* 'claude#work'" sent operators hunting for a per-account install that does
|
|
20
|
+
* not exist.
|
|
21
|
+
*/
|
|
22
|
+
export function parseTarget(raw) {
|
|
23
|
+
const hash = raw.indexOf('#');
|
|
24
|
+
const spec = hash === -1 ? raw : raw.slice(0, hash);
|
|
25
|
+
const account = hash === -1 ? undefined : raw.slice(hash + 1).trim();
|
|
26
|
+
if (hash !== -1 && !account) {
|
|
27
|
+
throw new Error(`Select an account after # in '${raw}', e.g. claude#work — or just <agent>.`);
|
|
28
|
+
}
|
|
29
|
+
if (account?.includes('@')) {
|
|
30
|
+
throw new Error(`Put the installation before the account: <agent>@<installed-version>#<account>, not '${raw}'.`);
|
|
31
|
+
}
|
|
32
|
+
const at = spec.indexOf('@');
|
|
33
|
+
const name = at === -1 ? spec : spec.slice(0, at);
|
|
34
|
+
const selector = at === -1 ? undefined : spec.slice(at + 1).trim();
|
|
16
35
|
if (at !== -1 && !selector) {
|
|
17
36
|
throw new Error(`Missing installation in '${raw}'. Use <agent>@<installed-version>, or just <agent>.`);
|
|
18
37
|
}
|
|
19
38
|
const agent = resolveAgentName(name);
|
|
20
39
|
if (!agent)
|
|
21
40
|
throw new Error(formatAgentError(name));
|
|
22
|
-
|
|
41
|
+
if (account) {
|
|
42
|
+
const known = findUnifiedAccount(account, readMeta(), undefined, agent);
|
|
43
|
+
if (!known) {
|
|
44
|
+
throw new Error(`Unknown ${AGENTS[agent].name} account '${account}'. See: agents accounts list ${agent}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { agent, selector, account };
|
|
23
48
|
}
|
|
24
49
|
/**
|
|
25
50
|
* One line naming the installations a bare `agents update <agent>` did NOT
|
|
@@ -219,7 +244,10 @@ export function registerUpdateCommand(program) {
|
|
|
219
244
|
if (!target) {
|
|
220
245
|
throw new Error('Which agent? Use: agents update <agent>[@<installed-version>], or agents update --auto.');
|
|
221
246
|
}
|
|
222
|
-
const { agent, selector } = parseTarget(target);
|
|
247
|
+
const { agent, selector, account } = parseTarget(target);
|
|
248
|
+
if (account && !options.json) {
|
|
249
|
+
console.log(chalk.gray(` account '${account}' runs on the managed ${AGENTS[agent].name} installation; updating that.`));
|
|
250
|
+
}
|
|
223
251
|
if (options.check) {
|
|
224
252
|
const plan = (await planAutoUpdates({ agents: [agent] })).filter((entry) => !selector || entry.installation.label === selector || entry.installation.releaseVersion === selector);
|
|
225
253
|
if (selector && plan.length === 0) {
|
package/dist/commands/view.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { AccountInfo } from '../lib/agents.js';
|
|
|
4
4
|
import type { AgentId } from '../lib/types.js';
|
|
5
5
|
import { type ConfiguredDeviceRole } from '../lib/device-config.js';
|
|
6
6
|
import { type NativeAccountCatalogRow } from '../lib/account-catalog.js';
|
|
7
|
-
import type { ResourceSection, ViewJsonAgent } from '../lib/view-types.js';
|
|
7
|
+
import type { ResourceSection, ViewJsonAgent, ViewJsonRunReady } from '../lib/view-types.js';
|
|
8
8
|
export type { ResourceItemJson, ResourceSection, SyncState, VersionResourcesJson, ViewJsonAgent, ViewJsonVersion } from '../lib/view-types.js';
|
|
9
9
|
import { type ProfileSummary } from '../lib/profiles.js';
|
|
10
10
|
import { type ByokUsageResult } from '../lib/byok-usage.js';
|
|
@@ -76,6 +76,17 @@ export declare function parseResourceSections(options: {
|
|
|
76
76
|
resources?: string | boolean;
|
|
77
77
|
detailed?: boolean;
|
|
78
78
|
} & ViewSectionFilter, jsonMode: boolean): Set<ResourceSection>;
|
|
79
|
+
/**
|
|
80
|
+
* The one run-readiness gate for one agent on THIS box (PHNX-4116). Runs the
|
|
81
|
+
* SAME enumeration the local router picks from — `collectRunCandidates` (native
|
|
82
|
+
* slots + version homes) through `readinessFromCandidate` — so the answer
|
|
83
|
+
* `agents view --json` publishes is exactly what a `run` here would find, and a
|
|
84
|
+
* remote `--device auto` dispatcher can read it instead of re-deriving freshness
|
|
85
|
+
* on its own box (which drifted: view.ts lists version homes, the router lists
|
|
86
|
+
* slots). Returns undefined when the agent has no candidates at all (nothing
|
|
87
|
+
* installed), so the field is simply absent rather than a misleading verdict.
|
|
88
|
+
*/
|
|
89
|
+
export declare function computeAgentRunReady(agentId: AgentId): Promise<ViewJsonRunReady | undefined>;
|
|
79
90
|
/**
|
|
80
91
|
* Collect structured info for one or more agents without rendering to the
|
|
81
92
|
* terminal. Used by `--json` output and any programmatic consumer (e.g. the
|