diff --git a/frontend/src/components/MessageComponents.tsx b/frontend/src/components/MessageComponents.tsx index 71f3954a..d19679df 100644 --- a/frontend/src/components/MessageComponents.tsx +++ b/frontend/src/components/MessageComponents.tsx @@ -233,6 +233,7 @@ export function ToolResultMessageComponent({ maxPreviewLines={maxPreviewLines} showPreview={shouldShowPreview} defaultExpanded={defaultExpanded} + useDiffHighlighter={message.toolName === "Edit"} /> ); } diff --git a/frontend/src/components/SimpleDiffHighlighter.tsx b/frontend/src/components/SimpleDiffHighlighter.tsx new file mode 100644 index 00000000..73d2563e --- /dev/null +++ b/frontend/src/components/SimpleDiffHighlighter.tsx @@ -0,0 +1,74 @@ +import React from 'react'; +import { hasDiffContent, parseDiffLines, type DiffLine } from '../utils/simpleDiffDetector'; +import { useTheme } from '../hooks/useSettings'; + +interface SimpleDiffHighlighterProps { + content: string; + className?: string; +} + +interface DiffLineProps { + line: DiffLine; + isDark: boolean; +} + +function DiffLineComponent({ line, isDark }: DiffLineProps) { + const getLineStyles = () => { + switch (line.type) { + case 'addition': + return isDark + ? `bg-green-900/30 text-green-300` + : `bg-green-50 text-green-700`; + + case 'removal': + return isDark + ? `bg-red-900/30 text-red-300` + : `bg-red-50 text-red-700`; + + default: // context + return isDark + ? `text-emerald-300` + : `text-emerald-700`; + } + }; + + return ( + + {line.content} + + ); +} + +export function SimpleDiffHighlighter({ content, className = '' }: SimpleDiffHighlighterProps) { + const { theme } = useTheme(); + const isDark = theme === 'dark'; + + // Check if content contains diff lines + const isDiff = hasDiffContent(content); + + // If not a diff, render as plain pre + if (!isDiff) { + return ( +
+ {content}
+
+ );
+ }
+
+ // Parse diff lines and render with highlighting
+ const diffLines = parseDiffLines(content);
+
+ return (
+
+ {diffLines.map((line, index) => (
+
+
+ {index < diffLines.length - 1 && '\n'}
+
+ ))}
+
+ );
+}
\ No newline at end of file
diff --git a/frontend/src/components/messages/CollapsibleDetails.tsx b/frontend/src/components/messages/CollapsibleDetails.tsx
index 4215c034..2e58d250 100644
--- a/frontend/src/components/messages/CollapsibleDetails.tsx
+++ b/frontend/src/components/messages/CollapsibleDetails.tsx
@@ -3,6 +3,7 @@ import {
createContentPreview,
createMoreLinesIndicator,
} from "../../utils/contentUtils";
+import { SimpleDiffHighlighter } from "../SimpleDiffHighlighter";
interface CollapsibleDetailsProps {
label: string;
@@ -20,6 +21,7 @@ interface CollapsibleDetailsProps {
showPreview?: boolean;
previewContent?: string;
previewSummary?: string;
+ useDiffHighlighter?: boolean;
}
export function CollapsibleDetails({
@@ -33,6 +35,7 @@ export function CollapsibleDetails({
showPreview = true,
previewContent,
previewSummary,
+ useDiffHighlighter = false,
}: CollapsibleDetailsProps) {
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
const hasDetails = details.trim().length > 0;
@@ -104,11 +107,15 @@ export function CollapsibleDetails({
className="mt-2 pl-6 border-l-2 border-dashed opacity-80"
style={{ borderColor: "inherit" }}
>
-
- {contentPreview.preview}
-
+ {useDiffHighlighter ? (
+
+ {contentPreview.preview}
+
+ )}
- {details}
-
+ {useDiffHighlighter ? (
+
+ {details}
+
+ )}
+
)}
);
diff --git a/frontend/src/utils/simpleDiffDetector.ts b/frontend/src/utils/simpleDiffDetector.ts
new file mode 100644
index 00000000..621e1a49
--- /dev/null
+++ b/frontend/src/utils/simpleDiffDetector.ts
@@ -0,0 +1,48 @@
+/**
+ * Simple diff detection utility for Edit tool results
+ */
+
+export interface DiffLine {
+ type: 'addition' | 'removal' | 'context';
+ content: string;
+ originalContent: string; // Content without +/- markers
+}
+
+/**
+ * Check if content contains diff-style lines (lines starting with + or -)
+ */
+export function hasDiffContent(content: string): boolean {
+ const lines = content.split('\n');
+ return lines.some(line =>
+ line.startsWith('+') || line.startsWith('-')
+ );
+}
+
+/**
+ * Parse content into diff lines with type classification
+ */
+export function parseDiffLines(content: string): DiffLine[] {
+ const lines = content.split('\n');
+
+ return lines.map(line => {
+ if (line.startsWith('+')) {
+ return {
+ type: 'addition' as const,
+ content: line,
+ originalContent: line.substring(1) // Remove + marker
+ };
+ } else if (line.startsWith('-')) {
+ return {
+ type: 'removal' as const,
+ content: line,
+ originalContent: line.substring(1) // Remove - marker
+ };
+ } else {
+ return {
+ type: 'context' as const,
+ content: line,
+ originalContent: line
+ };
+ }
+ });
+}
\ No newline at end of file