### 变更内容
- **模型/Google**:添加 Gemini 3.1 支持 (`google/gemini-3.1-pro-preview`)。
- **提供商/入门**:添加火山引擎(豆包)和 BytePlus 提供商/模型(包括编码变体),为交互式和非交互式流程配置入门身份验证选项,并将文档与 `volcengine-api-key` 对齐。(#7967) 感谢 @funmore123。
- **渠道/CLI**:添加按账户/渠道的 `defaultTo` 出站路由回退,以便当配置了默认目标时,`openclaw agent --deliver` 可以在没有明确 `--reply-to` 的情况下发送。(#16985) 感谢 @KirillShchetinin。
- **渠道**:允许通过 `channels.modelByChannel` 进行按渠道的模型覆盖,并在 /status 中注明。感谢 @thewilloftheshadow。
- **Telegram/流式传输**:将预览流式传输配置简化为 `channels.telegram.streaming`(布尔值),自动映射旧的 `streamMode` 值,并移除块与部分预览的分支逻辑。(#22012) 感谢 @obviyus。
- **Discord/流式传输**:为实时草稿回复添加流式预览模式,包含部分/块选项和可配置的分块。感谢 @thewilloftheshadow。灵感来自 @neoagentic-ship-it。
- **Discord/Telegram**:为排队/思考/工具/完成/错误阶段添加可配置的生命周期状态反应,使用共享控制器和表情/时间覆盖。感谢 @wolly-tundracube 和 @thewilloftheshadow。
- **Discord/语音**:通过 `/vc` 添加语音频道加入/离开/状态功能,以及用于实时语音对话的自动加入配置。感谢 @thewilloftheshadow。
- **Discord**:为斜杠命令响应添加可配置的临时性默认设置。(#16563) 感谢 @wei。
- **Discord**:支持通过频道编辑操作更新论坛 `available_tags`,用于论坛标签管理。(#12070) 感谢 @xiaoyaner0201。
- **Discord**:在新会话的受信任入站元数据中包含频道主题。感谢 @thewilloftheshadow。
- **Discord/子代理**:在 Discord 上添加线程绑定的子代理会话,具有按线程的焦点/列表控制,以及为衍生的辅助代理提供线程绑定的延续路由。(#21805) 感谢 @onutc。
- **iOS/聊天**:通过剥离入站不受信任的元数据/时间戳前缀、将工具输出格式化为简洁摘要/错误、在输入时压缩撰写器,并支持在聊天视图中点击关闭键盘,来清理聊天界面噪音。(#22122) 感谢 @mbelinky。
- **iOS/手表**:将镜像的手表提示通知操作桥接到 iOS 快速回复处理中,包括排队操作移交直到应用模型初始化完成。(#22123) 感谢 @mbelinky。
- **iOS/网关**:通过后台重连抑制/租用窗口、BGAppRefresh 唤醒回退、位置唤醒钩子节流以及 APNs 唤醒重试+轻推检测,稳定后台唤醒和重连行为。(#21226) 感谢 @mbelinky。
- **自动回复/UI**:在详细日志中添加模型回退生命周期可见性,在 /status 活动模型上下文中添加回退原因,以及统一的 WebUI 回退指示器。(#20704) 感谢 @joshavant。
- **MSTeams**:通过移除重复的每条消息 Set 存储并使用时间戳 Map 键作为单一成员资格来源,来对已发送消息缓存存储进行去重。(#22514) 感谢 @TaKO8Ki。
- **代理/子代理**:子代理默认衍生深度现在使用共享的 `maxSpawnDepth=2`,默认启用深度为 1 的编排器衍生,同时保持衍生和提示路径的深度策略检查一致。(#22223) 感谢 @tyler6204。
- **安全/代理**:使所有者 ID 混淆使用配置中的专用 HMAC 密钥 (`ownerDisplaySecret`),并更新哈希行为,使混淆与网关令牌处理解耦,以改进控制。(#7343) 感谢 @vincentkoc。
- **安全/基础设施**:将网关锁和工具调用合成 ID 从 SHA-1 切换到 SHA-256,同时保持截断长度不变,以加强哈希基础,同时保持确定性行为和锁键格式。(#7343) 感谢 @vincentkoc。
- **依赖项/工具**:通过 Knip/ts-prune/ts-unused-exports 在 CI 中添加非阻塞的死代码扫描,以更早地发现未使用的依赖项和导出。(#22468) 感谢 @vincentkoc。
- **依赖项/未使用的依赖项**:移除或限定未使用的根依赖项和扩展依赖项 (`@larksuiteoapi/node-sdk`, `signal-utils`, `ollama`, `lit`, `@lit/context`, `@lit-labs/signals`, `@microsoft/agents-hosting-express`, `@microsoft/agents-hosting-extensions-teams`,以及插件本地的 `openclaw` devDeps,位于 `extensions/open-prose`, `extensions/lobster`, `extensions/llm-task`)。(#22471, #22495) 感谢 @vincentkoc。
- **依赖项/A2UI**:在根清理后强化依赖项解析(从工作区/根解析 `lit`, `@lit/context`, `@lit-labs/signals`, `signal-utils`)并简化捆绑回退行为,包括 `pnpm dlx rolldown` 兼容性。(#22481, #22507) 感谢 @vincentkoc。
### 修复内容
- **安全/代理**:使用更高的配置文件感知动态限制(32-160 次尝试)来限制嵌入式 Pi 运行器外部重试循环,并在重试永不收敛时返回明确的 `retry_limit` 错误负载,防止无限制的内部重试循环 (`GHSA-76m6-pj3w-v7mf`)。
- **Telegram**:在启动/状态时检测跨 Telegram 账户的重复机器人令牌所有权,将次要账户标记为未配置并显示明确的修复消息,并在轮询前阻止重复账户启动,以避免无尽的 `getUpdates` 冲突循环。
- **代理/工具图像**:在 `agents/tool-images` 调整大小日志中包含源文件名,以便压缩事件可以追溯到特定文件。
- **提供商/OAuth**:通过验证刷新响应过期值并在提供商返回空刷新令牌字段时保留先前的刷新令牌,来强化 Qwen 和 Chutes 的刷新处理,并为空令牌响应提供回归覆盖。
- **模型/Kimi-Coding**:为 `kimi-coding` 添加缺失的隐式提供商模板,包含正确的 `anthropic-messages` API 类型和基础 URL,修复使用 Kimi 进行编码时的 403 错误。(#22409)
- **自动回复/工具**:通过嵌入式排队/后续运行器参数转发 `senderIsOwner`,以便仅限所有者的工具对授权发送者保持可用。(#22296) 感谢 @hcoj。
- **Discord**:当提供商缺失时恢复模型选择器的返回导航,并记录 Discord 选择器流程。(#21458) 感谢 @pejmanjohn 和 @thewilloftheshadow。
- **内存/QMD**:在网关 QMD 启动初始化期间,尊重每个代理的 `memorySearch.enabled=false`,将多集合 QMD 搜索拆分为每个集合的查询 (`search`/`vsearch`/`query`) 以避免稀疏项丢失,优先使用集合提示的文档解析以避免陈旧哈希冲突,在瞬态锁/超时失败时重试启动更新,在仅 BM25 的 `search` 模式(包括 `memory index --force`)中跳过 `qmd embed`,并全局序列化嵌入运行并具有失败回退,以防止多代理主机上的 CPU 风暴。(#20581, #21590, #20513, #20001, #21266, #21583, #20346, #19493) 感谢 @danielrevivo, @zanderkrause, @sunyan034-cmd, @tilleulenspiegel, @dae-oss, @adamlongcreativellc, @jonathanadams96, 和 @kiliansitel。
- **内存/内置**:通过跳过关闭后的同步启动并在关闭 SQLite 前等待正在进行的同步,来防止自动同步竞争与管理器关闭,使得 `onSearch`/`onSessionStart` 在临时 CLI 流程中不再因 `database is not open` 而失败。(#20556, #7464) 感谢 @FuzzyTG 和 @henrybottter。
- **提供商/Copilot**:为 Claude 模型删除持久化的助手 `thinking` 块(同时保留回合结构/工具块),以便后续请求不再因无效的 `thinkingSignature` 负载而失败。(#19459) 感谢 @jackheuberger。
- **提供商/Copilot**:将 `claude-sonnet-4.6` 和 `claude-sonnet-4.5` 添加到默认的 GitHub Copilot 模型目录,并为模型列表/定义助手添加覆盖。(#20270, 修复 #20091) 感谢 @Clawborn。
- **自动回复/WebChat**:避免将入站运行时频道标签默认设置为不相关的提供商(例如 `whatsapp`)用于 webchat 会话,以便频道特定的格式化指导保持准确。(#21534) 感谢 @lbo728。
- **状态**:在会话摘要中包含持久化的 `cacheRead`/`cacheWrite`,以便紧凑的 `/status` 输出始终显示来自真实会话数据的缓存命中百分比。
- **心跳/Cron**:恢复间隔心跳行为,以便缺失的 `HEARTBEAT.md` 不再抑制运行(仅实际为空的文件会跳过),保留提示驱动和带标签的 cron 执行路径。
- **WhatsApp/Cron/心跳**:通过合并配对存储 + 配置的 `allowFrom` 收件人来强制执行隐式计划/系统传递的白名单路由,当最后路由上下文指向非白名单聊天时选择授权收件人,并防止心跳扩散到最近未授权的聊天。
- **心跳/活动时间**:在时间验证中将活动时间 `24` 哨兵解析限制为 `24:00`,以便像 `24:30` 这样的无效值被尽早拒绝。(#21410) 感谢 @adhitShet。
- **心跳**:将 `start`/`end` 时间相同的 `activeHours` 窗口视为零宽度(始终在窗口外),而不是始终活动。(#21408) 感谢 @adhitShet。
- **CLI/配对**:当省略时,将 `pairing list` 和 `pairing approve` 默认为唯一可用的配对频道,以便仅 TUI 的设置可以从 `pairing required` 中恢复,而无需猜测频道参数。(#21527) 感谢 @losts1。
- **TUI/配对**:在网关断开连接返回 `pairing required` 后显示明确的配对要求恢复指导,包括批准步骤以解除对新安装的快速启动 TUI 孵化的阻塞。(#21841) 感谢 @nicolinux。
- **TUI/输入**:抑制在同一输入突发窗口中到达的重复退格事件,以便 SSH 会话在撰写器中不再每次按退格键删除两个字符。(#19318) 感谢 @eheimer。
- **TUI/心跳**:当 `showOk` 禁用时,抑制聊天流式传输中的心跳 ACK/提示噪音,同时仍在最终输出中保留非 ACK 心跳警报。(#20228) 感谢 @bhalliburton。
- **TUI/历史记录**:限制聊天日志组件增长并修剪陈旧的渲染节点/引用,以便大的默认历史记录加载不再因 `RangeError: Maximum call stack size exceeded` 而溢出渲染递归。(#18068) 感谢 @JaniJegoroff。
- **内存/QMD**:当会话和内存集合同时存在时,多样化混合来源搜索排名,以便会话转录命中不再在顶部结果中排挤持久内存文件匹配。(#19913) 感谢 @alextempr。
- **内存/工具**:当嵌入/提供商失败(包括配额耗尽)发生时,从 `memory_search` 返回明确的 `unavailable` 警告/操作,以便禁用的内存看起来不像空的召回结果。(#21894) 感谢 @XBS9。
- **会话/启动**:要求 `/new` 和 `/reset` 问候路径在响应前运行会话启动文件读取指令,以便每日内存启动上下文不会在新会话问候时被跳过。(#22338) 感谢 @armstrong-pv。
- **身份验证/入门**:将 OAuth 配置文件 ID 配置映射与存储的凭据 ID 对齐,用于 OpenAI Codex 和 Chutes 流程,防止当 OAuth 返回电子邮件范围的凭据时出现 `provider:default` 不匹配。(#12692) 感谢 @mudrii。
- **提供商/HTTP**:将 HTTP 503 视为 LLM 提供商错误的故障转移资格。(#21086) 感谢 @Protocol-zero-0。
- **Slack**:通过 Slack 原生流式调用传递 `recipient_team_id` / `recipient_user_id`,以便 `chat.startStream`/`appendStream`/`stopStream` 在 DM 和 Slack Connect 设置中可靠工作,并在原生流式传输活动时禁用块流式传输。(#20988) 感谢 @Dithilli。早期的收件人 ID 基础工作由 @AsserAl1012 在 #20377 中贡献。
- **CLI/配置**:为 `config set` 添加规范的 `--strict-json` 解析,并保留 `--json` 作为旧别名以减少帮助/行为漂移。(#21332) 感谢 @adhitShet。
- **CLI**:保持 `openclaw -v` 作为仅根级别的版本别名,以便子命令的 `-v, --verbose` 标志(例如 ACP/钩子/技能)不再被全局拦截。(#21303) 感谢 @adhitShet。
- **内存**:当 `memory_get`/QMD 读取尚未创建的文件时返回空片段,并强化内存索引/会话助手以抵御 ENOENT 竞争,以便缺失的 Markdown 不再导致工具崩溃。(#20680) 感谢 @pahdo。
- **Telegram/流式传输**:即使在分派抛出异常进行回退处理之前,也始终清理草稿预览,防止在运行失败期间出现孤立的预览消息。(#19041) 感谢 @mudrii。
- **Telegram/流式传输**:拆分推理和答案草稿预览通道以防止跨通道覆盖,并忽略内联/围栏代码片段中的字面 `<think>` 标签,以便示例标记不会被误路由为推理。(#20774) 感谢 @obviyus。
- **Telegram/流式传输**:恢复 30 字符的首个预览防抖,并将 `NO_REPLY` 前缀抑制范围限定为部分哨兵片段,以便正常的 `No...` 文本不被过滤。(#22613) 感谢 @obviyus。
- **Telegram/状态反应**:在重复的阶段更新时刷新停滞计时器,并在启用生命周期反应时确认反应范围,防止虚假的停滞表情和不想要的群组反应。感谢 @wolly-tundracube 和 @thewilloftheshadow。
- **Telegram/状态反应**:当可用反应查找失败时,通过回退到无限制的变体选择而不是抑制反应更新,来保持生命周期反应活动。(#22380) 感谢 @obviyus。
- **Discord/流式传输**:仅将 `replyToMode: first` 应用于第一个 Discord 块,以便块流式回复不会垃圾邮件式地提及 ping。(#20726) 感谢 @thewilloftheshadow 的报告。
- **Discord/组件**:将 DM 频道目标映射回用户范围的组件会话,以便按钮/选择交互保持在主 DM 会话中。感谢 @thewilloftheshadow。
- **Discord/白名单**:在解析 Discord 用户白名单时延迟加载公会列表,以便即使公会获取失败,仅 ID 的条目也能解析。(#20208) 感谢 @zhangjunmengyang。
- **Discord/网关**:处理关闭代码 4014(缺少特权网关意图)而不使网关崩溃。感谢 @thewilloftheshadow。
- **Discord**:将入站贴纸作为媒体摄取,以便仅贴纸的消息和转发的贴纸对代理可见。感谢 @thewilloftheshadow。
- **自动回复/运行器**:仅在代理生命周期或工具活动开始后(且每次运行仅一次)发出 `onAgentRunStart`,以便回退预检错误不再将运行标记为已开始。(#21165) 感谢 @shakkernerd。
- **自动回复/工具结果**:序列化工具结果传递,并在单个失败后保持传递链继续进行,以便并发工具输出保持用户可见的顺序。(#21231) 感谢 @ahdernasr。
- **自动回复/提示缓存**:通过保持入站系统元数据会话稳定,并将每条消息的 ID (`message_id`, `message_id_full`, `reply_to_id`, `sender_id`) 移动到不受信任的对话上下文中,来恢复前缀缓存稳定性。(#20597) 感谢 @anisoptera。
- **iOS/手表**:添加可操作的手表批准/拒绝控件和快速回复操作,以便手表发起的批准和响应可以直接从通知流程发送。(#21996) 感谢 @mbelinky。
- **iOS/手表**:使用龙虾图标集刷新 iOS 和手表应用图标资源,以保持手机/手表品牌一致。(#21997) 感谢 @mbelinky。
- **CLI/入门**:通过规范化基础 URL 以避免在设置检查期间出现重复的 `/v1` 路径,来修复 Anthropic 兼容的自定义提供商验证。(#21336) 感谢 @17jmumford。
- **iOS/网关/工具**:当存在重复显示名称时,优先选择唯一连接的节点匹配,提供带有请求 ID 的可操作的 `nodes invoke` 配对要求指导,并在位置能力设置更改后刷新活动的 iOS 网关注册,以便能力更新立即应用。(#22120) 感谢 @mbelinky。
- **网关/身份
### Changes
- Models/Google: add Gemini 3.1 support (`google/gemini-3.1-pro-preview`).
- Providers/Onboarding: add Volcano Engine (Doubao) and BytePlus providers/models (including coding variants), wire onboarding auth choices for interactive + non-interactive flows, and align docs to `volcengine-api-key`. (#7967) Thanks @funmore123.
- Channels/CLI: add per-account/channel `defaultTo` outbound routing fallback so `openclaw agent --deliver` can send without explicit `--reply-to` when a default target is configured. (#16985) Thanks @KirillShchetinin.
- Channels: allow per-channel model overrides via `channels.modelByChannel` and note them in /status. Thanks @thewilloftheshadow.
- Telegram/Streaming: simplify preview streaming config to `channels.telegram.streaming` (boolean), auto-map legacy `streamMode` values, and remove block-vs-partial preview branching. (#22012) thanks @obviyus.
- Discord/Streaming: add stream preview mode for live draft replies with partial/block options and configurable chunking. Thanks @thewilloftheshadow. Inspiration @neoagentic-ship-it.
- Discord/Telegram: add configurable lifecycle status reactions for queued/thinking/tool/done/error phases with a shared controller and emoji/timing overrides. Thanks @wolly-tundracube and @thewilloftheshadow.
- Discord/Voice: add voice channel join/leave/status via `/vc`, plus auto-join configuration for realtime voice conversations. Thanks @thewilloftheshadow.
- Discord: add configurable ephemeral defaults for slash-command responses. (#16563) Thanks @wei.
- Discord: support updating forum `available_tags` via channel edit actions for forum tag management. (#12070) Thanks @xiaoyaner0201.
- Discord: include channel topics in trusted inbound metadata on new sessions. Thanks @thewilloftheshadow.
- Discord/Subagents: add thread-bound subagent sessions on Discord with per-thread focus/list controls and thread-bound continuation routing for spawned helper agents. (#21805) Thanks @onutc.
- iOS/Chat: clean chat UI noise by stripping inbound untrusted metadata/timestamp prefixes, formatting tool outputs into concise summaries/errors, compacting the composer while typing, and supporting tap-to-dismiss keyboard in chat view. (#22122) thanks @mbelinky.
- iOS/Watch: bridge mirrored watch prompt notification actions into iOS quick-reply handling, including queued action handoff until app model initialization. (#22123) thanks @mbelinky.
- iOS/Gateway: stabilize background wake and reconnect behavior with background reconnect suppression/lease windows, BGAppRefresh wake fallback, location wake hook throttling, and APNs wake retry+nudge instrumentation. (#21226) thanks @mbelinky.
- Auto-reply/UI: add model fallback lifecycle visibility in verbose logs, /status active-model context with fallback reason, and cohesive WebUI fallback indicators. (#20704) Thanks @joshavant.
- MSTeams: dedupe sent-message cache storage by removing duplicate per-message Set storage and using timestamps Map keys as the single membership source. (#22514) Thanks @TaKO8Ki.
- Agents/Subagents: default subagent spawn depth now uses shared `maxSpawnDepth=2`, enabling depth-1 orchestrator spawning by default while keeping depth policy checks consistent across spawn and prompt paths. (#22223) Thanks @tyler6204.
- Security/Agents: make owner-ID obfuscation use a dedicated HMAC secret from configuration (`ownerDisplaySecret`) and update hashing behavior so obfuscation is decoupled from gateway token handling for improved control. (#7343) Thanks @vincentkoc.
- Security/Infra: switch gateway lock and tool-call synthetic IDs from SHA-1 to SHA-256 with unchanged truncation length to strengthen hash basis while keeping deterministic behavior and lock key format. (#7343) Thanks @vincentkoc.
- Dependencies/Tooling: add non-blocking dead-code scans in CI via Knip/ts-prune/ts-unused-exports to surface unused dependencies and exports earlier. (#22468) Thanks @vincentkoc.
- Dependencies/Unused Dependencies: remove or scope unused root and extension deps (`@larksuiteoapi/node-sdk`, `signal-utils`, `ollama`, `lit`, `@lit/context`, `@lit-labs/signals`, `@microsoft/agents-hosting-express`, `@microsoft/agents-hosting-extensions-teams`, and plugin-local `openclaw` devDeps in `extensions/open-prose`, `extensions/lobster`, and `extensions/llm-task`). (#22471, #22495) Thanks @vincentkoc.
- Dependencies/A2UI: harden dependency resolution after root cleanup (resolve `lit`, `@lit/context`, `@lit-labs/signals`, and `signal-utils` from workspace/root) and simplify bundling fallback behavior, including `pnpm dlx rolldown` compatibility. (#22481, #22507) Thanks @vincentkoc.
### Fixes
- Security/Agents: cap embedded Pi runner outer retry loop with a higher profile-aware dynamic limit (32-160 attempts) and return an explicit `retry_limit` error payload when retries never converge, preventing unbounded internal retry cycles (`GHSA-76m6-pj3w-v7mf`).
- Telegram: detect duplicate bot-token ownership across Telegram accounts at startup/status time, mark secondary accounts as not configured with an explicit fix message, and block duplicate account startup before polling to avoid endless `getUpdates` conflict loops.
- Agents/Tool images: include source filenames in `agents/tool-images` resize logs so compression events can be traced back to specific files.
- Providers/OAuth: harden Qwen and Chutes refresh handling by validating refresh response expiry values and preserving prior refresh tokens when providers return empty refresh token fields, with regression coverage for empty-token responses.
- Models/Kimi-Coding: add missing implicit provider template for `kimi-coding` with correct `anthropic-messages` API type and base URL, fixing 403 errors when using Kimi for Coding. (#22409)
- Auto-reply/Tools: forward `senderIsOwner` through embedded queued/followup runner params so owner-only tools remain available for authorized senders. (#22296) thanks @hcoj.
- Discord: restore model picker back navigation when a provider is missing and document the Discord picker flow. (#21458) Thanks @pejmanjohn and @thewilloftheshadow.
- Memory/QMD: respect per-agent `memorySearch.enabled=false` during gateway QMD startup initialization, split multi-collection QMD searches into per-collection queries (`search`/`vsearch`/`query`) to avoid sparse-term drops, prefer collection-hinted doc resolution to avoid stale-hash collisions, retry boot updates on transient lock/timeout failures, skip `qmd embed` in BM25-only `search` mode (including `memory index --force`), and serialize embed runs globally with failure backoff to prevent CPU storms on multi-agent hosts. (#20581, #21590, #20513, #20001, #21266, #21583, #20346, #19493) Thanks @danielrevivo, @zanderkrause, @sunyan034-cmd, @tilleulenspiegel, @dae-oss, @adamlongcreativellc, @jonathanadams96, and @kiliansitel.
- Memory/Builtin: prevent automatic sync races with manager shutdown by skipping post-close sync starts and waiting for in-flight sync before closing SQLite, so `onSearch`/`onSessionStart` no longer fail with `database is not open` in ephemeral CLI flows. (#20556, #7464) Thanks @FuzzyTG and @henrybottter.
- Providers/Copilot: drop persisted assistant `thinking` blocks for Claude models (while preserving turn structure/tool blocks) so follow-up requests no longer fail on invalid `thinkingSignature` payloads. (#19459) Thanks @jackheuberger.
- Providers/Copilot: add `claude-sonnet-4.6` and `claude-sonnet-4.5` to the default GitHub Copilot model catalog and add coverage for model-list/definition helpers. (#20270, fixes #20091) Thanks @Clawborn.
- Auto-reply/WebChat: avoid defaulting inbound runtime channel labels to unrelated providers (for example `whatsapp`) for webchat sessions so channel-specific formatting guidance stays accurate. (#21534) Thanks @lbo728.
- Status: include persisted `cacheRead`/`cacheWrite` in session summaries so compact `/status` output consistently shows cache hit percentages from real session data.
- Heartbeat/Cron: restore interval heartbeat behavior so missing `HEARTBEAT.md` no longer suppresses runs (only effectively empty files skip), preserving prompt-driven and tagged-cron execution paths.
- WhatsApp/Cron/Heartbeat: enforce allowlisted routing for implicit scheduled/system delivery by merging pairing-store + configured `allowFrom` recipients, selecting authorized recipients when last-route context points to a non-allowlisted chat, and preventing heartbeat fan-out to recent unauthorized chats.
- Heartbeat/Active hours: constrain active-hours `24` sentinel parsing to `24:00` in time validation so invalid values like `24:30` are rejected early. (#21410) thanks @adhitShet.
- Heartbeat: treat `activeHours` windows with identical `start`/`end` times as zero-width (always outside the window) instead of always-active. (#21408) thanks @adhitShet.
- CLI/Pairing: default `pairing list` and `pairing approve` to the sole available pairing channel when omitted, so TUI-only setups can recover from `pairing required` without guessing channel arguments. (#21527) Thanks @losts1.
- TUI/Pairing: show explicit pairing-required recovery guidance after gateway disconnects that return `pairing required`, including approval steps to unblock quickstart TUI hatching on fresh installs. (#21841) Thanks @nicolinux.
- TUI/Input: suppress duplicate backspace events arriving in the same input burst window so SSH sessions no longer delete two characters per backspace press in the composer. (#19318) Thanks @eheimer.
- TUI/Heartbeat: suppress heartbeat ACK/prompt noise in chat streaming when `showOk` is disabled, while still preserving non-ACK heartbeat alerts in final output. (#20228) Thanks @bhalliburton.
- TUI/History: cap chat-log component growth and prune stale render nodes/references so large default history loads no longer overflow render recursion with `RangeError: Maximum call stack size exceeded`. (#18068) Thanks @JaniJegoroff.
- Memory/QMD: diversify mixed-source search ranking when both session and memory collections are present so session transcript hits no longer crowd out durable memory-file matches in top results. (#19913) Thanks @alextempr.
- Memory/Tools: return explicit `unavailable` warnings/actions from `memory_search` when embedding/provider failures occur (including quota exhaustion), so disabled memory does not look like an empty recall result. (#21894) Thanks @XBS9.
- Session/Startup: require the `/new` and `/reset` greeting path to run Session Startup file-reading instructions before responding, so daily memory startup context is not skipped on fresh-session greetings. (#22338) Thanks @armstrong-pv.
- Auth/Onboarding: align OAuth profile-id config mapping with stored credential IDs for OpenAI Codex and Chutes flows, preventing `provider:default` mismatches when OAuth returns email-scoped credentials. (#12692) thanks @mudrii.
- Provider/HTTP: treat HTTP 503 as failover-eligible for LLM provider errors. (#21086) Thanks @Protocol-zero-0.
- Slack: pass `recipient_team_id` / `recipient_user_id` through Slack native streaming calls so `chat.startStream`/`appendStream`/`stopStream` work reliably across DMs and Slack Connect setups, and disable block streaming when native streaming is active. (#20988) Thanks @Dithilli. Earlier recipient-ID groundwork was contributed in #20377 by @AsserAl1012.
- CLI/Config: add canonical `--strict-json` parsing for `config set` and keep `--json` as a legacy alias to reduce help/behavior drift. (#21332) thanks @adhitShet.
- CLI: keep `openclaw -v` as a root-only version alias so subcommand `-v, --verbose` flags (for example ACP/hooks/skills) are no longer intercepted globally. (#21303) thanks @adhitShet.
- Memory: return empty snippets when `memory_get`/QMD read files that have not been created yet, and harden memory indexing/session helpers against ENOENT races so missing Markdown no longer crashes tools. (#20680) Thanks @pahdo.
- Telegram/Streaming: always clean up draft previews even when dispatch throws before fallback handling, preventing orphaned preview messages during failed runs. (#19041) thanks @mudrii.
- Telegram/Streaming: split reasoning and answer draft preview lanes to prevent cross-lane overwrites, and ignore literal `<think>` tags inside inline/fenced code snippets so sample markup is not misrouted as reasoning. (#20774) Thanks @obviyus.
- Telegram/Streaming: restore 30-char first-preview debounce and scope `NO_REPLY` prefix suppression to partial sentinel fragments so normal `No...` text is not filtered. (#22613) thanks @obviyus.
- Telegram/Status reactions: refresh stall timers on repeated phase updates and honor ack-reaction scope when lifecycle reactions are enabled, preventing false stall emojis and unwanted group reactions. Thanks @wolly-tundracube and @thewilloftheshadow.
- Telegram/Status reactions: keep lifecycle reactions active when available-reactions lookup fails by falling back to unrestricted variant selection instead of suppressing reaction updates. (#22380) thanks @obviyus.
- Discord/Streaming: apply `replyToMode: first` only to the first Discord chunk so block-streamed replies do not spam mention pings. (#20726) Thanks @thewilloftheshadow for the report.
- Discord/Components: map DM channel targets back to user-scoped component sessions so button/select interactions stay in the main DM session. Thanks @thewilloftheshadow.
- Discord/Allowlist: lazy-load guild lists when resolving Discord user allowlists so ID-only entries resolve even if guild fetch fails. (#20208) Thanks @zhangjunmengyang.
- Discord/Gateway: handle close code 4014 (missing privileged gateway intents) without crashing the gateway. Thanks @thewilloftheshadow.
- Discord: ingest inbound stickers as media so sticker-only messages and forwarded stickers are visible to agents. Thanks @thewilloftheshadow.
- Auto-reply/Runner: emit `onAgentRunStart` only after agent lifecycle or tool activity begins (and only once per run), so fallback preflight errors no longer mark runs as started. (#21165) Thanks @shakkernerd.
- Auto-reply/Tool results: serialize tool-result delivery and keep the delivery chain progressing after individual failures so concurrent tool outputs preserve user-visible ordering. (#21231) thanks @ahdernasr.
- Auto-reply/Prompt caching: restore prefix-cache stability by keeping inbound system metadata session-stable and moving per-message IDs (`message_id`, `message_id_full`, `reply_to_id`, `sender_id`) into untrusted conversation context. (#20597) Thanks @anisoptera.
- iOS/Watch: add actionable watch approval/reject controls and quick-reply actions so watch-originated approvals and responses can be sent directly from notification flows. (#21996) Thanks @mbelinky.
- iOS/Watch: refresh iOS and watch app icon assets with the lobster icon set to keep phone/watch branding aligned. (#21997) Thanks @mbelinky.
- CLI/Onboarding: fix Anthropic-compatible custom provider verification by normalizing base URLs to avoid duplicate `/v1` paths during setup checks. (#21336) Thanks @17jmumford.
- iOS/Gateway/Tools: prefer uniquely connected node matches when duplicate display names exist, surface actionable `nodes invoke` pairing-required guidance with request IDs, and refresh active iOS gateway registration after location-capability setting changes so capability updates apply immediately. (#22120) thanks @mbelinky.
- Gateway/Auth: require `gateway.trustedProxies` to include a loopback proxy address when `auth.mode="trusted-proxy"` and `bind="loopback"`, preventing same-host proxy misconfiguration from silently blocking auth. (#22082, follow-up to #20097) thanks @mbelinky.
- Gateway/Auth: allow trusted-proxy mode with loopback bind for same-host reverse-proxy deployments, while still requiring configured `gateway.trustedProxies`. (#20097) thanks @xinhuagu.
- Gateway/Auth: allow authenticated clients across roles/scopes to call `health` while preserving role and scope enforcement for non-health methods. (#19699) thanks @Nachx639.
- Gateway/Hooks: include transform export name in hook-transform cache keys so distinct exports from the same module do not reuse the wrong cached transform function. (#13855) thanks @mcaxtr.
- Gateway/Control UI: return 404 for missing static-asset paths instead of serving SPA fallback HTML, while preserving client-route fallback behavior for extensionless and non-asset dotted paths. (#12060) thanks @mcaxtr.
- Gateway/Pairing: prevent device-token rotate scope escalation by enforcing an approved-scope baseline, preserving approved scopes across metadata updates, and rejecting rotate requests that exceed approved role scope implications. (#20703) thanks @coygeek.
- Gateway/Pairing: clear persisted paired-device state when the gateway client closes with `device token mismatch` (`1008`) so reconnect flows can cleanly re-enter pairing. (#22071) Thanks @mbelinky.
- Gateway/Config: allow `gateway.customBindHost` in strict config validation when `gateway.bind="custom"` so valid custom bind-host configurations no longer fail startup. (#20318, fixes #20289) Thanks @MisterGuy420.
- Gateway/Pairing: tolerate legacy paired devices missing `roles`/`scopes` metadata in websocket upgrade checks and backfill metadata on reconnect. (#21447, fixes #21236) Thanks @joshavant.
- Gateway/Pairing/CLI: align read-scope compatibility in pairing/device-token checks and add local `openclaw devices` fallback recovery for loopback `pairing required` deadlocks, with explicit fallback notice to unblock approval bootstrap flows. (#21616) Thanks @shakkernerd.
- Cron: honor `cron.maxConcurrentRuns` in the timer loop so due jobs can execute up to the configured parallelism instead of always running serially. (#11595) Thanks @Takhoffman.
- Agents/Compaction: restore embedded compaction safeguard/context-pruning extension loading in production by wiring bundled extension factories into the resource loader instead of runtime file-path resolution. (#22349) Thanks @Glucksberg.
- Agents/Subagents: restore announce-chain delivery to agent injection, defer nested announce output until descendant follow-up content is ready, and prevent descendant deferrals from consuming announce retry budget so deep chains do not drop final completions. (#22223) Thanks @tyler6204.
- Agents/System Prompt: label allowlisted senders as authorized senders to avoid implying ownership. Thanks @thewilloftheshadow.
- Agents/Tool display: fix exec cwd suffix inference so `pushd ... && popd ... && <command>` does not keep stale `(in <dir>)` context in summaries. (#21925) Thanks @Lukavyi.
- Tools/web_search: handle xAI Responses API payloads that emit top-level `output_text` blocks (without a `message` wrapper) so Grok web_search no longer returns `No response` for those results. (#20508) Thanks @echoVic.
- Agents/Failover: treat non-default override runs as direct fallback-to-configured-primary (skip configured fallback chain), normalize default-model detection for provider casing/whitespace, and add regression coverage for override/auth error paths. (#18820) Thanks @Glucksberg.
- Docker/Build: include `ownerDisplay` in `CommandsSchema` object-level defaults so Docker `pnpm build` no longer fails with `TS2769` during plugin SDK d.ts generation. (#22558) Thanks @obviyus.
- Docker/Browser: install Playwright Chromium into `/home/node/.cache/ms-playwright` and set `node:node` ownership so browser binaries are available to the runtime user in browser-enabled images. (#22585) thanks @obviyus.
- Hooks/Session memory: trigger bundled `session-memory` persistence on both `/new` and `/reset` so reset flows no longer skip markdown transcript capture before archival. (#21382) Thanks @mofesolapaul.
- Dependencies/Agents: bump embedded Pi SDK packages (`@mariozechner/pi-agent-core`, `@mariozechner/pi-ai`, `@mariozechner/pi-coding-agent`, `@mariozechner/pi-tui`) to `0.54.0`. (#21578) Thanks @Takhoffman.
- Config/Agents: expose Pi compaction tuning values `agents.defaults.compaction.reserveTokens` and `agents.defaults.compaction.keepRecentTokens` in config schema/types and apply them in embedded Pi runner settings overrides with floor enforcement via `reserveTokensFloor`. (#21568) Thanks @Takhoffman.
- Docker: pin base images to SHA256 digests in Docker builds to prevent mutable tag drift. (#7734) Thanks @coygeek.
- Docker: run build steps as the `node` user and use `COPY --chown` to avoid recursive ownership changes, trimming image size and layer churn. Thanks @huntharo.
- Config/Memory: restore schema help/label metadata for hybrid `mmr` and `temporalDecay` settings so configuration surfaces show correct names and guidance. (#18786) Thanks @rodrigouroz.
- Skills/SonosCLI: add troubleshooting guidance for `sonos discover` failures on macOS direct mode (`sendto: no route to host`) and sandbox network restrictions (`bind: operation not permitted`). (#21316) Thanks @huntharo.
- macOS/Build: default release packaging to `BUNDLE_ID=ai.openclaw.mac` in `scripts/package-mac-dist.sh`, so Sparkle feed URL is retained and auto-update no longer fails with an empty appcast feed. (#19750) thanks @loganprit.
- Signal/Outbound: preserve case for Base64 group IDs during outbound target normalization so cross-context routing and policy checks no longer break when group IDs include uppercase characters. (#5578) Thanks @heyhudson.
- Anthropic/Agents: preserve required pi-ai default OAuth beta headers when `context1m` injects `anthropic-beta`, preventing 401 auth failures for `sk-ant-oat-*` tokens. (#19789, fixes #19769) Thanks @minupla.
- Security/Exec: block unquoted heredoc body expansion tokens in shell allowlist analysis, reject unterminated heredocs, and require explicit approval for allowlisted heredoc execution on gateway hosts to prevent heredoc substitution allowlist bypass. Thanks @torturado for reporting.
- macOS/Security: evaluate `system.run` allowlists per shell segment in macOS node runtime and companion exec host (including chained shell operators), fail closed on shell/process substitution parsing, and require explicit approval on unsafe parse cases to prevent allowlist bypass via `rawCommand` chaining. Thanks @tdjackey for reporting.
- WhatsApp/Security: enforce allowlist JID authorization for reaction actions so authenticated callers cannot target non-allowlisted chats by forging `chatJid` + valid `messageId` pairs. Thanks @aether-ai-agent for reporting.
- ACP/Security: escape control and delimiter characters in ACP `resource_link` title/URI metadata before prompt interpolation to prevent metadata-driven prompt injection through resource links. Thanks @aether-ai-agent for reporting.
- TTS/Security: make model-driven provider switching opt-in by default (`messages.tts.modelOverrides.allowProvider=false` unless explicitly enabled), while keeping voice/style overrides available, to reduce prompt-injection-driven provider hops and unexpected TTS cost escalation. Thanks @aether-ai-agent for reporting.
- Security/Agents: keep overflow compaction retry budgeting global across tool-result truncation recovery so successful truncation cannot reset the overflow retry counter and amplify retry/cost cycles. Thanks @aether-ai-agent for reporting.
- BlueBubbles/Security: require webhook token authentication for all BlueBubbles webhook requests (including loopback/proxied setups), removing passwordless webhook fallback behavior. Thanks @zpbrent.
- iOS/Security: force `https://` for non-loopback manual gateway hosts during iOS onboarding to block insecure remote transport URLs. (#21969) Thanks @mbelinky.
- Gateway/Security: remove shared-IP fallback for canvas endpoints and require token or session capability for canvas access. Thanks @thewilloftheshadow.
- Gateway/Security: require secure context and paired-device checks for Control UI auth even when `gateway.controlUi.allowInsecureAuth` is set, and align audit messaging with the hardened behavior. (#20684) Thanks @coygeek and @Vasco0x4 for reporting.
- Gateway/Security: scope tokenless Tailscale forwarded-header auth to Control UI websocket auth only, so HTTP gateway routes still require token/password even on trusted hosts. Thanks @zpbrent for reporting.
- Docker/Security: run E2E and install-sh test images as non-root by adding appuser directives. Thanks @thewilloftheshadow.
- Skills/Security: sanitize skill env overrides to block unsafe runtime injection variables and only allow sensitive keys when declared in skill metadata, with warnings for suspicious values. Thanks @thewilloftheshadow.
- Security/Commands: block prototype-key injection in runtime `/debug` overrides and require own-property checks for gated command flags (`bash`, `config`, `debug`) so inherited prototype values cannot enable privileged commands. Thanks @tdjackey for reporting.
- Security/Browser: block non-network browser navigation protocols (including `file:`, `data:`, and `javascript:`) while preserving `about:blank`, preventing local file reads via browser tool navigation. Thanks @q1uf3ng for reporting.
- Security/Exec: block shell startup-file env injection (`BASH_ENV`, `ENV`, `BASH_FUNC_*`, `LD_*`, `DYLD_*`) across config env ingestion, node-host inherited environment sanitization, and macOS exec host runtime to prevent pre-command execution from attacker-controlled environment variables. Thanks @tdjackey.
- Security/Exec (Windows): canonicalize `cmd.exe /c` command text across validation, approval binding, and audit/event rendering to prevent trailing-argument approval mismatches in `system.run`. Thanks @tdjackey for reporting.
- Security/Gateway/Hooks: block `__proto__`, `constructor`, and `prototype` traversal in webhook template path resolution to prevent prototype-chain payload data leakage in `messageTemplate` rendering. (#22213) Thanks @SleuthCo.
- Security/OpenClawKit/UI: prevent injected inbound user context metadata blocks from leaking into chat history in TUI, webchat, and macOS surfaces by stripping all untrusted metadata prefixes at display boundaries. (#22142) Thanks @Mellowambience, @vincentkoc.
- Security/OpenClawKit/UI: strip inbound metadata blocks from user messages in TUI rendering while preserving user-authored content. (#22345) Thanks @kansodata, @vincentkoc.
- Security/OpenClawKit/UI: prevent inbound metadata leaks and reply-tag streaming artifacts in TUI rendering by stripping untrusted metadata prefixes at display boundaries. (#22346) Thanks @akramcodez, @vincentkoc.
- Security/Agents: restrict local MEDIA tool attachments to core tools and the OpenClaw temp root to prevent untrusted MCP tool file exfiltration. Thanks @NucleiAv and @thewilloftheshadow.
- Security/Net: strip sensitive headers (`Authorization`, `Proxy-Authorization`, `Cookie`, `Cookie2`) on cross-origin redirects in `fetchWithSsrFGuard` to prevent credential forwarding across origin boundaries. (#20313) Thanks @afurm.
- Security/Systemd: reject CR/LF in systemd unit environment values and fix argument escaping so generated units cannot be injected with extra directives. Thanks @thewilloftheshadow.
- Security/Tools: add per-wrapper random IDs to untrusted-content markers from `wrapExternalContent`/`wrapWebContent`, preventing marker spoofing from escaping content boundaries. (#19009) Thanks @Whoaa512.
- Shared/Security: reject insecure deep links that use `ws://` non-loopback gateway URLs to prevent plaintext remote websocket configuration. (#21970) Thanks @mbelinky.
- macOS/Security: reject non-loopback `ws://` remote gateway URLs in macOS remote config to block insecure plaintext websocket endpoints. (#21971) Thanks @mbelinky.
- Browser/Security: block upload path symlink escapes so browser upload sources cannot traverse outside the allowed workspace via symlinked paths. (#21972) Thanks @mbelinky.
- Security/Dependencies: bump transitive `hono` usage to `4.11.10` to incorporate timing-safe authentication comparison hardening for `basicAuth`/`bearerAuth` (`GHSA-gq3j-xvxp-8hrf`). Thanks @vincentkoc.
- Security/Gateway: parse `X-Forwarded-For` with trust-preserving semantics when requests come from configured trusted proxies, preventing proxy-chain spoofing from influencing client IP classification and rate-limit identity. Thanks @AnthonyDiSanti and @vincentkoc.
- Security/Sandbox: remove default `--no-sandbox` for the browser container entrypoint, add explicit opt-in via `OPENCLAW_BROWSER_NO_SANDBOX` / `CLAWDBOT_BROWSER_NO_SANDBOX`, and add security-audit checks for stale/missing sandbox browser Docker hash labels. Thanks @TerminalsandCoffee and @vincentkoc.
- Security/Sandbox Browser: require VNC password auth for noVNC observer sessions in the sandbox browser entrypoint, plumb per-container noVNC passwords from runtime, and emit short-lived noVNC observer token URLs while keeping loopback-only host port publishing. Thanks @TerminalsandCoffee for reporting.
- Security/Sandbox Browser: default browser sandbox containers to a dedicated Docker network (`openclaw-sandbox-browser`), add optional CDP ingress source-range restrictions, auto-create missing dedicated networks, and warn in `openclaw security --audit` when browser sandboxing runs on bridge without source-range limits. Thanks @TerminalsandCoffee for reporting.
> Note: npm shipped a follow-up update fix as `
[email protected]`.