Repository navigation
Description
What happened?
When I open src/core/task/index.ts and ask Cline to do a minor code refactor (it works with simple changes) the extension returns “context-window overflow” and aborts.
The file is roughly four thousand lines, and Cline is configured with a 1 M-token limit, so this should not happen with typical usage.
Actual Behavior
- Extension logs show a context-overflow error.
- No response is produced; the agent stops.
Expected Behavior
Cline should load the file—or at least stream it in workable slices—without exceeding the available context window, just as it does for the rest of the codebase.
Suspected Root Cause
src/core/task/index.ts is a single monolithic file.
Because the entire file is sent to the model every time, Cline cannot stay within its token budget.
Also, replace_in_files seems to be doing some grep line by line on the file and I think that's the reason it hangs. Towards the end of the file, you can see Cline visibly slowing down, taking much longer to scan a single line
Proposed Fixes
Break index.ts into 3–4 focused modules and re-export from index.ts to avoid a breaking change:
| New file | Responsibility |
|---|---|
task-definitions.ts |
Shared types, interfaces, enums, constants, and simple helpers (mapStringToPlatformEnum, formatErrorWithStatusCode, …) |
task-io.ts |
All input/output operations: webview communication (ask/say), gRPC interactions (postInitialStateToGrpcClient), state persistence (history saving, saveClineMessagesAndUpdateHistory), checkpoint management (restoreCheckpoint, saveCheckpoint, CheckpointTracker) |
task-tool-handler.ts |
Parsing and handling assistant messages (presentAssistantMessage), tool-execution logic (executeCommandTool, browser actions, use_mcp_tool/access_mcp_resource), auto-approval helpers (shouldAutoApproveTool*), context loading (loadContext) |
task-lifecycle.ts (optional) |
Core task orchestration: Task constructor, startTask, resumeTaskFromHistory, main agent loop (initiateTaskLoop, recursivelyMakeClineRequests), API-interaction logic (attemptApiRequest), task abortion flow (abortTask) |
Splitting the logic makes the code a lot more readable, editable, not to mention the merge conflicts. But most importantly it would allow working on it with Cline and fixing our context overflow issue. On my fork of Cline i found myself making changes to it myself frequently, so I split it up into 2 big files (not 4 like proposed), this helped a little, but 2 files ended up being almost 2k LOC each....
Together with this refactor we would also be addressing the main issue of context overflow which also occurs inside task index.ts.
Steps to reproduce
- Open
src/core/task/index.ts(≈4 000 lines) in VS Code. - Ask Cline to perform any analysis (e.g. “summarize this file” or “find where
executeTaskis defined”). - Observe the extension output / dev-tools console.
Relevant Logs (trimmed)
// …excerpt showing first overflow message …
ClineError: context_window_overflow (needed: 4 286 KB, available: 1 024 KB)
at presentAssistantMessage (task/index.ts:2 977:13)
// …additional stack frames…
### Relevant API REQUEST output
> ```shell
<<<<<<< SEARCH
// Assign correct oneof payload based on internal type
if (msg.type === "ask" && msg.ask) {
protoMsg.ask_type = msg.ask; // Map internal ask string to proto enum (assuming direct mapping)
// Add specific payload assignments here if needed based on msg.ask value
} else if (msg.type === "say" && msg.say) {
protoMsg.say_type = msg.say; // Map internal say string to proto enum (assuming direct mapping)
// Add specific payload assignments here if needed based on msg.say value
// Example for SAY_API_REQ_INFO:
// if (msg.say === "api_req_started" || msg.say === "api_req_finished" || msg.say === "api_req_retried") {
=======
// Assign correct oneof payload based on internal type
if (msg.type === "ask" && msg.ask) {
// Map internal ask string to proto enum (assuming direct mapping - requires enum keys match string values)
const askTypeEnumKey = msg.ask.toUpperCase() as keyof typeof ClineAskType;
protoMsg.ask_type = ClineAskType[askTypeEnumKey] || ClineAskType.CLINE_ASK_TYPE_UNSPECIFIED;
// Add specific payload assignments here if needed based on msg.ask value
} else if (msg.type === "say" && msg.say) {
// Map internal say string to proto enum (assuming direct mapping - requires enum keys match string values)
const sayTypeEnumKey = msg.say.toUpperCase() as keyof typeof ClineSayType;
protoMsg.say_type = ClineSayType[sayTypeEnumKey] || ClineSayType.CLINE_SAY_TYPE_UNSPECIFIED;
// Add specific payload assignments here if needed based on msg.say value
// Example for SAY_API_REQ_INFO:
// if (msg.say === "api_req_started" || msg.say === "api_req_finished" || msg.say === "api_req_retried") {
>>>>>>> REPLACE
<<<<<<< SEARCH
tokens_in: item.tokensIn,
tokens_out: item.tokensOut,
cache_writes: item.cacheWrites,
cache_reads: item.cacheReads,
total_cost: item.totalCost,
size: item.size,
shadow_git_config_work_tree: item.shadowGitConfigWorkTree,
conversation_history_deleted_range: item.conversationHistoryDeletedRange
? { start_index: item.conversationHistoryDeletedRange.start, end_index: item.conversationHistoryDeletedRange.end } // Map to proto structure
: undefined,
};
return historyItemProto;
});
// Construct the STATE message payload conforming to ExtensionState proto definition
const statePayload: ExtensionState = { // Construct the payload object first
api_configuration: allState.apiConfiguration, // Ensure snake_case matches proto
auto_approval_settings: allState.autoApprovalSettings, // Ensure snake_case matches proto
browser_settings: allState.browserSettings, // Ensure snake_case matches proto
// remote_browser_host: allState.remoteBrowserHost, // Check if this exists in allState and proto
chat_settings: allState.chatSettings, // Ensure snake_case matches proto
checkpoint_tracker_error_message: this.checkpointTrackerErrorMessage, // Ensure snake_case matches proto
cline_messages: protoClineMessages, // Use correctly mapped proto type
current_task_item: protoTaskHistory.find((item) => item.id === this.taskId), // Ensure snake_case matches proto
custom_instructions: allState.customInstructions, // Ensure snake_case matches proto
mcp_marketplace_enabled: allState.mcpMarketplaceEnabled, // Ensure snake_case matches proto
plan_act_separate_models_setting: allState.planActSeparateModelsSetting, // Ensure snake_case matches proto
=======
// Use snake_case names directly as expected by the proto definition
tokens_in: item.tokensIn || 0,
tokens_out: item.tokensOut || 0,
cache_writes: item.cacheWrites, // Keep optional
cache_reads: item.cacheReads, // Keep optional
total_cost: item.totalCost || 0, // Ensure number/double
size: item.size, // Keep optional
shadow_git_config_work_tree: item.shadowGitConfigWorkTree, // Keep optional
conversation_history_deleted_range: item.conversationHistoryDeletedRange // Keep internal object format
? { start_index: item.conversationHistoryDeletedRange.start, end_index: item.conversationHistoryDeletedRange.end }
: undefined,
};
return historyItemProto;
});
// Construct the STATE message payload conforming to ExtensionState proto definition (using snake_case)
const statePayload: ExtensionState = { // Construct the payload object first
api_configuration: allState.apiConfiguration,
auto_approval_settings: allState.autoApprovalSettings,
browser_settings: allState.browserSettings,
// remote_browser_host: allState.remoteBrowserHost, // Check if this exists
chat_settings: allState.chatSettings,
checkpoint_tracker_error_message: this.checkpointTrackerErrorMessage,
cline_messages: protoClineMessages, // Use correctly mapped proto type
current_task_item: protoTaskHistory.find((item) => item.id === this.taskId),
custom_instructions: allState.customInstructions,
mcp_marketplace_enabled: allState.mcpMarketplaceEnabled,
plan_act_separate_models_setting: allState.planActSeparateModelsSetting,
>>>>>>> REPLACE
<<<<<<< SEARCH
// Map internal ask/say strings to correct proto enums
ask_type: lastMessage.ask ? ClineAskType[lastMessage.ask as keyof typeof ClineAskType] : undefined,
say_type: lastMessage.say ? ClineSayType[lastMessage.say as keyof typeof ClineSayType] : undefined,
text: lastMessage.text,
images: lastMessage.images || [], // Ensure array
partial: lastMessage.partial || false, // Ensure boolean
conversationHistoryIndex: lastMessage.conversationHistoryIndex || 0, // Ensure number
conversationHistoryDeletedRange: lastMessage.conversationHistoryDeletedRange, // Assumed object format
lastCheckpointHash: lastMessage.lastCheckpointHash,
isCheckpointCheckedOut: lastMessage.isCheckpointCheckedOut || false, // Ensure boolean
}
// Construct the PARTIAL_MESSAGE ExtensionMessage correctly
const partialExtensionMessage: ExtensionMessage = {
type: ExtensionMessageType.PARTIAL_MESSAGE,
partialMessage:
Diff Edit Mismatch
The model used search patterns that don't match anything in the file. Retrying...Provider/Model
gemini-2.5-pro-exp-03-25
Operating System
macOS Sequoia 15.3.2 (24D81)
Cline Version
3.13.1
Additional context
It would be great to get this fixed. Ive been trying to build something on my fork of cline, but navigating the task index.ts file with an AI agent ie. Cline is really difficult and always exhausts the context
Happy to submit a PR if maintainers agree with this direction.
Feel free to suggest an alternative structure or naming convention.
Thanks for the great project! ❤️
Activity
[-]`src/core/task/index.ts` exhausts Cline’s context window (≈4 000 LOC)[/-][+]Cline exhausts context window on `src/core/task/index.ts` (≈4 000 LOC)[/+]kevinneung commentedon Apr 24, 2025
"Hi @JanNoszczyk , thank you for logging this issue! I'll assign a team member shortly that can review your suggestions, get it prioritized, and collaborate.
I want to mention: we really appreciate the attention to detail in your proposal, it's ripe for the collaboration we want to do at Cline with our community. Keep them coming!"
pashpashpash commentedon Apr 24, 2025
I'm unable to reproduce this issue, refer to the screenshot here:
I @ mention the task/index.ts file and it works great, even with a 200k context window model. Maybe you could provide what specific models/providers you tried this with where it breaks?
As goes for your refactoring suggestions, I totally agree. We're currently working towards refactoring a lot of this code and breaking it up.
JanNoszczyk commentedon Apr 26, 2025
Actually you need to ask it something more elaborate, it tends to work with easy changes using
replace_in_file. Try asking it to do some random minor refactor inside the task index.ts file.I updated the issue description a little, I hope its clearer now.
github-actions commentedon Jun 28, 2025
This issue is stale because it has been open for 60 days with no activity.
github-actions commentedon Sep 22, 2025
This issue was closed because it has been inactive for 14 days since being marked as stale.
gvelesandro commentedon Mar 13, 2026
Hi @JanNoszczyk, I run Agents Need Context and I am researching one specific failure mode: the model can edit code, but loses usable repo or file context once a task stops being trivial. Your
task/index.tsreport is one of the clearer public examples of a large-file context limit turning a minor refactor into a dead end.If you are open to it, I would value one short written postmortem here: https://www.agentsneedcontext.com/agent-failure-postmortem
I am looking for five specifics: what the agent was trying to do, what context was missing, where that context lived, what workaround you used, and what it cost. No pitch, just research.