Skip to content

Commit fdcdcb6

Browse files
ContinueRomneyDa
andcommitted
Address PR feedback: simplify context handling and improve bash truncation
- Remove duplicate token validation logic; use compileChatMessages directly - Eliminate unnecessary conversions between unified history and ChatMessage formats - Change bash tool truncation to keep LAST X lines/chars instead of first X - Better captures test/install outcomes at the end of command output - Simplify pruning flow: always use compileChatMessages for context management Addresses feedback from @RomneyDa and @chezsmithy Co-authored-by: dallin <dallin@continue.dev>
1 parent 7a62835 commit fdcdcb6

File tree

2 files changed

+52
-89
lines changed

2 files changed

+52
-89
lines changed

extensions/cli/src/stream/streamChatResponse.ts

Lines changed: 43 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ import { ModelConfig } from "@continuedev/config-yaml";
22
import { BaseLlmApi } from "@continuedev/openai-adapters";
33
import type { ChatHistoryItem } from "core/index.js";
44
import { compileChatMessages } from "core/llm/countTokens.js";
5-
import {
6-
convertFromUnifiedHistoryWithSystemMessage,
7-
convertToUnifiedHistory,
8-
} from "core/util/messageConversion.js";
5+
import { convertFromUnifiedHistoryWithSystemMessage } from "core/util/messageConversion.js";
96
import * as dotenv from "dotenv";
107
import type {
118
ChatCompletionMessageParam,
@@ -22,7 +19,6 @@ import {
2219
withExponentialBackoff,
2320
} from "../util/exponentialBackoff.js";
2421
import { logger } from "../util/logger.js";
25-
import { validateContextLength } from "../util/tokenizer.js";
2622

2723
import { getAllTools, handleToolCalls } from "./handleToolCalls.js";
2824
import { handleAutoCompaction } from "./streamChatResponse.autoCompaction.js";
@@ -152,91 +148,56 @@ export async function processStreamingResponse(
152148
tools,
153149
} = options;
154150

155-
// Validate context length before making the request
156-
const validation = validateContextLength(chatHistory, model);
157-
158-
// Get fresh system message and inject it
151+
// Get fresh system message
159152
const systemMessage = await services.systemMessage.getSystemMessage(
160153
services.toolPermissions.getState().currentMode,
161154
);
162155

163-
let openaiChatHistory: ChatCompletionMessageParam[];
164-
let chatHistoryToUse = chatHistory;
165-
166-
// If validation fails, try to prune using compileChatMessages
167-
if (!validation.isValid) {
168-
logger.warn(
169-
"Context length validation failed, attempting to prune messages",
170-
{
171-
error: validation.error,
172-
historyLength: chatHistory.length,
173-
},
174-
);
175-
176-
try {
177-
// Convert to ChatMessage format for pruning
178-
const openaiMessages = convertFromUnifiedHistoryWithSystemMessage(
179-
chatHistory,
180-
systemMessage,
181-
) as ChatCompletionMessageParam[];
182-
183-
// Use compileChatMessages to prune
184-
const contextLength = model.contextLength || 4096;
185-
const maxTokens = model.defaultCompletionOptions?.maxTokens || 1024;
186-
187-
const result = compileChatMessages({
188-
modelName: model.model,
189-
msgs: openaiMessages.map((msg) => ({
190-
role: msg.role,
191-
content: msg.content || "",
192-
...("tool_calls" in msg && msg.tool_calls
193-
? { toolCalls: msg.tool_calls }
194-
: {}),
195-
...("tool_call_id" in msg && msg.tool_call_id
196-
? { toolCallId: msg.tool_call_id }
197-
: {}),
198-
})),
199-
knownContextLength: contextLength,
200-
maxTokens,
201-
supportsImages: false,
202-
tools,
203-
});
156+
// Convert unified history to ChatMessage format for compileChatMessages
157+
const openaiMessages = convertFromUnifiedHistoryWithSystemMessage(
158+
chatHistory,
159+
systemMessage,
160+
) as ChatCompletionMessageParam[];
204161

205-
if (result.didPrune) {
206-
logger.info("Successfully pruned chat history to fit context length", {
207-
originalLength: chatHistory.length,
208-
prunedLength: result.compiledChatMessages.length,
209-
contextPercentage: `${(result.contextPercentage * 100).toFixed(1)}%`,
210-
});
162+
// Convert to ChatMessage format and use compileChatMessages to handle pruning
163+
const contextLength = model.contextLength || 4096;
164+
const maxTokens = model.defaultCompletionOptions?.maxTokens || 1024;
165+
166+
const chatMessages = openaiMessages.map((msg) => ({
167+
role: msg.role,
168+
content: msg.content || "",
169+
...("tool_calls" in msg && msg.tool_calls
170+
? { toolCalls: msg.tool_calls }
171+
: {}),
172+
...("tool_call_id" in msg && msg.tool_call_id
173+
? { toolCallId: msg.tool_call_id }
174+
: {}),
175+
}));
176+
177+
const result = compileChatMessages({
178+
modelName: model.model,
179+
msgs: chatMessages,
180+
knownContextLength: contextLength,
181+
maxTokens,
182+
supportsImages: false,
183+
tools,
184+
});
211185

212-
// Convert pruned messages back to ChatHistoryItem format
213-
const prunedOpenaiMessages = result.compiledChatMessages.map(
214-
(msg: any) => ({
215-
role: msg.role,
216-
content: msg.content,
217-
...(msg.toolCalls ? { tool_calls: msg.toolCalls } : {}),
218-
...(msg.toolCallId ? { tool_call_id: msg.toolCallId } : {}),
219-
}),
220-
) as ChatCompletionMessageParam[];
221-
222-
// Remove system message from the pruned messages to avoid duplication
223-
const messagesWithoutSystem = prunedOpenaiMessages.filter(
224-
(msg) => msg.role !== "system",
225-
);
226-
chatHistoryToUse = convertToUnifiedHistory(messagesWithoutSystem);
227-
}
228-
} catch (pruneError: any) {
229-
logger.error("Failed to prune chat history", { error: pruneError });
230-
throw new Error(
231-
`Context length validation failed and pruning failed: ${pruneError.message}`,
232-
);
233-
}
186+
if (result.didPrune) {
187+
logger.info("Chat history pruned to fit context length", {
188+
originalLength: chatHistory.length,
189+
prunedLength: result.compiledChatMessages.length,
190+
contextPercentage: `${(result.contextPercentage * 100).toFixed(1)}%`,
191+
});
234192
}
235193

236-
openaiChatHistory = convertFromUnifiedHistoryWithSystemMessage(
237-
chatHistoryToUse,
238-
systemMessage,
239-
) as ChatCompletionMessageParam[];
194+
// Convert back to OpenAI format
195+
const openaiChatHistory = result.compiledChatMessages.map((msg: any) => ({
196+
role: msg.role,
197+
content: msg.content,
198+
...(msg.toolCalls ? { tool_calls: msg.toolCalls } : {}),
199+
...(msg.toolCallId ? { tool_call_id: msg.toolCallId } : {}),
200+
})) as ChatCompletionMessageParam[];
240201

241202
const requestStartTime = Date.now();
242203

extensions/cli/src/tools/runTerminalCommand.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,25 @@ const MAX_OUTPUT_LINES = 5000;
1818
const MAX_OUTPUT_CHARS = 200000;
1919

2020
// Helper function to truncate command output by both lines and characters
21+
// Keeps the LAST X lines/chars to capture test/install outcomes
2122
function truncateOutput(output: string): string {
2223
const lines = output.split("\n");
2324
let truncated = output;
2425
let truncationMsg = "";
2526

26-
// First check character limit
27+
// First check character limit - keep last X characters
2728
if (output.length > MAX_OUTPUT_CHARS) {
28-
truncated = output.substring(0, MAX_OUTPUT_CHARS);
29-
truncationMsg = `\n\n[Output truncated to first ${MAX_OUTPUT_CHARS} characters of ${output.length} total]`;
29+
const startIndex = output.length - MAX_OUTPUT_CHARS;
30+
truncated = output.substring(startIndex);
31+
truncationMsg = `[Output truncated: showing last ${MAX_OUTPUT_CHARS} characters of ${output.length} total]\n\n`;
3032
}
31-
// Then check line limit (only if not already truncated by characters)
33+
// Then check line limit (only if not already truncated by characters) - keep last X lines
3234
else if (lines.length > MAX_OUTPUT_LINES) {
33-
truncated = lines.slice(0, MAX_OUTPUT_LINES).join("\n");
34-
truncationMsg = `\n\n[Output truncated to first ${MAX_OUTPUT_LINES} lines of ${lines.length} total]`;
35+
truncated = lines.slice(-MAX_OUTPUT_LINES).join("\n");
36+
truncationMsg = `[Output truncated: showing last ${MAX_OUTPUT_LINES} lines of ${lines.length} total]\n\n`;
3537
}
3638

37-
return truncationMsg ? truncated + truncationMsg : truncated;
39+
return truncationMsg ? truncationMsg + truncated : truncated;
3840
}
3941

4042
// Helper function to use login shell on Unix/macOS and PowerShell on Windows

0 commit comments

Comments
 (0)