@v0-sdk/react 0.5.1 → 3.0.0-canary.9ae7b76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -256
- package/dist/index-Byqc8Ogm.d.cts +111 -0
- package/dist/index-Byqc8Ogm.d.cts.map +1 -0
- package/dist/index-CknrgtQb.d.mts +111 -0
- package/dist/index-CknrgtQb.d.mts.map +1 -0
- package/dist/index.cjs +2 -1252
- package/dist/index.d.cts +3 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +4 -0
- package/dist/index.mjs.map +1 -0
- package/dist/request-C1Ues3qu.cjs +1 -0
- package/dist/request-enP5rNQ_.mjs +2 -0
- package/dist/request-enP5rNQ_.mjs.map +1 -0
- package/dist/swr.cjs +1 -0
- package/dist/swr.d.cts +1009 -0
- package/dist/swr.d.cts.map +1 -0
- package/dist/swr.d.mts +1009 -0
- package/dist/swr.d.mts.map +1 -0
- package/dist/swr.mjs +2 -0
- package/dist/swr.mjs.map +1 -0
- package/package.json +66 -44
- package/dist/index.d.ts +0 -594
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -1203
package/README.md
CHANGED
|
@@ -1,299 +1,126 @@
|
|
|
1
1
|
# @v0-sdk/react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React hooks for building apps with the v0 API.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Install
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
For the AI SDK transport:
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- **Zero DOM dependencies** - No `react-dom` required
|
|
13
|
-
- **Streaming support** - Real-time message streaming with `useStreamingMessage`
|
|
14
|
-
- **Backward compatible** - Drop-in replacement for existing implementations
|
|
9
|
+
```sh
|
|
10
|
+
npm install @v0-sdk/react react ai @ai-sdk/react
|
|
11
|
+
```
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
Add SWR when using the generated API hooks:
|
|
17
14
|
|
|
18
|
-
```
|
|
19
|
-
npm install @v0-sdk/react
|
|
20
|
-
# or
|
|
21
|
-
yarn add @v0-sdk/react
|
|
22
|
-
# or
|
|
23
|
-
pnpm add @v0-sdk/react
|
|
15
|
+
```sh
|
|
16
|
+
npm install @v0-sdk/react react swr
|
|
24
17
|
```
|
|
25
18
|
|
|
26
|
-
##
|
|
19
|
+
## Getting started
|
|
27
20
|
|
|
28
|
-
|
|
21
|
+
Create backend routes that authenticate with the server-side `v0` SDK, then pass those route URLs to the hooks. For example, this Next.js route proxies a streaming message request while keeping `V0_API_KEY` on the server:
|
|
29
22
|
|
|
30
|
-
```
|
|
31
|
-
|
|
23
|
+
```ts
|
|
24
|
+
// app/api/v0/chats/[chatId]/messages/stream/route.ts
|
|
25
|
+
import { v0 } from 'v0'
|
|
32
26
|
|
|
33
|
-
function
|
|
34
|
-
|
|
35
|
-
<Message
|
|
36
|
-
content={content}
|
|
37
|
-
messageId="msg-1"
|
|
38
|
-
role="assistant"
|
|
39
|
-
className="my-message"
|
|
40
|
-
/>
|
|
41
|
-
)
|
|
42
|
-
}
|
|
27
|
+
export async function POST(request: Request, { params }: { params: Promise<{ chatId: string }> }) {
|
|
28
|
+
// Perform your own authentication and validation
|
|
43
29
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
onComplete={(content) => console.log('Complete:', content)}
|
|
51
|
-
/>
|
|
52
|
-
)
|
|
30
|
+
const { chatId } = await params
|
|
31
|
+
const body = await request.json()
|
|
32
|
+
|
|
33
|
+
const result = await v0.messages.sendStream({ chatId, ...body })
|
|
34
|
+
|
|
35
|
+
return result.toResponse()
|
|
53
36
|
}
|
|
54
37
|
```
|
|
55
38
|
|
|
56
|
-
|
|
39
|
+
The client can call that route with the corresponding hook:
|
|
57
40
|
|
|
58
41
|
```tsx
|
|
59
|
-
import {
|
|
60
|
-
import { Text, View } from 'react-native' // or any other renderer
|
|
42
|
+
import { useChat, useMessages, useSendMessage } from '@v0-sdk/react/swr'
|
|
61
43
|
|
|
62
|
-
function
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
role: 'assistant',
|
|
44
|
+
export function Chat({ chatId }: { chatId: string }) {
|
|
45
|
+
const chat = useChat(`/api/v0/chats/${chatId}`)
|
|
46
|
+
const messages = useMessages(`/api/v0/chats/${chatId}/messages`, {
|
|
47
|
+
limit: 50,
|
|
67
48
|
})
|
|
49
|
+
const send = useSendMessage(`/api/v0/chats/${chatId}/messages/stream`)
|
|
68
50
|
|
|
69
|
-
|
|
70
|
-
<
|
|
71
|
-
{messageData.elements.map((element) => (
|
|
72
|
-
<Text key={element.key}>
|
|
73
|
-
{element.type === 'text' ? element.data : JSON.stringify(element)}
|
|
74
|
-
</Text>
|
|
75
|
-
))}
|
|
76
|
-
</View>
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function HeadlessStreamingMessage({ stream }) {
|
|
81
|
-
const streamingData = useStreamingMessageData({
|
|
82
|
-
stream,
|
|
83
|
-
messageId: 'streaming-msg',
|
|
84
|
-
role: 'assistant',
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
if (streamingData.error) {
|
|
88
|
-
return <Text style={{ color: 'red' }}>Error: {streamingData.error}</Text>
|
|
51
|
+
if (chat.isLoading || messages.isLoading) {
|
|
52
|
+
return <p>Loading…</p>
|
|
89
53
|
}
|
|
90
54
|
|
|
91
|
-
if (
|
|
92
|
-
return <
|
|
55
|
+
if (chat.error || messages.error) {
|
|
56
|
+
return <p>Unable to load the chat.</p>
|
|
93
57
|
}
|
|
94
58
|
|
|
95
59
|
return (
|
|
96
|
-
<
|
|
97
|
-
{
|
|
98
|
-
<Text key={element.key}>
|
|
99
|
-
{element.type === 'text' ? element.data : JSON.stringify(element)}
|
|
100
|
-
</Text>
|
|
101
|
-
))}
|
|
102
|
-
</View>
|
|
103
|
-
)
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Ink CLI Example
|
|
60
|
+
<main>
|
|
61
|
+
<h1>{chat.data?.title}</h1>
|
|
108
62
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
import { Text, Box } from 'ink'
|
|
112
|
-
|
|
113
|
-
function CliMessage({ content }) {
|
|
114
|
-
const messageData = useMessage({
|
|
115
|
-
content,
|
|
116
|
-
messageId: 'cli-msg',
|
|
117
|
-
role: 'assistant',
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
return (
|
|
121
|
-
<Box flexDirection="column">
|
|
122
|
-
{messageData.elements.map((element) => (
|
|
123
|
-
<Text key={element.key}>
|
|
124
|
-
{element.type === 'text' ? element.data : `[${element.type}]`}
|
|
125
|
-
</Text>
|
|
63
|
+
{messages.data?.messages.map((message) => (
|
|
64
|
+
<article key={message.id}>{message.content}</article>
|
|
126
65
|
))}
|
|
127
|
-
</Box>
|
|
128
|
-
)
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
## Available Hooks
|
|
133
|
-
|
|
134
|
-
### Core Hooks
|
|
135
|
-
|
|
136
|
-
- `useMessage(props)` - Process message content into headless data structure
|
|
137
|
-
- `useStreamingMessageData(props)` - Handle streaming messages with real-time updates
|
|
138
|
-
- `useStreamingMessage(stream, options)` - Low-level streaming hook
|
|
139
|
-
|
|
140
|
-
### Component Hooks
|
|
141
|
-
|
|
142
|
-
- `useIcon(props)` - Icon data and fallbacks
|
|
143
|
-
- `useCodeBlock(props)` - Code block processing
|
|
144
|
-
- `useMath(props)` - Math content processing
|
|
145
|
-
- `useThinkingSection(props)` - Thinking section state management
|
|
146
|
-
- `useTaskSection(props)` - Task section state and processing
|
|
147
|
-
- `useCodeProject(props)` - Code project structure
|
|
148
|
-
- `useContentPart(part)` - Content part analysis and processing
|
|
149
|
-
|
|
150
|
-
## Available Components
|
|
151
|
-
|
|
152
|
-
All components are optional JSX renderers that work with DOM environments. For headless usage, use the corresponding hooks instead.
|
|
153
|
-
|
|
154
|
-
- `Message` - Main message renderer
|
|
155
|
-
- `StreamingMessage` - Streaming message with loading states
|
|
156
|
-
- `Icon` - Generic icon component with fallbacks
|
|
157
|
-
- `CodeBlock` - Code syntax highlighting
|
|
158
|
-
- `MathPart` - Math content rendering
|
|
159
|
-
- `ThinkingSection` - Collapsible thinking sections
|
|
160
|
-
- `TaskSection` - Collapsible task sections
|
|
161
|
-
- `CodeProjectPart` - Code project file browser
|
|
162
|
-
- `ContentPartRenderer` - Handles different content part types
|
|
163
66
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
- `task-coding-v1` - Code generation and editing tasks
|
|
176
|
-
- `task-generate-design-inspiration-v1` - Design inspiration generation
|
|
177
|
-
- `task-start-v1` - Task initialization (usually hidden)
|
|
178
|
-
|
|
179
|
-
### Future-Proof Support
|
|
180
|
-
|
|
181
|
-
Any new task type following the `task-*-v1` pattern will be automatically supported with:
|
|
182
|
-
|
|
183
|
-
- Auto-generated readable titles
|
|
184
|
-
- Appropriate icon selection
|
|
185
|
-
- Proper task section rendering
|
|
186
|
-
- Graceful fallback handling
|
|
187
|
-
|
|
188
|
-
## Customization
|
|
189
|
-
|
|
190
|
-
### Custom Components
|
|
191
|
-
|
|
192
|
-
```tsx
|
|
193
|
-
import { Message } from '@v0-sdk/react'
|
|
194
|
-
|
|
195
|
-
function CustomMessage({ content }) {
|
|
196
|
-
return (
|
|
197
|
-
<Message
|
|
198
|
-
content={content}
|
|
199
|
-
components={{
|
|
200
|
-
// Override specific HTML elements
|
|
201
|
-
p: ({ children }) => <MyParagraph>{children}</MyParagraph>,
|
|
202
|
-
code: ({ children }) => <MyCode>{children}</MyCode>,
|
|
203
|
-
|
|
204
|
-
// Override v0-specific components
|
|
205
|
-
CodeBlock: ({ language, code }) => (
|
|
206
|
-
<MyCodeHighlighter lang={language}>{code}</MyCodeHighlighter>
|
|
207
|
-
),
|
|
208
|
-
Icon: ({ name }) => <MyIcon icon={name} />,
|
|
209
|
-
}}
|
|
210
|
-
/>
|
|
67
|
+
<button
|
|
68
|
+
disabled={send.isMutating}
|
|
69
|
+
onClick={async () => {
|
|
70
|
+
const response = await send.trigger({ message: 'Build a dashboard' })
|
|
71
|
+
await response.text()
|
|
72
|
+
await messages.mutate()
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
Send message
|
|
76
|
+
</button>
|
|
77
|
+
</main>
|
|
211
78
|
)
|
|
212
79
|
}
|
|
213
80
|
```
|
|
214
81
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
```tsx
|
|
218
|
-
import { useMessage } from '@v0-sdk/react'
|
|
82
|
+
## AI SDK `useChat`
|
|
219
83
|
|
|
220
|
-
|
|
221
|
-
const messageData = useMessage({ content })
|
|
222
|
-
|
|
223
|
-
const renderElement = (element) => {
|
|
224
|
-
switch (element.type) {
|
|
225
|
-
case 'text':
|
|
226
|
-
return <MyText>{element.data}</MyText>
|
|
227
|
-
case 'code-project':
|
|
228
|
-
return <MyCodeProject {...element.data} />
|
|
229
|
-
case 'html':
|
|
230
|
-
return <MyHtmlElement {...element.data} />
|
|
231
|
-
default:
|
|
232
|
-
return null
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
return <MyContainer>{messageData.elements.map(renderElement)}</MyContainer>
|
|
237
|
-
}
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
## TypeScript Support
|
|
241
|
-
|
|
242
|
-
Full TypeScript support with exported types:
|
|
84
|
+
Use AI SDK directly with `V0Transport`. The transport points at your create, send, and resume proxy routes; v0 credentials remain on the server.
|
|
243
85
|
|
|
244
86
|
```tsx
|
|
245
|
-
import
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
87
|
+
import { useChat as useAIChat } from '@ai-sdk/react'
|
|
88
|
+
import {
|
|
89
|
+
shouldResumeV0Chat,
|
|
90
|
+
toV0UIMessages,
|
|
91
|
+
V0Transport,
|
|
92
|
+
type MessagesListResponse,
|
|
93
|
+
type V0UIMessage,
|
|
252
94
|
} from '@v0-sdk/react'
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const messageData = useMessage({ content })
|
|
271
|
-
|
|
272
|
-
const renderElement = (element) => {
|
|
273
|
-
if (element.type === 'text') {
|
|
274
|
-
return <Text key={element.key}>{element.data}</Text>
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
if (element.type === 'html' && element.data.tagName === 'p') {
|
|
278
|
-
return (
|
|
279
|
-
<Text key={element.key} style={{ marginVertical: 8 }}>
|
|
280
|
-
{element.children?.map(renderElement)}
|
|
281
|
-
</Text>
|
|
282
|
-
)
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
return <Text key={element.key}>[{element.type}]</Text>
|
|
286
|
-
}
|
|
95
|
+
import { useMemo } from 'react'
|
|
96
|
+
|
|
97
|
+
export function AIChat({ history }: { history: MessagesListResponse['messages'] }) {
|
|
98
|
+
const chatId = history[0]?.chatId
|
|
99
|
+
const transport = useMemo(
|
|
100
|
+
() =>
|
|
101
|
+
new V0Transport({
|
|
102
|
+
chatId,
|
|
103
|
+
messages: history,
|
|
104
|
+
urls: {
|
|
105
|
+
create: '/api/v0/chats/stream',
|
|
106
|
+
send: (id) => `/api/v0/chats/${id}/messages/stream`,
|
|
107
|
+
resume: (id) => `/api/v0/chats/${id}/resume`,
|
|
108
|
+
},
|
|
109
|
+
}),
|
|
110
|
+
[chatId, history],
|
|
111
|
+
)
|
|
287
112
|
|
|
288
|
-
|
|
289
|
-
|
|
113
|
+
const chat = useAIChat<V0UIMessage>({
|
|
114
|
+
id: chatId,
|
|
115
|
+
messages: toV0UIMessages(history),
|
|
116
|
+
resume: shouldResumeV0Chat(history),
|
|
117
|
+
transport,
|
|
118
|
+
})
|
|
290
119
|
|
|
291
|
-
|
|
292
|
-
const iconData = useIcon({ name })
|
|
293
|
-
return <Text>{iconData.fallback}</Text>
|
|
120
|
+
return <button onClick={() => chat.sendMessage({ text: 'Build a dashboard' })}>Send</button>
|
|
294
121
|
}
|
|
295
122
|
```
|
|
296
123
|
|
|
297
|
-
|
|
124
|
+
`toV0UIMessages` maps persisted newest-first v0 history to chronological AI SDK messages. Text, reasoning, files, tools, rich v0 data parts, metadata, and resumable state are preserved. To stop generation, import `useStopMessage` from `@v0-sdk/react/swr`, call it for the active assistant on the server, then call the AI SDK's `chat.stop()` locally.
|
|
298
125
|
|
|
299
|
-
|
|
126
|
+
See [`examples/react-chat`](../../examples/react-chat) for a complete one-page app and authenticated proxy routes.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { ChatTransport, UIMessage, UIMessageChunk } from "ai";
|
|
2
|
+
import { ChatsCreateStreamData, Message, MessagesSendStreamData, V0StreamFinal, V0StreamResult, V0StreamUpdate } from "v0/browser";
|
|
3
|
+
|
|
4
|
+
//#region src/chat/messages.d.ts
|
|
5
|
+
type V0Part = Message['parts'][number];
|
|
6
|
+
type Serialized<T> = T extends Date ? string : T extends Array<infer Item> ? Array<Serialized<Item>> : T extends object ? { [Key in keyof T]: Serialized<T[Key]> } : T;
|
|
7
|
+
type V0UIMessageMetadata = Serialized<Partial<Omit<Message, 'role' | 'content' | 'parts'>>>;
|
|
8
|
+
type V0DataPart = Exclude<V0Part, {
|
|
9
|
+
type: 'text' | 'thinking';
|
|
10
|
+
}>;
|
|
11
|
+
type V0UIDataTypes = { [Part in V0DataPart as `v0-${Part['type']}`]: Serialized<Omit<Part, 'type'>> };
|
|
12
|
+
type V0UIMessage = UIMessage<V0UIMessageMetadata, V0UIDataTypes>;
|
|
13
|
+
/** Converts a persisted v0 message to an AI SDK UI message. */
|
|
14
|
+
declare function toV0UIMessage(message: Message): V0UIMessage;
|
|
15
|
+
/** Converts SDK history to chronological AI SDK UI messages. */
|
|
16
|
+
declare function toV0UIMessages(messages: readonly Message[], options?: {
|
|
17
|
+
newestFirst?: boolean;
|
|
18
|
+
}): V0UIMessage[];
|
|
19
|
+
declare function toV0UIMessageMetadata(message: Message): V0UIMessageMetadata;
|
|
20
|
+
declare function serializeDates<T>(value: T): Serialized<T>;
|
|
21
|
+
declare function getV0PartId(messageId: string, index: number): string;
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/chat/chunks.d.ts
|
|
24
|
+
type V0Chunk = UIMessageChunk<V0UIMessageMetadata, V0UIDataTypes>;
|
|
25
|
+
/** Converts accumulated v0 message snapshots into incremental AI SDK chunks. */
|
|
26
|
+
declare class V0SnapshotChunkReducer {
|
|
27
|
+
private previous;
|
|
28
|
+
private metadata;
|
|
29
|
+
private metadataJson;
|
|
30
|
+
private started;
|
|
31
|
+
private finished;
|
|
32
|
+
private readonly activeText;
|
|
33
|
+
private readonly textPartAttempts;
|
|
34
|
+
constructor(seed?: Message);
|
|
35
|
+
push(update: V0StreamUpdate | V0StreamFinal, final?: boolean): V0Chunk[];
|
|
36
|
+
private updateTextPart;
|
|
37
|
+
}
|
|
38
|
+
/** Adapts a parsed v0 stream to the stream consumed by AI SDK `useChat`. */
|
|
39
|
+
declare function v0StreamToUIMessageStream(result: V0StreamResult, options?: {
|
|
40
|
+
seed?: Message;
|
|
41
|
+
onUpdate?: (update: V0StreamUpdate | V0StreamFinal) => void;
|
|
42
|
+
onClose?: () => void;
|
|
43
|
+
abort?: (reason?: unknown) => void;
|
|
44
|
+
}): ReadableStream<V0Chunk>;
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/chat/composition.d.ts
|
|
47
|
+
/** True only when the newest SDK message is an unfinished assistant. */
|
|
48
|
+
declare function shouldResumeV0Chat(messages: readonly Message[]): boolean;
|
|
49
|
+
declare function getResumableV0Assistant(messages: readonly Message[]): Message | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Prepends an older newest-first SDK page without replacing active AI SDK
|
|
52
|
+
* message objects already present in local state.
|
|
53
|
+
*/
|
|
54
|
+
declare function prependV0UIMessageHistory(current: readonly V0UIMessage[], olderNewestFirst: readonly Message[]): V0UIMessage[];
|
|
55
|
+
//#endregion
|
|
56
|
+
//#region src/request.d.ts
|
|
57
|
+
type V0Fetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
58
|
+
interface V0RequestOptions extends Omit<RequestInit, 'body' | 'method'> {
|
|
59
|
+
/** Override the Fetch implementation for this hook. */
|
|
60
|
+
fetch?: V0Fetch;
|
|
61
|
+
}
|
|
62
|
+
type V0HttpMethod = Uppercase<'get' | 'post' | 'patch' | 'delete' | 'put'>;
|
|
63
|
+
type V0ResponseKind = 'json' | 'stream' | 'blob';
|
|
64
|
+
type V0ResponseTransformer<Data> = (data: unknown) => Data | Promise<Data>;
|
|
65
|
+
interface V0Operation<Data> {
|
|
66
|
+
id: string;
|
|
67
|
+
method: V0HttpMethod;
|
|
68
|
+
response: V0ResponseKind;
|
|
69
|
+
transform?: V0ResponseTransformer<Data>;
|
|
70
|
+
}
|
|
71
|
+
/** HTTP error returned by the application's v0 proxy. */
|
|
72
|
+
declare class V0ResponseError<Body = unknown> extends Error {
|
|
73
|
+
readonly status: number;
|
|
74
|
+
readonly statusText: string;
|
|
75
|
+
readonly body: Body;
|
|
76
|
+
readonly response: Response;
|
|
77
|
+
constructor(response: Response, body: Body, message?: string);
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/chat/transport.d.ts
|
|
81
|
+
type V0TransportChatUrl = string | ((chatId: string) => string);
|
|
82
|
+
interface V0TransportUrls {
|
|
83
|
+
create: string;
|
|
84
|
+
send: V0TransportChatUrl;
|
|
85
|
+
resume: V0TransportChatUrl;
|
|
86
|
+
}
|
|
87
|
+
interface V0TransportOptions {
|
|
88
|
+
urls: V0TransportUrls;
|
|
89
|
+
chatId?: string;
|
|
90
|
+
/** Newest-first SDK history, used to seed a resumed assistant. */
|
|
91
|
+
messages?: readonly Message[];
|
|
92
|
+
create?: Omit<ChatsCreateStreamData['body'], 'message' | 'attachments'>;
|
|
93
|
+
send?: Omit<MessagesSendStreamData['body'], 'message' | 'attachments'>;
|
|
94
|
+
request?: V0RequestOptions;
|
|
95
|
+
onChatCreated?: (chatId: string) => void;
|
|
96
|
+
}
|
|
97
|
+
/** AI SDK chat transport backed by caller-owned v0 proxy routes. */
|
|
98
|
+
declare class V0Transport implements ChatTransport<V0UIMessage> {
|
|
99
|
+
private currentChatId;
|
|
100
|
+
private reconnecting;
|
|
101
|
+
private readonly seed;
|
|
102
|
+
private readonly options;
|
|
103
|
+
constructor(options: V0TransportOptions);
|
|
104
|
+
get chatId(): string | undefined;
|
|
105
|
+
sendMessages(options: Parameters<ChatTransport<V0UIMessage>['sendMessages']>[0]): Promise<ReadableStream<UIMessageChunk>>;
|
|
106
|
+
reconnectToStream(options: Parameters<ChatTransport<V0UIMessage>['reconnectToStream']>[0]): Promise<ReadableStream<UIMessageChunk> | null>;
|
|
107
|
+
private captureChatId;
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
export { toV0UIMessage as C, serializeDates as S, toV0UIMessages as T, Serialized as _, V0Fetch as a, V0UIMessageMetadata as b, V0RequestOptions as c, V0ResponseTransformer as d, getResumableV0Assistant as f, v0StreamToUIMessageStream as g, V0SnapshotChunkReducer as h, V0TransportUrls as i, V0ResponseError as l, shouldResumeV0Chat as m, V0TransportChatUrl as n, V0HttpMethod as o, prependV0UIMessageHistory as p, V0TransportOptions as r, V0Operation as s, V0Transport as t, V0ResponseKind as u, V0UIDataTypes as v, toV0UIMessageMetadata as w, getV0PartId as x, V0UIMessage as y };
|
|
111
|
+
//# sourceMappingURL=index-Byqc8Ogm.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-Byqc8Ogm.d.cts","names":[],"sources":["../src/chat/messages.ts","../src/chat/chunks.ts","../src/chat/composition.ts","../src/request.ts","../src/chat/transport.ts"],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { ChatsCreateStreamData, Message, MessagesSendStreamData, V0StreamFinal, V0StreamResult, V0StreamUpdate } from "v0/browser";
|
|
2
|
+
import { ChatTransport, UIMessage, UIMessageChunk } from "ai";
|
|
3
|
+
|
|
4
|
+
//#region src/chat/messages.d.ts
|
|
5
|
+
type V0Part = Message['parts'][number];
|
|
6
|
+
type Serialized<T> = T extends Date ? string : T extends Array<infer Item> ? Array<Serialized<Item>> : T extends object ? { [Key in keyof T]: Serialized<T[Key]> } : T;
|
|
7
|
+
type V0UIMessageMetadata = Serialized<Partial<Omit<Message, 'role' | 'content' | 'parts'>>>;
|
|
8
|
+
type V0DataPart = Exclude<V0Part, {
|
|
9
|
+
type: 'text' | 'thinking';
|
|
10
|
+
}>;
|
|
11
|
+
type V0UIDataTypes = { [Part in V0DataPart as `v0-${Part['type']}`]: Serialized<Omit<Part, 'type'>> };
|
|
12
|
+
type V0UIMessage = UIMessage<V0UIMessageMetadata, V0UIDataTypes>;
|
|
13
|
+
/** Converts a persisted v0 message to an AI SDK UI message. */
|
|
14
|
+
declare function toV0UIMessage(message: Message): V0UIMessage;
|
|
15
|
+
/** Converts SDK history to chronological AI SDK UI messages. */
|
|
16
|
+
declare function toV0UIMessages(messages: readonly Message[], options?: {
|
|
17
|
+
newestFirst?: boolean;
|
|
18
|
+
}): V0UIMessage[];
|
|
19
|
+
declare function toV0UIMessageMetadata(message: Message): V0UIMessageMetadata;
|
|
20
|
+
declare function serializeDates<T>(value: T): Serialized<T>;
|
|
21
|
+
declare function getV0PartId(messageId: string, index: number): string;
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/chat/chunks.d.ts
|
|
24
|
+
type V0Chunk = UIMessageChunk<V0UIMessageMetadata, V0UIDataTypes>;
|
|
25
|
+
/** Converts accumulated v0 message snapshots into incremental AI SDK chunks. */
|
|
26
|
+
declare class V0SnapshotChunkReducer {
|
|
27
|
+
private previous;
|
|
28
|
+
private metadata;
|
|
29
|
+
private metadataJson;
|
|
30
|
+
private started;
|
|
31
|
+
private finished;
|
|
32
|
+
private readonly activeText;
|
|
33
|
+
private readonly textPartAttempts;
|
|
34
|
+
constructor(seed?: Message);
|
|
35
|
+
push(update: V0StreamUpdate | V0StreamFinal, final?: boolean): V0Chunk[];
|
|
36
|
+
private updateTextPart;
|
|
37
|
+
}
|
|
38
|
+
/** Adapts a parsed v0 stream to the stream consumed by AI SDK `useChat`. */
|
|
39
|
+
declare function v0StreamToUIMessageStream(result: V0StreamResult, options?: {
|
|
40
|
+
seed?: Message;
|
|
41
|
+
onUpdate?: (update: V0StreamUpdate | V0StreamFinal) => void;
|
|
42
|
+
onClose?: () => void;
|
|
43
|
+
abort?: (reason?: unknown) => void;
|
|
44
|
+
}): ReadableStream<V0Chunk>;
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/chat/composition.d.ts
|
|
47
|
+
/** True only when the newest SDK message is an unfinished assistant. */
|
|
48
|
+
declare function shouldResumeV0Chat(messages: readonly Message[]): boolean;
|
|
49
|
+
declare function getResumableV0Assistant(messages: readonly Message[]): Message | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Prepends an older newest-first SDK page without replacing active AI SDK
|
|
52
|
+
* message objects already present in local state.
|
|
53
|
+
*/
|
|
54
|
+
declare function prependV0UIMessageHistory(current: readonly V0UIMessage[], olderNewestFirst: readonly Message[]): V0UIMessage[];
|
|
55
|
+
//#endregion
|
|
56
|
+
//#region src/request.d.ts
|
|
57
|
+
type V0Fetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
58
|
+
interface V0RequestOptions extends Omit<RequestInit, 'body' | 'method'> {
|
|
59
|
+
/** Override the Fetch implementation for this hook. */
|
|
60
|
+
fetch?: V0Fetch;
|
|
61
|
+
}
|
|
62
|
+
type V0HttpMethod = Uppercase<'get' | 'post' | 'patch' | 'delete' | 'put'>;
|
|
63
|
+
type V0ResponseKind = 'json' | 'stream' | 'blob';
|
|
64
|
+
type V0ResponseTransformer<Data> = (data: unknown) => Data | Promise<Data>;
|
|
65
|
+
interface V0Operation<Data> {
|
|
66
|
+
id: string;
|
|
67
|
+
method: V0HttpMethod;
|
|
68
|
+
response: V0ResponseKind;
|
|
69
|
+
transform?: V0ResponseTransformer<Data>;
|
|
70
|
+
}
|
|
71
|
+
/** HTTP error returned by the application's v0 proxy. */
|
|
72
|
+
declare class V0ResponseError<Body = unknown> extends Error {
|
|
73
|
+
readonly status: number;
|
|
74
|
+
readonly statusText: string;
|
|
75
|
+
readonly body: Body;
|
|
76
|
+
readonly response: Response;
|
|
77
|
+
constructor(response: Response, body: Body, message?: string);
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/chat/transport.d.ts
|
|
81
|
+
type V0TransportChatUrl = string | ((chatId: string) => string);
|
|
82
|
+
interface V0TransportUrls {
|
|
83
|
+
create: string;
|
|
84
|
+
send: V0TransportChatUrl;
|
|
85
|
+
resume: V0TransportChatUrl;
|
|
86
|
+
}
|
|
87
|
+
interface V0TransportOptions {
|
|
88
|
+
urls: V0TransportUrls;
|
|
89
|
+
chatId?: string;
|
|
90
|
+
/** Newest-first SDK history, used to seed a resumed assistant. */
|
|
91
|
+
messages?: readonly Message[];
|
|
92
|
+
create?: Omit<ChatsCreateStreamData['body'], 'message' | 'attachments'>;
|
|
93
|
+
send?: Omit<MessagesSendStreamData['body'], 'message' | 'attachments'>;
|
|
94
|
+
request?: V0RequestOptions;
|
|
95
|
+
onChatCreated?: (chatId: string) => void;
|
|
96
|
+
}
|
|
97
|
+
/** AI SDK chat transport backed by caller-owned v0 proxy routes. */
|
|
98
|
+
declare class V0Transport implements ChatTransport<V0UIMessage> {
|
|
99
|
+
private currentChatId;
|
|
100
|
+
private reconnecting;
|
|
101
|
+
private readonly seed;
|
|
102
|
+
private readonly options;
|
|
103
|
+
constructor(options: V0TransportOptions);
|
|
104
|
+
get chatId(): string | undefined;
|
|
105
|
+
sendMessages(options: Parameters<ChatTransport<V0UIMessage>['sendMessages']>[0]): Promise<ReadableStream<UIMessageChunk>>;
|
|
106
|
+
reconnectToStream(options: Parameters<ChatTransport<V0UIMessage>['reconnectToStream']>[0]): Promise<ReadableStream<UIMessageChunk> | null>;
|
|
107
|
+
private captureChatId;
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
export { toV0UIMessage as C, serializeDates as S, toV0UIMessages as T, Serialized as _, V0Fetch as a, V0UIMessageMetadata as b, V0RequestOptions as c, V0ResponseTransformer as d, getResumableV0Assistant as f, v0StreamToUIMessageStream as g, V0SnapshotChunkReducer as h, V0TransportUrls as i, V0ResponseError as l, shouldResumeV0Chat as m, V0TransportChatUrl as n, V0HttpMethod as o, prependV0UIMessageHistory as p, V0TransportOptions as r, V0Operation as s, V0Transport as t, V0ResponseKind as u, V0UIDataTypes as v, toV0UIMessageMetadata as w, getV0PartId as x, V0UIMessage as y };
|
|
111
|
+
//# sourceMappingURL=index-CknrgtQb.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-CknrgtQb.d.mts","names":[],"sources":["../src/chat/messages.ts","../src/chat/chunks.ts","../src/chat/composition.ts","../src/request.ts","../src/chat/transport.ts"],"mappings":"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"}
|