feat(a2ui-playground): share whole conversation instead of final result#2795
Conversation
The per-conversation Share button used to copy a render.html link that only showed the final generated UI. It now serializes the entire conversation (transcript + data-model snapshot), uploads it via the existing Supabase payload endpoint, and builds an `?importConv=<url>` link. Opening that link rehydrates the conversation into the recipient's playground as a fresh local conversation, so they can read every prompt -> result turn and continue chatting from there. The shared document keeps each message's content and the snapshot dataModel -- exactly what the agent needs to restore its ConversationContext (history + a dataModel system message) on the next turn. The redundant previewMessages render cache is dropped and rebuilt from history on import to stay under the server body-size limit. Changes: - storage/sharedConversation.ts (new): SharedConversationDoc, serializeConversation, isSharedConversationDoc - utils/shareConversation.ts (new): publishConversation, buildConversationShareUrl, import-param helpers - storage/conversationRepo.ts: importConversation() - hooks/useConversation.ts: importShared() - pages/AIChatPage.tsx: rewritten share handler + one-time import effect - components/ConversationListPanel.tsx: relabel share button
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughImplements full conversation sharing: a versioned shared document format, serialization and publish utilities, repository import to persist shared docs, a new ChangesShared Conversation Import and Export
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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.
Inline comments:
In `@packages/genui/a2ui-playground/src/hooks/useConversation.ts`:
- Around line 459-494: The in-memory branch in useConversation.ts (inside the
!persistentRef.current block) creates meta without previewText, causing empty
previews; fix it by importing and invoking previewTextFromSharedMessages (from
conversationRepo.ts) the same way importConversation does and set
meta.previewText = previewTextFromSharedMessages(doc.messages) when building
ConversationMeta (alongside messageCount); this ensures the previewText is
populated for the in-memory path and mirrors the persistent import behavior.
In `@packages/genui/a2ui-playground/src/storage/sharedConversation.ts`:
- Around line 89-99: The runtime guard is only checking top-level fields in
isSharedConversationDoc (checking kind, v and Array.isArray(doc.messages)), so
malformed entries in doc.messages can slip through and later crash import;
update isSharedConversationDoc to validate each entry of doc.messages (for the
SharedConversationDoc message shape) by ensuring every element is a non-null
object and has the required properties and correct types (e.g., message id if
present, role/sender as string/enum, content as string or expected content
structure, timestamp as number/ISO-string if used), returning false if any
element fails, while keeping the existing checks for SHARED_CONVERSATION_KIND
and v === 1.
In `@packages/genui/a2ui-playground/src/utils/shareConversation.ts`:
- Around line 48-54: The current clearImportConversationParam function drops the
whole query string; instead, read the current URLSearchParams, delete only the
"importConv" key (use readImportConversationParam to guard), reconstruct the
query string from the remaining params and preserve window.location.hash, then
call window.history.replaceState (same usage as in the diff) with pathname +
(params.toString() ? '?' + params.toString() : '') + window.location.hash so
other query params remain intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 135cac4c-9135-420f-91ec-ecf4e80dfd7b
📒 Files selected for processing (6)
packages/genui/a2ui-playground/src/components/ConversationListPanel.tsxpackages/genui/a2ui-playground/src/hooks/useConversation.tspackages/genui/a2ui-playground/src/pages/AIChatPage.tsxpackages/genui/a2ui-playground/src/storage/conversationRepo.tspackages/genui/a2ui-playground/src/storage/sharedConversation.tspackages/genui/a2ui-playground/src/utils/shareConversation.ts
Merging this PR will not alter performance
Comparing Footnotes
|
- isSharedConversationDoc: validate each message entry (role + string content), not just the top-level shape, so a malformed shared document is rejected before import instead of crashing later. - clearImportConversationParam: delete only the importConv param and preserve other query params (e.g. a2uiEndpoint) and the hash. - importShared (in-memory fallback): populate previewText via previewTextFromSharedMessages so the conversation-list preview matches the persistent import path when IndexedDB is unavailable.
The per-conversation Share button used to copy a render.html link that only showed the final generated UI. It now serializes the entire conversation (transcript + data-model snapshot), uploads it via the existing Supabase payload endpoint, and builds an
?importConv=<url>link. Opening that link rehydrates the conversation into the recipient's playground as a fresh local conversation, so they can read every prompt -> result turn and continue chatting from there.The shared document keeps each message's content and the snapshot dataModel -- exactly what the agent needs to restore its ConversationContext (history + a dataModel system message) on the next turn. The redundant previewMessages render cache is dropped and rebuilt from history on import to stay under the server body-size limit.
Changes:
Summary by CodeRabbit
Release Notes
Checklist