refactor: dedupe helpers and source seams

This commit is contained in:
Peter Steinberger
2026-03-24 20:39:45 +00:00
parent ebe18c0379
commit bcd61f0a38
83 changed files with 2795 additions and 4495 deletions

View File

@@ -12,6 +12,7 @@ import {
import { VERSION } from "../../version.js";
import { listWebSearchProviders, runWebSearch } from "../../web-search/runtime.js";
import { createRuntimeAgent } from "./runtime-agent.js";
import { defineCachedValue } from "./runtime-cache.js";
import { createRuntimeChannel } from "./runtime-channel.js";
import { createRuntimeConfig } from "./runtime-config.js";
import { createRuntimeEvents } from "./runtime-events.js";
@@ -21,26 +22,6 @@ import { createRuntimeSystem } from "./runtime-system.js";
import { createRuntimeTools } from "./runtime-tools.js";
import type { PluginRuntime } from "./types.js";
function defineCachedValue<T extends object, K extends PropertyKey>(
target: T,
key: K,
create: () => unknown,
): void {
let cached: unknown;
let ready = false;
Object.defineProperty(target, key, {
configurable: true,
enumerable: true,
get() {
if (!ready) {
cached = create();
ready = true;
}
return cached;
},
});
}
const loadTtsRuntime = createLazyRuntimeModule(() => import("./runtime-tts.runtime.js"));
const loadMediaUnderstandingRuntime = createLazyRuntimeModule(
() => import("./runtime-media-understanding.runtime.js"),

View File

@@ -7,28 +7,9 @@ import { ensureAgentWorkspace } from "../../agents/workspace.js";
import { resolveSessionFilePath, resolveStorePath } from "../../config/sessions/paths.js";
import { loadSessionStore, saveSessionStore } from "../../config/sessions/store.js";
import { createLazyRuntimeMethod, createLazyRuntimeModule } from "../../shared/lazy-runtime.js";
import { defineCachedValue } from "./runtime-cache.js";
import type { PluginRuntime } from "./types.js";
function defineCachedValue<T extends object, K extends PropertyKey>(
target: T,
key: K,
create: () => unknown,
): void {
let cached: unknown;
let ready = false;
Object.defineProperty(target, key, {
configurable: true,
enumerable: true,
get() {
if (!ready) {
cached = create();
ready = true;
}
return cached;
},
});
}
const loadEmbeddedPiRuntime = createLazyRuntimeModule(
() => import("./runtime-embedded-pi.runtime.js"),
);

View File

@@ -0,0 +1,19 @@
export function defineCachedValue<T extends object, K extends PropertyKey>(
target: T,
key: K,
create: () => unknown,
): void {
let cached: unknown;
let ready = false;
Object.defineProperty(target, key, {
configurable: true,
enumerable: true,
get() {
if (!ready) {
cached = create();
ready = true;
}
return cached;
},
});
}

View File

@@ -76,6 +76,7 @@ import {
resolveLineAccount,
} from "../../plugin-sdk/line.js";
import { buildAgentSessionKey, resolveAgentRoute } from "../../routing/resolve-route.js";
import { defineCachedValue } from "./runtime-cache.js";
import { createRuntimeDiscord } from "./runtime-discord.js";
import { createRuntimeIMessage } from "./runtime-imessage.js";
import { createRuntimeMatrix } from "./runtime-matrix.js";
@@ -85,26 +86,6 @@ import { createRuntimeTelegram } from "./runtime-telegram.js";
import { createRuntimeWhatsApp } from "./runtime-whatsapp.js";
import type { PluginRuntime } from "./types.js";
function defineCachedValue<T extends object, K extends PropertyKey>(
target: T,
key: K,
create: () => unknown,
): void {
let cached: unknown;
let ready = false;
Object.defineProperty(target, key, {
configurable: true,
enumerable: true,
get() {
if (!ready) {
cached = create();
ready = true;
}
return cached;
},
});
}
export function createRuntimeChannel(): PluginRuntime["channel"] {
const channelRuntime = {
text: {

View File

@@ -1,14 +1,9 @@
import fs from "node:fs";
import path from "node:path";
import { createJiti } from "jiti";
import { loadConfig } from "../../config/config.js";
import { loadPluginManifestRegistry } from "../manifest-registry.js";
import {
buildPluginLoaderJitiOptions,
resolvePluginSdkAliasFile,
resolvePluginSdkScopedAliasMap,
shouldPreferNativeJiti,
} from "../sdk-alias.js";
loadPluginBoundaryModuleWithJiti,
resolvePluginRuntimeModulePath,
resolvePluginRuntimeRecord,
} from "./runtime-plugin-boundary.js";
const MATRIX_PLUGIN_ID = "matrix";
@@ -24,70 +19,12 @@ let cachedModule: MatrixModule | null = null;
const jitiLoaders = new Map<boolean, ReturnType<typeof createJiti>>();
function readConfigSafely() {
try {
return loadConfig();
} catch {
return {};
}
}
function resolveMatrixPluginRecord(): MatrixPluginRecord | null {
const manifestRegistry = loadPluginManifestRegistry({
config: readConfigSafely(),
cache: true,
});
const record = manifestRegistry.plugins.find((plugin) => plugin.id === MATRIX_PLUGIN_ID);
if (!record?.source) {
return null;
}
return {
rootDir: record.rootDir,
source: record.source,
};
return resolvePluginRuntimeRecord(MATRIX_PLUGIN_ID) as MatrixPluginRecord | null;
}
function resolveMatrixRuntimeModulePath(record: MatrixPluginRecord): string | null {
const candidates = [
path.join(path.dirname(record.source), "runtime-api.js"),
path.join(path.dirname(record.source), "runtime-api.ts"),
...(record.rootDir
? [path.join(record.rootDir, "runtime-api.js"), path.join(record.rootDir, "runtime-api.ts")]
: []),
];
for (const candidate of candidates) {
if (fs.existsSync(candidate)) {
return candidate;
}
}
return null;
}
function getJiti(modulePath: string) {
const tryNative = shouldPreferNativeJiti(modulePath);
const cached = jitiLoaders.get(tryNative);
if (cached) {
return cached;
}
const pluginSdkAlias = resolvePluginSdkAliasFile({
srcFile: "root-alias.cjs",
distFile: "root-alias.cjs",
modulePath,
});
const aliasMap = {
...(pluginSdkAlias ? { "openclaw/plugin-sdk": pluginSdkAlias } : {}),
...resolvePluginSdkScopedAliasMap({ modulePath }),
};
const loader = createJiti(import.meta.url, {
...buildPluginLoaderJitiOptions(aliasMap),
tryNative,
});
jitiLoaders.set(tryNative, loader);
return loader;
}
function loadWithJiti<TModule>(modulePath: string): TModule {
return getJiti(modulePath)(modulePath) as TModule;
return resolvePluginRuntimeModulePath(record, "runtime-api");
}
function loadMatrixModule(): MatrixModule | null {
@@ -102,7 +39,7 @@ function loadMatrixModule(): MatrixModule | null {
if (cachedModule && cachedModulePath === modulePath) {
return cachedModule;
}
const loaded = loadWithJiti<MatrixModule>(modulePath);
const loaded = loadPluginBoundaryModuleWithJiti<MatrixModule>(modulePath, jitiLoaders);
cachedModulePath = modulePath;
cachedModule = loaded;
return loaded;

View File

@@ -0,0 +1,106 @@
import fs from "node:fs";
import path from "node:path";
import { createJiti } from "jiti";
import { loadConfig } from "../../config/config.js";
import { loadPluginManifestRegistry } from "../manifest-registry.js";
import {
buildPluginLoaderJitiOptions,
resolvePluginSdkAliasFile,
resolvePluginSdkScopedAliasMap,
shouldPreferNativeJiti,
} from "../sdk-alias.js";
type PluginRuntimeRecord = {
origin?: string;
rootDir?: string;
source: string;
};
export function readPluginBoundaryConfigSafely() {
try {
return loadConfig();
} catch {
return {};
}
}
export function resolvePluginRuntimeRecord(
pluginId: string,
onMissing?: () => never,
): PluginRuntimeRecord | null {
const manifestRegistry = loadPluginManifestRegistry({
config: readPluginBoundaryConfigSafely(),
cache: true,
});
const record = manifestRegistry.plugins.find((plugin) => plugin.id === pluginId);
if (!record?.source) {
if (onMissing) {
onMissing();
}
return null;
}
return {
...(record.origin ? { origin: record.origin } : {}),
rootDir: record.rootDir,
source: record.source,
};
}
export function resolvePluginRuntimeModulePath(
record: Pick<PluginRuntimeRecord, "rootDir" | "source">,
entryBaseName: string,
onMissing?: () => never,
): string | null {
const candidates = [
path.join(path.dirname(record.source), `${entryBaseName}.js`),
path.join(path.dirname(record.source), `${entryBaseName}.ts`),
...(record.rootDir
? [
path.join(record.rootDir, `${entryBaseName}.js`),
path.join(record.rootDir, `${entryBaseName}.ts`),
]
: []),
];
for (const candidate of candidates) {
if (fs.existsSync(candidate)) {
return candidate;
}
}
if (onMissing) {
onMissing();
}
return null;
}
export function getPluginBoundaryJiti(
modulePath: string,
loaders: Map<boolean, ReturnType<typeof createJiti>>,
) {
const tryNative = shouldPreferNativeJiti(modulePath);
const cached = loaders.get(tryNative);
if (cached) {
return cached;
}
const pluginSdkAlias = resolvePluginSdkAliasFile({
srcFile: "root-alias.cjs",
distFile: "root-alias.cjs",
modulePath,
});
const aliasMap = {
...(pluginSdkAlias ? { "openclaw/plugin-sdk": pluginSdkAlias } : {}),
...resolvePluginSdkScopedAliasMap({ modulePath }),
};
const loader = createJiti(import.meta.url, {
...buildPluginLoaderJitiOptions(aliasMap),
tryNative,
});
loaders.set(tryNative, loader);
return loader;
}
export function loadPluginBoundaryModuleWithJiti<TModule>(
modulePath: string,
loaders: Map<boolean, ReturnType<typeof createJiti>>,
): TModule {
return getPluginBoundaryJiti(modulePath, loaders)(modulePath) as TModule;
}

View File

@@ -1,21 +1,16 @@
import fs from "node:fs";
import path from "node:path";
import { createJiti } from "jiti";
import { resolveWhatsAppHeartbeatRecipients } from "../../channels/plugins/whatsapp-heartbeat.js";
import { loadConfig } from "../../config/config.js";
import {
getDefaultLocalRoots as getDefaultLocalRootsImpl,
loadWebMedia as loadWebMediaImpl,
loadWebMediaRaw as loadWebMediaRawImpl,
optimizeImageToJpeg as optimizeImageToJpegImpl,
} from "../../media/web-media.js";
import { loadPluginManifestRegistry } from "../manifest-registry.js";
import {
buildPluginLoaderJitiOptions,
resolvePluginSdkAliasFile,
resolvePluginSdkScopedAliasMap,
shouldPreferNativeJiti,
} from "../sdk-alias.js";
loadPluginBoundaryModuleWithJiti,
resolvePluginRuntimeModulePath,
resolvePluginRuntimeRecord,
} from "./runtime-plugin-boundary.js";
const WHATSAPP_PLUGIN_ID = "whatsapp";
@@ -35,86 +30,34 @@ let cachedLightModule: WhatsAppLightModule | null = null;
const jitiLoaders = new Map<boolean, ReturnType<typeof createJiti>>();
function readConfigSafely() {
try {
return loadConfig();
} catch {
return {};
}
}
function resolveWhatsAppPluginRecord(): WhatsAppPluginRecord {
const manifestRegistry = loadPluginManifestRegistry({
config: readConfigSafely(),
cache: true,
});
const record = manifestRegistry.plugins.find((plugin) => plugin.id === WHATSAPP_PLUGIN_ID);
if (!record?.source) {
return resolvePluginRuntimeRecord(WHATSAPP_PLUGIN_ID, () => {
throw new Error(
`WhatsApp plugin runtime is unavailable: missing plugin '${WHATSAPP_PLUGIN_ID}'`,
);
}
return {
origin: record.origin,
rootDir: record.rootDir,
source: record.source,
};
}) as WhatsAppPluginRecord;
}
function resolveWhatsAppRuntimeModulePath(
record: WhatsAppPluginRecord,
entryBaseName: "light-runtime-api" | "runtime-api",
): string {
const candidates = [
path.join(path.dirname(record.source), `${entryBaseName}.js`),
path.join(path.dirname(record.source), `${entryBaseName}.ts`),
...(record.rootDir
? [
path.join(record.rootDir, `${entryBaseName}.js`),
path.join(record.rootDir, `${entryBaseName}.ts`),
]
: []),
];
for (const candidate of candidates) {
if (fs.existsSync(candidate)) {
return candidate;
}
}
throw new Error(
`WhatsApp plugin runtime is unavailable: missing ${entryBaseName} for plugin '${WHATSAPP_PLUGIN_ID}'`,
);
}
function getJiti(modulePath: string) {
const tryNative = shouldPreferNativeJiti(modulePath);
const cached = jitiLoaders.get(tryNative);
if (cached) {
return cached;
}
const pluginSdkAlias = resolvePluginSdkAliasFile({
srcFile: "root-alias.cjs",
distFile: "root-alias.cjs",
modulePath: modulePath,
const modulePath = resolvePluginRuntimeModulePath(record, entryBaseName, () => {
throw new Error(
`WhatsApp plugin runtime is unavailable: missing ${entryBaseName} for plugin '${WHATSAPP_PLUGIN_ID}'`,
);
});
const aliasMap = {
...(pluginSdkAlias ? { "openclaw/plugin-sdk": pluginSdkAlias } : {}),
...resolvePluginSdkScopedAliasMap({ modulePath }),
};
const loader = createJiti(import.meta.url, {
...buildPluginLoaderJitiOptions(aliasMap),
tryNative,
});
jitiLoaders.set(tryNative, loader);
return loader;
}
function loadWithJiti<TModule>(modulePath: string): TModule {
return getJiti(modulePath)(modulePath) as TModule;
if (!modulePath) {
throw new Error(
`WhatsApp plugin runtime is unavailable: missing ${entryBaseName} for plugin '${WHATSAPP_PLUGIN_ID}'`,
);
}
return modulePath;
}
function loadCurrentHeavyModuleSync(): WhatsAppHeavyModule {
const modulePath = resolveWhatsAppRuntimeModulePath(resolveWhatsAppPluginRecord(), "runtime-api");
return loadWithJiti<WhatsAppHeavyModule>(modulePath);
return loadPluginBoundaryModuleWithJiti<WhatsAppHeavyModule>(modulePath, jitiLoaders);
}
function loadWhatsAppLightModule(): WhatsAppLightModule {
@@ -125,7 +68,7 @@ function loadWhatsAppLightModule(): WhatsAppLightModule {
if (cachedLightModule && cachedLightModulePath === modulePath) {
return cachedLightModule;
}
const loaded = loadWithJiti<WhatsAppLightModule>(modulePath);
const loaded = loadPluginBoundaryModuleWithJiti<WhatsAppLightModule>(modulePath, jitiLoaders);
cachedLightModulePath = modulePath;
cachedLightModule = loaded;
return loaded;
@@ -137,7 +80,7 @@ async function loadWhatsAppHeavyModule(): Promise<WhatsAppHeavyModule> {
if (cachedHeavyModule && cachedHeavyModulePath === modulePath) {
return cachedHeavyModule;
}
const loaded = loadWithJiti<WhatsAppHeavyModule>(modulePath);
const loaded = loadPluginBoundaryModuleWithJiti<WhatsAppHeavyModule>(modulePath, jitiLoaders);
cachedHeavyModulePath = modulePath;
cachedHeavyModule = loaded;
return loaded;