Compare commits
2 Commits
main
...
fix/messag
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c01bfcbc12 | ||
|
|
47110e88c7 |
@ -31,6 +31,7 @@ Docs: https://docs.clawd.bot
|
|||||||
- TUI: keep thinking blocks ordered before content during streaming and isolate per-run assembly. (#1202) — thanks @aaronveklabs.
|
- TUI: keep thinking blocks ordered before content during streaming and isolate per-run assembly. (#1202) — thanks @aaronveklabs.
|
||||||
- TUI: align custom editor initialization with the latest pi-tui API. (#1298) — thanks @sibbl.
|
- TUI: align custom editor initialization with the latest pi-tui API. (#1298) — thanks @sibbl.
|
||||||
- CLI: avoid duplicating --profile/--dev flags when formatting commands.
|
- CLI: avoid duplicating --profile/--dev flags when formatting commands.
|
||||||
|
- CLI: load channel plugins for commands that need registry-backed lookups. (#1338) — thanks @MaudeBot.
|
||||||
- Status: route native `/status` to the active agent so model selection reflects the correct profile. (#1301)
|
- Status: route native `/status` to the active agent so model selection reflects the correct profile. (#1301)
|
||||||
- Exec: prefer bash when fish is default shell, falling back to sh if bash is missing. (#1297) — thanks @ysqander.
|
- Exec: prefer bash when fish is default shell, falling back to sh if bash is missing. (#1297) — thanks @ysqander.
|
||||||
- Exec: merge login-shell PATH for host=gateway exec while keeping daemon PATH minimal. (#1304)
|
- Exec: merge login-shell PATH for host=gateway exec while keeping daemon PATH minimal. (#1304)
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import type { Command } from "commander";
|
import type { Command } from "commander";
|
||||||
import { listChannelPlugins } from "../channels/plugins/index.js";
|
|
||||||
import {
|
import {
|
||||||
channelsAddCommand,
|
channelsAddCommand,
|
||||||
channelsCapabilitiesCommand,
|
channelsCapabilitiesCommand,
|
||||||
@ -13,9 +12,11 @@ import { danger } from "../globals.js";
|
|||||||
import { defaultRuntime } from "../runtime.js";
|
import { defaultRuntime } from "../runtime.js";
|
||||||
import { formatDocsLink } from "../terminal/links.js";
|
import { formatDocsLink } from "../terminal/links.js";
|
||||||
import { theme } from "../terminal/theme.js";
|
import { theme } from "../terminal/theme.js";
|
||||||
|
import { resolveCliChannelOptions } from "./channel-options.js";
|
||||||
import { runChannelLogin, runChannelLogout } from "./channel-auth.js";
|
import { runChannelLogin, runChannelLogout } from "./channel-auth.js";
|
||||||
import { runCommandWithRuntime } from "./cli-utils.js";
|
import { runCommandWithRuntime } from "./cli-utils.js";
|
||||||
import { hasExplicitOptions } from "./command-options.js";
|
import { hasExplicitOptions } from "./command-options.js";
|
||||||
|
import { markCommandRequiresPluginRegistry } from "./program/command-metadata.js";
|
||||||
|
|
||||||
const optionNamesAdd = [
|
const optionNamesAdd = [
|
||||||
"channel",
|
"channel",
|
||||||
@ -58,9 +59,7 @@ function runChannelsCommandWithDanger(action: () => Promise<void>, label: string
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function registerChannelsCli(program: Command) {
|
export function registerChannelsCli(program: Command) {
|
||||||
const channelNames = listChannelPlugins()
|
const channelNames = resolveCliChannelOptions().join("|");
|
||||||
.map((plugin) => plugin.id)
|
|
||||||
.join("|");
|
|
||||||
const channels = program
|
const channels = program
|
||||||
.command("channels")
|
.command("channels")
|
||||||
.description("Manage chat channel accounts")
|
.description("Manage chat channel accounts")
|
||||||
@ -72,6 +71,7 @@ export function registerChannelsCli(program: Command) {
|
|||||||
"docs.clawd.bot/cli/channels",
|
"docs.clawd.bot/cli/channels",
|
||||||
)}\n`,
|
)}\n`,
|
||||||
);
|
);
|
||||||
|
markCommandRequiresPluginRegistry(channels);
|
||||||
|
|
||||||
channels
|
channels
|
||||||
.command("list")
|
.command("list")
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
import { listChannelPlugins } from "../../channels/plugins/index.js";
|
|
||||||
import { parseAbsoluteTimeMs } from "../../cron/parse.js";
|
import { parseAbsoluteTimeMs } from "../../cron/parse.js";
|
||||||
import type { CronJob, CronSchedule } from "../../cron/types.js";
|
import type { CronJob, CronSchedule } from "../../cron/types.js";
|
||||||
import { defaultRuntime } from "../../runtime.js";
|
import { defaultRuntime } from "../../runtime.js";
|
||||||
import { colorize, isRich, theme } from "../../terminal/theme.js";
|
import { colorize, isRich, theme } from "../../terminal/theme.js";
|
||||||
|
import { resolveCliChannelOptions } from "../channel-options.js";
|
||||||
import type { GatewayRpcOpts } from "../gateway-rpc.js";
|
import type { GatewayRpcOpts } from "../gateway-rpc.js";
|
||||||
import { callGatewayFromCli } from "../gateway-rpc.js";
|
import { callGatewayFromCli } from "../gateway-rpc.js";
|
||||||
|
|
||||||
export const getCronChannelOptions = () =>
|
export const getCronChannelOptions = () => ["last", ...resolveCliChannelOptions()].join("|");
|
||||||
["last", ...listChannelPlugins().map((plugin) => plugin.id)].join("|");
|
|
||||||
|
|
||||||
export async function warnIfCronSchedulerDisabled(opts: GatewayRpcOpts) {
|
export async function warnIfCronSchedulerDisabled(opts: GatewayRpcOpts) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { resolveMessageChannelSelection } from "../infra/outbound/channel-select
|
|||||||
import { defaultRuntime } from "../runtime.js";
|
import { defaultRuntime } from "../runtime.js";
|
||||||
import { formatDocsLink } from "../terminal/links.js";
|
import { formatDocsLink } from "../terminal/links.js";
|
||||||
import { theme } from "../terminal/theme.js";
|
import { theme } from "../terminal/theme.js";
|
||||||
|
import { markCommandRequiresPluginRegistry } from "./program/command-metadata.js";
|
||||||
|
|
||||||
function parseLimit(value: unknown): number | null {
|
function parseLimit(value: unknown): number | null {
|
||||||
if (typeof value === "number" && Number.isFinite(value)) {
|
if (typeof value === "number" && Number.isFinite(value)) {
|
||||||
@ -42,6 +43,7 @@ export function registerDirectoryCli(program: Command) {
|
|||||||
.action(() => {
|
.action(() => {
|
||||||
directory.help({ error: true });
|
directory.help({ error: true });
|
||||||
});
|
});
|
||||||
|
markCommandRequiresPluginRegistry(directory);
|
||||||
|
|
||||||
const withChannel = (cmd: Command) =>
|
const withChannel = (cmd: Command) =>
|
||||||
cmd
|
cmd
|
||||||
|
|||||||
@ -34,12 +34,16 @@ vi.mock("../channels/plugins/index.js", () => ({
|
|||||||
normalizeChannelId,
|
normalizeChannelId,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("../config/config.js", () => ({
|
vi.mock("../config/config.js", async (importOriginal) => {
|
||||||
|
const actual = await importOriginal<typeof import("../config/config.js")>();
|
||||||
|
return {
|
||||||
|
...actual,
|
||||||
loadConfig: vi.fn().mockReturnValue({}),
|
loadConfig: vi.fn().mockReturnValue({}),
|
||||||
}));
|
};
|
||||||
|
});
|
||||||
|
|
||||||
describe("pairing cli", () => {
|
describe("pairing cli", () => {
|
||||||
it("evaluates pairing channels when registering the CLI (not at import)", async () => {
|
it("defers pairing channel lookup until command execution", async () => {
|
||||||
listPairingChannels.mockClear();
|
listPairingChannels.mockClear();
|
||||||
|
|
||||||
const { registerPairingCli } = await import("./pairing-cli.js");
|
const { registerPairingCli } = await import("./pairing-cli.js");
|
||||||
@ -49,6 +53,10 @@ describe("pairing cli", () => {
|
|||||||
program.name("test");
|
program.name("test");
|
||||||
registerPairingCli(program);
|
registerPairingCli(program);
|
||||||
|
|
||||||
|
expect(listPairingChannels).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
listChannelPairingRequests.mockResolvedValueOnce([]);
|
||||||
|
await program.parseAsync(["pairing", "list", "telegram"], { from: "user" });
|
||||||
expect(listPairingChannels).toHaveBeenCalledTimes(1);
|
expect(listPairingChannels).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,9 @@ import {
|
|||||||
} from "../pairing/pairing-store.js";
|
} from "../pairing/pairing-store.js";
|
||||||
import { formatDocsLink } from "../terminal/links.js";
|
import { formatDocsLink } from "../terminal/links.js";
|
||||||
import { theme } from "../terminal/theme.js";
|
import { theme } from "../terminal/theme.js";
|
||||||
|
import { resolveCliChannelOptions } from "./channel-options.js";
|
||||||
import { formatCliCommand } from "./command-format.js";
|
import { formatCliCommand } from "./command-format.js";
|
||||||
|
import { markCommandRequiresPluginRegistry } from "./program/command-metadata.js";
|
||||||
|
|
||||||
/** Parse channel, allowing extension channels not in core registry. */
|
/** Parse channel, allowing extension channels not in core registry. */
|
||||||
function parseChannel(raw: unknown, channels: PairingChannel[]): PairingChannel {
|
function parseChannel(raw: unknown, channels: PairingChannel[]): PairingChannel {
|
||||||
@ -44,7 +46,9 @@ async function notifyApproved(channel: PairingChannel, id: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function registerPairingCli(program: Command) {
|
export function registerPairingCli(program: Command) {
|
||||||
const channels = listPairingChannels();
|
const channelOptions = resolveCliChannelOptions();
|
||||||
|
const channelHint =
|
||||||
|
channelOptions.length > 0 ? `Channel (${channelOptions.join(", ")})` : "Channel";
|
||||||
const pairing = program
|
const pairing = program
|
||||||
.command("pairing")
|
.command("pairing")
|
||||||
.description("Secure DM pairing (approve inbound requests)")
|
.description("Secure DM pairing (approve inbound requests)")
|
||||||
@ -53,14 +57,16 @@ export function registerPairingCli(program: Command) {
|
|||||||
() =>
|
() =>
|
||||||
`\n${theme.muted("Docs:")} ${formatDocsLink("/cli/pairing", "docs.clawd.bot/cli/pairing")}\n`,
|
`\n${theme.muted("Docs:")} ${formatDocsLink("/cli/pairing", "docs.clawd.bot/cli/pairing")}\n`,
|
||||||
);
|
);
|
||||||
|
markCommandRequiresPluginRegistry(pairing);
|
||||||
|
|
||||||
pairing
|
pairing
|
||||||
.command("list")
|
.command("list")
|
||||||
.description("List pending pairing requests")
|
.description("List pending pairing requests")
|
||||||
.option("--channel <channel>", `Channel (${channels.join(", ")})`)
|
.option("--channel <channel>", channelHint)
|
||||||
.argument("[channel]", `Channel (${channels.join(", ")})`)
|
.argument("[channel]", channelHint)
|
||||||
.option("--json", "Print JSON", false)
|
.option("--json", "Print JSON", false)
|
||||||
.action(async (channelArg, opts) => {
|
.action(async (channelArg, opts) => {
|
||||||
|
const channels = listPairingChannels();
|
||||||
const channelRaw = opts.channel ?? channelArg;
|
const channelRaw = opts.channel ?? channelArg;
|
||||||
if (!channelRaw) {
|
if (!channelRaw) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@ -87,11 +93,12 @@ export function registerPairingCli(program: Command) {
|
|||||||
pairing
|
pairing
|
||||||
.command("approve")
|
.command("approve")
|
||||||
.description("Approve a pairing code and allow that sender")
|
.description("Approve a pairing code and allow that sender")
|
||||||
.option("--channel <channel>", `Channel (${channels.join(", ")})`)
|
.option("--channel <channel>", channelHint)
|
||||||
.argument("<codeOrChannel>", "Pairing code (or channel when using 2 args)")
|
.argument("<codeOrChannel>", "Pairing code (or channel when using 2 args)")
|
||||||
.argument("[code]", "Pairing code (when channel is passed as the 1st arg)")
|
.argument("[code]", "Pairing code (when channel is passed as the 1st arg)")
|
||||||
.option("--notify", "Notify the requester on the same channel", false)
|
.option("--notify", "Notify the requester on the same channel", false)
|
||||||
.action(async (codeOrChannel, code, opts) => {
|
.action(async (codeOrChannel, code, opts) => {
|
||||||
|
const channels = listPairingChannels();
|
||||||
const channelRaw = opts.channel ?? codeOrChannel;
|
const channelRaw = opts.channel ?? codeOrChannel;
|
||||||
const resolvedCode = opts.channel ? codeOrChannel : code;
|
const resolvedCode = opts.channel ? codeOrChannel : code;
|
||||||
if (!opts.channel && !code) {
|
if (!opts.channel && !code) {
|
||||||
|
|||||||
24
src/cli/program/command-metadata.test.ts
Normal file
24
src/cli/program/command-metadata.test.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { Command } from "commander";
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import {
|
||||||
|
commandRequiresPluginRegistry,
|
||||||
|
markCommandRequiresPluginRegistry,
|
||||||
|
} from "./command-metadata.js";
|
||||||
|
|
||||||
|
describe("commandRequiresPluginRegistry", () => {
|
||||||
|
it("detects direct requirement", () => {
|
||||||
|
const program = new Command();
|
||||||
|
const cmd = program.command("message");
|
||||||
|
markCommandRequiresPluginRegistry(cmd);
|
||||||
|
expect(commandRequiresPluginRegistry(cmd)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("walks parent chain", () => {
|
||||||
|
const program = new Command();
|
||||||
|
const parent = program.command("channels");
|
||||||
|
const child = parent.command("list");
|
||||||
|
markCommandRequiresPluginRegistry(parent);
|
||||||
|
expect(commandRequiresPluginRegistry(child)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
21
src/cli/program/command-metadata.ts
Normal file
21
src/cli/program/command-metadata.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import type { Command } from "commander";
|
||||||
|
|
||||||
|
const REQUIRES_PLUGIN_REGISTRY = Symbol.for("clawdbot.requiresPluginRegistry");
|
||||||
|
|
||||||
|
type CommandWithPluginRequirement = Command & {
|
||||||
|
[REQUIRES_PLUGIN_REGISTRY]?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function markCommandRequiresPluginRegistry(command: Command): Command {
|
||||||
|
(command as CommandWithPluginRequirement)[REQUIRES_PLUGIN_REGISTRY] = true;
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function commandRequiresPluginRegistry(command?: Command | null): boolean {
|
||||||
|
let current: Command | null | undefined = command;
|
||||||
|
while (current) {
|
||||||
|
if ((current as CommandWithPluginRequirement)[REQUIRES_PLUGIN_REGISTRY]) return true;
|
||||||
|
current = current.parent ?? undefined;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@ -86,6 +86,7 @@ const routeSessions: RouteSpec = {
|
|||||||
|
|
||||||
const routeAgentsList: RouteSpec = {
|
const routeAgentsList: RouteSpec = {
|
||||||
match: (path) => path[0] === "agents" && path[1] === "list",
|
match: (path) => path[0] === "agents" && path[1] === "list",
|
||||||
|
loadPlugins: true,
|
||||||
run: async (argv) => {
|
run: async (argv) => {
|
||||||
const json = hasFlag(argv, "--json");
|
const json = hasFlag(argv, "--json");
|
||||||
const bindings = hasFlag(argv, "--bindings");
|
const bindings = hasFlag(argv, "--bindings");
|
||||||
|
|||||||
56
src/cli/program/preaction.test.ts
Normal file
56
src/cli/program/preaction.test.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { Command } from "commander";
|
||||||
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
import { markCommandRequiresPluginRegistry } from "./command-metadata.js";
|
||||||
|
|
||||||
|
vi.mock("../plugin-registry.js", () => ({
|
||||||
|
ensurePluginRegistryLoaded: vi.fn(),
|
||||||
|
}));
|
||||||
|
vi.mock("./config-guard.js", () => ({
|
||||||
|
ensureConfigReady: vi.fn(async () => {}),
|
||||||
|
}));
|
||||||
|
vi.mock("../banner.js", () => ({
|
||||||
|
emitCliBanner: vi.fn(),
|
||||||
|
}));
|
||||||
|
vi.mock("../argv.js", () => ({
|
||||||
|
getCommandPath: vi.fn(() => ["message"]),
|
||||||
|
hasHelpOrVersion: vi.fn(() => false),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const loadRegisterPreActionHooks = async () => {
|
||||||
|
const mod = await import("./preaction.js");
|
||||||
|
return mod.registerPreActionHooks;
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadEnsurePluginRegistryLoaded = async () => {
|
||||||
|
const mod = await import("../plugin-registry.js");
|
||||||
|
return mod.ensurePluginRegistryLoaded;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("registerPreActionHooks", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
const ensurePluginRegistryLoaded = await loadEnsurePluginRegistryLoaded();
|
||||||
|
vi.mocked(ensurePluginRegistryLoaded).mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("loads plugins for marked commands", async () => {
|
||||||
|
const registerPreActionHooks = await loadRegisterPreActionHooks();
|
||||||
|
const ensurePluginRegistryLoaded = await loadEnsurePluginRegistryLoaded();
|
||||||
|
const program = new Command();
|
||||||
|
registerPreActionHooks(program, "test");
|
||||||
|
|
||||||
|
const message = program.command("message").action(() => {});
|
||||||
|
markCommandRequiresPluginRegistry(message);
|
||||||
|
|
||||||
|
const originalArgv = process.argv;
|
||||||
|
const argv = ["node", "clawdbot", "message"];
|
||||||
|
process.argv = argv;
|
||||||
|
try {
|
||||||
|
await program.parseAsync(argv);
|
||||||
|
} finally {
|
||||||
|
process.argv = originalArgv;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(vi.mocked(ensurePluginRegistryLoaded)).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -2,6 +2,8 @@ import type { Command } from "commander";
|
|||||||
import { defaultRuntime } from "../../runtime.js";
|
import { defaultRuntime } from "../../runtime.js";
|
||||||
import { emitCliBanner } from "../banner.js";
|
import { emitCliBanner } from "../banner.js";
|
||||||
import { getCommandPath, hasHelpOrVersion } from "../argv.js";
|
import { getCommandPath, hasHelpOrVersion } from "../argv.js";
|
||||||
|
import { ensurePluginRegistryLoaded } from "../plugin-registry.js";
|
||||||
|
import { commandRequiresPluginRegistry } from "./command-metadata.js";
|
||||||
import { ensureConfigReady } from "./config-guard.js";
|
import { ensureConfigReady } from "./config-guard.js";
|
||||||
|
|
||||||
function setProcessTitleForCommand(actionCommand: Command) {
|
function setProcessTitleForCommand(actionCommand: Command) {
|
||||||
@ -20,8 +22,12 @@ export function registerPreActionHooks(program: Command, programVersion: string)
|
|||||||
emitCliBanner(programVersion);
|
emitCliBanner(programVersion);
|
||||||
const argv = process.argv;
|
const argv = process.argv;
|
||||||
if (hasHelpOrVersion(argv)) return;
|
if (hasHelpOrVersion(argv)) return;
|
||||||
|
const needsPlugins = commandRequiresPluginRegistry(actionCommand);
|
||||||
const commandPath = getCommandPath(argv, 2);
|
const commandPath = getCommandPath(argv, 2);
|
||||||
if (commandPath[0] === "doctor") return;
|
if (commandPath[0] === "doctor") return;
|
||||||
await ensureConfigReady({ runtime: defaultRuntime, commandPath });
|
await ensureConfigReady({ runtime: defaultRuntime, commandPath });
|
||||||
|
if (needsPlugins) {
|
||||||
|
ensurePluginRegistryLoaded();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,10 +14,11 @@ import { theme } from "../../terminal/theme.js";
|
|||||||
import { hasExplicitOptions } from "../command-options.js";
|
import { hasExplicitOptions } from "../command-options.js";
|
||||||
import { createDefaultDeps } from "../deps.js";
|
import { createDefaultDeps } from "../deps.js";
|
||||||
import { runCommandWithRuntime } from "../cli-utils.js";
|
import { runCommandWithRuntime } from "../cli-utils.js";
|
||||||
|
import { markCommandRequiresPluginRegistry } from "./command-metadata.js";
|
||||||
import { collectOption } from "./helpers.js";
|
import { collectOption } from "./helpers.js";
|
||||||
|
|
||||||
export function registerAgentCommands(program: Command, args: { agentChannelOptions: string }) {
|
export function registerAgentCommands(program: Command, args: { agentChannelOptions: string }) {
|
||||||
program
|
const agent = program
|
||||||
.command("agent")
|
.command("agent")
|
||||||
.description("Run an agent turn via the Gateway (use --local for embedded)")
|
.description("Run an agent turn via the Gateway (use --local for embedded)")
|
||||||
.requiredOption("-m, --message <text>", "Message body for the agent")
|
.requiredOption("-m, --message <text>", "Message body for the agent")
|
||||||
@ -67,6 +68,7 @@ ${theme.muted("Docs:")} ${formatDocsLink("/cli/agent", "docs.clawd.bot/cli/agent
|
|||||||
await agentCliCommand(opts, defaultRuntime, deps);
|
await agentCliCommand(opts, defaultRuntime, deps);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
markCommandRequiresPluginRegistry(agent);
|
||||||
|
|
||||||
const agents = program
|
const agents = program
|
||||||
.command("agents")
|
.command("agents")
|
||||||
@ -76,6 +78,7 @@ ${theme.muted("Docs:")} ${formatDocsLink("/cli/agent", "docs.clawd.bot/cli/agent
|
|||||||
() =>
|
() =>
|
||||||
`\n${theme.muted("Docs:")} ${formatDocsLink("/cli/agents", "docs.clawd.bot/cli/agents")}\n`,
|
`\n${theme.muted("Docs:")} ${formatDocsLink("/cli/agents", "docs.clawd.bot/cli/agents")}\n`,
|
||||||
);
|
);
|
||||||
|
markCommandRequiresPluginRegistry(agents);
|
||||||
|
|
||||||
agents
|
agents
|
||||||
.command("list")
|
.command("list")
|
||||||
|
|||||||
@ -8,9 +8,10 @@ import { defaultRuntime } from "../../runtime.js";
|
|||||||
import { formatDocsLink } from "../../terminal/links.js";
|
import { formatDocsLink } from "../../terminal/links.js";
|
||||||
import { theme } from "../../terminal/theme.js";
|
import { theme } from "../../terminal/theme.js";
|
||||||
import { runCommandWithRuntime } from "../cli-utils.js";
|
import { runCommandWithRuntime } from "../cli-utils.js";
|
||||||
|
import { markCommandRequiresPluginRegistry } from "./command-metadata.js";
|
||||||
|
|
||||||
export function registerConfigureCommand(program: Command) {
|
export function registerConfigureCommand(program: Command) {
|
||||||
program
|
const configure = program
|
||||||
.command("configure")
|
.command("configure")
|
||||||
.description("Interactive prompt to set up credentials, devices, and agent defaults")
|
.description("Interactive prompt to set up credentials, devices, and agent defaults")
|
||||||
.addHelpText(
|
.addHelpText(
|
||||||
@ -48,4 +49,5 @@ export function registerConfigureCommand(program: Command) {
|
|||||||
await configureCommandWithSections(sections as never, defaultRuntime);
|
await configureCommandWithSections(sections as never, defaultRuntime);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
markCommandRequiresPluginRegistry(configure);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import type { Command } from "commander";
|
|||||||
import { formatDocsLink } from "../../terminal/links.js";
|
import { formatDocsLink } from "../../terminal/links.js";
|
||||||
import { theme } from "../../terminal/theme.js";
|
import { theme } from "../../terminal/theme.js";
|
||||||
import type { ProgramContext } from "./context.js";
|
import type { ProgramContext } from "./context.js";
|
||||||
|
import { markCommandRequiresPluginRegistry } from "./command-metadata.js";
|
||||||
import { createMessageCliHelpers } from "./message/helpers.js";
|
import { createMessageCliHelpers } from "./message/helpers.js";
|
||||||
import { registerMessageDiscordAdminCommands } from "./message/register.discord-admin.js";
|
import { registerMessageDiscordAdminCommands } from "./message/register.discord-admin.js";
|
||||||
import {
|
import {
|
||||||
@ -39,6 +40,7 @@ ${theme.muted("Docs:")} ${formatDocsLink("/cli/message", "docs.clawd.bot/cli/mes
|
|||||||
.action(() => {
|
.action(() => {
|
||||||
message.help({ error: true });
|
message.help({ error: true });
|
||||||
});
|
});
|
||||||
|
markCommandRequiresPluginRegistry(message);
|
||||||
|
|
||||||
const helpers = createMessageCliHelpers(message, ctx.messageChannelOptions);
|
const helpers = createMessageCliHelpers(message, ctx.messageChannelOptions);
|
||||||
registerMessageSendCommand(message, helpers);
|
registerMessageSendCommand(message, helpers);
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import { defaultRuntime } from "../../runtime.js";
|
|||||||
import { formatDocsLink } from "../../terminal/links.js";
|
import { formatDocsLink } from "../../terminal/links.js";
|
||||||
import { theme } from "../../terminal/theme.js";
|
import { theme } from "../../terminal/theme.js";
|
||||||
import { runCommandWithRuntime } from "../cli-utils.js";
|
import { runCommandWithRuntime } from "../cli-utils.js";
|
||||||
|
import { markCommandRequiresPluginRegistry } from "./command-metadata.js";
|
||||||
|
|
||||||
function resolveInstallDaemonFlag(
|
function resolveInstallDaemonFlag(
|
||||||
command: unknown,
|
command: unknown,
|
||||||
@ -32,7 +33,7 @@ function resolveInstallDaemonFlag(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function registerOnboardCommand(program: Command) {
|
export function registerOnboardCommand(program: Command) {
|
||||||
program
|
const onboard = program
|
||||||
.command("onboard")
|
.command("onboard")
|
||||||
.description("Interactive wizard to set up the gateway, workspace, and skills")
|
.description("Interactive wizard to set up the gateway, workspace, and skills")
|
||||||
.addHelpText(
|
.addHelpText(
|
||||||
@ -150,4 +151,5 @@ export function registerOnboardCommand(program: Command) {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
markCommandRequiresPluginRegistry(onboard);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { defaultRuntime } from "../../runtime.js";
|
|||||||
import { formatDocsLink } from "../../terminal/links.js";
|
import { formatDocsLink } from "../../terminal/links.js";
|
||||||
import { theme } from "../../terminal/theme.js";
|
import { theme } from "../../terminal/theme.js";
|
||||||
import { runCommandWithRuntime } from "../cli-utils.js";
|
import { runCommandWithRuntime } from "../cli-utils.js";
|
||||||
|
import { markCommandRequiresPluginRegistry } from "./command-metadata.js";
|
||||||
import { parsePositiveIntOrUndefined } from "./helpers.js";
|
import { parsePositiveIntOrUndefined } from "./helpers.js";
|
||||||
|
|
||||||
function resolveVerbose(opts: { verbose?: boolean; debug?: boolean }): boolean {
|
function resolveVerbose(opts: { verbose?: boolean; debug?: boolean }): boolean {
|
||||||
@ -24,7 +25,7 @@ function parseTimeoutMs(timeout: unknown): number | null | undefined {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function registerStatusHealthSessionsCommands(program: Command) {
|
export function registerStatusHealthSessionsCommands(program: Command) {
|
||||||
program
|
const status = program
|
||||||
.command("status")
|
.command("status")
|
||||||
.description("Show channel health and recent session recipients")
|
.description("Show channel health and recent session recipients")
|
||||||
.option("--json", "Output JSON instead of text", false)
|
.option("--json", "Output JSON instead of text", false)
|
||||||
@ -72,8 +73,9 @@ Examples:
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
markCommandRequiresPluginRegistry(status);
|
||||||
|
|
||||||
program
|
const health = program
|
||||||
.command("health")
|
.command("health")
|
||||||
.description("Fetch health from the running gateway")
|
.description("Fetch health from the running gateway")
|
||||||
.option("--json", "Output JSON instead of text", false)
|
.option("--json", "Output JSON instead of text", false)
|
||||||
@ -103,6 +105,7 @@ Examples:
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
markCommandRequiresPluginRegistry(health);
|
||||||
|
|
||||||
program
|
program
|
||||||
.command("sessions")
|
.command("sessions")
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { sandboxExplainCommand } from "../commands/sandbox-explain.js";
|
|||||||
import { defaultRuntime } from "../runtime.js";
|
import { defaultRuntime } from "../runtime.js";
|
||||||
import { formatDocsLink } from "../terminal/links.js";
|
import { formatDocsLink } from "../terminal/links.js";
|
||||||
import { theme } from "../terminal/theme.js";
|
import { theme } from "../terminal/theme.js";
|
||||||
|
import { markCommandRequiresPluginRegistry } from "./program/command-metadata.js";
|
||||||
|
|
||||||
// --- Types ---
|
// --- Types ---
|
||||||
|
|
||||||
@ -142,7 +143,7 @@ export function registerSandboxCli(program: Command) {
|
|||||||
|
|
||||||
// --- Explain Command ---
|
// --- Explain Command ---
|
||||||
|
|
||||||
sandbox
|
const explain = sandbox
|
||||||
.command("explain")
|
.command("explain")
|
||||||
.description("Explain effective sandbox/tool policy for a session/agent")
|
.description("Explain effective sandbox/tool policy for a session/agent")
|
||||||
.option("--session <key>", "Session key to inspect (defaults to agent main)")
|
.option("--session <key>", "Session key to inspect (defaults to agent main)")
|
||||||
@ -161,4 +162,5 @@ export function registerSandboxCli(program: Command) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
markCommandRequiresPluginRegistry(explain);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { fixSecurityFootguns } from "../security/fix.js";
|
|||||||
import { formatDocsLink } from "../terminal/links.js";
|
import { formatDocsLink } from "../terminal/links.js";
|
||||||
import { isRich, theme } from "../terminal/theme.js";
|
import { isRich, theme } from "../terminal/theme.js";
|
||||||
import { formatCliCommand } from "./command-format.js";
|
import { formatCliCommand } from "./command-format.js";
|
||||||
|
import { markCommandRequiresPluginRegistry } from "./program/command-metadata.js";
|
||||||
|
|
||||||
type SecurityAuditOptions = {
|
type SecurityAuditOptions = {
|
||||||
json?: boolean;
|
json?: boolean;
|
||||||
@ -36,6 +37,7 @@ export function registerSecurityCli(program: Command) {
|
|||||||
() =>
|
() =>
|
||||||
`\n${theme.muted("Docs:")} ${formatDocsLink("/cli/security", "docs.clawd.bot/cli/security")}\n`,
|
`\n${theme.muted("Docs:")} ${formatDocsLink("/cli/security", "docs.clawd.bot/cli/security")}\n`,
|
||||||
);
|
);
|
||||||
|
markCommandRequiresPluginRegistry(security);
|
||||||
|
|
||||||
security
|
security
|
||||||
.command("audit")
|
.command("audit")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user