Skip to content

feat(chat,board): historicalToUnified + scripted-stream replay + standalone TicketCardView#1460

Merged
michaelassraf merged 2 commits into
mainfrom
feat/hero-demo-lib-followups
Jul 15, 2026
Merged

feat(chat,board): historicalToUnified + scripted-stream replay + standalone TicketCardView#1460
michaelassraf merged 2 commits into
mainfrom
feat/hero-demo-lib-followups

Conversation

@michaelassraf

@michaelassraf michaelassraf commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

What

Lib primitives backing the multi-platform-hub hero agent demos (hub #848), extracted so the hub carries no duplicated chat/ticket logic. (Supersedes the changes that were on the already-merged #1459 branch — this is a fresh PR off current main.)

Changes

  • historicalToUnified (use-nats-chat-adapter.ts) — one-call HistoricalMessage[]UnifiedChatMessage[] (rehydrate + unified-map + identity re-attach), so a host replaying a stored conversation doesn't hand-roll the two-step.
  • Scripted-stream replay engine (utils/scripted-stream.ts + hooks/use-scripted-stream.ts) — buildStreamFrames turns a HistoricalMessage[] into mock-SSE playback frames (thinking → token-by-token → tool/approval → idle); useScriptedStream is the playback clock. Moved out of the hub so any consumer (marketing heroes, docs, tours) can drive a previewMode chat from a canned conversation.
  • TicketCardView / TicketCardBody (board/ticket-card.tsx) — extracted the real board ticket-card design into a presentational component with no useSortable/dnd dependency, so /tickets?viewMode=board's exact card renders standalone from static props (off-board embeds, hero mocks). TicketCard (draggable) now composes TicketCardBody; behavior unchanged.

Notes

  • Additive + backward-compatible: new exports only; TicketCard's public API and rendering are unchanged.
  • Consumed by hub update login page #848 (which pins the lib and will bump to the release cut from this).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added scripted chat playback that simulates live streaming, typing indicators, thinking states, and reduced-motion support.
    • Added tools for replaying historical conversations in a unified chat format.
    • Added reusable static and draggable ticket card views for flexible board and preview layouts.
    • Expanded ticket card displays with shared content for titles, assignments, tags, timestamps, messages, and approvals.
  • Improvements

    • Updated chat and board components to make these capabilities available through their public interfaces.

…rdView

- scripted-stream: buildStreamFrames + useScriptedStream (mock-SSE replay of a
  HistoricalMessage[], moved out of the hub so any consumer can drive a
  previewMode chat from a canned conversation)
- extract TicketCardBody + TicketCardView (the real board ticket-card design,
  standalone, no useSortable/dnd) so it renders from static props off-board [preview:none]
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds deterministic scripted chat playback and historical-message conversion helpers, and refactors board ticket cards into reusable body and static-view components while preserving draggable behavior and adapting approval callbacks.

Changes

Chat playback and historical conversion

Layer / File(s) Summary
Scripted stream frame generation
openframe-frontend-core/src/components/chat/utils/scripted-stream.ts, openframe-frontend-core/src/components/chat/utils/index.ts
Historical messages are normalized into deterministic thinking, streaming, idle, and non-text playback frames with token-preserving timing behavior.
Scripted stream playback hook
openframe-frontend-core/src/components/chat/hooks/use-scripted-stream.ts, openframe-frontend-core/src/components/chat/hooks/index.ts
useScriptedStream advances frames by delay, handles reset keys and frame-size changes, supports reduced motion, and is publicly re-exported.
Historical message conversion
openframe-frontend-core/src/components/chat/hooks/use-nats-chat-adapter.ts
historicalToUnified processes historical messages, maps them to unified messages, and restores author identity fields.

Ticket card composition

Layer / File(s) Summary
Shared ticket card body and static view
openframe-frontend-core/src/components/features/board/ticket-card.tsx
Ticket card presentation is extracted into TicketCardBody and TicketCardView; approval callbacks use request IDs and approved checkmark rendering is removed.
Draggable card integration and exports
openframe-frontend-core/src/components/features/board/ticket-card.tsx, openframe-frontend-core/src/components/features/board/index.ts
The draggable card composes the shared body while retaining sortable wrappers, and the board barrel exports the new components and prop types.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant HistoricalMessage
  participant buildStreamFrames
  participant useScriptedStream
  participant ChatSurface
  HistoricalMessage->>buildStreamFrames: historical messages
  buildStreamFrames->>useScriptedStream: StreamFrame array
  useScriptedStream->>ChatSurface: current frame after delayMs
Loading

Possibly related PRs

Suggested reviewers: pavlo-flamingo

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main additions: historical conversion, scripted stream replay, and standalone TicketCardView.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/hero-demo-lib-followups

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@michaelassraf
michaelassraf merged commit 5216b20 into main Jul 15, 2026
6 of 7 checks passed
@michaelassraf
michaelassraf deleted the feat/hero-demo-lib-followups branch July 15, 2026 22:24

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
openframe-frontend-core/src/components/chat/utils/scripted-stream.ts (1)

63-111: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add unit tests for buildStreamFrames.

This pure function has several branches (user vs. assistant turns, thinking-pause gating, per-token streaming, tool/approval segment pop-in, empty-message fallback) and an explicitly documented invariant (frame-count determinism for a stable prefix) that's easy to regress silently. Worth covering with deterministic unit tests, especially the tokenize-reconstruction and prefix-stability guarantees.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openframe-frontend-core/src/components/chat/utils/scripted-stream.ts` around
lines 63 - 111, Add deterministic unit tests covering buildStreamFrames for user
and assistant turns, thinking-pause gating, per-token text streaming with
tokenize reconstruction, tool/approval segment pop-in, and the empty-message
fallback. Include assertions for frame-count determinism when extending a stable
message prefix, and verify each frame’s messages, phase, typing, and delayMs
values without changing the implementation.
openframe-frontend-core/src/components/features/board/ticket-card.tsx (1)

50-51: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

showNewMessage computation is duplicated across three components.

The same !!ticket.hasNewMessage && !!columnColor expression is recomputed independently here, in TicketCardView (Line 148), and in TicketCard (Line 191). Extracting a small shared helper would prevent future drift if the condition ever changes.

♻️ Suggested helper extraction
+function shouldShowNewMessage(ticket: BoardTicket, columnColor?: string): boolean {
+  return !!ticket.hasNewMessage && !!columnColor
+}
+
 export function TicketCardBody({ ticket, columnColor, renderAssignSlot, onApprove, onReject }: TicketCardBodyProps) {
-  const showNewMessage = !!ticket.hasNewMessage && !!columnColor
+  const showNewMessage = shouldShowNewMessage(ticket, columnColor)

Apply the same replacement at Line 148 (TicketCardView) and Line 191 (TicketCard).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openframe-frontend-core/src/components/features/board/ticket-card.tsx` around
lines 50 - 51, Extract the shared showNewMessage condition into a small helper
and replace the duplicated expressions in the current component plus
TicketCardView and TicketCard. Ensure all three call sites use the helper while
preserving the existing boolean behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@openframe-frontend-core/src/components/chat/utils/scripted-stream.ts`:
- Around line 63-111: Add deterministic unit tests covering buildStreamFrames
for user and assistant turns, thinking-pause gating, per-token text streaming
with tokenize reconstruction, tool/approval segment pop-in, and the
empty-message fallback. Include assertions for frame-count determinism when
extending a stable message prefix, and verify each frame’s messages, phase,
typing, and delayMs values without changing the implementation.

In `@openframe-frontend-core/src/components/features/board/ticket-card.tsx`:
- Around line 50-51: Extract the shared showNewMessage condition into a small
helper and replace the duplicated expressions in the current component plus
TicketCardView and TicketCard. Ensure all three call sites use the helper while
preserving the existing boolean behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f2fc5d9d-42c8-4246-a74e-bce97a50a89c

📥 Commits

Reviewing files that changed from the base of the PR and between d0b04e8 and 8cf5f17.

📒 Files selected for processing (7)
  • openframe-frontend-core/src/components/chat/hooks/index.ts
  • openframe-frontend-core/src/components/chat/hooks/use-nats-chat-adapter.ts
  • openframe-frontend-core/src/components/chat/hooks/use-scripted-stream.ts
  • openframe-frontend-core/src/components/chat/utils/index.ts
  • openframe-frontend-core/src/components/chat/utils/scripted-stream.ts
  • openframe-frontend-core/src/components/features/board/index.ts
  • openframe-frontend-core/src/components/features/board/ticket-card.tsx

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant