Repository navigation
Add selected editor code to the chat draft with file and buffer-line context #416
Description
Problem and benefit
After finding code in Threadlane’s editor, asking the agent about a fragment requires copying it, switching to Chat, pasting, and adding its filename/location. A path mention cannot capture a partial selection or unsaved edits.
Add Add selection to chat to both file-editor hosts: append selected buffer text with its checkout-relative path and buffer line range to the current draft, then reveal/focus the composer. This is editable text, not an automatic send, live attachment, file write, or GitHub review comment.
Source inspiration
Source-code research only; no application was launched or visually inspected. Reviewed pinned snapshots, not necessarily the latest source HEADs:
- Synara:
WorkspaceFilePreview.tsx:832–881distinguishes exact source selections from rendered Markdown snippets and passes path plus selection toonReferenceInChat. The source-selection action here is limited to noneditable documents with a chat target.useCodeSelectionAction.ts:19–71implements the handoff. Borrow precise file context, not its floating web toolbar or assumptions about editable buffers. - T3 Code:
FilePreviewPanel.tsx:759–838normalizes selected line ranges and submits file review comments to a specificcomposerDraftTarget, carrying file path, range, text, and contents. Edit handling accounts for buffer changes and annotation remapping. Borrow explicit destination and provenance; do not adopt autosave, an annotation store, or persistent remapping.
The common useful idea is precisely identified file context in a draft without a clipboard round trip. Plain editable excerpts are a smaller fit than persistent reference chips or line-comment threads.
Current Threadlane architecture
Inspected ab06c9a373c777c8bc646ff3f89ef7c9fe42a82e, matching upstream HEAD during research:
EditorTab/EditorViewown checkout, relative path, dirty/loading state andEditorState. Current actions expose save/tab management, not selection-to-chat.- The Files panel is a second editable host:
RightPanelView::render_filescomposes sharedpanel_document_headerandeditor_buffer. Include both real file editors; exclude Review patch documents. threadlane-ui-kit/src/editor.rsowns presentation; hosts retain buffers, file access and guards.ChatListView::append_draft_text_foralready checks(work_dir, session_id), appends through an undoable edit, preserves images/clipboard, clears recall/completion, reveals Chat and focuses the composer. Reuse it, not another draft store or an unscoped queued insert.add_terminal_selection_to_chatprovides the guarded host-to-chat precedent; bounded safe-fence formatting is an existing reuse opportunity.- The pinned GPUI dependency exposes
selected_rangeas a UTF-8 byte range for the active selection andselected_value. No clipboard reads or new editor dependency are necessary. API availability alone does not prove focus behavior; test it in GPUI.
UX and interaction states
- Invoke: a quiet labeled Add selection to chat Button beside file actions in both hosts, plus the same editor-scoped Action in a keyboard-operable command surface. No hover-only or floating toolbar. Explain in tooltip/accessibility description that multiple cursors contribute only the active selection. Moving focus to the command must preserve the selection.
- Result: append
File excerpt: src/config.rs · buffer lines 12–18, a provenance label (Unsaved bufferwhen dirty, otherwiseBuffer snapshot), and a safely fenced exact excerpt. Preserve partial lines and whitespace. One-based inclusive line numbers refer to the captured buffer, not guaranteed current disk contents. Preserve prior draft/images/clipboard; reveal Chat and focus the composer only after success. One Undo removes the insertion without losing the prior draft. - Unavailable: disabled with textual reasons for empty active selection, loading/failed/non-text documents, Review/diff documents, no valid composer checkout, or source/destination checkout mismatch. Reject selections exceeding 32 KiB UTF-8 with
Select less code (maximum 32 KiB); never truncate silently. New-task drafts are eligible only with a matching checkout. A running agent does not change the action into send/queue/steer. - Stale activation: capture source entity/buffer, checkout, path, selection and destination key together. Revalidate source and destination immediately before append; stale tab/project/session changes leave drafts/files unchanged. Prefer synchronous capture/dispatch. Never replace selected unsaved text with a disk reread. Failures retain source selection and show a concise reason. Menus dismiss with Escape and restore focus; successful commands transfer focus after dismissal so menus cannot steal it back.
- Accessibility/scope: standard kit focus, hover, pressed and disabled states; semantic theme tokens, accessible names, no color-only status. Narrow widths retain a keyboard-reachable overflow command. No whole-file fallback, rendered Markdown/diff-side selection, GitHub comments, persistent citations/jump-back anchors, or automatic excerpt refresh.
Implementation plan
- Extend
crates/threadlane-ui-kit/src/editor.rswith shared controlled command/state for both hosts. Put only the minimal shared snapshot/formatting logic needed by both hosts in an appropriate existing shared module; no new service/reference framework. Reuse/extract safe-fence logic where practical. Derive text and line labels from the same byte range, correctly handling an exclusive end at the next line’s start, Unicode and embedded backticks. Bound bytes before copying; do not materialize whole buffers on every render. - Wire capture in
crates/threadlane-ui-editor/src/view.rsandcrates/threadlane-ui-right-panel/src/view.rsfrom existingEditorState, checkout/path and dirty status. Observe selection changes for availability. Keep file identity and stale-result guards in hosts. No filesystem reads, saves, or extension to Review documents. - Expose a small typed event/callback from each host. Route the central editor through its parent in
crates/threadlane-ui-chat/src/view.rs, and the Files panel throughcrates/threadlane-ui-workspace/src/view.rs, intoappend_draft_text_for. This avoids a dependency cycle from editor to chat. Revalidate captured identities and use the boolean success result for focus/error handling; do not introduce an asynchronous unscoped queue. - Add fixture-based enabled/empty/oversized/unsaved states to the existing
crates/threadlane-ui-kit/examples/previewgallery without browser-host filesystem access. Add formatting/guard tests and focused GPUI tests near existing editor/right-panel/chat/workspace tests. Follow AGENTS.md’s reuse/leaf-crate rules and native interaction guidance.
Acceptance criteria and validation
- Both editable file hosts expose the same named keyboard-operable command; Review/diff documents cannot invoke it.
- Exact selection, correct relative path/range and snapshot provenance reach the intended draft once. No send, queue mutation, save, clipboard change or image loss.
- Successful activation focuses the composer; Undo restores the prior draft and its existing history.
- Empty/oversized/loading and mismatched-checkout cases give useful reasons. Stale actions never land in another session or same-named file in another checkout.
- Unit tests cover forward/reverse and partial-line ranges, end-at-next-line-start, CRLF, Unicode, embedded fences, size boundary, active selection with multiple cursors, dirty buffers and source/destination identity changes.
- GPUI tests mounted under
gpui_component::Rootverify command focus does not erase selection, keyboard activation/dismissal, post-insert focus, clipboard/images and Undo. Include same session IDs in different projects. - Run focused
cargo nextest run -p <affected-package> <filter>,cargo check -p threadlane-gpuiandgit diff --checkusing the project toolchain. Manually exercise both hosts at minimum width, larger text and light/dark themes, during an active agent turn and session switching. Do not claim visual verification before doing it.
Duplicate research
Reviewed all 100 destination issues, open and closed, and searched concepts/synonyms including editor, snippet, selected code, code selection, file excerpt, line range, reference and add-to-chat. Inspected the neighboring bodies and discussion; the directly relevant issues below had no additional comments when checked.
- #32: completed basic editor, with no body/comments; current code lacks this handoff.
- #310: composer path completion, not selected buffer text or unsaved provenance.
- #377: find file contents/open matching lines, not editor-to-draft insertion.
- #320: terminal output, providing a reusable insertion precedent.
- #405: assistant-response text, not file identity, buffer line ranges, dirty-buffer provenance or either editor host.
- #350: composer insert identity hardening; reuse project/session scoping rather than reopen it.
Risks/tradeoffs
- Buffer line labels become stale after edits. Snapshot labeling and exact text are intentional; live remapping is out of scope.
- Cross-checkout insertion is intentionally rejected, even for deliberate comparisons, to keep v1 provenance/destination unambiguous.
- Two editor hosts can drift: shared kit presentation and matching tests should prevent divergent UX while hosts retain operational guards.
- Large-buffer materialization would hurt responsiveness. Use rope/range APIs and bounded extraction.
- Selected text may contain secrets. Require explicit insertion and a separate send action; add no telemetry/reference persistence channel.
Activity