Skip to content

Conversation

@iteratetograceness
Copy link
Contributor

@iteratetograceness iteratetograceness commented May 15, 2025

Background

Refactor @ai-sdk/svelte package to use new ChatStore and ChatTransport

Summary

This PR:

  1. Refactors the existing Svelte Chat class to support new Chat Store approach
  2. Introduces a State Manager (work done by @elliott-with-the-longest-name-on-github) to allow frameworks to uniquely define state + setters w/ their preferred approach

More detailed doc, written by @elliott-with-the-longest-name-on-github found here: https://www.notion.so/vercel/An-Essay-on-ai-sdk-svelte-3-and-ai-5-1fbe06b059c480e1bda6dbf3a613a0a9

As a result of 2, we refactored the React implementation as well to integrate the State Manager, where methods strictly adhere to immutability.

This also sets up the Vue refactor to be quite simple!

Verification

Tasks

  • Tests have been added / updated (for bug fixes / features)
  • Documentation has been added / updated (for bug fixes / features)
  • A patch changeset for relevant packages has been added (for bug fixes / features - run pnpm changeset in the project root)
  • Formatting issues have been fixed (run pnpm prettier-fix in the project root)

Future Work

Related Issues

@iteratetograceness iteratetograceness changed the base branch from main to v5 May 15, 2025 04:09
@iteratetograceness iteratetograceness marked this pull request as ready for review May 15, 2025 21:24
import { Chat } from '@ai-sdk/svelte';
import { defaultChatStore } from 'ai';
const chat = new Chat(() => ({
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@elliott-with-the-longest-name-on-github the chat class tests pass but i'm seeing funky behavior w/ re-rendering message part changes when running the example!

if you have time to look or if you have time to sync again tomorrow lmk!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

seems like under the hood, sveltekit's optimizations for only re-rendering when state changes doesn't account for the deeply nested message parts changes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(for context: chat store's getMessages just returns chat.messages!)

if (!this.hasChat(id)) {
throw new Error(`chat '${id}' not found`);
this.addChat(id, []);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lgrammel we decided to add this logic to the chat store itself! this resolves a concern w/ the svelte approach where upon switching chats after Chat class is initialized, new chat id's did not exist in the store


const state = createStreamingUIMessageState({
lastMessage,
lastMessage: structuredClone(lastMessage),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved structuredClone of last message out of createStreamingUIMessageState (explanation in corresponding file)

}) {
const state = createStreamingUIMessageState({
lastMessage,
lastMessage: lastMessage ? structuredClone(lastMessage) : undefined,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same comment as above

InferUIDataParts<UI_DATA_PART_SCHEMAS>
> = isContinuation
? structuredClone(lastMessage)
? lastMessage
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed because this was breaking the Svelte impl.

Quote from @elliott-with-the-longest-name-on-github:
"The problem is that structuredClone doesn't work on Svelte state (because it's a Proxy, which isn't cloneable)"

createAIContext();
const chat1 = new Chat({ chatId });
const chat2 = new Chat({ chatId });
createAIContext(defaultChatStore({ api: '/api/chat' }));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@elliott-with-the-longest-name-on-github I believe we won't need this and the corresponding store context provider anymore, but want to confirm with you!

};

export class ChatStore<
export interface ChatStateManagerFactory<
Copy link
Collaborator

Choose a reason for hiding this comment

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

lol

},
"peerDependencies": {
"svelte": "^5.0.0",
"svelte": "^5.31.0",
Copy link
Collaborator

Choose a reason for hiding this comment

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

why is this needed?

lgrammel added a commit that referenced this pull request May 26, 2025
## Background

Use the new chat store concept in Svelte to increase code reuse and
standardize.

## Summary

- refactor chat store to allow for react and svelte optimizations
- refactor initialization pattern to fix react issue with overrides on
render

## Verification

- [x] react with tool calls
- [x] svelte with tool calls

## Future Work

- vue
- refine svelte and react implementations

## Related Issues

Continues #6329

---------

Co-authored-by: Grace Yun <graceyunn@gmail.com>
Co-authored-by: Grace Yun <74513600+iteratetograceness@users.noreply.github.com>
Co-authored-by: S. Elliott Johnson <sejohnson@torchcloudconsulting.com>
@iteratetograceness
Copy link
Contributor Author

Closing, changes shipped in #6487

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.

3 participants