### 变更
- CLI:新增 `openclaw logs --local-time` 选项,用于在本地时区显示日志时间戳。(#13818)感谢 @xialonglee。
- Telegram:将引用块渲染为原生 `<blockquote>` 标签,而非直接移除。(#14608)
- 配置:在配置快照脱敏时避免对 `maxTokens` 类字段进行脱敏,防止 `/config` 接口往返验证失败。(#14006)感谢 @constansino。
### 重大变更
- 钩子:`POST /hooks/agent` 接口现在默认拒绝请求负载中的 `sessionKey` 覆盖。如需保持固定的钩子上下文,请设置 `hooks.defaultSessionKey`(建议与 `hooks.allowedSessionKeyPrefixes: ["hook:"]` 配合使用)。如需保留旧版行为,请显式设置 `hooks.allowRequestSessionKey: true`。感谢 @alpernae 报告此问题。
### 修复
- 网关/开放响应:通过显式的 SSRF 拒绝策略、主机名白名单(`files.urlAllowlist` / `images.urlAllowlist`)、单次请求 URL 输入上限(`maxUrlParts`)、阻止式抓取审计日志以及回归测试覆盖/文档更新,强化基于 URL 的 `input_file`/`input_image` 处理。
- 安全:修复未认证的 Nostr 配置文件 API 远程配置篡改问题。(#13719)感谢 @coygeek。
- 安全:移除捆绑的 soul-evil 钩子。(#14757)感谢 @Imccccc。
- 安全/审计:新增钩子会话路由强化检查(`hooks.defaultSessionKey`、`hooks.allowRequestSessionKey` 及前缀白名单),并在 HTTP API 端点允许显式会话密钥路由时发出警告。
- 安全/沙箱:将镜像技能同步目标限制在沙箱 `skills/` 根目录下,并停止使用由 frontmatter 控制的技能名称作为文件系统目标路径。感谢 @1seal。
- 安全/网页工具:默认将浏览器/网页内容视为不可信(对浏览器快照/标签页/控制台输出进行包装,并为网页工具提供结构化的外部内容元数据),并从面向模型的转录/压缩输入中移除 `toolResult.details`,以降低提示注入重放风险。
- 安全/钩子:通过共享的恒定时间密钥比较强化 Webhook 和设备令牌验证,并为钩子端点添加基于客户端的认证失败限流(`429` + `Retry-After`)。感谢 @akhmittra。
- 安全/浏览器:要求对环回浏览器控制 HTTP 路由进行认证;当浏览器控制启动时若未配置认证,则自动生成 `gateway.auth.token`;并添加针对未认证浏览器控制的安全审计检查。感谢 @tcusolle。
- 会话/网关:强化转录路径解析,拒绝不安全的会话 ID/文件路径,确保会话操作保持在代理会话目录内。感谢 @akhmittra。
- 网关:提高 WebSocket 负载/缓冲区限制,确保 5,000,000 字节的图像附件可靠工作。(#14486)感谢 @0xRaini。
- 日志/CLI:控制台前缀时间戳使用本地时区,并在使用 `openclaw logs --local-time` 时包含 `±HH:MM` 偏移量以避免歧义。(#14771)感谢 @0xRaini。
- 网关:在重启前排空活动回合,防止消息丢失。(#13931)感谢 @0xRaini。
- 网关:在安装期间自动生成认证令牌,防止 launchd 重启循环。(#13813)感谢 @cathrynlavery。
- 网关:防止认证配置中出现 `undefined`/缺失令牌。(#13809)感谢 @asklee-klawd。
- 网关:处理关闭期间 stdout/stderr 上的异步 `EPIPE` 错误。(#13414)感谢 @keshav55。
- 网关/控制界面:解决当 `openclaw` 通过基于符号链接的 Node 管理器(nvm/fnm/n/Homebrew)全局安装时,仪表板资源缺失的问题。(#14919)感谢 @aynorica。
- 定时任务:使用请求的 `agentId` 进行独立作业的认证解析。(#13983)感谢 @0xRaini。
- 定时任务:防止当 `nextRunAtMs` 提前时,定时任务跳过执行。(#14068)感谢 @WalterSumbon。
- 定时任务:为主会话作业传递 `agentId` 到 `runHeartbeatOnce`。(#14140)感谢 @ishikawa-pro。
- 定时任务:当 `onTimer` 触发时若作业仍在执行,则重新设置定时器。(#14233)感谢 @tomron87。
- 定时任务:防止多个作业同时触发时重复执行。(#14256)感谢 @xinhuagu。
- 定时任务:隔离调度器错误,确保单个错误作业不会影响所有作业。(#14385)感谢 @MarvinDontPanic。
- 定时任务:防止一次性 `at` 作业在重启后因跳过/错误运行而重新触发。(#13878)感谢 @lailoo。
- 心跳:防止调度器因意外运行错误而停滞,并避免在 `requests-in-flight` 跳过执行后立即进入重试循环。(#14901)感谢 @joeykrug。
- 定时任务:为独立代理运行保留存储的会话模型覆盖,同时保持 Gmail 钩子会话中 `hooks.gmail.model` 的优先级。(#14983)感谢 @shtse8。
- 日志/浏览器:当 `/tmp/openclaw` 不可用时,回退到 `os.tmpdir()/openclaw` 作为默认的日志、浏览器跟踪和浏览器下载临时路径。
- WhatsApp:将 Markdown 粗体/删除线转换为 WhatsApp 格式化文本。(#14285)感谢 @Raikan10。
- WhatsApp:允许仅发送媒体消息,并规范化开头的空白负载。(#14408)感谢 @karimnaguib。
- WhatsApp:当 Baileys 未提供时,为语音消息设置默认 MIME 类型。(#14444)感谢 @mcaxtr。
- Telegram:处理模型选择器中 `editMessageText` 的无文本消息情况。(#14397)感谢 @0xRaini。
- Telegram:将 `REACTION_INVALID` 作为非致命警告显示。(#14340)感谢 @0xRaini。
- BlueBubbles:修复通过环回代理信任导致的 Webhook 认证绕过问题。(#13787)感谢 @coygeek。
- Slack:将默认的 `replyToMode` 从 "off" 改为 "all"。(#14364)感谢 @nm-de。
- Slack:当频道消息以机器人提及前缀开头时(例如 `@Bot /new`),检测控制命令。(#14142)感谢 @beefiker。
- Signal:在 Signal 机器人账户提示中强制执行 E.164 验证,以便及早捕获输入错误的号码。(#15063)感谢 @Duartemartins。
- Discord:处理私信反应,而非静默丢弃。(#10418)感谢 @mcaxtr。
- Discord:在主题线程中遵守 `replyToMode` 设置。(#11062)感谢 @cordx56。
- 心跳:过滤仅包含噪声的系统事件,确保当定时任务运行仅携带心跳标记时,不会触发计划提醒通知。(#13317)感谢 @pvtclawn。
- Signal:将提及占位符渲染为 `@uuid`/`@phone`,以便提及门控和 Clawdbot 目标定位正常工作。(#2013)感谢 @alexgleason。
- Discord:对于仅包含媒体的消息,省略空的内容字段,同时保留标题空白。(#9507)感谢 @leszekszpunar。
- 入门/提供商:新增 Z.AI 端点特定的认证选项(`zai-coding-global`、`zai-coding-cn`、`zai-global`、`zai-cn`),并扩展默认的 Z.AI 模型配置。(#13456)感谢 @tomsun28。
- 入门/提供商:将 MiniMax API 的默认/推荐模型从 M2.1 更新为 M2.5,添加 M2.5/M2.5-Lightning 模型条目,并将 `minimax-m2.5` 包含在现代模型筛选中。(#14865)感谢 @adao-max。
- Ollama:使用配置的 `models.providers.ollama.baseUrl` 进行模型发现,并将 `/v1` 端点标准化到原生 Ollama API 根路径。(#14131)感谢 @shtse8。
- 语音通话:通过 `<Parameter>` 而非查询字符串传递 Twilio 流认证令牌。(#14029)感谢 @mcwigglesmcgee。
- 飞书:将 `Buffer` 直接传递给飞书 SDK 上传 API,而非使用 `Readable.from(...)`,以避免表单数据上传失败。(#10345)感谢 @youngerstyle。
- 飞书:仅当机器人本身被提及时(而非任何提及)才触发提及门控的群组处理。(#11088)感谢 @openperf。
- 飞书:探测状态使用已解析的账户上下文进行多账户凭证检查。(#11233)感谢 @onevcat。
- 飞书 DocX:在写入/追加文档时,使用 `firstLevelBlockIds` 保留顶级转换块的顺序。(#13994)感谢 @Cynosure159。
- 飞书插件打包:从 `extensions/feishu` 中移除 `workspace:*` `openclaw` 依赖,并同步 lockfile 以确保安装兼容性。(#14423)感谢 @jackcooper2015。
- CLI/向导:当 `configure`、`agents add` 或交互式 `onboard` 向导被取消时,以代码 1 退出,以便 `set -e` 自动化脚本正确停止。(#14156)感谢 @0xRaini。
- 媒体:移除包含本地路径的 `MEDIA:` 行,而非将其作为可见文本泄露。(#14399)感谢 @0xRaini。
- 配置/定时任务:从配置脱敏中排除 `maxTokens`,并在跳过的定时任务中遵守 `deleteAfterRun` 设置。(#13342)感谢 @niceysam。
- 配置:在配置文件监视器中忽略 `meta` 字段的更改。(#13460)感谢 @brandonwise。
- 定时任务:使用请求的 `agentId` 进行独立作业的认证解析。(#13983)感谢 @0xRaini。
- 定时任务:为主会话作业传递 `agentId` 到 `runHeartbeatOnce`。(#14140)感谢 @ishikawa-pro。
- 定时任务:防止当 `nextRunAtMs` 提前时,定时任务跳过执行。(#14068)感谢 @WalterSumbon。
- 定时任务:当 `onTimer` 触发时若作业仍在执行,则重新设置定时器。(#14233)感谢 @tomron87。
- 定时任务:防止多个作业同时触发时重复执行。(#14256)感谢 @xinhuagu。
- 定时任务:隔离调度器错误,确保单个错误作业不会影响所有作业。(#14385)感谢 @MarvinDontPanic。
- 定时任务:防止一次性 `at` 作业在重启后因跳过/错误运行而重新触发。(#13878)感谢 @lailoo。
- 守护进程:在重启 LaunchAgent 时抑制 `EPIPE` 错误。(#14343)感谢 @0xRaini。
- Antigravity:添加 opus 4.6 前向兼容模型,并绕过思考签名清理。(#14218)感谢 @jg-noncelogic。
- 代理:防止子进程清理中的文件描述符泄漏。(#13565)感谢 @KyleChen26。
- 代理:防止因缓存 TTL 绕过防护而导致的双重压缩。(#13514)感谢 @taw0002。
- 代理:使用最后一次 API 调用的缓存令牌进行上下文显示,而非累计总和。(#13805)感谢 @akari-musubi。
- 代理:通过使用最后一次调用的用量和共享的令牌计数逻辑,保持后续运行器会话的 `totalTokens` 与压缩后上下文一致。(#14979)感谢 @shtse8。
- 钩子/插件:将 9 个先前未接入的插件生命周期钩子接入核心运行时路径(会话、压缩、网关和出站消息钩子)。(#14882)感谢 @shtse8。
- 钩子/工具:从两个工具执行路径分发 `before_tool_call` 和 `after_tool_call` 钩子,并附带修复后的冲突合并。(#15012)感谢 @Patrick-Barletta, @Takhoffman。
- Discord:允许通过频道编辑归档/锁定主题线程并设置自动归档时长。(#5542)感谢 @stumct。
- Discord 测试:在斜杠命令覆盖测试中使用部分 @buape/carbon 模拟。(#13262)感谢 @arosstale。
- 测试:更新 Slack 消息收集测试中的线程 ID 处理。(#14108)感谢 @swizzmagik。
### Changes
- CLI: add `openclaw logs --local-time` to display log timestamps in local timezone. (#13818) Thanks @xialonglee.
- Telegram: render blockquotes as native `<blockquote>` tags instead of stripping them. (#14608)
- Config: avoid redacting `maxTokens`-like fields during config snapshot redaction, preventing round-trip validation failures in `/config`. (#14006) Thanks @constansino.
### Breaking
- Hooks: `POST /hooks/agent` now rejects payload `sessionKey` overrides by default. To keep fixed hook context, set `hooks.defaultSessionKey` (recommended with `hooks.allowedSessionKeyPrefixes: ["hook:"]`). If you need legacy behavior, explicitly set `hooks.allowRequestSessionKey: true`. Thanks @alpernae for reporting.
### Fixes
- Gateway/OpenResponses: harden URL-based `input_file`/`input_image` handling with explicit SSRF deny policy, hostname allowlists (`files.urlAllowlist` / `images.urlAllowlist`), per-request URL input caps (`maxUrlParts`), blocked-fetch audit logging, and regression coverage/docs updates.
- Security: fix unauthenticated Nostr profile API remote config tampering. (#13719) Thanks @coygeek.
- Security: remove bundled soul-evil hook. (#14757) Thanks @Imccccc.
- Security/Audit: add hook session-routing hardening checks (`hooks.defaultSessionKey`, `hooks.allowRequestSessionKey`, and prefix allowlists), and warn when HTTP API endpoints allow explicit session-key routing.
- Security/Sandbox: confine mirrored skill sync destinations to the sandbox `skills/` root and stop using frontmatter-controlled skill names as filesystem destination paths. Thanks @1seal.
- Security/Web tools: treat browser/web content as untrusted by default (wrapped outputs for browser snapshot/tabs/console and structured external-content metadata for web tools), and strip `toolResult.details` from model-facing transcript/compaction inputs to reduce prompt-injection replay risk.
- Security/Hooks: harden webhook and device token verification with shared constant-time secret comparison, and add per-client auth-failure throttling for hook endpoints (`429` + `Retry-After`). Thanks @akhmittra.
- Security/Browser: require auth for loopback browser control HTTP routes, auto-generate `gateway.auth.token` when browser control starts without auth, and add a security-audit check for unauthenticated browser control. Thanks @tcusolle.
- Sessions/Gateway: harden transcript path resolution and reject unsafe session IDs/file paths so session operations stay within agent sessions directories. Thanks @akhmittra.
- Gateway: raise WS payload/buffer limits so 5,000,000-byte image attachments work reliably. (#14486) Thanks @0xRaini.
- Logging/CLI: use local timezone timestamps for console prefixing, and include `±HH:MM` offsets when using `openclaw logs --local-time` to avoid ambiguity. (#14771) Thanks @0xRaini.
- Gateway: drain active turns before restart to prevent message loss. (#13931) Thanks @0xRaini.
- Gateway: auto-generate auth token during install to prevent launchd restart loops. (#13813) Thanks @cathrynlavery.
- Gateway: prevent `undefined`/missing token in auth config. (#13809) Thanks @asklee-klawd.
- Gateway: handle async `EPIPE` on stdout/stderr during shutdown. (#13414) Thanks @keshav55.
- Gateway/Control UI: resolve missing dashboard assets when `openclaw` is installed globally via symlink-based Node managers (nvm/fnm/n/Homebrew). (#14919) Thanks @aynorica.
- Cron: use requested `agentId` for isolated job auth resolution. (#13983) Thanks @0xRaini.
- Cron: prevent cron jobs from skipping execution when `nextRunAtMs` advances. (#14068) Thanks @WalterSumbon.
- Cron: pass `agentId` to `runHeartbeatOnce` for main-session jobs. (#14140) Thanks @ishikawa-pro.
- Cron: re-arm timers when `onTimer` fires while a job is still executing. (#14233) Thanks @tomron87.
- Cron: prevent duplicate fires when multiple jobs trigger simultaneously. (#14256) Thanks @xinhuagu.
- Cron: isolate scheduler errors so one bad job does not break all jobs. (#14385) Thanks @MarvinDontPanic.
- Cron: prevent one-shot `at` jobs from re-firing on restart after skipped/errored runs. (#13878) Thanks @lailoo.
- Heartbeat: prevent scheduler stalls on unexpected run errors and avoid immediate rerun loops after `requests-in-flight` skips. (#14901) Thanks @joeykrug.
- Cron: honor stored session model overrides for isolated-agent runs while preserving `hooks.gmail.model` precedence for Gmail hook sessions. (#14983) Thanks @shtse8.
- Logging/Browser: fall back to `os.tmpdir()/openclaw` for default log, browser trace, and browser download temp paths when `/tmp/openclaw` is unavailable.
- WhatsApp: convert Markdown bold/strikethrough to WhatsApp formatting. (#14285) Thanks @Raikan10.
- WhatsApp: allow media-only sends and normalize leading blank payloads. (#14408) Thanks @karimnaguib.
- WhatsApp: default MIME type for voice messages when Baileys omits it. (#14444) Thanks @mcaxtr.
- Telegram: handle no-text message in model picker editMessageText. (#14397) Thanks @0xRaini.
- Telegram: surface REACTION_INVALID as non-fatal warning. (#14340) Thanks @0xRaini.
- BlueBubbles: fix webhook auth bypass via loopback proxy trust. (#13787) Thanks @coygeek.
- Slack: change default replyToMode from "off" to "all". (#14364) Thanks @nm-de.
- Slack: detect control commands when channel messages start with bot mention prefixes (for example, `@Bot /new`). (#14142) Thanks @beefiker.
- Signal: enforce E.164 validation for the Signal bot account prompt so mistyped numbers are caught early. (#15063) Thanks @Duartemartins.
- Discord: process DM reactions instead of silently dropping them. (#10418) Thanks @mcaxtr.
- Discord: respect replyToMode in threads. (#11062) Thanks @cordx56.
- Heartbeat: filter noise-only system events so scheduled reminder notifications do not fire when cron runs carry only heartbeat markers. (#13317) Thanks @pvtclawn.
- Signal: render mention placeholders as `@uuid`/`@phone` so mention gating and Clawdbot targeting work. (#2013) Thanks @alexgleason.
- Discord: omit empty content fields for media-only messages while preserving caption whitespace. (#9507) Thanks @leszekszpunar.
- Onboarding/Providers: add Z.AI endpoint-specific auth choices (`zai-coding-global`, `zai-coding-cn`, `zai-global`, `zai-cn`) and expand default Z.AI model wiring. (#13456) Thanks @tomsun28.
- Onboarding/Providers: update MiniMax API default/recommended models from M2.1 to M2.5, add M2.5/M2.5-Lightning model entries, and include `minimax-m2.5` in modern model filtering. (#14865) Thanks @adao-max.
- Ollama: use configured `models.providers.ollama.baseUrl` for model discovery and normalize `/v1` endpoints to the native Ollama API root. (#14131) Thanks @shtse8.
- Voice Call: pass Twilio stream auth token via `<Parameter>` instead of query string. (#14029) Thanks @mcwigglesmcgee.
- Feishu: pass `Buffer` directly to the Feishu SDK upload APIs instead of `Readable.from(...)` to avoid form-data upload failures. (#10345) Thanks @youngerstyle.
- Feishu: trigger mention-gated group handling only when the bot itself is mentioned (not just any mention). (#11088) Thanks @openperf.
- Feishu: probe status uses the resolved account context for multi-account credential checks. (#11233) Thanks @onevcat.
- Feishu DocX: preserve top-level converted block order using `firstLevelBlockIds` when writing/appending documents. (#13994) Thanks @Cynosure159.
- Feishu plugin packaging: remove `workspace:*` `openclaw` dependency from `extensions/feishu` and sync lockfile for install compatibility. (#14423) Thanks @jackcooper2015.
- CLI/Wizard: exit with code 1 when `configure`, `agents add`, or interactive `onboard` wizards are canceled, so `set -e` automation stops correctly. (#14156) Thanks @0xRaini.
- Media: strip `MEDIA:` lines with local paths instead of leaking as visible text. (#14399) Thanks @0xRaini.
- Config/Cron: exclude `maxTokens` from config redaction and honor `deleteAfterRun` on skipped cron jobs. (#13342) Thanks @niceysam.
- Config: ignore `meta` field changes in config file watcher. (#13460) Thanks @brandonwise.
- Cron: use requested `agentId` for isolated job auth resolution. (#13983) Thanks @0xRaini.
- Cron: pass `agentId` to `runHeartbeatOnce` for main-session jobs. (#14140) Thanks @ishikawa-pro.
- Cron: prevent cron jobs from skipping execution when `nextRunAtMs` advances. (#14068) Thanks @WalterSumbon.
- Cron: re-arm timers when `onTimer` fires while a job is still executing. (#14233) Thanks @tomron87.
- Cron: prevent duplicate fires when multiple jobs trigger simultaneously. (#14256) Thanks @xinhuagu.
- Cron: isolate scheduler errors so one bad job does not break all jobs. (#14385) Thanks @MarvinDontPanic.
- Cron: prevent one-shot `at` jobs from re-firing on restart after skipped/errored runs. (#13878) Thanks @lailoo.
- Daemon: suppress `EPIPE` error when restarting LaunchAgent. (#14343) Thanks @0xRaini.
- Antigravity: add opus 4.6 forward-compat model and bypass thinking signature sanitization. (#14218) Thanks @jg-noncelogic.
- Agents: prevent file descriptor leaks in child process cleanup. (#13565) Thanks @KyleChen26.
- Agents: prevent double compaction caused by cache TTL bypassing guard. (#13514) Thanks @taw0002.
- Agents: use last API call's cache tokens for context display instead of accumulated sum. (#13805) Thanks @akari-musubi.
- Agents: keep followup-runner session `totalTokens` aligned with post-compaction context by using last-call usage and shared token-accounting logic. (#14979) Thanks @shtse8.
- Hooks/Plugins: wire 9 previously unwired plugin lifecycle hooks into core runtime paths (session, compaction, gateway, and outbound message hooks). (#14882) Thanks @shtse8.
- Hooks/Tools: dispatch `before_tool_call` and `after_tool_call` hooks from both tool execution paths with rebased conflict fixes. (#15012) Thanks @Patrick-Barletta, @Takhoffman.
- Discord: allow channel-edit to archive/lock threads and set auto-archive duration. (#5542) Thanks @stumct.
- Discord tests: use a partial @buape/carbon mock in slash command coverage. (#13262) Thanks @arosstale.
- Tests: update thread ID handling in Slack message collection tests. (#14108) Thanks @swizzmagik.