function safeLogValue(value: string): string { return sanitizeForLog(value);
}
function maybeWarnTrustedHookSource(source: string): void { if (source === "openclaw-workspace") {
log.warn( "Loading workspace hook code into the gateway process. Workspace hooks are trusted local code.",
); return;
} if (source === "openclaw-managed") {
log.warn( "Loading managed hook code into the gateway process. Managed hooks are trusted local code.",
);
}
}
function resetLoadedInternalHooks(): void { while (loadedHookRegistrations.length > 0) { const registration = loadedHookRegistrations.pop(); if (!registration) { continue;
}
unregisterInternalHook(registration.event, registration.handler);
}
}
for (const entry of eligible) { try { const hookBaseDir = resolveExistingRealpath(entry.hook.baseDir); if (!hookBaseDir) {
log.error(
`Hook '${safeLogValue(entry.hook.name)}' base directory is no longer readable: ${safeLogValue(entry.hook.baseDir)}`,
); continue;
} const opened = await openBoundaryFile({
absolutePath: entry.hook.handlerPath,
rootPath: hookBaseDir,
boundaryLabel: "hook directory",
}); if (!opened.ok) {
log.error(
`Hook '${safeLogValue(entry.hook.name)}' handler path fails boundary checks: ${safeLogValue(entry.hook.handlerPath)}`,
); continue;
} const safeHandlerPath = opened.path;
fs.closeSync(opened.fd);
maybeWarnTrustedHookSource(entry.hook.source);
// Import handler module — only cache-bust mutable (workspace/managed) hooks const importUrl = buildImportUrl(safeHandlerPath, entry.hook.source); const mod = (await import(importUrl)) as Record<string, unknown>;
// Get handler function (default or named export) const exportName = entry.metadata?.export ?? "default"; const handler = resolveFunctionModuleExport<InternalHookHandler>({
mod,
exportName,
});
if (!handler) {
log.error(
`Handler '${safeLogValue(exportName)}' from ${safeLogValue(entry.hook.name)} is not a function`,
); continue;
}
// Register for all events listed in metadata const events = entry.metadata?.events ?? []; if (events.length === 0) {
log.warn(`Hook '${safeLogValue(entry.hook.name)}' has no events defined in metadata`); continue;
}
for (const event of events) {
registerInternalHook(event, handler);
loadedHookRegistrations.push({ event, handler });
}
// 2. Load legacy config handlers (backwards compatibility) const handlers = getLegacyInternalHookHandlers(cfg); for (const handlerConfig of handlers) { try { // Legacy handler paths: keep them workspace-relative. const rawModule = handlerConfig.module.trim(); if (!rawModule) {
log.error("Handler module path is empty"); continue;
} if (path.isAbsolute(rawModule)) {
log.error(
`Handler module path must be workspace-relative (got absolute path): ${safeLogValue(rawModule)}`,
); continue;
} const baseDir = path.resolve(workspaceDir); const modulePath = path.resolve(baseDir, rawModule); const baseDirReal = resolveExistingRealpath(baseDir); if (!baseDirReal) {
log.error(
`Workspace directory is no longer readable while loading hooks: ${safeLogValue(baseDir)}`,
); continue;
} const modulePathSafe = resolveExistingRealpath(modulePath); if (!modulePathSafe) {
log.error(
`Handler module path could not be resolved with realpath: ${safeLogValue(rawModule)}`,
); continue;
} const rel = path.relative(baseDirReal, modulePathSafe); if (!rel || rel.startsWith("..") || path.isAbsolute(rel)) {
log.error(`Handler module path must stay within workspaceDir: ${safeLogValue(rawModule)}`); continue;
} const opened = await openBoundaryFile({
absolutePath: modulePathSafe,
rootPath: baseDirReal,
boundaryLabel: "workspace directory",
}); if (!opened.ok) {
log.error(
`Handler module path fails boundary checks under workspaceDir: ${safeLogValue(rawModule)}`,
); continue;
} const safeModulePath = opened.path;
fs.closeSync(opened.fd);
log.warn(
`Loading legacy internal hook module from workspace path ${safeLogValue(rawModule)}. Legacy hook modules are trusted local code.`,
);
// Legacy handlers are always workspace-relative, so use mtime-based cache busting const importUrl = buildImportUrl(safeModulePath, "openclaw-workspace"); const mod = (await import(importUrl)) as Record<string, unknown>;
// Get the handler function const exportName = handlerConfig.export ?? "default"; const handler = resolveFunctionModuleExport<InternalHookHandler>({
mod,
exportName,
});
if (!handler) {
log.error(
`Handler '${safeLogValue(exportName)}' from ${safeLogValue(modulePath)} is not a function`,
); continue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.