@phnx-labs/agents-cli 1.20.72 → 1.20.73
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 +299 -0
- package/README.md +40 -4
- package/dist/bin/agents +0 -0
- package/dist/commands/activity.d.ts +12 -0
- package/dist/commands/activity.js +68 -0
- package/dist/commands/apply.d.ts +13 -0
- package/dist/commands/apply.js +28 -3
- package/dist/commands/browser.js +1 -1
- package/dist/commands/cloud.js +21 -11
- package/dist/commands/doctor.js +8 -4
- package/dist/commands/events.d.ts +11 -10
- package/dist/commands/events.js +30 -21
- package/dist/commands/exec.d.ts +34 -0
- package/dist/commands/exec.js +337 -39
- package/dist/commands/feed.d.ts +13 -0
- package/dist/commands/feed.js +130 -29
- package/dist/commands/hq.d.ts +2 -0
- package/dist/commands/hq.js +58 -0
- package/dist/commands/lease.d.ts +19 -0
- package/dist/commands/lease.js +138 -11
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +123 -0
- package/dist/commands/logs.js +1 -1
- package/dist/commands/mine.d.ts +27 -0
- package/dist/commands/mine.js +207 -0
- package/dist/commands/monitors.js +79 -49
- package/dist/commands/plugins.js +1 -0
- package/dist/commands/profiles.js +158 -0
- package/dist/commands/repo.js +2 -60
- package/dist/commands/resources.d.ts +5 -0
- package/dist/commands/resources.js +95 -0
- package/dist/commands/routines.d.ts +2 -0
- package/dist/commands/routines.js +139 -37
- package/dist/commands/secrets.js +234 -47
- package/dist/commands/send.d.ts +15 -0
- package/dist/commands/send.js +62 -0
- package/dist/commands/sessions-tail.d.ts +1 -0
- package/dist/commands/sessions-tail.js +20 -9
- package/dist/commands/sessions.js +18 -3
- package/dist/commands/setup-mine.d.ts +18 -0
- package/dist/commands/setup-mine.js +106 -0
- package/dist/commands/setup-share.js +2 -2
- package/dist/commands/setup.js +3 -1
- package/dist/commands/share.d.ts +8 -1
- package/dist/commands/share.js +122 -37
- package/dist/commands/ssh.d.ts +9 -0
- package/dist/commands/ssh.js +196 -26
- package/dist/commands/sync.js +1 -1
- package/dist/commands/teams.js +11 -2
- package/dist/index.js +79 -10
- package/dist/lib/activity.d.ts +124 -0
- package/dist/lib/activity.js +542 -0
- package/dist/lib/agents.js +16 -5
- package/dist/lib/artifact-actions.d.ts +1 -1
- package/dist/lib/artifact-actions.js +1 -1
- package/dist/lib/ask-classifier.d.ts +2 -1
- package/dist/lib/ask-classifier.js +3 -3
- package/dist/lib/auth-health.d.ts +32 -4
- package/dist/lib/auth-health.js +40 -1
- package/dist/lib/auto-pull.js +8 -1
- package/dist/lib/brand.d.ts +40 -0
- package/dist/lib/brand.js +122 -0
- package/dist/lib/browser/drivers/ssh.js +4 -7
- package/dist/lib/browser/service.js +6 -8
- package/dist/lib/channels/providers/index.d.ts +2 -0
- package/dist/lib/channels/providers/index.js +20 -0
- package/dist/lib/channels/providers/mailbox.d.ts +2 -0
- package/dist/lib/channels/providers/mailbox.js +26 -0
- package/dist/lib/channels/providers/openclaw-telegram.d.ts +2 -0
- package/dist/lib/channels/providers/openclaw-telegram.js +34 -0
- package/dist/lib/channels/providers/rush.d.ts +6 -0
- package/dist/lib/channels/providers/rush.js +55 -0
- package/dist/lib/channels/registry.d.ts +42 -0
- package/dist/lib/channels/registry.js +20 -0
- package/dist/lib/channels/resolve.d.ts +11 -0
- package/dist/lib/channels/resolve.js +12 -0
- package/dist/lib/cli-resources.d.ts +18 -0
- package/dist/lib/cli-resources.js +53 -4
- package/dist/lib/cloud/codex.js +6 -3
- package/dist/lib/cloud/factory.d.ts +1 -0
- package/dist/lib/cloud/factory.js +10 -4
- package/dist/lib/cloud/rush.d.ts +3 -1
- package/dist/lib/cloud/rush.js +6 -1
- package/dist/lib/cloud/types.d.ts +2 -0
- package/dist/lib/codex-home.d.ts +35 -0
- package/dist/lib/codex-home.js +136 -0
- package/dist/lib/crabbox/cli.d.ts +44 -0
- package/dist/lib/crabbox/cli.js +120 -20
- package/dist/lib/crabbox/lease.d.ts +52 -1
- package/dist/lib/crabbox/lease.js +117 -16
- package/dist/lib/crabbox/progress.d.ts +31 -0
- package/dist/lib/crabbox/progress.js +76 -0
- package/dist/lib/crabbox/runtimes.d.ts +4 -0
- package/dist/lib/crabbox/runtimes.js +33 -8
- package/dist/lib/crabbox/setup-copy.d.ts +87 -0
- package/dist/lib/crabbox/setup-copy.js +127 -0
- package/dist/lib/daemon.d.ts +5 -5
- package/dist/lib/daemon.js +9 -9
- package/dist/lib/drive-sync.js +6 -3
- package/dist/lib/event-stream.d.ts +36 -0
- package/dist/lib/event-stream.js +68 -0
- package/dist/lib/events.d.ts +1 -1
- package/dist/lib/exec.d.ts +11 -0
- package/dist/lib/exec.js +23 -2
- package/dist/lib/feed-policy.d.ts +1 -1
- package/dist/lib/feed-policy.js +14 -9
- package/dist/lib/feed-ranking.d.ts +32 -0
- package/dist/lib/feed-ranking.js +224 -0
- package/dist/lib/feed.d.ts +35 -2
- package/dist/lib/feed.js +66 -3
- package/dist/lib/fleet/auth-sync.d.ts +53 -0
- package/dist/lib/fleet/auth-sync.js +92 -0
- package/dist/lib/fleet/remote-login.d.ts +187 -0
- package/dist/lib/fleet/remote-login.js +556 -0
- package/dist/lib/format.d.ts +30 -3
- package/dist/lib/format.js +34 -5
- package/dist/lib/fs-atomic.d.ts +7 -2
- package/dist/lib/fs-atomic.js +8 -12
- package/dist/lib/git.d.ts +16 -0
- package/dist/lib/git.js +79 -2
- package/dist/lib/heal.js +11 -3
- package/dist/lib/hosts/progress.d.ts +28 -10
- package/dist/lib/hosts/progress.js +79 -22
- package/dist/lib/hosts/remote-cmd.js +4 -0
- package/dist/lib/hq/floor.d.ts +87 -0
- package/dist/lib/hq/floor.js +226 -0
- package/dist/lib/menubar/install-menubar.js +14 -20
- package/dist/lib/notify.d.ts +1 -0
- package/dist/lib/notify.js +3 -3
- package/dist/lib/open-url.d.ts +2 -0
- package/dist/lib/open-url.js +19 -0
- package/dist/lib/openclaw-keychain.d.ts +56 -0
- package/dist/lib/openclaw-keychain.js +236 -0
- package/dist/lib/overdue.js +10 -0
- package/dist/lib/permissions.d.ts +44 -1
- package/dist/lib/permissions.js +284 -7
- package/dist/lib/project-launch.d.ts +6 -12
- package/dist/lib/project-launch.js +13 -228
- package/dist/lib/project-resources.d.ts +7 -0
- package/dist/lib/project-resources.js +291 -0
- package/dist/lib/pty-client.d.ts +27 -0
- package/dist/lib/pty-client.js +136 -10
- package/dist/lib/refresh.js +14 -10
- package/dist/lib/resource-profiles.d.ts +26 -0
- package/dist/lib/resource-profiles.js +157 -0
- package/dist/lib/resources/permissions.js +7 -1
- package/dist/lib/resources/types.d.ts +1 -1
- package/dist/lib/resources.d.ts +1 -1
- package/dist/lib/resources.js +32 -3
- package/dist/lib/routines.d.ts +11 -0
- package/dist/lib/routines.js +56 -15
- package/dist/lib/runner.d.ts +1 -0
- package/dist/lib/runner.js +66 -5
- package/dist/lib/secrets/bundles.d.ts +16 -3
- package/dist/lib/secrets/bundles.js +206 -37
- package/dist/lib/secrets/icloud-import.d.ts +2 -2
- package/dist/lib/secrets/icloud-import.js +9 -6
- package/dist/lib/secrets/mcp.js +1 -1
- package/dist/lib/secrets/vault-age-helper.d.ts +1 -0
- package/dist/lib/secrets/vault-age-helper.js +34 -0
- package/dist/lib/secrets/vault.d.ts +49 -0
- package/dist/lib/secrets/vault.js +397 -0
- package/dist/lib/self-heal/checks/path.js +3 -1
- package/dist/lib/self-heal/checks/shadowing.js +10 -2
- package/dist/lib/self-heal/checks/shims.js +19 -11
- package/dist/lib/session/cloud.d.ts +2 -2
- package/dist/lib/session/cloud.js +2 -2
- package/dist/lib/session/db.d.ts +4 -0
- package/dist/lib/session/db.js +44 -7
- package/dist/lib/session/discover.d.ts +2 -0
- package/dist/lib/session/discover.js +114 -3
- package/dist/lib/session/stream-render.d.ts +3 -0
- package/dist/lib/session/stream-render.js +130 -0
- package/dist/lib/session/types.d.ts +6 -0
- package/dist/lib/share/analytics.d.ts +13 -0
- package/dist/lib/share/analytics.js +45 -0
- package/dist/lib/share/config.d.ts +19 -5
- package/dist/lib/share/config.js +44 -8
- package/dist/lib/share/provision.d.ts +58 -6
- package/dist/lib/share/provision.js +97 -22
- package/dist/lib/share/publish.d.ts +36 -13
- package/dist/lib/share/publish.js +55 -8
- package/dist/lib/share/worker-template.js +83 -17
- package/dist/lib/shims.d.ts +9 -0
- package/dist/lib/shims.js +91 -13
- package/dist/lib/ssh-exec.d.ts +14 -0
- package/dist/lib/ssh-exec.js +57 -0
- package/dist/lib/staleness/detectors/hooks.js +25 -1
- package/dist/lib/staleness/detectors/permissions.js +66 -0
- package/dist/lib/staleness/detectors/workflows.js +20 -0
- package/dist/lib/staleness/writers/hooks.js +58 -4
- package/dist/lib/staleness/writers/permissions.js +2 -2
- package/dist/lib/staleness/writers/skills.js +1 -1
- package/dist/lib/staleness/writers/sources.d.ts +10 -1
- package/dist/lib/staleness/writers/sources.js +68 -1
- package/dist/lib/star-nudge.d.ts +45 -0
- package/dist/lib/star-nudge.js +91 -0
- package/dist/lib/startup/command-registry.d.ts +6 -1
- package/dist/lib/startup/command-registry.js +17 -3
- package/dist/lib/state.d.ts +2 -0
- package/dist/lib/state.js +3 -0
- package/dist/lib/subagents-registry.d.ts +2 -0
- package/dist/lib/subagents-registry.js +3 -0
- package/dist/lib/teams/parsers.js +214 -6
- package/dist/lib/teams/supervisor.d.ts +7 -0
- package/dist/lib/teams/supervisor.js +2 -1
- package/dist/lib/template.d.ts +1 -1
- package/dist/lib/template.js +1 -1
- package/dist/lib/triggers/webhook.js +36 -3
- package/dist/lib/types.d.ts +73 -0
- package/dist/lib/version.d.ts +40 -0
- package/dist/lib/version.js +94 -16
- package/dist/lib/versions.d.ts +11 -0
- package/dist/lib/versions.js +208 -76
- package/dist/lib/workflows.d.ts +2 -0
- package/dist/lib/workflows.js +88 -0
- package/package.json +2 -1
- package/dist/commands/daemon.d.ts +0 -10
- package/dist/commands/daemon.js +0 -121
package/dist/commands/logs.js
CHANGED
|
@@ -62,7 +62,7 @@ async function showSession(session, follow, full, json = false) {
|
|
|
62
62
|
console.error(chalk.red(`Tailing is supported for claude and codex sessions only (got ${session.agent}).`));
|
|
63
63
|
process.exit(2);
|
|
64
64
|
}
|
|
65
|
-
await streamSessionTail(session, {});
|
|
65
|
+
await streamSessionTail(session, { raw: full });
|
|
66
66
|
return;
|
|
67
67
|
}
|
|
68
68
|
await renderSessionLog(session, full ? 'markdown' : 'summary');
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agents mine` — white-label the CLI under your own name.
|
|
3
|
+
*
|
|
4
|
+
* `agents mine init <name>` mints a personally-named binary (e.g. `jack`) that
|
|
5
|
+
* IS agents-cli: a pure pass-through shim on PATH that runs every `agents` verb
|
|
6
|
+
* under the brand's name, with the brand's disabled commands and curated
|
|
7
|
+
* resource profile applied. `list` / `toggle` / `remove` manage brands.
|
|
8
|
+
*
|
|
9
|
+
* The discoverable entry point is the `agents setup mine` wizard
|
|
10
|
+
* (see setup-mine.ts), which delegates to `initBrand` here.
|
|
11
|
+
*
|
|
12
|
+
* Storage: brand config in `meta.brands` (agents.yaml); the curated resource set
|
|
13
|
+
* reuses the resource-profile engine — each brand owns a preset named
|
|
14
|
+
* `mine-<name>` in `meta.profiles.presets`. See lib/brand.ts.
|
|
15
|
+
*/
|
|
16
|
+
import type { Command } from 'commander';
|
|
17
|
+
/**
|
|
18
|
+
* Create (or re-mint) a brand. Shared by `mine init` and the `setup mine`
|
|
19
|
+
* wizard. Writes the shim, the brand config, and an empty resource preset.
|
|
20
|
+
*/
|
|
21
|
+
export declare function initBrand(name: string, opts?: {
|
|
22
|
+
disabledCommands?: string[];
|
|
23
|
+
force?: boolean;
|
|
24
|
+
}): {
|
|
25
|
+
pathWarning: boolean;
|
|
26
|
+
};
|
|
27
|
+
export declare function registerMineCommand(program: Command): void;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { validateBrandName, listBrands, getBrandConfig, upsertBrand, removeBrand, brandPresetName, } from '../lib/brand.js';
|
|
3
|
+
import { createBrandShim, removeBrandShim, isShimsInPath } from '../lib/shims.js';
|
|
4
|
+
import { updateMeta } from '../lib/state.js';
|
|
5
|
+
import { COMMAND_LOADERS } from '../lib/startup/command-registry.js';
|
|
6
|
+
/** Built-in top-level command names, for validating `--disable <cmd>`. */
|
|
7
|
+
function knownCommandNames() {
|
|
8
|
+
const names = new Set(Object.keys(COMMAND_LOADERS));
|
|
9
|
+
// Inline aliases registered outside COMMAND_LOADERS (see src/index.ts).
|
|
10
|
+
for (const n of ['perms', 'exec', 'jobs', 'cron', 'upgrade'])
|
|
11
|
+
names.add(n);
|
|
12
|
+
return names;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Add/remove a `!name` exclusion on a preset's pattern list for one kind,
|
|
16
|
+
* keeping `*` so everything not explicitly disabled stays enabled. Deletes the
|
|
17
|
+
* key entirely once nothing but `*` remains, so a clean brand has an empty preset.
|
|
18
|
+
*/
|
|
19
|
+
function applyResourceToggle(preset, kind, name, enable) {
|
|
20
|
+
// Cast to a plain string-bag: writing through the union-keyed `preset[kind]`
|
|
21
|
+
// collapses to `never` under strict TS, so index the bag instead.
|
|
22
|
+
const bag = preset;
|
|
23
|
+
const arr = [...(bag[kind] ?? [])];
|
|
24
|
+
if (arr.length === 0)
|
|
25
|
+
arr.push('*');
|
|
26
|
+
const excl = `!${name}`;
|
|
27
|
+
const idx = arr.indexOf(excl);
|
|
28
|
+
if (enable) {
|
|
29
|
+
if (idx !== -1)
|
|
30
|
+
arr.splice(idx, 1);
|
|
31
|
+
}
|
|
32
|
+
else if (idx === -1) {
|
|
33
|
+
arr.push(excl);
|
|
34
|
+
}
|
|
35
|
+
const onlyStar = arr.length === 1 && arr[0] === '*';
|
|
36
|
+
if (onlyStar)
|
|
37
|
+
delete bag[kind];
|
|
38
|
+
else
|
|
39
|
+
bag[kind] = arr;
|
|
40
|
+
}
|
|
41
|
+
/** Ensure the brand's preset exists in meta.profiles.presets and return a mutable copy path. */
|
|
42
|
+
function ensurePresetExists(name) {
|
|
43
|
+
const presetName = brandPresetName(name);
|
|
44
|
+
updateMeta((meta) => {
|
|
45
|
+
const profiles = meta.profiles ?? {};
|
|
46
|
+
const presets = { ...(profiles.presets ?? {}) };
|
|
47
|
+
if (!presets[presetName]) {
|
|
48
|
+
presets[presetName] = { description: `Resource set for the "${name}" brand` };
|
|
49
|
+
}
|
|
50
|
+
return { ...meta, profiles: { ...profiles, presets } };
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** Mutate the brand's resource preset under lock. */
|
|
54
|
+
function editPreset(name, fn) {
|
|
55
|
+
const presetName = brandPresetName(name);
|
|
56
|
+
updateMeta((meta) => {
|
|
57
|
+
const profiles = meta.profiles ?? {};
|
|
58
|
+
const presets = { ...(profiles.presets ?? {}) };
|
|
59
|
+
const preset = { ...(presets[presetName] ?? {}) };
|
|
60
|
+
fn(preset);
|
|
61
|
+
presets[presetName] = preset;
|
|
62
|
+
return { ...meta, profiles: { ...profiles, presets } };
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create (or re-mint) a brand. Shared by `mine init` and the `setup mine`
|
|
67
|
+
* wizard. Writes the shim, the brand config, and an empty resource preset.
|
|
68
|
+
*/
|
|
69
|
+
export function initBrand(name, opts = {}) {
|
|
70
|
+
const err = validateBrandName(name);
|
|
71
|
+
if (err) {
|
|
72
|
+
console.error(chalk.red(err));
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
if (getBrandConfig(name) && !opts.force) {
|
|
76
|
+
console.error(chalk.red(`Brand "${name}" already exists. Use --force to re-mint, or 'agents mine toggle ${name}'.`));
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
ensurePresetExists(name);
|
|
80
|
+
const disabled = (opts.disabledCommands ?? []).filter((c) => c.length > 0);
|
|
81
|
+
const known = knownCommandNames();
|
|
82
|
+
for (const c of disabled) {
|
|
83
|
+
if (!known.has(c))
|
|
84
|
+
console.error(chalk.yellow(` note: "${c}" is not a known command — kept anyway.`));
|
|
85
|
+
}
|
|
86
|
+
const cfg = {
|
|
87
|
+
name,
|
|
88
|
+
enabled: true,
|
|
89
|
+
profile: brandPresetName(name),
|
|
90
|
+
...(disabled.length > 0 ? { disabledCommands: disabled } : {}),
|
|
91
|
+
};
|
|
92
|
+
upsertBrand(cfg);
|
|
93
|
+
createBrandShim(name);
|
|
94
|
+
const pathWarning = !isShimsInPath();
|
|
95
|
+
return { pathWarning };
|
|
96
|
+
}
|
|
97
|
+
function printMinted(name, pathWarning) {
|
|
98
|
+
console.log(`${chalk.green('Minted')} ${chalk.bold(name)} — your own agents CLI.`);
|
|
99
|
+
console.log(chalk.dim(` try: ${name} --help ${name} run claude "hello"`));
|
|
100
|
+
if (pathWarning) {
|
|
101
|
+
console.log(chalk.yellow(` note: the shims dir isn't on your PATH yet — run 'agents setup' or open a new shell.`));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function registerMineCommand(program) {
|
|
105
|
+
const cmd = program
|
|
106
|
+
.command('mine')
|
|
107
|
+
.description('White-label the CLI: your own personally-named binary (e.g. `jack`)');
|
|
108
|
+
cmd
|
|
109
|
+
.command('init <name>')
|
|
110
|
+
.description('Mint your own branded CLI that runs every agents verb under <name>')
|
|
111
|
+
.option('--disable <commands...>', 'Built-in commands to hide from this brand (e.g. teams cloud)')
|
|
112
|
+
.option('--force', 'Re-mint even if the brand already exists')
|
|
113
|
+
.action((name, options) => {
|
|
114
|
+
const { pathWarning } = initBrand(name, {
|
|
115
|
+
disabledCommands: options.disable,
|
|
116
|
+
force: options.force,
|
|
117
|
+
});
|
|
118
|
+
printMinted(name, pathWarning);
|
|
119
|
+
});
|
|
120
|
+
cmd
|
|
121
|
+
.command('list')
|
|
122
|
+
.alias('ls')
|
|
123
|
+
.description('Show your brands and what each has turned off')
|
|
124
|
+
.action(() => {
|
|
125
|
+
const brands = listBrands();
|
|
126
|
+
const entries = Object.entries(brands);
|
|
127
|
+
if (entries.length === 0) {
|
|
128
|
+
console.log(chalk.gray("No brands yet. Try: agents setup mine (or: agents mine init jack)"));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const width = entries.reduce((m, [n]) => Math.max(m, n.length), 0);
|
|
132
|
+
for (const [name, cfg] of entries) {
|
|
133
|
+
const off = cfg.disabledCommands?.length ? `disabled: ${cfg.disabledCommands.join(', ')}` : 'all commands on';
|
|
134
|
+
const state = cfg.enabled === false ? chalk.yellow('(disabled) ') : '';
|
|
135
|
+
console.log(` ${chalk.bold(name.padEnd(width))} ${state}${chalk.dim(off)}`);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
cmd
|
|
139
|
+
.command('toggle <name>')
|
|
140
|
+
.description('Enable/disable features for a brand')
|
|
141
|
+
.option('--disable <commands...>', 'Hide these built-in commands')
|
|
142
|
+
.option('--enable <commands...>', 'Un-hide these built-in commands')
|
|
143
|
+
.option('--disable-plugin <names...>', 'Disable these plugins for the brand')
|
|
144
|
+
.option('--enable-plugin <names...>', 'Re-enable these plugins')
|
|
145
|
+
.option('--disable-skill <names...>', 'Disable these skills for the brand')
|
|
146
|
+
.option('--enable-skill <names...>', 'Re-enable these skills')
|
|
147
|
+
.action((name, options) => {
|
|
148
|
+
const cfg = getBrandConfig(name);
|
|
149
|
+
if (!cfg) {
|
|
150
|
+
console.error(chalk.red(`No brand named "${name}". Create it with 'agents mine init ${name}'.`));
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
// Built-in command toggles → brand.disabledCommands.
|
|
154
|
+
const disabledSet = new Set(cfg.disabledCommands ?? []);
|
|
155
|
+
const known = knownCommandNames();
|
|
156
|
+
for (const c of options.disable ?? []) {
|
|
157
|
+
if (!known.has(c))
|
|
158
|
+
console.error(chalk.yellow(` note: "${c}" is not a known command — kept anyway.`));
|
|
159
|
+
disabledSet.add(c);
|
|
160
|
+
}
|
|
161
|
+
for (const c of options.enable ?? [])
|
|
162
|
+
disabledSet.delete(c);
|
|
163
|
+
const nextDisabled = [...disabledSet];
|
|
164
|
+
const nextCfg = { ...cfg };
|
|
165
|
+
if (nextDisabled.length > 0)
|
|
166
|
+
nextCfg.disabledCommands = nextDisabled;
|
|
167
|
+
else
|
|
168
|
+
delete nextCfg.disabledCommands;
|
|
169
|
+
upsertBrand(nextCfg);
|
|
170
|
+
// Resource toggles → the brand's profile preset.
|
|
171
|
+
const resourceOps = [];
|
|
172
|
+
for (const p of options.disablePlugin ?? [])
|
|
173
|
+
resourceOps.push(['plugins', p, false]);
|
|
174
|
+
for (const p of options.enablePlugin ?? [])
|
|
175
|
+
resourceOps.push(['plugins', p, true]);
|
|
176
|
+
for (const s of options.disableSkill ?? [])
|
|
177
|
+
resourceOps.push(['skills', s, false]);
|
|
178
|
+
for (const s of options.enableSkill ?? [])
|
|
179
|
+
resourceOps.push(['skills', s, true]);
|
|
180
|
+
if (resourceOps.length > 0) {
|
|
181
|
+
ensurePresetExists(name);
|
|
182
|
+
editPreset(name, (preset) => {
|
|
183
|
+
for (const [kind, n, enable] of resourceOps)
|
|
184
|
+
applyResourceToggle(preset, kind, n, enable);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
console.log(`${chalk.green('Updated')} ${chalk.bold(name)}.`);
|
|
188
|
+
const finalCfg = getBrandConfig(name);
|
|
189
|
+
const off = finalCfg.disabledCommands?.length ? finalCfg.disabledCommands.join(', ') : '(none)';
|
|
190
|
+
console.log(chalk.dim(` disabled commands: ${off}`));
|
|
191
|
+
});
|
|
192
|
+
cmd
|
|
193
|
+
.command('remove <name>')
|
|
194
|
+
.alias('rm')
|
|
195
|
+
.description('Remove a brand (its shim + config)')
|
|
196
|
+
.option('--purge', "Also delete the brand's resource profile preset")
|
|
197
|
+
.action((name, options) => {
|
|
198
|
+
const existed = getBrandConfig(name) !== undefined;
|
|
199
|
+
const shimRemoved = removeBrandShim(name);
|
|
200
|
+
if (!existed && !shimRemoved) {
|
|
201
|
+
console.error(chalk.red(`No brand named "${name}".`));
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
removeBrand(name, options.purge === true);
|
|
205
|
+
console.log(`${chalk.yellow('Removed')} brand ${chalk.bold(name)}`);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
@@ -23,6 +23,12 @@ import { machineId, normalizeHost } from '../lib/machine-id.js';
|
|
|
23
23
|
import { loadDevices } from '../lib/devices/registry.js';
|
|
24
24
|
import { setHelpSections } from '../lib/help.js';
|
|
25
25
|
import { isInteractiveTerminal, requireInteractiveSelection } from './utils.js';
|
|
26
|
+
function stdoutJson(payload) {
|
|
27
|
+
process.stdout.write(JSON.stringify(payload) + '\n');
|
|
28
|
+
}
|
|
29
|
+
function stderrLine(message) {
|
|
30
|
+
process.stderr.write(message + '\n');
|
|
31
|
+
}
|
|
26
32
|
/** A one-line human label for what a monitor watches. */
|
|
27
33
|
function sourceLabel(source) {
|
|
28
34
|
switch (source.type) {
|
|
@@ -70,7 +76,7 @@ function ownerLabel(monitor) {
|
|
|
70
76
|
function ensureDaemonRunning() {
|
|
71
77
|
if (isDaemonRunning()) {
|
|
72
78
|
signalDaemonReload();
|
|
73
|
-
|
|
79
|
+
stderrLine(chalk.gray('Daemon reloaded'));
|
|
74
80
|
return;
|
|
75
81
|
}
|
|
76
82
|
const result = startDaemon();
|
|
@@ -79,22 +85,22 @@ function ensureDaemonRunning() {
|
|
|
79
85
|
console.log(chalk.gray('Stop anytime with: agents routines stop'));
|
|
80
86
|
}
|
|
81
87
|
else {
|
|
82
|
-
|
|
88
|
+
stderrLine(chalk.yellow('Could not start the daemon. Start it manually with: agents routines start'));
|
|
83
89
|
}
|
|
84
90
|
}
|
|
85
91
|
/** Validate a single device name against the registered fleet; exit on miss. */
|
|
86
92
|
async function validateDevice(name) {
|
|
87
93
|
const normalized = normalizeHost(name.trim());
|
|
88
94
|
if (!normalized) {
|
|
89
|
-
|
|
95
|
+
stderrLine(chalk.red('device name must be non-empty'));
|
|
90
96
|
process.exit(1);
|
|
91
97
|
}
|
|
92
98
|
const registry = await loadDevices();
|
|
93
99
|
const registered = new Set(Object.keys(registry).map((k) => normalizeHost(k)));
|
|
94
100
|
if (!registered.has(normalized)) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
101
|
+
stderrLine(chalk.red(`Unknown device: ${normalized}`));
|
|
102
|
+
stderrLine(chalk.gray(`Registered: ${[...registered].sort().join(', ') || '(none)'}`));
|
|
103
|
+
stderrLine(chalk.gray('Enroll devices with: agents devices sync'));
|
|
98
104
|
process.exit(1);
|
|
99
105
|
}
|
|
100
106
|
return normalized;
|
|
@@ -126,7 +132,7 @@ function buildSource(options) {
|
|
|
126
132
|
const raw = String(options.on);
|
|
127
133
|
const [src, event] = raw.includes(':') ? raw.split(':', 2) : ['github', raw];
|
|
128
134
|
if (src !== 'github' && src !== 'linear') {
|
|
129
|
-
|
|
135
|
+
stderrLine(chalk.red('--on source must be github or linear'));
|
|
130
136
|
process.exit(1);
|
|
131
137
|
}
|
|
132
138
|
const webhook = { source: src, event };
|
|
@@ -143,11 +149,11 @@ function buildSource(options) {
|
|
|
143
149
|
chosen.push({ type: 'webhook', source: { type: 'webhook', webhook } });
|
|
144
150
|
}
|
|
145
151
|
if (chosen.length === 0) {
|
|
146
|
-
|
|
152
|
+
stderrLine(chalk.red('A source is required: --watch, --poll, --poll-http, --ws, --watch-file, --watch-device, or --on'));
|
|
147
153
|
process.exit(1);
|
|
148
154
|
}
|
|
149
155
|
if (chosen.length > 1) {
|
|
150
|
-
|
|
156
|
+
stderrLine(chalk.red(`Exactly one source is allowed; got ${chosen.map((c) => c.type).join(', ')}`));
|
|
151
157
|
process.exit(1);
|
|
152
158
|
}
|
|
153
159
|
return chosen[0].source;
|
|
@@ -162,7 +168,7 @@ function buildCondition(options) {
|
|
|
162
168
|
if (options.every)
|
|
163
169
|
modes.push('every');
|
|
164
170
|
if (modes.length > 1) {
|
|
165
|
-
|
|
171
|
+
stderrLine(chalk.red('--on-change, --match, and --every are mutually exclusive'));
|
|
166
172
|
process.exit(1);
|
|
167
173
|
}
|
|
168
174
|
const mode = modes[0] ?? (options.match ? 'match' : 'on-change');
|
|
@@ -196,11 +202,11 @@ function buildAction(options) {
|
|
|
196
202
|
if (options.webhookOut)
|
|
197
203
|
chosen.push({ type: 'webhook-out', url: options.webhookOut });
|
|
198
204
|
if (chosen.length === 0) {
|
|
199
|
-
|
|
205
|
+
stderrLine(chalk.red('An action is required: --run <agent> --prompt, --routine, --notify, or --webhook-out'));
|
|
200
206
|
process.exit(1);
|
|
201
207
|
}
|
|
202
208
|
if (chosen.length > 1) {
|
|
203
|
-
|
|
209
|
+
stderrLine(chalk.red(`Exactly one action is allowed; got ${chosen.map((c) => c.type).join(', ')}`));
|
|
204
210
|
process.exit(1);
|
|
205
211
|
}
|
|
206
212
|
return chosen[0];
|
|
@@ -209,7 +215,7 @@ function buildAction(options) {
|
|
|
209
215
|
async function pickMonitor(message, alternatives = []) {
|
|
210
216
|
const monitors = listMonitors();
|
|
211
217
|
if (monitors.length === 0) {
|
|
212
|
-
|
|
218
|
+
stderrLine(chalk.yellow('No monitors configured'));
|
|
213
219
|
return null;
|
|
214
220
|
}
|
|
215
221
|
if (!isInteractiveTerminal()) {
|
|
@@ -227,7 +233,7 @@ async function pickMonitor(message, alternatives = []) {
|
|
|
227
233
|
}
|
|
228
234
|
catch (err) {
|
|
229
235
|
if (err instanceof Error && (err.name === 'ExitPromptError' || err.message.includes('User force closed'))) {
|
|
230
|
-
|
|
236
|
+
stderrLine(chalk.gray('Cancelled'));
|
|
231
237
|
return null;
|
|
232
238
|
}
|
|
233
239
|
throw err;
|
|
@@ -322,16 +328,16 @@ export function registerMonitorsCommands(program) {
|
|
|
322
328
|
parsed = yaml.parse(fs.readFileSync(resolved, 'utf-8'));
|
|
323
329
|
}
|
|
324
330
|
catch (err) {
|
|
325
|
-
|
|
331
|
+
stderrLine(chalk.red(`Invalid YAML: ${err.message}`));
|
|
326
332
|
process.exit(1);
|
|
327
333
|
}
|
|
328
334
|
const name = parsed?.name || path.basename(resolved).replace(/\.ya?ml$/, '');
|
|
329
335
|
const config = { enabled: true, ...parsed, name };
|
|
330
336
|
const errors = validateMonitor(config);
|
|
331
337
|
if (errors.length > 0) {
|
|
332
|
-
|
|
338
|
+
stderrLine(chalk.red('Validation errors:'));
|
|
333
339
|
for (const err of errors)
|
|
334
|
-
|
|
340
|
+
stderrLine(chalk.red(` - ${err}`));
|
|
335
341
|
process.exit(1);
|
|
336
342
|
}
|
|
337
343
|
writeMonitor(config);
|
|
@@ -340,8 +346,8 @@ export function registerMonitorsCommands(program) {
|
|
|
340
346
|
return;
|
|
341
347
|
}
|
|
342
348
|
if (!nameOrPath) {
|
|
343
|
-
|
|
344
|
-
|
|
349
|
+
stderrLine(chalk.red('Monitor name is required'));
|
|
350
|
+
stderrLine(chalk.gray('Usage: agents monitors add <name> --poll "<cmd>" 30s --match fail --run claude --prompt "..."'));
|
|
345
351
|
process.exit(1);
|
|
346
352
|
}
|
|
347
353
|
const source = buildSource(options);
|
|
@@ -357,7 +363,7 @@ export function registerMonitorsCommands(program) {
|
|
|
357
363
|
let device;
|
|
358
364
|
let devices;
|
|
359
365
|
if (options.device && options.devices) {
|
|
360
|
-
|
|
366
|
+
stderrLine(chalk.red('--device (single owner) and --devices (allowlist) are mutually exclusive'));
|
|
361
367
|
process.exit(1);
|
|
362
368
|
}
|
|
363
369
|
if (options.device)
|
|
@@ -371,13 +377,13 @@ export function registerMonitorsCommands(program) {
|
|
|
371
377
|
// --run-on with no owner pin would fire from every daemon → duplicate actions.
|
|
372
378
|
if (options.runOn && !device && !devices) {
|
|
373
379
|
device = machineId();
|
|
374
|
-
|
|
380
|
+
stderrLine(chalk.gray(`--run-on set with no --device/--devices: pinned owner to this machine (${device}).`));
|
|
375
381
|
}
|
|
376
382
|
let rateLimit;
|
|
377
383
|
if (options.rateLimit) {
|
|
378
384
|
const m = String(options.rateLimit).match(/^(\d+)\/(.+)$/);
|
|
379
385
|
if (!m) {
|
|
380
|
-
|
|
386
|
+
stderrLine(chalk.red('--rate-limit must be N/<interval>, e.g. 5/1m'));
|
|
381
387
|
process.exit(1);
|
|
382
388
|
}
|
|
383
389
|
rateLimit = { max: parseInt(m[1], 10), per: m[2] };
|
|
@@ -395,15 +401,15 @@ export function registerMonitorsCommands(program) {
|
|
|
395
401
|
};
|
|
396
402
|
const errors = validateMonitor(config);
|
|
397
403
|
if (errors.length > 0) {
|
|
398
|
-
|
|
404
|
+
stderrLine(chalk.red('Validation errors:'));
|
|
399
405
|
for (const err of errors)
|
|
400
|
-
|
|
406
|
+
stderrLine(chalk.red(` - ${err}`));
|
|
401
407
|
process.exit(1);
|
|
402
408
|
}
|
|
403
409
|
// Coverage lint (Anthropic's "silence is not success"): warn when a --match
|
|
404
410
|
// names only a success-shaped token with no failure branch.
|
|
405
411
|
if (condition.mode === 'match' && condition.match && /^(issued|success|ok|pass(ed)?|done|ready)$/i.test(condition.match)) {
|
|
406
|
-
|
|
412
|
+
stderrLine(chalk.yellow(` Note: --match '${condition.match}' only fires on success — it stays silent if the source breaks or never matches.`));
|
|
407
413
|
}
|
|
408
414
|
writeMonitor(config);
|
|
409
415
|
console.log(chalk.green(`Monitor '${nameOrPath}' added`));
|
|
@@ -432,7 +438,7 @@ export function registerMonitorsCommands(program) {
|
|
|
432
438
|
lastFiredAt: state?.lastFiredAt ?? null,
|
|
433
439
|
};
|
|
434
440
|
});
|
|
435
|
-
|
|
441
|
+
stdoutJson(payload);
|
|
436
442
|
return;
|
|
437
443
|
}
|
|
438
444
|
if (monitors.length === 0) {
|
|
@@ -456,7 +462,8 @@ export function registerMonitorsCommands(program) {
|
|
|
456
462
|
monitorsCmd
|
|
457
463
|
.command('view [name]')
|
|
458
464
|
.description('Show a monitor’s full YAML config plus its current watched-state and recent fires.')
|
|
459
|
-
.
|
|
465
|
+
.option('--json', 'Emit machine-readable JSON')
|
|
466
|
+
.action(async (name, options) => {
|
|
460
467
|
if (!name) {
|
|
461
468
|
name = (await pickMonitor('Select monitor to view', ['agents monitors view <name>'])) ?? undefined;
|
|
462
469
|
if (!name)
|
|
@@ -464,12 +471,24 @@ export function registerMonitorsCommands(program) {
|
|
|
464
471
|
}
|
|
465
472
|
const monitor = readMonitor(name);
|
|
466
473
|
if (!monitor) {
|
|
467
|
-
|
|
474
|
+
stderrLine(chalk.red(`Monitor '${name}' not found`));
|
|
468
475
|
process.exit(1);
|
|
469
476
|
}
|
|
477
|
+
const state = readState(name);
|
|
478
|
+
const recentFires = listFires(name).slice(-5);
|
|
479
|
+
if (options.json) {
|
|
480
|
+
stdoutJson({
|
|
481
|
+
name,
|
|
482
|
+
monitor,
|
|
483
|
+
owner: ownerLabel(monitor),
|
|
484
|
+
runsHere: monitorRunsOnThisDevice(monitor),
|
|
485
|
+
state,
|
|
486
|
+
recentFires,
|
|
487
|
+
});
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
470
490
|
console.log(chalk.bold(`Monitor: ${name}\n`));
|
|
471
491
|
console.log(yaml.stringify(monitor));
|
|
472
|
-
const state = readState(name);
|
|
473
492
|
if (state) {
|
|
474
493
|
console.log(chalk.bold('Watched state'));
|
|
475
494
|
console.log(chalk.gray(` last seen: ${state.lastSeenAt}`));
|
|
@@ -477,10 +496,9 @@ export function registerMonitorsCommands(program) {
|
|
|
477
496
|
console.log(chalk.gray(` last fired: ${state.lastFiredAt}`));
|
|
478
497
|
console.log(chalk.gray(` last value: ${state.lastValue.replace(/\s+/g, ' ').slice(0, 120)}`));
|
|
479
498
|
}
|
|
480
|
-
|
|
481
|
-
if (fires.length > 0) {
|
|
499
|
+
if (recentFires.length > 0) {
|
|
482
500
|
console.log(chalk.bold('\nRecent fires'));
|
|
483
|
-
for (const f of
|
|
501
|
+
for (const f of recentFires) {
|
|
484
502
|
console.log(` ${chalk.gray(f.firedAt)} ${f.action ?? '?'} ${f.ok === false ? chalk.red('failed') : chalk.green('ok')}`);
|
|
485
503
|
}
|
|
486
504
|
}
|
|
@@ -489,7 +507,8 @@ export function registerMonitorsCommands(program) {
|
|
|
489
507
|
monitorsCmd
|
|
490
508
|
.command('test [name]')
|
|
491
509
|
.description('DRY-RUN: evaluate the source once and print the emitted event + whether it would fire. No action is taken.')
|
|
492
|
-
.
|
|
510
|
+
.option('--json', 'Emit machine-readable JSON')
|
|
511
|
+
.action(async (name, options) => {
|
|
493
512
|
if (!name) {
|
|
494
513
|
name = (await pickMonitor('Select monitor to test', ['agents monitors test <name>'])) ?? undefined;
|
|
495
514
|
if (!name)
|
|
@@ -497,12 +516,24 @@ export function registerMonitorsCommands(program) {
|
|
|
497
516
|
}
|
|
498
517
|
const monitor = readMonitor(name);
|
|
499
518
|
if (!monitor) {
|
|
500
|
-
|
|
519
|
+
stderrLine(chalk.red(`Monitor '${name}' not found`));
|
|
501
520
|
process.exit(1);
|
|
502
521
|
}
|
|
522
|
+
const { observation, decision } = await evaluateMonitorOnce(monitor);
|
|
523
|
+
const wouldFire = Boolean(decision?.fire);
|
|
524
|
+
if (options.json) {
|
|
525
|
+
stdoutJson({
|
|
526
|
+
name,
|
|
527
|
+
dryRun: true,
|
|
528
|
+
monitor,
|
|
529
|
+
observation,
|
|
530
|
+
decision,
|
|
531
|
+
wouldFire,
|
|
532
|
+
});
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
503
535
|
console.log(chalk.bold(`Dry-run: ${name}\n`));
|
|
504
536
|
console.log(chalk.gray(` ${sourceLabel(monitor.source)} · [${monitor.condition.mode}] · ${actionLabel(monitor.action)}\n`));
|
|
505
|
-
const { observation, decision } = await evaluateMonitorOnce(monitor);
|
|
506
537
|
if (!observation) {
|
|
507
538
|
console.log(chalk.yellow('No observation — this source is push-only (ws/webhook) or produced nothing this tick.'));
|
|
508
539
|
return;
|
|
@@ -511,7 +542,6 @@ export function registerMonitorsCommands(program) {
|
|
|
511
542
|
console.log(observation.raw.split('\n').slice(0, 20).map((l) => ` ${l}`).join('\n'));
|
|
512
543
|
if (observation.meta)
|
|
513
544
|
console.log(chalk.gray(` meta: ${JSON.stringify(observation.meta)}`));
|
|
514
|
-
const wouldFire = Boolean(decision?.fire);
|
|
515
545
|
console.log('');
|
|
516
546
|
console.log(`Would fire: ${wouldFire ? chalk.green('yes') : chalk.gray('no')}`);
|
|
517
547
|
if (decision?.event) {
|
|
@@ -560,15 +590,15 @@ export function registerMonitorsCommands(program) {
|
|
|
560
590
|
return;
|
|
561
591
|
const errors = validateMonitor(monitor);
|
|
562
592
|
if (errors.length > 0) {
|
|
563
|
-
|
|
593
|
+
stderrLine(chalk.yellow('\nWarning: monitor has validation errors:'));
|
|
564
594
|
for (const err of errors)
|
|
565
|
-
|
|
595
|
+
stderrLine(chalk.yellow(` - ${err}`));
|
|
566
596
|
}
|
|
567
597
|
else {
|
|
568
598
|
console.log(chalk.green(`\nMonitor '${name}' saved`));
|
|
569
599
|
if (isDaemonRunning()) {
|
|
570
600
|
signalDaemonReload();
|
|
571
|
-
|
|
601
|
+
stderrLine(chalk.gray('Daemon reloaded'));
|
|
572
602
|
}
|
|
573
603
|
}
|
|
574
604
|
});
|
|
@@ -587,14 +617,14 @@ export function registerMonitorsCommands(program) {
|
|
|
587
617
|
}
|
|
588
618
|
const run = options.run ? listRuns(name).find((r) => r.runId === options.run) : getLatestRun(name);
|
|
589
619
|
if (!run) {
|
|
590
|
-
|
|
591
|
-
|
|
620
|
+
stderrLine(chalk.yellow(`No action runs found for monitor '${name}'`));
|
|
621
|
+
stderrLine(chalk.gray(' (notify / webhook-out actions have no run log — see: agents monitors runs)'));
|
|
592
622
|
return;
|
|
593
623
|
}
|
|
594
624
|
const logPath = path.join(getRunDir(name, run.runId), 'stdout.log');
|
|
595
625
|
if (options.full) {
|
|
596
626
|
if (!fs.existsSync(logPath)) {
|
|
597
|
-
|
|
627
|
+
stderrLine(chalk.yellow(`Log not found: ${logPath}`));
|
|
598
628
|
return;
|
|
599
629
|
}
|
|
600
630
|
console.log(chalk.gray(`Run: ${run.runId}\n`));
|
|
@@ -628,7 +658,7 @@ export function registerMonitorsCommands(program) {
|
|
|
628
658
|
}
|
|
629
659
|
const fires = listFires(name);
|
|
630
660
|
if (fires.length === 0) {
|
|
631
|
-
|
|
661
|
+
stderrLine(chalk.yellow(`No fires recorded for monitor '${name}'`));
|
|
632
662
|
return;
|
|
633
663
|
}
|
|
634
664
|
console.log(chalk.bold(`Fire history: ${name}\n`));
|
|
@@ -656,7 +686,7 @@ export function registerMonitorsCommands(program) {
|
|
|
656
686
|
signalDaemonReload();
|
|
657
687
|
}
|
|
658
688
|
catch (err) {
|
|
659
|
-
|
|
689
|
+
stderrLine(chalk.red(err.message));
|
|
660
690
|
process.exit(1);
|
|
661
691
|
}
|
|
662
692
|
});
|
|
@@ -676,7 +706,7 @@ export function registerMonitorsCommands(program) {
|
|
|
676
706
|
signalDaemonReload();
|
|
677
707
|
}
|
|
678
708
|
catch (err) {
|
|
679
|
-
|
|
709
|
+
stderrLine(chalk.red(err.message));
|
|
680
710
|
process.exit(1);
|
|
681
711
|
}
|
|
682
712
|
});
|
|
@@ -688,7 +718,7 @@ export function registerMonitorsCommands(program) {
|
|
|
688
718
|
.option('--clear', 'Remove the owner pin so the monitor runs on every device')
|
|
689
719
|
.action(async (name, options) => {
|
|
690
720
|
if (options.set !== undefined && options.clear) {
|
|
691
|
-
|
|
721
|
+
stderrLine(chalk.red('--set and --clear are mutually exclusive'));
|
|
692
722
|
process.exit(1);
|
|
693
723
|
}
|
|
694
724
|
if (!name) {
|
|
@@ -698,7 +728,7 @@ export function registerMonitorsCommands(program) {
|
|
|
698
728
|
}
|
|
699
729
|
const monitor = readMonitor(name);
|
|
700
730
|
if (!monitor) {
|
|
701
|
-
|
|
731
|
+
stderrLine(chalk.red(`Monitor '${name}' not found`));
|
|
702
732
|
process.exit(1);
|
|
703
733
|
}
|
|
704
734
|
if (options.clear) {
|
|
@@ -737,11 +767,11 @@ export function registerMonitorsCommands(program) {
|
|
|
737
767
|
console.log(chalk.green(`Monitor '${name}' removed`));
|
|
738
768
|
if (isDaemonRunning()) {
|
|
739
769
|
signalDaemonReload();
|
|
740
|
-
|
|
770
|
+
stderrLine(chalk.gray('Daemon reloaded'));
|
|
741
771
|
}
|
|
742
772
|
}
|
|
743
773
|
else {
|
|
744
|
-
|
|
774
|
+
stderrLine(chalk.red(`Monitor '${name}' not found`));
|
|
745
775
|
process.exit(1);
|
|
746
776
|
}
|
|
747
777
|
});
|
package/dist/commands/plugins.js
CHANGED
|
@@ -493,6 +493,7 @@ Examples:
|
|
|
493
493
|
// agents plugins install <spec>
|
|
494
494
|
pluginsCmd
|
|
495
495
|
.command('install <spec>')
|
|
496
|
+
.alias('add')
|
|
496
497
|
.description('Install a plugin from a git URL or local path (format: name@source or source)')
|
|
497
498
|
.option('--allow-exec-surfaces', 'Allow installing plugins that ship executable surfaces')
|
|
498
499
|
.addHelpText('after', `
|