@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 CHANGED
@@ -1,299 +1,126 @@
1
1
  # @v0-sdk/react
2
2
 
3
- > **⚠️ Developer Preview**: This SDK is currently in beta and is subject to change. Use in production at your own risk.
3
+ React hooks for building apps with the v0 API.
4
4
 
5
- Headless React components and hooks for rendering content from the v0 Platform API.
5
+ ## Install
6
6
 
7
- ## Features
7
+ For the AI SDK transport:
8
8
 
9
- - **Headless by design** - Works with React Native, TUIs, and any React renderer
10
- - **Flexible rendering** - Use provided JSX components or build your own with headless hooks
11
- - **Customizable** - Override any component or styling
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
- ## Installation
13
+ Add SWR when using the generated API hooks:
17
14
 
18
- ```bash
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
- ## Usage
19
+ ## Getting started
27
20
 
28
- ### Basic JSX Components (Web/React DOM)
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
- ```tsx
31
- import { Message, StreamingMessage } from '@v0-sdk/react'
23
+ ```ts
24
+ // app/api/v0/chats/[chatId]/messages/stream/route.ts
25
+ import { v0 } from 'v0'
32
26
 
33
- function ChatMessage({ content }) {
34
- return (
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
- function StreamingChat({ stream }) {
45
- return (
46
- <StreamingMessage
47
- stream={stream}
48
- messageId="streaming-msg"
49
- role="assistant"
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
- ### Headless Hooks (React Native/Ink/TUI)
39
+ The client can call that route with the corresponding hook:
57
40
 
58
41
  ```tsx
59
- import { useMessage, useStreamingMessageData } from '@v0-sdk/react'
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 HeadlessMessage({ content }) {
63
- const messageData = useMessage({
64
- content,
65
- messageId: 'msg-1',
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
- return (
70
- <View>
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 (streamingData.isStreaming && !streamingData.messageData) {
92
- return <Text>Loading...</Text>
55
+ if (chat.error || messages.error) {
56
+ return <p>Unable to load the chat.</p>
93
57
  }
94
58
 
95
59
  return (
96
- <View>
97
- {streamingData.messageData?.elements.map((element) => (
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
- ```tsx
110
- import { useMessage } from '@v0-sdk/react'
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
- ## Supported Task Types
165
-
166
- The package automatically handles all v0 Platform API task types:
167
-
168
- ### Explicitly Supported Tasks
169
-
170
- - `task-thinking-v1` - AI reasoning and thought processes
171
- - `task-search-web-v1` - Web search operations with results
172
- - `task-search-repo-v1` - Repository/codebase search functionality
173
- - `task-diagnostics-v1` - Code analysis and issue detection
174
- - `task-read-file-v1` - File reading operations
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
- ### Headless Custom Rendering
216
-
217
- ```tsx
218
- import { useMessage } from '@v0-sdk/react'
82
+ ## AI SDK `useChat`
219
83
 
220
- function CustomHeadlessMessage({ content }) {
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 type {
246
- MessageData,
247
- MessageElement,
248
- StreamingMessageData,
249
- IconData,
250
- CodeBlockData,
251
- // ... and many more
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
- ## Migration from Previous Versions
256
-
257
- This version is backward compatible. Existing code will continue to work unchanged. To adopt headless patterns:
258
-
259
- 1. **Keep existing JSX components** for web/DOM environments
260
- 2. **Use headless hooks** for React Native, Ink, or custom renderers
261
- 3. **Gradually migrate** components as needed
262
-
263
- ## React Native Example
264
-
265
- ```tsx
266
- import { useMessage, useIcon } from '@v0-sdk/react'
267
- import { View, Text, ScrollView } from 'react-native'
268
-
269
- function RNMessage({ content }) {
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
- return <ScrollView>{messageData.elements.map(renderElement)}</ScrollView>
289
- }
113
+ const chat = useAIChat<V0UIMessage>({
114
+ id: chatId,
115
+ messages: toV0UIMessages(history),
116
+ resume: shouldResumeV0Chat(history),
117
+ transport,
118
+ })
290
119
 
291
- function RNIcon({ name }) {
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
- ## License
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
- Apache-2.0
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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"}