Skip to content

Comments

feat: add support for data-* prefixed types in messages and attachments#2

Open
adi-bradwell wants to merge 2 commits intomainfrom
feat/data-star-types-support
Open

feat: add support for data-* prefixed types in messages and attachments#2
adi-bradwell wants to merge 2 commits intomainfrom
feat/data-star-types-support

Conversation

@adi-bradwell
Copy link
Owner

@adi-bradwell adi-bradwell commented Feb 19, 2026

Summary

Adds full support for data-* prefixed types in user messages and attachments, addressing all issues from #3358.

Changes (17 files, +66 / -29)

New types (packages/core/src/types/):

  • Added DataUIPart type: { type: \data-${string}`; data: unknown; id?: string }`
  • Updated ThreadUserMessagePart union to include DataUIPart
  • Split BaseAttachment into a discriminated union: BaseFileAttachment (with required contentType: string) and BaseDataAttachment (with optional contentType?: string)

Graceful degradation in switch statements:

  • thread-message-like.ts: user handler returns data-* parts as-is (using isDataUIPart type guard); assistant handler returns null (skips)
  • MessageParts.tsx / MessagePartsGrouped.tsx: returns null for data-* parts
  • ComposerAttachments.tsx / MessageAttachments.tsx: falls back to components?.Attachment
  • auiV0.ts: skips data-* parts via return null + .filter(Boolean)
  • All downstream packages (react-a2a, react-langgraph, react-ai-sdk, ui, docs) updated

Adapter guards:

  • CompositeAttachmentAdapter.remove(): early return for data-* attachments
  • CloudFileAttachmentAdapter.send(): graceful handling when contentType is absent
  • vercelAttachmentAdapter.send(): runtime check for contentType

Exports:

  • DataUIPart exported from both @assistant-ui/core and @assistant-ui/react

Design principles

  • Add-only: no existing behavior is changed; guards are added in default cases before existing throws
  • Uses type.startsWith("data-") consistently (not "data") to avoid changing behavior for the existing bare "data" type
  • No as assertions — uses proper type guard (isDataUIPart) instead

Verified

  • All 44 build tasks pass
  • All 35 test tasks pass

Test plan

  • Full monorepo build passes (44/44 tasks)
  • Full test suite passes (35/35 tasks)
  • Verify data-* parts in user messages don't crash rendering
  • Verify data-* attachments can be created and removed without errors
  • Verify existing "data", "image", "file", etc. types continue working unchanged

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added support for custom data-* attachments and data-* message parts across messaging and UI, allowing extensible data-prefixed types to be accepted and rendered or preserved.
  • Bug Fixes

    • Improved validation for attachments with missing content type and reduced crashes by skipping or safely handling unknown data-* parts.
    • Converter now preserves specific data-* type labels for data parts.

Add DataUIPart type for custom data-* message parts (e.g. data-workflow),
update ThreadUserMessagePart union, and split BaseAttachment into a
discriminated union (BaseFileAttachment | BaseDataAttachment) so data-*
attachments can have optional contentType.

All switch statements on message part type and attachment type now
gracefully handle data-* prefixed types instead of throwing. Encoding
functions skip them, rendering components return null or fall back to
a generic component.

Closes assistant-ui#3358

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

📝 Walkthrough

Walkthrough

Adds explicit support for data-* prefixed attachment and message-part types across types, runtimes, adapters, and UI: new discriminated types and guards let data- parts be recognized, skipped, or handled instead of triggering exhaustive-type errors.

Changes

Cohort / File(s) Summary
Type system & exports
packages/core/src/types/attachment.ts, packages/core/src/types/message.ts, packages/core/src/types/index.ts, packages/react/src/types/index.ts
Adds DataAttachmentType/FileAttachmentType, BaseDataAttachment/BaseFileAttachment, DataUIPart type; updates unions and re-exports to include data- UI parts.
Runtime message utilities
packages/core/src/runtime/utils/thread-message-like.ts
Adds isDataUIPart guard; includes DataUIPart in ThreadMessageLike content union; adjusts assistant/user part handling to skip or pass through data- parts.
Adapters & attachment logic
packages/core/src/adapters/attachment.ts, packages/react-ai-sdk/src/ui/utils/vercelAttachmentAdapter.ts, packages/react/src/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.ts
Early returns for data-* attachments in remove/send flows; require/validate contentType where relevant; avoid creating content for attachments missing contentType.
UI attachment rendering
apps/docs/components/legacy/attachment-old.tsx, packages/ui/src/components/assistant-ui/attachment.tsx, packages/react/src/primitives/composer/ComposerAttachments.tsx, packages/react/src/primitives/message/MessageAttachments.tsx
Switch/default branches updated to allow data-* attachment types to render (or be used as labels) instead of throwing unknown-type errors.
Message part rendering
packages/react/src/primitives/message/MessageParts.tsx, packages/react/src/primitives/message/MessagePartsGrouped.tsx
Default cases now return null for data-* message parts, filtering/skipping them rather than throwing unhandled-type errors.
Message conversion & runtime guards
packages/react-ai-sdk/src/ui/utils/convertMessage.ts, packages/react-a2a/src/useA2ARuntime.ts, packages/react-langgraph/src/useLangGraphRuntime.ts, packages/react/src/legacy-runtime/cloud/auiV0.ts, apps/docs/components/legacy/attachment-old.tsx
Converters and getMessageContent/encoding paths now check for data-* prefixes: convert uses the specific data- type as the discriminator; runtimes either throw early for unsupported data- types or return/filter them instead of relying on exhaustive-check fallthroughs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A tiny hop for code and type,
I sniffed out data- in the night,
Now parts that once would cause a fright
Are handled gentle, quiet, light—
A rabbit cheers: the build runs right! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and concisely summarizes the main change: adding support for data-* prefixed types across messages and attachments, which aligns with all 17 modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/data-star-types-support

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

The converter was replacing `type: "data-attachment"` with `type: "data"`,
losing the original type discriminator. Now passes through part.type as-is
so the format stays consistent with AI SDK v5 DataUIPart<T>.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/react-ai-sdk/src/ui/utils/convertMessage.ts (1)

143-149: ⚠️ Potential issue | 🔴 Critical

Type mismatch: code cannot satisfy DataMessagePart with template literal types.

The code at line 145 assigns type: part.type (where part.type is a value like "data-attachment" matching data-${string}), but uses satisfies DataMessagePart which requires type: "data" as a literal string. These are incompatible:

  • DataMessagePart.type is defined as the literal "data"
  • DataUIPart.type is defined as data-${string}

The object being returned matches DataUIPart, not DataMessagePart. Either change the assertion to satisfies DataUIPart (though this removes the name field) or revert to hardcoding type: "data" to match the actual DataMessagePart contract. The current code has a type incompatibility.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-ai-sdk/src/ui/utils/convertMessage.ts` around lines 143 - 149,
The returned object in convertMessage.ts inside the branch if
(part.type.startsWith("data-")) currently uses part.type (e.g.,
"data-attachment") but asserts satisfies DataMessagePart which requires type:
"data"; fix this by making the returned object's type property the literal
"data" (keep name: part.type.substring(5) and data: (part as any).data) so the
shape truly matches DataMessagePart, and keep the satisfies DataMessagePart
assertion; update the object returned in that branch accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/react-ai-sdk/src/ui/utils/convertMessage.ts`:
- Around line 143-149: The returned object in convertMessage.ts inside the
branch if (part.type.startsWith("data-")) currently uses part.type (e.g.,
"data-attachment") but asserts satisfies DataMessagePart which requires type:
"data"; fix this by making the returned object's type property the literal
"data" (keep name: part.type.substring(5) and data: (part as any).data) so the
shape truly matches DataMessagePart, and keep the satisfies DataMessagePart
assertion; update the object returned in that branch accordingly.

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