Skip to content

Commit 5e5d14c

Browse files
authored
Handle more message types (#140)
1 parent 4d4e218 commit 5e5d14c

File tree

1 file changed

+99
-28
lines changed

1 file changed

+99
-28
lines changed

apps/web/src/app/(authenticated)/usage/Messages.tsx

Lines changed: 99 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,28 @@ type MessagesProps = {
99
messages: Message[];
1010
};
1111

12+
type QuestionData = {
13+
question: string;
14+
suggestions: string[];
15+
};
16+
17+
const parseQuestionData = (text: string): QuestionData | null => {
18+
try {
19+
const parsed = JSON.parse(text);
20+
21+
if (parsed?.question && Array.isArray(parsed.suggest)) {
22+
return {
23+
question: parsed.question,
24+
suggestions: parsed.suggest,
25+
};
26+
}
27+
} catch {
28+
// Not valid JSON
29+
}
30+
31+
return null;
32+
};
33+
1234
export const Messages = ({ messages }: MessagesProps) => {
1335
const conversation = useMemo(
1436
() =>
@@ -20,31 +42,68 @@ export const Messages = ({ messages }: MessagesProps) => {
2042

2143
return (
2244
<div className="space-y-6">
23-
{conversation.map((message) => (
24-
<div
25-
key={message.id}
26-
className={cn(
27-
'flex flex-col gap-3 rounded-lg p-4',
28-
message.role === 'user' ? 'bg-primary/10' : 'bg-secondary/10',
29-
)}
30-
>
31-
<div className="flex flex-row items-center justify-between gap-2 text-xs font-medium text-muted-foreground">
32-
<div className="flex items-center gap-2">
33-
<div>{message.name}</div>
34-
<div>&middot;</div>
35-
<div>{message.timestamp}</div>
45+
{conversation.map((message) => {
46+
const isQuestion = message.type === 'ask' && message.ask === 'followup';
47+
const isCommand = message.type === 'ask' && message.ask === 'command';
48+
const questionData =
49+
isQuestion && message.text ? parseQuestionData(message.text) : null;
50+
51+
return (
52+
<div
53+
key={message.id}
54+
className={cn(
55+
'flex flex-col gap-3 rounded-lg p-4',
56+
message.role === 'user' ? 'bg-primary/10' : 'bg-secondary/10',
57+
)}
58+
>
59+
<div className="flex flex-row items-center justify-between gap-2 text-xs font-medium text-muted-foreground">
60+
<div className="flex items-center gap-2">
61+
<div>{message.name}</div>
62+
<div>&middot;</div>
63+
<div>{message.timestamp}</div>
64+
</div>
65+
{message.mode && (
66+
<div className="px-2 py-1 bg-muted rounded text-xs font-medium">
67+
{message.mode}
68+
</div>
69+
)}
3670
</div>
37-
{message.mode && (
38-
<div className="px-2 py-1 bg-muted rounded text-xs font-medium">
39-
{message.mode}
71+
72+
{isQuestion && questionData ? (
73+
<div className="space-y-4">
74+
{questionData.question && (
75+
<div className="text-sm leading-relaxed">
76+
{questionData.question}
77+
</div>
78+
)}
79+
{questionData.suggestions &&
80+
questionData.suggestions.length > 0 && (
81+
<div className="space-y-2">
82+
{questionData.suggestions.map((suggestion, index) => (
83+
<div
84+
key={index}
85+
className="px-4 py-3 bg-background border border-border rounded-md text-sm hover:bg-muted/50 cursor-pointer transition-colors"
86+
>
87+
{suggestion}
88+
</div>
89+
))}
90+
</div>
91+
)}
92+
</div>
93+
) : isCommand ? (
94+
<div className="space-y-3">
95+
<div className="bg-black/90 text-green-400 p-3 rounded-md font-mono text-sm">
96+
{message.text}
97+
</div>
98+
</div>
99+
) : (
100+
<div className="text-sm leading-relaxed markdown-prose">
101+
<ReactMarkdown>{message.text}</ReactMarkdown>
40102
</div>
41103
)}
42104
</div>
43-
<div className="text-sm leading-relaxed markdown-prose">
44-
<ReactMarkdown>{message.text}</ReactMarkdown>
45-
</div>
46-
</div>
47-
))}
105+
);
106+
})}
48107
</div>
49108
);
50109
};
@@ -59,10 +118,22 @@ const decorate = ({ message, index }: { message: Message; index: number }) => {
59118
return { ...message, role, name, timestamp };
60119
};
61120

62-
const isVisible = (message: Message) =>
63-
(message.ask === 'text' ||
64-
message.say === 'text' ||
65-
message.say === 'completion_result' ||
66-
message.say === 'user_feedback') &&
67-
typeof message.text === 'string' &&
68-
message.text.length > 0;
121+
const isVisible = (message: Message) => {
122+
// Always show followup and command messages regardless of text content
123+
if (
124+
message.type === 'ask' &&
125+
(message.ask === 'followup' || message.ask === 'command')
126+
) {
127+
return true;
128+
}
129+
130+
// For other message types, require non-empty text
131+
return (
132+
(message.ask === 'text' ||
133+
message.say === 'text' ||
134+
message.say === 'completion_result' ||
135+
message.say === 'user_feedback') &&
136+
typeof message.text === 'string' &&
137+
message.text.length > 0
138+
);
139+
};

0 commit comments

Comments
 (0)