mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-16 15:43:57 -06:00
499d81cdbd
* perf(plugins): close the last kysely closure chains and guard reachability transitively Follow-up to #120698/#120811/#120882: the closure guard's enumerated barrel bans cannot catch new heavy edges, and two closures still statically reached kysely on main. - guard: add a transitive kysely-reachability test that walks static value imports from every doctor-contract and legacy-setup closure through plugin, plugin-sdk, and relative core graphs, failing with the full import chain; type-only and lazy dynamic imports stay allowed - llm-task/model refs: manifest-model-id-normalization reads snapshots through a registration-slot runtime bridge (snapshot modules register at eval; require fallback covers cold processes) and current-plugin-metadata-state moves its process-scoped facts onto a globalThis singleton so dual module instances share published state - telegram: split thread-bindings-store.ts (pure record shapes + legacy-file readers) out of the acp-runtime-heavy manager, delete the consumer-less testing export, move the pure bot-user-id token parse to token-fingerprint.ts, and lazy-import token.js in the async update-offset detector llm-task enumeration drops to ~0.8s/157 modules cold; every closure is now statically kysely-free and stays that way by construction. * fix(telegram): repoint the native-command menu state at the token-fingerprint parser
96 lines
3.4 KiB
TypeScript
96 lines
3.4 KiB
TypeScript
/**
|
|
* Lazy bridge for plugin metadata snapshot reads. The snapshot modules pull
|
|
* the control-plane context (installed-plugin index/kysely), which light
|
|
* shared modules and doctor closures must not cold-load at import time.
|
|
*
|
|
* The snapshot module registers its reader here at eval time, so any process
|
|
* that published or scoped a snapshot serves reads through the registered
|
|
* instance. The require fallback only covers cold processes that never loaded
|
|
* the metadata system (built code loads .js; source/jiti paths resolve .ts).
|
|
*/
|
|
import { createRequire } from "node:module";
|
|
import { resolveGlobalSingleton } from "../shared/global-singleton.js";
|
|
|
|
type CurrentSnapshotModule = Pick<
|
|
typeof import("./current-plugin-metadata-snapshot.js"),
|
|
"getCurrentPluginMetadataSnapshot"
|
|
>;
|
|
type SnapshotLoaderModule = Pick<
|
|
typeof import("./plugin-metadata-snapshot.js"),
|
|
"resolvePluginMetadataSnapshot"
|
|
>;
|
|
|
|
type SnapshotReaderSlot = {
|
|
getCurrentPluginMetadataSnapshot?: CurrentSnapshotModule["getCurrentPluginMetadataSnapshot"];
|
|
resolvePluginMetadataSnapshot?: SnapshotLoaderModule["resolvePluginMetadataSnapshot"];
|
|
};
|
|
|
|
// globalThis-keyed so a require-loaded second module instance shares the slot.
|
|
const snapshotReaderSlot = resolveGlobalSingleton<SnapshotReaderSlot>(
|
|
Symbol.for("openclaw.pluginMetadataSnapshotReaders"),
|
|
() => ({}),
|
|
);
|
|
|
|
/** Called by the snapshot modules at eval time; last registration wins. */
|
|
export function registerPluginMetadataSnapshotReaders(readers: SnapshotReaderSlot): void {
|
|
Object.assign(snapshotReaderSlot, readers);
|
|
}
|
|
|
|
const require = createRequire(import.meta.url);
|
|
|
|
function createModuleLoader(candidates: readonly string[]): () => unknown {
|
|
let loaded: unknown;
|
|
let attempted = false;
|
|
return () => {
|
|
if (loaded) {
|
|
return loaded;
|
|
}
|
|
if (attempted) {
|
|
return null;
|
|
}
|
|
attempted = true;
|
|
for (const candidate of candidates) {
|
|
try {
|
|
loaded = require(candidate);
|
|
return loaded;
|
|
} catch {
|
|
// Try source/runtime candidates in order.
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
}
|
|
|
|
const loadCurrentSnapshotModule = createModuleLoader([
|
|
"./current-plugin-metadata-snapshot.js",
|
|
"./current-plugin-metadata-snapshot.ts",
|
|
]) as () => CurrentSnapshotModule | null;
|
|
const loadSnapshotLoaderModule = createModuleLoader([
|
|
"./plugin-metadata-snapshot.js",
|
|
"./plugin-metadata-snapshot.ts",
|
|
]) as () => SnapshotLoaderModule | null;
|
|
|
|
/** Reads the current plugin metadata snapshot, loading the snapshot graph lazily. */
|
|
export function getCurrentPluginMetadataSnapshotRuntime(
|
|
params: Parameters<CurrentSnapshotModule["getCurrentPluginMetadataSnapshot"]>[0],
|
|
): ReturnType<CurrentSnapshotModule["getCurrentPluginMetadataSnapshot"]> {
|
|
const reader =
|
|
snapshotReaderSlot.getCurrentPluginMetadataSnapshot ??
|
|
loadCurrentSnapshotModule()?.getCurrentPluginMetadataSnapshot;
|
|
return reader?.(params) ?? undefined;
|
|
}
|
|
|
|
/**
|
|
* Resolves a plugin metadata snapshot, or undefined when the metadata system
|
|
* is unavailable (cold test workers without a CJS TS hook); callers treat that
|
|
* as "no manifest policies exist".
|
|
*/
|
|
export function resolvePluginMetadataSnapshotRuntime(
|
|
params: Parameters<SnapshotLoaderModule["resolvePluginMetadataSnapshot"]>[0],
|
|
): ReturnType<SnapshotLoaderModule["resolvePluginMetadataSnapshot"]> | undefined {
|
|
const resolver =
|
|
snapshotReaderSlot.resolvePluginMetadataSnapshot ??
|
|
loadSnapshotLoaderModule()?.resolvePluginMetadataSnapshot;
|
|
return resolver?.(params);
|
|
}
|