diff --git a/src/core/environment/context/metadata.ts b/src/core/environment/context/metadata.ts index 86dde9772c..3d412ba48e 100644 --- a/src/core/environment/context/metadata.ts +++ b/src/core/environment/context/metadata.ts @@ -30,7 +30,7 @@ export async function getMetadataContext(cline: Task) { .padStart(2, "0")}:${offsetMinutes.toString().padStart(2, "0")}` const isoDateWithOffset = now.toISOString().replace(/Z$/, offsetString) const time = { - "@v": isoDateWithOffset, + "@I": isoDateWithOffset, } const { totalCost } = getApiMetrics(cline.clineMessages) diff --git a/src/core/environment/getEnvironmentDetails.ts b/src/core/environment/getEnvironmentDetails.ts index a78dadef7f..6b12448ab1 100644 --- a/src/core/environment/getEnvironmentDetails.ts +++ b/src/core/environment/getEnvironmentDetails.ts @@ -19,7 +19,7 @@ export async function getEnvironmentDetails(task: Task, includeFileDetails: bool getTodoContext(task), ]) - const envDetails = { + const currentEnvDetails = { ...vscodeContext, ...terminalContext, ...fileContext, @@ -28,6 +28,10 @@ export async function getEnvironmentDetails(task: Task, includeFileDetails: bool ...todoContext, } + const diffEnvDetails = _envDiff(currentEnvDetails, task.prevEnvDetails) + + task.prevEnvDetails = currentEnvDetails + const builder = new XMLBuilder({ format: true, // Enable pretty printing indentBy: " ", // Use two spaces for indentation @@ -38,5 +42,54 @@ export async function getEnvironmentDetails(task: Task, includeFileDetails: bool textNodeName: "#text", }) - return builder.build({ environment_details: envDetails }) + return builder.build({ environment_details: diffEnvDetails }) +} + +function _envDiff(current: any, previous: any): any { + if (!previous) return current + + return Object.keys(current).reduce((acc, key) => { + const currentValue = current[key] + const previousValue = previous ? previous[key] : undefined + + if (_objIsEqual(currentValue, previousValue)) { + return acc + } + + // Check for nested objects (but not arrays) + if ( + typeof currentValue === "object" && + currentValue !== null && + !Array.isArray(currentValue) && + typeof previousValue === "object" && + previousValue !== null && + !Array.isArray(previousValue) + ) { + const nestedDiff = _envDiff(currentValue, previousValue) + if (Object.keys(nestedDiff).length > 0) { + acc[key] = nestedDiff + } + } else { + // For primitives, arrays, or if previous was not an object + acc[key] = currentValue + } + + return acc + }, {} as any) +} + +function _objIsEqual(a: any, b: any): boolean { + if (a === b) return true + if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false + + const keysA = Object.keys(a) + const keysB = Object.keys(b) + + if (keysA.length !== keysB.length) return false + + for (const key of keysA) { + if (!keysB.includes(key) || !_objIsEqual(a[key], b[key])) return false + } + + return true } diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index 8a1bf1101d..1c81987e92 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -180,6 +180,7 @@ export class Task extends EventEmitter { // LLM Messages & Chat Messages apiConversationHistory: ApiMessage[] = [] clineMessages: ClineMessage[] = [] + prevEnvDetails?: Record // Ask private askResponse?: ClineAskResponse