Skip to content

feat(vscode): add copy content button to Documents viewer - #14634

Merged
brunoagatao merged 12 commits into
mainfrom
feat/documents-copy-content
Oct 1, 2026
Merged

brunoagatao merged 12 commits into
mainfrom
feat/documents-copy-content

Conversation

@brunoagatao

@brunoagatao brunoagatao commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

What

Adds a copy affordance to the Kilo Documents viewer panel:

  • A toolbar "Copy content" icon button that copies the full document text to the clipboard, with a brief check-icon confirmation.
  • A right-click context menu on the document content with "Copy" and, for non-Markdown files, "Copy as Markdown" (wraps the content in a fenced code block using the file extension as the language).

Why

Closes #14598. Users viewing a file in the Documents panel had no quick way to copy its content.

Notes

  • Uses navigator.clipboard.writeText directly in the shared DocumentPanel component, since it renders in both the standalone Documents webview and the Agent Manager inline host — this avoids duplicating a host-side clipboard handler for each.
  • Added agentManager.documents.copy / `agentManager.documents.copyAsMarkdown" strings to all locale files (existing i18n split test requires every agent-manager key to be present in every locale).
1 2 3 4

Adds a toolbar button and right-click context menu with Copy and
Copy as Markdown actions for the Documents viewer panel content.

Closes #14598
@kilo-code-bot

kilo-code-bot Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

The previously flagged issue (copy-confirmation timer cancelled before the clipboard write settled) is resolved in 99476546ac: clearTimeout(copyTimer) now runs only after copyText succeeds, so a failed re-copy leaves the prior timer running instead of stranding the check icon.

Files Reviewed (1 file)
  • packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx
Previous Review Summaries (6 snapshots, latest commit 17abdb9)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 17abdb9)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx 138 The copy-confirmation timer is cancelled before the clipboard write settles, so a failed re-copy leaves the success check stuck.
Files Reviewed (6 files)
  • packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx - 1 suggestion
  • packages/kilo-vscode/webview-ui/documents/state.ts
  • packages/kilo-vscode/webview-ui/src/components/chat/SessionTabMenu.tsx
  • packages/kilo-vscode/src/DocumentViewerProvider.ts
  • packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts
  • packages/kilo-vscode/tests/unit/agent-manager-documents.test.ts

Previously raised findings are resolved: copyText now logs clipboard failures instead of swallowing them, path actions use the canonical documentPath, and host clipboard promises are handled.

Fix these issues in Kilo Cloud

Previous review (commit 7ee84c8)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx 66 copyText swallows a rejected writeText with an empty .catch, hiding clipboard failures.
Files Reviewed (33 files)
  • packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx - reworked copy; 1 suggestion
  • packages/kilo-vscode/webview-ui/documents/index.tsx
  • packages/kilo-vscode/webview-ui/documents/state.ts
  • packages/kilo-vscode/webview-ui/src/components/chat/SessionTabMenu.tsx
  • packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts
  • packages/kilo-vscode/webview-ui/agent-manager/ClosableTab.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/documents/DocumentPanelHost.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/i18n/*.ts (21 locale files) - new copy keys present in all locales
  • packages/kilo-vscode/src/DocumentViewerProvider.ts
  • packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts
  • packages/kilo-vscode/src/agent-manager/types.ts
  • packages/kilo-vscode/tests/unit/agent-manager-documents.test.ts
  • .changeset/copy-document-content.md

Fix these issues in Kilo Cloud

Previous review (commit 661fcbc)

Status: No Issues Found | Recommendation: Merge

The incremental commit 661fcbc adds a fenceFor helper that sizes the Markdown code fence past the longest run of backticks in the copied content, so content cannot prematurely close the block. This resolves the prior review's concern about content containing triple backticks. Previously raised suggestions remain resolved and no new issues were found in the changed lines.

Files Reviewed (1 file)
  • packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx - fence sizing fix, no new issues

Previous review (commit 459d88a)

Status: No Issues Found | Recommendation: Merge

All four prior suggestions on DocumentPanel.tsx were resolved in commit 459d88a: the Markdown fence language is derived from the file basename (so extensionless files no longer use the whole filename), the copy-confirmation timer is cleared via onCleanup, clipboard failures are handled with .then/.catch, and the toolbar copy button is now hidden for image documents. No new issues found in the incremental diff.

Files Reviewed (1 changed file)
  • packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx - 4 prior suggestions resolved, no new issues

Previous review (commit 9fd3536)

Status: 4 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 4
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx 103 file().split(".").pop() yields the whole filename as the Markdown fence language for extensionless files (LICENSE, Makefile) and leaks directory dots.
packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx 109 Copy confirmation timeout is never cleared, so a pending timer can outlive the component.
packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx 107 Clipboard write is fire-and-forget; a failed writeText still shows the success check and the rejection is unhandled.
packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx 277 Copy button is shown for kind === "image" documents where content() is empty, copying an empty string with a success flash.
Files Reviewed (23 files)
  • packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx - 4 suggestions
  • packages/kilo-vscode/webview-ui/agent-manager/i18n/*.ts (21 locale files) - unchanged since prior review, new keys present in all locales, no issues
  • .changeset/copy-document-content.md - unchanged since prior review, user-facing description, no issues

Fix these issues in Kilo Cloud

Previous review (commit 34ec938)

Status: 4 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 4
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx 107 file().split(".").pop() yields the whole filename as the Markdown fence language for extensionless files (LICENSE, Makefile) and leaks directory dots.
packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx 102 Copy confirmation timeout is never cleared, so a pending timer can outlive the component.
packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx 111 Clipboard write is fire-and-forget; failure still shows the success check and the rejection is unhandled (also line 115).
packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx 284 Copy button is shown for kind === "image" documents where content() is empty, copying an empty string with a success flash.
Files Reviewed (23 files)
  • packages/kilo-vscode/webview-ui/documents/DocumentPanel.tsx - 4 suggestions
  • packages/kilo-vscode/webview-ui/agent-manager/i18n/*.ts (21 locale files) - new keys present in all locales, no issues
  • .changeset/copy-document-content.md - user-facing description, no issues

Fix these issues in Kilo Cloud


Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0

Review guidance: REVIEW.md from base branch main

- Fix Markdown fence language extraction to use the basename instead
  of splitting the full path, so files like LICENSE/Makefile or paths
  with dotted directories don't leak into the fence language.
- Clear the copy-confirmation timer on cleanup and before re-copying.
- Handle clipboard write rejection instead of always flashing success.
- Hide the toolbar copy button for image documents, matching the
  existing content-area and context-menu image gating.
@brunoagatao brunoagatao self-assigned this Sep 28, 2026
Copy as Markdown wrapped content in a fixed triple-backtick fence,
which breaks if the copied content itself contains a run of three or
more backticks (e.g. a nested code block). The fence now expands past
the longest backtick run found in the content, per the CommonMark
fenced code block rule.

@kirillk kirillk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review findings

  1. High: this does not complete the linked issue. Issue #14598 requests document-tab actions for Copy Path, Copy Relative Path, Copy File Name, and Open in Editor. Tabs still receive only close actions in DocumentPanel.tsx:331-355. This PR instead adds a context menu to the document body, so it should not close the issue as implemented.

  2. Medium: Copy Content is enabled while content is unavailable or stale. The toolbar only checks !isImage() at DocumentPanel.tsx:299-309. Loading and errored documents pass that condition, while content() converts missing content to an empty string. Opening a missing, binary, or oversized document leaves a working copy button that overwrites the clipboard with an empty string and reports success. During refresh, it can copy cached stale content.

  3. Medium: the custom menu regresses selection-based copying in the standalone Documents panel. The trigger at DocumentPanel.tsx:370-406 suppresses the native context menu, and Copy Content always copies the complete document. Previously, users could select one line and use the native right-click Copy action. This is specifically a standalone-panel regression; Agent Manager already suppresses native menus globally.

  4. Medium: Copy as Markdown can crash on an accepted large document. fenceFor spreads every backtick match into Math.max at DocumentPanel.tsx:64-67, while the document reader accepts files up to 2 MB. A valid file containing "` ".repeat(1_000_000) reproduces RangeError: Maximum call stack size exceeded. A loop or reduction avoids the argument limit.

  5. Low: Copy as Markdown adds an extra blank line when the source already ends in a newline. DocumentPanel.tsx:76 always inserts another newline before the closing fence. For example, content ending in const x = 1\n gains an empty line inside the fenced block.

  6. Low: copy confirmation belongs to the panel rather than the document. Copy document A and switch to B within 1.5 seconds; B shows the check icon even though it was not copied. The state at DocumentPanel.tsx:135-138 is not reset by the tab-change effect.

