From fd9e2d3def4ac2b5b603cf8724c8c2ab5e30d06e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 9 Jan 2026 16:55:47 +0100 Subject: [PATCH] feat: remove provider config in configure --- CHANGELOG.md | 1 + src/commands/configure.ts | 103 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 100 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 713ff04dd..783575b69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -106,6 +106,7 @@ - CLI: centralize lobster palette + apply it to onboarding/config prompts. — thanks @steipete - Gateway/CLI: add `clawdbot gateway --dev/--reset` to auto-create a dev config/workspace with a robot identity (no BOOTSTRAP.md), and reset wipes config/creds/sessions/workspace (subcommand --dev no longer collides with global --dev profile). — thanks @steipete - Configure: stop prompting to open the Control UI (still shown in onboarding). — thanks @steipete +- Configure: add wizard mode to remove a provider config block. — thanks @steipete - Onboarding/TUI: prompt to start TUI (best option) when BOOTSTRAP.md exists and add `tui --message` to auto-send the first prompt. — thanks @steipete - Telegram: suppress grammY getUpdates stack traces; log concise retry message instead. — thanks @steipete - Gateway/CLI: allow dev profile (`clawdbot --dev`) to auto-create the dev config + workspace. — thanks @steipete diff --git a/src/commands/configure.ts b/src/commands/configure.ts index d75a1527e..2ff885478 100644 --- a/src/commands/configure.ts +++ b/src/commands/configure.ts @@ -37,6 +37,7 @@ import { resolveGatewayService } from "../daemon/service.js"; import { buildServiceEnvironment } from "../daemon/service-env.js"; import { ensureControlUiAssetsBuilt } from "../infra/control-ui-assets.js"; import { upsertSharedEnvVar } from "../infra/env-file.js"; +import { listChatProviders } from "../providers/registry.js"; import type { RuntimeEnv } from "../runtime.js"; import { defaultRuntime } from "../runtime.js"; import { @@ -105,6 +106,8 @@ type WizardSection = | "skills" | "health"; +type ProvidersWizardMode = "configure" | "remove"; + type ConfigureWizardParams = { command: "configure" | "update"; sections?: WizardSection[]; @@ -862,6 +865,74 @@ async function maybeInstallDaemon(params: { } } +async function removeProviderConfigWizard( + cfg: ClawdbotConfig, + runtime: RuntimeEnv, +): Promise { + let next = { ...cfg }; + + const listConfiguredProviders = () => + listChatProviders().filter((meta) => { + const value = (next as Record)[meta.id]; + return value !== undefined; + }); + + while (true) { + const configured = listConfiguredProviders(); + if (configured.length === 0) { + note( + [ + "No provider config found in clawdbot.json.", + "Tip: `clawdbot providers status` shows what is configured and enabled.", + ].join("\n"), + "Remove provider", + ); + return next; + } + + const provider = guardCancel( + await select({ + message: "Remove which provider config?", + options: [ + ...configured.map((meta) => ({ + value: meta.id, + label: meta.label, + hint: "Deletes tokens + settings from config (credentials stay on disk)", + })), + { value: "done", label: "Done" }, + ], + }), + runtime, + ) as string; + + if (provider === "done") return next; + + const label = + listChatProviders().find((meta) => meta.id === provider)?.label ?? + provider; + const confirmed = guardCancel( + await confirm({ + message: `Delete ${label} configuration from ${CONFIG_PATH_CLAWDBOT}?`, + initialValue: false, + }), + runtime, + ); + if (!confirmed) continue; + + const clone = { ...next } as Record; + delete clone[provider]; + next = clone as ClawdbotConfig; + + note( + [ + `${label} removed from config.`, + "Note: credentials/sessions on disk are unchanged.", + ].join("\n"), + "Provider removed", + ); + } +} + export async function runConfigureWizard( opts: ConfigureWizardParams, runtime: RuntimeEnv = defaultRuntime, @@ -1051,10 +1122,34 @@ export async function runConfigureWizard( } if (selected.includes("providers")) { - nextConfig = await setupProviders(nextConfig, runtime, prompter, { - allowDisable: true, - allowSignalInstall: true, - }); + const providerMode = guardCancel( + await select({ + message: "Providers", + options: [ + { + value: "configure", + label: "Configure/link", + hint: "Add/update providers; disable unselected accounts", + }, + { + value: "remove", + label: "Remove provider config", + hint: "Delete provider tokens/settings from clawdbot.json", + }, + ], + initialValue: "configure", + }), + runtime, + ) as ProvidersWizardMode; + + if (providerMode === "configure") { + nextConfig = await setupProviders(nextConfig, runtime, prompter, { + allowDisable: true, + allowSignalInstall: true, + }); + } else { + nextConfig = await removeProviderConfigWizard(nextConfig, runtime); + } } if (selected.includes("skills")) {