Drop classifyEvent.ts, render TermMsg directly
Per review: StreamRow was meant to match what the server sends in TermMsg, not be a separate model needing a translation step. - classifyEvent.ts and streamRow.ts deleted; termMsg.ts holds the wire types (TermMsg/TermEnvelope) plus TermRow, a TermMsg with just the key/fromHistory bookkeeping Preact needs for list rendering. - Row.tsx renders a TermRow directly: level -> CSS class, empty summary + markdown body -> flat row, everything else with a body -> expandable details gated by the operator's preference. No separate classification step. - useLiveStream.ts drops ClassifyCtx (a single incrementing key counter didn't need a whole context object) and maps envelopes to rows inline. - docs/terminal-rendering.md trimmed substantially — was documenting more implementation detail than useful; points at stream_enrich.rs for the per-tool specifics instead of duplicating them in prose.
This commit is contained in:
parent
5eefaa951d
commit
cebf3c6ced
6 changed files with 156 additions and 436 deletions
|
|
@ -1,13 +1,16 @@
|
|||
// Renders one `StreamRow` — flat `<div class="row …">` or expandable
|
||||
// `<details class="row …">`, matching @hive/shared/terminal.css's
|
||||
// existing row-kind classes exactly (see docs/terminal-rendering.md).
|
||||
// Reuses that stylesheet as-is (imported once by LiveStream.tsx) — the
|
||||
// taxonomy's visual language isn't what mara asked to change, the
|
||||
// component *model* underneath it is.
|
||||
// Renders one `TermRow` — flat `<div class="row …">` or expandable
|
||||
// `<details class="row …">`, driven straight off the wire shape
|
||||
// (`lib/termMsg.ts`'s `TermMsg`, mirroring hive-agent's `term_msg.rs`):
|
||||
// `level` picks the colour class, an empty `summary` + markdown `body`
|
||||
// is a flat row with just the body (assistant text), anything else with
|
||||
// a body is an expandable details row gated by the operator's
|
||||
// expand-tool-output preference. No separate classification step —
|
||||
// mara: "StreamRow should now match what the server sends in TermMsg."
|
||||
import { useEffect, useRef } from 'preact/hooks';
|
||||
import type { StreamRow } from '../lib/streamRow.js';
|
||||
import type { TermRow } from '../lib/termMsg.js';
|
||||
import { linkifyToNodes } from '../lib/linkify.js';
|
||||
import { renderMarkdown } from '../lib/markdown.js';
|
||||
import { getExpandDetailsPref } from '@hive/shared/prefs.js';
|
||||
|
||||
function MarkdownBody({ text }: { text: string }) {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
|
@ -41,25 +44,39 @@ function DiffBody({ text }: { text: string }) {
|
|||
);
|
||||
}
|
||||
|
||||
export function Row({ row }: { row: StreamRow }) {
|
||||
if (row.details) {
|
||||
export function Row({ row }: { row: TermRow }) {
|
||||
const cssClass = 'level-' + row.level;
|
||||
const icon = row.icon != null && row.icon !== '' && <span className="row-glyph">{row.icon}</span>;
|
||||
|
||||
if (row.body == null) {
|
||||
return (
|
||||
<details className={`row ${row.cssClass}`} open={row.defaultOpen || undefined}>
|
||||
<summary>
|
||||
{row.icon != null && row.icon !== '' && <span className="row-glyph">{row.icon}</span>}
|
||||
<span className="summary-text">{row.text}</span>
|
||||
</summary>
|
||||
{row.diffBody != null && <DiffBody text={row.diffBody} />}
|
||||
{row.markdownBody != null && <MarkdownBody text={row.markdownBody} />}
|
||||
{row.plainBody != null && <pre className="tool-body">{linkifyToNodes(row.plainBody)}</pre>}
|
||||
</details>
|
||||
<div className={`row ${cssClass}`}>
|
||||
{icon}
|
||||
{linkifyToNodes(row.summary)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Empty summary + markdown body → the body itself is the whole row
|
||||
// (assistant text), no summary prefix line, never collapsible.
|
||||
if (row.body_format === 'markdown' && row.summary === '') {
|
||||
return (
|
||||
<div className={`row ${cssClass}`}>
|
||||
{icon}
|
||||
<MarkdownBody text={row.body} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`row ${row.cssClass}`}>
|
||||
{row.icon != null && row.icon !== '' && <span className="row-glyph">{row.icon}</span>}
|
||||
{row.text != null && linkifyToNodes(row.text)}
|
||||
{row.markdownBody != null && <MarkdownBody text={row.markdownBody} />}
|
||||
</div>
|
||||
<details className={`row ${cssClass}`} open={getExpandDetailsPref() || undefined}>
|
||||
<summary>
|
||||
{icon}
|
||||
<span className="summary-text">{row.summary}</span>
|
||||
</summary>
|
||||
{row.body_format === 'diff' && <DiffBody text={row.body} />}
|
||||
{row.body_format === 'markdown' && <MarkdownBody text={row.body} />}
|
||||
{row.body_format == null && <pre className="tool-body">{linkifyToNodes(row.body)}</pre>}
|
||||
</details>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue