






















@@ -4,6 +4,10 @@ import path from "node:path";
44import { fileURLToPath, pathToFileURL } from "node:url";
55import { openBoundaryFileSync } from "../infra/boundary-file-read.js";
66import { resolveBundledPluginsDir } from "../plugins/bundled-dir.js";
7+import {
8+isBuiltBundledPluginRuntimeRoot,
9+prepareBundledPluginRuntimeRoot,
10+} from "../plugins/bundled-runtime-root.js";
711import {
812getCachedPluginJitiLoader,
913type PluginJitiLoaderCache,
@@ -170,54 +174,114 @@ export type FacadeModuleLocation = {
170174boundaryRoot: string;
171175};
172176177+function resolveBuiltBundledPluginRoot(params: {
178+modulePath: string;
179+pluginId: string;
180+}): string | null {
181+const resolvedModulePath = path.resolve(params.modulePath);
182+let currentDir = path.dirname(resolvedModulePath);
183+while (true) {
184+if (
185+path.basename(currentDir) === params.pluginId &&
186+isBuiltBundledPluginRuntimeRoot(currentDir)
187+) {
188+const relativePath = path.relative(currentDir, resolvedModulePath);
189+if (!relativePath.startsWith("..") && !path.isAbsolute(relativePath)) {
190+return currentDir;
191+}
192+}
193+const parentDir = path.dirname(currentDir);
194+if (parentDir === currentDir) {
195+return null;
196+}
197+currentDir = parentDir;
198+}
199+}
200+201+function prepareFacadeLocationForBundledRuntimeDeps(params: {
202+location: FacadeModuleLocation;
203+runtimeDeps?: {
204+pluginId: string;
205+env?: NodeJS.ProcessEnv;
206+};
207+}): FacadeModuleLocation {
208+if (!params.runtimeDeps) {
209+return params.location;
210+}
211+const pluginRoot = resolveBuiltBundledPluginRoot({
212+modulePath: params.location.modulePath,
213+pluginId: params.runtimeDeps.pluginId,
214+});
215+if (!pluginRoot) {
216+return params.location;
217+}
218+const prepared = prepareBundledPluginRuntimeRoot({
219+pluginId: params.runtimeDeps.pluginId,
220+ pluginRoot,
221+modulePath: params.location.modulePath,
222+ ...(params.runtimeDeps.env ? { env: params.runtimeDeps.env } : {}),
223+});
224+return {
225+modulePath: prepared.modulePath,
226+boundaryRoot: prepared.pluginRoot,
227+};
228+}
229+173230export function loadFacadeModuleAtLocationSync<T extends object>(params: {
174231location: FacadeModuleLocation;
175232trackedPluginId: string | (() => string);
233+runtimeDeps?: {
234+pluginId: string;
235+env?: NodeJS.ProcessEnv;
236+};
176237loadModule?: (modulePath: string) => T;
177238}): T {
178-const cached = loadedFacadeModules.get(params.location.modulePath);
239+const location = prepareFacadeLocationForBundledRuntimeDeps({
240+location: params.location,
241+ ...(params.runtimeDeps ? { runtimeDeps: params.runtimeDeps } : {}),
242+});
243+const cached = loadedFacadeModules.get(location.modulePath);
179244if (cached) {
180245return cached as T;
181246}
182247183248const opened = openBoundaryFileSync({
184-absolutePath: params.location.modulePath,
185-rootPath: params.location.boundaryRoot,
249+absolutePath: location.modulePath,
250+rootPath: location.boundaryRoot,
186251boundaryLabel:
187-params.location.boundaryRoot === getOpenClawPackageRoot()
252+location.boundaryRoot === getOpenClawPackageRoot()
188253 ? "OpenClaw package root"
189254 : (() => {
190255const bundledDir = resolveBundledPluginsDir();
191-return bundledDir &&
192-path.resolve(params.location.boundaryRoot) === path.resolve(bundledDir)
256+return bundledDir && path.resolve(location.boundaryRoot) === path.resolve(bundledDir)
193257 ? "bundled plugin directory"
194258 : "plugin root";
195259})(),
196260rejectHardlinks: false,
197261});
198262if (!opened.ok) {
199-throw new Error(`Unable to open bundled plugin public surface ${params.location.modulePath}`, {
263+throw new Error(`Unable to open bundled plugin public surface ${location.modulePath}`, {
200264cause: opened.error,
201265});
202266}
203267fs.closeSync(opened.fd);
204268205269const sentinel = {} as T;
206-loadedFacadeModules.set(params.location.modulePath, sentinel);
270+loadedFacadeModules.set(location.modulePath, sentinel);
207271208272let loaded: T;
209273try {
210274loaded =
211-params.loadModule?.(params.location.modulePath) ??
212-(getJiti(params.location.modulePath)(params.location.modulePath) as T);
275+params.loadModule?.(location.modulePath) ??
276+(getJiti(location.modulePath)(location.modulePath) as T);
213277Object.assign(sentinel, loaded);
214278loadedFacadePluginIds.add(
215279typeof params.trackedPluginId === "function"
216280 ? params.trackedPluginId()
217281 : params.trackedPluginId,
218282);
219283} catch (err) {
220-loadedFacadeModules.delete(params.location.modulePath);
284+loadedFacadeModules.delete(location.modulePath);
221285throw err;
222286}
223287@@ -240,6 +304,10 @@ export function loadBundledPluginPublicSurfaceModuleSync<T extends object>(param
240304return loadFacadeModuleAtLocationSync({
241305 location,
242306trackedPluginId: params.trackedPluginId ?? params.dirName,
307+runtimeDeps: {
308+pluginId: params.dirName,
309+ ...(params.env ? { env: params.env } : {}),
310+},
243311});
244312}
245313@@ -255,28 +323,37 @@ export async function loadBundledPluginPublicSurfaceModule<T extends object>(par
255323`Unable to resolve bundled plugin public surface ${params.dirName}/${params.artifactBasename}`,
256324);
257325}
258-const cached = loadedFacadeModules.get(location.modulePath);
326+const preparedLocation = prepareFacadeLocationForBundledRuntimeDeps({
327+ location,
328+runtimeDeps: {
329+pluginId: params.dirName,
330+ ...(params.env ? { env: params.env } : {}),
331+},
332+});
333+const cached = loadedFacadeModules.get(preparedLocation.modulePath);
259334if (cached) {
260335return cached as T;
261336}
262337263338const opened = openBoundaryFileSync({
264-absolutePath: location.modulePath,
265-rootPath: location.boundaryRoot,
339+absolutePath: preparedLocation.modulePath,
340+rootPath: preparedLocation.boundaryRoot,
266341boundaryLabel:
267-location.boundaryRoot === getOpenClawPackageRoot() ? "OpenClaw package root" : "plugin root",
342+preparedLocation.boundaryRoot === getOpenClawPackageRoot()
343+ ? "OpenClaw package root"
344+ : "plugin root",
268345rejectHardlinks: false,
269346});
270347if (!opened.ok) {
271-throw new Error(`Unable to open bundled plugin public surface ${location.modulePath}`, {
348+throw new Error(`Unable to open bundled plugin public surface ${preparedLocation.modulePath}`, {
272349cause: opened.error,
273350});
274351}
275352fs.closeSync(opened.fd);
276353277354try {
278-const loaded = (await import(pathToFileURL(location.modulePath).href)) as T;
279-loadedFacadeModules.set(location.modulePath, loaded);
355+const loaded = (await import(pathToFileURL(preparedLocation.modulePath).href)) as T;
356+loadedFacadeModules.set(preparedLocation.modulePath, loaded);
280357loadedFacadePluginIds.add(
281358typeof params.trackedPluginId === "function"
282359 ? params.trackedPluginId()
@@ -285,7 +362,7 @@ export async function loadBundledPluginPublicSurfaceModule<T extends object>(par
285362return loaded;
286363} catch {
287364return loadFacadeModuleAtLocationSync({
288- location,
365+location: preparedLocation,
289366trackedPluginId: params.trackedPluginId ?? params.dirName,
290367});
291368}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。