Skip to content

feat(composer): spill large text pastes to session scratch files #20

Description

@vastsa

Summary

When a user pastes a long text block into the Composer, the entire block currently remains in the textarea and is sent as prompt content. Add a configurable character threshold (default: 600) that converts oversized text-only pastes into session-scoped temporary text files and inserts an inline @<temporary-file-name> reference at the original paste position.

Current behavior

  • Text-only paste uses the native textarea path.
  • OS file/image paste already writes to <data_dir>/scratch/<sessionId>/pasted/ through the Electron composer paste bridge.
  • Session scratch files are removed with the session and by the startup sweep.
  • Composer references use a display name plus an internal canonical path.

Requirements

  • Add a Composer setting for the paste threshold, defaulting to 600 characters.
  • Apply the threshold to text-only clipboard content; 600 or fewer characters remain inline, and values above the threshold are converted.
  • Count whitespace and newlines; preserve the pasted text exactly as UTF-8 in a .txt file.
  • Save the file under the active session's scratch pasted/ directory. If the home Composer has no session yet, materialize the session before saving.
  • Replace the selected paste range at the original caret position with @<temporary-file-name> and preserve surrounding draft text.
  • Keep a session-scoped structured mapping from the displayed reference to the canonical scratch path. Dispatch must resolve the mapping exactly once so the agent receives a valid @ reference and never an unresolved basename or duplicate fallback.
  • Preserve the mapping through queueing, session draft restoration, and unanswered Stop restoration. Removing or editing the generated token must stop it from being dispatched as a file reference.
  • Keep existing file/image paste behavior and the native path for text at or below the threshold unchanged.
  • Do not write into the project workspace or dirty Git state. Reuse existing scratch cleanup and security boundaries.
  • Show the existing busy/error states while the asynchronous save is in progress or fails.

Acceptance criteria

  1. Pasting 599 and 600 characters inserts the text inline without creating a file.
  2. Pasting 601 characters creates one unique session scratch .txt file and inserts its @ reference at the paste location.
  3. Multiline text, whitespace, Unicode text, selection replacement, and mid-draft paste preserve the expected content and caret behavior.
  4. Sending the draft lets the agent read the temporary file; the full pasted block is not included in prompt content.
  5. Switching sessions never leaks a temporary reference into another session.
  6. Deleting the session removes the generated file.
  7. Save failures leave the draft unchanged and do not leave an invalid reference.
  8. The setting is localized, validated, and persists using the existing settings flow.

Scope notes

This is intentionally limited to text-only clipboard paste. Clipboard payloads containing OS files/images continue through the existing file paste flow. Update the relevant UX/runtime specs, ADR decision record, and E2E test plan together with the implementation.

Related implementation

  • apps/desktop/src/components/Composer.tsx
  • apps/desktop/electron/main/composer-paste.ts
  • apps/desktop/electron/main/index.ts
  • packages/shared/src/composer-trigger.ts
  • Existing ADRs 0024, 0059, and 0070

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions