Skip to content

Terminal Output Handling Refactor: Persisted Output Pattern #10941

@hannesrudolph

Description

@hannesrudolph

Summary

Refactor how Roo Code captures and relays terminal output to the LLM. Currently, output is compressed and truncated (lossy), which means information is permanently lost. Adopt a "persisted output" pattern inspired by Claude Code where full output is saved to disk and the LLM receives a fixed-size preview.

Problem

Current approach:

  • Output is compressed via RLE, carriage return processing, etc.
  • Then truncated to terminalOutputLineLimit (500) and terminalOutputCharacterLimit (100000)
  • 20% head / 80% tail split means middle content is permanently lost
  • Agent cannot recover truncated content
  • Variable context window cost (unpredictable)

Proposed Solution

Implement an OutputInterceptor that:

  1. Accumulates output up to a threshold (e.g., 4KB)
  2. If threshold exceeded, spills full output to disk artifact
  3. Returns preview (first N bytes) + artifact ID to LLM
  4. Agent can use new read_command_output tool to access full output when needed

Key Architectural Decisions

  1. Storage location: Artifacts stored in task storage directory (globalStoragePath/tasks/<taskId>/command-output/), NOT workspace
  2. Lifecycle: Artifacts tied to conversation history - cleaned up on task completion AND on history rewind/delete
  3. New tool required: read_command_output tool since existing read_file/search_files are workspace-scoped

Storage Architecture

globalStoragePath/tasks/<taskId>/
├── api_conversation_history.json    # Existing
├── ui_messages.json                 # Existing
├── task_metadata.json               # Existing
├── checkpoints/                     # Existing
└── command-output/                  # NEW
    ├── cmd-<executionId-1>.txt
    ├── cmd-<executionId-2>.txt
    └── ...

Settings Changes

Remove

  • terminalOutputLineLimit (slider)
  • terminalOutputCharacterLimit (slider)

Keep

  • terminalCompressProgressBar (checkbox) - still useful for preview quality

Add

  • terminalOutputPreviewSize (dropdown: Small 2KB / Medium 4KB / Large 8KB)
    • Default: Medium (4KB)

Implementation Phases

  1. Phase 1: Types - Add TerminalOutputPreviewSize, PersistedCommandOutput types
  2. Phase 2: OutputInterceptor - Core class for buffering + spilling to disk
  3. Phase 3: ExecuteCommandTool Integration - Wire interceptor into command execution
  4. Phase 4: Lifecycle Management - Cleanup on task completion + history rewind
  5. Phase 5: Settings UI - Remove old sliders, add new dropdown
  6. Phase 6: read_command_output Tool - New tool to access artifacts
  7. Phase 7: Testing - Unit + integration + manual tests
  8. Phase 8: Documentation - Update docs

New Tool: read_command_output

interface ReadCommandOutputParams {
  artifact_id: string      // e.g., "cmd-1706119234567.txt"
  search?: string          // Optional: grep-like search
  offset?: number          // Optional: byte offset
  limit?: number           // Optional: max bytes (default: 32KB)
}

Tool Result Format

When output fits in preview:

Command executed in '/project'. Exit code: 0
Output:
npm install completed successfully.

When output exceeds preview:

Command executed in '/project'. Exit code: 1

Output (47.3KB) persisted. Artifact ID: cmd-1706119234.txt

Preview:
> npm test
FAIL src/integrations/terminal/...
...

Use read_command_output tool to view full output if needed.

Success Criteria

  • Commands producing <4KB output work identically to before (inline)
  • Commands producing >4KB output create artifacts in task storage
  • Agent can successfully use read_command_output on artifacts
  • Artifacts are cleaned up on task completion
  • Artifacts are cleaned up on history rewind/delete
  • Settings UI shows new dropdown, old sliders removed
  • No increase in memory usage for large outputs
  • Context window usage is predictable (preview size)

References

  • Detailed implementation plan: plans/terminal-output-refactor-plan.md
  • Claude Code research: .roo/commands/claude-code-terminal.md
  • Current implementation: src/core/tools/ExecuteCommandTool.ts

Metadata

Metadata

Assignees

No one assigned

    Labels

    EnhancementNew feature or request

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions