OpenClaw 24h 更新快报(2026-11-14):模型能力目录、OAuth 刷新、进程代理稳定性

内容管家 其他评论6字数 3918阅读13分3秒阅读模式
OpenClaw 24h 更新快报(2026-11-14):模型能力目录、OAuth 刷新、进程代理稳定性

OpenClaw 24h 更新快报(2026-11-14):模型能力目录、OAuth 刷新、进程代理稳定性

过去 24 小时,openclaw/openclaw 主干合入 247 个 PR,主线不是新功能,而是把几件一直含糊的事收口成契约:模型目录要求显式声明对话能力,共享 OAuth 登录的刷新权回到运行中的 Gateway,进程代理与插件调用作用域的边界也修了几个会让 Gateway 卡死或崩溃循环的坑。

体感变化集中在三处:模型选择不再凭空少掉一批,OAuth 凭据不再反复丢失,2026.9 升级也不再被一次误报失败挡住。

模型与 AI 能力:对话能力变成显式契约

PR #198288 把共享模型发现逻辑改成“必须声明支持 chat/text 或者被目录精确收录”才准入聊天候选。改之前,非对话模型(音频专用、被显式禁用对话的条目)会混进聊天模型列表,用户选中后拿到的却是一个误导性的“模型不存在”错误;更糟的是 provider 侧返回的确定性 HTTP 400 会触发三次压缩重试,把一次本该立刻失败的请求放大成多次重试。现在聊天候选里不再出现非对话模型,已经保存的旧选择也不会被静默改写,而是明确提示“This model doesn't support chat; pick another model.”;压缩路径改用结构化的失败分类器,对确定性失败直接跳过重试。这条改动同时落在 Anthropic、OpenAI、OpenCode、xAI、Qwen、oMLX、Bifrost 等多个扩展上,兼容性风险被单独标了出来。

这次收紧立刻暴露了 provider 侧的信息缺口。PR #198582 修的正是随之而来的回归:LiteLLM 代理在 /v1/models 里给每一行标注自己的 mode: "chat" 字段,但共享发现逻辑并不读取这个字段,于是代理列出的对话模型在 openclaw models list --provider litellm --refresh 中消失,用 openclaw agent --model litellm/<model> 发起对话也会被判定为“不支持对话”而拒绝发送。修法不是让共享逻辑去读所有 provider 的 mode 字段(那会改变所有 OpenAI 兼容 provider 的准入行为),而是像 Anthropic、Baseten 那样,由 LiteLLM 插件自己把 mode: "chat" 投影成 capabilities: { chat: true } 再交给共享规则;嵌入类模型和没有标注 mode 的条目仍然留在聊天之外。文档同步说明:代理列出的聊天部署如果没有 mode,需要显式写 model_info.mode: chat。

模型目录的元数据本身也有一次修补。PR #198465 让原生 Anthropic 模型(包括不在内置清单里的自定义与发现条目)在已配置模型补全和目录发布链路中保留 provider 清单声明的权威 model family,调用方目录不再需要靠猜来判定模型家族。

OpenAI 一侧是一个会让会话永久死掉的问题。PR #198357 修复了回放压缩检查点后每轮都被拒的 item_conflict:真实的 Responses API 只接受一次带 store:true 的压缩窗口,之后再回放同一检查点必然被拒,而清空所有 item ID 依然失败、改为无状态重放(store:false)则成功。共享的 payload 策略现在在原生公开 OpenAI 端点上对压缩输入统一走无状态重放,检查点内容保持原样,普通请求仍保留存量的 HTTP 续传行为。受影响的会话升级后下一轮即可继续,不需要手工编辑或丢弃历史。

工具侧也有一个直接影响提示词预算的改进。PR #198348 把 MCP 工具纳入按使用量排序的 tool index。此前 MCP 工具完全不参与排序,有限的 MCP 目录在 tool_search 描述里要么丢掉所有描述,要么把整个 server 折叠成一行计数——像 Granola 加 Linear 约 100 个工具的组合会直接冲破 4096 字节预算。开启 Settings → Labs → Usage-ranked tool index 后,MCP 工具也能从成功调用中学习,常用工具保留描述、名字不再被折叠,模型可以省掉一次 tool_search 往返。实验关闭时提示词字节数不变。

凭据与授权:只有运行中的 Gateway 能刷新 OAuth

PR #198214 修掉了一类很难自查的故障。“外部写入必须通过 Gateway 或独占离线托管”这条规则此前是逐条命令实现的,任何漏掉检查的命令都可能在一个正在运行的 Gateway 旁边刷新共享 OAuth 登录并写入新 token;Gateway 的 auth 行缓存看不到别的进程的提交,它自己的刷新竞争失败、重读同一行陈旧数据后放弃,从此该 profile 上的每一轮对话都报 No credentials found for profile "<provider>:<account>",直到重启 Gateway 才恢复。修复把 OAuth 刷新收敛成唯一裁决点:只读命令只有在刷新 OAuth 时才可能写凭据;token 仍有效就直接使用,由 Gateway 在下一轮自行刷新;已过期则在写入之前拒绝,并明确告诉用户 Gateway(pid/port)持有共享凭据且只有它能刷新。此前未受保护的命令包括 infer image/audio/video/web/embedding、本地 infer tts convert、infer model auth login/logout,另外 agent --local、agent exec --state-dir、tui --local、models status --probe 还有四份各自为政的重复拒绝提示,这次一并统一。

