From 60f559e2178a2ccb1a854050f6834862e4427800 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 21 Mar 2026 21:10:48 -0700 Subject: [PATCH] refactor(doctor): extract matrix sequencing (#52056) --- src/commands/doctor-config-flow.ts | 49 +++----------------- src/commands/doctor/providers/matrix.test.ts | 37 +++++++++++++++ src/commands/doctor/providers/matrix.ts | 46 ++++++++++++++++++ 3 files changed, 90 insertions(+), 42 deletions(-) diff --git a/src/commands/doctor-config-flow.ts b/src/commands/doctor-config-flow.ts index 8f392135fed..082da7786a0 100644 --- a/src/commands/doctor-config-flow.ts +++ b/src/commands/doctor-config-flow.ts @@ -2,19 +2,12 @@ import { formatCliCommand } from "../cli/command-format.js"; import type { OpenClawConfig } from "../config/config.js"; import { CONFIG_PATH } from "../config/config.js"; import { applyPluginAutoEnable } from "../config/plugin-auto-enable.js"; -import { detectLegacyMatrixCrypto } from "../infra/matrix-legacy-crypto.js"; -import { detectLegacyMatrixState } from "../infra/matrix-legacy-state.js"; import { note } from "../terminal/note.js"; import { noteOpencodeProviderOverrides } from "./doctor-config-analysis.js"; import { runDoctorConfigPreflight } from "./doctor-config-preflight.js"; import { normalizeCompatibilityConfigValues } from "./doctor-legacy-config.js"; import type { DoctorOptions } from "./doctor-prompter.js"; -import { - applyMatrixDoctorRepair, - collectMatrixInstallPathWarnings, - formatMatrixLegacyCryptoPreview, - formatMatrixLegacyStatePreview, -} from "./doctor/providers/matrix.js"; +import { runMatrixDoctorSequence } from "./doctor/providers/matrix.js"; import { runDoctorRepairSequence } from "./doctor/repair-sequencing.js"; import { applyLegacyCompatibilityStep, @@ -82,44 +75,16 @@ export async function loadAndMaybeMigrateDoctorConfig(params: { })); } - const matrixLegacyState = detectLegacyMatrixState({ + const matrixSequence = await runMatrixDoctorSequence({ cfg: candidate, env: process.env, + shouldRepair, }); - const matrixLegacyCrypto = detectLegacyMatrixCrypto({ - cfg: candidate, - env: process.env, - }); - if (shouldRepair) { - const matrixRepair = await applyMatrixDoctorRepair({ - cfg: candidate, - env: process.env, - }); - for (const change of matrixRepair.changes) { - note(change, "Doctor changes"); - } - for (const warning of matrixRepair.warnings) { - note(warning, "Doctor warnings"); - } - } else if (matrixLegacyState) { - if ("warning" in matrixLegacyState) { - note(`- ${matrixLegacyState.warning}`, "Doctor warnings"); - } else { - note(formatMatrixLegacyStatePreview(matrixLegacyState), "Doctor warnings"); - } + for (const change of matrixSequence.changeNotes) { + note(change, "Doctor changes"); } - if ( - !shouldRepair && - (matrixLegacyCrypto.warnings.length > 0 || matrixLegacyCrypto.plans.length > 0) - ) { - for (const preview of formatMatrixLegacyCryptoPreview(matrixLegacyCrypto)) { - note(preview, "Doctor warnings"); - } - } - - const matrixInstallWarnings = await collectMatrixInstallPathWarnings(candidate); - if (matrixInstallWarnings.length > 0) { - note(matrixInstallWarnings.join("\n"), "Doctor warnings"); + for (const warning of matrixSequence.warningNotes) { + note(warning, "Doctor warnings"); } const missingDefaultAccountBindingWarnings = diff --git a/src/commands/doctor/providers/matrix.test.ts b/src/commands/doctor/providers/matrix.test.ts index 6606309b72b..8e377112e58 100644 --- a/src/commands/doctor/providers/matrix.test.ts +++ b/src/commands/doctor/providers/matrix.test.ts @@ -7,6 +7,7 @@ import { collectMatrixInstallPathWarnings, formatMatrixLegacyCryptoPreview, formatMatrixLegacyStatePreview, + runMatrixDoctorSequence, } from "./matrix.js"; vi.mock("../../../infra/matrix-migration-snapshot.js", () => ({ @@ -137,4 +138,40 @@ describe("doctor matrix provider helpers", () => { ]); expect(result.warnings).toEqual([]); }); + + it("collects matrix preview and install warnings through the provider sequence", async () => { + const matrixStateModule = await import("../../../infra/matrix-legacy-state.js"); + const matrixCryptoModule = await import("../../../infra/matrix-legacy-crypto.js"); + + const stateSpy = vi.spyOn(matrixStateModule, "detectLegacyMatrixState").mockReturnValue({ + accountId: "default", + legacyStoragePath: "/tmp/legacy-sync.json", + targetStoragePath: "/tmp/new-sync.json", + legacyCryptoPath: "/tmp/legacy-crypto.json", + targetCryptoPath: "/tmp/new-crypto.json", + selectionNote: "Picked the newest account.", + targetRootDir: "/tmp/account-root", + }); + const cryptoSpy = vi.spyOn(matrixCryptoModule, "detectLegacyMatrixCrypto").mockReturnValue({ + warnings: ["matrix warning"], + plans: [], + }); + + try { + const result = await runMatrixDoctorSequence({ + cfg: {}, + env: process.env, + shouldRepair: false, + }); + + expect(result.changeNotes).toEqual([]); + expect(result.warningNotes).toEqual([ + expect.stringContaining("Matrix plugin upgraded in place."), + "- matrix warning", + ]); + } finally { + stateSpy.mockRestore(); + cryptoSpy.mockRestore(); + } + }); }); diff --git a/src/commands/doctor/providers/matrix.ts b/src/commands/doctor/providers/matrix.ts index f9980e336ed..43dfaae1a93 100644 --- a/src/commands/doctor/providers/matrix.ts +++ b/src/commands/doctor/providers/matrix.ts @@ -145,3 +145,49 @@ export async function applyMatrixDoctorRepair(params: { return { changes, warnings }; } + +export async function runMatrixDoctorSequence(params: { + cfg: OpenClawConfig; + env: NodeJS.ProcessEnv; + shouldRepair: boolean; +}): Promise<{ changeNotes: string[]; warningNotes: string[] }> { + const matrixLegacyState = detectLegacyMatrixState({ + cfg: params.cfg, + env: params.env, + }); + const matrixLegacyCrypto = detectLegacyMatrixCrypto({ + cfg: params.cfg, + env: params.env, + }); + const warningNotes: string[] = []; + const changeNotes: string[] = []; + + if (params.shouldRepair) { + const matrixRepair = await applyMatrixDoctorRepair({ + cfg: params.cfg, + env: params.env, + }); + changeNotes.push(...matrixRepair.changes); + warningNotes.push(...matrixRepair.warnings); + } else if (matrixLegacyState) { + if ("warning" in matrixLegacyState) { + warningNotes.push(`- ${matrixLegacyState.warning}`); + } else { + warningNotes.push(formatMatrixLegacyStatePreview(matrixLegacyState)); + } + } + + if ( + !params.shouldRepair && + (matrixLegacyCrypto.warnings.length > 0 || matrixLegacyCrypto.plans.length > 0) + ) { + warningNotes.push(...formatMatrixLegacyCryptoPreview(matrixLegacyCrypto)); + } + + const matrixInstallWarnings = await collectMatrixInstallPathWarnings(params.cfg); + if (matrixInstallWarnings.length > 0) { + warningNotes.push(matrixInstallWarnings.join("\n")); + } + + return { changeNotes, warningNotes }; +}