mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 14:10:51 +00:00
refactor: share private QA bundled root override
This commit is contained in:
31
src/plugin-sdk/private-qa-bundled-env.ts
Normal file
31
src/plugin-sdk/private-qa-bundled-env.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { resolveOpenClawPackageRootSync } from "../infra/openclaw-root.js";
|
||||
|
||||
export function resolvePrivateQaBundledPluginsEnv(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): NodeJS.ProcessEnv | undefined {
|
||||
if (env.OPENCLAW_ENABLE_PRIVATE_QA_CLI !== "1") {
|
||||
return undefined;
|
||||
}
|
||||
const packageRoot = resolveOpenClawPackageRootSync({
|
||||
argv1: process.argv[1],
|
||||
cwd: process.cwd(),
|
||||
moduleUrl: import.meta.url,
|
||||
});
|
||||
if (!packageRoot) {
|
||||
return undefined;
|
||||
}
|
||||
const sourceExtensionsDir = path.join(packageRoot, "extensions");
|
||||
if (
|
||||
!fs.existsSync(path.join(packageRoot, ".git")) ||
|
||||
!fs.existsSync(path.join(packageRoot, "src")) ||
|
||||
!fs.existsSync(sourceExtensionsDir)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
...env,
|
||||
OPENCLAW_BUNDLED_PLUGINS_DIR: sourceExtensionsDir,
|
||||
};
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import type { Command } from "commander";
|
||||
import { resolveOpenClawPackageRootSync } from "../infra/openclaw-root.js";
|
||||
import type { PluginManifestRecord } from "../plugins/manifest-registry.js";
|
||||
import { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";
|
||||
import {
|
||||
loadBundledPluginPublicSurfaceModuleSync,
|
||||
tryLoadActivatedBundledPluginPublicSurfaceModuleSync,
|
||||
} from "./facade-runtime.js";
|
||||
import { resolvePrivateQaBundledPluginsEnv } from "./private-qa-bundled-env.js";
|
||||
|
||||
export type QaRunnerCliRegistration = {
|
||||
commandName: string;
|
||||
@@ -56,7 +54,7 @@ function isMissingQaRuntimeError(error: unknown) {
|
||||
}
|
||||
|
||||
export function loadQaRuntimeModule(): QaRuntimeSurface {
|
||||
const env = resolvePrivateQaRunnerEnv();
|
||||
const env = resolvePrivateQaBundledPluginsEnv();
|
||||
return loadBundledPluginPublicSurfaceModuleSync<QaRuntimeSurface>({
|
||||
dirName: ["qa", "lab"].join("-"),
|
||||
artifactBasename: ["runtime-api", "js"].join("."),
|
||||
@@ -76,36 +74,8 @@ export function isQaRuntimeAvailable(): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
function resolvePrivateQaRunnerEnv(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): NodeJS.ProcessEnv | undefined {
|
||||
if (env.OPENCLAW_ENABLE_PRIVATE_QA_CLI !== "1") {
|
||||
return undefined;
|
||||
}
|
||||
const packageRoot = resolveOpenClawPackageRootSync({
|
||||
argv1: process.argv[1],
|
||||
cwd: process.cwd(),
|
||||
moduleUrl: import.meta.url,
|
||||
});
|
||||
if (!packageRoot) {
|
||||
return undefined;
|
||||
}
|
||||
const sourceExtensionsDir = path.join(packageRoot, "extensions");
|
||||
if (
|
||||
!fs.existsSync(path.join(packageRoot, ".git")) ||
|
||||
!fs.existsSync(path.join(packageRoot, "src")) ||
|
||||
!fs.existsSync(sourceExtensionsDir)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
...env,
|
||||
OPENCLAW_BUNDLED_PLUGINS_DIR: sourceExtensionsDir,
|
||||
};
|
||||
}
|
||||
|
||||
function listDeclaredQaRunnerPlugins(
|
||||
env: NodeJS.ProcessEnv | undefined = resolvePrivateQaRunnerEnv(),
|
||||
env: NodeJS.ProcessEnv | undefined = resolvePrivateQaBundledPluginsEnv(),
|
||||
): Array<
|
||||
PluginManifestRecord & {
|
||||
qaRunners: NonNullable<PluginManifestRecord["qaRunners"]>;
|
||||
@@ -167,7 +137,7 @@ function loadQaRunnerRuntimeSurface(
|
||||
}
|
||||
|
||||
export function listQaRunnerCliContributions(): readonly QaRunnerCliContribution[] {
|
||||
const env = resolvePrivateQaRunnerEnv();
|
||||
const env = resolvePrivateQaBundledPluginsEnv();
|
||||
const contributions = new Map<string, QaRunnerCliContribution>();
|
||||
|
||||
for (const plugin of listDeclaredQaRunnerPlugins(env)) {
|
||||
|
||||
@@ -1,14 +1,38 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const loadBundledPluginPublicSurfaceModuleSync = vi.hoisted(() => vi.fn());
|
||||
const resolveOpenClawPackageRootSync = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("./facade-runtime.js", () => ({
|
||||
loadBundledPluginPublicSurfaceModuleSync,
|
||||
}));
|
||||
|
||||
vi.mock("../infra/openclaw-root.js", () => ({
|
||||
resolveOpenClawPackageRootSync,
|
||||
}));
|
||||
|
||||
describe("plugin-sdk qa-runtime", () => {
|
||||
const tempDirs: string[] = [];
|
||||
const originalPrivateQaCli = process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI;
|
||||
|
||||
beforeEach(() => {
|
||||
loadBundledPluginPublicSurfaceModuleSync.mockReset();
|
||||
resolveOpenClawPackageRootSync.mockReset().mockReturnValue(null);
|
||||
delete process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
for (const dir of tempDirs.splice(0)) {
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
if (originalPrivateQaCli === undefined) {
|
||||
delete process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI;
|
||||
} else {
|
||||
process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI = originalPrivateQaCli;
|
||||
}
|
||||
});
|
||||
|
||||
it("stays cold until the runtime seam is used", async () => {
|
||||
@@ -35,6 +59,34 @@ describe("plugin-sdk qa-runtime", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("uses the source bundled tree for qa-lab runtime loading in private qa mode", async () => {
|
||||
const sourceRoot = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-qa-runtime-root-"));
|
||||
tempDirs.push(sourceRoot);
|
||||
fs.mkdirSync(path.join(sourceRoot, "src"), { recursive: true });
|
||||
fs.mkdirSync(path.join(sourceRoot, "extensions"), { recursive: true });
|
||||
fs.writeFileSync(path.join(sourceRoot, ".git"), "gitdir: /tmp/mock\n", "utf8");
|
||||
process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI = "1";
|
||||
resolveOpenClawPackageRootSync.mockReturnValue(sourceRoot);
|
||||
|
||||
const runtimeSurface = {
|
||||
defaultQaRuntimeModelForMode: vi.fn(),
|
||||
startQaLiveLaneGateway: vi.fn(),
|
||||
};
|
||||
loadBundledPluginPublicSurfaceModuleSync.mockReturnValue(runtimeSurface);
|
||||
|
||||
const module = await import("./qa-runtime.js");
|
||||
|
||||
expect(module.loadQaRuntimeModule()).toBe(runtimeSurface);
|
||||
expect(loadBundledPluginPublicSurfaceModuleSync).toHaveBeenCalledWith({
|
||||
dirName: "qa-lab",
|
||||
artifactBasename: "runtime-api.js",
|
||||
env: expect.objectContaining({
|
||||
OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1",
|
||||
OPENCLAW_BUNDLED_PLUGINS_DIR: path.join(sourceRoot, "extensions"),
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
it("reports the runtime as unavailable when the qa-lab surface is missing", async () => {
|
||||
loadBundledPluginPublicSurfaceModuleSync.mockImplementation(() => {
|
||||
throw new Error("Unable to resolve bundled plugin public surface qa-lab/runtime-api.js");
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
|
||||
import { resolvePrivateQaBundledPluginsEnv } from "./private-qa-bundled-env.js";
|
||||
|
||||
type QaRuntimeSurface = {
|
||||
defaultQaRuntimeModelForMode: (
|
||||
@@ -20,9 +21,11 @@ function isMissingQaRuntimeError(error: unknown) {
|
||||
}
|
||||
|
||||
export function loadQaRuntimeModule(): QaRuntimeSurface {
|
||||
const env = resolvePrivateQaBundledPluginsEnv();
|
||||
return loadBundledPluginPublicSurfaceModuleSync<QaRuntimeSurface>({
|
||||
dirName: "qa-lab",
|
||||
artifactBasename: "runtime-api.js",
|
||||
...(env ? { env } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user