chore(doc):fix the changelog section error (#5868)

This commit is contained in:
Willem Jiang 2026-09-28 11:49:20 +08:00 committed by GitHub
parent b72753c226
commit c89ba45f7f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 107 deletions

View File

@ -1358,6 +1358,30 @@ This release closes that milestone with **181 merged pull requests**.
some later edit. The loader now reads once through a shared
`file_signature.read_config_with_signature()` helper that signs exactly the
returned bytes; a racing edit can only cost one extra reload. ([#5848])
- **dev:** `make stop` / `make dev` can now reclaim dev ports held by a sibling
worktree whose path contains spaces. `serve.sh` built its worktree-root list
with `awk '{print $2}'` over `git worktree list --porcelain`, whose paths are
unquoted, so `.../deer flow two` was recorded as `.../deer`; a Gateway or
frontend started from that worktree was never recognised as deer-flow's and
the start aborted with "port already in use". The whole path is kept now. ([#5856])
- **uploads:** A malformed `files[*].size` in a run's message metadata no
longer fails the whole run. `UploadsMiddleware` validated every other field
of a client-supplied file entry fail-soft but passed `size` straight to
`int()`, so a value such as `"abc"` or a list raised out of `before_agent`
before the model was called — and again on every edit or regenerate of that
message, since the entry is carried over verbatim. The size only feeds the
human-readable line in `<current_uploads>`; unusable values now fall back to
`0`, the same as a missing size, while numeric strings keep working. ([#5855])
- **release:** Bumping the version no longer leaves `backend/uv.lock` behind.
`scripts/bump_version.sh` rewrote `backend/pyproject.toml`, `frontend/package.json`
and the Helm chart, but the lockfile records the root package's own version too
(uv keeps its PEP 440 form, so `2.1.0-rc0` is stored as `2.1.0rc0`). The
documented release step therefore produced a commit whose lock CI rejects:
`uv lock --check` fails on the stale lock and `uv sync --locked` refuses the
tree, and with pre-commit installed it broke a step earlier on the
`uv-lock-check` hook. The script now refreshes the lock with `uv lock` and exits
before editing anything when `uv` is missing, instead of leaving a half-bumped
working tree behind. Only the root package's version line moves. ([#5859])
### Security
@ -2519,71 +2543,6 @@ This release closes that milestone with **772 merged pull requests**.
### Fixed
- **dev:** `make stop` / `make dev` can now reclaim dev ports held by a sibling
worktree whose path contains spaces. `serve.sh` built its worktree-root list
with `awk '{print $2}'` over `git worktree list --porcelain`, whose paths are
unquoted, so `.../deer flow two` was recorded as `.../deer`; a Gateway or
frontend started from that worktree was never recognised as deer-flow's and
the start aborted with "port already in use". The whole path is kept now. ([#5856])
- **uploads:** A malformed `files[*].size` in a run's message metadata no
longer fails the whole run. `UploadsMiddleware` validated every other field
of a client-supplied file entry fail-soft but passed `size` straight to
`int()`, so a value such as `"abc"` or a list raised out of `before_agent`
before the model was called — and again on every edit or regenerate of that
message, since the entry is carried over verbatim. The size only feeds the
human-readable line in `<current_uploads>`; unusable values now fall back to
`0`, the same as a missing size, while numeric strings keep working. ([#5855])
- **release:** Bumping the version no longer leaves `backend/uv.lock` behind.
`scripts/bump_version.sh` rewrote `backend/pyproject.toml`, `frontend/package.json`
and the Helm chart, but the lockfile records the root package's own version too
(uv keeps its PEP 440 form, so `2.1.0-rc0` is stored as `2.1.0rc0`). The
documented release step therefore produced a commit whose lock CI rejects:
`uv lock --check` fails on the stale lock and `uv sync --locked` refuses the
tree, and with pre-commit installed it broke a step earlier on the
`uv-lock-check` hook. The script now refreshes the lock with `uv lock` and exits
before editing anything when `uv` is missing, instead of leaving a half-bumped
working tree behind. Only the root package's version line moves. ([#5859])
- **config:** A `config.yaml` edit that lands while the previous edit is still
being loaded is no longer lost until the next edit. `get_app_config()`'s
loader parsed the file and then hashed it again to record the cache
signature, so a write between those two reads left the cache holding the
older content under the newer content's signature — a state the signature
comparison can never detect. The loader now reads the file once and signs
the bytes it parsed; a write that races the load just triggers one more
reload on the next call. ([#5848])
- **config:** `request_admission.requests_per_minute` and `max_queue_size` now
accept `$VAR` environment references like every other field. Both are strict
integers so a bool or float is still rejected, but `$VAR` substitution always
produces a string, so `requests_per_minute: $RPM` failed the whole config load
with "Input should be a valid integer" even when `RPM=60`. A decimal literal
delivered as a string is now converted before the strict check; any other
string is still rejected. ([#5838])
- **scheduler:** Pausing a scheduled task no longer loses the pause when a
dispatch is in flight on SQLite. `release_dispatch_lease` guards on the lease
owner — which pausing clears — but read the row without taking SQLite's
writer, so a stale read passed the guard and wrote the task back to
`enabled` with `next_run_at` untouched, leaving the scheduler firing a task
the API had reported as paused. The read now takes the writer first, as every
other mutating path in that repository does. PostgreSQL was unaffected.
([#5777])
- **mcp:** Lazy MCP initialization no longer runs tool discovery twice when
discovery itself raises a `RuntimeError` such as `McpTaskConfigurationError`.
The `asyncio.run` fallback in `get_cached_mcp_tools()` was meant only for
`get_event_loop()` failing, but it also caught discovery errors and
re-spawned every stdio server (and re-fetched OAuth tokens) before giving
up; inside a running loop it also logged a misleading "asyncio.run() cannot
be called from a running event loop" traceback instead of the real cause.
- **uploads:** Deleting an uploaded document no longer deletes the converted
Markdown beside it. Conversion names a companion after the document's stem
and falls back to a `_N` suffix when that name is taken, so the `.md` next to
a document can belong to another document sharing the stem, or to the user:
uploading `a.docx` and `a.pdf` produced `a.md` and `a_1.md`, and deleting
`a.pdf` destroyed `a.docx`'s companion. Companions now survive their
document, stay listed, and can be deleted on their own. ([#5673])
- **subagents:** Recognize zero-byte regular deliverables in remote sandbox
acceptance checks. Readable empty files now satisfy `exists` and
`file_written` and deterministically fail `non-empty`, instead of remaining
UNVERIFIED. ([#5559])
- **frontend:** Keep the `…` (kebab) menu on project chat rows inside the
sidebar. In the sidebar's grouped Projects mode the indented nested menus
kept `SidebarMenu`'s `w-full` while carrying an extra `ml-4`, so they were

View File

@ -393,6 +393,23 @@
`custom/` 下的一级链接,但 `delete_custom_skill` 用 `shutil.rmtree` 删除包目录,而它拒绝
符号链接:删除在写入历史记录之后以 `OSError` 失败,退出时清空了用户的技能投影视图,
`DELETE /api/skills/custom/{name}` 返回 500。现在只移除链接本身,绝不触碰其指向的外部目录。([#5881])
- **开发:** 当同级 worktree 的路径包含空格时,`make stop` / `make dev` 现在也能回收它占用的
开发端口。`serve.sh` 用 `awk '{print $2}'` 解析 `git worktree list --porcelain` 来构建
worktree 根目录列表,而该输出中的路径不加引号,因此 `.../deer flow two` 被记录成了
`.../deer`;从那个 worktree 启动的 Gateway 或前端永远不会被识别为 deer-flow 的进程,
启动会以“端口已被占用”中止。现在会保留整条路径。([#5856])
- **上传:** 运行消息元数据中格式错误的 `files[*].size` 不再导致整个运行失败。
`UploadsMiddleware` 对客户端提供的文件条目的其他字段都做了容错校验,唯独把 `size` 直接交给
`int()`,因此 `"abc"` 或列表这样的值会在调用模型之前从 `before_agent` 抛出——而且由于该条目
会被原样带入,之后每次编辑或重新生成这条消息都会再次失败。该字段只用于 `<current_uploads>`
里的可读大小;现在无法使用的值会回退为 `0`,与缺失时一致,数字字符串仍然有效。([#5855])
- **发布:** 版本升级不再把 `backend/uv.lock` 落下。`scripts/bump_version.sh` 会改写
`backend/pyproject.toml`、`frontend/package.json` 与 Helm chart,但 lockfile 同样记录了
根包自身的版本(uv 保留其 PEP 440 形式,因此 `2.1.0-rc0` 存为 `2.1.0rc0`),于是文档给出的
发布步骤产出的提交会被 lock 相关 CI 拦下:`uv lock --check` 判其过期,`uv sync --locked`
也会拒绝该工作区;装了 pre-commit 时还会更早在 `uv-lock-check` 钩子上失败。现在该脚本会用
`uv lock` 刷新 lockfile,并在缺少 `uv` 时于修改任何文件之前退出,而不是留下一个只改一半的
工作区。实际改动仅涉及根包的那一行版本号。([#5859])
- **前端:** 子任务渲染状态不再在 `MessageList` 渲染过程中被就地修
改。子任务同步从渲染阶段移入 effect,因此即使任务上下文尚未发布
更新,卡片也能立即拿到纯派生自消息的快照——修复了最终流式参数与
@ -2193,48 +2210,6 @@
### 修复
- **开发:** 当同级 worktree 的路径包含空格时,`make stop` / `make dev` 现在也能回收它占用的
开发端口。`serve.sh` 用 `awk '{print $2}'` 解析 `git worktree list --porcelain` 来构建
worktree 根目录列表,而该输出中的路径不加引号,因此 `.../deer flow two` 被记录成了
`.../deer`;从那个 worktree 启动的 Gateway 或前端永远不会被识别为 deer-flow 的进程,
启动会以“端口已被占用”中止。现在会保留整条路径。([#5856])
- **上传:** 运行消息元数据中格式错误的 `files[*].size` 不再导致整个运行失败。
`UploadsMiddleware` 对客户端提供的文件条目的其他字段都做了容错校验,唯独把 `size` 直接交给
`int()`,因此 `"abc"` 或列表这样的值会在调用模型之前从 `before_agent` 抛出——而且由于该条目
会被原样带入,之后每次编辑或重新生成这条消息都会再次失败。该字段只用于 `<current_uploads>`
里的可读大小;现在无法使用的值会回退为 `0`,与缺失时一致,数字字符串仍然有效。([#5855])
- **发布:** 版本升级不再把 `backend/uv.lock` 落下。`scripts/bump_version.sh` 会改写
`backend/pyproject.toml`、`frontend/package.json` 与 Helm chart,但 lockfile 同样记录了
根包自身的版本(uv 保留其 PEP 440 形式,因此 `2.1.0-rc0` 存为 `2.1.0rc0`),于是文档给出的
发布步骤产出的提交会被 lock 相关 CI 拦下:`uv lock --check` 判其过期,`uv sync --locked`
也会拒绝该工作区;装了 pre-commit 时还会更早在 `uv-lock-check` 钩子上失败。现在该脚本会用
`uv lock` 刷新 lockfile,并在缺少 `uv` 时于修改任何文件之前退出,而不是留下一个只改一半的
工作区。实际改动仅涉及根包的那一行版本号。([#5859])
- **配置:** 在上一次编辑仍在加载时落盘的 `config.yaml` 编辑,不再要等到下一次编辑才生效。
`get_app_config()` 的加载器先解析文件,再重新读取一遍来计算缓存签名,因此夹在两次读取
之间的写入会让缓存以较新内容的签名保存较旧的内容,而签名比较永远无法发现这种状态。
现在加载器只读取文件一次,并对解析的那份字节计算签名;与加载竞争的写入只会在下一次
调用时多触发一次重载。([#5848])
- **配置:** `request_admission.requests_per_minute` 与 `max_queue_size` 现在与其他字段一样
接受 `$VAR` 环境变量引用。这两个字段是严格整数,布尔值与浮点数仍会被拒绝;但 `$VAR`
替换得到的永远是字符串,因此即使 `RPM=60`,`requests_per_minute: $RPM` 也会让整个配置
加载失败并报 "Input should be a valid integer"。现在以字符串形式到达的十进制整数字面量会在
严格校验之前被转换;其他字符串仍会被拒绝。([#5838])
- **调度器:** 在 SQLite 上,调度分发进行中暂停计划任务时不再丢失暂停状态。
`release_dispatch_lease` 依据租约持有者做校验(暂停会清除该字段),但读取任务行时没有先获取
SQLite 的写锁,因此过期的读取会通过校验,并把任务状态写回 `enabled` 且不改动 `next_run_at`,
导致接口已回复“已暂停”的任务仍被继续触发。现在该读取会像该仓储中其他写入路径一样先获取写锁。
PostgreSQL 不受影响。([#5777])
- **mcp:** MCP 延迟初始化在工具发现本身抛出 `RuntimeError`(例如
`McpTaskConfigurationError`)时,不再把发现流程跑两遍。`get_cached_mcp_tools()` 里的
`asyncio.run` 兜底只为 `get_event_loop()` 失败而设,却同时捕获了发现阶段的错误,于是在
放弃之前会重新拉起每一个 stdio 服务器(并重新获取 OAuth 令牌);在运行中的事件循环里,
它记录的还是误导性的 "asyncio.run() cannot be called from a running event loop"
堆栈,而不是真正的原因。
- **上传:** 删除已上传的文档时,不再连带删除其旁边转换生成的 Markdown。转换以文档主干名
命名配套文件,名称被占用时回退为 `_N` 后缀,因此文档旁的 `.md` 可能属于主干名相同的另一个
文档,或属于用户自己:上传 `a.docx` 与 `a.pdf` 会生成 `a.md` 与 `a_1.md`,删除 `a.pdf`
却会销毁 `a.docx` 的配套文件。现在配套文件会保留、继续出现在列表中,可单独删除。([#5673])
- **nginx:** 把 600 秒读取超时扩展到其余两个会等待 Gateway 的 location,它们在线程路由的修复
之后仍沿用 nginx 默认的 60 秒。`/api/` 兜底 location 之后:无状态的 `POST /api/runs/wait`
阻塞在同一套运行完成等待上,并在客户端断开时取消该运行,因此等待超过 60 秒的 API 调用方会