mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-26 01:11:37 +00:00
fix(plugins): preserve live hook registry during gateway runs
This commit is contained in:
@@ -159,6 +159,7 @@ function getHooksForNameAndPlugin<K extends PluginHookName>(
|
||||
export function createHookRunner(registry: PluginRegistry, options: HookRunnerOptions = {}) {
|
||||
const logger = options.logger;
|
||||
const catchErrors = options.catchErrors ?? true;
|
||||
const hookCheckpointLogsEnabled = process.env.OPENCLAW_PLUGIN_CHECKPOINTS === "1";
|
||||
|
||||
const mergeBeforeModelResolve = (
|
||||
acc: PluginHookBeforeModelResolveResult | undefined,
|
||||
@@ -250,9 +251,17 @@ export function createHookRunner(registry: PluginRegistry, options: HookRunnerOp
|
||||
}
|
||||
|
||||
logger?.debug?.(`[hooks] running ${hookName} (${hooks.length} handlers)`);
|
||||
if (hookCheckpointLogsEnabled) {
|
||||
logger?.warn(
|
||||
`[hooks][checkpoints] dispatch ${hookName} handlers=${hooks.map((hook) => hook.pluginId).join(",")}`,
|
||||
);
|
||||
}
|
||||
|
||||
const promises = hooks.map(async (hook) => {
|
||||
try {
|
||||
if (hookCheckpointLogsEnabled) {
|
||||
logger?.warn(`[hooks][checkpoints] invoke ${hookName} plugin=${hook.pluginId}`);
|
||||
}
|
||||
await (hook.handler as (event: unknown, ctx: unknown) => Promise<void>)(event, ctx);
|
||||
} catch (err) {
|
||||
handleHookError({ hookName, pluginId: hook.pluginId, error: err });
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { resolveGlobalSingleton } from "../shared/global-singleton.js";
|
||||
import { createEmptyPluginRegistry } from "./registry-empty.js";
|
||||
import type { PluginRegistry } from "./registry.js";
|
||||
|
||||
@@ -12,15 +11,33 @@ type RegistryState = {
|
||||
version: number;
|
||||
};
|
||||
|
||||
const state = resolveGlobalSingleton<RegistryState>(REGISTRY_STATE, () => ({
|
||||
registry: createEmptyPluginRegistry(),
|
||||
httpRouteRegistry: null,
|
||||
httpRouteRegistryPinned: false,
|
||||
key: null,
|
||||
version: 0,
|
||||
}));
|
||||
const state: RegistryState = (() => {
|
||||
const globalState = globalThis as typeof globalThis & {
|
||||
[REGISTRY_STATE]?: RegistryState;
|
||||
};
|
||||
if (!globalState[REGISTRY_STATE]) {
|
||||
globalState[REGISTRY_STATE] = {
|
||||
registry: createEmptyPluginRegistry(),
|
||||
httpRouteRegistry: null,
|
||||
httpRouteRegistryPinned: false,
|
||||
key: null,
|
||||
version: 0,
|
||||
};
|
||||
}
|
||||
return globalState[REGISTRY_STATE];
|
||||
})();
|
||||
|
||||
export function setActivePluginRegistry(registry: PluginRegistry, cacheKey?: string) {
|
||||
if (process.env.OPENCLAW_PLUGIN_CHECKPOINTS === "1") {
|
||||
const stack = new Error().stack
|
||||
?.split("\n")
|
||||
.slice(2, 5)
|
||||
.map((line) => line.trim())
|
||||
.join(" | ");
|
||||
console.warn(
|
||||
`[plugins][checkpoints] activate registry key=${cacheKey ?? "none"} plugins=${registry.plugins.length} typedHooks=${registry.typedHooks.length}${stack ? ` caller=${stack}` : ""}`,
|
||||
);
|
||||
}
|
||||
state.registry = registry;
|
||||
if (!state.httpRouteRegistryPinned) {
|
||||
state.httpRouteRegistry = registry;
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { PluginRegistry } from "./registry.js";
|
||||
import type { OpenClawPluginServiceContext, PluginLogger } from "./types.js";
|
||||
|
||||
const log = createSubsystemLogger("plugins");
|
||||
const pluginCheckpointLogsEnabled = process.env.OPENCLAW_PLUGIN_CHECKPOINTS === "1";
|
||||
|
||||
function createPluginLogger(): PluginLogger {
|
||||
return {
|
||||
@@ -47,8 +48,18 @@ export async function startPluginServices(params: {
|
||||
|
||||
for (const entry of params.registry.services) {
|
||||
const service = entry.service;
|
||||
const typedHookCountBefore = params.registry.typedHooks.length;
|
||||
try {
|
||||
await service.start(serviceContext);
|
||||
if (pluginCheckpointLogsEnabled) {
|
||||
const newTypedHooks = params.registry.typedHooks
|
||||
.slice(typedHookCountBefore)
|
||||
.filter((hook) => hook.pluginId === entry.pluginId)
|
||||
.map((hook) => hook.hookName);
|
||||
log.warn(
|
||||
`[plugins][checkpoints] service started (${service.id}, plugin=${entry.pluginId}) typedHooksAdded=${newTypedHooks.length}${newTypedHooks.length > 0 ? ` hooks=${newTypedHooks.join(",")}` : ""}`,
|
||||
);
|
||||
}
|
||||
running.push({
|
||||
id: service.id,
|
||||
stop: service.stop ? () => service.stop?.(serviceContext) : undefined,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { applyTestPluginDefaults, normalizePluginsConfig } from "./config-state.js";
|
||||
import { loadOpenClawPlugins } from "./loader.js";
|
||||
import { createPluginLoaderLogger } from "./logger.js";
|
||||
import { getActivePluginRegistry, getActivePluginRegistryKey } from "./runtime.js";
|
||||
import type { OpenClawPluginToolContext } from "./types.js";
|
||||
|
||||
const log = createSubsystemLogger("plugins");
|
||||
@@ -59,17 +60,21 @@ export function resolvePluginTools(params: {
|
||||
return [];
|
||||
}
|
||||
|
||||
const registry = loadOpenClawPlugins({
|
||||
config: effectiveConfig,
|
||||
workspaceDir: params.context.workspaceDir,
|
||||
runtimeOptions: params.allowGatewaySubagentBinding
|
||||
? {
|
||||
allowGatewaySubagentBinding: true,
|
||||
}
|
||||
: undefined,
|
||||
env,
|
||||
logger: createPluginLoaderLogger(log),
|
||||
});
|
||||
const activeRegistry = getActivePluginRegistry();
|
||||
const registry =
|
||||
getActivePluginRegistryKey() && activeRegistry
|
||||
? activeRegistry
|
||||
: loadOpenClawPlugins({
|
||||
config: effectiveConfig,
|
||||
workspaceDir: params.context.workspaceDir,
|
||||
runtimeOptions: params.allowGatewaySubagentBinding
|
||||
? {
|
||||
allowGatewaySubagentBinding: true,
|
||||
}
|
||||
: undefined,
|
||||
env,
|
||||
logger: createPluginLoaderLogger(log),
|
||||
});
|
||||
|
||||
const tools: AnyAgentTool[] = [];
|
||||
const existing = params.existingToolNames ?? new Set<string>();
|
||||
|
||||
Reference in New Issue
Block a user