diff --git a/packages/app/src/components/message.tsx b/packages/app/src/components/message.tsx
index 35df2274e..3aa80a676 100644
--- a/packages/app/src/components/message.tsx
+++ b/packages/app/src/components/message.tsx
@@ -1286,22 +1286,7 @@ export const ToolCall = memo(function ToolCall({
result,
error,
status,
- parsedEditEntries,
- parsedReadEntries,
- parsedCommandDetails,
}: ToolCallProps) {
- const { editEntries, readEntries, commandDetails } = useMemo(
- () =>
- resolveToolCallPreview({
- args,
- result,
- parsedEditEntries,
- parsedReadEntries,
- parsedCommandDetails,
- }),
- [args, result, parsedEditEntries, parsedReadEntries, parsedCommandDetails]
- );
-
const [isExpanded, setIsExpanded] = useState(false);
// Check if result has a type field for structured rendering
@@ -1404,166 +1389,6 @@ export const ToolCall = memo(function ToolCall({
[]
);
- const hasCommandDetails = Boolean(
- commandDetails &&
- (commandDetails.command ||
- commandDetails.cwd ||
- commandDetails.exitCode !== undefined ||
- commandDetails.output)
- );
-
- function renderJsonSection(
- label: string,
- text: string,
- isError = false
- ): ReactNode {
- const displayText = text.length ? text : "(empty)";
-
- return (
-
- {label}
-
-
- {displayText}
-
-
-
- );
- }
-
- const commandSection = useMemo(() => {
- if (!hasCommandDetails || !commandDetails) {
- return null;
- }
- return (
-
- Command
- {commandDetails.command ? (
-
-
- {commandDetails.command}
-
-
- ) : null}
- {commandDetails.cwd ? (
-
- Directory
- {commandDetails.cwd}
-
- ) : null}
- {commandDetails.exitCode !== undefined ? (
-
- Exit Code
-
- {commandDetails.exitCode === null
- ? "Unknown"
- : commandDetails.exitCode}
-
-
- ) : null}
- {commandDetails.output ? (
-
-
- {commandDetails.output}
-
-
- ) : null}
-
- );
- }, [commandDetails, hasCommandDetails]);
-
- const editSections = useMemo(
- () =>
- editEntries.map((entry, index) => (
-
- Diff
- {entry.filePath ? (
-
- {entry.filePath}
-
- ) : null}
-
-
-
-
- )),
- [editEntries]
- );
-
- const readSections = useMemo(
- () =>
- readEntries.map((entry, index) => (
-
- Read Result
- {entry.filePath ? (
-
- {entry.filePath}
-
- ) : null}
-
- {entry.content}
-
-
- )),
- [readEntries]
- );
-
- // Check if we have structured content that makes raw JSON redundant
- const hasStructuredContent = Boolean(
- commandDetails?.output || editEntries.length > 0 || readEntries.length > 0
- );
-
- const jsonSections = useMemo(() => {
- const sections: ReactNode[] = [];
- if (args !== undefined) {
- sections.push(renderJsonSection("Arguments", serializedArgs));
- }
- // Only show raw Result JSON if we don't have structured content showing the same data
- if (result !== undefined && !hasStructuredContent) {
- sections.push(renderJsonSection("Result", serializedResult));
- }
- if (error !== undefined) {
- sections.push(renderJsonSection("Error", serializedError, true));
- }
- return sections;
- }, [args, serializedArgs, result, serializedResult, error, serializedError, hasStructuredContent]);
-
const renderDetails = useCallback(() => {
// If we have a structured result, use type-based rendering
if (structuredResult) {
@@ -1743,15 +1568,63 @@ export const ToolCall = memo(function ToolCall({
return {sections};
}
- // Fall back to heuristic parsing for backwards compatibility
- const showReadSections = !commandDetails?.output && readSections.length > 0;
+ // No structured result - show raw JSON
+ const sections: ReactNode[] = [];
- if (
- !commandSection &&
- editSections.length === 0 &&
- !showReadSections &&
- jsonSections.length === 0
- ) {
+ if (args !== undefined) {
+ sections.push(
+
+ Arguments
+
+ {serializedArgs}
+
+
+ );
+ }
+
+ if (result !== undefined) {
+ sections.push(
+
+ Result
+
+ {serializedResult}
+
+
+ );
+ }
+
+ if (error !== undefined) {
+ sections.push(
+
+ Error
+
+
+ {serializedError}
+
+
+
+ );
+ }
+
+ if (sections.length === 0) {
return (
No additional details available
@@ -1759,14 +1632,7 @@ export const ToolCall = memo(function ToolCall({
);
}
- return (
-
- {commandSection}
- {editSections}
- {showReadSections ? readSections : null}
- {jsonSections}
-
- );
+ return {sections};
}, [
structuredResult,
extractCommandFromStructured,
@@ -1778,11 +1644,6 @@ export const ToolCall = memo(function ToolCall({
args,
result,
error,
- commandSection,
- commandDetails?.output,
- editSections,
- readSections,
- jsonSections,
]);
return (
diff --git a/packages/server/src/server/agent/providers/claude-agent.ts b/packages/server/src/server/agent/providers/claude-agent.ts
index 97fc828f6..54e0dbcaf 100644
--- a/packages/server/src/server/agent/providers/claude-agent.ts
+++ b/packages/server/src/server/agent/providers/claude-agent.ts
@@ -1122,12 +1122,15 @@ class ClaudeAgentSession implements AgentSession {
normalizedTool === "apply_diff"
) {
if (input && typeof input.file_path === "string") {
+ // Support both old_str/new_str and old_string/new_string parameter names
+ const oldContent = typeof input.old_str === "string" ? input.old_str : typeof input.old_string === "string" ? input.old_string : undefined;
+ const newContent = typeof input.new_str === "string" ? input.new_str : typeof input.new_string === "string" ? input.new_string : undefined;
return {
type: "file_edit",
filePath: input.file_path,
diff: typeof input.patch === "string" ? input.patch : typeof input.diff === "string" ? input.diff : undefined,
- oldContent: typeof input.old_str === "string" ? input.old_str : undefined,
- newContent: typeof input.new_str === "string" ? input.new_str : undefined,
+ oldContent,
+ newContent,
};
}
}