Context-menu convention

Using @kilocode/kilo-ui/context-menu is consistent with existing Agent Manager UI. It is not the native VS Code webview pattern: VS Code recommends contributes.menus["webview/context"] with data-vscode-context, which integrates with the editor menu and preserves default selection-based Copy/Paste items. The custom menu is reasonable for Agent Manager, but the native mechanism is a better fit for the standalone DocumentViewerProvider and avoids the selection-copy regression.

No tests were added for the new serialization, loading/error gating, tab switching, or either host menu behavior.

kirillk's review found this PR did not implement the issue as scoped
and introduced several regressions/bugs with the added document-body
context menu and 'Copy as Markdown' feature. Address each point:

- Remove the document-body right-click menu and 'Copy as Markdown'.
  It suppressed the native context menu in the standalone Documents
  webview, regressing selection-based Copy, and its fence-wrapping
  logic had unrelated bugs (stack overflow on huge inputs, spurious
  blank lines). This was scope creep beyond the linked issue.
- Add the tab context menu actions the issue actually requested:
  Copy Path, Copy Relative Path, Copy File Name, and Open in Editor.
  Copy Path needs the workspace-absolute path, which the webview does
  not know, so it round-trips through a new 'document.copyPath'
  message (standalone DocumentViewerProvider) and a new
  'agentManager.copyFilePath' message (Agent Manager), both resolving
  the path host-side and writing to the clipboard.
