Skip to content

Commit 3828c0d

Browse files
* base * button callback * prompt * smol * full truncate * base 2 * changeset * dup new task resp * Update src/core/prompts/commands.ts Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * comments --------- Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
1 parent a2263de commit 3828c0d

File tree

13 files changed

+213
-4
lines changed

13 files changed

+213
-4
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"claude-dev": minor
3+
---
4+
5+
add smol command

src/core/assistant-message/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export const toolUseNames = [
2424
"load_mcp_documentation",
2525
"attempt_completion",
2626
"new_task",
27+
"condense",
2728
] as const
2829

2930
// Converts array of tool call names into a union type ("execute_command" | "read_file" | ...)

src/core/context/context-management/ContextManager.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,14 +193,20 @@ export class ContextManager {
193193
public getNextTruncationRange(
194194
apiMessages: Anthropic.Messages.MessageParam[],
195195
currentDeletedRange: [number, number] | undefined,
196-
keep: "half" | "quarter",
196+
keep: "none" | "lastTwo" | "half" | "quarter",
197197
): [number, number] {
198198
// We always keep the first user-assistant pairing, and truncate an even number of messages from there
199199
const rangeStartIndex = 2 // index 0 and 1 are kept
200200
const startOfRest = currentDeletedRange ? currentDeletedRange[1] + 1 : 2 // inclusive starting index
201201

202202
let messagesToRemove: number
203-
if (keep === "half") {
203+
if (keep === "none") {
204+
// Removes all messages beyond the first core user/assistant message pair
205+
messagesToRemove = Math.max(apiMessages.length - startOfRest, 0)
206+
} else if (keep === "lastTwo") {
207+
// Keep the last user-assistant pair in addition to the first core user/assistant message pair
208+
messagesToRemove = Math.max(apiMessages.length - startOfRest - 2, 0)
209+
} else if (keep === "half") {
204210
// Remove half of remaining user-assistant pairs
205211
// We first calculate half of the messages then divide by 2 to get the number of pairs.
206212
// After flooring, we multiply by 2 to get the number of messages.
@@ -382,6 +388,17 @@ export class ContextManager {
382388
return [contextHistoryUpdated, uniqueFileReadIndices]
383389
}
384390

391+
/**
392+
* Public function for triggering potentially setting the truncation message
393+
* If the truncation message already exists, does nothing, otherwise adds the message
394+
*/
395+
async triggerApplyStandardContextTruncationNoticeChange(timestamp: number, taskDirectory: string) {
396+
const updated = this.applyStandardContextTruncationNoticeChange(timestamp)
397+
if (updated) {
398+
await this.saveContextHistory(taskDirectory)
399+
}
400+
}
401+
385402
/**
386403
* if there is any truncation and there is no other alteration already set, alter the assistant message to indicate this occurred
387404
*/

src/core/controller/index.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,20 @@ export class Controller {
274274
})
275275
break
276276
}
277+
case "newTask":
278+
// Code that should run in response to the hello message command
279+
//vscode.window.showInformationMessage(message.text!)
280+
281+
// Send a message to our webview.
282+
// You can send any JSON serializable data.
283+
// Could also do this in extension .ts
284+
//this.postMessageToWebview({ type: "text", text: `Extension: ${Date.now()}` })
285+
// initializing new instance of Cline will make sure that any agentically running promises in old instance don't affect our new task. this essentially creates a fresh slate for the new task
286+
await this.initTask(message.text, message.images)
287+
break
288+
case "condense":
289+
this.task?.handleWebviewAskResponse("yesButtonClicked")
290+
break
277291
case "apiConfiguration":
278292
if (message.apiConfiguration) {
279293
await updateApiConfiguration(this.context, message.apiConfiguration)

src/core/prompts/commands.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,65 @@ Usage:
2525
Below is the the user's input when they indicated that they wanted to create a new task.
2626
</explicit_instructions>\n
2727
`
28+
29+
export const condenseToolResponse = () =>
30+
`<explicit_instructions type="condense">
31+
The user has explicitly asked you to create a detailed summary of the conversation so far, which will be used to compact the current context window while retaining key information. The user may have provided instructions or additional information for you to consider when summarizing the conversation.
32+
Irrespective of whether additional information or instructions are given, you are only allowed to respond to this message by calling the condense tool.
33+
34+
The condense tool is defined below:
35+
36+
Description:
37+
Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions. This summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the conversation and supporting any continuing tasks.
38+
The user will be presented with a preview of your generated summary and can choose to use it to compact their context window or keep chatting in the current conversation.
39+
Users may refer to this tool as 'smol' or 'compact' as well. You should consider these to be equivalent to 'condense' when used in a similar context.
40+
41+
Parameters:
42+
- Context: (required) The context to continue the conversation with. If applicable based on the current task, this should include:
43+
1. Previous Conversation: High level details about what was discussed throughout the entire conversation with the user. This should be written to allow someone to be able to follow the general overarching conversation flow.
44+
2. Current Work: Describe in detail what was being worked on prior to this request to compact the context window. Pay special attention to the more recent messages / conversation.
45+
3. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for continuing with this work.
46+
4. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
47+
5. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
48+
6. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks.
49+
50+
Usage:
51+
<condense>
52+
<context>Your detailed summary</context>
53+
</condense>
54+
55+
Example:
56+
<condense>
57+
<context>
58+
1. Previous Conversation:
59+
[Detailed description]
60+
61+
2. Current Work:
62+
[Detailed description]
63+
64+
3. Key Technical Concepts:
65+
- [Concept 1]
66+
- [Concept 2]
67+
- [...]
68+
69+
4. Relevant Files and Code:
70+
- [File Name 1]
71+
- [Summary of why this file is important]
72+
- [Summary of the changes made to this file, if any]
73+
- [Important Code Snippet]
74+
- [File Name 2]
75+
- [Important Code Snippet]
76+
- [...]
77+
78+
5. Problem Solving:
79+
[Detailed description]
80+
81+
6. Pending Tasks and Next Steps:
82+
- [Task 1 details & next steps]
83+
- [Task 2 details & next steps]
84+
- [...]
85+
</context>
86+
</condense>
87+
88+
</explicit_instructions>\n
89+
`

src/core/prompts/responses.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ export const formatResponse = {
1010
contextTruncationNotice: () =>
1111
`[NOTE] Some previous conversation history with the user has been removed to maintain optimal context window length. The initial user task and the most recent exchanges have been retained for continuity, while intermediate conversation history has been removed. Please keep this in mind as you continue assisting the user.`,
1212

13+
condense: () =>
14+
`The user has accepted the condensed conversation summary you generated. This summary covers important details of the historical conversation with the user which has been truncated.\n<explicit_instructions type="condense_response">It's crucial that you respond by ONLY asking the user what you should work on next. You should NOT take any initiative or make any assumptions about continuing with work. For example you should NOT suggest file changes or attempt to read any files.\nWhen asking the user what you should work on next, you can reference information in the summary which was just generated. However, you should NOT reference information outside of what's contained in the summary for this response. Keep this response CONCISE.</explicit_instructions>`,
15+
1316
toolDenied: () => `The user denied this operation.`,
1417

1518
toolError: (error?: string) => `The tool execution failed with the following error:\n<error>\n${error}\n</error>`,

src/core/slash-commands/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
import { newTaskToolResponse } from "../prompts/commands"
1+
import { newTaskToolResponse, condenseToolResponse } from "../prompts/commands"
22

33
/**
44
* Processes text for slash commands and transforms them with appropriate instructions
55
* This is called after parseMentions() to process any slash commands in the user's message
66
*/
77
export function parseSlashCommands(text: string): string {
8-
const SUPPORTED_COMMANDS = ["newtask"]
8+
const SUPPORTED_COMMANDS = ["newtask", "smol"]
99

1010
const commandReplacements: Record<string, string> = {
1111
newtask: newTaskToolResponse(),
12+
smol: condenseToolResponse(),
1213
}
1314

1415
// this currently allows matching prepended whitespace prior to /slash-command

src/core/task/index.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,6 +1676,8 @@ export class Task {
16761676
return `[${block.name}]`
16771677
case "new_task":
16781678
return `[${block.name} for creating a new task]`
1679+
case "condense":
1680+
return `[${block.name}]`
16791681
}
16801682
}
16811683

@@ -3013,6 +3015,65 @@ export class Task {
30133015
break
30143016
}
30153017
}
3018+
case "condense": {
3019+
const context: string | undefined = block.params.context
3020+
try {
3021+
if (block.partial) {
3022+
await this.ask("condense", removeClosingTag("context", context), block.partial).catch(() => {})
3023+
break
3024+
} else {
3025+
if (!context) {
3026+
this.consecutiveMistakeCount++
3027+
pushToolResult(await this.sayAndCreateMissingParamError("condense", "context"))
3028+
break
3029+
}
3030+
this.consecutiveMistakeCount = 0
3031+
3032+
if (this.autoApprovalSettings.enabled && this.autoApprovalSettings.enableNotifications) {
3033+
showSystemNotification({
3034+
subtitle: "Cline wants to condense the conversation...",
3035+
message: `Cline is suggesting to condense your conversation with: ${context}`,
3036+
})
3037+
}
3038+
3039+
const { text, images } = await this.ask("condense", context, false)
3040+
3041+
// If the user provided a response, treat it as feedback
3042+
if (text || images?.length) {
3043+
await this.say("user_feedback", text ?? "", images)
3044+
pushToolResult(
3045+
formatResponse.toolResult(
3046+
`The user provided feedback on the condensed conversation summary:\n<feedback>\n${text}\n</feedback>`,
3047+
images,
3048+
),
3049+
)
3050+
} else {
3051+
// If no response, the user accepted the condensed version
3052+
pushToolResult(formatResponse.toolResult(formatResponse.condense()))
3053+
3054+
const lastMessage = this.apiConversationHistory[this.apiConversationHistory.length - 1]
3055+
const summaryAlreadyAppended = lastMessage && lastMessage.role === "assistant"
3056+
const keepStrategy = summaryAlreadyAppended ? "lastTwo" : "none"
3057+
3058+
// clear the context history at this point in time
3059+
this.conversationHistoryDeletedRange = this.contextManager.getNextTruncationRange(
3060+
this.apiConversationHistory,
3061+
this.conversationHistoryDeletedRange,
3062+
keepStrategy,
3063+
)
3064+
await this.saveClineMessagesAndUpdateHistory()
3065+
await this.contextManager.triggerApplyStandardContextTruncationNoticeChange(
3066+
Date.now(),
3067+
await ensureTaskDirectoryExists(this.getContext(), this.taskId),
3068+
)
3069+
}
3070+
break
3071+
}
3072+
} catch (error) {
3073+
await handleError("condensing context window", error)
3074+
break
3075+
}
3076+
}
30163077
case "plan_mode_respond": {
30173078
const response: string | undefined = block.params.response
30183079
const optionsRaw: string | undefined = block.params.options

src/shared/ExtensionMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ export type ClineAsk =
183183
| "browser_action_launch"
184184
| "use_mcp_server"
185185
| "new_task"
186+
| "condense"
186187

187188
export type ClineSay =
188189
| "task"

src/shared/WebviewMessage.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ export interface WebviewMessage {
1212
| "addRemoteServer"
1313
| "apiConfiguration"
1414
| "webviewDidLaunch"
15+
| "newTask"
16+
| "condense"
1517
| "askResponse"
1618
| "didShowAnnouncement"
1719
| "selectImages"

0 commit comments

Comments
 (0)