Skip to content

Commit 75f31d8

Browse files
committed
add display
1 parent 63a2908 commit 75f31d8

File tree

7 files changed

+761
-763
lines changed

7 files changed

+761
-763
lines changed

apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-messages/message-content/index.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ export const MessageContent = observer(
2424
[parts]
2525
);
2626

27-
if (!parts.length) {
28-
return null;
29-
}
30-
3127
const renderedParts = parts.map((part, idx) => {
3228
if (part.type === 'text') {
3329
return (

apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-messages/message-content/tool-call-display.tsx

Lines changed: 142 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -36,182 +36,180 @@ export const ToolCallDisplay = ({
3636
isStream: boolean,
3737
applied: boolean
3838
}) => {
39-
// Ensure the toolInvocation has a result property
40-
if (!isStream || toolInvocation.state === 'output-available') {
41-
const toolName = toolInvocation.type.split('-')[1];
4239

43-
if (toolName === TERMINAL_COMMAND_TOOL_NAME) {
44-
const args = toolInvocation.input as { command: string };
45-
const result = toolInvocation.output as { output?: string; error?: string } | null;
46-
if (!args?.command) {
47-
return (
48-
<ToolCallSimple
49-
toolInvocation={toolInvocation}
50-
key={toolInvocation.toolCallId}
51-
loading={false}
52-
/>
53-
);
54-
}
40+
const toolName = toolInvocation.type.split('-')[1];
41+
42+
if (toolName === TERMINAL_COMMAND_TOOL_NAME) {
43+
const args = toolInvocation.input as { command: string };
44+
const result = toolInvocation.output as { output?: string; error?: string } | null;
45+
if (!args?.command) {
5546
return (
56-
<BashCodeDisplay
47+
<ToolCallSimple
48+
toolInvocation={toolInvocation}
5749
key={toolInvocation.toolCallId}
58-
content={args.command}
59-
isStream={isStream}
60-
defaultStdOut={toolInvocation.state === 'output-available' ? result?.output ?? null : null}
61-
defaultStdErr={toolInvocation.state === 'output-available' ? result?.error ?? null : null}
50+
loading={false}
6251
/>
6352
);
6453
}
54+
return (
55+
<BashCodeDisplay
56+
key={toolInvocation.toolCallId}
57+
content={args.command}
58+
isStream={isStream}
59+
defaultStdOut={toolInvocation.state === 'output-available' ? result?.output ?? null : null}
60+
defaultStdErr={toolInvocation.state === 'output-available' ? result?.error ?? null : null}
61+
/>
62+
);
63+
}
6564

66-
if (toolName === WEB_SEARCH_TOOL_NAME && toolInvocation.state === 'output-available') {
67-
const searchResult: WebSearchResult | null = toolInvocation.output as WebSearchResult | null;
68-
const args = toolInvocation.input as z.infer<typeof WEB_SEARCH_TOOL_PARAMETERS>;
69-
if (args?.query && searchResult?.result && searchResult.result.length > 0) {
70-
return (
71-
<SearchSourcesDisplay
72-
query={String(args.query)}
73-
results={Array.isArray(searchResult.result) ? (searchResult.result as unknown[]).map((result: unknown) => ({
74-
title: String((result as { title?: string; url?: string }).title ?? (result as { url?: string }).url ?? ''),
75-
url: String((result as { url?: string }).url ?? '')
76-
})) : []}
77-
/>
78-
);
79-
}
65+
if (toolName === WEB_SEARCH_TOOL_NAME && toolInvocation.state === 'output-available') {
66+
const searchResult: WebSearchResult | null = toolInvocation.output as WebSearchResult | null;
67+
const args = toolInvocation.input as z.infer<typeof WEB_SEARCH_TOOL_PARAMETERS>;
68+
if (args?.query && searchResult?.result && searchResult.result.length > 0) {
69+
return (
70+
<SearchSourcesDisplay
71+
query={String(args.query)}
72+
results={Array.isArray(searchResult.result) ? (searchResult.result as unknown[]).map((result: unknown) => ({
73+
title: String((result as { title?: string; url?: string }).title ?? (result as { url?: string }).url ?? ''),
74+
url: String((result as { url?: string }).url ?? '')
75+
})) : []}
76+
/>
77+
);
8078
}
79+
}
8180

82-
if (toolName === WRITE_FILE_TOOL_NAME) {
83-
const args = toolInvocation.input as z.infer<typeof WRITE_FILE_TOOL_PARAMETERS>
84-
const filePath = args?.file_path;
85-
const codeContent = args?.content;
86-
if (!filePath || !codeContent) {
87-
return (
88-
<ToolCallSimple
89-
toolInvocation={toolInvocation}
90-
key={toolInvocation.toolCallId}
91-
loading={false}
92-
/>
93-
);
94-
}
81+
if (toolName === WRITE_FILE_TOOL_NAME) {
82+
const args = toolInvocation.input as z.infer<typeof WRITE_FILE_TOOL_PARAMETERS>
83+
const filePath = args?.file_path;
84+
const codeContent = args?.content;
85+
if (!filePath || !codeContent) {
9586
return (
96-
<CollapsibleCodeBlock
97-
path={filePath}
98-
content={codeContent}
99-
messageId={messageId}
100-
applied={applied}
101-
isStream={isStream}
102-
originalContent={codeContent}
103-
updatedContent={codeContent}
87+
<ToolCallSimple
88+
toolInvocation={toolInvocation}
89+
key={toolInvocation.toolCallId}
90+
loading={false}
10491
/>
10592
);
10693
}
94+
return (
95+
<CollapsibleCodeBlock
96+
path={filePath}
97+
content={codeContent}
98+
messageId={messageId}
99+
applied={applied}
100+
isStream={isStream}
101+
originalContent={codeContent}
102+
updatedContent={codeContent}
103+
/>
104+
);
105+
}
107106

108-
if (toolName === FUZZY_EDIT_FILE_TOOL_NAME) {
109-
const args = toolInvocation.input as z.infer<typeof FUZZY_EDIT_FILE_TOOL_PARAMETERS>;
110-
const filePath = args?.file_path;
111-
const codeContent = args?.content;
112-
if (!filePath || !codeContent) {
113-
return (
114-
<ToolCallSimple
115-
toolInvocation={toolInvocation}
116-
key={toolInvocation.toolCallId}
117-
loading={false}
118-
/>
119-
);
120-
}
107+
if (toolName === FUZZY_EDIT_FILE_TOOL_NAME) {
108+
const args = toolInvocation.input as z.infer<typeof FUZZY_EDIT_FILE_TOOL_PARAMETERS>;
109+
const filePath = args?.file_path;
110+
const codeContent = args?.content;
111+
if (!filePath || !codeContent) {
121112
return (
122-
<CollapsibleCodeBlock
123-
path={filePath}
124-
content={codeContent}
125-
messageId={messageId}
126-
applied={applied}
127-
isStream={isStream}
128-
originalContent={codeContent}
129-
updatedContent={codeContent}
113+
<ToolCallSimple
114+
toolInvocation={toolInvocation}
115+
key={toolInvocation.toolCallId}
116+
loading={false}
130117
/>
131118
);
132119
}
120+
return (
121+
<CollapsibleCodeBlock
122+
path={filePath}
123+
content={codeContent}
124+
messageId={messageId}
125+
applied={applied}
126+
isStream={isStream}
127+
originalContent={codeContent}
128+
updatedContent={codeContent}
129+
/>
130+
);
131+
}
133132

134-
if (toolName === SEARCH_REPLACE_EDIT_FILE_TOOL_NAME) {
135-
const args = toolInvocation.input as z.infer<typeof SEARCH_REPLACE_EDIT_FILE_TOOL_PARAMETERS>;
136-
const filePath = args?.file_path;
137-
const codeContent = args?.new_string;
138-
if (!filePath || !codeContent) {
139-
return (
140-
<ToolCallSimple
141-
toolInvocation={toolInvocation}
142-
key={toolInvocation.toolCallId}
143-
loading={false}
144-
/>
145-
);
146-
}
133+
if (toolName === SEARCH_REPLACE_EDIT_FILE_TOOL_NAME) {
134+
const args = toolInvocation.input as z.infer<typeof SEARCH_REPLACE_EDIT_FILE_TOOL_PARAMETERS>;
135+
const filePath = args?.file_path;
136+
const codeContent = args?.new_string;
137+
if (!filePath || !codeContent) {
147138
return (
148-
<CollapsibleCodeBlock
149-
path={filePath}
150-
content={codeContent}
151-
messageId={messageId}
152-
applied={applied}
153-
isStream={isStream}
154-
originalContent={codeContent}
155-
updatedContent={codeContent}
139+
<ToolCallSimple
140+
toolInvocation={toolInvocation}
141+
key={toolInvocation.toolCallId}
142+
loading={false}
156143
/>
157144
);
158145
}
146+
return (
147+
<CollapsibleCodeBlock
148+
path={filePath}
149+
content={codeContent}
150+
messageId={messageId}
151+
applied={applied}
152+
isStream={isStream}
153+
originalContent={codeContent}
154+
updatedContent={codeContent}
155+
/>
156+
);
157+
}
159158

160-
if (toolName === SEARCH_REPLACE_MULTI_EDIT_FILE_TOOL_NAME) {
161-
const args = toolInvocation.input as z.infer<typeof SEARCH_REPLACE_MULTI_EDIT_FILE_TOOL_PARAMETERS>;
162-
const filePath = args?.file_path;
163-
const codeContent = args?.edits?.map((edit) => edit.new_string).join('\n...\n');
164-
if (!filePath || !codeContent) {
165-
return (
166-
<ToolCallSimple
167-
toolInvocation={toolInvocation}
168-
key={toolInvocation.toolCallId}
169-
loading={false}
170-
/>
171-
);
172-
}
159+
if (toolName === SEARCH_REPLACE_MULTI_EDIT_FILE_TOOL_NAME) {
160+
const args = toolInvocation.input as z.infer<typeof SEARCH_REPLACE_MULTI_EDIT_FILE_TOOL_PARAMETERS>;
161+
const filePath = args?.file_path;
162+
const codeContent = args?.edits?.map((edit) => edit.new_string).join('\n...\n');
163+
if (!filePath || !codeContent) {
173164
return (
174-
<CollapsibleCodeBlock
175-
path={filePath}
176-
content={codeContent}
177-
messageId={messageId}
178-
applied={applied}
179-
isStream={isStream}
180-
originalContent={codeContent}
181-
updatedContent={codeContent}
165+
<ToolCallSimple
166+
toolInvocation={toolInvocation}
167+
key={toolInvocation.toolCallId}
168+
loading={false}
182169
/>
183170
);
184171
}
172+
return (
173+
<CollapsibleCodeBlock
174+
path={filePath}
175+
content={codeContent}
176+
messageId={messageId}
177+
applied={applied}
178+
isStream={isStream}
179+
originalContent={codeContent}
180+
updatedContent={codeContent}
181+
/>
182+
);
183+
}
185184

186-
if (toolName === TODO_WRITE_TOOL_NAME) {
187-
const args = toolInvocation.input as z.infer<typeof TODO_WRITE_TOOL_PARAMETERS>;
188-
const todos = args?.todos;
189-
if (!todos || todos.length === 0) {
190-
return (
191-
<ToolCallSimple
192-
toolInvocation={toolInvocation}
193-
key={toolInvocation.toolCallId}
194-
loading={false}
195-
/>
196-
);
197-
}
185+
if (toolName === TODO_WRITE_TOOL_NAME) {
186+
const args = toolInvocation.input as z.infer<typeof TODO_WRITE_TOOL_PARAMETERS>;
187+
const todos = args?.todos;
188+
if (!todos || todos.length === 0) {
198189
return (
199-
<div>
200-
{todos.map((todo) => (
201-
<div className="flex items-center gap-2 text-sm" key={todo.content}>
202-
<div className="flex items-center justify-center w-4 h-4 min-w-4">
203-
{todo.status === 'completed' ? <Icons.SquareCheck className="w-4 h-4" /> : <Icons.Square className="w-4 h-4" />}
204-
</div>
205-
<p className={cn(
206-
todo.status === 'completed' ? 'line-through text-green-500' : '',
207-
todo.status === 'in_progress' ? 'text-yellow-500' : '',
208-
todo.status === 'pending' ? 'text-gray-500' : '',
209-
)}>{todo.content}</p>
210-
</div>
211-
))}
212-
</div>
190+
<ToolCallSimple
191+
toolInvocation={toolInvocation}
192+
key={toolInvocation.toolCallId}
193+
loading={false}
194+
/>
213195
);
214196
}
197+
return (
198+
<div>
199+
{todos.map((todo) => (
200+
<div className="flex items-center gap-2 text-sm" key={todo.content}>
201+
<div className="flex items-center justify-center w-4 h-4 min-w-4">
202+
{todo.status === 'completed' ? <Icons.SquareCheck className="w-4 h-4" /> : <Icons.Square className="w-4 h-4" />}
203+
</div>
204+
<p className={cn(
205+
todo.status === 'completed' ? 'line-through text-green-500' : '',
206+
todo.status === 'in_progress' ? 'text-yellow-500' : '',
207+
todo.status === 'pending' ? 'text-gray-500' : '',
208+
)}>{todo.content}</p>
209+
</div>
210+
))}
211+
</div>
212+
);
215213
}
216214

217215
return (

apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-messages/message-content/tool-call-simple.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
TERMINAL_COMMAND_TOOL_NAME,
2525
TODO_WRITE_TOOL_NAME,
2626
type TODO_WRITE_TOOL_PARAMETERS,
27+
TYPECHECK_TOOL_NAME,
2728
WEB_SEARCH_TOOL_NAME,
2829
type WEB_SEARCH_TOOL_PARAMETERS,
2930
WRITE_FILE_TOOL_NAME,
@@ -53,6 +54,7 @@ const TOOL_ICONS: Record<string, any> = {
5354
[TODO_WRITE_TOOL_NAME]: Icons.ListBullet,
5455
[EXIT_PLAN_MODE_TOOL_NAME]: Icons.ListBullet,
5556
[BASH_READ_TOOL_NAME]: Icons.EyeOpen,
57+
[TYPECHECK_TOOL_NAME]: Icons.MagnifyingGlass,
5658
} as const;
5759

5860
export function ToolCallSimple({
@@ -67,10 +69,6 @@ export function ToolCallSimple({
6769
const toolName = toolInvocation.type.split('-')[1] ?? '';
6870
const Icon = TOOL_ICONS[toolName] ?? Icons.QuestionMarkCircled;
6971

70-
if (toolInvocation.state === 'output-available') {
71-
return null;
72-
}
73-
7472
const getLabel = () => {
7573
try {
7674
switch (toolName) {
@@ -174,6 +172,8 @@ export function ToolCallSimple({
174172
return 'Reading style guide';
175173
case ONLOOK_INSTRUCTIONS_TOOL_NAME:
176174
return 'Reading Onlook instructions';
175+
case TYPECHECK_TOOL_NAME:
176+
return 'Checking types';
177177
default:
178178
return toolName?.replace(/[-_]/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
179179
}

0 commit comments

Comments
 (0)