Skip to content

Commit c8b8eff

Browse files
committed
Setting for number of terminal lines to return from commands
1 parent 667312e commit c8b8eff

File tree

8 files changed

+72
-5
lines changed

8 files changed

+72
-5
lines changed

.changeset/early-dodos-know.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"roo-cline": patch
3+
---
4+
5+
Add a setting to control the number of terminal output lines to pass to the model when executing commands

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ A fork of Cline, an autonomous coding agent, with some additional experimental f
2020
- Per-tool MCP auto-approval
2121
- Enable/disable MCP servers
2222
- Configurable delay after auto-writes to allow diagnostics to detect potential problems
23+
- Control the number of terminal output lines to pass to the model when executing commands
2324
- Runs alongside the original Cline
2425

2526
## Disclaimer

src/core/Cline.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -721,16 +721,32 @@ export class Cline {
721721
}
722722
}
723723

724-
let result = ""
724+
let lines: string[] = []
725725
process.on("line", (line) => {
726-
result += line + "\n"
726+
lines.push(line)
727727
if (!didContinue) {
728728
sendCommandOutput(line)
729729
} else {
730730
this.say("command_output", line)
731731
}
732732
})
733733

734+
const getFormattedOutput = async () => {
735+
const { terminalOutputLineLimit } = await this.providerRef.deref()?.getState() ?? {}
736+
const limit = terminalOutputLineLimit ?? 0
737+
738+
if (limit > 0 && lines.length > limit) {
739+
const beforeLimit = Math.floor(limit * 0.2) // 20% of lines before
740+
const afterLimit = limit - beforeLimit // remaining 80% after
741+
return [
742+
...lines.slice(0, beforeLimit),
743+
`\n[...${lines.length - limit} lines omitted...]\n`,
744+
...lines.slice(-afterLimit)
745+
].join('\n')
746+
}
747+
return lines.join('\n')
748+
}
749+
734750
let completed = false
735751
process.once("completed", () => {
736752
completed = true
@@ -749,7 +765,8 @@ export class Cline {
749765
// grouping command_output messages despite any gaps anyways)
750766
await delay(50)
751767

752-
result = result.trim()
768+
const output = await getFormattedOutput()
769+
const result = output.trim()
753770

754771
if (userFeedback) {
755772
await this.say("user_feedback", userFeedback.text, userFeedback.images)

src/core/webview/ClineProvider.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ type GlobalStateKey =
7676
| "fuzzyMatchThreshold"
7777
| "preferredLanguage" // Language setting for Cline's communication
7878
| "writeDelayMs"
79+
| "terminalOutputLineLimit"
7980

8081
export const GlobalFileNames = {
8182
apiConversationHistory: "api_conversation_history.json",
@@ -642,6 +643,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
642643
await this.updateGlobalState("writeDelayMs", message.value)
643644
await this.postStateToWebview()
644645
break
646+
case "terminalOutputLineLimit":
647+
await this.updateGlobalState("terminalOutputLineLimit", message.value)
648+
await this.postStateToWebview()
649+
break
645650
case "deleteMessage": {
646651
const answer = await vscode.window.showInformationMessage(
647652
"Are you sure you want to delete this message and all subsequent messages?",
@@ -1046,6 +1051,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
10461051
screenshotQuality,
10471052
preferredLanguage,
10481053
writeDelayMs,
1054+
terminalOutputLineLimit,
10491055
} = await this.getState()
10501056

10511057
const allowedCommands = vscode.workspace
@@ -1075,6 +1081,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
10751081
screenshotQuality: screenshotQuality ?? 75,
10761082
preferredLanguage: preferredLanguage ?? 'English',
10771083
writeDelayMs: writeDelayMs ?? 1000,
1084+
terminalOutputLineLimit: terminalOutputLineLimit ?? 500,
10781085
}
10791086
}
10801087

@@ -1174,6 +1181,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
11741181
preferredLanguage,
11751182
writeDelayMs,
11761183
screenshotQuality,
1184+
terminalOutputLineLimit,
11771185
] = await Promise.all([
11781186
this.getGlobalState("apiProvider") as Promise<ApiProvider | undefined>,
11791187
this.getGlobalState("apiModelId") as Promise<string | undefined>,
@@ -1218,6 +1226,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
12181226
this.getGlobalState("preferredLanguage") as Promise<string | undefined>,
12191227
this.getGlobalState("writeDelayMs") as Promise<number | undefined>,
12201228
this.getGlobalState("screenshotQuality") as Promise<number | undefined>,
1229+
this.getGlobalState("terminalOutputLineLimit") as Promise<number | undefined>,
12211230
])
12221231

12231232
let apiProvider: ApiProvider
@@ -1279,6 +1288,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
12791288
screenshotQuality: screenshotQuality ?? 75,
12801289
fuzzyMatchThreshold: fuzzyMatchThreshold ?? 1.0,
12811290
writeDelayMs: writeDelayMs ?? 1000,
1291+
terminalOutputLineLimit: terminalOutputLineLimit ?? 500,
12821292
preferredLanguage: preferredLanguage ?? (() => {
12831293
// Get VSCode's locale setting
12841294
const vscodeLang = vscode.env.language;

src/shared/ExtensionMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export interface ExtensionState {
6161
fuzzyMatchThreshold?: number
6262
preferredLanguage: string
6363
writeDelayMs: number
64+
terminalOutputLineLimit?: number
6465
}
6566

6667
export interface ClineMessage {

src/shared/WebviewMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export interface WebviewMessage {
4848
| "enhancedPrompt"
4949
| "draggedImages"
5050
| "deleteMessage"
51+
| "terminalOutputLineLimit"
5152
text?: string
5253
disabled?: boolean
5354
askResponse?: ClineAskResponse

webview-ui/src/components/settings/SettingsView.tsx

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
4646
setWriteDelayMs,
4747
screenshotQuality,
4848
setScreenshotQuality,
49+
terminalOutputLineLimit,
50+
setTerminalOutputLineLimit,
4951
} = useExtensionState()
5052
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
5153
const [modelIdErrorMessage, setModelIdErrorMessage] = useState<string | undefined>(undefined)
@@ -76,6 +78,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
7678
vscode.postMessage({ type: "preferredLanguage", text: preferredLanguage })
7779
vscode.postMessage({ type: "writeDelayMs", value: writeDelayMs })
7880
vscode.postMessage({ type: "screenshotQuality", value: screenshotQuality ?? 75 })
81+
vscode.postMessage({ type: "terminalOutputLineLimit", value: terminalOutputLineLimit ?? 500 })
7982
onDone()
8083
}
8184
}
@@ -210,6 +213,31 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
210213
</p>
211214
</div>
212215

216+
<div style={{ marginBottom: 5 }}>
217+
<div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
218+
<span style={{ fontWeight: "500", minWidth: '150px' }}>Terminal output limit</span>
219+
<input
220+
type="range"
221+
min="100"
222+
max="5000"
223+
step="100"
224+
value={terminalOutputLineLimit ?? 500}
225+
onChange={(e) => setTerminalOutputLineLimit(parseInt(e.target.value))}
226+
style={{
227+
flexGrow: 1,
228+
accentColor: 'var(--vscode-button-background)',
229+
height: '2px'
230+
}}
231+
/>
232+
<span style={{ minWidth: '45px', textAlign: 'left' }}>
233+
{terminalOutputLineLimit ?? 500}
234+
</span>
235+
</div>
236+
<p style={{ fontSize: "12px", marginTop: "5px", color: "var(--vscode-descriptionForeground)" }}>
237+
Maximum number of lines to include in terminal output when executing commands. When exceeded lines will be removed from the middle, saving tokens.
238+
</p>
239+
</div>
240+
213241
<div style={{ marginBottom: 5 }}>
214242
<VSCodeCheckbox checked={diffEnabled} onChange={(e: any) => setDiffEnabled(e.target.checked)}>
215243
<span style={{ fontWeight: "500" }}>Enable editing through diffs</span>
@@ -431,7 +459,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
431459
<div style={{ marginBottom: 10 }}>
432460
<div style={{ marginBottom: 15 }}>
433461
<h3 style={{ color: "var(--vscode-foreground)", margin: 0, marginBottom: 15 }}>Browser Settings</h3>
434-
<label style={{ fontWeight: "500", display: "block", marginBottom: 5 }}>Viewport Size</label>
462+
<label style={{ fontWeight: "500", display: "block", marginBottom: 5 }}>Viewport size</label>
435463
<select
436464
value={browserViewportSize}
437465
onChange={(e) => setBrowserViewportSize(e.target.value)}
@@ -460,7 +488,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
460488

461489
<div style={{ marginBottom: 15 }}>
462490
<div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
463-
<span style={{ fontWeight: "500", minWidth: '100px' }}>Screenshot Quality</span>
491+
<span style={{ fontWeight: "500", minWidth: '100px' }}>Screenshot quality</span>
464492
<input
465493
type="range"
466494
min="1"

webview-ui/src/context/ExtensionStateContext.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export interface ExtensionStateContextType extends ExtensionState {
3939
setWriteDelayMs: (value: number) => void
4040
screenshotQuality?: number
4141
setScreenshotQuality: (value: number) => void
42+
terminalOutputLineLimit?: number
43+
setTerminalOutputLineLimit: (value: number) => void
4244
}
4345

4446
export const ExtensionStateContext = createContext<ExtensionStateContextType | undefined>(undefined)
@@ -58,6 +60,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
5860
writeDelayMs: 1000,
5961
browserViewportSize: "900x600",
6062
screenshotQuality: 75,
63+
terminalOutputLineLimit: 500,
6164
})
6265
const [didHydrateState, setDidHydrateState] = useState(false)
6366
const [showWelcome, setShowWelcome] = useState(false)
@@ -176,6 +179,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
176179
setPreferredLanguage: (value) => setState((prevState) => ({ ...prevState, preferredLanguage: value })),
177180
setWriteDelayMs: (value) => setState((prevState) => ({ ...prevState, writeDelayMs: value })),
178181
setScreenshotQuality: (value) => setState((prevState) => ({ ...prevState, screenshotQuality: value })),
182+
setTerminalOutputLineLimit: (value) => setState((prevState) => ({ ...prevState, terminalOutputLineLimit: value })),
179183
}
180184

181185
return <ExtensionStateContext.Provider value={contextValue}>{children}</ExtensionStateContext.Provider>

0 commit comments

Comments
 (0)