Files
gemini-cli/packages/core/src/tools/diffOptions.ts

115 lines
2.9 KiB
TypeScript
Raw Normal View History

/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import * as Diff from 'diff';
import type { DiffStat } from './tools.js';
const DEFAULT_STRUCTURED_PATCH_OPTS: Diff.StructuredPatchOptionsNonabortable = {
context: 3,
ignoreWhitespace: false,
};
export const DEFAULT_DIFF_OPTIONS: Diff.CreatePatchOptionsNonabortable = {
context: 3,
ignoreWhitespace: false,
};
export function getDiffStat(
fileName: string,
oldStr: string,
aiStr: string,
userStr: string,
): DiffStat {
const getStats = (patch: Diff.StructuredPatch) => {
let addedLines = 0;
let removedLines = 0;
let addedChars = 0;
let removedChars = 0;
patch.hunks.forEach((hunk: Diff.StructuredPatchHunk) => {
hunk.lines.forEach((line: string) => {
if (line.startsWith('+')) {
addedLines++;
addedChars += line.length - 1;
} else if (line.startsWith('-')) {
removedLines++;
removedChars += line.length - 1;
}
});
});
return { addedLines, removedLines, addedChars, removedChars };
};
const modelPatch = Diff.structuredPatch(
fileName,
fileName,
oldStr,
aiStr,
'Current',
'Proposed',
DEFAULT_STRUCTURED_PATCH_OPTS,
);
const modelStats = getStats(modelPatch);
const userPatch = Diff.structuredPatch(
fileName,
fileName,
aiStr,
userStr,
'Proposed',
'User',
DEFAULT_STRUCTURED_PATCH_OPTS,
);
const userStats = getStats(userPatch);
return {
model_added_lines: modelStats.addedLines,
model_removed_lines: modelStats.removedLines,
model_added_chars: modelStats.addedChars,
model_removed_chars: modelStats.removedChars,
user_added_lines: userStats.addedLines,
user_removed_lines: userStats.removedLines,
user_added_chars: userStats.addedChars,
user_removed_chars: userStats.removedChars,
};
}
refactor(cli,core): foundational layout, identity management, and type safety This commit establishes the structural foundation and required infrastructure to support the upcoming compact tool output changes. It includes identity management improvements, layout fixes, and type-safety enhancements that stand independently. 1. Identity & History Management: - useHistoryManager: Ensure strictly increasing IDs for history items, even with identical timestamps. - acpClient: Introduced callIdCounter to prevent callId collisions during rapid execution. - MainContent: Implemented negative ID logic for pending items to ensure stable React keys and prevent collisions. - historyUtils: New file containing extracted history logic (isToolExecuting, getAllToolCalls) hoisted from AppContainer. 2. UI Infrastructure & Layout: - test-utils/render: Modernized renderWithProviders and removed legacy props. - AskUserDialog: Fixed layout, scroll visibility, and alignment issues. - toolLayoutUtils: Increased TOOL_RESULT_STANDARD_RESERVED_LINE_COUNT for better spacing. - ShellToolMessage/ToolGroupMessage: Updated line-count expectations and snapshots to align with layout changes. 3. IDE & Diffing Improvements: - ToolActionsContext: Refactored IdeClient initialization to fix a race condition and potential memory leak. - edit/diffOptions: Improved accuracy of diff stat derivation, ensuring "full content" stats are available for the model. - coreToolScheduler: Automatically derive diff stats from patches if missing. - state-manager: Ensure diffStat preservation for rejected tool calls. 4. Type Safety & Constants: - types/tools: Added foundational types like DiffStat, FileDiff, and StructuredToolResult. - Type Guards: Added guards for isFileDiff, isTodoList, isAnsiOutput, and hasSummary. - CodeColorizer: Added function overloads to gracefully handle null language detection. - tool-names: Introduced DISPLAY_NAME constants for consistent tool labeling. This commit passes all workspace tests and builds successfully. Feature-specific logic for compact output is excluded.
2026-03-20 11:30:52 -07:00
/**
* Extracts line and character stats from a unified diff patch string.
* This is useful for reconstructing stats for rejected or errored operations
* where the full strings may no longer be easily accessible.
*/
export function getDiffStatFromPatch(patch: string): DiffStat {
let addedLines = 0;
let removedLines = 0;
let addedChars = 0;
let removedChars = 0;
const lines = patch.split('\n');
for (const line of lines) {
// Only count lines that are additions or removals,
// excluding the diff headers (--- and +++) and metadata (\)
if (line.startsWith('+') && !line.startsWith('+++')) {
addedLines++;
addedChars += line.length - 1;
} else if (line.startsWith('-') && !line.startsWith('---')) {
removedLines++;
removedChars += line.length - 1;
}
}
return {
model_added_lines: addedLines,
model_removed_lines: removedLines,
model_added_chars: addedChars,
model_removed_chars: removedChars,
user_added_lines: 0,
user_removed_lines: 0,
user_added_chars: 0,
user_removed_chars: 0,
};
}