mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 10:30:44 +00:00
perf(test): split doctor preflight mock modes
This commit is contained in:
@@ -4,6 +4,7 @@ type DoctorConfigTestInput = {
|
||||
config: Record<string, unknown>;
|
||||
exists: boolean;
|
||||
path: string;
|
||||
preflightMode: "fast" | "issues" | "compat";
|
||||
};
|
||||
|
||||
function setDoctorConfigInputForTest(input: DoctorConfigTestInput | null): void {
|
||||
@@ -24,18 +25,125 @@ export function getDoctorConfigInputForTest(): DoctorConfigTestInput | null {
|
||||
return globalState[DOCTOR_CONFIG_TEST_INPUT] ?? null;
|
||||
}
|
||||
|
||||
function shouldUseCompatPreflight(path: ReadonlyArray<string>, value: unknown): boolean {
|
||||
if (path.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const joined = path.join(".");
|
||||
const last = path[path.length - 1];
|
||||
if (
|
||||
joined === "heartbeat" ||
|
||||
joined === "memorySearch" ||
|
||||
joined === "gateway.bind" ||
|
||||
joined === "hooks.internal.handlers"
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
joined === "channels.telegram.groupMentionsOnly" ||
|
||||
joined === "agents.defaults.sandbox.perSession"
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (path.length >= 4 && path[0] === "agents" && path[1] === "list" && last === "perSession") {
|
||||
return true;
|
||||
}
|
||||
if (last === "ttlHours" && path[path.length - 2] === "threadBindings") {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
last === "allow" &&
|
||||
typeof value === "boolean" &&
|
||||
((path.length === 5 &&
|
||||
path[0] === "channels" &&
|
||||
path[1] === "slack" &&
|
||||
path[2] === "channels") ||
|
||||
(path.length === 5 &&
|
||||
path[0] === "channels" &&
|
||||
path[1] === "googlechat" &&
|
||||
path[2] === "groups") ||
|
||||
(path.length === 7 &&
|
||||
path[0] === "channels" &&
|
||||
path[1] === "discord" &&
|
||||
path[2] === "guilds" &&
|
||||
path[4] === "channels"))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
last === "streamMode" ||
|
||||
last === "chunkMode" ||
|
||||
last === "blockStreaming" ||
|
||||
last === "draftChunk" ||
|
||||
last === "blockStreamingCoalesce" ||
|
||||
last === "nativeStreaming"
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (last === "streaming" && (typeof value === "boolean" || typeof value === "string")) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
joined === "talk.voiceId" ||
|
||||
joined === "talk.voiceAliases" ||
|
||||
joined === "talk.modelId" ||
|
||||
joined === "talk.outputFormat" ||
|
||||
joined === "talk.apiKey"
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function hasCompatPreflightSignals(config: Record<string, unknown>): boolean {
|
||||
const stack: Array<{ path: string[]; value: unknown }> = [{ path: [], value: config }];
|
||||
while (stack.length > 0) {
|
||||
const current = stack.pop();
|
||||
if (!current || !current.value || typeof current.value !== "object") {
|
||||
continue;
|
||||
}
|
||||
if (Array.isArray(current.value)) {
|
||||
for (let index = current.value.length - 1; index >= 0; index -= 1) {
|
||||
stack.push({
|
||||
path: [...current.path, String(index)],
|
||||
value: current.value[index],
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for (const [key, entry] of Object.entries(current.value)) {
|
||||
const nextPath = [...current.path, key];
|
||||
if (shouldUseCompatPreflight(nextPath, entry)) {
|
||||
return true;
|
||||
}
|
||||
if (entry && typeof entry === "object") {
|
||||
stack.push({ path: nextPath, value: entry });
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function runDoctorConfigWithInput<T>(params: {
|
||||
config: Record<string, unknown>;
|
||||
repair?: boolean;
|
||||
preflightMode?: "fast" | "issues" | "compat";
|
||||
run: (args: {
|
||||
options: { nonInteractive: boolean; repair?: boolean };
|
||||
confirm: () => Promise<boolean>;
|
||||
}) => Promise<T>;
|
||||
}) {
|
||||
const inferredPreflightMode = hasCompatPreflightSignals(params.config)
|
||||
? params.repair
|
||||
? "compat"
|
||||
: "issues"
|
||||
: "fast";
|
||||
setDoctorConfigInputForTest({
|
||||
config: structuredClone(params.config),
|
||||
exists: true,
|
||||
path: "/virtual/.openclaw/openclaw.json",
|
||||
preflightMode: params.preflightMode ?? inferredPreflightMode,
|
||||
});
|
||||
try {
|
||||
return await params.run({
|
||||
|
||||
@@ -551,6 +551,43 @@ vi.mock("./doctor-config-preflight.js", async () => {
|
||||
parsed = {};
|
||||
}
|
||||
}
|
||||
if (injected?.preflightMode === "fast") {
|
||||
return {
|
||||
snapshot: {
|
||||
exists,
|
||||
path: configPath,
|
||||
parsed,
|
||||
config: parsed,
|
||||
sourceConfig: parsed,
|
||||
valid: true,
|
||||
warnings: [],
|
||||
legacyIssues: [],
|
||||
},
|
||||
baseConfig: parsed,
|
||||
};
|
||||
}
|
||||
if (injected?.preflightMode === "issues") {
|
||||
const legacyIssues = findLegacyConfigIssues(
|
||||
parsed,
|
||||
parsed,
|
||||
listPluginDoctorLegacyConfigRules({
|
||||
pluginIds: collectRelevantDoctorPluginIds(parsed),
|
||||
}),
|
||||
);
|
||||
return {
|
||||
snapshot: {
|
||||
exists,
|
||||
path: configPath,
|
||||
parsed,
|
||||
config: parsed,
|
||||
sourceConfig: parsed,
|
||||
valid: legacyIssues.length === 0,
|
||||
warnings: [],
|
||||
legacyIssues,
|
||||
},
|
||||
baseConfig: parsed,
|
||||
};
|
||||
}
|
||||
const legacyIssues = findLegacyConfigIssues(
|
||||
parsed,
|
||||
parsed,
|
||||
|
||||
Reference in New Issue
Block a user