Skip to content

[Dev UI] refactor: decompose convertPartsToDomNodes in MessageRenderingService #6279

Description

@MichaelDoyle

Problem

MessageRenderingService.convertPartsToDomNodes in src/app/services/message-rendering.service.ts has grown to ~140 lines (~30% of the service) and combines multiple competing responsibilities in a single procedural loop:

  1. 12-branch if / else if dispatch ladder: Dispatches across text, reasoning, 5 media variants, toolRequest, resource, custom, a2ui, and fallback data.
  2. Imperative loop mutation (i += consumed): Inside the render loop, combineAdjacentStringParts mutates the loop index i mid-flight to coalesce streaming chunks. This couples stream normalization with DOM construction and makes index tracking fragile alongside index-dependent lookups (such as A2UI surface anchoring and leftovers mapping).
  3. Disproportionate complexity: Complex protocol logic (such as A2UI surface card anchoring, container reshaping, and leftovers fallback) lives inline inside the loop body.

Proposed Solution

Adopt a phased pipeline similar to the strategy pattern used for trace previews in src/app/components/json-viewer/render-types:

  1. Upstream Normalization Pass:
    • Introduce a pure, framework-agnostic normalizeParts(parts: Part[]): Part[] helper that coalesces adjacent string parts (text/reasoning lacking metadata) upfront.
    • Eliminates lookaheads, consumed counters, and i += consumed index mutations during rendering.
  2. Modular Part Renderers / Strategies:
    • Extract individual branch logic into dedicated renderers/helpers (e.g., A2uiPartRenderer, MediaPartRenderer, TextPartRenderer).
    • Replace the 12-branch ladder with an ordered registry of handlers (canRender(part) / render(part, context)).

Benefits

  • Testability: Normalization and individual part handlers can be unit-tested in isolation without full Angular component/DOM harnesses.
  • Maintainability & OCP: Adding support for future part types will no longer require expanding the central render loop.
  • Safer Iteration: Removes manual loop pointer manipulation and cleanly decouples stream parsing from DOM generation.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions