Skip to content

fix(chat): 修复本地文件链接跨平台路径解析 - #422

Merged
su-fen merged 4 commits into
mainfrom
fix/chat-file-link-cross-platform-paths
Aug 10, 2026
Merged

fix(chat): 修复本地文件链接跨平台路径解析#422
su-fen merged 4 commits into
mainfrom
fix/chat-file-link-cross-platform-paths

Conversation

@su-fen

@su-fen su-fen commented Aug 10, 2026

Copy link
Copy Markdown
Member

Closes #421

问题

聊天里模型输出的本地文件引用,三类常见写法点击必报错(详见 issue):

场景 报错
Windows [下载](/D:/workspace/.../a.zip) "The linked path is not valid on this device."
macOS [查看](~/Desktop/report.pdf) "The linked file does not exist."
双平台 .zip/.tar.gz/.7z 等压缩包 "The linked file type cannot be opened safely."

修改

前端 chatFileLinks.ts(agent-gui 与 gateway/web 两端镜像,逐字节同步)

  • 新增 URL_STYLE_DRIVE_PATH_PATTERN:裸路径分支与 payload decode 分支补 /D:/... → D:/... 前导斜杠剥离,与 file-url 分支既有行为对齐
  • 新增 HOME_ANCHORED_PATH_PATTERN:~ / ~/... 归类为 absolute(在会话归属设备上解析,由 host 展开)

Rust chat_file_links.rs

  • absolute / file-url 源的链接路径经 expand_tilde_path 展开;relative 源保持字面量,工作区内名为 ~ 的目录仍按相对路径 join,不受影响
  • 新增 ARCHIVE_EXTENSIONS(zip、7z、rar、tar、gz、tgz、bz2、xz、zst 等):归入 revealed 动作,在文件管理器中定位而非执行,也不再兜底拒绝

安全性

  • 剥离仅作用于 ^\/[a-zA-Z]:\/ 精确形态,C:drive-relative.txt(盘符相对路径)仍被拒绝,拒绝测试集不变
  • 压缩包走 reveal(open -R / explorer /select,),不 launch;EXECUTABLE 语义未动
  • ~ 展开只在 absolute/file-url 源生效,relative 源行为与之前完全一致

测试

  • crates/agent-gateway/web:node --test test/*.test.mjs → 326 pass
  • crates/agent-gui:node --test test/chat/*.test.mjs → 567 pass
  • cargo test --lib chat_file_links → 9 pass(新增压缩包 reveal、~ 展开 + 字面 ~ 目录回归)
  • 两端 tsc --noEmit、biome、rustfmt 均通过
  • 新增用例:/D:/.../d:/...(小写盘符)、~/release/a.zip~/work/a.ts:12

已知不修(有意)

  • %USERPROFILE%/$HOME 环境变量形态不展开(注入面大、收益低),维持 "does not exist"
  • macOS 本机会话点 D:/... 报 "not valid on this device" 是正确语义(文件确实不在该设备)

三个独立问题导致聊天里模型输出的本地文件链接"可点击但必报错":

1. URL 风格盘符路径 /D:/work/a.zip:裸路径分支缺少 file-url 分支
   已有的前导斜杠剥离,Windows 端 Path::is_absolute() 为 false,
   报 "The linked path is not valid on this device."。
   补 URL_STYLE_DRIVE_PATH_PATTERN 剥离(parse 与 decode 两处)。

2. macOS 家目录路径 ~/release/a.zip:此前判为 relative,Rust 端
   join 出 <workdir>/~/... 报 "does not exist"。前端将 ~ 锚定路径
   归为 absolute,Rust 端 absolute/file-url 源经 expand_tilde_path
   展开;relative 源保持字面量,工作区内名为 "~" 的目录不受影响。

3. 压缩包(zip/7z/tar/gz 等)不在任何动作名单,双平台一律
   "cannot be opened safely"。新增 ARCHIVE_EXTENSIONS 归入
   reveal(文件管理器定位,不执行)。

chatFileLinks.ts 两端镜像逐字节同步;双端前端测试与 Rust 测试
补齐 /D:/、/d:/、~/、压缩包及字面 "~" 目录回归用例。
@StackCairn
StackCairn marked this pull request as draft August 10, 2026 09:25
@github-actions

Copy link
Copy Markdown
Contributor

PR governance checks failed — this PR has been converted to draft.

  • UI change without screenshots: this PR modifies frontend code. Please add before/after screenshots or a recording under "Screenshots / preview" in the PR body.

Fix the items above, then click Ready for review to re-run the checks.

chatFileLinks.ts 此前在 agent-gui 与 gateway/web 各存一份、
靠人工逐字节同步。迁移到 crates/agent-ui/src/lib/chat/(共享
代码唯一归宿),两端宿主与 agent-ui 内部引用统一改为
@liveagent/ui/lib/chat/chatFileLinks,宿主副本删除。

- agent-ui 内 Markdown/ThinkingActivity/openChatFileLink 改
  相对导入,不再经 @liveagent/app 反查宿主
- 双端 chat-file-links 测试改为加载共享模块(按惯例测试保留
  双份,守护各自宿主的 prop 链)
@su-fen

su-fen commented Aug 10, 2026

Copy link
Copy Markdown
Member Author

追加 23472bf:chatFileLinks.ts 抽离到共享层 crates/agent-ui/src/lib/chat/,消除 GUI/WebUI 双端逐字节镜像(-225/+16 行)。

  • 两端宿主 11 处引用 + agent-ui 内 3 处引用统一改 @liveagent/ui/lib/chat/chatFileLinks;agent-ui 内部改相对导入,不再经 @liveagent/app 反查宿主
  • 双端 chat-file-links 测试改为加载共享模块;按仓库惯例测试保留双份(各自守护宿主 prop 链)
  • 验证:三端 tsc ✅ / WebUI 326 pass ✅ / GUI 1521 pass ✅ / check-ui-boundaries ✅ / biome ✅
  • GUI 套件中 test/workspace/markdown-assets.test.mjs 1 例失败为 main 上既有问题(@liveagent/ui-core/... 模块缺失,stash 本改动后同样失败),与本 PR 无关

su-fen added 2 commits August 10, 2026 20:16
…oss-platform-paths

# Conflicts:
#	crates/agent-gui/src/pages/chat/components/assistant-bubble/RoundContent.tsx
#	crates/agent-ui/src/components/chat/AssistantBubble.tsx
#	crates/agent-ui/src/components/chat/assistant-bubble/RoundContent.tsx
@su-fen
su-fen requested a review from yyg-max August 10, 2026 12:58
@yyg-max yyg-max added the governance-exempt Skip PR governance checks label Aug 10, 2026
@yyg-max
yyg-max marked this pull request as ready for review August 10, 2026 13:17
@su-fen
su-fen merged commit 64268be into main Aug 10, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

governance-exempt Skip PR governance checks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

聊天本地文件链接跨平台打开失败:/D:/ 盘符路径、~/ 家目录路径、压缩包类型

2 participants