Compare commits

...
13 changed files with 51 additions and 8 deletions
+9
View File
@@ -75,6 +75,12 @@ message TaskCompleteData {
map<string, string> task_metadata = 1;
}
// Message for deleted range tuple (start, end indices)
message DeletedRange {
int32 start_index = 1;
int32 end_index = 2;
}
// Data for PreCompact hook
message PreCompactData {
// Task identification
@@ -118,4 +124,7 @@ message PreCompactData {
// Use this to analyze total context size, overhead, and exactly what the model sees
// This file will be automatically cleaned up after the hook completes
string context_raw_path = 13;
// Multiple non-contiguous deleted ranges (for advanced context compaction)
repeated DeletedRange deleted_ranges = 14;
}
+2
View File
@@ -218,6 +218,8 @@ message ClineMessage {
ClineAskNewTask ask_new_task = 21;
ClineApiReqInfo api_req_info = 22;
ClineModelInfo model_info = 23;
repeated ConversationHistoryDeletedRange conversation_history_deleted_ranges = 24;
}
// UiService provides methods for managing UI interactions
@@ -189,6 +189,7 @@ async function reconstructTaskHistoryItem(taskId: string): Promise<HistoryItem |
size: taskInfo.size,
isFavorited: taskInfo.isFavorited,
conversationHistoryDeletedRange: taskInfo.conversationHistoryDeletedRange,
conversationHistoryDeletedRanges: taskInfo.conversationHistoryDeletedRanges,
}
return historyItem
@@ -209,6 +210,7 @@ interface TaskInfo {
size?: number
isFavorited?: boolean
conversationHistoryDeletedRange?: [number, number]
conversationHistoryDeletedRanges?: Array<[number, number]>
}
function extractTaskInformation(clineMessages: ClineMessage[], metadata: any): TaskInfo {
+7
View File
@@ -124,6 +124,8 @@ export interface PreCompactHookParams {
apiConversationHistory: ClineStorageMessage[]
/** Current deleted range (if any) */
conversationHistoryDeletedRange?: [number, number]
/** Multiple non-contiguous deleted ranges (if any) */
conversationHistoryDeletedRanges?: Array<[number, number]>
/** Cline messages for extracting token usage */
clineMessages: ClineMessage[]
@@ -231,6 +233,11 @@ export async function executePreCompactHookWithCleanup(params: PreCompactHookPar
deletedRangeEnd,
contextJsonPath: contextJsonPath,
contextRawPath: contextRawPath,
deletedRanges:
params.conversationHistoryDeletedRanges?.map((range) => ({
startIndex: range[0],
endIndex: range[1],
})) ?? [],
},
},
isCancellable: true,
+1
View File
@@ -34,6 +34,7 @@ export class TaskState {
// Context and history
conversationHistoryDeletedRange?: [number, number]
conversationHistoryDeletedRanges?: Array<[number, number]>
// Tool execution flags
didRejectTool = false
+2
View File
@@ -322,6 +322,7 @@ export class Task {
this.ulid = historyItem.ulid ?? ulid()
this.taskIsFavorited = historyItem.isFavorited
this.taskState.conversationHistoryDeletedRange = historyItem.conversationHistoryDeletedRange
this.taskState.conversationHistoryDeletedRanges = historyItem.conversationHistoryDeletedRanges
if (historyItem.checkpointManagerErrorMessage) {
this.taskState.checkpointManagerErrorMessage = historyItem.checkpointManagerErrorMessage
}
@@ -382,6 +383,7 @@ export class Task {
cancelTask: this.cancelTask,
postStateToWebview: this.postStateToWebview,
initialConversationHistoryDeletedRange: this.taskState.conversationHistoryDeletedRange,
initialConversationHistoryDeletedRanges: this.taskState.conversationHistoryDeletedRanges,
initialCheckpointManagerErrorMessage: this.taskState.checkpointManagerErrorMessage,
stateManager: this.stateManager,
})
+2
View File
@@ -118,6 +118,7 @@ export class MessageStateHandler {
shadowGitConfigWorkTree: await this.checkpointTracker?.getShadowGitConfigWorkTree(),
cwdOnTaskInitialization: cwd,
conversationHistoryDeletedRange: this.taskState.conversationHistoryDeletedRange,
conversationHistoryDeletedRanges: this.taskState.conversationHistoryDeletedRanges,
isFavorited: this.taskIsFavorited,
checkpointManagerErrorMessage: this.taskState.checkpointManagerErrorMessage,
modelId: lastModelInfo?.modelInfo?.modelId,
@@ -165,6 +166,7 @@ export class MessageStateHandler {
// it's important that apiConversationHistory is initialized before we add cline messages
message.conversationHistoryIndex = this.apiConversationHistory.length - 1 // NOTE: this is the index of the last added message which is the user message, and once the clinemessages have been presented we update the apiconversationhistory with the completed assistant message. This means when resetting to a message, we need to +1 this index to get the correct assistant message that this tool use corresponds to
message.conversationHistoryDeletedRange = this.taskState.conversationHistoryDeletedRange
message.conversationHistoryDeletedRanges = this.taskState.conversationHistoryDeletedRanges
this.clineMessages.push(message)
await this.saveClineMessagesAndUpdateHistoryInternal()
})
@@ -54,6 +54,7 @@ export class SummarizeTaskHandler implements IToolHandler, IPartialBlockHandler
ulid: config.ulid,
apiConversationHistory: apiHistory,
conversationHistoryDeletedRange: config.taskState.conversationHistoryDeletedRange,
conversationHistoryDeletedRanges: config.taskState.conversationHistoryDeletedRanges,
contextManager: config.services.contextManager,
clineMessages: config.messageState.getClineMessages(),
messageStateHandler: config.messageState,
+3
View File
@@ -46,6 +46,7 @@ type BuildArgs = {
// initial state for single-root
initialConversationHistoryDeletedRange?: [number, number]
initialConversationHistoryDeletedRanges?: Array<[number, number]>
initialCheckpointManagerErrorMessage?: string
stateManager: StateManager
@@ -69,6 +70,7 @@ export function buildCheckpointManager(args: BuildArgs): ICheckpointManager {
cancelTask,
postStateToWebview,
initialConversationHistoryDeletedRange,
initialConversationHistoryDeletedRanges,
initialCheckpointManagerErrorMessage,
stateManager,
} = args
@@ -99,6 +101,7 @@ export function buildCheckpointManager(args: BuildArgs): ICheckpointManager {
},
{
conversationHistoryDeletedRange: initialConversationHistoryDeletedRange,
conversationHistoryDeletedRanges: initialConversationHistoryDeletedRanges,
checkpointManagerErrorMessage: initialCheckpointManagerErrorMessage,
},
)
+7 -8
View File
@@ -50,6 +50,7 @@ interface CheckpointManagerCallbacks {
}
interface CheckpointManagerInternalState {
conversationHistoryDeletedRange?: [number, number]
conversationHistoryDeletedRanges?: Array<[number, number]>
checkpointTracker?: CheckpointTracker
checkpointManagerErrorMessage?: string
checkpointTrackerInitPromise?: Promise<CheckpointTracker | undefined>
@@ -57,6 +58,7 @@ interface CheckpointManagerInternalState {
interface CheckpointRestoreStateUpdate {
conversationHistoryDeletedRange?: [number, number]
conversationHistoryDeletedRanges?: Array<[number, number]>
checkpointManagerErrorMessage?: string
}
@@ -363,6 +365,9 @@ export class TaskCheckpointManager implements ICheckpointManager {
if (this.state.conversationHistoryDeletedRange !== undefined) {
checkpointManagerStateUpdate.conversationHistoryDeletedRange = this.state.conversationHistoryDeletedRange
}
if (this.state.conversationHistoryDeletedRanges !== undefined) {
checkpointManagerStateUpdate.conversationHistoryDeletedRanges = this.state.conversationHistoryDeletedRanges
}
} else {
sendRelinquishControlEvent()
@@ -663,6 +668,8 @@ export class TaskCheckpointManager implements ICheckpointManager {
// Update conversation history deleted range in our state
this.state.conversationHistoryDeletedRange = message.conversationHistoryDeletedRange
this.taskState.conversationHistoryDeletedRange = message.conversationHistoryDeletedRange
this.state.conversationHistoryDeletedRanges = message.conversationHistoryDeletedRanges
this.taskState.conversationHistoryDeletedRanges = message.conversationHistoryDeletedRanges
const apiConversationHistory = this.services.messageStateHandler.getApiConversationHistory()
const newConversationHistory = apiConversationHistory.slice(0, (message.conversationHistoryIndex || 0) + 2) // +1 since this index corresponds to the last user message, and another +1 since slice end index is exclusive
@@ -855,14 +862,6 @@ export class TaskCheckpointManager implements ICheckpointManager {
// TODO - Future telemetry event capture here
}
/**
* Updates the conversation history deleted range
*/
updateConversationHistoryDeletedRange(range: [number, number] | undefined): void {
this.state.conversationHistoryDeletedRange = range
// TODO - Future telemetry event capture here
}
// ============================================================================
// Internal utilities - Private helpers for checkpoint operations
// ============================================================================
+1
View File
@@ -125,6 +125,7 @@ export interface ClineMessage {
isOperationOutsideWorkspace?: boolean
conversationHistoryIndex?: number
conversationHistoryDeletedRange?: [number, number] // for when conversation history is truncated for API requests
conversationHistoryDeletedRanges?: Array<[number, number]> // for multiple non-contiguous deleted ranges
modelInfo?: ClineMessageModelInfo
}
+1
View File
@@ -13,6 +13,7 @@ export type HistoryItem = {
shadowGitConfigWorkTree?: string
cwdOnTaskInitialization?: string
conversationHistoryDeletedRange?: [number, number]
conversationHistoryDeletedRanges?: Array<[number, number]>
isFavorited?: boolean
checkpointManagerErrorMessage?: string
@@ -195,6 +195,11 @@ export function convertClineMessageToProto(message: AppClineMessage): ProtoCline
endIndex: message.conversationHistoryDeletedRange[1],
}
: undefined,
conversationHistoryDeletedRanges:
message.conversationHistoryDeletedRanges?.map((range) => ({
startIndex: range[0],
endIndex: range[1],
})) ?? [],
// Additional optional fields for specific ask/say types
sayTool: undefined,
sayBrowserAction: undefined,
@@ -272,5 +277,13 @@ export function convertProtoToClineMessage(protoMessage: ProtoClineMessage): App
]
}
// Convert conversationHistoryDeletedRanges from array of objects to array of tuples
if (protoMessage.conversationHistoryDeletedRanges.length > 0) {
message.conversationHistoryDeletedRanges = protoMessage.conversationHistoryDeletedRanges.map((range) => [
range.startIndex,
range.endIndex,
])
}
return message
}