fix(web-shell): preserve separators in tool description paths - #11977
Conversation
E2E verification report / E2E 验证报告Result: VERIFIED_FIXED at
结果:VERIFIED_FIXED。在 macOS 上验证提交
|
|
✅ Qwen Triage finished — CI landed green on ✅ Qwen Triage 已完成 —— |
|
Thanks for the PR — this is a real bug, and I could confirm it without running anything. Template looks good ✓ Problem: observed, not theoretical. I traced the chain statically on the base commit: Direction: right layer. Core is producing a correct relative path; the defect is the web-shell formatter treating a mid-token Size: not applicable — Approach: this is what I'd have written. Before reading the diff my own proposal was "require a token boundary before an embedded absolute path", which is exactly the Risk: no elevated risk signals — neither changed file matches the revert-correlated path list. Outside this test file, One thing to think about, not a blocker: the boundary set is whitespace, Moving on to code review. 🔍 中文说明感谢贡献——这是一个真实存在的 bug,我不需要运行任何代码就能确认。 模板完整 ✓ **问题:**已观测到,不是理论性加固。我在 base commit 上静态追踪了整条链路: **方向:**修在了正确的层。core 产出的相对路径本身是对的,缺陷在于 web-shell 的格式化逻辑把 token 中间的 **规模:**不适用—— **方案:**和我自己的写法一致。在读 diff 之前我的独立提案就是"内嵌绝对路径必须出现在 token 边界处",也就是这个 **风险:**无升级风险信号——两个改动文件都不在 revert 相关路径列表内。除本测试文件外, 有一点可以想想,但不是阻塞项:边界集合是空白字符、 进入代码审查 🔍 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
Code reviewNo blockers. What I actually checked, rather than assumed: I hand-traced all twelve new expectations through I also re-traced the pre-existing title tests that route through the same function, since adding a boundary requirement is exactly the kind of change that silently stops shortening something an older test depends on. Downstream surface is bounded and I named every consumer: outside this test file, Two mechanical things that could have bitten and don't: One non-blocking note. The Test evidenceThis was an unattended CI run ( At the time of writing there is nothing red to excerpt. Three substantive checks are still running; two workflow runs with Final CI results for
One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。 The skipped macOS/Windows Sandboxed verification, if a maintainer wants it: 中文说明代码审查没有阻塞项。以下是我实际核对过的内容,而不是想当然: 我在审查 worktree 中读 base commit 源码,手工推演了全部 12 条新断言的完整路径: 我也重新推演了走同一函数的既有标题用例,因为"增加边界要求"正是那种会悄悄让某个老断言不再被缩短的改动。 下游影响面是有界的,且我点名了每一个消费者:除本测试文件外, 两个本来可能出问题但没有的机械细节: 一条非阻塞提示。 测试证据本次是无人值守的 CI 运行( 撰写时没有任何红色检查可供摘录。三项实质检查仍在运行; 上表中 macOS/Windows 的 如果维护者希望做沙箱验证: — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
🖼️ web-shell visual previewRendered against a mock daemon (no real backend): the PR base vs this PR head Screenshots · before / after✅ No screenshot changes against the PR base. Full-resolution recordings (.webm) are attached to the workflow run. — Qwen Code · web-shell visuals |
|
Confidence: 5/5 — smallest possible fix for a defect I reproduced from source independently of the PR, with tests that genuinely fail without it. Stepping back. My independent proposal before reading the diff was "require a token boundary before an embedded absolute path", and that is literally what this does — so there is no simpler path I found that it missed, which is the usual reason I hold a PR back. Four production lines, one test file, no drive-by edits, no formatting churn, nothing unrelated riding along. In six months the tests are what will make this maintainable: they spell out the boundary contract (whitespace, quotes, parens, start-of-string) and pin the I went looking for reasons to say no and did not find one. I re-traced the pre-existing title tests through the new regex specifically because a boundary requirement is the kind of change that quietly stops shortening something an older assertion depends on; none of them move. I named every consumer of the two exported functions and confirmed the string is display-only and never parsed back into a path, so nothing downstream can desync. The problem itself I confirmed without the author's help — The two notes I left in Stage 2 are not defects in this diff and I do not want them read as hesitation: the boundary set omits backticks, brackets and bare colons by necessity, because admitting The one honest limit on my confidence is that this was a static review on an unattended CI run: I built nothing and ran nothing, so I have not watched the eight regression cases fail on base and pass on head. I traced that they must, and the author's reported numbers match my derivation exactly, but a trace is an argument rather than a measurement — Stage 2 names the lane that would convert it into one. Approval is deferred until CI lands green on 中文说明Confidence: 5/5 —— 用尽可能小的改动修复了一个我独立于 PR、直接从源码复现出来的缺陷,且配套测试在没有这个修复时确实会失败。 退一步看整体。我在读 diff 之前的独立提案就是"内嵌绝对路径必须出现在 token 边界处",而这正是本 PR 做的事——所以我没有找到它遗漏的更简路径,而那通常是我压下一个 PR 的理由。4 行生产代码、一个测试文件,没有顺手改动,没有格式化噪声,没有任何无关内容夹带。半年后真正让这个改动可维护的是它的测试:这些测试把边界契约(空白字符、引号、括号、字符串开头)写清楚了,并固定住了 我是带着"找出说不的理由"去看的,没有找到。我特意把既有的标题用例重新过了一遍新正则,因为"增加边界要求"正是那种会悄悄让某个老断言不再被缩短的改动;结果它们都不变。我点名了两个导出函数的每一个消费者,确认该字符串仅用于显示、绝不会被反向解析成路径,因此下游不可能失同步。问题本身我在没有作者帮助的情况下也确认了—— 我在 Stage 2 留下的两条提示并不是本 diff 的缺陷,也不应被读成犹豫:边界集合不含反引号、方括号和裸冒号是必要的取舍,因为一旦纳入 对我这份信心唯一诚实的限制是:本次是无人值守 CI 运行下的静态审查——我没有构建、也没有运行任何东西,所以我没有亲眼看到那 8 条回归用例在 base 上失败、在 head 上通过。我推演出它们必然如此,作者报告的数字也与我的推导完全吻合,但推演是论证而不是实测——Stage 2 已点名可以把论证变成实测的那条通道。 **批准将推迟到 CI 在 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
chiga0
left a comment
There was a problem hiding this comment.
No blocking findings. Approval blockers: none.
Triage: Standard tier
Root cause (static trace)
The old regex (?:[A-Za-z]:)?\/[^\s'")+ had no start-boundary requirement. In packages/web-shell/.../MessageList.dom.test.tsx, the /web-shell/... suffix matched as an absolute path; pathForDisplay took its basename, and the remaining prefix packages concatenated directly to produce packagesMessageList.dom.test.tsx.
URL edge case independently verified: https://example.com/docs/index.html — old regex matched at position 4 (s: as drive prefix), basename to index.html, htt + index.html = httpindex.html. New regex requires a token boundary before s; p preceding it is not in [\s'"(], so no match. Preserved. Confirmed the bot's independent derivation.
New regex spot-checks
"prefix:"/workspace/project/src/a.ts"-> prefix=", path=/workspace/project/src/a.ts(stops at"), result"src/a.ts". Closing"untouched. OK.(prefix:(/workspace/project/src/a.ts)-> prefix=(, path stops at), result(src/a.ts). OK.^zero-width:/workspace/.../a.ts extra-> prefix="", resultsrc/a.ts extra. OK.'is in both start boundary and stop set:'/path/file'-> prefix=', filePath=/path/file(stops at closing'), result'basename'. OK.- Windows
C:/...at start of string:isAbsoluteLikePathearly-return handles it directly. Mid-string with space boundary also works. - Relative paths e.g.
packages/web-shell/...:pbefore first/not in boundary set, no match, preserved. OK.
Test validity
All 8 "preserves separators" cases fail on the old regex (mid-token / matched) and pass on the new one. The 4 "normalizes embedded absolute path" cases verify boundary-detected paths are still shortened. Tests exercise both getToolDescription and getToolSummaryDescription through the full call chain.
Cross-check vs existing reviews
qwen-code-ci-bot stage 2/3 independently reproduced the root cause, hand-traced all 12 new expectations, confirmed no blockers, confidence 5/5. URL corruption case (httpindex.html) independently confirmed by me above.
Unreviewed dimensions
- Windows / Linux browser runs not tested (PR acknowledges with warning)
- Execution tier not run: pure display-layer regex change, no state, no I/O
Reviewed with AI assistance.
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship — CI landed green after the review. ✅
|
Released in v0.24.0. |
What this PR does
Preserves directory separators in Web Shell tool summaries by matching embedded absolute paths only at a token boundary. Relative paths, shortened paths, glob patterns, and URLs retain their original text; supported absolute paths still use the existing display shortening.
Why it's needed
A relative title such as
packages/web-shell/client/components/MessageList.dom.test.tsx (lines 277-298)was displayed aspackagesMessageList.dom.test.tsx (lines 277-298). The formatter treated the suffix beginning at the first slash as an absolute path and replaced it with its basename, joining the remaining directory prefix directly to the filename.Reviewer Test Plan
How to verify
packages/web-shell/client/adapters/messageTypes.tsand lines 277–298 ofpackages/web-shell/client/components/MessageList.dom.test.tsx.Local validation: 172 targeted formatter and tool-row tests passed, including eight regression cases that failed before the fix. Full build, bundle, typecheck, targeted ESLint, and Prettier checks passed.
Evidence (Before & After)
Before: global
qwen0.22.0, real daemon and file tools. The second file was read successfully but its summary lost the directory separators. The first request used a nonexistenttypes/messageTypes.tspath and failed; that row demonstrates only the display defect.After: local bundle at
ef69048fd67a5d919685cee488b0d11f9871a27b, real daemon and file tools. The first request was corrected toadapters/messageTypes.ts; both reads succeeded, summaries retained separators and line ranges, and expanding the second result showed the requested TSX content. No mock daemon was used. Screenshots were visually inspected. The baseline used the in-app browser; verification used Chrome because the in-app browser became unavailable.Images are stored on a separate asset branch in
ytahdn/qwen-code, linked by immutable commit, and are absent from the implementation branch.Tested on
Environment (optional)
macOS, Node.js 22.14.0; isolated runtime directories for the global baseline and local
node dist/cli.js serve --port 0 --web --safe-modeverification.Risk & Scope
Linked Issues
Reported and reproduced from a user screenshot; no linked GitHub issue.
中文说明
此 PR 的改动
仅在标记边界处匹配标题中嵌入的绝对路径,保留 Web Shell 工具摘要中的目录分隔符。相对路径、已缩写路径、通配符和 URL 保持原文;受支持的绝对路径继续沿用现有的显示缩短规则。
为什么需要
类似
packages/web-shell/client/components/MessageList.dom.test.tsx (lines 277-298)的相对路径标题,此前会显示成packagesMessageList.dom.test.tsx (lines 277-298)。格式化逻辑将第一个斜杠开始的后缀误认为绝对路径,并替换为文件名,导致剩余目录前缀直接与文件名粘连。审查者测试计划
如何验证
packages/web-shell/client/adapters/messageTypes.ts的第 161–200 行,以及packages/web-shell/client/components/MessageList.dom.test.tsx的第 277–298 行。本地验证:172 个格式化及工具行相关测试通过,其中 8 个回归用例在修复前失败。全量 build、bundle、typecheck,以及定向 ESLint 和 Prettier 检查均通过。
证据(修复前后)
修复前:全局
qwen0.22.0,使用真实 daemon 和文件工具。第二个文件读取成功,但摘要丢失目录分隔符。第一条请求使用了不存在的types/messageTypes.ts路径,读取失败;该行仅用于展示显示问题。修复后:提交
ef69048fd67a5d919685cee488b0d11f9871a27b的本地 bundle,使用真实 daemon 和文件工具。第一条请求改为正确的adapters/messageTypes.ts;两次读取均成功,摘要保留分隔符和行号范围,展开第二条结果可查看所请求的 TSX 内容。未使用模拟 daemon,截图已目视检查。基线使用应用内浏览器;验证时因应用内浏览器不可用而改用 Chrome。截图存放于
ytahdn/qwen-code的独立素材分支,通过固定 commit 链接引用,不进入实现分支。测试平台
环境(可选)
macOS、Node.js 22.14.0;全局基线和本地
node dist/cli.js serve --port 0 --web --safe-mode验证使用各自独立的运行时目录。风险与范围
关联 Issue
来自用户截图报告并已复现,未关联 GitHub issue。