mirror of
http://192.168.0.88:13333/lywsvip/openclaw-zero-token.git
synced 2026-05-08 08:08:33 +08:00
Major upgrade from e26988a38 to upstream v2026.3.28 (f9b107928).
Key changes:
- Upstream src/, ui/, extensions/ (89 bundled extensions)
- Zero-token web providers preserved in src/zero-token/
- AskOnce plugin restored and registered as CLI command
- Added missing packages: @anthropic-ai/vertex-sdk, @modelcontextprotocol/sdk
- Fixed tsconfig rootDir, skipLibCheck for plugin-sdk DTS build
- Added askonce to bundled plugin metadata and package.json exports
- Fixed AskOnce CLI command registration (missing commands metadata)
- Restored AskOnce adapter imports (correct 5-level relative paths)
- Removed stale migration artifacts from root directory
103 lines
2.8 KiB
TypeScript
103 lines
2.8 KiB
TypeScript
/**
|
|
* Global Plugin Hook Runner
|
|
*
|
|
* Singleton hook runner that's initialized when plugins are loaded
|
|
* and can be called from anywhere in the codebase.
|
|
*/
|
|
|
|
import { createSubsystemLogger } from "../logging/subsystem.js";
|
|
import { resolveGlobalSingleton } from "../shared/global-singleton.js";
|
|
import { createHookRunner, type HookRunner } from "./hooks.js";
|
|
import type { PluginRegistry } from "./registry.js";
|
|
import type { PluginHookGatewayContext, PluginHookGatewayStopEvent } from "./types.js";
|
|
|
|
type HookRunnerGlobalState = {
|
|
hookRunner: HookRunner | null;
|
|
registry: PluginRegistry | null;
|
|
};
|
|
|
|
const hookRunnerGlobalStateKey = Symbol.for("openclaw.plugins.hook-runner-global-state");
|
|
const getState = () =>
|
|
resolveGlobalSingleton<HookRunnerGlobalState>(hookRunnerGlobalStateKey, () => ({
|
|
hookRunner: null,
|
|
registry: null,
|
|
}));
|
|
|
|
const getLog = () => createSubsystemLogger("plugins");
|
|
|
|
/**
|
|
* Initialize the global hook runner with a plugin registry.
|
|
* Called once when plugins are loaded during gateway startup.
|
|
*/
|
|
export function initializeGlobalHookRunner(registry: PluginRegistry): void {
|
|
const state = getState();
|
|
const log = getLog();
|
|
state.registry = registry;
|
|
state.hookRunner = createHookRunner(registry, {
|
|
logger: {
|
|
debug: (msg) => log.debug(msg),
|
|
warn: (msg) => log.warn(msg),
|
|
error: (msg) => log.error(msg),
|
|
},
|
|
catchErrors: true,
|
|
});
|
|
|
|
const hookCount = registry.hooks.length;
|
|
if (hookCount > 0) {
|
|
log.info(`hook runner initialized with ${hookCount} registered hooks`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the global hook runner.
|
|
* Returns null if plugins haven't been loaded yet.
|
|
*/
|
|
export function getGlobalHookRunner(): HookRunner | null {
|
|
return getState().hookRunner;
|
|
}
|
|
|
|
/**
|
|
* Get the global plugin registry.
|
|
* Returns null if plugins haven't been loaded yet.
|
|
*/
|
|
export function getGlobalPluginRegistry(): PluginRegistry | null {
|
|
return getState().registry;
|
|
}
|
|
|
|
/**
|
|
* Check if any hooks are registered for a given hook name.
|
|
*/
|
|
export function hasGlobalHooks(hookName: Parameters<HookRunner["hasHooks"]>[0]): boolean {
|
|
return getState().hookRunner?.hasHooks(hookName) ?? false;
|
|
}
|
|
|
|
export async function runGlobalGatewayStopSafely(params: {
|
|
event: PluginHookGatewayStopEvent;
|
|
ctx: PluginHookGatewayContext;
|
|
onError?: (err: unknown) => void;
|
|
}): Promise<void> {
|
|
const log = getLog();
|
|
const hookRunner = getGlobalHookRunner();
|
|
if (!hookRunner?.hasHooks("gateway_stop")) {
|
|
return;
|
|
}
|
|
try {
|
|
await hookRunner.runGatewayStop(params.event, params.ctx);
|
|
} catch (err) {
|
|
if (params.onError) {
|
|
params.onError(err);
|
|
return;
|
|
}
|
|
log.warn(`gateway_stop hook failed: ${String(err)}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reset the global hook runner (for testing).
|
|
*/
|
|
export function resetGlobalHookRunner(): void {
|
|
const state = getState();
|
|
state.hookRunner = null;
|
|
state.registry = null;
|
|
}
|