@tanstack/ai-client 0.18.5 → 0.19.0

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 (59) hide show
  1. package/dist/esm/audio-recorder.d.ts +76 -0
  2. package/dist/esm/audio-recorder.js +215 -0
  3. package/dist/esm/audio-recorder.js.map +1 -0
  4. package/dist/esm/chat-client.d.ts +264 -0
  5. package/dist/esm/chat-client.js +1097 -0
  6. package/dist/esm/chat-client.js.map +1 -0
  7. package/dist/esm/client-persistor.d.ts +86 -0
  8. package/dist/esm/client-persistor.js +243 -0
  9. package/dist/esm/client-persistor.js.map +1 -0
  10. package/dist/esm/connection-adapters.d.ts +203 -0
  11. package/dist/esm/connection-adapters.js +611 -0
  12. package/dist/esm/connection-adapters.js.map +1 -0
  13. package/dist/esm/devtools-noop.d.ts +63 -0
  14. package/dist/esm/devtools-noop.js +141 -0
  15. package/dist/esm/devtools-noop.js.map +1 -0
  16. package/dist/esm/devtools.d.ts +276 -0
  17. package/dist/esm/devtools.js +1178 -0
  18. package/dist/esm/devtools.js.map +1 -0
  19. package/dist/esm/events.d.ts +129 -0
  20. package/dist/esm/events.js +227 -0
  21. package/dist/esm/events.js.map +1 -0
  22. package/dist/esm/generation-client.d.ts +99 -0
  23. package/dist/esm/generation-client.js +325 -0
  24. package/dist/esm/generation-client.js.map +1 -0
  25. package/dist/esm/generation-types.d.ts +261 -0
  26. package/dist/esm/generation-types.js +14 -0
  27. package/dist/esm/generation-types.js.map +1 -0
  28. package/dist/esm/index.d.ts +20 -0
  29. package/dist/esm/index.js +48 -0
  30. package/dist/esm/index.js.map +1 -0
  31. package/dist/esm/mcp-app-bridge.d.ts +27 -0
  32. package/dist/esm/mcp-app-bridge.js +70 -0
  33. package/dist/esm/mcp-app-bridge.js.map +1 -0
  34. package/dist/esm/realtime-client.d.ts +98 -0
  35. package/dist/esm/realtime-client.js +403 -0
  36. package/dist/esm/realtime-client.js.map +1 -0
  37. package/dist/esm/realtime-types.d.ts +78 -0
  38. package/dist/esm/response-stream.d.ts +7 -0
  39. package/dist/esm/response-stream.js +32 -0
  40. package/dist/esm/response-stream.js.map +1 -0
  41. package/dist/esm/sse-parser.d.ts +8 -0
  42. package/dist/esm/sse-parser.js +52 -0
  43. package/dist/esm/sse-parser.js.map +1 -0
  44. package/dist/esm/sse-utils.d.ts +1 -0
  45. package/dist/esm/sse-utils.js +11 -0
  46. package/dist/esm/sse-utils.js.map +1 -0
  47. package/dist/esm/tool-types.d.ts +20 -0
  48. package/dist/esm/types.d.ts +419 -0
  49. package/dist/esm/types.js +11 -0
  50. package/dist/esm/types.js.map +1 -0
  51. package/dist/esm/video-generation-client.d.ts +110 -0
  52. package/dist/esm/video-generation-client.js +382 -0
  53. package/dist/esm/video-generation-client.js.map +1 -0
  54. package/package.json +4 -3
  55. package/src/audio-recorder.ts +322 -0
  56. package/src/generation-types.ts +24 -4
  57. package/src/index.ts +10 -0
  58. package/src/mcp-app-bridge.ts +120 -0
  59. package/src/types.ts +2 -0
