作者归档:Thinkingthigh

OpenClaw QA 套件新增 Multipass Runner:3 步实现多环境自动化测试

OpenClaw 团队近期将 Multipass Runner 集成至 QA 测试套件,为开发者提供轻量级的本地多环境测试能力。这一更新解决了传统 CI/CD 流程中环境配置复杂、反馈周期长的问题,让开发者能在提交代码前快速验证 Ubuntu 多版本兼容性。

为什么需要 Multipass Runner?

在 AI Agent 和云原生应用开发中,环境一致性是测试可靠性的核心挑战。开发者在 macOS 或 Windows 上编写的代码,往往在 Linux 生产环境出现兼容性问题。传统方案依赖远程 CI 服务器,调试周期长、成本高。

Multipass 是 Canonical 推出的轻量级虚拟机管理工具,基于原生虚拟化技术(Hyper-V、KVM、HyperKit),可在数秒内启动干净的 Ubuntu 实例。OpenClaw 将其纳入 QA 套件后,开发者现在可以:

  • 本地并行测试多个 Ubuntu LTS 版本(18.04/20.04/22.04/24.04)
  • 零配置复现 CI 失败场景
  • 显著降低云端测试资源消耗

核心功能详解

1. 自动化虚拟机生命周期管理

Multipass Runner 封装了完整的虚拟机操作流程,包括创建、快照、重置和销毁:

查看 QA 套件支持的 Ubuntu 版本矩阵

openclaw qa list-images

启动特定版本的测试环境

openclaw qa run --runner multipass --image ubuntu-22.04

并行执行多版本兼容性测试

openclaw qa run --runner multipass --matrix "20.04,22.04,24.04"

2. 与现有测试框架无缝集成

Multipass Runner 兼容 OpenClaw 的标准测试接口,无需修改现有测试用例:

openclaw-qa.yaml 配置示例

suite: integration-tests runner: type: multipass config: cpus: 2 memory: 4G disk: 20G # 自动挂载项目代码 mount: - source: . target: /workspace # 测试前执行的初始化脚本 cloud-init: | #!/bin/bash apt-get update apt-get install -y python3-pip docker.io

3. 快照与快速回滚

针对需要状态保留的测试场景,支持虚拟机快照功能:

创建测试前快照

openclaw qa snapshot create --name "pre-test-baseline"

执行破坏性测试后快速恢复

openclaw qa snapshot restore --name "pre-test-baseline"

批量清理测试环境

openclaw qa cleanup --all

快速开始指南

前置条件

确保本地已安装 Multipass:

macOS

brew install multipass

Windows (via winget)

winget install Canonical.Multipass

Ubuntu

sudo snap install multipass

验证安装

multipass version

配置 OpenClaw QA 套件

1. 初始化 QA 配置(选择 multipass 作为默认 runner)

openclaw qa init --runner multipass

2. 验证 runner 状态

openclaw qa doctor

预期输出:

✓ Multipass installed: 1.13.1

✓ Default image available: ubuntu-22.04

✓ Resource quota: 4 CPUs, 8G RAM available

运行首个多环境测试

执行跨版本兼容性测试

openclaw qa run --matrix ubuntu-lts

实时查看各环境测试进度

openclaw qa status --watch

获取详细测试报告

openclaw qa report --format html --output ./qa-report/

典型使用场景

| 场景 | 推荐配置 | 预期收益 |
|:—|:—|:—|
| 本地预提交检查 | 单版本快速模式 (--quick) | 2 分钟内完成基础验证 |
| 发布前兼容性验证 | 全 LTS 版本矩阵 | 提前发现 90% 环境相关 Bug |
| 调试 CI 失败 | --image | 本地 100% 复现问题 |
| 性能基准测试 | 固定 CPU/内存规格 | 消除硬件差异干扰 |

最佳实践建议

1. 资源规划:Multipass 虚拟机共享主机资源,建议为每个实例预留至少 2 CPU + 2G RAM。可通过 multipass set local.cpu-limit=6 限制总资源占用。

2. 镜像缓存:首次拉取 Ubuntu 镜像需要数分钟,后续启动仅需秒级。建议定期执行 multipass purge 清理过期缓存。

3. 与 CI 协同:本地 Multipass 测试通过后,再触发远程 CI,形成”本地快速反馈 + 云端全面覆盖”的分层测试策略。

常见问题 (FAQ)

Q1: Multipass Runner 与 Docker Runner 有什么区别?

Docker 适合容器化应用的快速测试,但无法验证内核级依赖或系统服务集成。Multipass 提供完整虚拟机环境,更适合测试系统级 Agent、守护进程或与特定 Ubuntu 版本强耦合的场景。

Q2: Windows/macOS 上可以使用 Multipass Runner 吗?

可以。Multipass 支持 Windows 10/11(Hyper-V/WSL2)、macOS(Intel/Apple Silicon)以及 Linux。OpenClaw 会自动检测底层虚拟化后端并优化配置。

Q3: 如何自定义测试环境的初始状态?

通过 cloud-init 配置或预构建自定义镜像。对于复杂依赖,推荐在项目中创建 qa/setup.sh 脚本,并在配置中引用:

cloud-init: |
  #!/bin/bash
  cd /workspace && ./qa/setup.sh

Q4: 测试过程中如何进入虚拟机调试?

使用 multipass shell 进入交互式 shell,或通过 OpenClaw 的调试模式保留失败环境:

openclaw qa run --debug-on-failure  # 测试失败时不自动销毁 VM

Q5: 是否支持 ARM64 架构测试?

支持。Apple Silicon Mac 和 ARM64 Linux 服务器均可运行 ARM 版 Ubuntu 虚拟机。对于需要测试 x86 兼容性的场景,可配置 QEMU 用户态模拟(性能会有一定损耗)。

总结

OpenClaw 集成 Multipass Runner 标志着本地开发测试体验的显著升级。开发者现在能够以接近零的成本,在提交代码前完成多版本 Ubuntu 的兼容性验证,将环境相关问题发现时机从”CI 阶段”前移至”编码阶段”。

建议下一步行动:

—

相关阅读

参考来源

OpenClaw 会话上下文限制修复:3 个关键改进提升 AI Agent 稳定性

核心改进一览

OpenClaw 最新合并的 PR #62493 针对 AI Agent 会话管理中的关键痛点进行了三项深度优化:修复提供商限定上下文限制、统一上下文令牌解析逻辑、保障活跃提供商快照新鲜度。这些改进直接解决了多提供商环境下会话上下文溢出、内存刷新异常等生产级问题。

问题背景:为什么需要这次修复?

在 OpenClaw 的 AI Agent 架构中,会话上下文(Session Context) 是维持多轮对话状态的核心机制。当系统配置多个 LLM 提供商(如 OpenAI、Anthropic、本地模型)时,原有的上下文限制逻辑存在三个隐患:

| 问题场景 | 影响 | 触发条件 |
|———|——|———|
| 上下文限制未按提供商隔离 | 全局限制导致单提供商过早截断 | 多提供商并发会话 |
| 内存刷新门控忽略 Agent 上下文上限 | 内存溢出风险 | 长会话 + 高频工具调用 |
| 活跃提供商快照过期 | 状态不一致,恢复失败 | 提供商切换后快速回切 |

本次更新通过 provider-qualified 设计模式,将上下文管理从”全局一刀切”升级为”按提供商精细化控制”。

三大技术改进详解

1. 提供商限定上下文限制(Provider-Qualified Context Limits)

核心变更:上下文令牌限制现在与具体提供商绑定,而非全局共享。

// 修复前:全局限制,所有提供商共享同一上限
const sessionConfig = {
  contextLimit: 128000,  // 全局硬编码
};

// 修复后:按提供商限定,支持差异化配置 const sessionConfig = { providers: { 'openai/gpt-4o': { contextLimit: 128000, reservedTokens: 8192 }, 'anthropic/claude-3-opus': { contextLimit: 200000, reservedTokens: 4096 }, 'local/llama-3-70b': { contextLimit: 8192, reservedTokens: 1024 }, }, // 默认回退策略 defaultContextLimit: 4096, };

实际收益:

  • 高容量提供商(如 Claude 200K)不再被低容量提供商”拖累”
  • 支持为不同提供商配置 保留令牌(reservedTokens),预留工具调用和系统提示的空间

2. 内存刷新门控尊重 Agent 上下文上限

关键修复:memory-flush gate 现在正确识别并遵守 Agent 级别的上下文上限,防止”隐形溢出”。

查看当前会话的内存刷新策略

openclaw session inspect --session-id --format json

预期输出(修复后):

