mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:50:42 +00:00
perf(test): cache qa scenario catalog
This commit is contained in:
@@ -230,6 +230,9 @@ const QA_SCENARIO_DIR_PATH = "qa/scenarios";
|
||||
const QA_PACK_FENCE_RE = /```ya?ml qa-pack\r?\n([\s\S]*?)\r?\n```/i;
|
||||
const QA_SCENARIO_FENCE_RE = /```ya?ml qa-scenario\r?\n([\s\S]*?)\r?\n```/i;
|
||||
const QA_FLOW_YAML_FENCE_RE = /```ya?ml qa-flow\r?\n([\s\S]*?)\r?\n```/i;
|
||||
const repoPathCache = new Map<string, string | null>();
|
||||
let qaScenarioMarkdownPathsCache: string[] | null = null;
|
||||
let qaScenarioPackCache: QaScenarioPack | null = null;
|
||||
|
||||
function walkUpDirectories(start: string): string[] {
|
||||
const roots: string[] = [];
|
||||
@@ -245,6 +248,10 @@ function walkUpDirectories(start: string): string[] {
|
||||
}
|
||||
|
||||
function resolveRepoPath(relativePath: string, kind: "file" | "directory" = "file"): string | null {
|
||||
const cacheKey = `${kind}:${relativePath}`;
|
||||
if (repoPathCache.has(cacheKey)) {
|
||||
return repoPathCache.get(cacheKey) ?? null;
|
||||
}
|
||||
for (const dir of walkUpDirectories(import.meta.dirname)) {
|
||||
const candidate = path.join(dir, relativePath);
|
||||
if (!fs.existsSync(candidate)) {
|
||||
@@ -252,9 +259,11 @@ function resolveRepoPath(relativePath: string, kind: "file" | "directory" = "fil
|
||||
}
|
||||
const stat = fs.statSync(candidate);
|
||||
if ((kind === "file" && stat.isFile()) || (kind === "directory" && stat.isDirectory())) {
|
||||
repoPathCache.set(cacheKey, candidate);
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
repoPathCache.set(cacheKey, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -320,17 +329,21 @@ export function readQaScenarioPackMarkdown(): string {
|
||||
}
|
||||
|
||||
export function readQaScenarioPack(): QaScenarioPack {
|
||||
if (qaScenarioPackCache) {
|
||||
return qaScenarioPackCache;
|
||||
}
|
||||
const packMarkdown = readTextFile(QA_SCENARIO_PACK_INDEX_PATH).trim();
|
||||
if (!packMarkdown) {
|
||||
// The QA scenario pack is optional in npm distributions. Return an empty
|
||||
// pack so completion cache updates and other consumers don't crash when
|
||||
// the qa/scenarios/ directory is not shipped with the package.
|
||||
return {
|
||||
qaScenarioPackCache = {
|
||||
version: 1,
|
||||
agent: { identityMarkdown: DEFAULT_QA_AGENT_IDENTITY_MARKDOWN },
|
||||
kickoffTask: "QA scenarios not available in this distribution.",
|
||||
scenarios: [],
|
||||
};
|
||||
return qaScenarioPackCache;
|
||||
}
|
||||
const parsedPack = parseQaYamlWithContext(
|
||||
qaScenarioPackSchema,
|
||||
@@ -368,18 +381,26 @@ export function readQaScenarioPack(): QaScenarioPack {
|
||||
}
|
||||
seenScenarioIds.add(scenario.id);
|
||||
}
|
||||
return {
|
||||
qaScenarioPackCache = {
|
||||
...parsedPack,
|
||||
scenarios,
|
||||
};
|
||||
return qaScenarioPackCache;
|
||||
}
|
||||
|
||||
export function listQaScenarioMarkdownPaths(): string[] {
|
||||
if (qaScenarioMarkdownPathsCache) {
|
||||
return qaScenarioMarkdownPathsCache;
|
||||
}
|
||||
const resolved = resolveRepoPath(QA_SCENARIO_DIR_PATH, "directory");
|
||||
if (!resolved) {
|
||||
return [];
|
||||
}
|
||||
return listQaScenarioMarkdownPathsInDirectory(resolved, QA_SCENARIO_DIR_PATH).toSorted();
|
||||
qaScenarioMarkdownPathsCache = listQaScenarioMarkdownPathsInDirectory(
|
||||
resolved,
|
||||
QA_SCENARIO_DIR_PATH,
|
||||
).toSorted();
|
||||
return qaScenarioMarkdownPathsCache;
|
||||
}
|
||||
|
||||
function listQaScenarioMarkdownPathsInDirectory(
|
||||
|
||||
Reference in New Issue
Block a user