@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
|
@@ -13,6 +13,7 @@ import * as yaml from 'yaml';
|
|
|
13
13
|
import { isDaemonRunning, signalDaemonReload, startDaemon, stopDaemon, readDaemonLog, getDaemonStatus, getDaemonLogPath, } from '../lib/daemon/daemon.js';
|
|
14
14
|
import { assertSchedulerEnabled, assertDaemonEnabled, isDaemonEnabled } from '../lib/device-config.js';
|
|
15
15
|
import { parseAgentVersionSpec, isAgentHardDeprecated, hardDeprecationError, ROUTINE_AGENT_IDS } from '../lib/agents.js';
|
|
16
|
+
import { isCustomHarnessName } from '../lib/profiles.js';
|
|
16
17
|
import { RUN_STRATEGIES, normalizeRunStrategy } from '../lib/accounting/rotate.js';
|
|
17
18
|
import { formatRepoLink, REPO_DISPLAY_MAX } from '../lib/routines-format.js';
|
|
18
19
|
import { listJobs as listAllJobs, deleteJob, readJob, validateJob, writeJob, setJobEnabled, listRuns, routineStats, getLatestRun, getRunDir, getJobPath, isCanonicalRoutineSource, parseAtTime, hasCompletedOneShotRun, isOneShotLikeSchedule, isOneShotRoutine, jobRunsOnThisDevice, checkJobDeviceEligibility, normalizeTriggerEvent, parseHostStrategy, resolveHostStrategy, HOST_STRATEGIES, computeProjectGroupKind, projectGroupKey, projectGroupTitle, projectGroupOrder, normalizeProjects, buildRoutineListJson, fireConditionLabel, nextRunForDisplay, nextRunLabel, localLatestRun, listJobsForDisplay, } from '../lib/scheduling/routines.js';
|
|
@@ -24,7 +25,7 @@ import { fireWebhookJobs, matchJobsToWebhook } from '../lib/triggers/webhook.js'
|
|
|
24
25
|
import { getRoutinesDir } from '../lib/state.js';
|
|
25
26
|
import { IS_WINDOWS } from '../lib/platform/index.js';
|
|
26
27
|
import { safeJoin } from '../lib/paths.js';
|
|
27
|
-
import { executeJob, monitorRunningJobs } from '../lib/runner.js';
|
|
28
|
+
import { executeJob, monitorRunningJobs } from '../lib/daemon/runner.js';
|
|
28
29
|
import { JobScheduler } from '../lib/scheduler.js';
|
|
29
30
|
import { detectOverdueJobs } from '../lib/overdue.js';
|
|
30
31
|
import { runCatchup } from '../lib/catchup.js';
|
|
@@ -897,7 +898,7 @@ export function registerRoutinesCommands(program) {
|
|
|
897
898
|
.command('add [nameOrPath]')
|
|
898
899
|
.description('Create a new routine from a YAML file or inline flags. Starts the scheduler automatically if it is not already running.')
|
|
899
900
|
.option('-s, --schedule <cron>', 'Cron schedule in standard format (5 fields: minute hour day month weekday)')
|
|
900
|
-
.option('-a, --agent <agent[@version]>', `Which agent runs this routine: ${ROUTINE_AGENT_IDS.join(', ')}. An @version pins that exact installed version (same syntax as agents run), persisted as separate agent + version fields.`)
|
|
901
|
+
.option('-a, --agent <agent[@version]>', `Which agent runs this routine: ${ROUTINE_AGENT_IDS.join(', ')}, or a custom harness name (agents harness list). An @version pins that exact installed version (same syntax as agents run), persisted as separate agent + version fields; a custom harness pins its own host version.`)
|
|
901
902
|
.option('--strategy <strategy>', `Version/account selection strategy for this routine: ${RUN_STRATEGIES.join(' | ')}. Overrides run.<agent>.strategy from the firing device's config. Conflicts with an @version pin.`)
|
|
902
903
|
.option('--balanced', 'Shortcut for --strategy balanced.')
|
|
903
904
|
.option('--workflow <name>', 'Run an installed workflow (~/.agents/workflows/<name>) via `agents run`. Mutually exclusive with --agent.')
|
|
@@ -984,17 +985,26 @@ export function registerRoutinesCommands(program) {
|
|
|
984
985
|
// silently missed a hard-deprecated harness pinned with @version.
|
|
985
986
|
let parsedAgent;
|
|
986
987
|
if (options.agent) {
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
988
|
+
// A custom harness (agents harness list) is a valid routine agent:
|
|
989
|
+
// the runner delegates it to `agents run <name>`. It pins its own
|
|
990
|
+
// host version, so no @version suffix applies (a suffixed name falls
|
|
991
|
+
// through to the parse error below).
|
|
992
|
+
if (isCustomHarnessName(options.agent)) {
|
|
993
|
+
parsedAgent = { agent: options.agent };
|
|
991
994
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
995
|
+
else {
|
|
996
|
+
const parsed = parseAgentVersionSpec(options.agent);
|
|
997
|
+
if ('error' in parsed) {
|
|
998
|
+
console.error(chalk.red(parsed.error));
|
|
999
|
+
process.exit(1);
|
|
1000
|
+
}
|
|
1001
|
+
parsedAgent = parsed;
|
|
1002
|
+
// Hard-deprecated harnesses cannot be scheduled — refuse at create time
|
|
1003
|
+
// so no new recurring job silently fails against a retired backend.
|
|
1004
|
+
if (isAgentHardDeprecated(parsed.agent)) {
|
|
1005
|
+
console.error(chalk.red(hardDeprecationError(parsed.agent)));
|
|
1006
|
+
process.exit(1);
|
|
1007
|
+
}
|
|
998
1008
|
}
|
|
999
1009
|
}
|
|
1000
1010
|
// --strategy / --balanced: per-routine selection policy, same vocabulary
|
|
@@ -1377,22 +1387,30 @@ export function registerRoutinesCommands(program) {
|
|
|
1377
1387
|
if (options.projectAnchor !== undefined)
|
|
1378
1388
|
existing.project = options.projectAnchor;
|
|
1379
1389
|
if (options.agent !== undefined) {
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1390
|
+
if (isCustomHarnessName(options.agent)) {
|
|
1391
|
+
// Custom harness: delegated to `agents run <name>`; the profile
|
|
1392
|
+
// pins its own host version, so any prior pin is cleared.
|
|
1393
|
+
existing.agent = options.agent;
|
|
1394
|
+
delete existing.version;
|
|
1384
1395
|
}
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1396
|
+
else {
|
|
1397
|
+
const parsed = parseAgentVersionSpec(options.agent);
|
|
1398
|
+
if ('error' in parsed) {
|
|
1399
|
+
console.error(chalk.red(parsed.error));
|
|
1400
|
+
process.exit(1);
|
|
1401
|
+
}
|
|
1402
|
+
if (isAgentHardDeprecated(parsed.agent)) {
|
|
1403
|
+
console.error(chalk.red(hardDeprecationError(parsed.agent)));
|
|
1404
|
+
process.exit(1);
|
|
1405
|
+
}
|
|
1406
|
+
existing.agent = parsed.agent;
|
|
1407
|
+
// An @version pin replaces any previous pin; a bare agent clears it so
|
|
1408
|
+
// the routine returns to strategy/balanced selection.
|
|
1409
|
+
if (parsed.version)
|
|
1410
|
+
existing.version = parsed.version;
|
|
1411
|
+
else
|
|
1412
|
+
delete existing.version;
|
|
1388
1413
|
}
|
|
1389
|
-
existing.agent = parsed.agent;
|
|
1390
|
-
// An @version pin replaces any previous pin; a bare agent clears it so
|
|
1391
|
-
// the routine returns to strategy/balanced selection.
|
|
1392
|
-
if (parsed.version)
|
|
1393
|
-
existing.version = parsed.version;
|
|
1394
|
-
else
|
|
1395
|
-
delete existing.version;
|
|
1396
1414
|
}
|
|
1397
1415
|
if (options.strategy !== undefined) {
|
|
1398
1416
|
const normalized = normalizeRunStrategy(options.strategy);
|
|
@@ -12,10 +12,29 @@ export interface RunAccountChoice {
|
|
|
12
12
|
*/
|
|
13
13
|
signInRequired: boolean;
|
|
14
14
|
}
|
|
15
|
+
/** One named account row for `agents accounts switch` (reuses this picker's layout). */
|
|
16
|
+
export interface SwitchAccountRow {
|
|
17
|
+
accountName: string;
|
|
18
|
+
kind: 'provider' | 'native';
|
|
19
|
+
detail: string;
|
|
20
|
+
current: boolean;
|
|
21
|
+
candidate: RotateCandidate | null;
|
|
22
|
+
}
|
|
15
23
|
/** Human-readable remaining capacity for every window the provider exposes. */
|
|
16
24
|
export declare function formatAccountLimits(candidate: RotateCandidate): string;
|
|
17
25
|
/** Build aligned picker rows with usable accounts first and unsafe rows disabled. */
|
|
18
26
|
export declare function buildRunAccountChoices(candidates: RotateCandidate[], globalDefault: string | null): RunAccountChoice[];
|
|
27
|
+
/**
|
|
28
|
+
* Aligned picker rows for `accounts switch`. Same columns as the run picker
|
|
29
|
+
* (identity, status, limits) but the value is the named account to set-default.
|
|
30
|
+
* Rows stay selectable: setting a default is not a launch.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildSwitchAccountChoices(rows: SwitchAccountRow[]): RunAccountChoice[];
|
|
33
|
+
/**
|
|
34
|
+
* Prompt for the named account that becomes this harness's default.
|
|
35
|
+
* A cancelled picker writes nothing.
|
|
36
|
+
*/
|
|
37
|
+
export declare function pickSwitchAccount(agent: AgentId, rows: SwitchAccountRow[]): Promise<string | null>;
|
|
19
38
|
/**
|
|
20
39
|
* Whether a zero-healthy run may recover by launching for a login, or must keep
|
|
21
40
|
* failing loud. Three inputs, all of which have to hold:
|
|
@@ -124,6 +124,87 @@ export function buildRunAccountChoices(candidates, globalDefault) {
|
|
|
124
124
|
signInRequired: row.signInRequired,
|
|
125
125
|
}));
|
|
126
126
|
}
|
|
127
|
+
function switchRowStatus(row) {
|
|
128
|
+
if (!row.candidate) {
|
|
129
|
+
return {
|
|
130
|
+
status: row.kind === 'provider' ? 'credential' : 'named',
|
|
131
|
+
limits: 'limits unavailable',
|
|
132
|
+
ready: true,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const readiness = readinessFromCandidate(row.candidate);
|
|
136
|
+
const authReason = readiness.ready ? null : readiness.reason;
|
|
137
|
+
const status = authReason === 'revoked'
|
|
138
|
+
? 'needs re-login'
|
|
139
|
+
: authReason === 'signed_out'
|
|
140
|
+
? 'logged out'
|
|
141
|
+
: authReason === 'rate_limited'
|
|
142
|
+
? 'rate limited'
|
|
143
|
+
: authReason === 'out_of_credits'
|
|
144
|
+
? 'out of credits'
|
|
145
|
+
: 'logged in';
|
|
146
|
+
const limits = authReason === 'revoked'
|
|
147
|
+
? 'needs re-authentication'
|
|
148
|
+
: authReason === 'signed_out'
|
|
149
|
+
? 'signed out'
|
|
150
|
+
: formatAccountLimits(row.candidate);
|
|
151
|
+
return { status, limits, ready: readiness.ready };
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Aligned picker rows for `accounts switch`. Same columns as the run picker
|
|
155
|
+
* (identity, status, limits) but the value is the named account to set-default.
|
|
156
|
+
* Rows stay selectable: setting a default is not a launch.
|
|
157
|
+
*/
|
|
158
|
+
export function buildSwitchAccountChoices(rows) {
|
|
159
|
+
const rendered = rows.map((row) => {
|
|
160
|
+
const { status, limits, ready } = switchRowStatus(row);
|
|
161
|
+
const account = row.current ? `${row.accountName} (default)` : row.accountName;
|
|
162
|
+
const kind = row.kind === 'provider' ? `provider · ${row.detail}` : `native · ${row.detail}`;
|
|
163
|
+
return { account, kind, status, limits, ready, value: row.accountName };
|
|
164
|
+
});
|
|
165
|
+
const accountWidth = Math.max(0, ...rendered.map((row) => row.account.length));
|
|
166
|
+
const kindWidth = Math.max(0, ...rendered.map((row) => row.kind.length));
|
|
167
|
+
const statusWidth = Math.max(0, ...rendered.map((row) => row.status.length));
|
|
168
|
+
return rendered.map((row) => ({
|
|
169
|
+
name: [
|
|
170
|
+
row.account.padEnd(accountWidth),
|
|
171
|
+
row.kind.padEnd(kindWidth),
|
|
172
|
+
row.status.padEnd(statusWidth),
|
|
173
|
+
row.limits,
|
|
174
|
+
].join(' '),
|
|
175
|
+
value: row.value,
|
|
176
|
+
ready: row.ready,
|
|
177
|
+
signInRequired: false,
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Prompt for the named account that becomes this harness's default.
|
|
182
|
+
* A cancelled picker writes nothing.
|
|
183
|
+
*/
|
|
184
|
+
export async function pickSwitchAccount(agent, rows) {
|
|
185
|
+
if (!isInteractiveTerminal()) {
|
|
186
|
+
requireInteractiveSelection(`Selecting a ${agentLabel(agent)} account`, [
|
|
187
|
+
`agents accounts switch ${agent} <account>`,
|
|
188
|
+
`agents accounts set-default ${agent} <account>`,
|
|
189
|
+
]);
|
|
190
|
+
}
|
|
191
|
+
if (rows.length === 0) {
|
|
192
|
+
throw new Error(`No named accounts for ${agent}. Add one with 'agents accounts add <name> --provider <p>' or 'agents accounts name ${agent}@<version> <name>'.`);
|
|
193
|
+
}
|
|
194
|
+
const choices = buildSwitchAccountChoices(rows).map(({ ready: _ready, signInRequired: _signInRequired, ...choice }) => choice);
|
|
195
|
+
try {
|
|
196
|
+
return await select({
|
|
197
|
+
message: `Select the default ${agentLabel(agent)} account:`,
|
|
198
|
+
choices,
|
|
199
|
+
loop: false,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
if (isPromptCancelled(err))
|
|
204
|
+
return null;
|
|
205
|
+
throw err;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
127
208
|
/**
|
|
128
209
|
* Whether a zero-healthy run may recover by launching for a login, or must keep
|
|
129
210
|
* failing loud. Three inputs, all of which have to hold:
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** Flag subset both twins share for the interactive-routing gate. */
|
|
2
|
+
export interface SessionsPickerGateOpts {
|
|
3
|
+
interactive?: boolean;
|
|
4
|
+
json?: boolean;
|
|
5
|
+
/** Present only on the browser twin; computer never sets it. */
|
|
6
|
+
open?: string | boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface SessionsPickerCommandSpec<TRow, TOpts extends SessionsPickerGateOpts> {
|
|
9
|
+
/**
|
|
10
|
+
* Browser requires `opts.open === undefined` so `--open` (bare or with a
|
|
11
|
+
* selector) falls through to the flat printer. Computer has no `--open`.
|
|
12
|
+
*/
|
|
13
|
+
requireOpenUndefined?: boolean;
|
|
14
|
+
runFlat: (opts: TOpts) => void;
|
|
15
|
+
buildRows: (opts: TOpts) => TRow[];
|
|
16
|
+
emptyMessage: (opts: TOpts) => string;
|
|
17
|
+
message: string;
|
|
18
|
+
matches: (row: TRow, query: string) => boolean;
|
|
19
|
+
labelFor: (row: TRow) => string;
|
|
20
|
+
buildPreview: (row: TRow) => string;
|
|
21
|
+
emptyFilterMessage: string;
|
|
22
|
+
enterHint: string;
|
|
23
|
+
onOpen: (row: TRow) => void | Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export interface SessionsPickerCommand<TOpts extends SessionsPickerGateOpts> {
|
|
26
|
+
shouldOpen: (opts: TOpts, isTTY: boolean) => boolean;
|
|
27
|
+
run: (opts: TOpts) => Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export declare function shouldOpenInteractiveSessions(opts: SessionsPickerGateOpts, isTTY: boolean, requireOpenUndefined?: boolean): boolean;
|
|
30
|
+
export declare function browseSessionsUntilQuit<TRow>(spec: {
|
|
31
|
+
message: string;
|
|
32
|
+
rows: TRow[];
|
|
33
|
+
matches: (row: TRow, query: string) => boolean;
|
|
34
|
+
labelFor: (row: TRow) => string;
|
|
35
|
+
buildPreview: (row: TRow) => string;
|
|
36
|
+
emptyFilterMessage: string;
|
|
37
|
+
enterHint: string;
|
|
38
|
+
onOpen: (row: TRow) => void | Promise<void>;
|
|
39
|
+
}): Promise<void>;
|
|
40
|
+
export declare function createSessionsPickerCommand<TRow, TOpts extends SessionsPickerGateOpts>(spec: SessionsPickerCommandSpec<TRow, TOpts>): SessionsPickerCommand<TOpts>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared interactive-routing + browse loop for the task-first session
|
|
3
|
+
* pickers (`browser-sessions-picker.ts`, `computer-sessions-picker.ts`).
|
|
4
|
+
*
|
|
5
|
+
* Each twin keeps its own row formatter, matcher, and enter-handler; this
|
|
6
|
+
* factory owns the TTY/`--json`/`--no-interactive` (and optional `--open`)
|
|
7
|
+
* gate, the empty-list message, and the cancel-aware `itemPicker` loop.
|
|
8
|
+
*/
|
|
9
|
+
import { itemPicker } from '../lib/picker.js';
|
|
10
|
+
import { isInteractiveTerminal, isPromptCancelled } from './utils.js';
|
|
11
|
+
export function shouldOpenInteractiveSessions(opts, isTTY, requireOpenUndefined = false) {
|
|
12
|
+
return (opts.interactive !== false &&
|
|
13
|
+
!opts.json &&
|
|
14
|
+
(!requireOpenUndefined || opts.open === undefined) &&
|
|
15
|
+
isTTY);
|
|
16
|
+
}
|
|
17
|
+
export async function browseSessionsUntilQuit(spec) {
|
|
18
|
+
for (;;) {
|
|
19
|
+
let picked;
|
|
20
|
+
try {
|
|
21
|
+
picked = await itemPicker({
|
|
22
|
+
message: spec.message,
|
|
23
|
+
items: spec.rows,
|
|
24
|
+
filter: (query) => (query.trim() ? spec.rows.filter((r) => spec.matches(r, query)) : spec.rows),
|
|
25
|
+
labelFor: spec.labelFor,
|
|
26
|
+
buildPreview: spec.buildPreview,
|
|
27
|
+
emptyMessage: spec.emptyFilterMessage,
|
|
28
|
+
enterHint: spec.enterHint,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
if (isPromptCancelled(err))
|
|
33
|
+
return;
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
if (!picked)
|
|
37
|
+
return;
|
|
38
|
+
await spec.onOpen(picked.item);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function createSessionsPickerCommand(spec) {
|
|
42
|
+
const shouldOpen = (opts, isTTY) => shouldOpenInteractiveSessions(opts, isTTY, spec.requireOpenUndefined === true);
|
|
43
|
+
return {
|
|
44
|
+
shouldOpen,
|
|
45
|
+
run: async (opts) => {
|
|
46
|
+
if (!shouldOpen(opts, isInteractiveTerminal())) {
|
|
47
|
+
spec.runFlat(opts);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const rows = spec.buildRows(opts);
|
|
51
|
+
if (rows.length === 0) {
|
|
52
|
+
console.log(spec.emptyMessage(opts));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
await browseSessionsUntilQuit({
|
|
56
|
+
message: spec.message,
|
|
57
|
+
rows,
|
|
58
|
+
matches: spec.matches,
|
|
59
|
+
labelFor: spec.labelFor,
|
|
60
|
+
buildPreview: spec.buildPreview,
|
|
61
|
+
emptyFilterMessage: spec.emptyFilterMessage,
|
|
62
|
+
enterHint: spec.enterHint,
|
|
63
|
+
onOpen: spec.onOpen,
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|