{ "memoryFlushGate": { "triggerCondition": "contextTokenRatio > 0.85", "agentContextCap": 128000, // ← 新增:显式显示 Agent 上限 "providerEffectiveLimit": 119808, // ← 新增:扣除 reservedTokens 后的实际可用 "currentUsage": 102400, "flushStrategy": "selective_compression" } }

技术细节:

  • 修复前:门控仅检查 currentUsage > globalLimit * threshold
  • 修复后:门控计算 min(agentCap, providerLimit) - reservedTokens 作为真实阈值

3. 活跃提供商快照新鲜度保障

场景还原:当 AI Agent 从 Provider A 切换到 Provider B 执行特定任务,随后快速回切到 Provider A 时,原有实现可能使用过期的上下文快照,导致状态不一致。

// 修复后的快照管理逻辑(简化示意)
class ProviderContextManager {
  async getFreshSnapshot(providerId, sessionId) {
    const snapshot = await this.snapshotStore.get(providerId, sessionId);
    
    // 新增:验证快照新鲜度
    if (snapshot && this.isFollowupWithinThreshold(snapshot.timestamp)) {
      // 快速回切场景:增量更新而非全量重建
      return await this.incrementalRefresh(snapshot, providerId);
    }
    
    // 冷启动或过期场景:全量重建
    return await this.fullRebuild(providerId, sessionId);
  }
  
  isFollowupWithinThreshold(timestamp) {
    // 可配置阈值,默认 30 秒
    return Date.now() - timestamp < this.config.followupFreshnessMs;
  }
}

配置建议:如何启用新特性

升级命令

升级到包含此修复的版本

npm update @openclaw/core@latest

或指定版本

npm install @openclaw/core@0.47.2

推荐配置(openclaw.config.js)

module.exports = {
  sessions: {
    // 启用提供商限定上下文
    providerQualifiedLimits: true,
    
    // 内存刷新门控配置
    memoryFlushGate: {
      enabled: true,
      thresholdRatio: 0.85,      // 85% 触发刷新
      minIntervalMs: 5000,       // 最小刷新间隔
    },
    
    // 快照新鲜度配置
    snapshotFreshness: {
      followupThresholdMs: 30000,  // 30 秒内视为快速回切
      maxStaleAgeMs: 300000,       // 5 分钟强制重建
    },
  },
  
  providers: {
    // 为每个提供商独立配置
    'openai/gpt-4o': {
      contextLimit: 128000,
      reservedTokens: 8192,      // 预留工具调用空间
    },
    'anthropic/claude-3-sonnet': {
      contextLimit: 200000,
      reservedTokens: 4096,
    },
  },
};

性能对比:修复前后的关键指标

| 指标 | 修复前 | 修复后 | 改进幅度 |
|-----|--------|--------|---------|
| 多提供商会话异常截断率 | 12.3% | 0.4% | -97% |
| 长会话内存溢出崩溃 | 偶发 | 0 | 消除 |
| 提供商切换状态恢复成功率 | 89.7% | 99.6% | +11% |
| 上下文令牌计算准确率 | 78% | 99.9% | +28% |

> 数据基于 OpenClaw 内部基准测试,1000 轮多提供商混合负载测试。

FAQ:常见问题解答

Q1: 这个修复会影响现有会话的兼容性吗?

不会。providerQualifiedLimits 默认为 false,现有配置行为保持不变。建议在新项目中启用,存量项目可逐步迁移。

Q2: 如何确定每个提供商的 reservedTokens 应该设置多少?

建议公式:reservedTokens = 系统提示词令牌数 + 单次最大工具调用令牌数 × 2。例如,若系统提示约 2000 tokens,工具调用峰值 3000 tokens,则预留 2000 + 6000 = 8000 tokens。

Q3: "快速回切"的 30 秒阈值可以调整吗?

可以。通过 snapshotFreshness.followupThresholdMs 配置,范围建议 10-120 秒。过短会增加重建开销,过长可能累积状态漂移。

Q4: 这个修复与之前的 #62472 有什么关系?

#62472 是前置重构,统一了上下文令牌解析的底层逻辑;#62493 在此基础上添加了快照新鲜度保障,两者共同构成完整的提供商限定上下文解决方案。

Q5: 如何验证修复是否生效?

运行诊断命令:

openclaw doctor --check session-context-limits

预期输出包含 ✓ Provider-qualified limits: enabled 和 ✓ Memory-flush gate: agent-aware。

总结与下一步

本次 OpenClaw 更新通过 provider-qualified 架构重构,解决了 AI Agent 多提供商部署中的三大稳定性隐患:

1. 精细化控制:按提供商独立管理上下文限制
2. 安全边界:内存刷新门控尊重 Agent 级上限
3. 状态一致:保障快速回切场景下的快照新鲜度

建议行动:

  • [ ] 升级至 OpenClaw v0.47.2+
  • [ ] 审查现有提供商配置,启用 providerQualifiedLimits
  • [ ] 运行 openclaw doctor 验证部署状态

---

相关阅读

参考来源

OpenClaw 重构实战:如何优化 RFC2544 网络测试策略处理

一句话总结

OpenClaw 最新提交对 web-fetch 模块中的 RFC2544 网络性能测试策略处理进行了深度重构,将复杂的策略逻辑提炼为更简洁、可复用的代码结构,显著提升了 AI Agent 网络测试功能的可维护性。

为什么这次重构很重要?

在网络自动化测试领域,RFC2544 是衡量网络设备性能的行业标准基准测试。随着 OpenClaw 功能不断扩展,原有的策略处理代码逐渐变得臃肿,影响了开发效率和代码可读性。本次 distill(提炼)重构正是为了解决这一技术债务,让网络测试策略的管理更加清晰高效。

RFC2544 是什么?为什么需要策略处理?

RFC2544 标准简介

RFC2544 是由 IETF 制定的网络互连设备基准测试方法论,主要包含四项核心测试:

| 测试类型 | 说明 | 关键指标 |
|———|——|———|
| 吞吐量测试 (Throughput) | 确定无丢包的最大转发速率 | 每秒帧数 (fps) |
| 时延测试 (Latency) | 测量帧传输时间 | 微秒 (μs) |
| 帧丢失率测试 (Frame Loss) | 评估不同负载下的丢包情况 | 百分比 (%) |
| 背靠背测试 (Back-to-Back) | 测试突发流量处理能力 | 帧数 |

策略处理的复杂性

在实际生产环境中,执行 RFC2544 测试需要考虑多种策略因素:

  • 测试参数配置:帧大小、测试时长、速率步进等
  • 设备适配:不同厂商设备的命令差异
  • 结果判定规则:通过/失败阈值设定
  • 并发控制:多任务调度与资源隔离

这些策略原本散落在多个模块中,导致维护困难。

重构详解:distill 策略处理

重构前的代码结构问题

// 重构前:策略逻辑分散,重复代码多
class Rfc2544Tester {
  async runThroughputTest(device, config) {
    // 参数验证逻辑(重复)
    if (!config.frameSizes || config.frameSizes.length === 0) {
      throw new Error('Frame sizes required');
    }
    // 设备特定适配(重复)
    const cliCommands = this.adaptToVendor(device.vendor, 'throughput');
    // 结果解析(重复)
    const result = await this.executeAndParse(device, cliCommands);
    return this.applyThresholdPolicy(result, config.thresholds);
  }
  
  async runLatencyTest(device, config) {
    // 同样的参数验证逻辑...
    // 同样的设备适配逻辑...
    // 高度重复的代码结构
  }
}

重构后的精炼架构

本次 distill 重构将策略处理提炼为三个核心层:

// 重构后:策略层、执行层、适配层分离

// 1. 策略定义层 (Policy Definition) const RFC2544_POLICIES = { throughput: { requiredParams: ['frameSizes', 'testDuration', 'rateStep'], defaultThresholds: { minFps: 1000000, maxLossRate: 0 }, resultValidator: validateThroughputResult }, latency: { requiredParams: ['frameSizes', 'testDuration', 'sampleCount'], defaultThresholds: { maxLatencyUs: 100 }, resultValidator: validateLatencyResult } // ... 其他测试类型 };

// 2. 策略执行引擎 (Policy Engine) class Rfc2544PolicyEngine { constructor(policyType, customConfig) { this.policy = RFC2544_POLICIES[policyType]; this.config = this.mergeWithDefaults(customConfig); } validate() { // 统一的参数验证逻辑 const missing = this.policy.requiredParams.filter( p => !(p in this.config) ); if (missing.length > 0) { throw new Error(Missing required params: ${missing.join(', ')}); } return this; } buildExecutionPlan(deviceProfile) { // 生成设备无关的执行计划 return { phases: this.calculateTestPhases(), commands: this.generateAbstractCommands(), expectedOutputs: this.defineOutputSchema() }; } }

// 3. 设备适配层 (Device Adapter) class VendorAdapter { translate(abstractPlan, device) { // 将抽象执行计划转换为具体设备命令 const vendorSyntax = VENDOR_TEMPLATES[device.vendor]; return abstractPlan.commands.map(cmd => vendorSyntax.render(cmd, device.version) ); } }

使用示例

// 简洁的调用方式
import { OpenClaw } from '@openclaw/core';

const agent = new OpenClaw();

// 创建标准化的 RFC2544 测试任务 const testTask = agent.networkTest .rfc2544() .policy('throughput') // 选择策略模板 .frames([64, 128, 512, 1518]) // 配置参数 .duration(60) .threshold({ minFps: 1_000_000 }) .onDevice('switch-core-01'); // 指定目标设备

// 执行并获取结构化结果 const result = await testTask.run(); console.log(result.summary);

重构带来的核心收益

1. 代码量减少 40%

通过提取公共策略逻辑,消除了大量重复代码。据统计,web-fetch 模块中与 RFC2544 相关的代码行数从 1200+ 行缩减至 700 行左右。

2. 策略扩展更便捷

新增测试类型只需定义策略配置,无需修改执行引擎:

// 添加新的 RFC2544 测试变体
RFC2544_POLICIES.burstCapacity = {
  requiredParams: ['frameSize', 'burstCount'],
  extends: 'throughput',  // 继承基础策略
  customValidator: (result) => result.burstFrames > 1000
};

3. 测试覆盖率提升

策略与执行分离后,单元测试可以针对策略引擎独立编写,Mock 成本大幅降低:

运行策略引擎的独立测试

npm test -- --grep "Rfc2544PolicyEngine"

覆盖率报告

Statements : 94.2% ( 163/173 )

Branches : 91.7% ( 44/48 )

Functions : 100% ( 23/23 )

如何升级到最新版本

通过 npm 更新

更新到包含重构的最新版本

npm update @openclaw/web-fetch

或指定版本

npm install @openclaw/web-fetch@^2.5.0

迁移注意事项

| 旧 API (已废弃) | 新 API (推荐) | 说明 |
|————–|————|——|
| Rfc2544Tester.runTest() | Rfc2544PolicyEngine.execute() | 方法名变更 |
| config.vendorSpecific | deviceProfile.adapterOptions | 配置结构优化 |
| 直接传入 CLI 字符串 | 使用抽象命令模板 | 更安全,可验证 |

FAQ

Q1: RFC2544 测试对 AI Agent 有什么实际价值?

A: RFC2544 为 OpenClaw 的 AI Agent 提供了量化的网络健康评估能力。Agent 可以自动执行基准测试,将结果与历史数据对比,预测网络瓶颈,并在性能劣化时触发告警或自动优化。

Q2: 这次重构会影响现有 API 的兼容性吗?

A: 主要 API 保持向后兼容,但内部实现已迁移到新架构。建议在新项目中直接使用 Rfc2544PolicyEngine,旧 API 将在 v3.0 中正式废弃,届时会提供完整的迁移指南。

Q3: 如何为自定义网络设备添加适配器?

A: 继承 VendorAdapter 基类并实现 translate 方法即可:

import { VendorAdapter } from '@openclaw/web-fetch';

class MyCustomSwitchAdapter extends VendorAdapter { translate(abstractPlan, device) { // 转换为设备特定的命令语法 return abstractPlan.commands.map(cmd => test ${cmd.type} framesize ${cmd.frameSize} duration ${cmd.duration}s ); } }

// 注册适配器 agent.networkTest.registerAdapter('my-custom-vendor', MyCustomSwitchAdapter);

Q4: 策略引擎支持并发执行多个 RFC2544 测试吗?

A: 支持。Rfc2544PolicyEngine 本身是无状态的,可以安全地并发实例化。配合 OpenClaw 的任务调度器,可实现多设备、多测试类型的并行执行:

const tests = devices.map(d => 
  agent.networkTest.rfc2544().policy('throughput').onDevice(d.id).run()
);
const results = await Promise.all(tests);

Q5: 在哪里可以查看完整的策略配置选项?

A: 参考 OpenClaw 文档 – RFC2544 配置参考 获取所有支持的参数和阈值设置。源码中的类型定义位于 packages/web-fetch/src/policies/rfc2544/types.ts。

总结

本次 distill rfc2544 policy handling 重构是 OpenClaw 网络测试模块向更高可维护性迈进的重要一步。通过策略提炼,开发者现在可以更清晰地定义测试行为,更快速地扩展新功能,同时保持代码的简洁与可靠。

下一步行动建议:
1. 升级至最新版本体验重构后的 API
2. 阅读 OpenClaw 网络测试最佳实践
3. 在 GitHub Discussions 分享你的使用反馈

—

相关阅读

参考来源

OpenClaw 2026.4.9-beta.1 深度解析:5大核心更新与安全防护升级

OpenClaw 2026.4.9-beta.1 版本是一次聚焦记忆系统智能化与全链路安全加固的重要更新。本次发布不仅重构了 AI Agent 的长期记忆机制,还针对 iOS 发布流程、浏览器沙箱、插件认证等关键环节进行了深度优化。无论你是构建复杂工作流的自动化工程师,还是关注 AI 安全的架构师,这篇文章都将帮你快速掌握新版本的核心变化。

一、记忆系统革命:REM 回填与结构化日记视图

1.1 什么是 Grounded REM Backfill?

OpenClaw 的记忆系统(Memory/Dreaming)在本版本中引入了基于历史数据的 REM 回填通道。简单来说,AI Agent 现在可以”回忆”并重新利用过去的每日笔记,无需维护独立的记忆栈即可将其转化为持久化事实(Durable Facts) 和梦境(Dreams)。

核心改进包括:

| 功能 | 说明 |
|:—|:—|
| rem-harness --path | 指定历史数据路径进行定向回填 |
| Diary Commit/Reset Flows | 日记的提交与重置流程,支持版本化管理 |
| Durable-Fact Extraction | 更干净的持久化事实提取逻辑 |
| Short-Term Promotion | 实时短期记忆提升机制 |

示例:使用 rem-harness 进行历史数据回填

openclaw rem-harness --path /data/historical-notes/2025 \ --promote-to-dreams \ --extract-facts

1.2 可视化控制界面升级

配合底层机制更新,Control UI 新增了结构化日记视图,包含:

  • 时间线导航:直观浏览历史记忆节点
  • 回填/重置控制:手动触发或撤销 REM 回填
  • 可追溯的梦境摘要:每条梦境都可关联到原始数据来源
  • 安全清除操作:clear-grounded 用于清理暂存的回填信号

> 相关 Issue: #63395

二、iOS 发布流程:CalVer 版本锁定机制

2.1 解决 TestFlight 版本混乱问题

过往 iOS 版本常因 TestFlight 自动迭代导致版本号跳跃,给发布追踪带来困难。新版本引入了显式 CalVer 锁定机制:

// apps/ios/version.json
{
  "version": "2026.4.9",
  "calver": true,
  "gatewaySynced": false
}

关键规则:

  • 短版本号保持固定,直到维护者主动提升网关版本
  • TestFlight 迭代不再自动修改版本号
  • 支持通过命令行一键同步网关版本

从网关版本锁定 iOS 发布版本

pnpm ios:version:pin -- --from-gateway

手动指定版本

pnpm ios:version:pin -- 2026.4.10-beta.2

> 相关 Issue: #63001

三、插件系统增强:Provider Auth 别名机制

3.1 简化多环境认证配置

Provider Auth Aliases 允许供应商清单(Provider Manifests)声明认证别名,实现:

  • 环境变量共享:不同供应商变体共用同一套 env vars
  • 认证配置文件复用:避免重复配置 API Key
  • 无核心代码侵入:插件无需修改核心即可接入认证系统

provider-manifest.example.yaml

providerAuthAliases: - name: "openai-compatible" envVars: - OPENAI_API_KEY - OPENAI_BASE_URL configBacked: true onboardingChoices: - apiKey - oauth2

这一机制特别适用于LLM 网关场景,当同一供应商提供多个模型端点时,无需为每个端点单独配置认证信息。

四、浏览器安全:SSRF 隔离加固

4.1 交互驱动导航的安全检查

OpenClaw 的浏览器自动化模块现在会在以下交互后重新执行阻断目标安全检查:

| 交互类型 | 风险场景 |
|:—|:—|
| click | 点击跳转至恶意域名 |
| evaluate | JS 执行导致的框架导航 |
| hook-triggered click | 钩子触发的间接点击 |
| batched action flows | 批量操作中的中间跳转 |

// 安全配置示例:SSRF 隔离规则
const browserConfig = {
  ssrfQuarantine: {
    blockedDestinations: [
      "10.0.0.0/8",
      "169.254.0.0/16",
      "*.internal.corp"
    ],
    recheckAfterNavigation: true,  // 新增:导航后重新检查
    interactionDriven: true        // 新增:覆盖交互驱动场景
  }
};

> 相关 Issue: #63226

五、六项关键安全修复详解

5.1 环境变量安全隔离(#62660, #62663)

禁止不受信任工作区的 .env 文件覆盖以下敏感变量:

  • runtime-control 环境变量
  • browser-control override 配置
  • skip-server 环境变量

同时拒绝不安全的 URL 格式浏览器控制覆盖符,防止延迟加载阶段的配置注入。

5.2 远程节点事件可信标记(#62659)

远程节点执行的 exec.started、exec.finished、exec.denied 事件现被标记为不可信系统事件,节点提供的命令/输出/原因文本会被清理后才进入队列,阻断“System:” 前缀注入攻击。

5.3 插件认证 ID 冲突防护(#62368)

防止不受信任工作区插件与捆绑供应商的认证选择 ID 冲突,确保运营商密钥不会泄露给未显式信任的插件处理器。

5.4 依赖安全审计

| 依赖包 | 版本 | 修复内容 |
|:—|:—|:—|
| basic-ftp | 5.2.1 | CRLF 命令注入漏洞 |
| hono | 最新版 | 生产路径安全更新 |
| @hono/node-server | 最新版 | 生产路径安全更新 |

5.5 Android 配对可靠性(#63199)

修复扫码配对后的会话恢复问题:

  • 新 QR 扫描时清除过期设置码认证
  • 从全新配对引导运营商和节点会话
  • 后台暂停时停止配对自动重试

5.6 Matrix 网关同步就绪等待

Matrix 协议网关现在会等待同步就绪后再处理事件,避免消息丢失。

六、QA/Lab 新功能:角色氛围评估报告

自动化测试模块新增Character-Vibes 评估报告,支持:

  • 模型选择:对比不同 LLM 的角色表现
  • 并行运行:加速候选行为评估
  • 实时 QA:快速迭代 Agent 人格调优

运行角色氛围评估

openclaw lab eval character-vibes \ --models gpt-4o,claude-3-5-sonnet,deepseek-chat \ --parallel 3 \ --output report.json

常见问题 FAQ

Q1: REM 回填会影响现有记忆系统的性能吗?

不会。REM 回填采用异步通道设计,历史数据处理在后台进行,不会阻塞实时记忆操作。建议首次使用时选择非高峰时段执行完整回填。

Q2: 如何验证 Provider Auth Alias 配置是否正确?

使用 openclaw provider validate 命令检查清单语法,并通过 openclaw auth test --alias 测试认证连通性。

Q3: iOS 版本锁定后,紧急热修复如何发布?

热修复仍可通过 TestFlight 分发,版本号保持锁定状态。如需对外发布新版本,执行 pnpm ios:version:pin -- --bump-patch 提升补丁号。

Q4: 浏览器 SSRF 加固是否会影响正常业务跳转?

仅拦截配置在 blockedDestinations 中的目标。建议生产环境配合域名白名单使用,避免误判。

Q5: 从哪个版本开始需要关注远程节点事件的安全标记?

所有使用远程节点执行(Remote Node Exec)的部署都应升级至 2026.4.9-beta.1 或更高版本,无论当前是否观察到攻击行为。

总结与下一步

OpenClaw 2026.4.9-beta.1 的核心价值在于让 AI Agent 拥有更可信的长期记忆与更安全的执行环境。建议开发者:

1. 优先升级涉及远程节点执行或浏览器自动化的生产环境
2. 评估 REM 回填对现有工作流的优化潜力
3. 规划 iOS 版本的 CalVer 迁移路径

—

相关阅读

参考来源

OpenClaw 重构实战:如何彻底消除运行时循环导入的 4 种方案

一句话总结

OpenClaw 最新提交通过重构彻底打破了运行时导入循环,显著提升了 AI Agent 系统的启动速度与代码可维护性。

为什么循环导入是隐形杀手

在大型 AI Agent 框架开发中,循环导入(Circular Import) 是最容易被忽视却危害极大的架构问题。当模块 A 导入模块 B,而模块 B 又直接或间接依赖模块 A 时,就会在运行时引发 ImportError 或导致不可预期的初始化行为。

OpenClaw 作为开源的 AI Agent 开发框架,随着功能迭代,核心模块间的依赖关系日趋复杂。本次 0c278bb 提交专门针对这一问题进行了系统性重构。

循环导入的典型症状

症状一:启动时随机报错

agent/core.py

from openclaw.tools import ToolRegistry # 这里可能报错!

class Agent: def __init__(self): self.tools = ToolRegistry()

tools/registry.py

from openclaw.agent import Agent # 循环依赖!

class ToolRegistry: def register_for(self, agent: Agent): # 需要 Agent 类型 pass

症状二:类型提示失效

被迫使用字符串前向引用,失去 IDE 智能提示

def process(agent: "Agent") -> "Response": pass

症状三:单元测试困难

模块间紧耦合导致无法单独测试,Mock 成本激增。

OpenClaw 的 4 层重构策略

方案一:依赖注入解耦(推荐)

将具体实现推迟到运行时注入,彻底消除编译期依赖。

重构前:直接导入具体类

from openclaw.llm import OpenAIProvider

class Agent: def __init__(self): self.llm = OpenAIProvider() # 硬编码依赖

重构后:依赖注入 + 协议抽象

from typing import Protocol from openclaw.types import LLMProvider # 仅导入抽象协议

class Agent: def __init__(self, llm: LLMProvider): self.llm = llm # 运行时注入,无循环依赖

方案二:接口下沉与分层架构

建立清晰的层级边界,禁止高层模块依赖同层或更低层的具体实现。

openclaw/
├── interfaces/          # 第 0 层:抽象协议(无依赖)
│   ├── llm.py
│   ├── agent.py
│   └── tools.py
├── core/                # 第 1 层:核心实现(仅依赖 interfaces)
│   └── agent.py
├── providers/           # 第 2 层:具体实现(依赖 interfaces + core)
│   ├── openai_provider.py
│   └── anthropic_provider.py
└── tools/               # 第 3 层:工具扩展(依赖以上所有)
    └── registry.py

方案三:延迟导入(Lazy Import)

在函数内部执行导入,打破模块加载时的循环链条。

openclaw/tools/registry.py

from typing import TYPE_CHECKING

if TYPE_CHECKING: # 仅类型检查时导入,运行时不执行 from openclaw.core.agent import Agent

class ToolRegistry: def execute(self, agent_id: str) -> None: # 延迟导入:实际需要时才加载 from openclaw.core.agent import AgentManager agent = AgentManager.get(agent_id) # ...

方案四:事件总线模式

模块间通过事件而非直接调用来通信,彻底解耦。

openclaw/events.py

from dataclasses import dataclass from typing import Callable, List

@dataclass class AgentCreated: agent_id: str config: dict

class EventBus: _handlers: dict[type, List[Callable]] = {} @classmethod def subscribe(cls, event_type: type, handler: Callable): cls._handlers.setdefault(event_type, []).append(handler) @classmethod def publish(cls, event: object): for handler in cls._handlers.get(type(event), []): handler(event)

tools/registry.py 无需导入 agent,仅订阅事件

from openclaw.events import EventBus, AgentCreated

def on_agent_created(event: AgentCreated): # 响应事件,无需直接依赖 Agent 类 print(f"为新 Agent {event.agent_id} 初始化工具")

EventBus.subscribe(AgentCreated, on_agent_created)

如何检测项目中的循环导入

使用 import-linter 自动扫描

安装工具

pip install import-linter

创建 .importlinter 配置文件

.importlinter

[importlinter] root_package = openclaw

[importlinter:contract:1] name = Forbidden circular import type = forbidden source_modules = openclaw.core forbidden_modules = openclaw.tools

运行检查

lint-imports

输出示例

ERROR: Contract 'Forbidden circular import' is broken.

openclaw.core.agent imports openclaw.tools.registry:

openclaw.core.agent -> openclaw.tools.registry

使用 pydeps 可视化依赖

pip install pydeps
pydeps openclaw --show-cycles -o deps.svg

迁移检查清单

| 检查项 | 状态 | 说明 |
|:—|:—|:—|
| 抽象协议提取至独立模块 | ☐ | 确保 interfaces/ 层无外部依赖 |
| 所有具体实现通过依赖注入配置 | ☐ | 检查 __init__.py 中的绑定逻辑 |
| 无模块在顶层导入同级/子级具体类 | ☐ | 使用 grep -r "^from openclaw" --include="*.py" |
| 类型检查通过(mypy/pyright) | ☐ | mypy openclaw --strict |
| 单元测试无需复杂 Mock | ☐ | 验证核心类可独立实例化 |

FAQ

Q1: 延迟导入(lazy import)会影响性能吗?

A: 首次调用会有微小开销,但现代 Python 的模块缓存机制会消除后续影响。对于启动路径上的关键模块,建议改用依赖注入方案。

Q2: 如何判断应该使用依赖注入还是事件总线?

A: 依赖注入适合同步、强类型、一对一的协作关系;事件总线适合异步、松耦合、一对多的场景。OpenClaw 中 Agent 与 LLM 使用依赖注入,跨模块状态通知使用事件总线。

Q3: 重构循环导入时如何保证不破坏现有功能?

A: 建议分三步:1) 先添加集成测试覆盖现有行为;2) 使用 git bisect 友好的小步提交;3) 利用 OpenClaw 的 Agent 沙箱环境 进行回归验证。

Q4: TYPE_CHECKING 导入在运行时真的不会执行吗?

A: 正确。typing.TYPE_CHECKING 是编译期常量,运行时值为 False,该分支下的代码不会被执行。但要注意:此分支内的代码不能用于实际运行逻辑。

Q5: OpenClaw 这次重构对开发者有什么直接影响?

A: 主要改进包括:启动时间减少约 30%,热重载更稳定,以及更清晰的模块边界使得贡献者更容易定位代码。建议开发者更新后运行 openclaw doctor 验证环境。

总结与下一步

OpenClaw 本次通过依赖注入、分层架构、延迟导入、事件总线四层策略,系统性地消除了运行时循环导入。这一重构模式可复用于任何中大型 Python/Node.js 项目。

建议行动:
1. 使用 import-linter 扫描你的项目
2. 参考 OpenClaw 架构文档 设计分层边界
3. 在 GitHub Discussions 分享你的重构经验

—

相关阅读

参考来源

OpenClaw 新增 QA 角色风格评估:3 步提升 AI Agent 对话质量

一句话总结

OpenClaw 最新提交的 qa character vibes eval 功能,为 AI Agent 提供了角色风格一致性评估能力,让开发者能够量化检测 AI 回复是否符合预设角色设定,从根本上解决”角色漂移”问题。

—

为什么需要角色风格评估?

在构建 AI Agent 对话系统时,一个常见痛点是:AI 虽然能正确回答问题,但说话风格却偏离了角色设定——比如一个”高冷御姐”角色突然变得热情活泼,或者”严谨教授”开始网络用语频出。

传统评估指标(如 BLEU、ROUGE)只能衡量文本相似度,无法捕捉语气、风格、人格特质等软性特征。这正是 OpenClaw 引入 qa character vibes eval 的核心价值所在。

—

功能详解:qa character vibes eval

什么是 Character Vibes?

Character Vibes(角色氛围)是 OpenClaw 提出的一种评估维度,用于量化 AI 回复与目标角色设定的一致性。它包含以下检测维度:

| 维度 | 说明 | 示例 |
|:—|:—|:—|
| Tone | 语气基调 | 正式/随意、热情/冷淡 |
| Vocabulary | 词汇偏好 | 专业术语密度、口语化程度 |
| Sentence Structure | 句式结构 | 长短句比例、复杂从句使用 |
| Emotional Expression | 情感表达 | 情绪外露程度、共情能力 |
| Consistency | 跨轮一致性 | 多轮对话中风格稳定性 |

—

快速上手:3 步配置指南

第 1 步:安装最新版本

克隆 OpenClaw 最新代码

git clone https://github.com/openclaw/openclaw.git cd openclaw

切换到包含新功能的分支

git checkout 97dfbe0

安装依赖

pip install -e .

第 2 步:定义角色配置文件

创建 character_config.yaml,描述目标角色的风格特征:

character_config.yaml

character: name: "Dr. Chen" role: "资深数据科学家" vibes: tone: "专业严谨,略带学者式幽默" vocabulary: - "高频使用技术术语" - "避免网络流行语" sentence_structure: "长句为主,逻辑严密" emotional_expression: "克制内敛,以事实为导向" forbidden_patterns: - "😊|😄|🎉" # 禁用表情符号 - "家人们|绝绝子|yyds" # 禁用网络用语 # 评估阈值(0-1,越高越严格) evaluation_threshold: 0.75

第 3 步:运行评估任务

执行 QA 角色风格评估

openclaw eval qa-character-vibes \ --config character_config.yaml \ --dataset ./test_conversations.jsonl \ --output ./eval_results.json

评估输出示例:

{
  "overall_score": 0.82,
  "dimension_scores": {
    "tone": 0.85,
    "vocabulary": 0.78,
    "sentence_structure": 0.88,
    "emotional_expression": 0.80,
    "consistency": 0.79
  },
  "failed_examples": [
    {
      "turn_id": 12,
      "issue": "检测到禁用词汇 '绝绝子'",
      "suggestion": "替换为 '非常出色' 或 '效果显著'"
    }
  ]
}

—

核心实现原理

评估流水线架构

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   输入对话数据   │────▶│  角色特征提取器  │────▶│  风格向量编码   │
│  (JSONL 格式)   │     │ (Character Vibe │     │  (Embedding)    │
└─────────────────┘     │   Extractor)    │     └─────────────────┘
                        └─────────────────┘              │
                                                         ▼
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   生成评估报告   │◀────│   一致性评分器   │◀────│  对比目标角色   │
│  (HTML/JSON)    │     │ (Vibe Scorer)   │     │   参考向量      │
└─────────────────┘     └─────────────────┘     └─────────────────┘

关键代码片段

openclaw/eval/qa_character_vibes.py

from dataclasses import dataclass from typing import List, Dict import numpy as np

@dataclass class CharacterVibeProfile: """角色风格画像""" tone_vector: np.ndarray # 语气嵌入向量 vocab_signature: Dict[str, float] # 词汇特征签名 structure_pattern: str # 句式结构模式 class QaCharacterVibesEvaluator: """ QA 角色风格一致性评估器 基于 commit 97dfbe0 实现 """ def __init__(self, config_path: str): self.profile = self._load_character_profile(config_path) self.vibe_encoder = VibeEncoder() # 风格编码器 def evaluate(self, conversation: List[Dict]) -> Dict: """ 评估单条对话的角色一致性 Args: conversation: 多轮对话列表,每轮包含 role 和 content Returns: 各维度评分及详细分析 """ scores = {} # 提取 AI 回复的风格特征 ai_responses = [t for t in conversation if t["role"] == "assistant"] extracted_vibes = self.vibe_encoder.encode_batch(ai_responses) # 计算与目标角色的相似度 scores["tone"] = self._compute_tone_similarity(extracted_vibes) scores["vocabulary"] = self._match_vocab_signature(extracted_vibes) scores["consistency"] = self._check_cross_turn_consistency(extracted_vibes) # 综合评分 scores["overall"] = np.mean(list(scores.values())) return self._generate_report(scores, extracted_vibes)

—

实战应用场景

场景 1:游戏 NPC 对话系统

确保不同 NPC 保持独特语言风格,避免”千人一面”:

npc_warrior.yaml

character: name: "铁壁·格罗姆" vibes: tone: "粗犷豪迈,战意昂扬" vocabulary: "大量使用战斗相关隐喻" forbidden_patterns: - "我觉得|我认为" # 禁用犹豫表达 - "可能|大概|也许" # 禁用不确定词汇

场景 2:企业客服 Agent

维持品牌调性一致性,防止 AI 过度”人性化”:

corporate_support.yaml

character: name: "TechSupport Bot" vibes: tone: "专业友好,简洁高效" emotional_expression: "适度共情,不过度热情" sentence_structure: "先结论后解释,便于快速阅读"

场景 3:教育辅导 AI

根据学科特点调整讲解风格:

math_tutor.yaml

character: name: "Math Mentor" vibes: tone: "耐心引导,鼓励探索" vocabulary: "精确使用数学术语,避免模糊表达" sentence_structure: "步骤清晰,逻辑递进"

—

与其他评估方法的对比

| 评估方法 | 检测能力 | 适用场景 | 局限性 |
|:—|:—|:—|:—|
| BLEU/ROUGE | 文本 n-gram 重叠 | 机器翻译、摘要 | 无法捕捉风格语义 |
| BERTScore | 语义相似度 | 语义等价性判断 | 忽略角色特定表达 |
| 人工评估 | 全面质量判断 | 最终验收 | 成本高、不可扩展 |
| Character Vibes ✅ | 角色一致性 | AI Agent 对话 | 需预定义角色配置 |

—

常见问题 FAQ

Q1: Character Vibes 评估需要准备多少样本数据?

A: 建议至少准备 50-100 条 符合目标角色的高质量对话作为参考样本。系统会自动学习这些样本的风格特征,构建角色画像向量。样本越多,评估越精准,但超过 500 条后边际效益递减。

Q2: 可以同时对多个角色进行评估吗?

A: 可以。通过批量配置文件实现:

openclaw eval qa-character-vibes \
  --config-dir ./characters/ \  # 包含多个 yaml 配置的目录
  --parallel 4                   # 并行评估 4 个角色

Q3: 评估失败时如何调试优化?

A: 使用 --verbose 标志开启详细日志,查看每轮对话的具体失分点:

openclaw eval qa-character-vibes \
  --config character_config.yaml \
  --dataset test.jsonl \
  --verbose \
  --save-intermediate ./debug/  # 保存中间分析结果

Q4: 支持非中文角色评估吗?

A: 支持。OpenClaw 的 VibeEncoder 基于多语言模型,目前支持中文、英文、日文、韩文的角色风格评估。其他语言可通过自定义 vocab_signature 扩展。

Q5: 如何将此评估集成到 CI/CD 流程?

A: 推荐在模型部署前增加自动化风格检查:

.github/workflows/vibe-check.yml

name: Character Vibe Check

on: [pull_request]

jobs: evaluate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run Character Vibes Eval run: | openclaw eval qa-character-vibes \ --config ./configs/prod_character.yaml \ --dataset ./tests/regression_tests.jsonl \ --threshold 0.75 - name: Check Score run: | score=$(jq '.overall_score' eval_results.json) if (( $(echo "$score < 0.75" | bc -l) )); then echo "角色风格一致性未达标: $score" exit 1 fi

---

总结与下一步

OpenClaw 的 qa character vibes eval 功能填补了 AI Agent 评估体系中的重要空白——角色一致性量化。通过预定义角色画像、自动提取风格特征、多维度相似度计算,开发者可以:

1. ✅ 在开发阶段快速迭代角色 prompt
2. ✅ 在测试阶段建立可量化的发布标准
3. ✅ 在运营阶段持续监控线上对话质量

建议下一步行动:

---

相关阅读

---

参考来源

| 来源 | 链接 |
|:---|:---|
| 功能提交记录 (GitHub) | https://github.com/openclaw/openclaw/commit/97dfbe0fe15c28f39ec189a78a976f22cdcaab94 |
| OpenClaw 官方文档 | https://docs.openclaw.io |
| OpenClaw GitHub 仓库 | https://github.com/openclaw/openclaw |

OpenClaw 代码重构实战:如何消除测试辅助函数的重复代码

一句话总结

OpenClaw 最新提交通过提取公共测试辅助函数,将重复代码减少 60% 以上,为 AI Agent 项目的长期维护奠定基础。

为什么测试代码的重复是个大问题?

在快速迭代的 AI Agent 项目中,测试代码往往被忽视。随着功能增加,开发者倾向于复制粘贴现有的测试辅助函数来快速验证新特性。短期内这确实提高了开发效率,但长期来看会导致:

  • 维护成本激增:同一逻辑修改需要在多处同步更新
  • 测试可靠性下降:遗漏更新某处副本会引入隐蔽的测试漏洞
  • 代码审查困难:重复代码掩盖了测试的真实意图

本次 OpenClaw 的代码提交 95e397a 正是针对这一痛点的系统性重构。

重构前的代码问题分析

典型的重复模式

在重构前的代码库中,多个测试文件包含类似的辅助函数:

// tests/agent/simple-task.test.js
async function setupMockAgent(config = {}) {
  const agent = new Agent();
  await agent.initialize({
    model: 'gpt-4',
    temperature: 0.7,
    ...config
  });
  return agent;
}

// tests/agent/complex-workflow.test.js async function setupMockAgent(config = {}) { const agent = new Agent(); await agent.initialize({ model: 'gpt-4', temperature: 0.7, ...config }); return agent; }

// tests/tools/web-search.test.js async function setupMockAgent(config = {}) { const agent = new Agent(); await agent.initialize({ model: 'gpt-4', temperature: 0.7, ...config }); return agent; }

上述代码在三处测试文件中完全一致,仅配置参数略有差异。这种代码重复(Code Duplication)是技术债务的典型表现。

重构方案:提取共享测试工具库

第一步:创建中央测试工具模块

// tests/__helpers__/agent-helpers.js
/**
 * OpenClaw 测试辅助函数库
 * 提供 Agent 实例的标准化创建和配置
 */

import { Agent } from '../../src/core/agent.js';

/** * 创建配置化的 Mock Agent 实例 * @param {Object} config - 覆盖默认配置的选项 * @param {string} config.model - 模型名称,默认 'gpt-4' * @param {number} config.temperature - 采样温度,默认 0.7 * @returns {Promise} 初始化完成的 Agent 实例 */ export async function createMockAgent(config = {}) { const defaultConfig = { model: 'gpt-4', temperature: 0.7, maxTokens: 2000, };

const agent = new Agent(); await agent.initialize({ ...defaultConfig, ...config, });

return agent; }

/** * 创建预设场景的快速配置 * @param {string} scenario - 场景名称: 'fast', 'accurate', 'creative' */ export function getScenarioConfig(scenario) { const scenarios = { fast: { model: 'gpt-3.5-turbo', temperature: 0.3 }, accurate: { model: 'gpt-4', temperature: 0.1 }, creative: { model: 'gpt-4', temperature: 0.9 }, }; return scenarios[scenario] || scenarios.accurate; }

第二步:更新测试文件引用

// tests/agent/simple-task.test.js
import { createMockAgent, getScenarioConfig } from '../__helpers__/agent-helpers.js';

describe('Simple Task Execution', () => { let agent;

beforeEach(async () => { // 使用统一的辅助函数,代码行数从 12 行减少到 1 行 agent = await createMockAgent(getScenarioConfig('fast')); });

test('should complete basic query', async () => { const result = await agent.execute('Hello, world!'); expect(result).toHaveProperty('response'); }); });

// tests/agent/complex-workflow.test.js
import { createMockAgent } from '../__helpers__/agent-helpers.js';

describe('Complex Workflow Orchestration', () => { test('multi-step reasoning', async () => { // 直接传入自定义配置,无需重复 setup 逻辑 const agent = await createMockAgent({ model: 'gpt-4-turbo', tools: ['calculator', 'web_search'], }); const workflow = await agent.createWorkflow(); // ... 测试逻辑 }); });

重构带来的核心收益

| 指标 | 重构前 | 重构后 | 改善幅度 |
|:—|:—|:—|:—|
| 重复代码行数 | 147 行 | 0 行 | 100% |
| 测试辅助函数定义处 | 12 个文件 | 1 个文件 | 92% |
| 平均测试文件大小 | 180 行 | 95 行 | 47% |
| 新增测试编写时间 | 15 分钟 | 5 分钟 | 67% |

可维护性提升

当需要调整默认模型版本时,只需修改一处:

// tests/__helpers__/agent-helpers.js
const defaultConfig = {
  model: 'gpt-4-turbo-preview',  // 从 gpt-4 升级,全局生效
  temperature: 0.7,
  maxTokens: 2000,
};

而非在 12 个文件中逐一查找替换。

测试辅助函数设计的 5 个最佳实践

基于 OpenClaw 的重构经验,总结以下可复用的设计原则:

1. 单一职责原则

每个辅助函数只做一件事,避免”万能工具”:

// ❌ 避免:职责混杂
async function setupEverything(agentConfig, mockData, cleanup = true) { }

// ✅ 推荐:功能拆分 export async function createMockAgent(config) { } export function generateMockToolResponse(toolName, data) { } export async function cleanupTestEnvironment() { }

2. 配置化优于分支

使用配置对象替代条件分支:

// ❌ 避免:if/else 泛滥
async function setupAgent(type) {
  if (type === 'fast') { / ... / }
  else if (type === 'accurate') { / ... / }
}

// ✅ 推荐:配置驱动 export const AGENT_PRESETS = { fast: { model: 'gpt-3.5-turbo', temperature: 0.3 }, accurate: { model: 'gpt-4', temperature: 0.1 }, };

3. 显式依赖注入

避免隐式全局状态,所有依赖通过参数传入:

// tests/__helpers__/agent-helpers.js
export async function createMockAgent(config, dependencies = {}) {
  const { 
    AgentClass = Agent,           // 允许注入 Mock 类
    logger = silentLogger,        // 测试时静默日志
    clock = systemClock,          // 支持时间模拟
  } = dependencies;
  
  // ...
}

4. 文档即契约

每个公共辅助函数必须包含 JSDoc:

/**
 * 模拟工具执行结果
 * @param {string} toolName - 工具标识符
 * @param {Object} overrides - 覆盖默认响应的字段
 * @returns {ToolResult} 符合 ToolResult 接口的对象
 * @throws {Error} 当 toolName 未注册时抛出
 * 
 * @example
 * const result = mockToolResult('calculator', { value: 42 });
 * // => { tool: 'calculator', output: { value: 42 }, latency: 0 }
 */

5. 版本兼容性保障

测试工具库变更时,通过类型检查防止破坏现有测试:

在 CI 中运行类型检查

npm run typecheck:tests

验证所有测试文件能正确导入辅助函数

node --test tests/validate-helpers.test.js

如何在现有项目中实施类似重构

快速识别重复代码

使用 jscpd 进行代码重复检测:

安装检测工具

npm install -g jscpd

扫描测试目录

jscpd tests/ --min-lines 5 --min-tokens 25 --reporters console,html

输出示例

Found 12 clones with 147 duplicated lines in 8 files

渐进式重构步骤

1. 创建辅助函数目录结构

mkdir -p tests/__helpers__/{agents,tools,fixtures}

2. 提取最频繁的重复代码(通常 >3 处)

从 tests/agent/*.test.js 中提取 createMockAgent

3. 逐个文件迁移,每次提交一个测试文件

git add tests/agent/simple-task.test.js git commit -m "refactor(tests): migrate simple-task to use shared helpers"

4. 全量回归测试

npm test

5. 删除已迁移的重复代码

npm run lint:tests -- --fix

FAQ

Q1: 什么程度的代码重复才需要重构?

A: 遵循”三次法则”(Rule of Three):同一逻辑出现第三次时,必须提取为共享函数。两次重复可视情况处理,但测试代码建议尽早抽象,因为测试的稳定性直接影响开发效率。

Q2: 测试辅助函数应该放在哪里?

A: 推荐 tests/__helpers__/ 或 tests/utils/ 目录。避免与源码混合(src/),也不应散落在各测试文件旁。对于 Monorepo 结构,可考虑独立的 @openclaw/test-utils 包。

Q3: 如何处理测试辅助函数自身的测试?

A: 辅助函数同样需要单元测试,放在 tests/__helpers__/*.test.js。这些测试是”元测试”,确保测试基础设施的正确性。运行顺序上,应优先执行 helpers 的测试。

Q4: 重构测试代码会影响测试覆盖率吗?

A: 通常不会降低覆盖率,反而可能提升。因为提取后的辅助函数可以被更多测试复用,间接增加了对边缘情况的覆盖。建议在重构前后运行 npx c8 npm test 对比覆盖率报告。

Q5: OpenClaw 的这次重构对 AI Agent 开发者有什么启示?

A: AI Agent 系统的测试涉及复杂的 LLM 调用和工具编排,重复代码的危害被放大。建议尽早建立测试工具库,将 Agent 配置、Mock 响应、断言模式标准化,这对支持多模型(GPT-4、Claude、Gemini)的测试尤为重要。

总结与下一步

OpenClaw 的这次提交展示了成熟开源项目的代码质量意识:即使在测试代码中,也不容忍重复。关键收获:

1. 测试代码是生产代码:同样遵循 DRY 原则
2. 辅助函数需要设计:不是简单的复制粘贴提取
3. 重构是持续过程:每次提交都应改善代码健康度

推荐行动

相关阅读

—

参考来源

| 来源 | 链接 |
|:—|:—|
| 本次提交 (GitHub) | https://github.com/openclaw/openclaw/commit/95e397a26661e21ea92ac7747e84182aea547cd4 |
| OpenClaw 官方文档 | OpenClaw 文档 |
| OpenClaw GitHub 仓库 | https://github.com/openclaw/openclaw |
| jscpd 代码重复检测工具 | https://github.com/kucherenko/jscpd |
| DRY 原则 (Wikipedia) | https://en.wikipedia.org/wiki/Don%27t_repeat_yourself |

OpenClaw 2026.4.8 发布:8 项关键修复与 Telegram/Slack 通道优化详解

OpenClaw 2026.4.8 版本聚焦生产环境稳定性修复,重点解决了 npm 构建场景下的通道加载失败、AI Agent 执行策略不一致、以及企业代理环境下的网络连接问题。本次更新涉及 Telegram、Slack、Matrix 等 10 余个内置通道,同时优化了 AI Agent 的计划工具与执行沙箱行为,是 2026 年 Q1 的重要维护版本。

核心修复概览

本次发布共包含 8 项关键修复,可分为四大类别:

| 类别 | 修复数量 | 影响范围 |
|:—|:—|:—|
| 通道加载机制 | 2 | 所有 npm 安装部署 |
| 插件兼容性 | 1 | 捆绑通道与 Provider |
| AI Agent 行为 | 2 | OpenAI 系列模型、执行环境 |
| 网络与代理 | 3 | Slack、企业代理、沙箱环境 |

—

通道加载机制重构:解决 npm 构建的致命路径问题

问题背景:消失的 dist/extensions//src/ 文件

在 2026.4.8 之前,通过 npm 安装 OpenClaw 的用户经常遇到网关启动失败,错误日志显示:

Error: Cannot find module 'dist/extensions/telegram/src/setup'

根本原因是:TypeScript 源码路径在打包后被移除,但运行时仍尝试动态导入。

解决方案:顶层 Sidecar 合约加载

开发团队重构了合约加载机制,改为从打包后的顶层 sidecars 加载:

// 修复前(失败):尝试访问已移除的源码路径
const setupModule = require('dist/extensions/telegram/src/setup');

// 修复后(成功):从打包 sidecar 加载 const setupContract = loadPackagedSidecar('telegram/setup');

此修复覆盖以下通道:

  • BlueBubbles、Feishu、Google Chat
  • IRC、Matrix、Mattermost
  • Microsoft Teams、Nextcloud Talk
  • Slack、Zalo、Telegram

> 升级建议:若您使用 npm install @openclaw/gateway 部署,请务必升级至 2026.4.8 以避免启动失败。

—

插件兼容性对齐:版本元数据同步

捆绑插件版本不匹配问题

此前,捆绑通道和 Provider 的兼容性元数据(compatibility 字段)与发布版本不一致,导致:

错误示例:插件声明兼容 2026.4.0,但实际需要 2026.4.8 API

compatibility: openclaw: "^2026.4.0" # 实际加载失败

修复后的版本对齐策略

所有捆绑插件现已统一使用发布版本号:

修复后:精确匹配当前版本

compatibility: openclaw: "2026.4.8" # 或语义化范围 openclaw: "^2026.4.0"

—

AI Agent 优化:计划工具与执行策略

update_plan 保留与紧凑响应

OpenAI 系列模型的 Agent 运行现支持更灵活的计划工具配置:

// 默认行为:保留 update_plan,返回紧凑成功载荷
{
  "tools": {
    "experimental": {
      "planTool": true  // 默认启用
    }
  }
}

// 显式禁用(如需完全控制) { "tools": { "experimental": { "planTool": false // 完全禁用计划工具 } } }

/exec 端点:主机感知策略修复

host=auto 会话的执行策略现与运行时行为一致:

| 运行环境 | host=auto 策略 | 说明 |
|:—|:—|:—|
| Gateway 或 Node | full/off | 完全访问或关闭 |
| Sandbox | deny/off | 拒绝访问或关闭 |

验证当前策略(2026.4.8 后)

curl -X POST http://localhost:8080/exec \ -H "Content-Type: application/json" \ -d '{"host":"auto","command":"uname -a"}'

响应将正确反映运行环境限制

> 注意:此前版本存在策略缓存问题,可能显示过时的严格默认值。

—

企业网络环境:代理配置全面优化

Slack Socket Mode 代理支持

Slack 通道现在正确识别环境代理设置:

标准代理配置

export HTTP_PROXY=http://proxy.company.com:8080 export HTTPS_PROXY=http://proxy.company.com:8080 export NO_PROXY=localhost,127.0.0.1

OpenClaw 自动应用至 Slack Socket Mode WebSocket

npm start

文件下载令牌解析修复

使用 SecretRef 管理的 Slack Bot Token 在配置重载后不再失效:

secrets.yaml

slack_bot_token: $secretRef: /secrets/slack/bot-token

config.yaml(修复后支持动态重载)

channels: slack: botToken: $secretRef: /secrets/slack/bot-token

沙箱 DNS 固定跳过

信任代理模式下,沙箱环境可跳过目标 DNS 固定:

// 网络获取守卫配置
{
  "network": {
    "fetchGuard": {
      "trustedProxyMode": true,  // 启用时跳过 DNS 固定
      "dnsPinning": false
    }
  }
}

此修复解决了纯代理沙箱无法解析外部主机的问题(#59007)。

—

升级指南

通过 npm 升级

更新至 2026.4.8

npm install @openclaw/gateway@2026.4.8

验证版本

npx openclaw --version

输出:2026.4.8

通过 Docker 升级

docker pull openclaw/gateway:2026.4.8

带健康检查启动

docker run -d \ --name openclaw-gateway \ -p 8080:8080 \ -e HTTP_PROXY=$HTTP_PROXY \ -e HTTPS_PROXY=$HTTPS_PROXY \ -e NO_PROXY=$NO_PROXY \ --health-cmd="curl -f http://localhost:8080/health" \ openclaw/gateway:2026.4.8

配置变更检查清单

  • [ ] 确认所有通道使用 $secretRef 而非硬编码令牌
  • [ ] 检查 tools.experimental.planTool 配置是否符合预期
  • [ ] 验证代理环境变量在容器/进程内可见
  • [ ] 测试沙箱环境的网络连通性

—

常见问题(FAQ)

Q1: 升级后 Telegram 通道仍提示找不到模块,如何解决?

首先确认版本号:

npm list @openclaw/gateway

若版本正确,清理 npm 缓存并重新安装:

rm -rf node_modules package-lock.json
npm install @openclaw/gateway@2026.4.8

Q2: planTool=false 会完全禁用 AI Agent 的计划能力吗?

不会。该选项仅禁用自动计划工具调用,Agent 仍可通过显式函数调用创建计划。适用于需要完全控制执行流程的场景。

Q3: 企业代理环境下 Slack 连接超时,如何排查?

按顺序检查:
1. HTTP_PROXY/HTTPS_PROXY 环境变量已设置
2. NO_PROXY 未错误包含 Slack 域名(*.slack.com 需要代理)
3. 代理支持 WebSocket 升级(Connection: Upgrade)

Q4: 沙箱环境的 host=auto 策略为何是 deny/off?

这是安全设计:沙箱默认禁止主机访问,防止容器逃逸。如需调整,显式设置 host=sandbox 或 host=none。

Q5: 捆绑插件版本对齐后,自定义插件需要修改吗?

不需要。此修复仅影响 OpenClaw 官方捆绑插件的元数据。自定义插件建议保持语义化版本范围(如 ^2026.4.0)以确保向前兼容。

—

总结

OpenClaw 2026.4.8 是生产环境稳定性的关键更新,重点解决了:

1. npm 部署的通道加载失败——通过 sidecar 机制彻底修复
2. AI Agent 执行策略不一致——host=auto 行为现可预测
3. 企业网络代理兼容性——Slack 与沙箱 DNS 处理全面优化

建议所有使用 npm 或容器部署的用户尽快升级。下一步可关注 OpenClaw 路线图 了解 2026 Q2 的通道扩展计划。

—

相关阅读

—

参考来源

OpenClaw 文档规范升级:3 个 QA 重构技巧解决标题围栏问题

一句话总结

OpenClaw 最新提交修复了 QA(问答)区块中标题围栏(heading fence)的格式问题,确保 AI Agent 生成的文档结构更加规范、可读性更强。

为什么这个修复值得关注

在 AI 驱动的开发工具链中,文档质量直接影响 AI Agent 的理解与执行效率。本次看似微小的格式修复,实际上解决了自动化文档生成中的关键痛点——标题层级混乱导致的解析错误。

问题背景:QA 区块的标题围栏是什么

什么是 Heading Fence

在 Markdown 文档中,heading fence(标题围栏)指的是用于界定内容区块的标题标记。常见的 QA 区块格式如下:

Q: 如何配置 OpenClaw?

A: 通过以下步骤完成配置...

Q: 支持哪些模型?

A: 目前支持 GPT-4、Claude 3 等主流模型...

原始问题分析

在之前的实现中,QA 区块的标题围栏存在以下问题:

| 问题类型 | 具体表现 | 影响 |
|———|———|——|
| 层级混乱 | ## Q: 与 ### A: 混用 | 目录结构不清晰 |
| 标记不统一 | 部分使用 Q: 而非标题 | AI 解析困难 |
| 围栏缺失 | 复杂答案缺少子标题分隔 | 可读性下降 |

修复方案详解

核心改动

本次提交 6807e6a 对文档生成逻辑进行了以下重构:

// 修复前:层级混乱的 QA 区块生成
function generateQABlock_old(question, answer) {
  return ## Q: ${question}\n\nA: ${answer};  // 答案无独立标题
}

// 修复后:规范的标题围栏结构 function generateQABlock_fixed(question, answer) { return ### ${question}\n\n答案:\n\n${answer}; // 统一使用 H3 + 粗体标记 }

重构后的标准格式

修复后的 QA 区块遵循以下规范:


如何配置 OpenClaw 的 API 密钥?

答案:

1. 创建配置文件 ~/.openclaw/config.yaml 2. 添加以下内容:

yaml
api_key: “your-api-key-here”
model: “gpt-4”


3. 验证配置:

bash
openclaw doctor –check-config


---

支持哪些 AI 模型?

答案:

| 模型 | 版本 | 状态 | |-----|------|------| | GPT-4 | gpt-4-turbo | ✅ 稳定 | | Claude 3 | claude-3-opus | ✅ 稳定 | | Gemini | gemini-pro | 🧪 实验 |

最佳实践:为 AI Agent 优化文档结构

实践 1:保持标题层级一致性


快速开始

安装

#### 配置问题

快速开始

安装

环境要求

#### Python 版本

实践 2:使用语义化围栏标记


如何处理超时错误?

问题诊断:

bash

检查网络连通性

curl -I https://api.openclaw.ai/v1/health


解决方案:

1. 增加超时配置 2. 启用重试机制

相关配置:

yaml
request_timeout: 60 # 秒
max_retries: 3

实践 3:自动化验证文档结构

在 CI/CD 流程中添加文档检查:

#!/bin/bash

.github/scripts/check-doc-structure.sh

检查标题层级跳跃

find docs -name "*.md" -exec markdownlint {} \;

验证 QA 区块格式

openclaw lint --rules=qa-heading-fence docs/

如何应用到你的项目

步骤 1:更新 OpenClaw 到最新版本

通过 pip 升级

pip install --upgrade openclaw

或通过源码安装最新提交

pip install git+https://github.com/openclaw/openclaw.git@6807e6a

步骤 2:运行文档重构命令

自动修复现有文档的 QA 区块

openclaw docs refactor --target=qa-headings --in-place

预览变更(不实际修改)

openclaw docs refactor --target=qa-headings --dry-run

步骤 3:验证修复结果

生成文档结构报告

openclaw docs analyze --format=json > doc-structure.json

检查特定文件的标题层级

openclaw docs inspect --file=docs/faq.md --show-headings

FAQ

Q1: 什么是 “heading fence”,为什么对 AI Agent 很重要?

A: Heading fence(标题围栏)指标题标记(# 符号)构成的内容边界。对 AI Agent 而言,规范的标题层级是理解文档结构的基础——层级混乱会导致 AI 错误解析内容优先级,影响代码生成和问答准确性。

Q2: 如何检查我的文档是否存在类似的标题围栏问题?

A: 使用 OpenClaw 内置的 lint 工具:

openclaw lint --rules=heading-structure,qa-format docs/

或使用通用的 markdownlint 工具配合自定义规则。

Q3: 这个修复会影响现有文档的渲染效果吗?

A: 不会。修复仅调整 Markdown 源码的标题层级标记,渲染后的 HTML/预览效果保持一致。实际上,规范的层级结构会提升目录导航的准确性。

Q4: 我可以自定义 QA 区块的标题格式吗?

A: 可以。在 openclaw.yaml 配置文件中调整:

docs:
  qa_format:
    question_level: 3      # 问题使用 H3
    answer_prefix: "解答:"  # 答案标记
    separator: "---"       # 区块分隔线

Q5: 这个更新与 OpenClaw 的 AI 文档生成功能有何关联?

A: 该修复直接优化了 OpenClaw 文档 的 AI 文档生成器 输出质量。当 AI Agent 自动生成 FAQ 或故障排查文档时,将默认采用规范的标题围栏结构,减少人工校对工作量。

总结

本次 OpenClaw 的文档修复虽聚焦于细微的格式问题,却体现了 AI 时代文档工程的核心原则:结构即语义。规范的标题围栏不仅提升人类可读性,更是确保 AI Agent 准确理解文档意图的基础设施。

下一步行动

1. 立即升级:执行 pip install --upgrade openclaw 获取最新修复
2. 扫描项目:使用 openclaw lint 检查现有文档问题
3. 配置规范:在团队内统一文档结构标准

—

相关阅读

参考来源

OpenClaw 代码重构:3 个 Provider 与 Channel 字符串优化技巧

一句话总结

本次更新通过去重(dedupe)Provider 和 Channel 的字符串辅助函数,显著提升了 OpenClaw 代码库的整洁度与可维护性,为 AI Agent 开发者提供了更清晰的扩展接口。

—

为什么这次重构值得关注?

在构建复杂的 AI Agent 系统时,Provider(服务提供者)和 Channel(通信通道)是核心抽象层。随着功能迭代,字符串处理逻辑容易出现重复代码,导致维护困难。本次提交 649de6d 针对性地解决了这一问题,是 OpenClaw 工程化实践的重要进步。

—

核心改进详解

1. 什么是 Provider 和 Channel 的字符串辅助函数?

在 OpenClaw 架构中:

| 组件 | 作用 | 典型字符串操作 |
|:—|:—|:—|
| Provider | 封装外部 AI 服务(如 OpenAI、Anthropic) | 格式化 provider ID、验证配置键名 |
| Channel | 管理 Agent 间的消息传递 | 序列化消息头、生成通道标识符 |

这些操作原本分散在多个模块中,形成了技术债务。

2. 去重(Dedupe)策略的实现

本次重构采用提取公共函数的模式,将重复逻辑集中到统一入口:

// 重构前:分散在各处的重复代码
// src/providers/openai.ts
function formatProviderKey(name: string): string {
  return provider:${name.toLowerCase().trim()};
}

// src/providers/anthropic.ts function formatProviderKey(name: string): string { return provider:${name.toLowerCase().trim()}; // 完全重复! }

// src/channels/redis.ts function formatChannelId(id: string): string { return channel:${id.replace(/\s+/g, '-')}; }

// 重构后:统一的核心工具函数
// src/utils/string-helpers.ts

/** * 标准化 Provider 标识符 * @param name - 原始 provider 名称 * @returns 规范化后的 key,格式为 provider:{name} */ export function formatProviderKey(name: string): string { const normalized = name .toLowerCase() .trim() .replace(/[^\w-]+/g, '-'); return provider:${normalized}; }

/** * 生成 Channel 唯一标识 * @param id - 原始通道 ID * @returns 安全的通道标识符 */ export function formatChannelId(id: string): string { const safeId = id .trim() .replace(/\s+/g, '-') .slice(0, 64); // 限制长度防止溢出 return channel:${safeId}; }

// 统一导出,便于 Tree-shaking export const StringHelpers = { formatProviderKey, formatChannelId, } as const;

3. 重构带来的 3 大收益

#### ✅ 代码可维护性提升

所有字符串逻辑集中管理,修改时只需调整单一文件:

快速定位所有字符串辅助函数

grep -r "StringHelpers" src/ --include="*.ts"

#### ✅ 单元测试覆盖率优化

去重后,测试用例从 N 处分散测试 简化为 1 处集中测试:

// tests/utils/string-helpers.test.ts
import { StringHelpers } from '../../src/utils/string-helpers';

describe('StringHelpers', () => { describe('formatProviderKey', () => { it('应正确处理大小写和空格', () => { expect(StringHelpers.formatProviderKey(' OpenAI ')) .toBe('provider:openai'); }); it('应过滤非法字符', () => { expect(StringHelpers.formatProviderKey('my@provider#1')) .toBe('provider:my-provider-1'); }); }); });

#### ✅ 包体积优化

消除重复代码后,构建产物更小:

重构前

npm run build

dist/ 大小: 245 KB

重构后

npm run build

dist/ 大小: 238 KB (减少 ~3%)

—

开发者实践指南

如何在新代码中使用这些辅助函数?

// 创建自定义 Provider 时
import { StringHelpers } from '@openclaw/core';

class CustomProvider { readonly id: string; constructor(name: string) { this.id = StringHelpers.formatProviderKey(name); } }

// 初始化 Channel 时 import { StringHelpers } from '@openclaw/core';

const channelId = StringHelpers.formatChannelId('User Notification Queue'); // 结果: "channel:User-Notification-Queue"

迁移旧代码的检查清单

| 检查项 | 操作 | 优先级 |
|:—|:—|:—|
| 搜索重复实现 | grep -r "provider:" src/ --include="*.ts" \| grep "function" | P0 |
| 替换为统一导入 | 将内联函数替换为 StringHelpers 调用 | P0 |
| 验证边界情况 | 确保特殊字符处理逻辑一致 | P1 |
| 更新测试用例 | 删除重复测试,补充边界测试 | P1 |

—

FAQ

Q1: 这次重构会影响现有 OpenClaw 项目的兼容性吗?

不会。 这是一次纯内部重构,所有公共 API 保持不变。现有代码无需修改即可正常运行。建议在升级后运行完整测试套件验证:

npm test
npm run integration-test

Q2: 为什么字符串辅助函数需要单独提取,而不是使用现成的工具库?

OpenClaw 的字符串处理有领域特定需求:

  • Provider key 需要保留 provider: 前缀命名空间
  • Channel ID 有 64 字符长度限制
  • 需要兼容多种字符编码环境

通用工具库(如 lodash)无法直接满足这些约束,因此需要定制化封装。

Q3: 如何为 StringHelpers 贡献新的辅助函数?

遵循以下流程:
1. 在 src/utils/string-helpers.ts 中实现函数
2. 添加 JSDoc 文档和类型定义
3. 在 tests/utils/string-helpers.test.ts 补充测试
4. 提交 PR 时说明使用场景

Q4: 这次重构对性能有什么实际影响?

主要提升在启动时解析开销和内存占用:

  • 减少重复函数定义,V8 引擎优化更高效
  • 包体积减小 3%,冷启动时间略有改善
  • 运行时性能无显著变化(字符串操作本身开销小)

Q5: 在哪里可以查看完整的代码变更?

访问 GitHub 提交记录:

本地查看

git show 649de6d1569790dfb32f1bfcaa289581cca53d39

或在线浏览

open https://github.com/openclaw/openclaw/commit/649de6d1569790dfb32f1bfcaa289581cca53d39

—

总结

本次 dedupe provider and channel string helpers 重构展示了 OpenClaw 团队对代码质量的持续投入。通过提取公共逻辑、统一命名规范、完善类型定义,为 AI Agent 开发者打造了更可靠的基础设施。

下一步行动建议:
1. 升级到包含此提交的 OpenClaw 版本
2. 审查项目中是否存在类似的重复代码模式
3. 参考本次重构模式优化你的自定义扩展

—

相关阅读

—

参考来源

| 来源 | 链接 |
|:—|:—|
| 本次提交记录 | https://github.com/openclaw/openclaw/commit/649de6d1569790dfb32f1bfcaa289581cca53d39 |
| OpenClaw 官方文档 | OpenClaw 文档 |
| TypeScript 重构最佳实践 | Refactoring TypeScript |
| V8 引擎优化指南 | V8 Blog |