- Gate the toolbar Copy Content button on loading/error state (not
  just image kind), so it cannot copy an empty or stale string while
  flashing success.
- Reset the copy-confirmation state when the active tab changes, so
  switching documents right after a copy no longer shows a stale
  checkmark on the wrong tab.
- Add unit tests for the new copyPath/openFile message plumbing.
@brunoagatao

brunoagatao commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator Author

@kirillk Thanks for the thorough review. I've addressed the points you outlined above and would appreciate another cycle-through 🙂

Select All previously selected the entire panel DOM (header title,
tab labels, action icons), not just the file's text -- the core
complaint in issue #14598. Intercept Cmd/Ctrl+A while focus is inside
the panel and outside any editable field, and select only the
rendered document content instead, matching what Copy Content
copies.
@kirillk

kirillk commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

Re-review findings at b7d7e9437e2

  1. High: absolute document paths break the new path actions. createDocuments.open() retains the original path in tab.file (webview-ui/documents/state.ts:67-79), even though readDocument() canonicalizes successful results to a relative path. The menu uses the original value at DocumentPanel.tsx:368-378.

    For an absolute in-worktree Markdown path:

    • Copy Relative Path copies the absolute path.
    • Standalone Copy Path does nothing because resolveInside() rejects absolute paths at src/diff/shared/path.ts:3-8.
    • On Windows, getFilename() only recognizes /, so a C:\repo\docs\file.md input makes Copy File Name and the tab label contain the entire path.

    The canonical DocumentData.file value should be used for relative path and filename actions. Tests currently cover only relative inputs.

  2. Low: delayed clipboard completion can still show confirmation on the wrong tab. Switching tabs resets copied, but an unresolved write from tab A can subsequently resolve and set the shared signal back to true on tab B. See DocumentPanel.tsx:69-81 and DocumentPanel.tsx:245-257. The operation needs a generation token or active-file check before updating confirmation state.

  3. Low: path-copy failures are silently swallowed or left unhandled. copyText() has an empty catch at DocumentPanel.tsx:65-67, which violates the repository error-handling rule. Standalone and Agent Manager host clipboard promises are also discarded at DocumentViewerProvider.ts:111-115 and AgentManagerProvider.ts:881-884.

The previous scope and context-menu findings are otherwise resolved: all requested tab actions are present, Copy as Markdown and the document-body custom menu were removed, standalone selected-text Copy is restored, loading/error gating is fixed, and immediate confirmation leakage is reset on tab changes.

Validation passed for typecheck, lint, knip, whitespace checks, and 107 focused tests. All hosted PR checks are green.

@kirillk

kirillk commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

@brunoagatao it seems 1-3 are worth addressing

- Copy Path/Relative Path/File Name and the tab label use the loaded
  document's canonical relative path, so absolute inputs work (and
  Windows separators no longer leak into names).
- Ignore late clipboard completions after switching tabs.
- Log clipboard failures instead of swallowing or dropping them.
- Track the copied file path instead of a boolean, removing the tab-switch
  reset and stale-completion guard.
- Select-all: ignore stale (detached) content, Shift/Alt variants, and
  editable targets inside shadow roots.
- Evaluate the tab menu's leading items once.
@brunoagatao

Copy link
Copy Markdown
Collaborator Author

@kirillk Addressed 🙂 Thanks again for the feedback!

@brunoagatao
brunoagatao merged commit b4dd1db into main Oct 1, 2026
26 checks passed
@brunoagatao
brunoagatao deleted the feat/documents-copy-content branch October 1, 2026 11:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add copy document content button and context menu options in Documents viewer

4 participants