@phnx-labs/agents-cli 1.22.42 → 1.22.44
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 +149 -0
- package/README.md +15 -13
- package/dist/bootstrap.js +33 -13
- package/dist/cli/command-registry.d.ts +0 -8
- package/dist/cli/command-registry.js +1 -25
- package/dist/commands/alias.d.ts +7 -4
- package/dist/commands/alias.js +33 -8
- package/dist/commands/apply.d.ts +7 -10
- package/dist/commands/apply.js +15 -35
- package/dist/commands/artifacts.js +4 -5
- package/dist/commands/audit.d.ts +6 -6
- package/dist/commands/audit.js +12 -12
- package/dist/commands/auth.js +14 -6
- package/dist/commands/beta.d.ts +7 -1
- package/dist/commands/beta.js +16 -9
- package/dist/commands/commands.js +1 -1
- package/dist/commands/computer.js +20 -6
- package/dist/commands/daemon.js +1 -1
- package/dist/commands/doctor.d.ts +4 -2
- package/dist/commands/doctor.js +21 -9
- package/dist/commands/events.d.ts +2 -2
- package/dist/commands/events.js +6 -5
- package/dist/commands/exec.d.ts +1 -1
- package/dist/commands/exec.js +11 -6
- package/dist/commands/factory.d.ts +1 -1
- package/dist/commands/feed.js +1 -30
- package/dist/commands/fleet-capture.d.ts +1 -1
- package/dist/commands/fleet-capture.js +4 -5
- package/dist/commands/harness.js +4 -52
- package/dist/commands/hooks.js +1 -1
- package/dist/commands/insights.d.ts +1 -1
- package/dist/commands/insights.js +3 -2
- package/dist/commands/menubar.js +58 -1
- package/dist/commands/monitors.js +1 -1
- package/dist/commands/org.d.ts +5 -0
- package/dist/commands/org.js +83 -29
- package/dist/commands/output.js +2 -2
- package/dist/commands/profiles.js +2 -2
- package/dist/commands/prune.js +5 -4
- package/dist/commands/routines.js +43 -25
- package/dist/commands/routines.test-fixture.d.ts +86 -0
- package/dist/commands/routines.test-fixture.js +345 -0
- package/dist/commands/sessions-picker.js +124 -122
- package/dist/commands/sessions.test-fixture.d.ts +24 -0
- package/dist/commands/sessions.test-fixture.js +224 -0
- package/dist/commands/setup.js +9 -1
- package/dist/commands/share.d.ts +9 -10
- package/dist/commands/share.js +68 -50
- package/dist/commands/skills.js +1 -1
- package/dist/commands/snapshot.d.ts +1 -1
- package/dist/commands/snapshot.js +4 -4
- package/dist/commands/ssh.js +15 -62
- package/dist/commands/status.d.ts +4 -2
- package/dist/commands/status.js +10 -7
- package/dist/commands/subagents.js +1 -1
- package/dist/commands/sync.d.ts +1 -0
- package/dist/commands/sync.js +29 -2
- package/dist/commands/view.js +11 -2
- package/dist/commands/webhook.js +1 -1
- 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 +7 -7
- package/dist/lib/agent-spec/agents.js +15 -15
- package/dist/lib/analytics/mix-commands.d.ts +6 -28
- package/dist/lib/analytics/mix-commands.js +14 -40
- package/dist/lib/audit/log.d.ts +2 -2
- package/dist/lib/audit/log.js +2 -2
- package/dist/lib/beta.js +1 -1
- package/dist/lib/browser/domain-skills.d.ts +26 -6
- package/dist/lib/browser/domain-skills.js +81 -43
- package/dist/lib/cloud/rush.d.ts +0 -15
- package/dist/lib/cloud/rush.js +0 -35
- package/dist/lib/crabbox/runtimes.d.ts +6 -2
- package/dist/lib/crabbox/runtimes.js +21 -5
- package/dist/lib/daemon/daemon.js +97 -58
- package/dist/lib/daemon/daemon.test-fixture.d.ts +24 -0
- package/dist/lib/daemon/daemon.test-fixture.js +71 -0
- package/dist/lib/daemon/runner.d.ts +18 -1
- package/dist/lib/daemon/runner.js +105 -11
- package/dist/lib/daemon-ticks.d.ts +38 -1
- package/dist/lib/daemon-ticks.js +52 -5
- package/dist/lib/device-config.js +1 -2
- package/dist/lib/devices/discovery-policy.d.ts +3 -3
- package/dist/lib/devices/discovery-policy.js +3 -3
- package/dist/lib/devices/doctor-findings.js +1 -1
- package/dist/lib/devices/fleet.d.ts +4 -8
- package/dist/lib/devices/fleet.js +3 -15
- package/dist/lib/devices/health-report.js +4 -4
- package/dist/lib/devices/pool.d.ts +0 -6
- package/dist/lib/devices/pool.js +0 -6
- package/dist/lib/devices/registry.d.ts +0 -15
- package/dist/lib/devices/registry.js +0 -9
- package/dist/lib/devices/stats-cache.d.ts +12 -0
- package/dist/lib/devices/stats-cache.js +24 -5
- 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/exec.js +13 -3
- package/dist/lib/fleet/capture.d.ts +1 -1
- package/dist/lib/fleet/manifest.js +1 -1
- package/dist/lib/fleet/remote-login.d.ts +2 -2
- package/dist/lib/fleet/remote-login.js +3 -4
- package/dist/lib/format.d.ts +9 -0
- package/dist/lib/format.js +16 -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 +6 -5
- package/dist/lib/hosts/dispatch.d.ts +2 -0
- package/dist/lib/hosts/dispatch.js +8 -1
- package/dist/lib/hosts/passthrough.d.ts +10 -0
- package/dist/lib/hosts/passthrough.js +28 -7
- package/dist/lib/hosts/providers/devices.js +1 -13
- package/dist/lib/hosts/ready.d.ts +12 -3
- package/dist/lib/hosts/ready.js +27 -12
- package/dist/lib/hosts/registry.d.ts +4 -5
- package/dist/lib/hosts/registry.js +3 -7
- package/dist/lib/hosts/session-index.js +1 -1
- package/dist/lib/installations/shims.js +1 -1
- package/dist/lib/installations/versions.d.ts +40 -0
- package/dist/lib/installations/versions.js +78 -4
- package/dist/lib/menubar/MenubarHelper.app/Contents/Info.plist +1 -5
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/_CodeSignature/CodeResources +2 -15
- package/dist/lib/menubar/install-menubar.d.ts +109 -0
- package/dist/lib/menubar/install-menubar.js +218 -12
- package/dist/lib/monitors/config.d.ts +2 -2
- package/dist/lib/monitors/config.js +3 -2
- 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/prix-account.d.ts +2 -1
- package/dist/lib/prix-account.js +2 -1
- package/dist/lib/profiles.d.ts +7 -0
- package/dist/lib/profiles.js +26 -1
- package/dist/lib/remote-agents-json.js +1 -7
- package/dist/lib/routines-placement.d.ts +1 -1
- package/dist/lib/routines-placement.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 +16 -8
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/Info.plist +0 -2
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +1 -13
- 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/service-manifest.d.ts +20 -0
- package/dist/lib/service-manifest.js +34 -0
- package/dist/lib/session/active.d.ts +4 -16
- package/dist/lib/session/active.js +2 -6
- package/dist/lib/session/cloud.js +1 -1
- package/dist/lib/session/db.d.ts +13 -98
- package/dist/lib/session/db.js +5 -12
- package/dist/lib/session/discover.d.ts +5 -81
- package/dist/lib/session/discover.js +5 -5
- 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/relative-time.d.ts +1 -44
- package/dist/lib/session/relative-time.js +4 -120
- package/dist/lib/session/remote/remote-bundle.d.ts +12 -0
- package/dist/lib/session/remote/remote-bundle.js +61 -0
- package/dist/lib/session/remote/remote-list.d.ts +148 -0
- package/dist/lib/session/remote/remote-list.js +607 -0
- package/dist/lib/session/remote/remote.d.ts +132 -0
- package/dist/lib/session/remote/remote.js +314 -0
- package/dist/lib/session/remote/watch.d.ts +101 -0
- package/dist/lib/session/remote/watch.js +241 -0
- package/dist/lib/session/remote-bundle.d.ts +1 -12
- package/dist/lib/session/remote-bundle.js +3 -61
- package/dist/lib/session/remote-list.d.ts +1 -148
- package/dist/lib/session/remote-list.js +3 -607
- package/dist/lib/session/remote.d.ts +1 -132
- package/dist/lib/session/remote.js +3 -314
- package/dist/lib/session/short-id.d.ts +1 -17
- package/dist/lib/session/short-id.js +4 -20
- package/dist/lib/session/watch.d.ts +1 -101
- package/dist/lib/session/watch.js +3 -242
- package/dist/lib/session/width.d.ts +1 -29
- package/dist/lib/session/width.js +4 -101
- package/dist/lib/share/config.d.ts +12 -2
- package/dist/lib/share/config.js +47 -11
- package/dist/lib/share/delete.js +1 -1
- package/dist/lib/share/publish.js +1 -1
- package/dist/lib/share/worker-template.js +2 -2
- package/dist/lib/smart-launch.d.ts +4 -4
- package/dist/lib/smart-launch.js +8 -18
- package/dist/lib/snapshot.d.ts +2 -2
- package/dist/lib/snapshot.js +1 -1
- package/dist/lib/staleness/index.d.ts +3 -1
- package/dist/lib/staleness/index.js +21 -1
- package/dist/lib/staleness/types.d.ts +11 -0
- package/dist/lib/staleness/writers/commands.js +13 -4
- package/dist/lib/staleness/writers/hooks.js +3 -1
- package/dist/lib/staleness/writers/mcp.d.ts +0 -7
- package/dist/lib/staleness/writers/mcp.js +16 -1
- package/dist/lib/staleness/writers/rules.js +1 -1
- package/dist/lib/staleness/writers/skills.js +3 -1
- package/dist/lib/staleness/writers/subagents.d.ts +0 -9
- package/dist/lib/staleness/writers/subagents.js +18 -1
- package/dist/lib/staleness/writers/types.d.ts +10 -0
- package/dist/lib/startup/command-registry.d.ts +10 -1
- package/dist/lib/startup/command-registry.js +26 -7
- package/dist/lib/startup/root-command.d.ts +18 -1
- package/dist/lib/startup/root-command.js +18 -1
- package/dist/lib/state.js +7 -0
- package/dist/lib/teams/placement-probe.js +28 -13
- package/dist/lib/teams/scheduler.d.ts +3 -1
- 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 +8 -0
- package/dist/lib/triggers/webhook.d.ts +1 -0
- package/dist/lib/triggers/webhook.js +2 -1
- package/dist/lib/types.d.ts +1 -1
- package/dist/lib/view-types.d.ts +7 -0
- package/package.json +2 -3
- package/dist/bin/agents +0 -0
- package/dist/commands/serve.d.ts +0 -10
- package/dist/commands/serve.js +0 -68
- package/dist/commands/tickets.d.ts +0 -2
- package/dist/commands/tickets.js +0 -43
- package/dist/commands/trends.d.ts +0 -10
- package/dist/commands/trends.js +0 -12
- package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/Resources/AppIcon.icns +0 -0
- package/dist/lib/observe-aliases.d.ts +0 -30
- package/dist/lib/observe-aliases.js +0 -38
- package/dist/lib/secrets/Agents CLI.app/Contents/Resources/AppIcon.icns +0 -0
- package/dist/lib/serve/control.d.ts +0 -95
- package/dist/lib/serve/control.js +0 -260
- package/dist/lib/serve/data.d.ts +0 -81
- package/dist/lib/serve/data.js +0 -91
- package/dist/lib/serve/page.d.ts +0 -7
- package/dist/lib/serve/page.js +0 -140
- package/dist/lib/serve/server.d.ts +0 -80
- package/dist/lib/serve/server.js +0 -145
- package/dist/lib/serve/stream.d.ts +0 -43
- package/dist/lib/serve/stream.js +0 -116
- package/dist/lib/serve/token.d.ts +0 -35
- package/dist/lib/serve/token.js +0 -85
- package/dist/lib/tickets/list.d.ts +0 -53
- package/dist/lib/tickets/list.js +0 -153
package/dist/commands/feed.js
CHANGED
|
@@ -312,7 +312,7 @@ export async function loadSessionMetasForFeedEnrichment(load) {
|
|
|
312
312
|
export function registerFeedCommand(program) {
|
|
313
313
|
const feed = program
|
|
314
314
|
.command('feed')
|
|
315
|
-
.description('Operator inbox + agent status posts
|
|
315
|
+
.description('Operator inbox + agent status posts. Default is needs-you; agent progress = --filter updates')
|
|
316
316
|
.option('--json', 'Output as JSON (each block stamped with its outcome + ask class)')
|
|
317
317
|
.option('--filter <view>', 'What to show: needs (default) · updates · all', 'needs')
|
|
318
318
|
.option('--flat', 'List one block per agent instead of grouping by outcome')
|
|
@@ -642,35 +642,6 @@ export function registerFeedCommand(program) {
|
|
|
642
642
|
renderOutcomeGroup(g, self);
|
|
643
643
|
await renderTrailingActivity();
|
|
644
644
|
});
|
|
645
|
-
// Observe-umbrella aliases (Phase 3): intentional second names, not deprecations.
|
|
646
|
-
// Re-parse into `feed` so flags/help stay single-sourced. See lib/observe-aliases.ts.
|
|
647
|
-
registerFeedObserveAliases(program);
|
|
648
|
-
}
|
|
649
|
-
/**
|
|
650
|
-
* `inbox` → feed. Loaded with the feed module so the lazy COMMAND_LOADERS entry
|
|
651
|
-
* for `inbox` also gets the real `feed` command registered for re-parse.
|
|
652
|
-
*/
|
|
653
|
-
function registerFeedObserveAliases(program) {
|
|
654
|
-
const reparse = async (alias) => {
|
|
655
|
-
const { expandObserveAlias } = await import('../lib/observe-aliases.js');
|
|
656
|
-
const rest = process.argv.slice(3);
|
|
657
|
-
const expanded = expandObserveAlias(alias, rest);
|
|
658
|
-
if (!expanded) {
|
|
659
|
-
console.error(chalk.red(`Unknown observe alias: ${alias}`));
|
|
660
|
-
process.exit(1);
|
|
661
|
-
}
|
|
662
|
-
if (process.stderr.isTTY)
|
|
663
|
-
process.stderr.write(chalk.gray(`${expanded.note}\n`));
|
|
664
|
-
await program.parseAsync(['node', 'agents', ...expanded.argv]);
|
|
665
|
-
};
|
|
666
|
-
program
|
|
667
|
-
.command('inbox')
|
|
668
|
-
.description('Needs-you inbox (alias of `agents feed`). Open blocks waiting on you.')
|
|
669
|
-
.allowUnknownOption()
|
|
670
|
-
.allowExcessArguments()
|
|
671
|
-
.action(async () => {
|
|
672
|
-
await reparse('inbox');
|
|
673
|
-
});
|
|
674
645
|
}
|
|
675
646
|
/**
|
|
676
647
|
* Mirror a written post to the configured sinks (`feed.broadcast` in
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `agents fleet capture` (alias surface of `agents devices capture`) — snapshot
|
|
3
3
|
* the live environment into the `fleet:` block of `agents.yaml` so a fresh
|
|
4
|
-
* machine can reconstruct it with `agents apply`.
|
|
4
|
+
* machine can reconstruct it with `agents fleet apply`.
|
|
5
5
|
*
|
|
6
6
|
* Local-read + local-write, zero SSH. Records device NAMES only (never IPs or
|
|
7
7
|
* usernames — those are re-resolved live from Tailscale at apply-time), plus the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `agents fleet capture` (alias surface of `agents devices capture`) — snapshot
|
|
3
3
|
* the live environment into the `fleet:` block of `agents.yaml` so a fresh
|
|
4
|
-
* machine can reconstruct it with `agents apply`.
|
|
4
|
+
* machine can reconstruct it with `agents fleet apply`.
|
|
5
5
|
*
|
|
6
6
|
* Local-read + local-write, zero SSH. Records device NAMES only (never IPs or
|
|
7
7
|
* usernames — those are re-resolved live from Tailscale at apply-time), plus the
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import * as fs from 'fs';
|
|
13
13
|
import chalk from 'chalk';
|
|
14
14
|
import * as yaml from 'yaml';
|
|
15
|
-
import { loadDevices
|
|
15
|
+
import { loadDevices } from '../lib/devices/registry.js';
|
|
16
16
|
import { readMeta, updateMeta, getDevicePinsPath } from '../lib/state.js';
|
|
17
17
|
import { machineId } from '../lib/machine-id.js';
|
|
18
18
|
import { listBundles } from '../lib/secrets/bundles.js';
|
|
@@ -39,10 +39,9 @@ function agentsFromPins(names) {
|
|
|
39
39
|
}
|
|
40
40
|
async function runCapture(opts) {
|
|
41
41
|
const meta = readMeta();
|
|
42
|
-
// Roster: registered
|
|
42
|
+
// Roster: every registered device name.
|
|
43
43
|
const registry = await loadDevices();
|
|
44
44
|
let names = Object.values(registry)
|
|
45
|
-
.filter((d) => !isControlDevice(d))
|
|
46
45
|
.map((d) => d.name)
|
|
47
46
|
.sort();
|
|
48
47
|
if (opts.device) {
|
|
@@ -83,7 +82,7 @@ async function runCapture(opts) {
|
|
|
83
82
|
console.log(chalk.green('Captured fleet profile') +
|
|
84
83
|
chalk.gray(` — ${deviceCount} device(s), ${defaults.agents?.length ?? 0} agent(s), ` +
|
|
85
84
|
`${inputs.secretsBundles?.length ?? 0} secret bundle(s), ${inputs.routines?.length ?? 0} routine(s).`));
|
|
86
|
-
console.log(chalk.gray(' Wrote agents.yaml → fleet:. Push it (`agents repo push`) and run `agents apply` on any machine.'));
|
|
85
|
+
console.log(chalk.gray(' Wrote agents.yaml → fleet:. Push it (`agents repo push`) and run `agents fleet apply` on any machine.'));
|
|
87
86
|
}
|
|
88
87
|
/** Attach `capture` to the `devices`/`fleet` command tree. */
|
|
89
88
|
export function registerFleetCaptureCommand(devicesCmd) {
|
package/dist/commands/harness.js
CHANGED
|
@@ -17,8 +17,6 @@ import { listProfiles, readProfile, writeProfile, deleteProfile, profileExists,
|
|
|
17
17
|
import { listPresets, getPreset } from '../lib/profiles-presets.js';
|
|
18
18
|
import { AGENTS, ALL_AGENT_IDS, resolveAgentName } from '../lib/agents.js';
|
|
19
19
|
import { findAccount } from '../lib/account-registry.js';
|
|
20
|
-
import { keychainItemName, setKeychainToken, deleteKeychainToken } from '../lib/secrets/profiles.js';
|
|
21
|
-
import { readStdinSync } from '../lib/format.js';
|
|
22
20
|
import { runWizardSteps, createSteps, editSteps, defaultWizardIO, } from './harness-wizard.js';
|
|
23
21
|
/** Short capability summary for a native harness — its supported run modes. */
|
|
24
22
|
function nativeModes(id) {
|
|
@@ -73,7 +71,7 @@ export function buildFork(source, name, opts) {
|
|
|
73
71
|
const account = findAccount(opts.account);
|
|
74
72
|
if (!account)
|
|
75
73
|
throw new Error(`Unknown account '${opts.account}'.`);
|
|
76
|
-
profile.account = account.
|
|
74
|
+
profile.account = account.name;
|
|
77
75
|
profile.provider = account.provider;
|
|
78
76
|
}
|
|
79
77
|
return profile;
|
|
@@ -97,7 +95,7 @@ export function buildFork(source, name, opts) {
|
|
|
97
95
|
const account = findAccount(opts.account);
|
|
98
96
|
if (!account)
|
|
99
97
|
throw new Error(`Unknown account '${opts.account}'.`);
|
|
100
|
-
profile.account = account.
|
|
98
|
+
profile.account = account.name;
|
|
101
99
|
profile.provider = account.provider;
|
|
102
100
|
}
|
|
103
101
|
return profile;
|
|
@@ -162,7 +160,7 @@ export function buildEdit(name, opts) {
|
|
|
162
160
|
const account = findAccount(opts.account);
|
|
163
161
|
if (!account)
|
|
164
162
|
throw new Error(`Unknown account '${opts.account}'.`);
|
|
165
|
-
edited.account = account.
|
|
163
|
+
edited.account = account.name;
|
|
166
164
|
edited.provider = account.provider;
|
|
167
165
|
}
|
|
168
166
|
if (opts.version === '')
|
|
@@ -567,7 +565,7 @@ Examples:
|
|
|
567
565
|
cmd
|
|
568
566
|
.command('remove <name>')
|
|
569
567
|
.alias('rm')
|
|
570
|
-
.description('Delete a custom harness (
|
|
568
|
+
.description('Delete a custom harness (credentials stay on `agents accounts`; this only drops the named pin).')
|
|
571
569
|
.action((name) => {
|
|
572
570
|
const existed = deleteProfile(name);
|
|
573
571
|
if (!existed) {
|
|
@@ -576,50 +574,4 @@ Examples:
|
|
|
576
574
|
}
|
|
577
575
|
console.log(chalk.green(`Harness '${name}' removed.`));
|
|
578
576
|
});
|
|
579
|
-
cmd
|
|
580
|
-
.command('login <provider>')
|
|
581
|
-
.description('Store or rotate the API key for a provider (e.g., openrouter). Shared across harnesses using that provider.')
|
|
582
|
-
.option('--key-stdin', 'Read API key from stdin')
|
|
583
|
-
.action(async (provider, opts) => {
|
|
584
|
-
try {
|
|
585
|
-
const item = keychainItemName(provider);
|
|
586
|
-
let token;
|
|
587
|
-
if (opts.keyStdin) {
|
|
588
|
-
token = readStdinSync();
|
|
589
|
-
if (!token)
|
|
590
|
-
throw new Error('No key received on stdin.');
|
|
591
|
-
}
|
|
592
|
-
else {
|
|
593
|
-
if (!isInteractiveTerminal()) {
|
|
594
|
-
throw new Error('A secret is required but the shell is not interactive. Pipe the key via stdin (--key-stdin).');
|
|
595
|
-
}
|
|
596
|
-
const { password } = await import('@inquirer/prompts');
|
|
597
|
-
token = await password({ message: `Enter API key for ${provider}`, mask: true });
|
|
598
|
-
}
|
|
599
|
-
setKeychainToken(item, token);
|
|
600
|
-
console.log(chalk.green(`Stored in keychain: ${item}`));
|
|
601
|
-
}
|
|
602
|
-
catch (err) {
|
|
603
|
-
console.error(chalk.red(err.message));
|
|
604
|
-
process.exit(1);
|
|
605
|
-
}
|
|
606
|
-
});
|
|
607
|
-
cmd
|
|
608
|
-
.command('logout <provider>')
|
|
609
|
-
.description('Remove a stored provider key from keychain')
|
|
610
|
-
.action((provider) => {
|
|
611
|
-
try {
|
|
612
|
-
const item = keychainItemName(provider);
|
|
613
|
-
const existed = deleteKeychainToken(item);
|
|
614
|
-
if (!existed) {
|
|
615
|
-
console.error(chalk.yellow(`No keychain item '${item}' to remove.`));
|
|
616
|
-
process.exit(1);
|
|
617
|
-
}
|
|
618
|
-
console.log(chalk.green(`Removed keychain item: ${item}`));
|
|
619
|
-
}
|
|
620
|
-
catch (err) {
|
|
621
|
-
console.error(chalk.red(err.message));
|
|
622
|
-
process.exit(1);
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
577
|
}
|
package/dist/commands/hooks.js
CHANGED
|
@@ -514,7 +514,7 @@ Examples:
|
|
|
514
514
|
}
|
|
515
515
|
else {
|
|
516
516
|
console.log(chalk.green(`\nRemoved ${removed} hook(s) from version homes.`));
|
|
517
|
-
console.log(chalk.gray(
|
|
517
|
+
console.log(chalk.gray("Central source unchanged. Restore any target with 'agents sync <agent>@<version> --yes'."));
|
|
518
518
|
}
|
|
519
519
|
});
|
|
520
520
|
// `hooks prune` moved to the top-level `agents prune cleanup` command.
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
* the coaching prose by piping the AGGREGATE (never raw transcripts) through a headless
|
|
32
32
|
* `claude -p`.
|
|
33
33
|
*
|
|
34
|
-
* `agents trends` is
|
|
34
|
+
* Former top-level `agents trends` is `agents insights mix` / `agents insights trends`.
|
|
35
35
|
*/
|
|
36
36
|
import type { Command } from 'commander';
|
|
37
37
|
export declare function registerInsightsCommand(program: Command): void;
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
* the coaching prose by piping the AGGREGATE (never raw transcripts) through a headless
|
|
32
32
|
* `claude -p`.
|
|
33
33
|
*
|
|
34
|
-
* `agents trends` is
|
|
34
|
+
* Former top-level `agents trends` is `agents insights mix` / `agents insights trends`.
|
|
35
35
|
*/
|
|
36
36
|
import * as fs from 'fs';
|
|
37
37
|
import chalk from 'chalk';
|
|
@@ -651,7 +651,8 @@ function configureInsightsCommand(cmd) {
|
|
|
651
651
|
\`agents insights mix\` — cheap counters from sessions.db + usage.db
|
|
652
652
|
Latency is \`agents perf\` (not mix). Quota is \`agents usage\`. Spend is
|
|
653
653
|
\`agents insights cost\`; shipped output is \`agents insights output\`. Skill/slash popularity
|
|
654
|
-
is \`agents sessions stats\`. \`agents trends\` is
|
|
654
|
+
is \`agents sessions stats\`. Former top-level \`agents trends\` is \`agents insights mix\`
|
|
655
|
+
(also \`agents insights trends\`).
|
|
655
656
|
|
|
656
657
|
The behavioural report parses in-scope transcripts once and caches facets; later runs
|
|
657
658
|
re-read only files that changed. \`--refresh\` forces a full re-read.
|
package/dist/commands/menubar.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import chalk from 'chalk';
|
|
10
10
|
import { setHelpSections } from '../lib/help.js';
|
|
11
|
-
import { enableMenubarService, disableMenubarService, getMenubarStatus, runMenubarSetup, } from '../lib/menubar/install-menubar.js';
|
|
11
|
+
import { enableMenubarService, disableMenubarService, getMenubarStatus, runMenubarSetup, buildMenubarDoctorReport, } from '../lib/menubar/install-menubar.js';
|
|
12
12
|
function notMac() {
|
|
13
13
|
if (process.platform !== 'darwin') {
|
|
14
14
|
console.log(chalk.yellow('AGI Menu is macOS only.'));
|
|
@@ -77,6 +77,32 @@ function printSetupResult(r) {
|
|
|
77
77
|
console.log(chalk.red('AGI Menu not fully configured.') + chalk.gray(' See the failed step above.'));
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
+
function printDoctorReport(r) {
|
|
81
|
+
console.log(chalk.bold('AGI Menu doctor\n'));
|
|
82
|
+
console.log(` install path ${r.installPath ? chalk.gray(r.installPath) : chalk.red('not installed')}`);
|
|
83
|
+
console.log(` installed version ${r.installedVersion ? chalk.gray(r.installedVersion) : chalk.gray('unknown')}`);
|
|
84
|
+
console.log(` CLI version ${chalk.gray(r.currentVersion)}${r.versionMatches ? '' : chalk.yellow(' (mismatch — `agents menubar setup` updates it)')}`);
|
|
85
|
+
const identity = r.signingIdentity === 'developer-id'
|
|
86
|
+
? chalk.green('Developer ID (update-stable)')
|
|
87
|
+
: r.signingIdentity === 'ad-hoc'
|
|
88
|
+
? chalk.red('ad-hoc (unstable — Accessibility grant breaks on every update)')
|
|
89
|
+
: chalk.gray('unknown (nothing installed)');
|
|
90
|
+
console.log(` signing identity ${identity}`);
|
|
91
|
+
console.log(` running ${r.running ? chalk.green('yes') : chalk.gray('no')}`);
|
|
92
|
+
if (r.staleRunningProcess.length > 0) {
|
|
93
|
+
for (const p of r.staleRunningProcess) {
|
|
94
|
+
const mark = p.stale
|
|
95
|
+
? chalk.red('started BEFORE the on-disk bundle — running the OLD binary')
|
|
96
|
+
: chalk.green('matches the on-disk bundle');
|
|
97
|
+
console.log(` pid ${String(p.pid).padEnd(10)} ${mark}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (r.accessibilityHintNeeded) {
|
|
101
|
+
console.log(chalk.yellow('\n Accessibility grant may not be trusted for the current binary.'));
|
|
102
|
+
console.log(chalk.gray(' Run `agents menubar setup` to reinstall + restart the helper, then grant access:'));
|
|
103
|
+
console.log(chalk.gray(' open "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"'));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
80
106
|
export function registerMenubarCommands(program) {
|
|
81
107
|
const menubar = program
|
|
82
108
|
.command('menubar')
|
|
@@ -184,6 +210,37 @@ export function registerMenubarCommands(program) {
|
|
|
184
210
|
}
|
|
185
211
|
printStatus(s);
|
|
186
212
|
});
|
|
213
|
+
const doctor = menubar
|
|
214
|
+
.command('doctor')
|
|
215
|
+
.description('Diagnose AGI Menu: install path, version skew, signing identity, stale process')
|
|
216
|
+
.option('--json', 'Emit machine-readable JSON')
|
|
217
|
+
.action((options) => {
|
|
218
|
+
const r = buildMenubarDoctorReport();
|
|
219
|
+
if (options.json) {
|
|
220
|
+
process.stdout.write(JSON.stringify(r) + '\n');
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (r.platform !== 'darwin') {
|
|
224
|
+
console.log(chalk.yellow('AGI Menu is macOS only.'));
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
printDoctorReport(r);
|
|
228
|
+
});
|
|
229
|
+
setHelpSections(doctor, {
|
|
230
|
+
examples: `
|
|
231
|
+
# Why did Accessibility ask again after an update?
|
|
232
|
+
agents menubar doctor
|
|
233
|
+
`,
|
|
234
|
+
notes: `
|
|
235
|
+
Read-only — never installs, restarts, or resets anything. Reports the
|
|
236
|
+
installed bundle's signing identity (ad-hoc signing breaks the
|
|
237
|
+
Accessibility grant on every update; Developer ID is stable across
|
|
238
|
+
updates) and whether a live helper pid started before the on-disk
|
|
239
|
+
bundle's last write — the sign that a running process is still the
|
|
240
|
+
binary an update just replaced. \`agents menubar setup\` is the fix for
|
|
241
|
+
anything this flags.
|
|
242
|
+
`,
|
|
243
|
+
});
|
|
187
244
|
// Bare `agents menubar` -> status.
|
|
188
245
|
menubar.action(() => {
|
|
189
246
|
const s = getMenubarStatus();
|
|
@@ -440,7 +440,7 @@ export function registerMonitorsCommands(program) {
|
|
|
440
440
|
.option('--dedupe-key <expr>', 'Regex whose first match is the "same event" signature (default: full output)')
|
|
441
441
|
.option('--every', 'Fire on every observation (no dedupe) — rate-limit this')
|
|
442
442
|
// ACTION
|
|
443
|
-
.option('--run <agent>', 'Spawn an agent (claude, codex,
|
|
443
|
+
.option('--run <agent>', 'Spawn an agent (claude, codex, ..., or a custom harness from agents harness list) with the prompt on fire')
|
|
444
444
|
.option('--prompt <prompt>', 'Prompt for --run; {event} is replaced with the fired event')
|
|
445
445
|
.option('--mode <mode>', 'Execution mode for --run: plan, edit, auto, or skip')
|
|
446
446
|
.option('--effort <effort>', 'Reasoning effort for --run: low | medium | high | xhigh | max | auto')
|
package/dist/commands/org.d.ts
CHANGED
|
@@ -3,4 +3,9 @@ import type { Command } from 'commander';
|
|
|
3
3
|
export declare function resolveInviteRole(raw: string | undefined): 'admin' | 'member';
|
|
4
4
|
/** Validate a role argument before any network call — same rule the backend enforces server-side. */
|
|
5
5
|
export declare function parseRole(raw: string): 'admin' | 'member';
|
|
6
|
+
/** One-line deprecation for the leftover top-level `agents org` spelling. */
|
|
7
|
+
export declare function printOrgDeprecation(): void;
|
|
8
|
+
/** Canonical home: `agents auth space …`. */
|
|
9
|
+
export declare function registerAuthSpaceCommand(auth: Command): void;
|
|
10
|
+
/** Leftover top-level spelling — same tree, deprecation on every path. */
|
|
6
11
|
export declare function registerOrgCommand(program: Command): void;
|
package/dist/commands/org.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { setHelpSections } from '../lib/help.js';
|
|
3
|
+
import { runOrDie } from '../lib/format.js';
|
|
3
4
|
import { createSpace, createSpaceInvite, fetchWhoAmI, listSpaceMembers, listSpaces, removeSpaceMember, resolveMemberFromList, resolvePrixToken, resolveSpaceFromList, slugify, updateSpaceMemberRole, } from '../lib/prix-account.js';
|
|
4
5
|
/** Every `agents org` subcommand needs a token up front — one place to say so. */
|
|
5
6
|
function requireToken() {
|
|
@@ -40,7 +41,7 @@ async function runList(o) {
|
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
42
43
|
if (!spaces.length) {
|
|
43
|
-
console.log(chalk.gray("No spaces. Create one with 'agents
|
|
44
|
+
console.log(chalk.gray("No spaces. Create one with 'agents auth space create <name>'."));
|
|
44
45
|
return;
|
|
45
46
|
}
|
|
46
47
|
for (const space of spaces)
|
|
@@ -132,43 +133,96 @@ async function runLeave(spaceArg, o) {
|
|
|
132
133
|
}
|
|
133
134
|
console.log(chalk.green(`Left '${space.name}'.`));
|
|
134
135
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
/** One-line deprecation for the leftover top-level `agents org` spelling. */
|
|
137
|
+
export function printOrgDeprecation() {
|
|
138
|
+
console.error(chalk.yellow('agents org is deprecated — use `agents auth space`.'));
|
|
139
|
+
}
|
|
140
|
+
/** Shared space CRUD tree — canonical under `auth space`, leftover under `org`. */
|
|
141
|
+
function attachSpaceCommands(parent, opts) {
|
|
142
|
+
const before = () => {
|
|
143
|
+
if (opts.deprecated)
|
|
144
|
+
printOrgDeprecation();
|
|
145
|
+
};
|
|
146
|
+
const jsonFlag = (o, command) => !!(o.json || command.optsWithGlobals().json);
|
|
147
|
+
parent.command('create <name>').description('Create a space (free tier: 1 owned space)')
|
|
138
148
|
.option('--slug <slug>', 'Override the derived slug')
|
|
139
149
|
.option('--description <text>', 'Optional description')
|
|
140
150
|
.option('--json', 'Machine-readable output')
|
|
141
|
-
.action((name, o, command) =>
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
151
|
+
.action((name, o, command) => {
|
|
152
|
+
before();
|
|
153
|
+
const json = jsonFlag(o, command);
|
|
154
|
+
return runOrDie(() => runCreate(name, { ...o, json }), { json });
|
|
155
|
+
});
|
|
156
|
+
parent.command('list').description('List spaces you own or belong to').option('--json', 'Machine-readable output')
|
|
157
|
+
.action((o, command) => {
|
|
158
|
+
before();
|
|
159
|
+
const json = jsonFlag(o, command);
|
|
160
|
+
return runOrDie(() => runList({ json }), { json });
|
|
161
|
+
});
|
|
162
|
+
parent.command('view [space]').description('Show one space (defaults to your only space)').option('--json', 'Machine-readable output')
|
|
163
|
+
.action((space, o, command) => {
|
|
164
|
+
before();
|
|
165
|
+
const json = jsonFlag(o, command);
|
|
166
|
+
return runOrDie(() => runView(space, { json }), { json });
|
|
167
|
+
});
|
|
168
|
+
parent.command('invite <email>').description('Invite (or directly add) a member')
|
|
147
169
|
.option('--role <role>', 'admin | member', 'member')
|
|
148
170
|
.option('--space <id-or-slug>', 'Space to invite into (defaults to your only space)')
|
|
149
171
|
.option('--json', 'Machine-readable output')
|
|
150
|
-
.action((email, o, command) =>
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
172
|
+
.action((email, o, command) => {
|
|
173
|
+
before();
|
|
174
|
+
const json = jsonFlag(o, command);
|
|
175
|
+
return runOrDie(() => runInvite(email, { ...o, json }), { json });
|
|
176
|
+
});
|
|
177
|
+
parent.command('members [space]').description("List a space's members").option('--json', 'Machine-readable output')
|
|
178
|
+
.action((space, o, command) => {
|
|
179
|
+
before();
|
|
180
|
+
const json = jsonFlag(o, command);
|
|
181
|
+
return runOrDie(() => runMembers(space, { json }), { json });
|
|
182
|
+
});
|
|
183
|
+
parent.command('role <email> <role>').description("Change a member's role (owner-only for admin)")
|
|
154
184
|
.option('--space <id-or-slug>', 'Space to change (defaults to your only space)')
|
|
155
185
|
.option('--json', 'Machine-readable output')
|
|
156
|
-
.action((email, role, o, command) =>
|
|
157
|
-
|
|
186
|
+
.action((email, role, o, command) => {
|
|
187
|
+
before();
|
|
188
|
+
const json = jsonFlag(o, command);
|
|
189
|
+
return runOrDie(() => runRole(email, role, { ...o, json }), { json });
|
|
190
|
+
});
|
|
191
|
+
parent.command('remove <email>').description('Remove a member from a space')
|
|
158
192
|
.option('--space <id-or-slug>', 'Space to remove from (defaults to your only space)')
|
|
159
193
|
.option('--json', 'Machine-readable output')
|
|
160
|
-
.action((email, o, command) =>
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
194
|
+
.action((email, o, command) => {
|
|
195
|
+
before();
|
|
196
|
+
const json = jsonFlag(o, command);
|
|
197
|
+
return runOrDie(() => runRemove(email, { ...o, json }), { json });
|
|
198
|
+
});
|
|
199
|
+
parent.command('leave [space]').description('Leave a space you do not own').option('--json', 'Machine-readable output')
|
|
200
|
+
.action((space, o, command) => {
|
|
201
|
+
before();
|
|
202
|
+
const json = jsonFlag(o, command);
|
|
203
|
+
return runOrDie(() => runLeave(space, { json }), { json });
|
|
204
|
+
});
|
|
205
|
+
setHelpSections(parent, {
|
|
206
|
+
examples: `${opts.prefix} create acme-team
|
|
207
|
+
${opts.prefix} list
|
|
208
|
+
${opts.prefix} view acme-team
|
|
209
|
+
${opts.prefix} invite dev@example.com --role admin
|
|
210
|
+
${opts.prefix} members
|
|
211
|
+
${opts.prefix} role dev@example.com admin
|
|
212
|
+
${opts.prefix} remove dev@example.com
|
|
213
|
+
${opts.prefix} leave acme-team`,
|
|
214
|
+
notes: opts.deprecated
|
|
215
|
+
? 'Deprecated alias of `agents auth space`. Maps to the Rush backend\'s /api/v1/spaces (the free-tier team primitive), not /api/v1/orgs. Free tier: 1 owned space, 3 members per space. Every command needs `agents auth login` (or a `rush login` session) first. `--space` is only needed once you belong to more than one space.'
|
|
216
|
+
: 'Maps to the Rush backend\'s /api/v1/spaces (the free-tier team primitive), not /api/v1/orgs. Free tier: 1 owned space, 3 members per space. Every command needs `agents auth login` (or a `rush login` session) first. `--space` is only needed once you belong to more than one space. The leftover `agents org` spelling still works and prints a deprecation line.',
|
|
173
217
|
});
|
|
174
218
|
}
|
|
219
|
+
/** Canonical home: `agents auth space …`. */
|
|
220
|
+
export function registerAuthSpaceCommand(auth) {
|
|
221
|
+
const space = auth.command('space').description('Create and manage a Prix space (invite collaborators)');
|
|
222
|
+
attachSpaceCommands(space, { prefix: 'agents auth space' });
|
|
223
|
+
}
|
|
224
|
+
/** Leftover top-level spelling — same tree, deprecation on every path. */
|
|
225
|
+
export function registerOrgCommand(program) {
|
|
226
|
+
const org = program.command('org').description('Deprecated alias of `agents auth space` — create and manage a Prix space');
|
|
227
|
+
attachSpaceCommands(org, { prefix: 'agents org', deprecated: true });
|
|
228
|
+
}
|
package/dist/commands/output.js
CHANGED
|
@@ -10,7 +10,7 @@ import { formatUsd, PRICING_VERSION } from '../lib/pricing/index.js';
|
|
|
10
10
|
import { formatDuration } from '../lib/session/render.js';
|
|
11
11
|
import { terminalWidth, truncateToWidth, padToWidth } from '../lib/session/width.js';
|
|
12
12
|
import { collectGitOutput } from '../lib/output/git-output.js';
|
|
13
|
-
import { loadDevices
|
|
13
|
+
import { loadDevices } from '../lib/devices/registry.js';
|
|
14
14
|
import { machineId } from '../lib/session/sync/config.js';
|
|
15
15
|
import { stripClixml } from '../lib/hosts/remote-cmd.js';
|
|
16
16
|
const execFileAsync = promisify(execFile);
|
|
@@ -189,7 +189,7 @@ async function outputAction(options) {
|
|
|
189
189
|
const self = machineId();
|
|
190
190
|
const registry = await loadDevices();
|
|
191
191
|
const remotes = Object.values(registry)
|
|
192
|
-
.filter(d => d.tailscale?.online && d.name !== self
|
|
192
|
+
.filter(d => d.tailscale?.online && d.name !== self)
|
|
193
193
|
.map(d => d.name);
|
|
194
194
|
if (!options.json)
|
|
195
195
|
console.error(chalk.gray(`Folding in ${remotes.length} online device${remotes.length !== 1 ? 's' : ''}…`));
|
|
@@ -191,7 +191,7 @@ export async function addProfile(name, opts, label = 'Profile') {
|
|
|
191
191
|
authEnvVar,
|
|
192
192
|
});
|
|
193
193
|
if (account) {
|
|
194
|
-
profile.account = account.
|
|
194
|
+
profile.account = account.name;
|
|
195
195
|
profile.provider = account.provider;
|
|
196
196
|
}
|
|
197
197
|
if (opts.fromSecrets)
|
|
@@ -213,7 +213,7 @@ export async function addProfile(name, opts, label = 'Profile') {
|
|
|
213
213
|
}
|
|
214
214
|
const profile = profileFromPreset(name, preset, opts.version);
|
|
215
215
|
if (account) {
|
|
216
|
-
profile.account = account.
|
|
216
|
+
profile.account = account.name;
|
|
217
217
|
profile.provider = account.provider;
|
|
218
218
|
}
|
|
219
219
|
if (opts.fromSecrets)
|
package/dist/commands/prune.js
CHANGED
|
@@ -12,10 +12,11 @@
|
|
|
12
12
|
* agents-cli.
|
|
13
13
|
* - Runs: routine execution logs, keeping only the last N per job.
|
|
14
14
|
*
|
|
15
|
-
* Sync (additive: copy missing/changed files into version homes) is
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* Sync (additive: copy missing/changed files into version homes) is the job
|
|
16
|
+
* of `agents sync` / `agents refresh` — the shim's launch hook
|
|
17
|
+
* (`agents sync --launch`) is project-scoped only and deliberately skips
|
|
18
|
+
* version-home reconciliation. Pruning, however, is destructive, so it stays
|
|
19
|
+
* explicit.
|
|
19
20
|
*
|
|
20
21
|
* Default scope: each agent's currently-pinned default version for orphan
|
|
21
22
|
* cleanup, plus the standard cross-agent version-dedup pass. Pass `--all`
|
|
@@ -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';
|
|
@@ -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);
|