style and display fixes
This commit is contained in:
parent
dd47212471
commit
b3c9579890
@ -76,12 +76,14 @@ const ChatTurn = memo(function ChatTurn({ turn }: ChatTurnProps) {
|
||||
|
||||
{/* Error Alert */}
|
||||
{turn.errorMessage && turn.status === "error" && (
|
||||
<div className="max-w-[80%] ml-0 mb-4">
|
||||
<div className="bg-red-600 text-white rounded p-4 border-2 border-red-400">
|
||||
<div className="text-sm font-semibold mb-2 flex items-center gap-2">
|
||||
<div className="max-w-[80%] ml-0 mb-2">
|
||||
<div className="bg-red-600 text-white rounded p-3 border-2 border-red-400">
|
||||
<div className="text-xs font-semibold mb-1 flex items-center gap-2">
|
||||
<span>⚠️</span> Error
|
||||
</div>
|
||||
<div className="whitespace-pre-wrap">{turn.errorMessage}</div>
|
||||
<div className="whitespace-pre-wrap text-sm">
|
||||
{turn.errorMessage}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@ -89,51 +91,53 @@ const ChatTurn = memo(function ChatTurn({ turn }: ChatTurnProps) {
|
||||
{/* User Prompt */}
|
||||
<div className="max-w-[80%] ml-0 mb-4">
|
||||
<div className="bg-[#4a0000] text-white rounded p-4">
|
||||
<div className="text-sm font-semibold mb-2">You</div>
|
||||
<div className="whitespace-pre-wrap">{turn.prompts?.user || ""}</div>
|
||||
<div className="text-xs font-semibold mb-2">You</div>
|
||||
<div className="whitespace-pre-wrap text-sm">
|
||||
{turn.prompts?.user || ""}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Agent Response */}
|
||||
{(turn.blocks && turn.blocks.length > 0) && (
|
||||
{turn.blocks && turn.blocks.length > 0 && (
|
||||
<div className="max-w-[80%] ml-auto mb-4 overflow-x-hidden">
|
||||
<div className="bg-bg-tertiary border border-border-default rounded p-4 overflow-x-auto">
|
||||
<div className="text-sm font-semibold mb-3 text-text-secondary">
|
||||
<div className="bg-bg-tertiary border border-border-default rounded p-3 overflow-x-auto">
|
||||
<div className="text-xs font-semibold mb-4 text-text-secondary">
|
||||
Gadget
|
||||
</div>
|
||||
|
||||
{/* Render blocks in order */}
|
||||
{turn.blocks.map((block, idx) => {
|
||||
if (block.mode === 'thinking') {
|
||||
if (block.mode === "thinking") {
|
||||
return (
|
||||
<div key={idx} className="mb-3">
|
||||
<div key={idx} className="mb-4">
|
||||
<div className="text-xs text-text-muted mb-1 font-mono">
|
||||
Thinking
|
||||
</div>
|
||||
<div
|
||||
className="p-3 bg-bg-secondary rounded text-sm text-text-muted whitespace-pre-wrap font-mono text-xs"
|
||||
className="gadget-markdown bg-bg-secondary rounded p-2 text-xs text-text-muted font-mono"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: marked.parse(block.content) as string
|
||||
__html: marked.parse(block.content) as string,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else if (block.mode === 'responding') {
|
||||
} else if (block.mode === "responding") {
|
||||
return (
|
||||
<div key={idx} className="mb-3 overflow-x-auto">
|
||||
<div key={idx} className="mb-4 overflow-x-auto">
|
||||
<div
|
||||
className="gadget-markdown"
|
||||
className="gadget-markdown text-[13px]"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: marked.parse(block.content) as string
|
||||
__html: marked.parse(block.content) as string,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else if (block.mode === 'tool') {
|
||||
} else if (block.mode === "tool") {
|
||||
const toolCall = block.content;
|
||||
const subagent = toolCall.subagent;
|
||||
return (
|
||||
<div key={idx} className="mb-3">
|
||||
<div key={idx} className="tool-call">
|
||||
<div className="flex items-center gap-2 text-xs font-mono text-text-secondary">
|
||||
<span className="text-brand">●</span>
|
||||
<span>{toolCall.name}</span>
|
||||
@ -144,16 +148,14 @@ const ChatTurn = memo(function ChatTurn({ turn }: ChatTurnProps) {
|
||||
<span className="text-green-500">✓</span>
|
||||
)}
|
||||
</div>
|
||||
{subagent && (
|
||||
<SubagentDisplay subagent={subagent} />
|
||||
)}
|
||||
{subagent && <SubagentDisplay subagent={subagent} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
|
||||
<div className="mt-2 text-xs text-text-muted">
|
||||
<div className="mt-1 text-xs text-text-muted">
|
||||
{startedAt.toLocaleTimeString()}
|
||||
</div>
|
||||
</div>
|
||||
@ -163,7 +165,11 @@ const ChatTurn = memo(function ChatTurn({ turn }: ChatTurnProps) {
|
||||
);
|
||||
});
|
||||
|
||||
function SubagentDisplay({ subagent }: { subagent: NonNullable<ChatTurnBlockTool['content']['subagent']> }) {
|
||||
function SubagentDisplay({
|
||||
subagent,
|
||||
}: {
|
||||
subagent: NonNullable<ChatTurnBlockTool["content"]["subagent"]>;
|
||||
}) {
|
||||
const [expanded, setExpanded] = useState(true);
|
||||
const toggle = useCallback(() => setExpanded((p) => !p), []);
|
||||
|
||||
@ -179,7 +185,7 @@ function SubagentDisplay({ subagent }: { subagent: NonNullable<ChatTurnBlockTool
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="ml-4 border-l-2 border-brand/20 pl-2">
|
||||
<div className="ml-3 border-l-2 border-brand/20 pl-1.5 mt-1">
|
||||
<button
|
||||
onClick={toggle}
|
||||
className="flex items-center gap-1.5 text-xs font-mono text-text-muted hover:text-text-primary transition-colors w-full text-left"
|
||||
@ -188,7 +194,8 @@ function SubagentDisplay({ subagent }: { subagent: NonNullable<ChatTurnBlockTool
|
||||
<span>Subagent</span>
|
||||
{subagent.stats && (
|
||||
<span className="text-text-muted">
|
||||
({subagent.toolCalls.length} calls · {formatDuration(subagent.stats.durationMs)})
|
||||
({subagent.toolCalls.length} calls ·{" "}
|
||||
{formatDuration(subagent.stats.durationMs)})
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
@ -198,9 +205,11 @@ function SubagentDisplay({ subagent }: { subagent: NonNullable<ChatTurnBlockTool
|
||||
{/* Thinking */}
|
||||
{subagent.thinking && (
|
||||
<div>
|
||||
<div className="text-xs text-text-muted font-mono mb-1">Thinking</div>
|
||||
<div className="text-xs text-text-muted font-mono mb-0.5">
|
||||
Thinking
|
||||
</div>
|
||||
<div
|
||||
className="subagent-compact gadget-markdown bg-bg-secondary rounded p-1.5 text-xs text-text-muted whitespace-pre-wrap font-mono"
|
||||
className="gadget-markdown bg-bg-secondary rounded p-1.5 text-xs text-text-muted font-mono"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: marked.parse(subagent.thinking) as string,
|
||||
}}
|
||||
@ -211,12 +220,15 @@ function SubagentDisplay({ subagent }: { subagent: NonNullable<ChatTurnBlockTool
|
||||
{/* Subagent Tool Calls */}
|
||||
{subagent.toolCalls.length > 0 && (
|
||||
<div>
|
||||
<div className="text-xs text-text-muted font-mono mb-1">
|
||||
<div className="text-xs text-text-muted font-mono mb-0.5">
|
||||
Tool Calls ({subagent.toolCalls.length})
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<div className="space-y-0.5">
|
||||
{subagent.toolCalls.map((tc, i) => (
|
||||
<div key={tc.callId || i} className="flex items-center gap-2 text-xs font-mono text-text-secondary">
|
||||
<div
|
||||
key={tc.callId || i}
|
||||
className="flex items-center gap-2 text-xs font-mono text-text-secondary"
|
||||
>
|
||||
<span className="text-yellow-500">◆</span>
|
||||
<span>{tc.name}</span>
|
||||
{tc.response && <span className="text-green-500">✓</span>}
|
||||
@ -229,9 +241,11 @@ function SubagentDisplay({ subagent }: { subagent: NonNullable<ChatTurnBlockTool
|
||||
{/* Response */}
|
||||
{subagent.response && (
|
||||
<div>
|
||||
<div className="text-xs text-text-muted font-mono mb-1">Response</div>
|
||||
<div className="text-xs text-text-muted font-mono mb-0.5">
|
||||
Response
|
||||
</div>
|
||||
<div
|
||||
className="subagent-compact gadget-markdown"
|
||||
className="gadget-markdown text-xs"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: marked.parse(subagent.response) as string,
|
||||
}}
|
||||
@ -246,7 +260,9 @@ function SubagentDisplay({ subagent }: { subagent: NonNullable<ChatTurnBlockTool
|
||||
<span>{formatTokenCount(subagent.stats.inputTokens)} in</span>
|
||||
<span>{formatTokenCount(subagent.stats.responseTokens)} out</span>
|
||||
{subagent.stats.thinkingTokenCount > 0 && (
|
||||
<span>{formatTokenCount(subagent.stats.thinkingTokenCount)} thinking</span>
|
||||
<span>
|
||||
{formatTokenCount(subagent.stats.thinkingTokenCount)} thinking
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -13,8 +13,9 @@
|
||||
--color-border-default: #2a2a2a;
|
||||
--color-border-highlight: #3a3a3a;
|
||||
|
||||
--font-mono: 'Courier New', Courier, monospace;
|
||||
--font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
--font-mono: "Fira Code", "Courier New", Courier, monospace;
|
||||
--font-sans:
|
||||
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
|
||||
--spacing-header: 48px;
|
||||
--spacing-status: 32px;
|
||||
@ -54,7 +55,17 @@ button {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
.tool-call {
|
||||
margin-top: theme("spacing.4");
|
||||
margin-bottom: theme("spacing.4");
|
||||
}
|
||||
|
||||
.tool-call + .tool-call {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
textarea {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
@ -77,8 +88,13 @@ input, textarea {
|
||||
}
|
||||
|
||||
@keyframes strobe {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.4; }
|
||||
0%,
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
.strobe {
|
||||
@ -86,20 +102,20 @@ input, textarea {
|
||||
}
|
||||
|
||||
/* ── Gadget Markdown Styles ─────────────────────────────────── */
|
||||
/* Applied to agent response output inside ChatTurn */
|
||||
/* Dense, technical display — no blog-style whitespace */
|
||||
|
||||
.gadget-markdown {
|
||||
color: var(--color-text-primary);
|
||||
line-height: 1.7;
|
||||
font-size: 14px;
|
||||
white-space: pre-wrap;
|
||||
line-height: 1.5;
|
||||
word-break: break-word;
|
||||
/* Prevent the markdown root from stretching to fill the scroll container —
|
||||
display:inline-block shrinks it to content width, so the
|
||||
overflow-x-auto on the parent actually clips and scrolls it. */
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin-bottom: 8px;
|
||||
|
||||
:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.gadget-markdown h1,
|
||||
@ -110,19 +126,37 @@ input, textarea {
|
||||
.gadget-markdown h6 {
|
||||
color: #e8e8e8;
|
||||
font-weight: 600;
|
||||
line-height: 1.3;
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.5em;
|
||||
line-height: 1.25;
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.gadget-markdown h1 { font-size: 1.4em; border-bottom: 1px solid var(--color-border-default); padding-bottom: 0.3em; }
|
||||
.gadget-markdown h2 { font-size: 1.2em; border-bottom: 1px solid var(--color-border-default); padding-bottom: 0.25em; }
|
||||
.gadget-markdown h3 { font-size: 1.05em; }
|
||||
.gadget-markdown h4 { font-size: 1em; }
|
||||
.gadget-markdown h1 {
|
||||
font-size: 1.5em;
|
||||
/* border-bottom: 1px solid var(--color-border-default); */
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
.gadget-markdown h2 {
|
||||
font-size: 1.4em;
|
||||
/* border-bottom: 1px solid var(--color-border-default); */
|
||||
padding-bottom: 0.15em;
|
||||
}
|
||||
.gadget-markdown h3 {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
.gadget-markdown h4 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
.gadget-markdown h5 {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
.gadget-markdown h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.gadget-markdown p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.85em;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.gadget-markdown a {
|
||||
@ -137,23 +171,23 @@ input, textarea {
|
||||
/* Inline code */
|
||||
.gadget-markdown code:not(pre code) {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.875em;
|
||||
font-size: 0.85em;
|
||||
background: #1e1e1e;
|
||||
color: #f472b6;
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
color: rgb(219, 219, 7);
|
||||
padding: 0.1em 0.3em;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #2d2d2d;
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
.gadget-markdown pre {
|
||||
line-height: 1rem;
|
||||
background: #0d0d0d;
|
||||
border: 1px solid #2a2a2a;
|
||||
border-radius: 6px;
|
||||
padding: 1em 1.2em;
|
||||
border-radius: 4px;
|
||||
padding: 0.5rem 0.7rem;
|
||||
overflow-x: auto;
|
||||
margin-bottom: 1em;
|
||||
/* Horizontal scroll fix — parent must have overflow-x-auto or be constrained */
|
||||
margin-bottom: 0.5rem;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
@ -173,14 +207,14 @@ input, textarea {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 1em;
|
||||
font-size: 0.9em;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
.gadget-markdown th,
|
||||
.gadget-markdown td {
|
||||
border: 1px solid #2a2a2a;
|
||||
padding: 0.5em 0.9em;
|
||||
padding: 0.35em 0.6em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@ -200,23 +234,23 @@ input, textarea {
|
||||
|
||||
/* Blockquotes */
|
||||
.gadget-markdown blockquote {
|
||||
border-left: 3px solid #3a3a3a;
|
||||
margin: 0 0 1em 0;
|
||||
padding: 0.5em 1em;
|
||||
border-left: 2px solid #3a3a3a;
|
||||
margin: 0 0 0.35rem 0;
|
||||
padding: 0.25rem 0.6rem;
|
||||
color: var(--color-text-muted);
|
||||
background: #111111;
|
||||
border-radius: 0 4px 4px 0;
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
|
||||
/* Lists */
|
||||
.gadget-markdown ul,
|
||||
.gadget-markdown ol {
|
||||
margin-bottom: 0.85em;
|
||||
padding-left: 1.5em;
|
||||
margin-bottom: 0.35rem;
|
||||
padding-left: 1.2rem;
|
||||
}
|
||||
|
||||
.gadget-markdown li {
|
||||
margin-bottom: 0.3em;
|
||||
margin-bottom: 0.15rem;
|
||||
}
|
||||
|
||||
.gadget-markdown li::marker {
|
||||
@ -227,13 +261,13 @@ input, textarea {
|
||||
.gadget-markdown hr {
|
||||
border: none;
|
||||
border-top: 1px solid var(--color-border-default);
|
||||
margin: 1.5em 0;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
/* Images */
|
||||
.gadget-markdown img {
|
||||
max-width: 100%;
|
||||
border-radius: 6px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--color-border-default);
|
||||
}
|
||||
|
||||
@ -243,61 +277,6 @@ input, textarea {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
|
||||
.gadget-markdown em {
|
||||
color: #c4c4c4;
|
||||
}
|
||||
|
||||
/* ── Subagent Compact Markdown ── */
|
||||
/* Higher-specificity overrides (.subagent-compact.gadget-markdown > .gadget-markdown)
|
||||
to crush the generous spacing that looks fine at top-level but explodes when nested. */
|
||||
.subagent-compact.gadget-markdown {
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.subagent-compact.gadget-markdown h1,
|
||||
.subagent-compact.gadget-markdown h2,
|
||||
.subagent-compact.gadget-markdown h3,
|
||||
.subagent-compact.gadget-markdown h4,
|
||||
.subagent-compact.gadget-markdown h5,
|
||||
.subagent-compact.gadget-markdown h6 {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.25rem;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.subagent-compact.gadget-markdown p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
|
||||
.subagent-compact.gadget-markdown pre {
|
||||
margin-top: 0.35rem;
|
||||
margin-bottom: 0.35rem;
|
||||
padding: 0.5rem 0.6rem;
|
||||
}
|
||||
|
||||
.subagent-compact.gadget-markdown ul,
|
||||
.subagent-compact.gadget-markdown ol {
|
||||
margin-bottom: 0.35rem;
|
||||
padding-left: 1.1rem;
|
||||
}
|
||||
|
||||
.subagent-compact.gadget-markdown li {
|
||||
margin-bottom: 0.15rem;
|
||||
}
|
||||
|
||||
.subagent-compact.gadget-markdown blockquote {
|
||||
margin-top: 0.25rem;
|
||||
margin-bottom: 0.25rem;
|
||||
padding: 0.25rem 0.6rem;
|
||||
}
|
||||
|
||||
.subagent-compact.gadget-markdown hr {
|
||||
margin: 0.4rem 0;
|
||||
}
|
||||
|
||||
.subagent-compact.gadget-markdown table {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
@ -1009,7 +1009,7 @@ export default function ChatSessionView() {
|
||||
{/* Chat View (75%) */}
|
||||
<div className="flex-1 flex flex-col overflow-hidden">
|
||||
{/* Messages */}
|
||||
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
||||
<div className="flex-1 overflow-y-auto p-3 space-y-2">
|
||||
{turns.map((turn) => (
|
||||
<ChatTurnComponent
|
||||
key={turn._id}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user