From 9f2a8ec6e0375e2ddcf547fe3332d1cc016e0403 Mon Sep 17 00:00:00 2001 From: Willem Jiang Date: Thu, 24 Sep 2026 10:56:44 +0800 Subject: [PATCH] chore(doc):Updated the CHANGLOG_zh.md for 2.1.0 --- CHANGELOG_zh.md | 114 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 24 deletions(-) diff --git a/CHANGELOG_zh.md b/CHANGELOG_zh.md index 0605420167..b44e78b267 100644 --- a/CHANGELOG_zh.md +++ b/CHANGELOG_zh.md @@ -10,7 +10,7 @@ ## [未发布] 本节累积面向 **2.1.0** 里程碑([里程碑 2](https://github.com/bytedance/deer-flow/milestone/2))的工作。 -该里程碑随本次发布收尾,共合并 **765 个 pull request**。 +该里程碑随本次发布收尾,共合并 **772 个 pull request**。 ### ⚠ 不兼容变更(Breaking Changes) @@ -727,25 +727,61 @@ ### 修复 +- **前端:** 项目会话行上的 `…`(kebab)菜单不再溢出侧边栏。在侧边栏的按项目分组模式下, + 缩进的嵌套菜单继承了 `SidebarMenu` 的 `w-full` 又额外带着 `ml-4`,实际宽度是"100% + 16px", + 其绝对定位的 `right-1` 操作按钮因此落到侧边栏边缘之外——活跃项目分组下的行被裁剪,Archived + 分组下双层缩进的行则完全看不到按钮;扁平会话列表(唯一不带缩进的菜单)不受影响,这也是问题 + 此前未被发现的原因。两个嵌套菜单现在改用 `w-auto`,块级 flex 容器按"剩余宽度减去外边距"填充。 + 除布局修复本身外,行为、数据与 API 均无变化。([#5682]) +- **持久化:** 修复静默跳过了 run-change clock schema 的数据库。`0023_run_change_seq` 被插到了 + 已经发布的 `0023_user_preferences` 修订之前,因此在该修订点(或之后)盖章的数据库会把它当作 + 已应用的祖先而从不执行——`run_change_clock` 表与 `runs.change_seq` 列永久缺失,第一次删除会话 + (任何 run-store change-clock 递增)就会以 `no such table: run_change_clock` 失败。新增的 + `0025_repair_run_change_seq` 修订在升级时重新应用同一份带守卫的 DDL,在形态健康的库上空操作。 + `RunChangeClockRow` 与 `UserPreferenceRow` 也已注册进 ORM 模型注册表,`create_all` 与 + autogenerate 通过显式导入(而非模块副作用)看到所有表。([#5517]) +- **后端:** 为 LangGraph 兼容的 `POST /api/assistants/search` 增加分页校验。此前 `limit` 与 + `offset` 直接用于 Python 切片,`offset: -1`、`limit: 0` 之类的非法值乃至过大的 limit 都会返回 + `200` 和误导性的结果,而不是在 API 边界被拒绝。现在 `limit` 必须落在兼容范围的 1~1000 内, + `offset` 必须非负;非法请求返回 `422`。([#5506]) +- **模型:** Claude Code 凭据加载器现在能防护格式错误的 `claudeAiOauth` 容器。 + `~/.claude/.credentials.json` 可能是合法 JSON 但 `claudeAiOauth` 的值不是对象——部分导出遗留的 + `null`、原始字符串、数组或数字——此前提取器会对它调用 `.get`,从 + `ClaudeChatModel.model_post_init` 抛出 `AttributeError` 并中断模型构造,与该模块文档声明的 + "优雅降级"行为相反(同属模型加载器的 Codex 一侧早已对同样形态做了防护)。现在顶层 payload + 或 `claudeAiOauth` 值不是对象时,会以 debug 级别记录并视为"此来源没有凭据",加载流程继续尝试 + 下一个来源,所有来源都不可用时最终返回 `None`。([#5494]) +- **事件:** 删除会话时保持 DB 写锁的代际稳定。`DbRunEventStore` 用一把 `asyncio.Lock` 串行化 + 每会话的序列号分配,而 `delete_by_thread()` 只要发现 `lock.locked()` 为假就把锁从注册表移除 + ——但 `asyncio.Lock.release()` 会先清除锁定状态、再让排队的等待者恢复运行,删除若恰好落在这个 + 交接窗口内,就会在已入队的等待者仍引用旧锁时移除注册表项。随后同一会话的新写入者会创建新一代 + 锁,两个写入者可能各持一把锁并行推进,破坏围绕 `max(seq) + INSERT` 的单进程串行化保证。现在 + 注册表改为弱引用,已入队的持锁者/等待者在自己排空之前锁仍可被发现;另用单独的强引用 pin 维持 + 正常运行中"每会话一把锁"的既有行为,删除只回收 pin。([#5462]) +- **setup:** BOM 前缀配置中的自定义 sandbox 镜像现在会生效。`setup-sandbox.sh` 用 `^sandbox:` + 去匹配仍带着 UTF-8 BOM 的首行,匹配失败后静默选择并拉取默认镜像,而运行时 YAML 加载器其实 + 接受同一份配置。脚本现在在进入镜像选择流程前剥离首行开头的 UTF-8 BOM,未引入新的运行时依赖。 + ([#5515]) +- **网关:** 关停时的运行排空在重复取消下得以存活。`_drain_inflight_runs()` 会对 + `RunManager.shutdown()` 任务加 shield 并再次 await,但第二次 `Task.cancel()` 若落在第二个 + shield 尚未完成时,会打断 helper 自身,让 lifespan 在运行任务仍在排空时继续退出——恰好重新 + 打开该排空机制要防止的资源顺序问题:checkpointer 开始拆除后,运行任务可能仍在写 checkpoint。 + 现在 helper 会强持有已启动的 shutdown 任务并反复 shield 直至其到达终态,记住首次调用方取消 + 并在有界排空完成后再传播;排空自身失败时的日志与错误行为保持不变。([#5487]) +- **模型:** Codex 的无效工具调用现在与其工具结果成对重放。Codex 模型发出 `arguments` 不是 + 合法 JSON 的 `function_call` 时并不会让本轮失败:调用被记入 `invalid_tool_calls`,由 + `DanglingToolCallMiddleware` 以占位 `ToolMessage` 应答,模型看到的是可恢复的工具错误。但 + Codex Responses 序列化器只对有效的 `tool_calls` 生成输入项,占位结果作为 + `function_call_output` 到达 provider 时,同一请求里没有与之配对的 `function_call`,而 + Responses API 要求二者成对——中间件本要恢复的那个场景反而以 provider 报错收场,而不是重试。 + Chat Completions 系 provider 经 LangChain 转换器本就会这样重放无效调用,OpenAI 兼容路径的 + 同类失败也已在中间件层修复;现在 Codex 请求同样把 `invalid_tool_calls` 作为 `function_call` + 输入项与有效调用并列重放。有效调用路径、解析侧与中间件均未改动。([#5509]) - **nginx:** 需要等待模型调用的线程路由不再在 60 秒时失败。浏览器直接调用 `/api/threads/*`, 而该 location 没有设置 `proxy_read_timeout`,因此沿用 nginx 默认的 60 秒,而 `/api/langgraph/` 允许 600 秒。较慢的 `/compact` 会返回 504,但 Gateway 仍会继续执行并保存压缩结果,于是 UI 对已经生效的操作显示错误,诱使用户重试并再次压缩。`/suggestions` 也受同一限制,`/runs/wait` 则会在 nginx 断开连接时取消其运行。Docker、本地开发与 Helm 配置现在都为该 location 允许 600 秒。([#5505]) -- **中间件:** 循环检测不再中断正在分段读取文件的智能体。此前 `read_file` 调用按 200 行分桶作为 - 键,因此任何短于一个桶的读取都会与相邻读取塌缩到同一个键:连续五次 40 行读取会哈希成相同值并 - 触发硬停止,运行被迫给出最终答复并带上 `stop_reason=loop_capped`——而这恰恰是 `read_file` 自身 - 的截断提示要求模型去做的分段读取。现在键使用精确的行区间,省略 `end_line` 时保持"读到末行"的 - 开放语义,因此不带范围的读取与显式 `start_line=1` 仍共用同一个键。重复同一区间依然会在原有阈值 - 被拦下,边界抖动的读取循环仍由按工具类型计数的频率层覆盖。 -- **子智能体:** `max_turns` 现在真正表示运维人员理解的"轮次"。此前它被直接当作 LangGraph 的 - `recursion_limit` 传入,而后者统计的是 super-step——每个图节点一步,且 `create_agent` 会为每个 - 中间件生命周期钩子编译出一个节点,因此在子智能体的中间件链上一轮要花掉 7~8 步:内置 - `general-purpose` 的 `max_turns=150` 实际只买到约 18 轮带工具调用的轮次,随后以 `turn_capped` - 结束;每往链上加一个中间件,有效预算还会再缩水一次。现在执行器会按实际组装出的中间件链的 - 每轮节点数来换算配置的轮次,调高 `max_turns` 就能得到它所声明的轮次。没有配置项变化;既有的 - `max_turns` 取值现在会获得完整预算,因此原先被截断的子智能体运行可能变长,其上界仍由 - `subagents.timeout_seconds` 与 `subagents.token_budget` 约束。 - **middleware:** 循环检测不再中断正在分段读取文件的智能体。`read_file` 调用 此前按 200 行的分桶建键,因此短于一个分桶的读取都会塌缩到相邻分桶上:连续 五次 40 行的读取哈希完全相同,会触发硬停止,使 run 以强制最终答复和 @@ -783,13 +819,6 @@ `parse_remote_search_output` 管的是**原始输出行数**上限,是另一条限制、 有自己的"多放一行"记账方式,其他 provider 的过滤后匹配数上限未作改动。 ([#5449]) - -- **沙箱:** AIO 的 `glob` 不再把"恰好填满"的结果报告为截断。其 `include_dirs` 分支在收集到 - `max_results` 个匹配时就立即返回,因此一个只有这么多匹配、后面再无匹配的目录列表也会被标记为 - 被截断,工具据此告诉模型结果不完整。该分支本就持有整份目录列表,现在改为多看一个匹配再判断, - 与同一函数的 `include_dirs=False` 分支一致(后者一直是按完整列表判断的)。这里涉及的只是 - **过滤后匹配数**上限;`parse_remote_search_output` 管的是**原始输出行数**上限,是另一条限制、 - 有自己的"多放一行"记账方式,其他 provider 的过滤后匹配数上限未作改动。 - **中间件:** 移除工具调用的守卫不再导致 Claude 或 OpenAI Responses 线程之后的每一轮都失败。 token 预算与循环检测的硬停止、subagent 数量限制的截断以及安全终止抑制只清空了 `tool_calls`, 却把 provider 自身的工具调用块留在消息 content 中。Anthropic 与 Responses API 会重新发送这些块, @@ -859,6 +888,26 @@ 后的宿主机路径与解析后的 outputs 根目录再次比对,`outputs/` 内被植入的符号链接同样 无法把写入重定向到别处。该规则现在收敛为一个共享 helper,IM 渠道的附件投递也走同 一实现,两处不会再各自漂移。([#5321]) +- **网关:** 不再把调用方提供的 `deerflow_trace_id` 持久化到 run 记录上。`body.metadata` + 会同时到达运行中的 run config(run worker 会重新盖章)和 runs API 原样回显的 run 记录, + 此前只覆盖了前者,因此客户端可以让 run 最持久的展示面与同一请求的 `X-Trace-Id` 及日志行 + 互相矛盾。现在 id 只在信任边界处盖章一次,`config.context` 也以同样方式封堵,且会话自身 + 的 metadata 不再被写入"创建它的那个 run"的 run 作用域 id。([#5119]) +- **网关:** 在 `Access-Control-Expose-Headers` 中暴露 `X-Trace-Id`。它不在 CORS 安全列表 + 中,因此跨域拆分的浏览器客户端——同样读不到 Gateway 日志的那一方——无法读到本应写进 + bug 报告的关联 id。([#5119]) +- **网关:** 未处理异常的 500 响应现在也携带 `X-Trace-Id`。Starlette 的 + `ServerErrorMiddleware` 通过所有用户中间件之外的原始 send 发出这类响应,因此服务器 bug + 的 500——最需要关联 id 的那个响应——成了唯一不带 id 的响应。`TraceMiddleware` 现在会在 + 重新抛出异常前自行发送一个携带该 header 的 500;服务端的异常日志不受影响,流中途的失败 + 也照旧传播。这一回退响应在 `CORSMiddleware` 之外发出、保持 CORS 不可读,因此跨域拆分的 + 浏览器客户端在这个响应上读不到 id——与它所替换的 `ServerErrorMiddleware` 500 一致。 + ([#5119]) +- **网关:** 从持久化的请求回显中剔除伪造的 `deerflow_trace_id`。`body.config` 会原样存入 + `runs.kwargs_json` 并由 runs API 返回,因此 `config.metadata` 或 `config.context` 中的 + 伪造 id 会在这一处幸存,而其他所有展示面都带着真实 id。`redact_config_secrets` 现在会把 + 该键从两个容器中剔除,`build_run_config` 则将 run metadata 合并到副本上,服务器盖章的 + id 不再能写穿回调用方的请求体。([#5119]) - **运行时:** 会话元数据现在仅在 run 通过启动屏障后才切换为 `running`,待取消的 run 不再短暂呈现 `running` 状态;worker 启动期间客户端可能观察到先前的会话状态 。([#4450]) @@ -2189,12 +2238,12 @@ 概念、快速上手、目录、委派用法、结果与验收、限制与容量、沙箱与隔离、可观测性、 按症状排查、开发者集成,以及附带 2026 年 6 月至 9 月变更记录的参考附录。原单页 成为该章节的索引页,指向该页面的已有链接保持有效;指向旧页面小节锚点的深链接 - 会落到索引页。 + 会落到索引页。([#5761]) - **文档:** 新增中英文扩展开发手册(`harness/extensions/`),覆盖 `deerflow-extension-api` 0.2.1 契约:何时编写扩展、快速上手、运行时模型、中间件 放置位置、生命周期与观察者、服务与路由、运行证据读取器、扩展运维、按错误信息排查, 以及列出全部公开名称和契约版本历史的参考章节。同时修正 `AGENTS.md` 中对贡献类型 - 和运行证据元数据脱敏的过时描述。 + 和运行证据元数据脱敏的过时描述。([#5769]) ### 内部改进 @@ -2245,6 +2294,12 @@ E2E 运行可解析平台对应的包二进制,不再因无扩展名的 POSIX shim 失败。([#5185]) - **测试:** Windows 上跳过 POSIX mode-bit 技能权限断言(`chmod` 契约在该平台不可 观测),使 Windows 贡献者可以获得绿色的后端套件基线。([#5244]) +- **测试:** 针对空技能目录固定 composer 技能建议的行为(RFC #4063 Phase 4):`skills` + 策略不允许任何技能的调用方——或没有任何技能的全新安装——会从 `GET /api/skills` 得到 + `[]`,此时 composer 必须降级为仅含内置命令的下拉框,而不是损坏或彻底消失。新增测试 + 驱动 matcher 并真实挂载 `InputBox`:输入 `/` 时恰好列出内置命令,输入无匹配的查询时 + 不渲染列表框。没有生产代码改动;已审计全部四处 `useSkills()` 消费方,均能优雅降级。 + ([#5490]) ## [2.0.0] — 2026-06-15 @@ -3473,6 +3528,7 @@ DeerFlow 2.0 是围绕"超级智能体"框架的彻底重写,核心包含子 [#5458]: https://github.com/bytedance/deer-flow/pull/5458 [#5459]: https://github.com/bytedance/deer-flow/pull/5459 [#5461]: https://github.com/bytedance/deer-flow/pull/5461 +[#5462]: https://github.com/bytedance/deer-flow/pull/5462 [#5463]: https://github.com/bytedance/deer-flow/pull/5463 [#5465]: https://github.com/bytedance/deer-flow/pull/5465 [#5467]: https://github.com/bytedance/deer-flow/pull/5467 @@ -3487,9 +3543,19 @@ DeerFlow 2.0 是围绕"超级智能体"框架的彻底重写,核心包含子 [#5483]: https://github.com/bytedance/deer-flow/pull/5483 [#5485]: https://github.com/bytedance/deer-flow/pull/5485 [#5486]: https://github.com/bytedance/deer-flow/pull/5486 +[#5487]: https://github.com/bytedance/deer-flow/pull/5487 [#5488]: https://github.com/bytedance/deer-flow/pull/5488 +[#5490]: https://github.com/bytedance/deer-flow/pull/5490 [#5492]: https://github.com/bytedance/deer-flow/pull/5492 +[#5494]: https://github.com/bytedance/deer-flow/pull/5494 [#5496]: https://github.com/bytedance/deer-flow/pull/5496 [#5501]: https://github.com/bytedance/deer-flow/pull/5501 [#5504]: https://github.com/bytedance/deer-flow/pull/5504 [#5505]: https://github.com/bytedance/deer-flow/pull/5505 +[#5506]: https://github.com/bytedance/deer-flow/pull/5506 +[#5509]: https://github.com/bytedance/deer-flow/pull/5509 +[#5515]: https://github.com/bytedance/deer-flow/pull/5515 +[#5517]: https://github.com/bytedance/deer-flow/pull/5517 +[#5682]: https://github.com/bytedance/deer-flow/pull/5682 +[#5761]: https://github.com/bytedance/deer-flow/pull/5761 +[#5769]: https://github.com/bytedance/deer-flow/pull/5769