ken-you-code
Version:
Connect your codebase to Kimi: Ultra-fast AI code analysis with Kimi-K2 model via MCP
89 lines (88 loc) • 3.4 kB
JavaScript
import { createPatch } from 'diff';
import { writeFile, copyFile } from 'fs/promises';
import path from 'path';
import { randomUUID } from 'crypto';
import { FileOperations } from './fileOperations.js';
export class DiffManager {
static pendingOperations = new Map();
static async createDiff(filePath, newContent, reason) {
try {
// Read current file content
const fileResult = await FileOperations.readFileSecurely(filePath);
const originalContent = fileResult.content;
// Generate diff patch
const patch = createPatch(path.basename(filePath), originalContent, newContent, 'current', 'proposed');
// Create operation
const operation = {
id: randomUUID(),
filePath,
originalContent,
newContent,
patch,
reason,
createdAt: new Date(),
applied: false,
};
// Store pending operation
this.pendingOperations.set(operation.id, operation);
return operation;
}
catch (error) {
throw new Error(`Failed to create diff: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
static getPendingOperation(operationId) {
return this.pendingOperations.get(operationId);
}
static async applyDiff(operationId, approved) {
const operation = this.pendingOperations.get(operationId);
if (!operation) {
return { success: false, message: 'Operation not found' };
}
if (operation.applied) {
return { success: false, message: 'Operation already applied' };
}
if (!approved) {
this.pendingOperations.delete(operationId);
return { success: true, message: 'Operation cancelled by user' };
}
try {
// Create backup
const backupPath = `${operation.filePath}.backup.${Date.now()}`;
await copyFile(operation.filePath, backupPath);
// Apply changes
await writeFile(operation.filePath, operation.newContent, 'utf-8');
// Mark as applied
operation.applied = true;
// Clean up pending operation
this.pendingOperations.delete(operationId);
return {
success: true,
message: `File updated successfully. Backup created at: ${backupPath}`,
};
}
catch (error) {
return {
success: false,
message: `Failed to apply diff: ${error instanceof Error ? error.message : 'Unknown error'}`,
};
}
}
static listPendingOperations() {
return Array.from(this.pendingOperations.values());
}
static cancelOperation(operationId) {
return this.pendingOperations.delete(operationId);
}
static clearExpiredOperations(maxAgeMinutes = 60) {
const cutoff = new Date(Date.now() - maxAgeMinutes * 60 * 1000);
let cleared = 0;
for (const [id, operation] of this.pendingOperations.entries()) {
if (operation.createdAt < cutoff && !operation.applied) {
this.pendingOperations.delete(id);
cleared++;
}
}
return cleared;
}
}