refactor: move git generation to session structured output

- Use active session prompts for commit/PR generation and drop backend git generation routes.
- Improve tool activity UX with Structured Output rendering, description styling tweaks, and detailed-mode expansion fixes.
This commit is contained in:
Bohdan Triapitsyn
2026-02-24 15:37:35 +02:00
parent 9462ac8498
commit 4a8c69e36a
11 changed files with 455 additions and 511 deletions
@@ -29,7 +29,7 @@ import { copyTextToClipboard } from '@/lib/clipboard';
const ToolOutputDialog = React.lazy(() => import('./message/ToolOutputDialog'));
const DETAILED_DEFAULT_TOOLS = new Set(['task', 'edit', 'multiedit', 'write', 'bash']);
const DETAILED_DEFAULT_TOOLS = new Set(['task', 'edit', 'multiedit', 'write', 'apply_patch', 'bash', 'todowrite']);
const isDetailedDefaultTool = (toolName: unknown): boolean =>
typeof toolName === 'string' && DETAILED_DEFAULT_TOOLS.has(toolName.toLowerCase());
@@ -437,8 +437,13 @@ const ChatMessage: React.FC<ChatMessageProps> = ({
}
const toolPart = activity.part as unknown as { id?: string; tool?: unknown };
if (toolPart.id && isDetailedDefaultTool(toolPart.tool)) {
defaultExpandedToolIds.add(toolPart.id);
if (isDetailedDefaultTool(toolPart.tool)) {
if (toolPart.id) {
defaultExpandedToolIds.add(toolPart.id);
}
if (activity.id) {
defaultExpandedToolIds.add(activity.id);
}
}
}
}
@@ -119,7 +119,7 @@ export const ReasoningTimelineBlock: React.FC<ReasoningTimelineBlockProps> = ({
{summary && (
<div className="flex-1 min-w-0 typography-meta text-muted-foreground/70">
<span className="truncate block">{summary}</span>
<span className="truncate block italic">{summary}</span>
</div>
)}
</div>
@@ -1,7 +1,7 @@
import React from 'react';
import { RuntimeAPIContext } from '@/contexts/runtimeAPIContext';
import { RiAiAgentLine, RiArrowDownSLine, RiArrowRightSLine, RiBookLine, RiExternalLinkLine, RiFileEditLine, RiFileList2Line, RiFileSearchLine, RiFileTextLine, RiFolder6Line, RiGitBranchLine, RiGlobalLine, RiListCheck3, RiMenuSearchLine, RiPencilLine, RiSurveyLine, RiTaskLine, RiTerminalBoxLine, RiToolsLine } from '@remixicon/react';
import { RiAiAgentLine, RiArrowDownSLine, RiArrowRightSLine, RiBookLine, RiExternalLinkLine, RiFileEditLine, RiFileList2Line, RiFileSearchLine, RiFileTextLine, RiFolder6Line, RiGitBranchLine, RiGlobalLine, RiListCheck2, RiListCheck3, RiMenuSearchLine, RiPencilLine, RiSurveyLine, RiTaskLine, RiTerminalBoxLine, RiToolsLine } from '@remixicon/react';
import { cn } from '@/lib/utils';
import { SimpleMarkdownRenderer } from '../../MarkdownRenderer';
import { getToolMetadata, getLanguageFromExtension, isImageFile, getImageMimeType } from '@/lib/toolHelpers';
@@ -88,6 +88,9 @@ export const getToolIcon = (toolName: string) => {
if (tool === 'todowrite' || tool === 'todoread') {
return <RiListCheck3 className={iconClass} />;
}
if (tool === 'structuredoutput' || tool === 'structured_output') {
return <RiListCheck2 className={iconClass} />;
}
if (tool === 'skill') {
return <RiBookLine className={iconClass} />;
}
@@ -189,6 +192,11 @@ const getToolDescription = (part: ToolPartType, state: ToolStateUnion, isMobile:
const stateWithData = state as ToolStateWithMetadata;
const metadata = stateWithData.metadata;
const input = stateWithData.input;
const tool = part.tool.toLowerCase();
if (tool === 'structuredoutput' || tool === 'structured_output') {
return 'Result';
}
if (part.tool === 'apply_patch') {
const files = Array.isArray(metadata?.files) ? metadata?.files : [];
@@ -1391,7 +1399,7 @@ const ToolPart: React.FC<ToolPartProps> = ({
<div className="flex items-center gap-1 flex-1 min-w-0 typography-meta" style={{ color: 'var(--tools-description)' }}>
{justificationText && (
<span className={cn("truncate italic", isMobile && "max-w-[120px]")} style={{ color: 'var(--tools-description)', opacity: 0.8 }}>
<span className={cn("truncate", isMobile && "max-w-[120px]")} style={{ color: 'var(--tools-description)', opacity: 0.8 }}>
{justificationText}
</span>
)}