级联配置解析

OpenClaw 使用 5 层级联配置系统实现灵活的运行时配置。

关键文件

  • src/config/runtime-overrides.ts (92 行): 内存中的运行时覆盖
  • src/config/io.ts: 基于文件的配置加载和合并
  • src/config/env-vars.ts: 环境变量应用

解析层(从高到低优先级)

第 1 层:运行时覆盖(内存中)

  • 最高优先级
  • 通过 setConfigOverride(path, value) 设置
  • 仅持久化在内存中,不写入配置文件
  • 用于执行期间的临时覆盖

来自 src/config/runtime-overrides.ts:

let overrides: OverrideTree = {};

export function setConfigOverride(pathRaw: string, value: unknown): {
  ok: boolean;
  error?: string;
} {
  const parsed = parseConfigPath(pathRaw);
  if (!parsed.ok || !parsed.path) {
    return { ok: false, error: parsed.error ?? "Invalid path." };
  }
  setConfigValueAtPath(overrides, parsed.path, sanitizeOverrideValue(value));
  return { ok: true };
}

第 2 层:环境变量

  • process.env 应用,带 OPENCLAW_* 前缀
  • 配置可通过 config.env 定义额外的环境变量
  • 环境变量在配置加载期间解析

第 3 层:Agent 特定配置

  • 作用域限定于特定 agent ID 的配置
  • config.agents[agentId] 中定义
  • 与更高和更低层合并

第 4 层:会话级配置

  • 特定于会话的配置
  • 存储在会话元数据中
  • 覆盖全局默认值,但服从更高层

第 5 层:全局默认值

  • 最低优先级,回退值
  • src/agents/defaults.tssrc/config/defaults.ts 中定义
  • 当没有更高层提供值时应用

合并策略

对象的深度合并

function mergeOverrides(base: unknown, override: unknown): unknown {
  if (!isPlainObject(base) || !isPlainObject(override)) {
    return override; // 非对象:完全替换
  }
  const next: OverrideTree = { ...base };
  for (const [key, value] of Object.entries(override)) {
    if (value === undefined || isBlockedObjectKey(key)) {
      continue; // 跳过 undefined 和原型污染键
    }
    next[key] = mergeOverrides((base as OverrideTree)[key], value);
  }
  return next;
}

数组:完全替换

  • 数组逐元素合并
  • 更高优先级的数组完全替换更低优先级的数组

原型污染键被阻止

来自 src/config/prototype-keys.ts:

const BLOCKED_KEYS = new Set([
  "__proto__",
  "constructor",
  "prototype",
]);

export function isBlockedObjectKey(key: string): boolean {
  return BLOCKED_KEYS.has(key);
}

工具策略级联

工具策略使用类似的 7 层级联允许列表系统:

  1. 运行时覆盖
  2. 环境变量
  3. Agent 特定策略
  4. 会话级策略
  5. 用户级策略
  6. 工具特定默认值
  7. 全局默认值

每一层都是与更低层合并的允许列表。

配置热重载

OpenClaw 支持通过 chokidar 热重载配置文件:

  • 监视器: 监控配置文件的更改
  • 去抖: 300 毫秒延迟以批处理快速更改
  • 模式:
    • off: 不监视
    • restart: 更改时重启进程
    • hot: 就地重载配置
    • hybrid: 带重启回退的热重载

交叉引用