mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-04 21:40:24 +00:00
refactor(plugins): decouple bundled plugin runtime loading
This commit is contained in:
@@ -7,6 +7,7 @@ import { clearRuntimeAuthProfileStoreSnapshots } from "../agents/auth-profiles.j
|
||||
import { resetCliCredentialCachesForTest } from "../agents/cli-credentials.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resetProviderRuntimeHookCacheForTest } from "../plugins/provider-runtime.js";
|
||||
import { resolveRelativeBundledPluginPublicModuleId } from "../test-utils/bundled-plugin-public-surface.js";
|
||||
|
||||
// Avoid exporting vitest mock types (TS2742 under pnpm + d.ts emit).
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
@@ -158,12 +159,17 @@ const webSessionMocks = getSharedMocks("openclaw.trigger-handling.web-session-mo
|
||||
readWebSelfId: vi.fn().mockReturnValue({ e164: "+1999" }),
|
||||
}));
|
||||
|
||||
const whatsappRuntimeApiModuleId = resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "whatsapp",
|
||||
artifactBasename: "runtime-api.js",
|
||||
});
|
||||
|
||||
export function getWebSessionMocks(): AnyMocks {
|
||||
return webSessionMocks;
|
||||
}
|
||||
|
||||
const installWebSessionMock = () =>
|
||||
vi.doMock("../../extensions/whatsapp/runtime-api.js", () => webSessionMocks);
|
||||
const installWebSessionMock = () => vi.doMock(whatsappRuntimeApiModuleId, () => webSessionMocks);
|
||||
|
||||
installWebSessionMock();
|
||||
|
||||
|
||||
@@ -34,8 +34,7 @@ describe("ACP install hints", () => {
|
||||
|
||||
const cfg = withAcpConfig({ backend: "acpx" });
|
||||
const hint = resolveAcpInstallCommandHint(cfg);
|
||||
expect(hint).toContain("openclaw plugins install ");
|
||||
expect(hint).toContain(path.join("extensions", "acpx"));
|
||||
expect(hint).toBe(`openclaw plugins install ${path.join(tempRoot, "extensions", "acpx")}`);
|
||||
});
|
||||
|
||||
it("falls back to scoped install hint for acpx when local extension is absent", () => {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { existsSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import type { OpenClawConfig } from "../../../config/config.js";
|
||||
import { resolveBundledPluginWorkspaceSourcePath } from "../../../plugins/bundled-plugin-metadata.js";
|
||||
import { resolveBundledPluginInstallCommandHint } from "../../../plugins/bundled-sources.js";
|
||||
|
||||
export function resolveConfiguredAcpBackendId(cfg: OpenClawConfig): string {
|
||||
return cfg.acp?.backend?.trim() || "acpx";
|
||||
@@ -11,11 +13,30 @@ export function resolveAcpInstallCommandHint(cfg: OpenClawConfig): string {
|
||||
if (configured) {
|
||||
return configured;
|
||||
}
|
||||
const workspaceDir = process.cwd();
|
||||
const backendId = resolveConfiguredAcpBackendId(cfg).toLowerCase();
|
||||
if (backendId === "acpx") {
|
||||
const localPath = path.resolve(process.cwd(), "extensions/acpx");
|
||||
if (existsSync(localPath)) {
|
||||
return `openclaw plugins install ${localPath}`;
|
||||
const workspaceLocalPath = resolveBundledPluginWorkspaceSourcePath({
|
||||
rootDir: workspaceDir,
|
||||
pluginId: backendId,
|
||||
});
|
||||
if (workspaceLocalPath && existsSync(workspaceLocalPath)) {
|
||||
return `openclaw plugins install ${workspaceLocalPath}`;
|
||||
}
|
||||
const bundledInstallHint = resolveBundledPluginInstallCommandHint({
|
||||
pluginId: backendId,
|
||||
workspaceDir,
|
||||
});
|
||||
if (bundledInstallHint) {
|
||||
const localPath = bundledInstallHint.replace(/^openclaw plugins install /u, "");
|
||||
const resolvedLocalPath = path.resolve(localPath);
|
||||
const relativeToWorkspace = path.relative(workspaceDir, resolvedLocalPath);
|
||||
const belongsToWorkspace =
|
||||
relativeToWorkspace.length === 0 ||
|
||||
(!relativeToWorkspace.startsWith("..") && !path.isAbsolute(relativeToWorkspace));
|
||||
if (belongsToWorkspace && existsSync(resolvedLocalPath)) {
|
||||
return bundledInstallHint;
|
||||
}
|
||||
}
|
||||
return "openclaw plugins install acpx";
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { installedPluginRoot } from "../../../test/helpers/bundled-plugin-paths.js";
|
||||
import { createPluginRecord, createPluginStatusReport } from "../../plugins/status.test-helpers.js";
|
||||
|
||||
const WORKSPACE_PLUGIN_ROOT = installedPluginRoot("/tmp/workspace/.openclaw", "superpowers");
|
||||
|
||||
const {
|
||||
readConfigFileSnapshotMock,
|
||||
validateConfigObjectWithPluginsMock,
|
||||
@@ -70,7 +73,7 @@ describe("handleCommands /plugins toggle", () => {
|
||||
createPluginRecord({
|
||||
id: "superpowers",
|
||||
format: "bundle",
|
||||
source: "/tmp/workspace/.openclaw/extensions/superpowers",
|
||||
source: WORKSPACE_PLUGIN_ROOT,
|
||||
enabled: false,
|
||||
status: "disabled",
|
||||
}),
|
||||
@@ -110,7 +113,7 @@ describe("handleCommands /plugins toggle", () => {
|
||||
createPluginRecord({
|
||||
id: "superpowers",
|
||||
format: "bundle",
|
||||
source: "/tmp/workspace/.openclaw/extensions/superpowers",
|
||||
source: WORKSPACE_PLUGIN_ROOT,
|
||||
enabled: true,
|
||||
}),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user