Skip to content

feat(workspace): 支持外部目录授权与多根文件访问 - #468

Open
yovinchen wants to merge 8 commits into
Stack-Cairn:mainfrom
yovinchen:feat/workspace-multi-root-settings
Open

feat(workspace): 支持外部目录授权与多根文件访问#468
yovinchen wants to merge 8 commits into
Stack-Cairn:mainfrom
yovinchen:feat/workspace-multi-root-settings

Conversation

@yovinchen

@yovinchen yovinchen commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Linked issue

Closes #408
Closes #459

Summary

Issue #408 的根因是文件工具只有单一工作区根目录:聊天中的文件导入只会把普通文件复制到上传作用域,目录既不会被挂载,也不会扩展结构化文件工具的可访问边界。因此 Agent 无法在保留当前项目归属的同时,安全地引用或修改另一个项目目录。

本 PR 增加项目级附加目录授权,并把入口统一到项目“三点菜单 → 配置”中:

  • 新增双栏“项目配置”模态框,包含“通用配置 / 目录与权限 / 资源配置”;项目重命名也统一移动到通用配置。
  • 支持为项目添加多个附加目录,并分别授予只读或读写权限;主目录仍是会话、Git、终端和文件树的默认工作位置。
  • 新增 root://<alias>/... 路径语义和最长根匹配解析,结构化 Read/List/Glob/Grep 可访问只读根,Write/Edit/Delete 仅可访问读写根。
  • 授权在桌面端 SQLite 中持久化;保存时规范化路径并校验别名、重复、包含关系、路径漂移和失效目录。
  • Gateway/WebUI 通过协议调用在线桌面 Agent 选择和保存目录,复用工作区目录选择器;远端项目删除时同步撤销本地授权。
  • 子 Agent 仅继承附加根的只读能力;Bash/ManagedProcess 不获得附加目录权限,避免把结构化文件授权误扩展到任意命令执行。

本 PR 实现的是“在项目配置中显式添加并授权外部目录”。将文件夹直接拖入聊天并转化为授权根不在本次范围内,避免在未完成确认流程和浏览器目录句柄设计前隐式扩大权限。

Change scope

  • Modules: agent-ui / agent-gui / src-tauri / agent-gateway / Gateway WebUI
  • Key paths:
    • crates/agent-ui/src/components/chat/WorkspaceProjectSettingsModal.tsx
    • crates/agent-gui/src/lib/tools/pathUtils.ts
    • crates/agent-gui/src/lib/tools/fsTools.ts
    • crates/agent-gui/src/lib/workspaceRootGrants.ts
    • crates/agent-gui/src-tauri/src/commands/workspace/root_grants.rs
    • crates/agent-gateway/proto/v2/gateway.proto
    • crates/agent-gateway/web/src/agent-ui-adapters/directoryPicker.tsx

Screenshots / preview

Draft 运行预览已完成:

  • Desktop:项目三点菜单已显示“配置”,模态框可切换“通用配置 / 目录与权限 / 资源配置”,目录页可选择目录并设置只读或读写。
  • WebUI:同一共享配置模态框通过 Gateway 请求在线桌面 Agent;目录选择复用新增工作区时的远端目录浏览器。
image image image image image image

Verification

  • cargo test --manifest-path crates/agent-gui/src-tauri/Cargo.toml root_grants --lib — 12 passed
  • mise exec -- go -C crates/agent-gateway test ./internal/protocol/pbws — passed
  • mise exec -- node --test crates/agent-gateway/web/test/gateway-v2-adapters.test.mjs — 9 passed
  • mise exec -- node --test crates/agent-gui/test/tools/path-and-system-tools.test.mjs crates/agent-gui/test/chat/markdown-image-policy.test.mjs crates/agent-gui/test/subagents/agent-tool.test.mjs — 102 passed
  • mise exec -- node --test crates/agent-gui/test/chat/sidebar-selection.test.mjs crates/agent-gui/test/settings/workspace-resource-settings.test.mjs — 12 passed
  • mise exec -- pnpm build:gui — passed
  • mise exec -- pnpm build:webui — passed
  • git diff --check origin/main...HEAD — passed

覆盖的关键场景包括:macOS/POSIX 路径、Windows 盘符与 UNC 路径、file://root://、路径穿越、符号链接漂移、重叠根、只读写入拒绝、子 Agent 权限降级、Gateway 请求校验和项目删除撤权。

Pre-submit checklist

  • A requirement issue is linked (or this is a trivial fix that needs no issue, as explained in the summary).
  • Synced with the target branch; no merge conflicts.
  • The change is focused, with no unrelated modifications.
  • No secrets, tokens, or personal data included.
  • Docs are updated for changes affecting user behavior, deployment, or configuration. Documentation is intentionally excluded from this draft and can be submitted separately if maintainers request it.

@yovinchen
yovinchen marked this pull request as ready for review August 13, 2026 18:50
@yovinchen

yovinchen commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

目前还有一个尚未确定的设计问题:在 Desktop 和 Web 端拖入文件夹时,应该采用怎样的处理方式。

当前拖入文件时,文件并不是直接发送给模型:如果文件原本位于工作空间内,就直接引用原文件;如果是工作空间外的文件或从 Web 端上传的文件,则会先进入应用管理的暂存目录,再把一个 Agent 可读取的路径提供给模型。基于这一现状,拖入文件夹大致有两种处理方式:

  1. 将文件夹视为一次目录授权,并添加为项目的附加目录。这个方式在 Desktop 端比较自然,因为应用能够获得真实且持续有效的本地路径。不过,我不确定拖拽操作是否应该直接扩大项目的目录访问范围。可能更安全的做法是先弹出确认,并默认仅授予只读权限。
  2. 将文件夹内容作为一个快照,上传或复制到应用管理的暂存目录。这个方式更适合 Web 端,因为浏览器无法提供一个可供服务端长期访问的本地目录路径。但它也需要明确递归范围、文件数量和大小限制、忽略规则、符号链接处理、暂存清理以及后续刷新方式。

不知道采用平台差异化处理是否合理:Desktop 端在用户确认后,将文件夹添加为附加只读目录;Web 端则把文件夹内容导入到独立的暂存目录。还是说,在确定一个统一的跨平台语义之前,暂时继续不支持文件夹拖拽会更合适?希望听听大家的意见。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant