mirror of https://github.com/openclaw/openclaw.git
96 lines
2.6 KiB
TypeScript
96 lines
2.6 KiB
TypeScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import type { OpenClawConfig } from "../config/config.js";
|
|
import { createSubsystemLogger } from "../logging/subsystem.js";
|
|
import {
|
|
normalizePluginsConfig,
|
|
resolveEffectiveEnableState,
|
|
resolveMemorySlotDecision,
|
|
} from "../plugins/config-state.js";
|
|
import { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";
|
|
import { isPathInsideWithRealpath } from "../security/scan-paths.js";
|
|
|
|
const log = createSubsystemLogger("hooks");
|
|
|
|
export type PluginHookDirEntry = {
|
|
dir: string;
|
|
pluginId: string;
|
|
};
|
|
|
|
export function resolvePluginHookDirs(params: {
|
|
workspaceDir: string | undefined;
|
|
config?: OpenClawConfig;
|
|
}): PluginHookDirEntry[] {
|
|
const workspaceDir = (params.workspaceDir ?? "").trim();
|
|
if (!workspaceDir) {
|
|
return [];
|
|
}
|
|
const registry = loadPluginManifestRegistry({
|
|
workspaceDir,
|
|
config: params.config,
|
|
});
|
|
if (registry.plugins.length === 0) {
|
|
return [];
|
|
}
|
|
|
|
const normalizedPlugins = normalizePluginsConfig(params.config?.plugins);
|
|
const memorySlot = normalizedPlugins.slots.memory;
|
|
let selectedMemoryPluginId: string | null = null;
|
|
const seen = new Set<string>();
|
|
const resolved: PluginHookDirEntry[] = [];
|
|
|
|
for (const record of registry.plugins) {
|
|
if (!record.hooks || record.hooks.length === 0) {
|
|
continue;
|
|
}
|
|
const enableState = resolveEffectiveEnableState({
|
|
id: record.id,
|
|
origin: record.origin,
|
|
config: normalizedPlugins,
|
|
rootConfig: params.config,
|
|
});
|
|
if (!enableState.enabled) {
|
|
continue;
|
|
}
|
|
|
|
const memoryDecision = resolveMemorySlotDecision({
|
|
id: record.id,
|
|
kind: record.kind,
|
|
slot: memorySlot,
|
|
selectedId: selectedMemoryPluginId,
|
|
});
|
|
if (!memoryDecision.enabled) {
|
|
continue;
|
|
}
|
|
if (memoryDecision.selected && record.kind === "memory") {
|
|
selectedMemoryPluginId = record.id;
|
|
}
|
|
|
|
for (const raw of record.hooks) {
|
|
const trimmed = raw.trim();
|
|
if (!trimmed) {
|
|
continue;
|
|
}
|
|
const candidate = path.resolve(record.rootDir, trimmed);
|
|
if (!fs.existsSync(candidate)) {
|
|
log.warn(`plugin hook path not found (${record.id}): ${candidate}`);
|
|
continue;
|
|
}
|
|
if (!isPathInsideWithRealpath(record.rootDir, candidate, { requireRealpath: true })) {
|
|
log.warn(`plugin hook path escapes plugin root (${record.id}): ${candidate}`);
|
|
continue;
|
|
}
|
|
if (seen.has(candidate)) {
|
|
continue;
|
|
}
|
|
seen.add(candidate);
|
|
resolved.push({
|
|
dir: candidate,
|
|
pluginId: record.id,
|
|
});
|
|
}
|
|
}
|
|
|
|
return resolved;
|
|
}
|