feat: improve doctor update flow
This commit is contained in:
@@ -121,10 +121,14 @@ export async function loadAndMaybeMigrateDoctorConfig(params: {
|
||||
options: DoctorOptions;
|
||||
confirm: (p: { message: string; initialValue: boolean }) => Promise<boolean>;
|
||||
}) {
|
||||
void params.confirm;
|
||||
const shouldRepair = params.options.repair === true || params.options.yes === true;
|
||||
const snapshot = await readConfigFileSnapshot();
|
||||
let cfg: ClawdbotConfig = snapshot.config ?? {};
|
||||
const baseCfg = snapshot.config ?? {};
|
||||
let cfg: ClawdbotConfig = baseCfg;
|
||||
let candidate = structuredClone(baseCfg) as ClawdbotConfig;
|
||||
let pendingChanges = false;
|
||||
let shouldWriteConfig = false;
|
||||
const fixHints: string[] = [];
|
||||
if (snapshot.exists && !snapshot.valid && snapshot.legacyIssues.length === 0) {
|
||||
note("Config invalid; doctor will run with best-effort config.", "Config");
|
||||
}
|
||||
@@ -139,52 +143,76 @@ export async function loadAndMaybeMigrateDoctorConfig(params: {
|
||||
snapshot.legacyIssues.map((issue) => `- ${issue.path}: ${issue.message}`).join("\n"),
|
||||
"Legacy config keys detected",
|
||||
);
|
||||
const { config: migrated, changes } = migrateLegacyConfig(snapshot.parsed);
|
||||
if (changes.length > 0) {
|
||||
note(changes.join("\n"), "Doctor changes");
|
||||
}
|
||||
if (migrated) {
|
||||
candidate = migrated;
|
||||
pendingChanges = pendingChanges || changes.length > 0;
|
||||
}
|
||||
if (shouldRepair) {
|
||||
// Legacy migration (2026-01-02, commit: 16420e5b) — normalize per-provider allowlists; move WhatsApp gating into channels.whatsapp.allowFrom.
|
||||
const { config: migrated, changes } = migrateLegacyConfig(snapshot.parsed);
|
||||
if (changes.length > 0) note(changes.join("\n"), "Doctor changes");
|
||||
if (migrated) cfg = migrated;
|
||||
} else {
|
||||
note(
|
||||
fixHints.push(
|
||||
`Run "${formatCliCommand("clawdbot doctor --fix")}" to apply legacy migrations.`,
|
||||
"Doctor",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const normalized = normalizeLegacyConfigValues(cfg);
|
||||
const normalized = normalizeLegacyConfigValues(candidate);
|
||||
if (normalized.changes.length > 0) {
|
||||
note(normalized.changes.join("\n"), "Doctor changes");
|
||||
candidate = normalized.config;
|
||||
pendingChanges = true;
|
||||
if (shouldRepair) {
|
||||
cfg = normalized.config;
|
||||
} else {
|
||||
note(`Run "${formatCliCommand("clawdbot doctor --fix")}" to apply these changes.`, "Doctor");
|
||||
fixHints.push(`Run "${formatCliCommand("clawdbot doctor --fix")}" to apply these changes.`);
|
||||
}
|
||||
}
|
||||
|
||||
const autoEnable = applyPluginAutoEnable({ config: cfg, env: process.env });
|
||||
const autoEnable = applyPluginAutoEnable({ config: candidate, env: process.env });
|
||||
if (autoEnable.changes.length > 0) {
|
||||
note(autoEnable.changes.join("\n"), "Doctor changes");
|
||||
candidate = autoEnable.config;
|
||||
pendingChanges = true;
|
||||
if (shouldRepair) {
|
||||
cfg = autoEnable.config;
|
||||
} else {
|
||||
note(`Run "${formatCliCommand("clawdbot doctor --fix")}" to apply these changes.`, "Doctor");
|
||||
fixHints.push(`Run "${formatCliCommand("clawdbot doctor --fix")}" to apply these changes.`);
|
||||
}
|
||||
}
|
||||
|
||||
const unknown = stripUnknownConfigKeys(cfg);
|
||||
const unknown = stripUnknownConfigKeys(candidate);
|
||||
if (unknown.removed.length > 0) {
|
||||
const lines = unknown.removed.map((path) => `- ${path}`).join("\n");
|
||||
candidate = unknown.config;
|
||||
pendingChanges = true;
|
||||
if (shouldRepair) {
|
||||
cfg = unknown.config;
|
||||
note(lines, "Doctor changes");
|
||||
} else {
|
||||
note(lines, "Unknown config keys");
|
||||
note('Run "clawdbot doctor --fix" to remove these keys.', "Doctor");
|
||||
fixHints.push('Run "clawdbot doctor --fix" to remove these keys.');
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldRepair && pendingChanges) {
|
||||
const shouldApply = await params.confirm({
|
||||
message: "Apply recommended config repairs now?",
|
||||
initialValue: true,
|
||||
});
|
||||
if (shouldApply) {
|
||||
cfg = candidate;
|
||||
shouldWriteConfig = true;
|
||||
} else if (fixHints.length > 0) {
|
||||
note(fixHints.join("\n"), "Doctor");
|
||||
}
|
||||
}
|
||||
|
||||
noteOpencodeProviderOverrides(cfg);
|
||||
|
||||
return { cfg, path: snapshot.path ?? CONFIG_PATH_CLAWDBOT };
|
||||
return { cfg, path: snapshot.path ?? CONFIG_PATH_CLAWDBOT, shouldWriteConfig };
|
||||
}
|
||||
|
||||
@@ -250,7 +250,8 @@ export async function doctorCommand(
|
||||
healthOk,
|
||||
});
|
||||
|
||||
if (prompter.shouldRepair) {
|
||||
const shouldWriteConfig = prompter.shouldRepair || configResult.shouldWriteConfig;
|
||||
if (shouldWriteConfig) {
|
||||
cfg = applyWizardMetadata(cfg, { command: "doctor", mode: resolveMode(cfg) });
|
||||
await writeConfigFile(cfg);
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
|
||||
Reference in New Issue
Block a user