import type { Command } from "commander"; import { DEFAULT_CHAT_CHANNEL } from "../../channels/registry.js"; import { agentCliCommand } from "../../commands/agent-via-gateway.js"; import { agentsAddCommand, agentsDeleteCommand, agentsListCommand, agentsSetIdentityCommand, } from "../../commands/agents.js"; import { setVerbose } from "../../globals.js"; import { defaultRuntime } from "../../runtime.js"; import { formatDocsLink } from "../../terminal/links.js"; import { theme } from "../../terminal/theme.js"; import { hasExplicitOptions } from "../command-options.js"; import { formatHelpExamples } from "../help-format.js"; import { createDefaultDeps } from "../deps.js"; import { runCommandWithRuntime } from "../cli-utils.js"; import { collectOption } from "./helpers.js"; export function registerAgentCommands(program: Command, args: { agentChannelOptions: string }) { program .command("agent") .description("Run an agent turn via the Gateway (use --local for embedded)") .requiredOption("-m, --message ", "Message body for the agent") .option("-t, --to ", "Recipient number in E.164 used to derive the session key") .option("--session-id ", "Use an explicit session id") .option("--agent ", "Agent id (overrides routing bindings)") .option("--thinking ", "Thinking level: off | minimal | low | medium | high") .option("--verbose ", "Persist agent verbose level for the session") .option( "--channel ", `Delivery channel: ${args.agentChannelOptions} (default: ${DEFAULT_CHAT_CHANNEL})`, ) .option("--reply-to ", "Delivery target override (separate from session routing)") .option("--reply-channel ", "Delivery channel override (separate from routing)") .option("--reply-account ", "Delivery account id override") .option( "--local", "Run the embedded agent locally (requires model provider API keys in your shell)", false, ) .option("--deliver", "Send the agent's reply back to the selected channel", false) .option("--json", "Output result as JSON", false) .option( "--timeout ", "Override agent command timeout (seconds, default 600 or config value)", ) .addHelpText( "after", () => ` ${theme.heading("Examples:")} ${formatHelpExamples([ ['moltbot agent --to +15555550123 --message "status update"', "Start a new session."], ['moltbot agent --agent ops --message "Summarize logs"', "Use a specific agent."], [ 'moltbot agent --session-id 1234 --message "Summarize inbox" --thinking medium', "Target a session with explicit thinking level.", ], [ 'moltbot agent --to +15555550123 --message "Trace logs" --verbose on --json', "Enable verbose logging and JSON output.", ], ['moltbot agent --to +15555550123 --message "Summon reply" --deliver', "Deliver reply."], [ 'moltbot agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports"', "Send reply to a different channel/target.", ], ])} ${theme.muted("Docs:")} ${formatDocsLink("/cli/agent", "docs.molt.bot/cli/agent")}`, ) .action(async (opts) => { const verboseLevel = typeof opts.verbose === "string" ? opts.verbose.toLowerCase() : ""; setVerbose(verboseLevel === "on"); // Build default deps (keeps parity with other commands; future-proofing). const deps = createDefaultDeps(); await runCommandWithRuntime(defaultRuntime, async () => { await agentCliCommand(opts, defaultRuntime, deps); }); }); const agents = program .command("agents") .description("Manage isolated agents (workspaces + auth + routing)") .addHelpText( "after", () => `\n${theme.muted("Docs:")} ${formatDocsLink("/cli/agents", "docs.molt.bot/cli/agents")}\n`, ); agents .command("list") .description("List configured agents") .option("--json", "Output JSON instead of text", false) .option("--bindings", "Include routing bindings", false) .action(async (opts) => { await runCommandWithRuntime(defaultRuntime, async () => { await agentsListCommand( { json: Boolean(opts.json), bindings: Boolean(opts.bindings) }, defaultRuntime, ); }); }); agents .command("add [name]") .description("Add a new isolated agent") .option("--workspace ", "Workspace directory for the new agent") .option("--model ", "Model id for this agent") .option("--agent-dir ", "Agent state directory for this agent") .option("--bind ", "Route channel binding (repeatable)", collectOption, []) .option("--non-interactive", "Disable prompts; requires --workspace", false) .option("--json", "Output JSON summary", false) .action(async (name, opts, command) => { await runCommandWithRuntime(defaultRuntime, async () => { const hasFlags = hasExplicitOptions(command, [ "workspace", "model", "agentDir", "bind", "nonInteractive", ]); await agentsAddCommand( { name: typeof name === "string" ? name : undefined, workspace: opts.workspace as string | undefined, model: opts.model as string | undefined, agentDir: opts.agentDir as string | undefined, bind: Array.isArray(opts.bind) ? (opts.bind as string[]) : undefined, nonInteractive: Boolean(opts.nonInteractive), json: Boolean(opts.json), }, defaultRuntime, { hasFlags }, ); }); }); agents .command("set-identity") .description("Update an agent identity (name/theme/emoji/avatar)") .option("--agent ", "Agent id to update") .option("--workspace ", "Workspace directory used to locate the agent + IDENTITY.md") .option("--identity-file ", "Explicit IDENTITY.md path to read") .option("--from-identity", "Read values from IDENTITY.md", false) .option("--name ", "Identity name") .option("--theme ", "Identity theme") .option("--emoji ", "Identity emoji") .option("--avatar ", "Identity avatar (workspace path, http(s) URL, or data URI)") .option("--json", "Output JSON summary", false) .addHelpText( "after", () => ` ${theme.heading("Examples:")} ${formatHelpExamples([ ['moltbot agents set-identity --agent main --name "Clawd" --emoji "🦞"', "Set name + emoji."], ["moltbot agents set-identity --agent main --avatar avatars/clawd.png", "Set avatar path."], ["moltbot agents set-identity --workspace ~/clawd --from-identity", "Load from IDENTITY.md."], [ "moltbot agents set-identity --identity-file ~/clawd/IDENTITY.md --agent main", "Use a specific IDENTITY.md.", ], ])} `, ) .action(async (opts) => { await runCommandWithRuntime(defaultRuntime, async () => { await agentsSetIdentityCommand( { agent: opts.agent as string | undefined, workspace: opts.workspace as string | undefined, identityFile: opts.identityFile as string | undefined, fromIdentity: Boolean(opts.fromIdentity), name: opts.name as string | undefined, theme: opts.theme as string | undefined, emoji: opts.emoji as string | undefined, avatar: opts.avatar as string | undefined, json: Boolean(opts.json), }, defaultRuntime, ); }); }); agents .command("delete ") .description("Delete an agent and prune workspace/state") .option("--force", "Skip confirmation", false) .option("--json", "Output JSON summary", false) .action(async (id, opts) => { await runCommandWithRuntime(defaultRuntime, async () => { await agentsDeleteCommand( { id: String(id), force: Boolean(opts.force), json: Boolean(opts.json), }, defaultRuntime, ); }); }); agents.action(async () => { await runCommandWithRuntime(defaultRuntime, async () => { await agentsListCommand({}, defaultRuntime); }); }); }