Browse Source

feat: compress repeated terminal output lines

Add Terminal.compressTerminalOutput static method to apply run-length encoding
before truncating terminal output. This significantly reduces output size for
repeated lines while maintaining readability.

- Add compressTerminalOutput static method to Terminal class
- Replace all truncateOutput calls with Terminal.compressTerminalOutput
- Import required functions from extract-text

Test program demonstrating compression:
```python
def generate_repeats():
    patterns = [
        ("A\n", 10),          # 10 lines
        ("AA\n", 100),        # 100 lines
        ("AAA\n", 1000),      # 1K lines
        ("AAAA\n", 10000),    # 10K lines
        ("AAAAA\n", 100000),  # 100K lines
        ("AAAAAA\n", 1000000) # 1M lines
    ]

    for text, count in patterns:
        print(text * count, end="")
```

Sample output showing compression:
```
A
A
A
A
A
A
A
A
A
A
AA
<previous line repeated 99 additional times>
AAA
<previous line repeated 999 additional times>
AAAA
<previous line repeated 9999 additional times>
AAAAA
<previous line repeated 99999 additional times>
AAAAAA
<previous line repeated 999999 additional times>
```

Signed-off-by: Eric Wheeler <[email protected]>
Eric Wheeler 11 months ago
parent
commit
0b4fa0b1d6
2 changed files with 16 additions and 6 deletions
  1. 6 6
      src/core/Cline.ts
  2. 10 0
      src/integrations/terminal/Terminal.ts

+ 6 - 6
src/core/Cline.ts

@@ -25,9 +25,9 @@ import {
 	addLineNumbers,
 	stripLineNumbers,
 	everyLineHasLineNumbers,
-	truncateOutput,
 } from "../integrations/misc/extract-text"
 import { ExitCodeDetails } from "../integrations/terminal/TerminalProcess"
+import { Terminal } from "../integrations/terminal/Terminal"
 import { TerminalRegistry } from "../integrations/terminal/TerminalRegistry"
 import { UrlContentFetcher } from "../services/browser/UrlContentFetcher"
 import { listFiles } from "../services/glob/list-files"
@@ -968,9 +968,9 @@ export class Cline {
 
 		process.on("line", (line) => {
 			if (!didContinue) {
-				sendCommandOutput(truncateOutput(line, terminalOutputLineLimit))
+				sendCommandOutput(Terminal.compressTerminalOutput(line, terminalOutputLineLimit))
 			} else {
-				this.say("command_output", truncateOutput(line, terminalOutputLineLimit))
+				this.say("command_output", Terminal.compressTerminalOutput(line, terminalOutputLineLimit))
 			}
 		})
 
@@ -1000,7 +1000,7 @@ export class Cline {
 		// grouping command_output messages despite any gaps anyways)
 		await delay(50)
 
-		result = truncateOutput(result, terminalOutputLineLimit)
+		result = Terminal.compressTerminalOutput(result, terminalOutputLineLimit)
 
 		if (userFeedback) {
 			await this.say("user_feedback", userFeedback.text, userFeedback.images)
@@ -3546,7 +3546,7 @@ export class Cline {
 				terminalDetails += `\n## Original command: \`${busyTerminal.getLastCommand()}\``
 				let newOutput = TerminalRegistry.getUnretrievedOutput(busyTerminal.id)
 				if (newOutput) {
-					newOutput = truncateOutput(newOutput, terminalOutputLineLimit)
+					newOutput = Terminal.compressTerminalOutput(newOutput, terminalOutputLineLimit)
 					terminalDetails += `\n### New Output\n${newOutput}`
 				} else {
 					// details += `\n(Still running, no new output)` // don't want to show this right after running the command
@@ -3573,7 +3573,7 @@ export class Cline {
 				for (const process of completedProcesses) {
 					let output = process.getUnretrievedOutput()
 					if (output) {
-						output = truncateOutput(output, terminalOutputLineLimit)
+						output = Terminal.compressTerminalOutput(output, terminalOutputLineLimit)
 						terminalOutputs.push(`Command: \`${process.command}\`\n${output}`)
 					}
 				}

+ 10 - 0
src/integrations/terminal/Terminal.ts

@@ -1,6 +1,7 @@
 import * as vscode from "vscode"
 import pWaitFor from "p-wait-for"
 import { ExitCodeDetails, mergePromise, TerminalProcess, TerminalProcessResultPromise } from "./TerminalProcess"
+import { truncateOutput, applyRunLengthEncoding } from "../misc/extract-text"
 
 export class Terminal {
 	public terminal: vscode.Terminal
@@ -218,4 +219,13 @@ export class Terminal {
 			throw error
 		}
 	}
+
+	/**
+	 * Compresses terminal output by applying run-length encoding and truncating to line limit
+	 * @param input The terminal output to compress
+	 * @returns The compressed terminal output
+	 */
+	public static compressTerminalOutput(input: string, lineLimit: number): string {
+		return truncateOutput(applyRunLengthEncoding(input), lineLimit)
+	}
 }