@@ -0,0 +1,261 @@
1
+ import { MediaPrompt, StreamChunk } from '@tanstack/ai/client';
2
+ import { ConnectConnectionAdapter } from './connection-adapters.js';
3
+ import { AIDevtoolsClientMetadata } from './devtools.js';
4
+ import { GenerationDevtoolsBridgeFactory, VideoDevtoolsBridgeFactory } from './devtools-noop.js';
5
+ /**
6
+ * Maps an `onResult` transform's raw return type to the stored output type.
7
+ *
8
+ * - A concrete return (excluding null/void/undefined) becomes the output type.
9
+ * - A return of only null/void/undefined falls back to TResult (the transform
10
+ * reacted to the result or chose to keep it, rather than replacing it).
11
+ *
12
+ * Hooks infer `TReturn` directly from the `onResult` return position — a
13
+ * covariant inference site that works even for an optional nested property —
14
+ * which both contextually types the callback parameter as `TResult` and
15
+ * narrows `result`. See issue #848.
16
+ *
17
+ * @template TResult - The raw result type from the generation
18
+ * @template TReturn - The transform's return type (defaults to `void` when no
19
+ * transform is provided)
20
+ */
21
+ export type InferGenerationOutputFromReturn<TResult, TReturn> = [
22
+ Exclude<TReturn, null | void | undefined>
23
+ ] extends [never] ? TResult : Exclude<TReturn, null | void | undefined>;
24
+ /**
25
+ * Infers the output type from an `onResult` callback's type.
26
+ *
27
+ * - If the callback returns a concrete type (excluding null/void/undefined), uses that type.
28
+ * - If the callback only returns null/void/undefined, or is not provided, falls back to TResult.
29
+ *
30
+ * @template TResult - The raw result type from the generation
31
+ * @template TFn - The onResult callback type (or undefined if not provided)
32
+ */
33
+ export type InferGenerationOutput<TResult, TFn> = TFn extends (result: any) => infer R ? InferGenerationOutputFromReturn<TResult, R> : TResult;
34
+ /**
35
+ * State machine for generation clients.
36
+ * Simpler than ChatClientState since generation is a single request/response cycle.
37
+ */
38
+ export type GenerationClientState = 'idle' | 'generating' | 'success' | 'error';
39
+ /**
40
+ * Well-known CUSTOM event names used by generation clients.
41
+ * These events are emitted by the server-side streaming helpers
42
+ * and consumed by the client-side GenerationClient.
43
+ */
44
+ export declare const GENERATION_EVENTS: {
45
+ /** The generation result payload */
46
+ readonly RESULT: "generation:result";
47
+ /** Progress update (0-100) with optional message */
48
+ readonly PROGRESS: "generation:progress";
49
+ /** Video job created with jobId */
50
+ readonly VIDEO_JOB_CREATED: "video:job:created";
51
+ /** Video job status update */
52
+ readonly VIDEO_STATUS: "video:status";
53
+ };
54
+ /**
55
+ * Options passed to a fetcher function by the generation client.
56
+ */
57
+ export interface GenerationFetcherOptions {
58
+ /** AbortSignal that is triggered when the user calls `stop()` */
59
+ signal: AbortSignal;
60
+ }
61
+ /**
62
+ * A direct async function that performs a generation request.
63
+ *
64
+ * Can return the result directly, or return a `Response` with an SSE body
65
+ * (e.g., from a TanStack Start server function using `toServerSentEventsResponse()`).
66
+ * When a `Response` is returned, the client will parse it as an SSE stream.
67
+ *
68
+ * @template TInput - The input type for the generation request
69
+ * @template TResult - The result type returned by the generation
70
+ */
71
+ export type GenerationFetcher<TInput, TResult> = (input: TInput, options?: GenerationFetcherOptions) => Promise<TResult | Response>;
72
+ /**
73
+ * Transport configuration for generation clients.
74
+ * Supports either a connect-based streaming adapter or a direct fetcher function.
75
+ */
76
+ export type GenerationTransport<TInput, TResult> = {
77
+ connection: ConnectConnectionAdapter;
78
+ fetcher?: never;
79
+ } | {
80
+ fetcher: GenerationFetcher<TInput, TResult>;
81
+ connection?: never;
82
+ };
83
+ /**
84
+ * Options for the GenerationClient.
85
+ *
86
+ * @template TInput - The input type for the generation request (used by consuming code)
87
+ * @template TResult - The result type returned by the generation
88
+ * @template TOutput - The output type after optional transform (defaults to TResult)
89
+ */
90
+ export interface GenerationClientOptions<_TInput, TResult, TOutput = TResult> {
91
+ /** Unique identifier for this generation client instance */
92
+ id?: string;
93
+ /** Additional body parameters to send with connect-based adapter requests */
94
+ body?: Record<string, any>;
95
+ /** Metadata used to register this generation hook with TanStack AI Devtools */
96
+ devtools?: Partial<AIDevtoolsClientMetadata>;
97
+ /**
98
+ * Factory that constructs the devtools bridge. Default is a no-op
99
+ * factory; the real implementation lives in `@tanstack/ai-client/devtools`.
100
+ */
101
+ devtoolsBridgeFactory?: GenerationDevtoolsBridgeFactory;
102
+ /**
103
+ * Callback when a result is received. Can optionally return a transformed value
104
+ * that replaces the stored result.
105
+ *
106
+ * - Return a non-null value to transform and store it as the result
107
+ * - Return `null` to keep the previous result unchanged
108
+ * - Return nothing (`void`) to store the raw result as-is
109
+ */
110
+ onResult?: (result: TResult) => TOutput | null | void;
111
+ /** Callback when an error occurs */
112
+ onError?: (error: Error) => void;
113
+ /** Callback when progress is reported (0-100) */
114
+ onProgress?: (progress: number, message?: string) => void;
115
+ /** Callback for each stream chunk (connect-based adapter mode only) */
116
+ onChunk?: (chunk: StreamChunk) => void;
117
+ /** @internal Called when result changes */
118
+ onResultChange?: (result: TOutput | null) => void;
119
+ /** @internal Called when loading state changes */
120
+ onLoadingChange?: (isLoading: boolean) => void;
121
+ /** @internal Called when error state changes */
122
+ onErrorChange?: (error: Error | undefined) => void;
123
+ /** @internal Called when generation status changes */
124
+ onStatusChange?: (status: GenerationClientState) => void;
125
+ }
126
+ /**
127
+ * Video status information returned during job polling.
128
+ */
129
+ export interface VideoStatusInfo {
130
+ /** Job identifier */
131
+ jobId: string;
132
+ /** Current status of the video generation job */
133
+ status: 'pending' | 'processing' | 'completed' | 'failed';
134
+ /** Progress percentage (0-100), if available */
135
+ progress?: number;
136
+ /** URL to the generated video (when completed) */
137
+ url?: string;
138
+ /** Error message if status is 'failed' */
139
+ error?: string;
140
+ }
141
+ /**
142
+ * Composite result for video generation (job completion).
143
+ */
144
+ export interface VideoGenerateResult {
145
+ /** Job identifier */
146
+ jobId: string;
147
+ /** Final status */
148
+ status: 'completed';
149
+ /** URL to the generated video */
150
+ url: string;
151
+ /** When the URL expires, if applicable */
152
+ expiresAt?: Date;
153
+ }
154
+ /**
155
+ * Options for the VideoGenerationClient.
156
+ */
157
+ export interface VideoGenerationClientOptions<TOutput = VideoGenerateResult> extends Omit<GenerationClientOptions<VideoGenerateInput, VideoGenerateResult, TOutput>, 'devtoolsBridgeFactory'> {
158
+ /**
159
+ * Factory that constructs the video devtools bridge. Default is a no-op
160
+ * factory; the real implementation lives in `@tanstack/ai-client/devtools`.
161
+ */
162
+ devtoolsBridgeFactory?: VideoDevtoolsBridgeFactory;
163
+ /** Callback when a video job is created */
164
+ onJobCreated?: (jobId: string) => void;
165
+ /** Callback on each status update */
166
+ onStatusUpdate?: (status: VideoStatusInfo) => void;
167
+ /** @internal Called when jobId changes */
168
+ onJobIdChange?: (jobId: string | null) => void;
169
+ /** @internal Called when video status changes */
170
+ onVideoStatusChange?: (status: VideoStatusInfo | null) => void;
171
+ }
172
+ /**
173
+ * Input for image generation.
174
+ */
175
+ export interface ImageGenerateInput {
176
+ /**
177
+ * Description of the desired image(s): plain text, or an ordered array of
178
+ * content parts (text + image) for image-conditioned generation
179
+ * (image-to-image, multi-reference, edit / inpaint).
180
+ */
181
+ prompt: MediaPrompt;
182
+ /** Number of images to generate (default: 1) */
183
+ numberOfImages?: number;
184
+ /** Image size in WIDTHxHEIGHT format (e.g., "1024x1024") */
185
+ size?: string;
186
+ /** Model-specific options */
187
+ modelOptions?: Record<string, any>;
188
+ }
189
+ /**
190
+ * Input for audio generation (music, sound effects).
191
+ */
192
+ export interface AudioGenerateInput {
193
+ /** Text description of the desired audio */
194
+ prompt: string;
195
+ /** Desired duration in seconds */
196
+ duration?: number;
197
+ /** Model-specific options */
198
+ modelOptions?: Record<string, any>;
199
+ }
200
+ /**
201
+ * Input for text-to-speech generation.
202
+ */
203
+ export interface SpeechGenerateInput {
204
+ /** The text to convert to speech */
205
+ text: string;
206
+ /** The voice to use for generation */
207
+ voice?: string;
208
+ /** The output audio format */
209
+ format?: 'mp3' | 'opus' | 'aac' | 'flac' | 'wav' | 'pcm';
210
+ /** The speed of the generated audio (0.25 to 4.0) */
211
+ speed?: number;
212
+ /** Model-specific options */
213
+ modelOptions?: Record<string, any>;
214
+ }
215
+ /**
216
+ * Input for audio transcription.
217
+ */
218
+ export interface TranscriptionGenerateInput {
219
+ /** The audio data to transcribe - can be base64 string, File, Blob, or ArrayBuffer */
220
+ audio: string | File | Blob | ArrayBuffer;
221
+ /** The language of the audio in ISO-639-1 format (e.g., 'en') */
222
+ language?: string;
223
+ /** An optional prompt to guide the transcription */
224
+ prompt?: string;
225
+ /** The format of the transcription output */
226
+ responseFormat?: 'json' | 'text' | 'srt' | 'verbose_json' | 'vtt';
227
+ /** Model-specific options */
228
+ modelOptions?: Record<string, any>;
229
+ }
230
+ /**
231
+ * Input for text summarization.
232
+ */
233
+ export interface SummarizeGenerateInput {
234
+ /** The text to summarize */
235
+ text: string;
236
+ /** Maximum length of the summary */
237
+ maxLength?: number;
238
+ /** Style of the summary */
239
+ style?: 'bullet-points' | 'paragraph' | 'concise';
240
+ /** Topics to focus on */
241
+ focus?: Array<string>;
242
+ /** Model-specific options */
243
+ modelOptions?: Record<string, any>;
244
+ }
245
+ /**
246
+ * Input for video generation.
247
+ */
248
+ export interface VideoGenerateInput {
249
+ /**
250
+ * Description of the desired video: plain text, or an ordered array of
251
+ * content parts (text + image) for image-conditioned generation
252
+ * (image-to-video, start/end frames).
253
+ */
254
+ prompt: MediaPrompt;
255
+ /** Video size — format depends on provider (e.g., "16:9", "1280x720") */
256
+ size?: string;
257
+ /** Video duration in seconds */
258
+ duration?: number;
259
+ /** Model-specific options */
260
+ modelOptions?: Record<string, any>;
261
+ }
@@ -0,0 +1,14 @@
1
+ const GENERATION_EVENTS = {
2
+ /** The generation result payload */
3
+ RESULT: "generation:result",
4
+ /** Progress update (0-100) with optional message */
5
+ PROGRESS: "generation:progress",
6
+ /** Video job created with jobId */
7
+ VIDEO_JOB_CREATED: "video:job:created",
8
+ /** Video job status update */
9
+ VIDEO_STATUS: "video:status"
10
+ };
11
+ export {
12
+ GENERATION_EVENTS
13
+ };
14
+ //# sourceMappingURL=generation-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generation-types.js","sources":["../../src/generation-types.ts"],"sourcesContent":["import type { MediaPrompt, StreamChunk } from '@tanstack/ai/client'\nimport type { ConnectConnectionAdapter } from './connection-adapters'\nimport type { AIDevtoolsClientMetadata } from './devtools'\nimport type {\n GenerationDevtoolsBridgeFactory,\n VideoDevtoolsBridgeFactory,\n} from './devtools-noop'\n\n// ===========================\n// Inference Utilities\n// ===========================\n\n/**\n * Maps an `onResult` transform's raw return type to the stored output type.\n *\n * - A concrete return (excluding null/void/undefined) becomes the output type.\n * - A return of only null/void/undefined falls back to TResult (the transform\n * reacted to the result or chose to keep it, rather than replacing it).\n *\n * Hooks infer `TReturn` directly from the `onResult` return position — a\n * covariant inference site that works even for an optional nested property —\n * which both contextually types the callback parameter as `TResult` and\n * narrows `result`. See issue #848.\n *\n * @template TResult - The raw result type from the generation\n * @template TReturn - The transform's return type (defaults to `void` when no\n * transform is provided)\n */\nexport type InferGenerationOutputFromReturn<TResult, TReturn> = [\n Exclude<TReturn, null | void | undefined>,\n] extends [never]\n ? TResult\n : Exclude<TReturn, null | void | undefined>\n\n/**\n * Infers the output type from an `onResult` callback's type.\n *\n * - If the callback returns a concrete type (excluding null/void/undefined), uses that type.\n * - If the callback only returns null/void/undefined, or is not provided, falls back to TResult.\n *\n * @template TResult - The raw result type from the generation\n * @template TFn - The onResult callback type (or undefined if not provided)\n */\nexport type InferGenerationOutput<TResult, TFn> = TFn extends (\n result: any,\n) => infer R\n ? InferGenerationOutputFromReturn<TResult, R>\n : TResult\n\n// ===========================\n// State\n// ===========================\n\n/**\n * State machine for generation clients.\n * Simpler than ChatClientState since generation is a single request/response cycle.\n */\nexport type GenerationClientState = 'idle' | 'generating' | 'success' | 'error'\n\n// ===========================\n// Event Constants\n// ===========================\n\n/**\n * Well-known CUSTOM event names used by generation clients.\n * These events are emitted by the server-side streaming helpers\n * and consumed by the client-side GenerationClient.\n */\nexport const GENERATION_EVENTS = {\n /** The generation result payload */\n RESULT: 'generation:result',\n /** Progress update (0-100) with optional message */\n PROGRESS: 'generation:progress',\n /** Video job created with jobId */\n VIDEO_JOB_CREATED: 'video:job:created',\n /** Video job status update */\n VIDEO_STATUS: 'video:status',\n} as const\n\n// ===========================\n// Transport Types\n// ===========================\n\n/**\n * Options passed to a fetcher function by the generation client.\n */\nexport interface GenerationFetcherOptions {\n /** AbortSignal that is triggered when the user calls `stop()` */\n signal: AbortSignal\n}\n\n/**\n * A direct async function that performs a generation request.\n *\n * Can return the result directly, or return a `Response` with an SSE body\n * (e.g., from a TanStack Start server function using `toServerSentEventsResponse()`).\n * When a `Response` is returned, the client will parse it as an SSE stream.\n *\n * @template TInput - The input type for the generation request\n * @template TResult - The result type returned by the generation\n */\nexport type GenerationFetcher<TInput, TResult> = (\n input: TInput,\n options?: GenerationFetcherOptions,\n) => Promise<TResult | Response>\n\n/**\n * Transport configuration for generation clients.\n * Supports either a connect-based streaming adapter or a direct fetcher function.\n */\nexport type GenerationTransport<TInput, TResult> =\n | { connection: ConnectConnectionAdapter; fetcher?: never }\n | { fetcher: GenerationFetcher<TInput, TResult>; connection?: never }\n\n// ===========================\n// Client Options\n// ===========================\n\n/**\n * Options for the GenerationClient.\n *\n * @template TInput - The input type for the generation request (used by consuming code)\n * @template TResult - The result type returned by the generation\n * @template TOutput - The output type after optional transform (defaults to TResult)\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention -- _TInput is unused in the interface body but part of the public positional generic API (callers supply it for inference)\nexport interface GenerationClientOptions<_TInput, TResult, TOutput = TResult> {\n /** Unique identifier for this generation client instance */\n id?: string\n\n /** Additional body parameters to send with connect-based adapter requests */\n body?: Record<string, any>\n\n /** Metadata used to register this generation hook with TanStack AI Devtools */\n devtools?: Partial<AIDevtoolsClientMetadata>\n\n /**\n * Factory that constructs the devtools bridge. Default is a no-op\n * factory; the real implementation lives in `@tanstack/ai-client/devtools`.\n */\n devtoolsBridgeFactory?: GenerationDevtoolsBridgeFactory\n\n /**\n * Callback when a result is received. Can optionally return a transformed value\n * that replaces the stored result.\n *\n * - Return a non-null value to transform and store it as the result\n * - Return `null` to keep the previous result unchanged\n * - Return nothing (`void`) to store the raw result as-is\n */\n onResult?: (result: TResult) => TOutput | null | void\n /** Callback when an error occurs */\n onError?: (error: Error) => void\n /** Callback when progress is reported (0-100) */\n onProgress?: (progress: number, message?: string) => void\n /** Callback for each stream chunk (connect-based adapter mode only) */\n onChunk?: (chunk: StreamChunk) => void\n\n // Framework state callbacks (set by hooks, not users)\n /** @internal Called when result changes */\n onResultChange?: (result: TOutput | null) => void\n /** @internal Called when loading state changes */\n onLoadingChange?: (isLoading: boolean) => void\n /** @internal Called when error state changes */\n onErrorChange?: (error: Error | undefined) => void\n /** @internal Called when generation status changes */\n onStatusChange?: (status: GenerationClientState) => void\n}\n\n// ===========================\n// Video-Specific Options\n// ===========================\n\n/**\n * Video status information returned during job polling.\n */\nexport interface VideoStatusInfo {\n /** Job identifier */\n jobId: string\n /** Current status of the video generation job */\n status: 'pending' | 'processing' | 'completed' | 'failed'\n /** Progress percentage (0-100), if available */\n progress?: number\n /** URL to the generated video (when completed) */\n url?: string\n /** Error message if status is 'failed' */\n error?: string\n}\n\n/**\n * Composite result for video generation (job completion).\n */\nexport interface VideoGenerateResult {\n /** Job identifier */\n jobId: string\n /** Final status */\n status: 'completed'\n /** URL to the generated video */\n url: string\n /** When the URL expires, if applicable */\n expiresAt?: Date\n}\n\n/**\n * Options for the VideoGenerationClient.\n */\nexport interface VideoGenerationClientOptions<\n TOutput = VideoGenerateResult,\n> extends Omit<\n GenerationClientOptions<VideoGenerateInput, VideoGenerateResult, TOutput>,\n 'devtoolsBridgeFactory'\n> {\n /**\n * Factory that constructs the video devtools bridge. Default is a no-op\n * factory; the real implementation lives in `@tanstack/ai-client/devtools`.\n */\n devtoolsBridgeFactory?: VideoDevtoolsBridgeFactory\n\n /** Callback when a video job is created */\n onJobCreated?: (jobId: string) => void\n /** Callback on each status update */\n onStatusUpdate?: (status: VideoStatusInfo) => void\n\n // Framework state callbacks\n /** @internal Called when jobId changes */\n onJobIdChange?: (jobId: string | null) => void\n /** @internal Called when video status changes */\n onVideoStatusChange?: (status: VideoStatusInfo | null) => void\n}\n\n// ===========================\n// Input Types\n// ===========================\n\n/**\n * Input for image generation.\n */\nexport interface ImageGenerateInput {\n /**\n * Description of the desired image(s): plain text, or an ordered array of\n * content parts (text + image) for image-conditioned generation\n * (image-to-image, multi-reference, edit / inpaint).\n */\n prompt: MediaPrompt\n /** Number of images to generate (default: 1) */\n numberOfImages?: number\n /** Image size in WIDTHxHEIGHT format (e.g., \"1024x1024\") */\n size?: string\n /** Model-specific options */\n modelOptions?: Record<string, any>\n}\n\n/**\n * Input for audio generation (music, sound effects).\n */\nexport interface AudioGenerateInput {\n /** Text description of the desired audio */\n prompt: string\n /** Desired duration in seconds */\n duration?: number\n /** Model-specific options */\n modelOptions?: Record<string, any>\n}\n\n/**\n * Input for text-to-speech generation.\n */\nexport interface SpeechGenerateInput {\n /** The text to convert to speech */\n text: string\n /** The voice to use for generation */\n voice?: string\n /** The output audio format */\n format?: 'mp3' | 'opus' | 'aac' | 'flac' | 'wav' | 'pcm'\n /** The speed of the generated audio (0.25 to 4.0) */\n speed?: number\n /** Model-specific options */\n modelOptions?: Record<string, any>\n}\n\n/**\n * Input for audio transcription.\n */\nexport interface TranscriptionGenerateInput {\n /** The audio data to transcribe - can be base64 string, File, Blob, or ArrayBuffer */\n audio: string | File | Blob | ArrayBuffer\n /** The language of the audio in ISO-639-1 format (e.g., 'en') */\n language?: string\n /** An optional prompt to guide the transcription */\n prompt?: string\n /** The format of the transcription output */\n responseFormat?: 'json' | 'text' | 'srt' | 'verbose_json' | 'vtt'\n /** Model-specific options */\n modelOptions?: Record<string, any>\n}\n\n/**\n * Input for text summarization.\n */\nexport interface SummarizeGenerateInput {\n /** The text to summarize */\n text: string\n /** Maximum length of the summary */\n maxLength?: number\n /** Style of the summary */\n style?: 'bullet-points' | 'paragraph' | 'concise'\n /** Topics to focus on */\n focus?: Array<string>\n /** Model-specific options */\n modelOptions?: Record<string, any>\n}\n\n/**\n * Input for video generation.\n */\nexport interface VideoGenerateInput {\n /**\n * Description of the desired video: plain text, or an ordered array of\n * content parts (text + image) for image-conditioned generation\n * (image-to-video, start/end frames).\n */\n prompt: MediaPrompt\n /** Video size — format depends on provider (e.g., \"16:9\", \"1280x720\") */\n size?: string\n /** Video duration in seconds */\n duration?: number\n /** Model-specific options */\n modelOptions?: Record<string, any>\n}\n"],"names":[],"mappings":"AAoEO,MAAM,oBAAoB;AAAA;AAAA,EAE/B,QAAQ;AAAA;AAAA,EAER,UAAU;AAAA;AAAA,EAEV,mBAAmB;AAAA;AAAA,EAEnB,cAAc;AAChB;"}
@@ -0,0 +1,20 @@
1
+ export { AudioRecorder } from './audio-recorder.js';
2
+ export type { AudioRecorderOptions, AudioRecorderState, AudioRecording, InferAudioRecordingOutput, } from './audio-recorder.js';
3
+ export { ChatClient } from './chat-client.js';
4
+ export { createMcpAppBridge } from './mcp-app-bridge.js';
5
+ export type { McpAppBridge, CreateMcpAppBridgeOptions } from './mcp-app-bridge.js';
6
+ export { RealtimeClient } from './realtime-client.js';
7
+ export { GenerationClient } from './generation-client.js';
8
+ export { VideoGenerationClient } from './video-generation-client.js';
9
+ export type { UIMessage, MessagePart, TextPart, ToolCallPart, ToolResultPart, ThinkingPart, StructuredOutputPart, ChatClientPersistence, ChatClientOptions, ClientContextOptionFromTools, ChatRequestBody, InferChatMessages, InferredClientContext, ChatClientState, ConnectionStatus, ChatFetcher, ChatFetcherInput, ChatFetcherOptions, ChatTransport, DistributedOmit, MultimodalContent, } from './types.js';
10
+ export type { InferGenerationOutput, InferGenerationOutputFromReturn, GenerationClientState, GenerationClientOptions, GenerationFetcher, GenerationFetcherOptions, GenerationTransport, VideoGenerationClientOptions, VideoStatusInfo, VideoGenerateResult, ImageGenerateInput, AudioGenerateInput, SpeechGenerateInput, TranscriptionGenerateInput, SummarizeGenerateInput, VideoGenerateInput, } from './generation-types.js';
11
+ export { GENERATION_EVENTS } from './generation-types.js';
12
+ export { UnsupportedResponseStreamError } from './response-stream.js';
13
+ export { clientTools, createChatClientOptions } from './types.js';
14
+ export { createAIDevtoolsGenerationPreview, type AIDevtoolsClientMetadata, type AIDevtoolsDisplayOptions, type AIDevtoolsGenerationMediaItem, type AIDevtoolsGenerationPreview, type AIDevtoolsGenerationProgress, type AIDevtoolsGenerationVideoJob, } from './devtools.js';
15
+ export type { ExtractToolNames, ExtractToolInput, ExtractToolOutput, } from './tool-types.js';
16
+ export type { AnyClientTool } from '@tanstack/ai/client';
17
+ export type { RealtimeAdapter, RealtimeConnection, RealtimeClientOptions, RealtimeClientState, RealtimeStateChangeCallback, } from './realtime-types.js';
18
+ export { fetchServerSentEvents, fetchHttpStream, xhrServerSentEvents, xhrHttpStream, stream, rpcStream, StreamTruncatedError, type ConnectConnectionAdapter, type ConnectionAdapter, type FetchConnectionOptions, type RunAgentInputContext, type SubscribeConnectionAdapter, type XhrConnectionOptions, } from './connection-adapters.js';
19
+ export { uiMessageToModelMessages, modelMessageToUIMessage, modelMessagesToUIMessages, convertMessagesToModelMessages, normalizeToUIMessage, generateMessageId, } from '@tanstack/ai/client';
20
+ export { StreamProcessor, ImmediateStrategy, PunctuationStrategy, BatchStrategy, WordBoundaryStrategy, CompositeStrategy, parsePartialJSON, PartialJSONParser, defaultJSONParser, type ChunkStrategy, type StreamProcessorOptions, type StreamProcessorEvents, type InternalToolCallState, type ToolCallState, type ToolResultState, type JSONParser, type ChunkRecording, type ProcessorResult, type ProcessorState, } from '@tanstack/ai/client';
@@ -0,0 +1,48 @@
1
+ import { AudioRecorder } from "./audio-recorder.js";
2
+ import { ChatClient } from "./chat-client.js";
3
+ import { createMcpAppBridge } from "./mcp-app-bridge.js";
4
+ import { RealtimeClient } from "./realtime-client.js";
5
+ import { GenerationClient } from "./generation-client.js";
6
+ import { VideoGenerationClient } from "./video-generation-client.js";
7
+ import { GENERATION_EVENTS } from "./generation-types.js";
8
+ import { UnsupportedResponseStreamError } from "./response-stream.js";
9
+ import { clientTools, createChatClientOptions } from "./types.js";
10
+ import { createAIDevtoolsGenerationPreview } from "./devtools.js";
11
+ import { StreamTruncatedError, fetchHttpStream, fetchServerSentEvents, rpcStream, stream, xhrHttpStream, xhrServerSentEvents } from "./connection-adapters.js";
12
+ import { BatchStrategy, CompositeStrategy, ImmediateStrategy, PartialJSONParser, PunctuationStrategy, StreamProcessor, WordBoundaryStrategy, convertMessagesToModelMessages, defaultJSONParser, generateMessageId, modelMessageToUIMessage, modelMessagesToUIMessages, normalizeToUIMessage, parsePartialJSON, uiMessageToModelMessages } from "@tanstack/ai/client";
13
+ export {
14
+ AudioRecorder,
15
+ BatchStrategy,
16
+ ChatClient,
17
+ CompositeStrategy,
18
+ GENERATION_EVENTS,
19
+ GenerationClient,
20
+ ImmediateStrategy,
21
+ PartialJSONParser,
22
+ PunctuationStrategy,
23
+ RealtimeClient,
24
+ StreamProcessor,
25
+ StreamTruncatedError,
26
+ UnsupportedResponseStreamError,
27
+ VideoGenerationClient,
28
+ WordBoundaryStrategy,
29
+ clientTools,
30
+ convertMessagesToModelMessages,
31
+ createAIDevtoolsGenerationPreview,
32
+ createChatClientOptions,
33
+ createMcpAppBridge,
34
+ defaultJSONParser,
35
+ fetchHttpStream,
36
+ fetchServerSentEvents,
37
+ generateMessageId,
38
+ modelMessageToUIMessage,
39
+ modelMessagesToUIMessages,
40
+ normalizeToUIMessage,
41
+ parsePartialJSON,
42
+ rpcStream,
43
+ stream,
44
+ uiMessageToModelMessages,
45
+ xhrHttpStream,
46
+ xhrServerSentEvents
47
+ };
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
@@ -0,0 +1,27 @@
1
+ export interface CreateMcpAppBridgeOptions {
2
+ threadId: string;
3
+ callEndpoint: string;
4
+ chat: {
5
+ sendMessage: (content: string, body?: Record<string, unknown>) => Promise<void>;
6
+ };
7
+ fetchImpl?: typeof fetch;
8
+ onLink?: (url: string) => void;
9
+ }
10
+ export interface McpAppBridge {
11
+ callTool: (input: {
12
+ serverId?: string;
13
+ toolName: string;
14
+ args?: Record<string, unknown>;
15
+ /**
16
+ * Reserved — forwarded to the call handler for correlation purposes but
17
+ * not consumed by the handler. Accepted on the wire; the handler does not
18
+ * read it (mirrors the `meta` convention on `UIResourcePart`).
19
+ */
20
+ messageId?: string;
21
+ }) => Promise<unknown>;
22
+ sendPrompt: (text: string) => Promise<void>;
23
+ openLink: (url: string) => {
24
+ isError: boolean;
25
+ };
26
+ }
27
+ export declare function createMcpAppBridge(options: CreateMcpAppBridgeOptions): McpAppBridge;
@@ -0,0 +1,70 @@
1
+ function isToolCallResponse(value) {
2
+ return value !== null && typeof value === "object" && "ok" in value && typeof value.ok === "boolean";
3
+ }
4
+ const SAFE_LINK_SCHEMES = /* @__PURE__ */ new Set(["http:", "https:", "mailto:"]);
5
+ function isSafeLink(url) {
6
+ try {
7
+ return SAFE_LINK_SCHEMES.has(new URL(url).protocol);
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+ function createMcpAppBridge(options) {
13
+ const { threadId, callEndpoint, chat, fetchImpl, onLink } = options;
14
+ const doFetch = fetchImpl ?? fetch;
15
+ return {
16
+ async callTool(input) {
17
+ const response = await doFetch(callEndpoint, {
18
+ method: "POST",
19
+ headers: { "content-type": "application/json" },
20
+ body: JSON.stringify({
21
+ threadId,
22
+ serverId: input.serverId,
23
+ toolName: input.toolName,
24
+ args: input.args,
25
+ messageId: input.messageId
26
+ })
27
+ });
28
+ if (!response.ok) {
29
+ throw new Error(`MCP app tool call failed: HTTP ${response.status}`);
30
+ }
31
+ const raw = await response.json();
32
+ if (!isToolCallResponse(raw)) {
33
+ throw new Error("MCP app tool call failed");
34
+ }
35
+ if (!raw.ok) {
36
+ throw new Error(raw.error ?? "MCP app tool call failed");
37
+ }
38
+ return raw.result;
39
+ },
40
+ async sendPrompt(text) {
41
+ await chat.sendMessage(text);
42
+ },
43
+ openLink(url) {
44
+ if (!isSafeLink(url)) {
45
+ console.warn(
46
+ "[mcp-app-bridge] openLink rejected: unsupported URL scheme",
47
+ url
48
+ );
49
+ return { isError: true };
50
+ }
51
+ if (onLink) {
52
+ try {
53
+ onLink(url);
54
+ return { isError: false };
55
+ } catch (err) {
56
+ console.warn("[mcp-app-bridge] openLink: onLink handler threw", err);
57
+ return { isError: true };
58
+ }
59
+ }
60
+ console.warn(
61
+ "[mcp-app-bridge] openLink ignored: no onLink handler configured"
62
+ );
63
+ return { isError: true };
64
+ }
65
+ };
66
+ }
67
+ export {
68
+ createMcpAppBridge
69
+ };
70
+ //# sourceMappingURL=mcp-app-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-app-bridge.js","sources":["../../src/mcp-app-bridge.ts"],"sourcesContent":["export interface CreateMcpAppBridgeOptions {\n threadId: string\n callEndpoint: string\n chat: {\n sendMessage: (\n content: string,\n body?: Record<string, unknown>,\n ) => Promise<void>\n }\n fetchImpl?: typeof fetch\n onLink?: (url: string) => void\n}\n\nexport interface McpAppBridge {\n callTool: (input: {\n serverId?: string\n toolName: string\n args?: Record<string, unknown>\n /**\n * Reserved — forwarded to the call handler for correlation purposes but\n * not consumed by the handler. Accepted on the wire; the handler does not\n * read it (mirrors the `meta` convention on `UIResourcePart`).\n */\n messageId?: string\n }) => Promise<unknown>\n sendPrompt: (text: string) => Promise<void>\n openLink: (url: string) => { isError: boolean }\n}\n\ninterface ToolCallResponse {\n ok: boolean\n result?: unknown\n error?: string\n}\n\nfunction isToolCallResponse(value: unknown): value is ToolCallResponse {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'ok' in value &&\n typeof value.ok === 'boolean'\n )\n}\n\n// Links arrive from an untrusted sandboxed widget. Only hand http(s)/mailto\n// URLs to the host's onLink; reject javascript:/data:/file:/etc. so a widget\n// can't smuggle a script-executing or local-resource URL through the bridge.\nconst SAFE_LINK_SCHEMES = new Set(['http:', 'https:', 'mailto:'])\nfunction isSafeLink(url: string): boolean {\n try {\n return SAFE_LINK_SCHEMES.has(new URL(url).protocol)\n } catch {\n return false\n }\n}\n\nexport function createMcpAppBridge(\n options: CreateMcpAppBridgeOptions,\n): McpAppBridge {\n const { threadId, callEndpoint, chat, fetchImpl, onLink } = options\n const doFetch = fetchImpl ?? fetch\n\n return {\n async callTool(input) {\n const response = await doFetch(callEndpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n threadId,\n serverId: input.serverId,\n toolName: input.toolName,\n args: input.args,\n messageId: input.messageId,\n }),\n })\n\n if (!response.ok) {\n throw new Error(`MCP app tool call failed: HTTP ${response.status}`)\n }\n\n const raw: unknown = await response.json()\n if (!isToolCallResponse(raw)) {\n throw new Error('MCP app tool call failed')\n }\n\n if (!raw.ok) {\n throw new Error(raw.error ?? 'MCP app tool call failed')\n }\n\n return raw.result\n },\n\n async sendPrompt(text) {\n await chat.sendMessage(text)\n },\n\n openLink(url) {\n if (!isSafeLink(url)) {\n console.warn(\n '[mcp-app-bridge] openLink rejected: unsupported URL scheme',\n url,\n )\n return { isError: true }\n }\n if (onLink) {\n try {\n onLink(url)\n return { isError: false }\n } catch (err) {\n console.warn('[mcp-app-bridge] openLink: onLink handler threw', err)\n return { isError: true }\n }\n }\n console.warn(\n '[mcp-app-bridge] openLink ignored: no onLink handler configured',\n )\n return { isError: true }\n },\n }\n}\n"],"names":[],"mappings":"AAmCA,SAAS,mBAAmB,OAA2C;AACrE,SACE,UAAU,QACV,OAAO,UAAU,YACjB,QAAQ,SACR,OAAO,MAAM,OAAO;AAExB;AAKA,MAAM,oBAAoB,oBAAI,IAAI,CAAC,SAAS,UAAU,SAAS,CAAC;AAChE,SAAS,WAAW,KAAsB;AACxC,MAAI;AACF,WAAO,kBAAkB,IAAI,IAAI,IAAI,GAAG,EAAE,QAAQ;AAAA,EACpD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,mBACd,SACc;AACd,QAAM,EAAE,UAAU,cAAc,MAAM,WAAW,WAAW;AAC5D,QAAM,UAAU,aAAa;AAE7B,SAAO;AAAA,IACL,MAAM,SAAS,OAAO;AACpB,YAAM,WAAW,MAAM,QAAQ,cAAc;AAAA,QAC3C,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,QAC3B,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA,UAAU,MAAM;AAAA,UAChB,UAAU,MAAM;AAAA,UAChB,MAAM,MAAM;AAAA,UACZ,WAAW,MAAM;AAAA,QAAA,CAClB;AAAA,MAAA,CACF;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,kCAAkC,SAAS,MAAM,EAAE;AAAA,MACrE;AAEA,YAAM,MAAe,MAAM,SAAS,KAAA;AACpC,UAAI,CAAC,mBAAmB,GAAG,GAAG;AAC5B,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC5C;AAEA,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,IAAI,SAAS,0BAA0B;AAAA,MACzD;AAEA,aAAO,IAAI;AAAA,IACb;AAAA,IAEA,MAAM,WAAW,MAAM;AACrB,YAAM,KAAK,YAAY,IAAI;AAAA,IAC7B;AAAA,IAEA,SAAS,KAAK;AACZ,UAAI,CAAC,WAAW,GAAG,GAAG;AACpB,gBAAQ;AAAA,UACN;AAAA,UACA;AAAA,QAAA;AAEF,eAAO,EAAE,SAAS,KAAA;AAAA,MACpB;AACA,UAAI,QAAQ;AACV,YAAI;AACF,iBAAO,GAAG;AACV,iBAAO,EAAE,SAAS,MAAA;AAAA,QACpB,SAAS,KAAK;AACZ,kBAAQ,KAAK,mDAAmD,GAAG;AACnE,iBAAO,EAAE,SAAS,KAAA;AAAA,QACpB;AAAA,MACF;AACA,cAAQ;AAAA,QACN;AAAA,MAAA;AAEF,aAAO,EAAE,SAAS,KAAA;AAAA,IACpB;AAAA,EAAA;AAEJ;"}
@@ -0,0 +1,98 @@
1
+ import { AudioVisualization, RealtimeMessage, RealtimeMode, RealtimeStatus } from '@tanstack/ai/client';
2
+ import { RealtimeClientOptions, RealtimeStateChangeCallback } from './realtime-types.js';
3
+ /**
4
+ * Client for managing realtime voice conversations.
5
+ *
6
+ * Handles connection lifecycle, audio I/O, message state,
7
+ * and tool execution for realtime voice-to-voice AI interactions.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { RealtimeClient } from '@tanstack/ai-client'
12
+ * import { openaiRealtime } from '@tanstack/ai-openai'
13
+ *
14
+ * const client = new RealtimeClient({
15
+ * getToken: () => fetch('/api/realtime-token').then(r => r.json()),
16
+ * adapter: openaiRealtime(),
17
+ * tools: [myTool.client(handler)],
18
+ * onMessage: (msg) => console.log('Message:', msg),
19
+ * })
20
+ *
21
+ * await client.connect()
22
+ * ```
23
+ */
24
+ export declare class RealtimeClient {
25
+ private readonly options;
26
+ private connection;
27
+ private token;
28
+ private tokenRefreshTimeout;
29
+ private readonly clientTools;
30
+ private readonly stateChangeCallbacks;
31
+ private unsubscribers;
32
+ private state;
33
+ constructor(options: RealtimeClientOptions);
34
+ /**
35
+ * Connect to the realtime session.
36
+ * Fetches a token and establishes the connection.
37
+ */
38
+ connect(): Promise<void>;
39
+ /**
40
+ * Disconnect from the realtime session.
41
+ */
42
+ disconnect(): Promise<void>;
43
+ /**
44
+ * Start listening for voice input.
45
+ * Only needed when vadMode is 'manual'.
46
+ */
47
+ startListening(): void;
48
+ /**
49
+ * Stop listening for voice input.
50
+ * Only needed when vadMode is 'manual'.
51
+ */
52
+ stopListening(): void;
53
+ /**
54
+ * Interrupt the current assistant response.
55
+ */
56
+ interrupt(): void;
57
+ /**
58
+ * Send a text message instead of voice.
59
+ */
60
+ sendText(text: string): void;
61
+ /**
62
+ * Send an image to the conversation.
63
+ * @param imageData - Base64-encoded image data or a URL
64
+ * @param mimeType - MIME type of the image (e.g., 'image/png', 'image/jpeg')
65
+ */
66
+ sendImage(imageData: string, mimeType: string): void;
67
+ /** Get current connection status */
68
+ get status(): RealtimeStatus;
69
+ /** Get current mode */
70
+ get mode(): RealtimeMode;
71
+ /** Get conversation messages */
72
+ get messages(): Array<RealtimeMessage>;
73
+ /** Get current error, if any */
74
+ get error(): Error | null;
75
+ /** Get pending user transcript (while user is speaking) */
76
+ get pendingUserTranscript(): string | null;
77
+ /** Get pending assistant transcript (while assistant is speaking) */
78
+ get pendingAssistantTranscript(): string | null;
79
+ /** Get audio visualization data */
80
+ get audio(): AudioVisualization | null;
81
+ /**
82
+ * Subscribe to state changes.
83
+ * @returns Unsubscribe function
84
+ */
85
+ onStateChange(callback: RealtimeStateChangeCallback): () => void;
86
+ /**
87
+ * Clean up resources.
88
+ * Call this when disposing of the client.
89
+ */
90
+ destroy(): void;
91
+ private updateState;
92
+ private addMessage;
93
+ private scheduleTokenRefresh;
94
+ private refreshToken;
95
+ private subscribeToConnectionEvents;
96
+ private applySessionConfig;
97
+ private generateId;
98
+ }