Skip to content

feat(desktop): support copying relative file locations - #3695

Open
Stella-xixi wants to merge 1 commit into
makecindy:mainfrom
Stella-xixi:codex/copy-file-location-3663
Open

feat(desktop): support copying relative file locations#3695
Stella-xixi wants to merge 1 commit into
makecindy:mainfrom
Stella-xixi:codex/copy-file-location-3663

Conversation

@Stella-xixi

@Stella-xixi Stella-xixi commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

这次改了什么

摘要

为 Cindy 回复中的文件位置引用增加“复制位置”右键菜单项,直接复制工作目录相对路径与行号,例如 src/example.ts:42;引用包含列号时复制为 src/example.ts:42:7,便于粘贴到 VS Code 的文件定位入口。

当前仅复制文件名或完整路径时,用户还需要手工补上相对目录和行号。本改动沿用已经解析成功的文件引用及其行列信息,不重新查询文件,不改变原有点击打开行为,也不替换“复制文件路径”的完整路径复制能力。

新入口仅对已唯一解析、位于来源工作目录内且带有效行号的文件显示。目录、缺失或歧义引用、没有有效行号、没有工作目录以及工作目录外的路径不会获得这个入口。行号范围沿用现有解析规则,复制起始行;不会推测列号或文件实际行数。

变更类型

  • feat 新功能
  • fix 缺陷修复
  • refactor / perf 重构或性能优化
  • docs / test / chore 文档、测试或工程维护
  • 其他:

范围

  • 关联 Issue / 需求:Closes 建议支持一键复制相对文件路径和行号 #3663
  • 本 PR 包含:回复文件引用的行列信息传递、共享右键菜单的新复制动作、相对位置格式化、文案与回归测试。
  • 明确不包含:文件解析算法、打开方式、文件内容复制、文件预览、VS Code 启动协议、Mobile UI、服务端、IPC、持久化配置或数据库变更。
  • 用户可见变化:右键点击符合条件的文件引用后,可以选择“复制位置”;复制成功显示“位置已复制”,剪贴板写入失败沿用现有失败提示。
  • 是否存在 breaking change:无;旧的菜单调用方无需提供位置参数,原有复制与打开动作保持不变。
  • Remote / mobile 结论:SSH 和 device-link 来源使用 ChatSessionFileContext 中的来源工作目录与已解析绝对路径做纯字符串转换,剪贴板仍属于当前 Desktop。此动作不读取本机对应路径、不下载远程文件、不新增网络请求或协议字段。Mobile 自身的渲染与交互不在本次改动范围内;不改变 runtime fingerprint。

实现说明