同一条链路上还有两个更具体的口子。PR #198141 让 openclaw infer model run 走真正拥有状态目录的 Gateway,而不是默认在本地执行——这正是上一条事故里 CLI 抢先刷新凭据的入口。PR #198427 则处理了回退链:当配置的主模型带着账户(例如 openai/<model>@openai:<account>)并且失败时,配置的 Claude CLI / Gemini CLI 回退永远不会启动,报错是 CLI backend "claude-cli" cannot use auth profile "openai:<account>" owned by "openai"。修复后跨 provider 的 CLI 回退用自己的账户作答;用户在会话上主动 pin 的账户(/model …@profile、人员关联的 pin)仍然在 CLI 启动前 fail closed,计划任务沿用原有的记录账户规则。

授权判定本身也做了区分。PR #198245 处理的是策略评估过程本身抛异常的情况:插件访问策略断言里的内部错误(包含调用作用域已关闭)此前被当成“永久拒绝”,直接撤销在线操作者的权限、关闭连接,并让已经准入的派生运行一并失效。修复后“拒绝”与“评估失败”被分开:记录脱敏后的内部错误,先重新计算一次没有被撤销信号的授权,再以不可用错误拒绝这次失败的操作;真正的授权撤销、结束或替换授权、身份变更和插件销毁仍然 fail closed。HTTP 层的策略故障现在返回 503,而不是把凭据问题误报成 401。

节点与自动化的权限边界同时收紧。PR #198553 规定与主设备一同被批准的节点要跟随主设备的证书有效期:主设备证书到期后,绑定节点不再保留访问权,到期清理会同时关掉这两个对象、注销由 ID 派生的配对与令牌,但不影响独立的后代设备、邀请加入的节点和其他本地批准。用户若要保留既有配对,需要在到期前续期;到期之后再单独续证书,则需要重新配对节点。

PR #198621 修的是聊天内改任务的越权路径。生产事故中,agent 通过 automations 工具检查并两次改写了某个 operator 创建、无 owner 的 trusted 任务,重发完整 agent-turn 负载(含 toolsAllow: ["*"]),两次都“成功”;任务因此带上 final-executable-surface 来源、调用方来源未知,却保留 trusted 策略且没有 owner 会话,结果在每次调度准入时都被拒绝,最后自动禁用。修复后聊天不再允许改动无 owner 的 trusted 任务内容,生命周期管理仍然可用,页面、CLI 与 Gateway API 上的直接运维不受影响;没有新增 schema、配置项或迁移。

Gateway 稳定性:崩溃止损与进程代理

PR #198645 是一次线上崩溃循环的止损。团队在 03:54:36Z、04:22:43Z、04:25:26Z 连续三次遭遇 Error: Plugin invocation scope is closed,最后一次在启动后仅 44 秒;每次都是关闭失败、看门狗 SIGKILL、systemd 重启,约两分钟服务中断,正在进行的回合和 agent 子进程一起被杀。堆栈显示进度播报器的重试定时器比渠道插件的调用作用域活得更久,定时器触发时插件包装的可见性判定抛错,而异常从裸 setTimeout 里逃逸出来直接终结进程。这次改动是最小化止损:可见性检查一旦抛错就结束本回合的播报(禁用、清理定时器、verbose 日志),作用域生命周期的根因由另一条线继续追查。

进程代理这边有两个独立的卡顿来源。PR #198478 修复了大型 Node 进程中 detached 回调启动 Git、exec 工具或容器助手时的 Gateway 停顿:spawn broker 的生命周期属于 Gateway,但查找逻辑只查请求级 async context,请求上下文结束后 detached 工作就退回到原生 spawn,哪怕 broker 本身健康。现在 broker 在自己的 owner 处注册就绪句柄,并在主机清理后清除,显式的 native-only 作用域与作用域内 broker 覆盖优先级不变。

PR #198132 面向的是拒绝进程组信号的主机,比如 OpenShell 沙箱的 seccomp 过滤会让带负 PID 的 kill(2) 一律返回 EPERM,而两处探测把 EPERM 当成“进程还活着”,于是 openclaw doctor --fix 和 spawn broker 的关闭永远等下去。对企业版而言,Agent 启动要等 Doctor 报告维护完成,因此升级后 Agent 起不来;修复后这类沙箱可以正常完成 Doctor 维护并关闭 spawn broker,普通主机行为不变。

