@tanstack/ai-client 0.18.3 → 0.18.5

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.
Files changed (49) hide show
  1. package/package.json +3 -3
  2. package/src/realtime-types.ts +6 -72
  3. package/dist/esm/chat-client.d.ts +0 -264
  4. package/dist/esm/chat-client.js +0 -1097
  5. package/dist/esm/chat-client.js.map +0 -1
  6. package/dist/esm/client-persistor.d.ts +0 -86
  7. package/dist/esm/client-persistor.js +0 -243
  8. package/dist/esm/client-persistor.js.map +0 -1
  9. package/dist/esm/connection-adapters.d.ts +0 -203
  10. package/dist/esm/connection-adapters.js +0 -611
  11. package/dist/esm/connection-adapters.js.map +0 -1
  12. package/dist/esm/devtools-noop.d.ts +0 -63
  13. package/dist/esm/devtools-noop.js +0 -141
  14. package/dist/esm/devtools-noop.js.map +0 -1
  15. package/dist/esm/devtools.d.ts +0 -276
  16. package/dist/esm/devtools.js +0 -1178
  17. package/dist/esm/devtools.js.map +0 -1
  18. package/dist/esm/events.d.ts +0 -129
  19. package/dist/esm/events.js +0 -227
  20. package/dist/esm/events.js.map +0 -1
  21. package/dist/esm/generation-client.d.ts +0 -99
  22. package/dist/esm/generation-client.js +0 -325
  23. package/dist/esm/generation-client.js.map +0 -1
  24. package/dist/esm/generation-types.d.ts +0 -242
  25. package/dist/esm/generation-types.js +0 -14
  26. package/dist/esm/generation-types.js.map +0 -1
  27. package/dist/esm/index.d.ts +0 -16
  28. package/dist/esm/index.js +0 -44
  29. package/dist/esm/index.js.map +0 -1
  30. package/dist/esm/realtime-client.d.ts +0 -98
  31. package/dist/esm/realtime-client.js +0 -403
  32. package/dist/esm/realtime-client.js.map +0 -1
  33. package/dist/esm/realtime-types.d.ts +0 -118
  34. package/dist/esm/response-stream.d.ts +0 -7
  35. package/dist/esm/response-stream.js +0 -32
  36. package/dist/esm/response-stream.js.map +0 -1
  37. package/dist/esm/sse-parser.d.ts +0 -8
  38. package/dist/esm/sse-parser.js +0 -52
  39. package/dist/esm/sse-parser.js.map +0 -1
  40. package/dist/esm/sse-utils.d.ts +0 -1
  41. package/dist/esm/sse-utils.js +0 -11
  42. package/dist/esm/sse-utils.js.map +0 -1
  43. package/dist/esm/tool-types.d.ts +0 -20
  44. package/dist/esm/types.d.ts +0 -419
  45. package/dist/esm/types.js +0 -11
  46. package/dist/esm/types.js.map +0 -1
  47. package/dist/esm/video-generation-client.d.ts +0 -110
  48. package/dist/esm/video-generation-client.js +0 -382
  49. package/dist/esm/video-generation-client.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/ai-client",
3
- "version": "0.18.3",
3
+ "version": "0.18.5",
4
4
  "description": "Framework-agnostic headless client for TanStack AI chat, realtime sessions, streaming transports, and media generations.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -49,8 +49,8 @@
49
49
  "src"
50
50
  ],
