diff --git a/src/cli/program.test.ts b/src/cli/program.test.ts index 7267f08ed..b916e77d1 100644 --- a/src/cli/program.test.ts +++ b/src/cli/program.test.ts @@ -4,6 +4,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; const messageCommand = vi.fn(); const statusCommand = vi.fn(); const configureCommand = vi.fn(); +const configureCommandWithSections = vi.fn(); const setupCommand = vi.fn(); const onboardCommand = vi.fn(); const callGateway = vi.fn(); @@ -23,7 +24,19 @@ vi.mock("../commands/message.js", () => ({ messageCommand, })); vi.mock("../commands/status.js", () => ({ statusCommand })); -vi.mock("../commands/configure.js", () => ({ configureCommand })); +vi.mock("../commands/configure.js", () => ({ + CONFIGURE_WIZARD_SECTIONS: [ + "workspace", + "model", + "gateway", + "daemon", + "providers", + "skills", + "health", + ], + configureCommand, + configureCommandWithSections, +})); vi.mock("../commands/setup.js", () => ({ setupCommand })); vi.mock("../commands/onboard.js", () => ({ onboardCommand })); vi.mock("../runtime.js", () => ({ defaultRuntime: runtime })); diff --git a/src/cli/program.ts b/src/cli/program.ts index c056741a7..fa1df59c1 100644 --- a/src/cli/program.ts +++ b/src/cli/program.ts @@ -5,7 +5,11 @@ import { agentsDeleteCommand, agentsListCommand, } from "../commands/agents.js"; -import { configureCommand } from "../commands/configure.js"; +import { + CONFIGURE_WIZARD_SECTIONS, + configureCommand, + configureCommandWithSections, +} from "../commands/configure.js"; import { doctorCommand } from "../commands/doctor.js"; import { healthCommand } from "../commands/health.js"; import { messageCommand } from "../commands/message.js"; @@ -349,9 +353,38 @@ export function buildProgram() { .description( "Interactive wizard to update models, providers, skills, and gateway", ) - .action(async () => { + .option( + "--section ", + `Configure only one section (repeatable). One of: ${CONFIGURE_WIZARD_SECTIONS.join(", ")}`, + (value, previous: string[]) => [...previous, value], + [] as string[], + ) + .action(async (opts) => { try { - await configureCommand(defaultRuntime); + const sections: string[] = Array.isArray(opts.section) + ? opts.section + .map((value: unknown) => + typeof value === "string" ? value.trim() : "", + ) + .filter(Boolean) + : []; + if (sections.length === 0) { + await configureCommand(defaultRuntime); + return; + } + + const invalid = sections.filter( + (s) => !CONFIGURE_WIZARD_SECTIONS.includes(s as never), + ); + if (invalid.length > 0) { + defaultRuntime.error( + `Invalid --section: ${invalid.join(", ")}. Expected one of: ${CONFIGURE_WIZARD_SECTIONS.join(", ")}.`, + ); + defaultRuntime.exit(1); + return; + } + + await configureCommandWithSections(sections as never, defaultRuntime); } catch (err) { defaultRuntime.error(String(err)); defaultRuntime.exit(1); diff --git a/src/commands/configure.ts b/src/commands/configure.ts index a50f6cd4f..4c5660d17 100644 --- a/src/commands/configure.ts +++ b/src/commands/configure.ts @@ -97,14 +97,17 @@ import { } from "./openai-codex-model-default.js"; import { ensureSystemdUserLingerInteractive } from "./systemd-linger.js"; -type WizardSection = - | "model" - | "providers" - | "gateway" - | "daemon" - | "workspace" - | "skills" - | "health"; +export const CONFIGURE_WIZARD_SECTIONS = [ + "workspace", + "model", + "gateway", + "daemon", + "providers", + "skills", + "health", +] as const; + +export type WizardSection = (typeof CONFIGURE_WIZARD_SECTIONS)[number]; type ProvidersWizardMode = "configure" | "remove"; @@ -1304,3 +1307,10 @@ export async function runConfigureWizard( export async function configureCommand(runtime: RuntimeEnv = defaultRuntime) { await runConfigureWizard({ command: "configure" }, runtime); } + +export async function configureCommandWithSections( + sections: WizardSection[], + runtime: RuntimeEnv = defaultRuntime, +) { + await runConfigureWizard({ command: "configure", sections }, runtime); +}