mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:20:43 +00:00
fix(test): align plugin gauntlet with built runtime
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { existsSync } from "node:fs";
|
||||
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import type { ModelProviderConfig } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
@@ -76,16 +76,20 @@ export function resolveQaBundledPluginSourceDir(params: { repoRoot: string; plug
|
||||
path.join(params.repoRoot, "extensions", params.pluginId),
|
||||
];
|
||||
const existingCandidates = candidates.filter((candidate) => existsSync(candidate));
|
||||
if (existingCandidates.length === 0) {
|
||||
const manifestCandidates = findQaBundledPluginDirsByManifestId(params);
|
||||
const allCandidates = [...existingCandidates, ...manifestCandidates].filter(
|
||||
(candidate, index, all) => all.indexOf(candidate) === index,
|
||||
);
|
||||
if (allCandidates.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const cliMetadataCandidate = existingCandidates.find((candidate) =>
|
||||
const cliMetadataCandidate = allCandidates.find((candidate) =>
|
||||
QA_CLI_METADATA_ENTRY_BASENAMES.some((basename) => existsSync(path.join(candidate, basename))),
|
||||
);
|
||||
if (cliMetadataCandidate) {
|
||||
return cliMetadataCandidate;
|
||||
}
|
||||
return existingCandidates[0] ?? null;
|
||||
return allCandidates[0] ?? null;
|
||||
}
|
||||
|
||||
function resolveQaBundledPluginScanRoots(repoRoot: string) {
|
||||
@@ -96,6 +100,37 @@ function resolveQaBundledPluginScanRoots(repoRoot: string) {
|
||||
].filter((candidate, index, all) => existsSync(candidate) && all.indexOf(candidate) === index);
|
||||
}
|
||||
|
||||
function readQaBundledManifestId(manifestPath: string): string | null {
|
||||
try {
|
||||
const parsed = JSON.parse(readFileSync(manifestPath, "utf8")) as { id?: unknown };
|
||||
return typeof parsed.id === "string" ? parsed.id.trim() || null : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function findQaBundledPluginDirsByManifestId(params: {
|
||||
repoRoot: string;
|
||||
pluginId: string;
|
||||
}): string[] {
|
||||
const candidates: string[] = [];
|
||||
for (const sourceRoot of resolveQaBundledPluginScanRoots(params.repoRoot)) {
|
||||
for (const entry of readdirSync(sourceRoot, { withFileTypes: true }).toSorted((left, right) =>
|
||||
left.name.localeCompare(right.name),
|
||||
)) {
|
||||
if (!entry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
const candidate = path.join(sourceRoot, entry.name);
|
||||
const manifestId = readQaBundledManifestId(path.join(candidate, "openclaw.plugin.json"));
|
||||
if (manifestId === params.pluginId) {
|
||||
candidates.push(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
export async function resolveQaOwnerPluginIdsForProviderIds(params: {
|
||||
repoRoot: string;
|
||||
providerIds: readonly string[];
|
||||
|
||||
@@ -791,6 +791,33 @@ describe("qa bundled plugin dir", () => {
|
||||
).toBe(path.join(repoRoot, "extensions", "qa-channel"));
|
||||
});
|
||||
|
||||
it("resolves bundled plugins by manifest id when the directory name differs", async () => {
|
||||
const repoRoot = await mkdtemp(path.join(os.tmpdir(), "qa-bundled-manifest-id-root-"));
|
||||
cleanups.push(async () => {
|
||||
await rm(repoRoot, { recursive: true, force: true });
|
||||
});
|
||||
await mkdir(path.join(repoRoot, "dist", "extensions", "kimi-coding"), {
|
||||
recursive: true,
|
||||
});
|
||||
await writeFile(
|
||||
path.join(repoRoot, "dist", "extensions", "kimi-coding", "openclaw.plugin.json"),
|
||||
JSON.stringify({ id: "kimi", providers: ["kimi"] }),
|
||||
"utf8",
|
||||
);
|
||||
await writeFile(
|
||||
path.join(repoRoot, "dist", "extensions", "kimi-coding", "package.json"),
|
||||
"{}",
|
||||
"utf8",
|
||||
);
|
||||
|
||||
expect(
|
||||
__testing.resolveQaBundledPluginSourceDir({
|
||||
repoRoot,
|
||||
pluginId: "kimi",
|
||||
}),
|
||||
).toBe(path.join(repoRoot, "dist", "extensions", "kimi-coding"));
|
||||
});
|
||||
|
||||
it("uses a source bundled plugin when the built copy is missing CLI metadata", async () => {
|
||||
const repoRoot = await mkdtemp(path.join(os.tmpdir(), "qa-bundled-cli-metadata-root-"));
|
||||
cleanups.push(async () => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import JSON5 from "json5";
|
||||
import { collectBundledPluginBuildEntries } from "./bundled-plugin-build-entries.mjs";
|
||||
|
||||
const MANIFEST_NAMES = ["openclaw.plugin.json", "openclaw.plugin.json5"];
|
||||
|
||||
@@ -142,9 +143,13 @@ function buildPluginMatrixEntry(params) {
|
||||
|
||||
function discoverBundledPluginManifests(repoRoot) {
|
||||
const extensionsDir = path.join(repoRoot, "extensions");
|
||||
const buildEntryDirs = new Set(
|
||||
collectBundledPluginBuildEntries({ cwd: repoRoot }).map((entry) => entry.id),
|
||||
);
|
||||
const entries = fs
|
||||
.readdirSync(extensionsDir, { withFileTypes: true })
|
||||
.filter((entry) => entry.isDirectory())
|
||||
.filter((entry) => buildEntryDirs.has(entry.name))
|
||||
.flatMap((entry) => {
|
||||
const pluginDir = path.join(extensionsDir, entry.name);
|
||||
const manifestName = MANIFEST_NAMES.find((name) => fs.existsSync(path.join(pluginDir, name)));
|
||||
|
||||
@@ -53,8 +53,8 @@ describe("plugin gateway gauntlet helpers", () => {
|
||||
);
|
||||
await writeManifest(
|
||||
"beta",
|
||||
"openclaw.plugin.json5",
|
||||
`{ id: "beta", commandAliases: ["dreaming"], onboardingScopes: ["memory"] }`,
|
||||
"openclaw.plugin.json",
|
||||
JSON.stringify({ id: "beta", commandAliases: ["dreaming"], onboardingScopes: ["memory"] }),
|
||||
);
|
||||
|
||||
const matrix = discoverBundledPluginManifests(repoRoot);
|
||||
@@ -77,6 +77,15 @@ describe("plugin gateway gauntlet helpers", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("skips source-only plugin dirs that are excluded from the built runtime", async () => {
|
||||
await writeManifest("qqbot", "openclaw.plugin.json", JSON.stringify({ id: "qqbot" }));
|
||||
await writeManifest("telegram", "openclaw.plugin.json", JSON.stringify({ id: "telegram" }));
|
||||
|
||||
const matrix = discoverBundledPluginManifests(repoRoot);
|
||||
|
||||
expect(matrix.map((entry) => entry.id)).toEqual(["telegram"]);
|
||||
});
|
||||
|
||||
it("selects plugin shards after explicit id filtering", () => {
|
||||
const entries = ["a", "b", "c", "d"].map((id) => ({ id }));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user