Files
openclaw/src/plugins/plugin-lookup-table.ts
Peter Steinberger 90e465833b feat(gateway): durable cloud worker environments, provider SDK contract, and lifecycle RPCs (#104401)
* docs(plan): add cloud workers design plan

* feat(plugin-sdk): add cloud worker provider foundations

* feat(protocol): add worker environment lifecycle shapes

* feat(gateway): persist worker environment lifecycles

* test(gateway): pin environment inventory assertion for damaged worker store

* style(cloud-workers): satisfy lint and docs formatting

* fix(gateway): narrow worker environment type boundaries

* chore(plugin-sdk): account for WorkerProvider surface growth

* docs: regenerate docs map
2026-07-11 04:54:27 -07:00

121 lines
4.1 KiB
TypeScript

/** Builds plugin lookup tables keyed by manifest ids, channels, providers, and commands. */
import type { OpenClawConfig } from "../config/types.openclaw.js";
import {
createGatewayStartupMetadataPluginIdScope,
isMetadataSnapshotScopedForGatewayStartup,
resolveGatewayStartupPluginPlanFromRegistry,
type GatewayStartupPluginPlan,
} from "./channel-plugin-ids.js";
import {
isPluginMetadataSnapshotCompatible,
resolvePluginMetadataSnapshot,
type PluginMetadataSnapshot,
} from "./plugin-metadata-snapshot.js";
import type { PluginRegistrySnapshot } from "./plugin-registry-snapshot.js";
import { normalizeWorkerProviderIds } from "./worker-provider-registry.js";
export type PluginLookUpTableMetrics = PluginMetadataSnapshot["metrics"] & {
startupPlanMs: number;
startupPluginCount: number;
deferredChannelPluginCount: number;
};
export type PluginLookUpTable = PluginMetadataSnapshot & {
startup: GatewayStartupPluginPlan;
workerProviderIds: readonly string[];
metrics: PluginLookUpTableMetrics;
};
export type LoadPluginLookUpTableParams = {
config: OpenClawConfig;
activationSourceConfig?: OpenClawConfig;
workspaceDir?: string;
env: NodeJS.ProcessEnv;
index?: PluginRegistrySnapshot;
metadataSnapshot?: PluginMetadataSnapshot;
workerProviderIds?: readonly string[];
};
let lookupTableMemoBySnapshot = new WeakMap<
PluginMetadataSnapshot,
Map<string, PluginLookUpTable>
>();
export function clearPluginLookUpTableMemoForTest(): void {
lookupTableMemoBySnapshot = new WeakMap<PluginMetadataSnapshot, Map<string, PluginLookUpTable>>();
}
export function loadPluginLookUpTable(params: LoadPluginLookUpTableParams): PluginLookUpTable {
const requestedSnapshotConfig = params.activationSourceConfig ?? params.config;
const workerProviderIds = normalizeWorkerProviderIds(params.workerProviderIds ?? []);
const pluginIdScope = createGatewayStartupMetadataPluginIdScope({
config: params.config,
...(params.activationSourceConfig !== undefined
? { activationSourceConfig: params.activationSourceConfig }
: {}),
env: params.env,
workerProviderIds,
});
const metadataSnapshot =
params.metadataSnapshot &&
isPluginMetadataSnapshotCompatible({
snapshot: params.metadataSnapshot,
config: requestedSnapshotConfig,
env: params.env,
allowScopedSnapshot: true,
workspaceDir: params.workspaceDir,
index: params.index,
}) &&
isMetadataSnapshotScopedForGatewayStartup({
metadataSnapshot: params.metadataSnapshot,
pluginIdScope,
})
? params.metadataSnapshot
: resolvePluginMetadataSnapshot({
config: requestedSnapshotConfig,
workspaceDir: params.workspaceDir,
env: params.env,
allowWorkspaceScopedCurrent: params.workspaceDir === undefined,
...(params.index ? { index: params.index } : {}),
pluginIdScope,
});
const memoKey = pluginIdScope.key;
const memo = lookupTableMemoBySnapshot.get(metadataSnapshot)?.get(memoKey);
if (memo) {
return memo;
}
const { index, manifestRegistry } = metadataSnapshot;
const startupPlanStartedAt = performance.now();
const startup = resolveGatewayStartupPluginPlanFromRegistry({
config: params.config,
...(params.activationSourceConfig !== undefined
? { activationSourceConfig: params.activationSourceConfig }
: {}),
env: params.env,
index,
manifestRegistry,
workerProviderIds,
});
const startupPlanMs = performance.now() - startupPlanStartedAt;
const table: PluginLookUpTable = {
...metadataSnapshot,
startup,
workerProviderIds,
metrics: {
...metadataSnapshot.metrics,
startupPlanMs,
totalMs: metadataSnapshot.metrics.totalMs + startupPlanMs,
startupPluginCount: startup.pluginIds.length,
deferredChannelPluginCount: startup.configuredDeferredChannelPluginIds.length,
},
};
let memoByKey = lookupTableMemoBySnapshot.get(metadataSnapshot);
if (!memoByKey) {
memoByKey = new Map();
lookupTableMemoBySnapshot.set(metadataSnapshot, memoByKey);
}
memoByKey.set(memoKey, table);
return table;
}