@phnx-labs/agents-cli 1.20.71 → 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 +325 -1
- 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/commands.js +2 -0
- 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 +39 -10
- package/dist/commands/mcp.js +2 -0
- 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/resource-view.d.ts +2 -0
- package/dist/commands/resource-view.js +8 -0
- 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.d.ts +6 -0
- package/dist/commands/sessions.js +26 -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/skills.js +2 -0
- package/dist/commands/ssh.d.ts +9 -0
- package/dist/commands/ssh.js +196 -26
- package/dist/commands/status.js +8 -2
- package/dist/commands/subagents.js +3 -1
- package/dist/commands/sync.js +1 -1
- package/dist/commands/teams.js +11 -2
- package/dist/commands/uninstall.d.ts +11 -0
- package/dist/commands/uninstall.js +158 -0
- package/dist/commands/utils.d.ts +29 -0
- package/dist/commands/utils.js +24 -0
- package/dist/commands/versions.js +120 -11
- package/dist/index.js +83 -12
- 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 +14 -5
- package/dist/lib/daemon.js +52 -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/logs.d.ts +12 -0
- package/dist/lib/hosts/logs.js +18 -0
- 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 +36 -0
- package/dist/lib/shims.js +120 -16
- 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 +7 -1
- package/dist/lib/startup/command-registry.js +19 -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/uninstall.d.ts +84 -0
- package/dist/lib/uninstall.js +347 -0
- package/dist/lib/usage.d.ts +13 -1
- package/dist/lib/usage.js +32 -14
- package/dist/lib/version.d.ts +40 -0
- package/dist/lib/version.js +94 -16
- package/dist/lib/versions.d.ts +27 -0
- package/dist/lib/versions.js +248 -79
- 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
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
import chalk from 'chalk';
|
|
24
24
|
import * as fs from 'fs';
|
|
25
25
|
import { discoverSessions, resolveSessionById } from '../lib/session/discover.js';
|
|
26
|
-
import { parseAgentFilter, renderSessionLog } from './sessions.js';
|
|
26
|
+
import { parseAgentFilter, renderSessionLog, renderSessionLogJson } from './sessions.js';
|
|
27
27
|
import { streamSessionTail, isTailable } from './sessions-tail.js';
|
|
28
|
-
import { showHostTaskLog } from '../lib/hosts/logs.js';
|
|
28
|
+
import { showHostTaskLog, hostTaskLogJson } from '../lib/hosts/logs.js';
|
|
29
29
|
import { listTasks } from '../lib/hosts/tasks.js';
|
|
30
30
|
import { itemPicker } from '../lib/picker.js';
|
|
31
31
|
import { query, stats, getLogsPath, rotate, levelFor, } from '../lib/events.js';
|
|
@@ -43,29 +43,57 @@ function candidateLabel(c) {
|
|
|
43
43
|
const title = s.label || s.topic || '';
|
|
44
44
|
return `${chalk.gray('sess')} ${s.shortId.padEnd(9)} ${(s.agent + ver).padEnd(14)} ${chalk.gray(s.timestamp.slice(0, 16))} ${title.slice(0, 40)}`;
|
|
45
45
|
}
|
|
46
|
+
/** Emit a host-dispatch task's log as JSON: `{ kind, task, log }`. */
|
|
47
|
+
function emitHostTaskJson(id) {
|
|
48
|
+
const hj = hostTaskLogJson(id);
|
|
49
|
+
if (!hj.found)
|
|
50
|
+
return false;
|
|
51
|
+
process.stdout.write(JSON.stringify({ kind: 'task', task: hj.task, log: hj.log ?? null }, null, 2) + '\n');
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
46
54
|
/** Show a resolved session — follow (tail), concise summary, or (`full`) transcript. */
|
|
47
|
-
async function showSession(session, follow, full) {
|
|
55
|
+
async function showSession(session, follow, full, json = false) {
|
|
56
|
+
if (json) {
|
|
57
|
+
await renderSessionLogJson(session);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
48
60
|
if (follow) {
|
|
49
61
|
if (!isTailable(session.agent)) {
|
|
50
62
|
console.error(chalk.red(`Tailing is supported for claude and codex sessions only (got ${session.agent}).`));
|
|
51
63
|
process.exit(2);
|
|
52
64
|
}
|
|
53
|
-
await streamSessionTail(session, {});
|
|
65
|
+
await streamSessionTail(session, { raw: full });
|
|
54
66
|
return;
|
|
55
67
|
}
|
|
56
68
|
await renderSessionLog(session, full ? 'markdown' : 'summary');
|
|
57
69
|
}
|
|
58
|
-
async function showCandidate(c, follow, full) {
|
|
70
|
+
async function showCandidate(c, follow, full, json = false) {
|
|
59
71
|
if (c.kind === 'task') {
|
|
72
|
+
if (json) {
|
|
73
|
+
emitHostTaskJson(c.task.id);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
60
76
|
const res = await showHostTaskLog(c.task.id, follow, full);
|
|
61
77
|
if (res.exitCode !== undefined)
|
|
62
78
|
process.exitCode = res.exitCode;
|
|
63
79
|
return;
|
|
64
80
|
}
|
|
65
|
-
await showSession(c.session, follow, full);
|
|
81
|
+
await showSession(c.session, follow, full, json);
|
|
66
82
|
}
|
|
67
83
|
/** Resolve an explicit id/--session: host task first, then a session. */
|
|
68
|
-
async function showById(id, follow, full) {
|
|
84
|
+
async function showById(id, follow, full, json = false) {
|
|
85
|
+
if (json) {
|
|
86
|
+
if (emitHostTaskJson(id))
|
|
87
|
+
return;
|
|
88
|
+
const sessions = await discoverSessions({ all: true, limit: 5000 });
|
|
89
|
+
const matches = resolveSessionById(sessions, id);
|
|
90
|
+
if (matches.length === 0) {
|
|
91
|
+
console.error(chalk.red(`No run or session found matching "${id}".`));
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
await renderSessionLogJson(matches[0]);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
69
97
|
const hostRes = await showHostTaskLog(id, follow, full);
|
|
70
98
|
if (hostRes.found) {
|
|
71
99
|
if (hostRes.exitCode !== undefined)
|
|
@@ -85,7 +113,7 @@ async function runLogs(id, opts) {
|
|
|
85
113
|
const full = !!opts.full;
|
|
86
114
|
const directId = opts.session ?? id;
|
|
87
115
|
if (directId) {
|
|
88
|
-
await showById(directId, follow, full);
|
|
116
|
+
await showById(directId, follow, full, !!opts.json);
|
|
89
117
|
return;
|
|
90
118
|
}
|
|
91
119
|
const { agent, version } = parseAgentFilter(opts.agent);
|
|
@@ -110,7 +138,7 @@ async function runLogs(id, opts) {
|
|
|
110
138
|
process.exit(1);
|
|
111
139
|
}
|
|
112
140
|
if (candidates.length === 1) {
|
|
113
|
-
await showCandidate(candidates[0], follow, full);
|
|
141
|
+
await showCandidate(candidates[0], follow, full, !!opts.json);
|
|
114
142
|
return;
|
|
115
143
|
}
|
|
116
144
|
// Multiple sessions matched → picker if interactive, else a list to pick from.
|
|
@@ -134,7 +162,7 @@ async function runLogs(id, opts) {
|
|
|
134
162
|
});
|
|
135
163
|
if (!picked)
|
|
136
164
|
return;
|
|
137
|
-
await showCandidate(picked.item, follow, full);
|
|
165
|
+
await showCandidate(picked.item, follow, full, !!opts.json);
|
|
138
166
|
}
|
|
139
167
|
function parseSince(s) {
|
|
140
168
|
const m = s.match(/^(\d+)([smhdw])$/);
|
|
@@ -343,6 +371,7 @@ export function registerLogsCommand(program) {
|
|
|
343
371
|
.option('--session <id>', 'Select a session/run by id (same as the positional id)')
|
|
344
372
|
.option('-f, --follow', 'Follow live output')
|
|
345
373
|
.option('-m, --full', 'Show the full raw transcript / stdout instead of the concise summary')
|
|
374
|
+
.option('--json', 'Machine-readable JSON: a host task as { kind, task, log }, a session as the redacted { session, events } (same shape as `sessions <id> --json`)')
|
|
346
375
|
.action((id, opts) => runLogs(id, opts));
|
|
347
376
|
logsCmd
|
|
348
377
|
.command('audit')
|
package/dist/commands/mcp.js
CHANGED
|
@@ -147,6 +147,7 @@ When to use:
|
|
|
147
147
|
.command('list [agent]')
|
|
148
148
|
.description('Show which MCP servers are registered and which agent versions they are synced to')
|
|
149
149
|
.option('-a, --agent <agent>', 'Filter to a specific agent (alternative to positional arg)')
|
|
150
|
+
.option('--json', 'Emit machine-readable JSON instead of the table/picker')
|
|
150
151
|
.action(async (agentArg, options) => {
|
|
151
152
|
const spinner = ora({ text: 'Loading...', isSilent: !process.stdout.isTTY }).start();
|
|
152
153
|
const agentInput = agentArg || options.agent;
|
|
@@ -176,6 +177,7 @@ When to use:
|
|
|
176
177
|
centralPath: getMcpDir(),
|
|
177
178
|
filterAgent,
|
|
178
179
|
filterVersion,
|
|
180
|
+
json: options.json,
|
|
179
181
|
});
|
|
180
182
|
});
|
|
181
183
|
mcpCmd
|
|
@@ -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
|
+
}
|