Skip to content

Conversation

@chaxus
Copy link
Contributor

@chaxus chaxus commented Nov 25, 2025

Description

I encountered a use case similar to the one described in #89, where I need to persist chat messages. This requires the ability to upload files attached via the Prompt Input component.

Currently, the component provides file metadata like id, type, url (a local object URL), mediaType, and filename. However, these properties are insufficient for actual file persistence because:

  • The url is a temporary blob link that becomes invalid after the session.

  • We lack access to the actual File object, which is required to upload the file data to a server or persistent storage.

Proposed Solution

I would like to suggest exposing the file property from the component. This would allow users to access the File object directly during the onSubmit event.

With access to the file data, we can then handle the file upload and storage independently, fitting it into our own persistence layer.

Benefits

Flexibility: Enables developers to implement custom file upload workflows.

Persistence: Supports use cases where messages (and their associated files) need to be saved permanently.

This is just a suggestion from my perspective, and I believe it would be a helpful addition for others with similar needs. Thank you for considering it!

@vercel
Copy link
Contributor

vercel bot commented Nov 25, 2025

@chaxus is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

@chaxus chaxus changed the title feat(prompt-input): add file property to attachment messages for pers… feat(prompt-input): Add file property to attachment messages for persistent storage Nov 25, 2025
Copy link
Contributor

@vercel vercel bot left a comment

Choose a reason for hiding this comment

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

Additional Suggestions:

  1. The PromptInputMessage type is not updated to reflect that the files now include the file property. This creates a type mismatch between what's actually passed to onSubmit and what the type signature declares.
View Details
📝 Patch Details
diff --git a/packages/elements/src/prompt-input.tsx b/packages/elements/src/prompt-input.tsx
index f00cbac..62e2874 100644
--- a/packages/elements/src/prompt-input.tsx
+++ b/packages/elements/src/prompt-input.tsx
@@ -415,7 +415,7 @@ export const PromptInputActionAddAttachments = ({
 
 export type PromptInputMessage = {
   text: string;
-  files: FileUIPart[];
+  files: (FileUIPart & { file: File })[];
 };
 
 export type PromptInputProps = Omit<
@@ -708,7 +708,7 @@ export const PromptInput = ({
         }
         return item;
       })
-    ).then((convertedFiles: FileUIPart[]) => {
+    ).then((convertedFiles: (FileUIPart & { file: File })[]) => {
       try {
         const result = onSubmit({ text, files: convertedFiles }, event);
 

Analysis

Type mismatch: PromptInputMessage doesn't reflect file property passed at runtime

What fails: The PromptInputMessage type declares files: FileUIPart[] but the actual data passed to the onSubmit callback includes (FileUIPart & { file: File })[]. This creates a type-runtime mismatch where the file property is accessible at runtime but TypeScript type-checking rejects access to it.

How to reproduce: Create a PromptInput component with an onSubmit handler that attempts to access the file property:

 
/>

Result: TypeScript compiler error when accessing message.files[0].file - "Property 'file' does not exist on type 'FileUIPart'". However, at runtime the file property IS present because the data transformation in handleSubmit (lines 702-704) preserves it through destructuring and spreading.

Expected behavior: Developers should be able to access the file property on objects in message.files without TypeScript errors, matching the actual runtime behavior. The files stored in the component (line 472) are explicitly typed as (FileUIPart & { id: string; file: File })[], and this property is preserved through the transformation before being passed to onSubmit.

2. The `PromptInputAttachmentsProps` type\'s children function signature doesn\'t include the `file` property\, but the actual attachment objects passed at line 385 now include it\.
View Details
📝 Patch Details
diff --git a/packages/elements/src/prompt-input.tsx b/packages/elements/src/prompt-input.tsx
index f00cbac..c3cdfb3 100644
--- a/packages/elements/src/prompt-input.tsx
+++ b/packages/elements/src/prompt-input.tsx
@@ -362,7 +362,7 @@ export type PromptInputAttachmentsProps = Omit<
   HTMLAttributes<HTMLDivElement>,
   "children"
 > & {
-  children: (attachment: FileUIPart & { id: string }) => ReactNode;
+  children: (attachment: FileUIPart & { id: string; file: File }) => ReactNode;
 };
 
 export function PromptInputAttachments({

Analysis

Type mismatch in PromptInputAttachmentsProps children function signature

What fails: The PromptInputAttachmentsProps type's children function is declared to receive (attachment: FileUIPart & { id: string }), but at line 384-385 in PromptInputAttachments(), the component passes attachment objects from attachments.files which are typed as (FileUIPart & { id: string, file: File })[]. This creates a type mismatch where the file property is not included in the children function's type signature.

How to reproduce:

  1. Open packages/elements/src/prompt-input.tsx
  2. Notice that AttachmentsContext.files (line 78) is typed as (FileUIPart & { id: string, file: File })[]
  3. Notice that PromptInputAttachmentsProps.children (line 365) is typed to accept FileUIPart & { id: string } - missing the file: File property
  4. At line 384, attachments.files.map((file) => children(file)) passes objects with the file property to a function that doesn't expect it

Result: TypeScript would show a type error when attempting to call children(file) because the file object has extra properties not included in the children function's parameter type. Developers cannot access the file property from the attachment without bypassing type safety.

Expected: The children function should accept the full type signature: (attachment: FileUIPart & { id: string; file: File }) => ReactNode, matching what is actually passed to it.

Fix applied: Updated the PromptInputAttachmentsProps type to include file: File in the children function signature to match the actual attachment objects being passed.

3. The `PromptInputAttachmentProps` type doesn\'t include the `file` property\, but the component might receive it from parent components that now include this property\.
View Details
📝 Patch Details
diff --git a/packages/elements/src/prompt-input.tsx b/packages/elements/src/prompt-input.tsx
index f00cbac..774aabe 100644
--- a/packages/elements/src/prompt-input.tsx
+++ b/packages/elements/src/prompt-input.tsx
@@ -263,7 +263,7 @@ export const usePromptInputAttachments = () => {
 };
 
 export type PromptInputAttachmentProps = HTMLAttributes<HTMLDivElement> & {
-  data: FileUIPart & { id: string };
+  data: FileUIPart & { id: string; file: File };
   className?: string;
 };
 
@@ -362,7 +362,7 @@ export type PromptInputAttachmentsProps = Omit<
   HTMLAttributes<HTMLDivElement>,
   "children"
 > & {
-  children: (attachment: FileUIPart & { id: string }) => ReactNode;
+  children: (attachment: FileUIPart & { id: string; file: File }) => ReactNode;
 };
 
 export function PromptInputAttachments({

Analysis

Missing file property in PromptInputAttachmentProps type

What fails: PromptInputAttachmentProps.data and PromptInputAttachmentsProps.children parameter types don't include the file property that was added to internal attachment state in commit 2ce0bef.

How to reproduce:

// In PromptInputAttachment component
const fileSize = data.file.size; // TypeScript error: Property 'file' does not exist

What happened: TypeScript error when trying to access the file property because the type declaration doesn't include it.

Expected: Since commit 2ce0bef ("feat(prompt-input): add file property to attachment messages for persistent storage") added the file property to AttachmentsContext.files, local state, and both provider and local PromptInput state, the public component prop types should also include it for type consistency and API completeness.

Context: The file property is available at runtime but hidden from the type signature due to TypeScript's width subtyping (allowing wider types to be used where narrower types are expected). However, for type safety and consistency with the internal state types, the component props should accurately reflect what properties are available.

Fix on Vercel

@chaxus chaxus closed this Nov 25, 2025
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