重启恢复也有一处修复。PR #198640 处理了父会话在重启后一直停住的问题:它们在等一个已暂停的子代理,而上一个进程的完成授权在注册表恢复时被刻意注销了,之前只有非 yield 的终态子节点会检查这一点;现在跟随后续消息或嵌套等待之前同样先做这项检查,受影响的父会话可以通过常规重启恢复流程继续,读取已保存结果或重新准入保留的子任务。

另有一条直接进入主干、没有走 PR 的独立提交 73f9a89(fix(gateway): retain authority through agent config publication),改动集中在 agent 创建与 Gateway 侧的 agents 方法,把 agent 配置发布过程中容易被中途丢掉的授权保留下来。

升级与发布链路

PR #198429 修的是升级误报失败:从已发布的 2026.9.x(包括扩展稳定版 2026.9.37)升级到当前主干时,更新会带着 post-update-failed 和 “Shared state migration did not finish: expected schema 40, found missing” 失败,可更新其实已经装好、Gateway 也是健康的。根因是此前一处改动让候选版本在回复 schema 版本时只保留归属已知的行,而 9.x 的驱动解析候选版本的发现计划时使用的 schema 并不认识这些归属字段,字段在计划回传前被剥离,共享行和 agent 行随之被过滤掉,9.x 的校验器因此判定共享 schema 缺失。修复后 2026.9.x 用户可以正常升到下一个版本,不需要手工执行 openclaw update repair,也不会再出现 state-migrated-no-rollback 这种中间态。

升级流程本身也被改造了一次。PR #197922 指出一个天然的滞后:预更新演练一直由已安装的旧 updater 跑(状态快照、Doctor 演练、测试 Gateway 及其时间预算),于是“把演练修好了”的那次更新,要到下一个版本才对用户生效。现在候选版本会自己先跑一遍演练,新增了包标记 openclaw.updateRehearsalProtocol: 1 和一个隐藏命令 openclaw update rehearse;在此之前发布的更新仍按旧行为走,会忽略新标记。

插件安装环节也有一处环境相关的修复。PR #198431 处理了在某些文件系统上 link() 成功却生成独立副本的情况(报告于 OrbStack 的 virtiofs bind mount,插件位于 node_modules 下):openclaw doctor --fix 以退出码 1 结束,Gateway 则陷入 “Native plugin artifact changed during admission” 的重启循环。硬链接原语此前把“链接成功但 inode 不同”当作源被替换;现在改为丢弃未经校验的输出,改走已有的受控拷贝路径并绑定到准入描述符仍然钉住的 inode,真实的源替换依然会被拒绝。

会话性能与开发者体验

会话层这一轮几乎全是性能与内存优化。PR #198512 让轻量 transcript 读取不再在前台 worker 启动时就加载完整的历史呈现图(哪怕 Control UI 是关闭的),轻量 worker 少占约 10 MiB 堆、首次查找更快,代价是第一次真正请求历史呈现时才付约 160 ms 的延迟导入成本。PR #198434 则把长对话历史反复被扫描的问题解决掉:解冻后的消息根节点此前挂在通用 memo 上,一旦无关活动把 memo 挤掉,准备阶段就会退回到全量扫描,现在这些根节点登记到 transcript 专属 owner,快速路径不再随 memo 淘汰而失效。PR #198610 则让投递侧把会话字段只编码一次 UTF-8 字节,两条信封路径共用这些字节,帧组装保留分段标识,不再假定 1 段或 3 段负载并复制进接收方缓冲区,生产代码净减 6 行。

多实例部署下的操作体验也修了一处。PR #198466 指出,同一台主机上跑多个 Gateway 时,“Pair this browser” 页面给出的 openclaw pair CODE 会打到错误的实例,报 “No browser is waiting for this code”。现在以命名 profile 运行的 Gateway 会显示带 profile 前缀的命令(形如 work:ABCD-EFGH),默认 profile 仍显示纯码,纯码在各处依然被接受;配对页面上只显示该命令、等待状态和取消按钮。

最后是一条直接进入主干、没有对应 PR 的独立提交 530d5bd(fix: PR auto-fix stops following review and CI feedback):PR 自动修复任务在首轮修复之后就停止跟踪后续的 review 意见与 CI 结果,因为失败的触发评估没有被持久化,下一次评估无法重新检测到该事件。修复让 auto-fix 任务把已触发的尝试与已结算的事件历史关联持久化(保住重试计数与冷却),并让原生观测复用与触发条件一致的准入调用方、取消信号和截止时间。改动覆盖 cron 侧的 PR 自动修复服务、GitHub 发布反馈扫描,以及 Control UI 中的 CI 自动化组件。

小结

这一轮的主线是收紧边界:什么算可用模型、谁能写凭据、进程与作用域活多久,都改成可校验的契约;一些原本能用的路径会明确失败,换来更少的静默中断和更可解释的报错。

常用链接

 
内容管家

发表评论