working i/o cards

This commit is contained in:
Ishaan Jaffer 2026-01-30 18:09:48 -08:00
parent 78850bb7a6
commit 28424804ad
4 changed files with 107 additions and 34 deletions

View file

@ -3,6 +3,7 @@
* Datadog-style: header with icon/metrics, content below
*/
import { useState } from 'react';
import { message } from 'antd';
import { ParsedMessage } from './prettyMessagesTypes';
import { SectionHeader } from './SectionHeader';
@ -17,6 +18,8 @@ interface InputCardProps {
}
export function InputCard({ messages, promptTokens, inputCost }: InputCardProps) {
const [isCollapsed, setIsCollapsed] = useState(false);
if (messages.length === 0) {
return null;
}
@ -48,30 +51,41 @@ export function InputCard({ messages, promptTokens, inputCost }: InputCardProps)
tokens={promptTokens}
cost={inputCost}
onCopy={handleCopy}
isCollapsed={isCollapsed}
onToggleCollapse={() => setIsCollapsed(!isCollapsed)}
/>
{/* Content */}
<div style={{ padding: '12px 16px' }}>
{/* System Message - Collapsible with arrow */}
{systemMessage && (
<CollapsibleMessage
label="SYSTEM"
content={systemMessage.content}
defaultExpanded={!!(systemMessage.content && systemMessage.content.length < 200)}
/>
)}
<div
style={{
maxHeight: isCollapsed ? '0px' : '10000px',
overflow: 'hidden',
transition: 'max-height 0.3s ease-out, opacity 0.3s ease-out',
opacity: isCollapsed ? 0 : 1,
}}
>
<div style={{ padding: '12px 16px' }}>
{/* System Message - Collapsible with arrow */}
{systemMessage && (
<CollapsibleMessage
label="SYSTEM"
content={systemMessage.content}
defaultExpanded={!!(systemMessage.content && systemMessage.content.length < 200)}
/>
)}
{/* History - Tree style, collapsed by default */}
{historyMessages.length > 0 && <HistoryTree messages={historyMessages} />}
{/* History - Tree style, collapsed by default */}
{historyMessages.length > 0 && <HistoryTree messages={historyMessages} />}
{/* Last User Message - Always visible */}
{lastMessage && (
<SimpleMessageBlock
label={lastMessage.role.toUpperCase()}
content={lastMessage.content}
toolCalls={lastMessage.toolCalls}
/>
)}
{/* Last User Message - Always visible */}
{lastMessage && (
<SimpleMessageBlock
label={lastMessage.role.toUpperCase()}
content={lastMessage.content}
toolCalls={lastMessage.toolCalls}
/>
)}
</div>
</div>
</div>
);

View file

@ -3,6 +3,7 @@
* Datadog-style: header with icon/metrics, content below
*/
import { useState } from 'react';
import { Typography, message as antdMessage } from 'antd';
import { ParsedMessage } from './prettyMessagesTypes';
import { SectionHeader } from './SectionHeader';
@ -17,6 +18,8 @@ interface OutputCardProps {
}
export function OutputCard({ message, completionTokens, outputCost }: OutputCardProps) {
const [isCollapsed, setIsCollapsed] = useState(false);
const handleCopy = () => {
if (!message) return;
@ -39,11 +42,22 @@ export function OutputCard({ message, completionTokens, outputCost }: OutputCard
tokens={completionTokens}
cost={outputCost}
onCopy={handleCopy}
isCollapsed={isCollapsed}
onToggleCollapse={() => setIsCollapsed(!isCollapsed)}
/>
<div style={{ padding: '12px 16px' }}>
<Text type="secondary" style={{ fontSize: 13, fontStyle: 'italic' }}>
No response data available
</Text>
<div
style={{
maxHeight: isCollapsed ? '0px' : '10000px',
overflow: 'hidden',
transition: 'max-height 0.3s ease-out, opacity 0.3s ease-out',
opacity: isCollapsed ? 0 : 1,
}}
>
<div style={{ padding: '12px 16px' }}>
<Text type="secondary" style={{ fontSize: 13, fontStyle: 'italic' }}>
No response data available
</Text>
</div>
</div>
</div>
);
@ -63,15 +77,26 @@ export function OutputCard({ message, completionTokens, outputCost }: OutputCard
tokens={completionTokens}
cost={outputCost}
onCopy={handleCopy}
isCollapsed={isCollapsed}
onToggleCollapse={() => setIsCollapsed(!isCollapsed)}
/>
{/* Content */}
<div style={{ padding: '12px 16px' }}>
<SimpleMessageBlock
label="ASSISTANT"
content={message.content}
toolCalls={message.toolCalls}
/>
<div
style={{
maxHeight: isCollapsed ? '0px' : '10000px',
overflow: 'hidden',
transition: 'max-height 0.3s ease-out, opacity 0.3s ease-out',
opacity: isCollapsed ? 0 : 1,
}}
>
<div style={{ padding: '12px 16px' }}>
<SimpleMessageBlock
label="ASSISTANT"
content={message.content}
toolCalls={message.toolCalls}
/>
</div>
</div>
</div>
);

View file

@ -5,7 +5,9 @@
import { Typography, Button, Tooltip } from 'antd';
import {
MessageOutlined,
CopyOutlined
CopyOutlined,
DownOutlined,
UpOutlined
} from '@ant-design/icons';
const { Text } = Typography;
@ -15,21 +17,45 @@ interface SectionHeaderProps {
tokens?: number;
cost?: number;
onCopy: () => void;
isCollapsed?: boolean;
onToggleCollapse?: () => void;
}
export function SectionHeader({ type, tokens, cost, onCopy }: SectionHeaderProps) {
export function SectionHeader({ type, tokens, cost, onCopy, isCollapsed, onToggleCollapse }: SectionHeaderProps) {
return (
<div
onClick={onToggleCollapse}
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '10px 16px',
borderBottom: '1px solid #f0f0f0',
borderBottom: isCollapsed ? 'none' : '1px solid #f0f0f0',
background: '#fafafa',
cursor: onToggleCollapse ? 'pointer' : 'default',
transition: 'background 0.15s ease',
}}
onMouseEnter={(e) => {
if (onToggleCollapse) {
e.currentTarget.style.background = '#f5f5f5';
}
}}
onMouseLeave={(e) => {
e.currentTarget.style.background = '#fafafa';
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
{/* Collapse Arrow */}
{onToggleCollapse && (
<div style={{ display: 'flex', alignItems: 'center' }}>
{isCollapsed ? (
<DownOutlined style={{ fontSize: 10, color: '#8c8c8c' }} />
) : (
<UpOutlined style={{ fontSize: 10, color: '#8c8c8c' }} />
)}
</div>
)}
{/* Icon + Label */}
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
{type === 'input' ? (
@ -59,7 +85,15 @@ export function SectionHeader({ type, tokens, cost, onCopy }: SectionHeaderProps
{/* Copy Button */}
<Tooltip title="Copy">
<Button type="text" size="small" icon={<CopyOutlined />} onClick={onCopy} />
<Button
type="text"
size="small"
icon={<CopyOutlined />}
onClick={(e) => {
e.stopPropagation(); // Prevent triggering collapse
onCopy();
}}
/>
</Tooltip>
</div>
);

File diff suppressed because one or more lines are too long