Skip to content

[AI-stack FB2] fresh-ui: chat-render item (parseBlocks/blockToText + RenderPart reload fidelity) #255

Description

@rickylabs

Add a chat-render fresh-ui item that parses fenced chart/donut/table/stats/line blocks out of assistant markdown into a typed RenderPart[] tree, guaranteed to reload byte-identical.

Context

Part of epic #238 · cluster fresh-ui · wave v1-min · depends-on FB0, FA1.

This sits directly downstream of FB0 (the chat-primitive manifest registration) and FA1 (the
message/part contract in @netscript/fresh/ai); it is the first slice that turns raw assistant
text into renderable design-system output, and every later generative-UI slice (FB5's recursive
JSON renderer, the eventual chat page assembly) parses through this seam rather than re-inventing
block detection.

Problem / motivation

Today there is no supported path from an LLM response to a rendered chart, donut, table, stats
block, or line chart in fresh-ui. eis-chat's prior art hand-rolls markdown-fence sniffing and
string-templates the result straight into JSX per call site, with no shared parser, no reload
guarantee, and no seam other pages can reuse. Doctrine requires generative UI to be owned by
fresh-ui's curated vocabulary (not ad-hoc per-app parsing), and FB0 only registers the primitives —
nothing yet turns model output into instances of them. Without this slice, FB0's primitives are
inert copy-paste components with no ingestion path.

Scope

Ships

  • packages/fresh-ui/src/chat/parse-blocks.ts (or equivalent src/chat/ module) exporting:
    • parseBlocks(input: string): RenderPart[]
    • blockToText(part: RenderPart): string (the inverse projection used for the reload check and
      for plain-text fallback/export)
    • the RenderPart discriminated union (chart, donut, table, stats, line, and a text
      fallback member for non-fenced prose)
  • Fenced-block grammar recognizing chart, donut, table, stats, ```line info-strings,
    parsing their body (JSON or the minimal DSL agreed with FA1's message contract) into the
    corresponding DS primitive's prop shape (ChartDatum[], table rows/columns, stats entries).
  • Reload-fidelity guarantee: parseBlocks(blockToText(parseBlocks(input))) produces a RenderPart[]
    deep-equal to the first parse, for every fixture covering the five block kinds plus mixed
    text+block input.
  • Unit tests under packages/fresh-ui/tests/chat/parse-blocks.test.ts covering each block kind,
    malformed-fence fallback to text, and the roundtrip-fidelity property.

Out of scope

  • Recursive/nested JSON-driven generic renderer — owned by FB5.
  • Registering the chat primitives themselves in the manifest/ai collection — owned by FB0.
  • The message/part wire contract and streaming assembly — owned by FA1 (fresh/ai).
  • Actually mounting RenderPart[] into a chat page/island — deferred to a later fresh-ui chat-page
    slice, not this one.

Public surface

  • New exports (subject to final file layout, all under packages/fresh-ui/src/chat/):
    parseBlocks, blockToText, RenderPart, and the per-kind part interfaces
    (ChartRenderPart, DonutRenderPart, TableRenderPart, StatsRenderPart, LineRenderPart,
    TextRenderPart).
  • New registry manifest item chat-render (kind lib, copyOwnership: app-owned-after-copy) added
    to the ai collection created by FB0, with files pointing at the shipped module(s) and
    dependencies on the existing chart/donut/table/stats primitive items.

Acceptance & fitness gates

  • F-5: public surface has @module + JSDoc on every exported symbol; parse-blocks.ts mod
    export count stays at or under the 20-export limit.
  • F-6: deno task publish:dry-run succeeds for @netscript/fresh-ui WITHOUT
    --allow-slow-types after this slice lands.
  • F-3: deno task arch:check passes — the parser stays a pure domain/application module with no
    new adapter-layer or @netscript/* runtime dependency.
  • Fidelity: a fixture-driven regression proves parseBlocks -> blockToText -> parseBlocks yields
    a deep-equal RenderPart[] for chart, donut, table, stats, and line blocks, plus one mixed
    text+multi-block fixture.
  • deno task check and deno task test pass scoped to packages/fresh-ui.
  • netscript ui:add ai (registered by FB0) resolves and includes chat-render alongside the
    chat primitive items it depends on.

Dependencies

Depends on FB0 (chat-primitive manifest registration, ai collection) and FA1 (fresh/ai
message/part contract) — GitHub numbers tracked in the #238 DAG checklist. Not blocked by #239.

Size

M

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions