feat(desktop): file reference & rich input enhancement文件引用与富文本输入增强#6414
Closed
SauronSkywalker wants to merge 7 commits into
Closed
feat(desktop): file reference & rich input enhancement文件引用与富文本输入增强#6414SauronSkywalker wants to merge 7 commits into
SauronSkywalker wants to merge 7 commits into
Conversation
SauronSkywalker
force-pushed
the
feat/file-ref-rich-input_20260713_170000
branch
from
July 18, 2026 02:46
e6ed1bf to
e7a0f11
Compare
Unify workspace file references (right-click/@-menu/drag-drop) into inline @path text instead of workspaceRef cards. Keep the workspaceRefs system intact — just redirect the 4 entry points to insert @path at cursor. Changes: - Composer.tsx: 4 entry points changed to insert @path; submit cleanup; empty-file error handling with new locale key - RichComposerInput.tsx: command highlighting for @refs, /commands, #chats - attachmentDisplay.ts: highlightRefsInText() for message bubble rendering - ComposerContextCard.tsx: stopPropagation on remove button - Message.tsx: filter workspace refs from cards, show full path, click-to-open - styles.css: command/ref highlight styles - locales: attachDropEmptyFile key (en/zh/zh-TW)
Add forceRich state: once a file reference is inserted as @path text, the composer switches from textarea to RichComposerInput so command highlighting works for @refs, /commands, #chats, !shell. - New useState forceRich, default false - Render ternary: invocations.length > 0 || forceRich → RichComposerInput - setForceRich(true) in all 4 @path insertion entry points - setForceRich(false) on draft clear - Textarea remains default on fresh start, switches permanently after first @path insertion
Remove the now-unused workspace refs card system since all file references are inserted as inline @path text. The workspaceRefs state, ref, draft fields, card rendering, and related functions (workspaceReferenceKey, removeWorkspaceReference) are no longer needed because the 4 entry points now directly insert @path text. Still preserved (actively used): - workspaceRef: WorkspaceReference type (used by composePickFileEntry) - formatWorkspaceReference / parseWorkspaceReference / reader - WORKSPACE_REF_DRAG_TYPE for drag detection
- attachments.go: split empty/directory/oversize errors for accurate messages - attachmentDisplay.ts: remove refTokenRe step (fix @path disappearing from bubbles); fold spaces to single instead of vanishing (both before punctuation and at edges) - Message.tsx: add highlightRefsInText in invocation rendering path - Composer.tsx: 7-category error mapping for attach failures; document-level drag interceptor (🚫 outside composer); restoreDraft forceRich detection; onDragOver stopPropagation to prevent interference
…path - attachmentDisplay.ts: fully remove whitespace folding (user request) - RichComposerInput.tsx: use match.index as span key (stable); split leading whitespace out of highlight span; guard empty core - open_workspace_windows.go: wrap path into error message for debugging
…ssion file locks Windows-only: WebView2 (msedgewebview2.exe) child processes may persist after the main window closes, holding file locks on session data. - killWebView2Processes(): enumerate processes via CreateToolhelp32Snapshot, find msedgewebview2.exe with ParentProcessID == our PID, TerminateProcess - killOrphanWebView2(): startup-time cleanup for crash-leftover orphans - Unix stubs for macOS/Linux (no WebView2)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request:文件引用内联化、输入框命令高亮与多项体验修复
CI 合规说明
本 PR 的 CI 检查项覆盖:
desktop/gofmtgofmt -l输出为空desktop/go mod tidydesktop/pnpm install --frozen-lockfiledesktop/pnpm builddesktop/go vetdesktop/go builddesktop/golangci-linttest / test -racesite/npm test变更总览(11 个文件)
1.
attachmentDisplay.ts— @path 显示修复 + highlightRefsInText为什么改:
parseAttachmentRefsForDisplay()中的refTokenRe()步骤将@path从显示文本剥离为卡片,但 workspace 卡片已被移除,导致@path在消息气泡中完全消失。改了什么:
.replace(refTokenRe(), ...)整个步骤(~8 行)unescapeRefPath导入.replace(/[ \t]+...、.trim()等 3 行)——CSSwhite-space: pre-wrap已保证空格保留,JS 层额外折叠是多余的highlightRefsInText()导出函数:用refTokenRe()分割文本,返回{text, isRef}[]分段效果:
@src/main.go在消息气泡中正常显示,不再消失;空格原样保留。2.
RichComposerInput.tsx— 输入框命令高亮为什么改:用户在输入
@src/main.go、/help、#history、!shell等 token 时没有视觉区分。改了什么:
CMD_HIGHLIGHT_RE正则:/(^|\s)(@(?!\[)[^\s]+|/[A-Za-z][A-Za-z0-9_.:-]*|#[^\s]+|![^\s]+)/gTRAILING_PUNCTUATION_RE:剥离尾部标点(,.;:等)renderHighlightedText():将文本分段为普通段和高亮段match[1]移出<span>(避免空白变色)match.index(稳定,避免 React 不必要的 DOM 重建)效果:输入框中
@refs、/commands、#chats、!shell实时显示为主题强调色。3.
ComposerContextCard.tsx— 移除按钮事件修复为什么改:点击附件卡片的 × 按钮同时触发了卡片的打开操作。
改了什么:
onClick={onRemove}→onClick={(e) => { e.stopPropagation(); onRemove(); }}效果:点击 × 只移除附件,不打开文件。
4.
Message.tsx— 消息气泡改进为什么改:
@path需要可点击打开文件改了什么:
cardAttachments = orderedAttachments.filter(a => a.source !== "workspace")→ 引用不生成卡片${ext} · ${source}改为{attachment.path}onClick={() => app.OpenWorkspacePath(path)}→ 点击可打开文件highlightRefsInText()+.ref-highlight--clickableunescapeRefPath导入,用于解析 @path 的转义字符效果:消息气泡中的
@path显示为高亮色、可点击打开文件;卡片显示完整路径;workspace 引用不在气泡中生成卡片。5.
styles.css— 高亮样式为什么改:没有 CSS 类,高亮不可见。
改了什么:+14 行新样式:
6.
Composer.tsx— 核心改动6.1 文件引用改为内联 @path
为什么改:右键/拖拽/@菜单插入文件引用时生成卡片,用户无法原地编辑,路径被截断。
改了什么:4 个入口点(
insertRequesteffect、attachDroppedPaths、onDrop、pickEntry)从调用addWorkspaceReference()改为在光标处插入formatWorkspaceReference()构建的@path文本。效果:所有文件引用方式统一为内联
@path文本,可原地编辑。6.2 workspaceRefs 系统清理
为什么改:4 个入口不再写入 workspaceRefs 后,state/ref/draft/渲染代码全部变为死代码。
改了什么:删除 ~34 行代码,包括
workspaceRefsstate、workspaceRefsRef、workspaceReferenceKey、addWorkspaceReference、addWorkspaceReferenceToDraft、removeWorkspaceReference、相关 draft 字段和卡片渲染 JSX。6.3 forceRich 自动切换
为什么改:textarea 不支持富文本渲染,插入 @path 后需要切换到 RichComposerInput 使命令高亮可见。
改了什么:新增
forceRichstate,4 个入口插入 @path 后setForceRich(true),渲染条件改为invocations.length > 0 || forceRich ?。提交后重置为 false。附加保护:
restoreComposerDraft检测 @path 自动切富文本draftKey变化时重置 forceRichrequestAnimationFrame兜底焦点6.4 拖放错误 7 种消息映射
为什么改:所有拖放失败统一显示"附件附加失败",用户无法定位问题。
改了什么:catch 块根据 Go 错误消息关键词匹配显示准确提示:
no such file or directory→File not foundpermission denied→Permission deniedattachment/image file is empty→File is empty (0 bytes)path is a directory→Path is a directory, not a filemust be between 1 byte and 25/10 MB→File/Image exceeds limitworkspace is not ready→Workspace is not readymust not be a symlink→Symbolic links are not allowedno space left on device→Disk is full6.5 文件拖放光标反馈
为什么改:鼠标拖文件到窗口任意位置都显示"复制"光标,但实际只有拖入输入框才生效。
改了什么:
dragover拦截 → 不可拖放区域dropEffect='none'→ 🚫 禁止符号onDragOver添加stopPropagation+dropEffect='copy'→ ✅ 复制符号7.
locales(en/zh/zh-TW)— 翻译补充新增
"composer.attachDropEmptyFile"key:File is empty (0 bytes), cannot attach文件为空(0字节),无法附加文件為空(0位元組),無法附加8.
attachments.go— Go 后端错误拆分为什么改:Go 端对文件为空、文件过大、目录返回完全相同的错误消息,前端无法区分。
改了什么:7 处检查点从合并条件拆分为三段独立判断:
9.
open_workspace_windows.go— 错误消息包含路径为什么改:文件打开失败时只返回 "The system cannot find the file specified",不包含具体路径,难以排查。
改了什么:将
openWorkspacePath的错误包装为fmt.Errorf("open %q: %w", path, err),错误消息包含完整路径。效果总结
@path直接插入文本,可编辑