import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../config/config.js"; import {
resolveStorePath,
resolveSessionTranscriptsDirForAgent,
} from "../config/sessions/paths.js"; import { noteStateIntegrity } from "./doctor-state-integrity.js";
it("does not prompt for oauth dir when no whatsapp/pairing config is active", async () => { const cfg: OpenClawConfig = {}; const confirmRuntimeRepair = await runStateIntegrity(cfg);
expect(confirmRuntimeRepair).not.toHaveBeenCalledWith(OAUTH_PROMPT_MATCHER); const text = stateIntegrityText();
expect(text).toContain("OAuth dir not present");
expect(text).not.toContain("CRITICAL: OAuth dir missing");
});
it("does not prompt for oauth dir when whatsapp is configured without persisted auth state", async () => { const cfg: OpenClawConfig = {
channels: {
whatsapp: {},
},
}; const confirmRuntimeRepair = await runStateIntegrity(cfg);
expect(confirmRuntimeRepair).not.toHaveBeenCalledWith(OAUTH_PROMPT_MATCHER);
expect(stateIntegrityText()).toContain("OAuth dir not present");
expect(stateIntegrityText()).not.toContain("CRITICAL: OAuth dir missing");
});
it("prompts for oauth dir when a channel dmPolicy is pairing", async () => { const cfg: OpenClawConfig = {
channels: {
telegram: {
dmPolicy: "pairing",
},
},
}; const confirmRuntimeRepair = await runStateIntegrity(cfg);
expect(confirmRuntimeRepair).toHaveBeenCalledWith(OAUTH_PROMPT_MATCHER);
});
it("prompts for oauth dir when OPENCLAW_OAUTH_DIR is explicitly configured", async () => {
process.env.OPENCLAW_OAUTH_DIR = path.join(tempHome, ".oauth"); const cfg: OpenClawConfig = {}; const confirmRuntimeRepair = await runStateIntegrity(cfg);
expect(confirmRuntimeRepair).toHaveBeenCalledWith(OAUTH_PROMPT_MATCHER);
expect(stateIntegrityText()).toContain("CRITICAL: OAuth dir missing");
});
it("warns about orphaned on-disk agent directories missing from agents.list", async () => {
createAgentDir("big-brain");
createAgentDir("cerebro");
expect(text).toContain("without a matching agents.list entry");
expect(text).toContain("Examples: big-brain, cerebro");
expect(text).toContain("config-driven routing, identity, and model selection will ignore them");
});
it("detects orphaned agent dirs even when the on-disk folder casing differs", async () => {
createAgentDir("Research");
expect(text).toContain("without a matching agents.list entry");
expect(text).toContain("Examples: Research (id research)");
} finally {
realpathSpy.mockRestore();
}
});
it("does not warn when a case-mismatched dir resolves to the configured agent path", async () => {
createAgentDir("Research");
it("detects orphan transcripts and offers archival remediation", async () => { const cfg: OpenClawConfig = {};
setupSessionState(cfg, process.env, process.env.HOME ?? ""); const sessionsDir = resolveSessionTranscriptsDirForAgent("main", process.env, () => tempHome);
fs.writeFileSync(path.join(sessionsDir, "orphan-session.jsonl"), '{"type":"session"}\n'); const confirmRuntimeRepair = vi.fn(async (params: { message: string }) =>
params.message.includes("This only renames them to *.deleted.<timestamp>."),
);
await noteStateIntegrity(cfg, { confirmRuntimeRepair, note: noteMock });
expect(stateIntegrityText()).toContain( "These .jsonl files are no longer referenced by sessions.json",
);
expect(stateIntegrityText()).toContain("Examples: orphan-session.jsonl");
expect(confirmRuntimeRepair).toHaveBeenCalledWith(
expect.objectContaining({
message: expect.stringContaining("This only renames them to *.deleted.<timestamp>."),
}),
); const files = fs.readdirSync(sessionsDir);
expect(files.some((name) => name.startsWith("orphan-session.jsonl.deleted."))).toBe(true);
});
it("suppresses orphan transcript warnings when QMD sessions are enabled", async () => { const confirmRuntimeRepair = await runOrphanTranscriptCheckWithQmdSessions(true, tempHome);
expect(stateIntegrityText()).not.toContain( "These .jsonl files are no longer referenced by sessions.json",
);
expect(confirmRuntimeRepair).not.toHaveBeenCalled();
});
it("still detects orphan transcripts when QMD sessions are disabled", async () => { const confirmRuntimeRepair = await runOrphanTranscriptCheckWithQmdSessions(false, tempHome);
expect(stateIntegrityText()).toContain( "These .jsonl files are no longer referenced by sessions.json",
);
expect(confirmRuntimeRepair).toHaveBeenCalled();
});
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.