文件 / 模块 改动与目的
MarkdownRenderer.tsx 将已有解析结果中的 linecolumn 传给 FileTargetChipResolvedLocalLink,覆盖 Markdown 文件链接、经现有插件识别的正文裸路径及行内代码引用。未改变 unresolved / ambiguous 分支。
useFileChipContextMenu.tsx 增加可选的 location 参数;仅在可格式化为有效文件位置时显示新菜单项。调用现有 navigator.clipboard.writeText,分别处理成功与失败提示。
lib/fileLocation.ts 校验正整数行列号,复用共享的 toWorkdirRel 计算工作目录相对路径,统一输出 / 分隔符;不依赖 Renderer 中的 Node 文件系统能力。
fileLocation.test.ts 覆盖 POSIX / Windows、远程逻辑路径、空格和中文文件名、目录边界、无效坐标及范围起始行语义。
fileChipCopyLocation.test.tsx 使用实际菜单组件验证复制内容、入口显隐、旧的完整路径复制、远程工作目录与剪贴板失败反馈。
i18n/locales/*/common.json 已补齐 en / zh-CN / zh-TW / ja / ko 的 copyLocationlocationCopied,五语 key 检查通过。

行为边界

引用条件 新动作的结果
/repo/src/example.ts:42,工作目录 /repo src/example.ts:42
同一文件带列号 42:7 src/example.ts:42:7
C:\Repo\src\example.ts:42:7,工作目录 c:\repo src/example.ts:42:7
范围引用 src/example.ts:42-50 复制解析器提供的起始行 src/example.ts:42
已解析的文件但没有行号 不显示“复制位置”;既有动作不变
工作目录外文件、目录或无法唯一解析的引用 不提供新的复制位置入口
剪贴板拒绝写入 显示现有复制失败提示,不显示成功提示

UI 变化

  • 在原“复制文件路径”下方增加“复制位置”,复用现有 DropdownMenuItemClipboardCopy 图标及 toast。

  • 引用的设计规范:docs/design-rules/DESIGN.md §4 Component Stylings / Select & Dropdown:沿用现有菜单组件及交互;§10 Theme System & Token Reference:不新增硬编码颜色,使用现有主题样式;§11 Voice & Content:使用“动词+对象”文案,英文菜单项为 Copy Location;§14.5 聊天正文的可点性信号:保留原文件引用的点击打开能力。

  • Light / Dark 实机目检尚未完成,不能把复用主题样式视为双模式目检通过。
    -文件引用右键菜单支持两种复制方式:

  • 「复制文件路径」:复制文件的绝对路径

  • 「复制位置」:复制 绝对路径:行号,例如 D:\repo\src\example.ts:42

default.mp4

界面结构示意

以下仅说明菜单局部顺序与复制结果,不是真机截图,也不是视觉验证证据。其他既有菜单项省略。

回复中的文件引用:example.ts:42
  右键菜单
    …
    复制
    复制文件路径  → /repo/src/example.ts
    复制位置      → src/example.ts:42       ← 新增
    打开文件所在目录
    …

成功提示:位置已复制

怎么验证的

自动验证

验证平台为 Windows / Node.js 22.19.0 / pnpm 10.33.2。代码已快进到 2026-08-31 本次获取的 origin/main123493813),修复已恢复且没有合并冲突,以下记录针对同步后的代码。

pnpm install --frozen-lockfile --config.proxy=http://127.0.0.1:7897 --config.https-proxy=http://127.0.0.1:7897
结果:PASS,依赖与工作区链接已更新;锁文件未改动。

pnpm --filter desktop exec vitest run src/renderer/__tests__/fileLocation.test.ts src/renderer/__tests__/fileChipCopyLocation.test.tsx src/renderer/__tests__/markdownTarget.test.ts src/renderer/__tests__/markdownTargetRendererContract.test.ts --maxWorkers=1 --no-file-parallelism
结果:PASS,4 个文件、73 项测试通过(含 34 项新增测试)。

pnpm --filter desktop run --if-present typecheck
结果:PASS。

pnpm test:unit:related
结果:PASS,Desktop 关联测试 422.3 秒;脚本自测 440 passed、8 skipped。

pnpm check:dco
结果:PASS,1 个提交已带 Signed-off-by(12349381..d5320901)。

pnpm check:i18n
结果:PASS,zh-CN / zh-TW / en / ja / ko 共 8519 个 key 一致;1045 处既有警告。

pnpm check:i18n-glossary
结果:PASS,五语无新增术语违规;18 处待裁决术语告警。

git diff --check
结果:PASS。

pnpm test:unit
结果:FAIL(已完整执行,不能标为全量通过)。
脚本测试:440 passed、8 skipped。
Desktop:2241 个文件通过、3 个文件失败;30296 passed、3 failed、61 skipped;另有 1 个 Vitest worker onTaskUpdate 超时错误。
maker-core:121 个文件通过、1 个文件失败、2 个文件跳过;3692 passed、3 failed、20 skipped。
Mobile 与其余适用工作区全部通过。

pnpm --filter desktop exec vitest run src/main/__tests__/windowsPackagedInstanceBarrier.test.ts src/main/doc-tools/__tests__/readSheetProcessPackaging.test.ts src/main/device-link/__tests__/crossProcessLock.test.ts --maxWorkers=1 --no-file-parallelism
结果:PASS,3 个文件、44 项测试全部通过;没有修改断言、实现或超时设置。

同步前旧基线失败的 codexAuthInvalidation.test.ts(maker-host)与 Review plugin.test.ts,本轮分别以 59 项、16 项全部通过。

第一次本地完整测试的未通过项如下(不是本 PR 的 GitHub CI 日志):

文件 / 组件 完整运行结果 后续核对
windowsPackagedInstanceBarrier.test.ts 预期 busy,收到启动锁获取超时 单 worker 复测通过
readSheetProcessPackaging.test.ts ExcelJS / JSZip 隔离依赖打包用例 60 秒超时 单 worker 复测通过,耗时约 33 秒
device-link/crossProcessLock.test.ts 预期持有锁,实际返回 busy 单 worker 复测通过
Vitest worker onTaskUpdate RPC 超时 全量运行中的未处理错误,不能忽略为通过
pi-agent.integration.test.ts bash 超时结果断言失败;bash 环境测试收到 WSL 输出且 HOME 为空;符号链接用例出现 ENOENT 后续干净 main 与本分支的完整 maker-core 分片均复现相同三项失败

后续已在相同提交 123493813 的独立干净 main 工作区与本分支,各单独复测两轮,并按 CI 展开参数运行 Desktop / maker-core 的两个完整分片(Desktop 4 workers、maker-core 1 worker;两端顺序运行)。原始三个 Desktop 文件均通过,但出现其他超时:codexProxyHost.test.ts 的同一 15 秒超时在两端分片均出现,单独各两轮均通过;codexExecFunctionAdapter.e2e.test.ts 的 afterEach 10 秒超时在两端单独各两轮均复现。Pi 原始三项在两端分片均失败;单独选择三个用例时,超时用例通过,环境变量与 symlink 用例均失败。

独立探针以及只在诊断进程中切换到 Git Bash 的真实 Pi 用例验证表明,环境变量失败与本机默认 WSL Bash 有关;切换后两端环境变量用例通过,symlink ENOENT 不变。普通 symlink 探针可以创建,innocent\\q 则因 Windows 路径分隔符和缺失父目录报 ENOENT。Bash 完整分片超时、Desktop 的具体资源/清理瓶颈仍证据不足。没有修改无关模块、安全逻辑、断言、timeout 或系统配置,也没有把复测通过改写成全量通过。

GitHub 旁证:基线主干 CI 通过;后续主干 Windows CI 在不包含本改动的情况下复现同名 crossProcessLock busy 失败。CI 跳过 Pi 二进制安装,不能用 CI 绿灯证明真实 Pi 集成用例已执行通过。

本次同步与 #3663 适配完成,按最新仓库规则的关联单测与 Desktop 类型检查已通过;更广泛测试仍有失败,完整结果如实披露,不声称全量通过。

手工验证

已 review 同步后的修复 diff;提交 d5320901f 基于本次验证的 origin/main 快照 123493813,仅包含 10 个 Desktop 文件。确认原“复制文件路径”处理函数不变,未新增权限、IPC 或文件读写。已有 Mobile .gitignore 改动已保留且没有纳入提交。

未启动 Electron,未执行真实剪贴板 / VS Code 粘贴或 Light / Dark 目检。菜单交互与剪贴板结果由 jsdom 测试验证,不等同于实机验证。

未执行的验证

  • 未在排除并行负载与解决 Pi 集成失败后,再次取得完整单测通过的结果。
  • Light / Dark 界面截图、实机目检与 VS Code 定位验证。
  • macOS、SSH、device-link 真机联调;测试中的远程路径是逻辑路径,不是真机连接。
  • 本 PR 的 GitHub CI 结果尚待确认;本地 DCO 检查已通过。

风险

风险分类

  • 无已知风险
  • SQLite / migration
  • system prompt
  • 协议兼容
  • 权限 / 安全 / 用户数据
  • 存量插件兼容(批准状态 / 指纹 / manifest 校验 / 安装布局 / 包格式)
  • 原生层 / fingerprint / OTA
  • 跨平台差异
  • 其他:完整单测未通过;失败与独立复测结果已如实记录。

影响与回滚

  • 影响范围:Desktop 回复中已解析文件引用的右键菜单与复制文本格式。未改变原来的绝对路径复制、文件打开、文件内容复制或来源路由。
  • 跨平台:复用现有 toWorkdirRel 的 POSIX / Windows 逻辑,Windows 盘符路径按既有规则比较,输出统一为 /。不承诺扩展现有工具不支持的路径形式;无法可靠换算时不显示新入口。
  • 失败范围:格式化失败只影响当前引用是否显示新菜单项;剪贴板失败只显示错误提示。未新增远程重试、下载、缓存、持久化状态或多设备广播。
  • 权限与数据:仅在用户选择菜单项后写入剪贴板;没有自动复制、上传内容或新增特权接口。现有凭证测试失败的排查没有导致安全逻辑变更。
  • 存量插件影响:无;未修改插件契约、批准状态、安装布局或权限。
  • 回滚 / 降级方式:撤销本改动即可恢复旧菜单,不涉及数据迁移或用户配置恢复;原“复制文件路径”始终保留。

提交前检查

  • 已 review 当前本地改动 diff
  • 已同步到验证基线 main 123493813 并复核修复 diff
  • 每个 commit 都带 DCO 签名(git commit -s),本地检查通过
  • UI 改动已在「UI 变化」注明引用的设计规范章节
  • 未提交凭证、令牌或授权文件
  • 已补充必要行为、边界与风险说明
  • 已补齐当前主干全部 locale,并通过文案检查
  • 已通过最新仓库要求的关联单元测试与涉及包类型检查,并如实记录更广泛测试失败

Signed-off-by: Stella-xixi <2559689615@qq.com>
@Stella-xixi
Stella-xixi requested a review from a team as a code owner August 31, 2026 13:30
@greptile-apps

greptile-apps Bot commented Aug 31, 2026

Copy link
Copy Markdown

Greptile Summary

此 PR 为 Desktop 中已唯一解析且位于来源工作目录内的文件引用增加“复制位置”菜单项。

  • 将 Markdown 文件目标已有的行列坐标传递至共享右键菜单
  • 使用工作目录相对路径生成 path:line[:column],并统一 Windows 输出分隔符
  • 保留原有绝对路径复制和文件打开行为,同时补充五种语言文案及回归测试

Confidence Score: 5/5

未发现需要阻止合并的具体问题,此 PR 看起来可以安全合并。

新动作仅对具备有效坐标且能换算为工作目录内相对路径的已解析文件显示,并保留了原有复制和打开行为;坐标、路径边界、远程工作目录及失败反馈均有对应校验和测试。

Important Files Changed

Filename Overview
apps/desktop/src/renderer/lib/fileLocation.ts 新增文件位置格式化函数,验证一基安全整数坐标并拒绝工作目录外路径。
apps/desktop/src/renderer/components/chat/useFileChipContextMenu.tsx 新增条件显示的“复制位置”动作,成功和剪贴板失败反馈与现有菜单行为一致。
apps/desktop/src/renderer/components/chat/MarkdownRenderer.tsx 将解析目标的绝对路径及行列信息透传给文件引用右键菜单,未改变解析和打开流程。
apps/desktop/src/renderer/tests/fileLocation.test.ts 覆盖 POSIX、Windows、远程逻辑路径、目录边界、无效坐标及范围起始行语义。
apps/desktop/src/renderer/tests/fileChipCopyLocation.test.tsx 覆盖菜单显隐、相对位置复制、原绝对路径动作、远程工作目录及剪贴板失败反馈。

Reviews (1): Last reviewed commit: "feat(desktop): support copying relative ..." | Re-trigger Greptile

@MagicLizi MagicLizi added awaiting-discussion 等待维护者讨论(review-pr) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) labels Sep 1, 2026
@MagicLizi

Copy link
Copy Markdown
Contributor

这个 PR 会给文件引用增加「复制相对位置」菜单项,已进入维护者确认,球不在作者手里。

请维护者直接在 PR 上 Approve;需要修改就 Request Changes。讨论 issue:#3717

@MagicLizi

Copy link
Copy Markdown
Contributor

命中 UI 路径(文件 chip 右键菜单 / Markdown 本地引用)但 description 未附界面效果证据——建议补充改动后效果:截图/录屏,或改动后界面的 HTML 页面,便于确认界面符合 DESIGN.md 设计规范。

@Stella-xixi

Copy link
Copy Markdown
Contributor Author

命中 UI 路径(文件 chip 右键菜单 / Markdown 本地引用)但 description 未附界面效果证据——建议补充改动后效果:截图/录屏,或改动后界面的 HTML 页面,便于确认界面符合 DESIGN.md 设计规范。

已在 PR description 中补充界面效果录屏和文字说明,展示「复制文件路径」和「复制位置」的实际效果,感谢建议。

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

Labels

awaiting-discussion 等待维护者讨论(review-pr) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

建议支持一键复制相对文件路径和行号

2 participants