51
51
  "dependencies": {
52
- "@tanstack/ai": "0.34.1",
53
- "@tanstack/ai-event-client": "0.6.6"
52
+ "@tanstack/ai": "0.36.0",
53
+ "@tanstack/ai-event-client": "0.6.7"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@standard-schema/spec": "^1.1.0",
@@ -1,83 +1,17 @@
1
1
  import type {
2
2
  AnyClientTool,
3
- AudioVisualization,
4
- RealtimeEvent,
5
- RealtimeEventHandler,
3
+ RealtimeAdapter,
6
4
  RealtimeMessage,
7
5
  RealtimeMode,
8
- RealtimeSessionConfig,
9
6
  RealtimeStatus,
10
7
  RealtimeToken,
11
8
  } from '@tanstack/ai/client'
12
9
 
13
- // ============================================================================
14
- // Adapter Interface
15
- // ============================================================================
16
-
17
- /**
18
- * Adapter interface for connecting to realtime providers.
19
- * Each provider (OpenAI, ElevenLabs, etc.) implements this interface.
20
- */
21
- export interface RealtimeAdapter {
22
- /** Provider identifier */
23
- provider: string
24
-
25
- /**
26
- * Create a connection using the provided token
27
- * @param token - The ephemeral token from the server
28
- * @param clientTools - Optional client-side tools to register with the provider
29
- * @returns A connection instance
30
- */
31
- connect: (
32
- token: RealtimeToken,
33
- clientTools?: ReadonlyArray<AnyClientTool>,
34
- ) => Promise<RealtimeConnection>
35
- }
36
-
37
- /**
38
- * Connection interface representing an active realtime session.
39
- * Handles audio I/O, events, and session management.
40
- */
41
- export interface RealtimeConnection {
42
- // Lifecycle
43
- /** Disconnect from the realtime session */
44
- disconnect: () => Promise<void>
45
-
46
- // Audio I/O
47
- /** Start capturing audio from the microphone */
48
- startAudioCapture: () => Promise<void>
49
- /** Stop capturing audio */
50
- stopAudioCapture: () => void
51
-
52
- // Text input
53
- /** Send a text message (fallback for when voice isn't available) */
54
- sendText: (text: string) => void
55
-
56
- // Image input
57
- /** Send an image to the conversation */
58
- sendImage: (imageData: string, mimeType: string) => void
59
-
60
- // Tool results
61
- /** Send a tool execution result back to the provider */
62
- sendToolResult: (callId: string, result: string) => void
63
-
64
- // Session management
65
- /** Update session configuration */
66
- updateSession: (config: Partial<RealtimeSessionConfig>) => void
67
- /** Interrupt the current response */
68
- interrupt: () => void
69
-
70
- // Events
71
- /** Subscribe to connection events */
72
- on: <TEvent extends RealtimeEvent>(
73
- event: TEvent,
74
- handler: RealtimeEventHandler<TEvent>,
75
- ) => () => void
76
-
77
- // Audio visualization
78
- /** Get audio visualization data */
79
- getAudioVisualization: () => AudioVisualization
80
- }
10
+ // The realtime adapter contract lives in `@tanstack/ai` (the shared layer both
11
+ // providers and this client depend on) so provider packages don't need to
12
+ // depend on `@tanstack/ai-client`. Re-exported here for backwards compatibility
13
+ // — `import { RealtimeAdapter } from '@tanstack/ai-client'` keeps working.
14
+ export type { RealtimeAdapter, RealtimeConnection } from '@tanstack/ai/client'
81
15
 
82
16
  // ============================================================================
83
17
  // Client Options
@@ -1,264 +0,0 @@
1
- import { AnyClientTool, ModelMessage, StreamChunk } from '@tanstack/ai/client';
2
- import { ConnectionAdapter } from './connection-adapters.js';
3
- import { ChatClientOptions, ChatClientState, ChatFetcher, ConnectionStatus, MultimodalContent, UIMessage } from './types.js';
4
- type ChatClientUpdateOptionsWithoutContext<TTools extends ReadonlyArray<AnyClientTool>> = {
5
- connection?: ConnectionAdapter;
6
- fetcher?: ChatFetcher;
7
- /** @deprecated Use `forwardedProps` instead. */
8
- body?: Record<string, any>;
9
- forwardedProps?: Record<string, any>;
10
- tools?: TTools;
11
- onResponse?: (response?: Response) => void | Promise<void>;
12
- onChunk?: (chunk: StreamChunk) => void;
13
- onFinish?: (message: UIMessage) => void;
14
- onError?: (error: Error) => void;
15
- onSubscriptionChange?: (isSubscribed: boolean) => void;
16
- onConnectionStatusChange?: (status: ConnectionStatus) => void;
17
- onSessionGeneratingChange?: (isGenerating: boolean) => void;
18
- onCustomEvent?: (eventType: string, data: unknown, context: {
19
- toolCallId?: string;
20
- }) => void;
21
- };
22
- type ClientToolResult = {
23
- toolCallId: string;
24
- tool: string;
25
- output: any;
26
- state?: 'output-available' | 'output-error';
27
- errorText?: string;
28
- };
29
- export declare class ChatClient<TTools extends ReadonlyArray<AnyClientTool> = any, TContext = unknown> {
30
- private readonly processor;
31
- private connection;
32
- private readonly uniqueId;
33
- private readonly threadId;
34
- private readonly persistor?;
35
- private currentRunId;
36
- private bodyOption;
37
- private forwardedPropsOption;
38
- private context;
39
- private pendingMessageBody;
40
- private isLoading;
41
- private isSubscribed;
42
- private error;
43
- private status;
44
- private connectionStatus;
45
- private abortController;
46
- private readonly clientToolsRef;
47
- private readonly devtoolsBridge;
48
- /**
49
- * Alias for `this.events`. The bridge installs an
50
- * emitter that auto-attaches run/thread context and auto-emits a
51
- * snapshot after every event, so chat-client only ever calls
52
- * `this.events.X(...)` exactly like it did before devtools landed.
53
- */
54
- private readonly events;
55
- private currentStreamId;
56
- private currentMessageId;
57
- private readonly postStreamActions;
58
- private readonly pendingToolExecutions;
59
- private activeClientTools;
60
- private activeContext;
61
- private continuationPending;
62
- private subscriptionAbortController;
63
- private processingResolve;
64
- private errorReportedGeneration;
65
- private streamGeneration;
66
- private continuationSkipped;
67
- private draining;
68
- private sessionGenerating;
69
- private readonly activeRunIds;
70
- private devtoolsMounted;
71
- private readonly callbacksRef;
72
- constructor(options: ChatClientOptions<TTools, TContext>);
73
- mountDevtools(): void;
74
- /**
75
- * Drain a runId-less RUN_ERROR that belongs to a cleared run the client is
76
- * still tracking. The persistor owns the cleared-run bookkeeping; the client
77
- * owns the active-run / session / processing state.
78
- */
79
- private drainIgnoredRunlessChunk;
80
- private updateRunLifecycle;
81
- private generateUniqueId;
82
- private setIsLoading;
83
- private setStatus;
84
- private setIsSubscribed;
85
- private setConnectionStatus;
86
- private setSessionGenerating;
87
- private resetSessionGenerating;
88
- private setError;
89
- private buildDevtoolsBridgeOptions;
90
- private getDevtoolsSnapshot;
91
- private findMessageIdForToolCall;
92
- private abortSubscriptionLoop;
93
- private resolveProcessing;
94
- private cancelInFlightStream;
95
- private reportStreamError;
96
- /**
97
- * Start the background subscription loop.
98
- */
99
- private startSubscription;
100
- /**
101
- * Consume chunks from the connection subscription.
102
- */
103
- private consumeSubscription;
104
- /**
105
- * Ensure subscription loop is running, starting it if needed.
106
- */
107
- private ensureSubscription;
108
- /**
109
- * Create a promise that resolves when onStreamEnd fires.
110
- * Used by streamResponse to await processing completion.
111
- */
112
- private waitForProcessing;
113
- /**
114
- * Send a message and stream the response.
115
- * Supports both simple string content and multimodal content (images, audio, video, documents).
116
- *
117
- * @param content - The message content. Can be:
118
- * - A simple string for text-only messages
119
- * - A MultimodalContent object with content array and optional custom ID
120
- * @param body - Optional body parameters to merge with the client's base body for this request.
121
- * Uses shallow merge with per-message body taking priority.
122
- *
123
- * @example
124
- * ```ts
125
- * // Simple text message
126
- * await client.sendMessage('Hello!')
127
- *
128
- * // Text message with custom body params
129
- * await client.sendMessage('Hello!', { temperature: 0.7 })
130
- *
131
- * // Multimodal message with image
132
- * await client.sendMessage({
133
- * content: [
134
- * { type: 'text', content: 'What is in this image?' },
135
- * { type: 'image', source: { type: 'url', value: 'https://example.com/photo.jpg' } }
136
- * ]
137
- * })
138
- *
139
- * // Multimodal message with custom ID and body params
140
- * await client.sendMessage(
141
- * {
142
- * content: [
143
- * { type: 'text', content: 'Describe this audio' },
144
- * { type: 'audio', source: { type: 'data', value: 'base64...' } }
145
- * ],
146
- * id: 'custom-message-id'
147
- * },
148
- * { model: 'gpt-4-audio' }
149
- * )
150
- * ```
151
- */
152
- sendMessage(content: string | MultimodalContent, body?: Record<string, any>): Promise<void>;
153
- /**
154
- * Normalize the message input to extract content and optional id.
155
- * Trims string content automatically.
156
- */
157
- private normalizeMessageInput;
158
- /**
159
- * Append a message and stream the response
160
- */
161
- append(message: UIMessage | ModelMessage): Promise<void>;
162
- /**
163
- * Stream a response from the LLM.
164
- * Returns true if the stream completed successfully, false on abort or error.
165
- */
166
- private streamResponse;
167
- /**
168
- * Start the client subscription loop.
169
- * This controls the connection lifecycle independently from request lifecycle.
170
- */
171
- subscribe(options?: {
172
- restart?: boolean;
173
- }): void;
174
- /**
175
- * Unsubscribe and fully tear down live behavior.
176
- * This aborts an in-flight request and the subscription loop.
177
- */
178
- unsubscribe(): void;
179
- /**
180
- * Reload the last assistant message
181
- */
182
- reload(): Promise<void>;
183
- /**
184
- * Stop the current stream
185
- */
186
- stop(): void;
187
- /**
188
- * Clear all messages
189
- */
190
- clear(): void;
191
- /**
192
- * Add the result of a client-side tool execution
193
- */
194
- addToolResult(result: ClientToolResult): Promise<void>;
195
- private addToolResultForClientTool;
196
- private validateClientToolOutput;
197
- /**
198
- * Respond to a tool approval request
199
- */
200
- addToolApprovalResponse(response: {
201
- id: string;
202
- approved: boolean;
203
- }): Promise<void>;
204
- /**
205
- * Queue an action to be executed after the current stream ends
206
- */
207
- private queuePostStreamAction;
208
- /**
209
- * Drain and execute all queued post-stream actions
210
- */
211
- private drainPostStreamActions;
212
- /**
213
- * Check if we should continue the flow and do so if needed
214
- */
215
- private checkForContinuation;
216
- /**
217
- * Check if all tool calls are complete and we should auto-send.
218
- * Requires that there is at least one tool call in the last assistant message;
219
- * a text-only response has nothing to auto-send.
220
- */
221
- private shouldAutoSend;
222
- /**
223
- * Get current messages
224
- */
225
- getMessages(): Array<UIMessage<TTools>>;
226
- /**
227
- * Get loading state
228
- */
229
- getIsLoading(): boolean;
230
- /**
231
- * Get current status
232
- */
233
- getStatus(): ChatClientState;
234
- /**
235
- * Get whether the subscription loop is active
236
- */
237
- getIsSubscribed(): boolean;
238
- /**
239
- * Get current connection lifecycle status
240
- */
241
- getConnectionStatus(): ConnectionStatus;
242
- /**
243
- * Whether the shared session is actively generating.
244
- * Derived from stream run events (RUN_STARTED / RUN_FINISHED / RUN_ERROR).
245
- * Unlike `isLoading` (request-local), this reflects shared generation
246
- * activity visible to all subscribers (e.g. across tabs/devices).
247
- */
248
- getSessionGenerating(): boolean;
249
- /**
250
- * Get current error
251
- */
252
- getError(): Error | undefined;
253
- /**
254
- * Manually set messages
255
- */
256
- setMessagesManually(messages: Array<UIMessage<TTools>>): void;
257
- /**
258
- * Update options refs (for use in React hooks to avoid recreating client)
259
- */
260
- updateOptions(options: ChatClientUpdateOptionsWithoutContext<TTools>): void;
261
- updateOptions(options: ChatClientUpdateOptionsWithoutContext<TTools> & Pick<ChatClientOptions<TTools, TContext>, 'context'>): void;
262
- dispose(): void;
263
- }
264
- export {};