|
| 1 | +import path from "node:path"; |
1 | 2 | import { formatCliCommand } from "../cli/command-format.js"; |
2 | 3 | import { findLegacyConfigIssues } from "../config/legacy.js"; |
3 | 4 | import { CONFIG_PATH } from "../config/paths.js"; |
@@ -26,6 +27,30 @@ function hasLegacyInternalHookHandlers(raw: unknown): boolean { |
26 | 27 | return Array.isArray(handlers) && handlers.length > 0; |
27 | 28 | } |
28 | 29 |
|
| 30 | +function collectInvalidHookTransformsDirWarnings( |
| 31 | + cfg: OpenClawConfig, |
| 32 | + configPath: string, |
| 33 | +): string[] { |
| 34 | + const transformsDir = cfg.hooks?.transformsDir?.trim(); |
| 35 | + if (!transformsDir) { |
| 36 | + return []; |
| 37 | + } |
| 38 | + const configDir = path.dirname(configPath); |
| 39 | + const transformsRoot = path.join(configDir, "hooks", "transforms"); |
| 40 | + const resolved = path.isAbsolute(transformsDir) |
| 41 | + ? path.resolve(transformsDir) |
| 42 | + : path.resolve(transformsRoot, transformsDir); |
| 43 | + const relative = path.relative(transformsRoot, resolved); |
| 44 | + const escapesRoot = |
| 45 | + relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative); |
| 46 | + if (!escapesRoot) { |
| 47 | + return []; |
| 48 | + } |
| 49 | + return [ |
| 50 | + `- hooks.transformsDir: ${transformsDir} is outside ${transformsRoot}. Hook transform modules must live under ${transformsRoot}; move custom transforms there or remove hooks.transformsDir.`, |
| 51 | + ]; |
| 52 | +} |
| 53 | + |
29 | 54 | function collectConfiguredChannelIds(cfg: OpenClawConfig): string[] { |
30 | 55 | const channels = |
31 | 56 | cfg.channels && typeof cfg.channels === "object" && !Array.isArray(cfg.channels) |
@@ -111,6 +136,10 @@ export async function loadAndMaybeMigrateDoctorConfig(params: { |
111 | 136 | "Legacy config keys detected", |
112 | 137 | ); |
113 | 138 | } |
| 139 | + const hookTransformsDirWarnings = collectInvalidHookTransformsDirWarnings(cfg, snapshot.path); |
| 140 | + if (hookTransformsDirWarnings.length > 0) { |
| 141 | + note(sanitizeDoctorNote(hookTransformsDirWarnings.join("\n")), "Doctor warnings"); |
| 142 | + } |
114 | 143 |
|
115 | 144 | const normalized = normalizeCompatibilityConfigValues(candidate); |
116 | 145 | if (normalized.changes.length > 0) { |
|
0 commit comments