@tanstack/ai-react 0.6.4 → 0.7.2

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/src/use-chat.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ChatClient } from '@tanstack/ai-client'
2
2
  import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react'
3
3
  import type { AnyClientTool, ModelMessage } from '@tanstack/ai'
4
- import type { ChatClientState } from '@tanstack/ai-client'
4
+ import type { ChatClientState, ConnectionStatus } from '@tanstack/ai-client'
5
5
 
6
6
  import type {
7
7
  MultimodalContent,
@@ -22,6 +22,10 @@ export function useChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
22
22
  const [isLoading, setIsLoading] = useState(false)
23
23
  const [error, setError] = useState<Error | undefined>(undefined)
24
24
  const [status, setStatus] = useState<ChatClientState>('ready')
25
+ const [isSubscribed, setIsSubscribed] = useState(false)
26
+ const [connectionStatus, setConnectionStatus] =
27
+ useState<ConnectionStatus>('disconnected')
28
+ const [sessionGenerating, setSessionGenerating] = useState(false)
25
29
 
26
30
  // Track current messages in a ref to preserve them when client is recreated
27
31
  const messagesRef = useRef<Array<UIMessage<TTools>>>(
@@ -78,6 +82,15 @@ export function useChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
78
82
  onStatusChange: (status: ChatClientState) => {
79
83
  setStatus(status)
80
84
  },
85
+ onSubscriptionChange: (nextIsSubscribed: boolean) => {
86
+ setIsSubscribed(nextIsSubscribed)
87
+ },
88
+ onConnectionStatusChange: (nextStatus: ConnectionStatus) => {
89
+ setConnectionStatus(nextStatus)
90
+ },
91
+ onSessionGeneratingChange: (isGenerating: boolean) => {
92
+ setSessionGenerating(isGenerating)
93
+ },
81
94
  })
82
95
  }, [clientId])
83
96
 
@@ -99,16 +112,29 @@ export function useChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
99
112
  }
100
113
  }, []) // Only run on mount - initialMessages are handled by ChatClient constructor
101
114
 
115
+ // Keep connection lifecycle opt-in and explicit.
116
+ useEffect(() => {
117
+ if (options.live) {
118
+ client.subscribe()
119
+ } else {
120
+ client.unsubscribe()
121
+ }
122
+ }, [client, options.live])
123
+
102
124
  // Cleanup on unmount: stop any in-flight requests
103
125
  // Note: We only cleanup when client changes or component unmounts.
104
126
  // DO NOT include isLoading in dependencies - that would cause the cleanup
105
127
  // to run when isLoading changes, aborting continuation requests.
106
128
  useEffect(() => {
107
129
  return () => {
108
- // Stop any active generation when component unmounts or client changes
109
- client.stop()
130
+ // live mode owns the connection lifecycle; non-live keeps request-only stop.
131
+ if (options.live) {
132
+ client.unsubscribe()
133
+ } else {
134
+ client.stop()
135
+ }
110
136
  }
111
- }, [client])
137
+ }, [client, options.live])
112
138
 
113
139
  // Note: Callback options (onResponse, onChunk, onFinish, onError, onToolCall)
114
140
  // are captured at client creation time. Changes to these callbacks require
@@ -176,6 +202,9 @@ export function useChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
176
202
  isLoading,
177
203
  error,
178
204
  status,
205
+ isSubscribed,
206
+ connectionStatus,
207
+ sessionGenerating,
179
208
  setMessages: setMessagesManually,
180
209
  clear,
181
210
  addToolResult,
@@ -1,7 +1,7 @@
1
1
  import { useGeneration } from './use-generation'
2
2
  import type { ImageGenerationResult, StreamChunk } from '@tanstack/ai'
3
3
  import type {
4
- ConnectionAdapter,
4
+ ConnectConnectionAdapter,
5
5
  GenerationClientState,
6
6
  GenerationFetcher,
7
7
  ImageGenerateInput,
@@ -14,13 +14,13 @@ import type {
14
14
  * @template TOutput - The output type after optional transform (defaults to ImageGenerationResult)
15
15
  */
16
16
  export interface UseGenerateImageOptions<TOutput = ImageGenerationResult> {
17
- /** Connection adapter for streaming transport (SSE, HTTP stream, custom) */
18
- connection?: ConnectionAdapter
17
+ /** Connect-based adapter for streaming transport (SSE, HTTP stream, custom) */
18
+ connection?: ConnectConnectionAdapter
19
19
  /** Direct async function for image generation */
20
20
  fetcher?: GenerationFetcher<ImageGenerateInput, ImageGenerationResult>
21
21
  /** Unique identifier for this generation instance */
22
22
  id?: string
23
- /** Additional body parameters to send with ConnectionAdapter requests */
23
+ /** Additional body parameters to send with connect-based adapter requests */
24
24
  body?: Record<string, any>
25
25
  /**
26
26
  * Callback when images are generated. Can optionally return a transformed value.
@@ -34,7 +34,7 @@ export interface UseGenerateImageOptions<TOutput = ImageGenerationResult> {
34
34
  onError?: (error: Error) => void
35
35
  /** Callback when progress is reported (0-100) */
36
36
  onProgress?: (progress: number, message?: string) => void
37
- /** Callback for each stream chunk (ConnectionAdapter mode only) */
37
+ /** Callback for each stream chunk (connect-based adapter mode only) */
38
38
  onChunk?: (chunk: StreamChunk) => void
39
39
  }
40
40
 
@@ -64,7 +64,7 @@ export interface UseGenerateImageReturn<TOutput = ImageGenerationResult> {
64
64
  * React hook for generating images using AI models.
65
65
  *
66
66
  * Supports two transport modes:
67
- * - **ConnectionAdapter** — Streaming transport (SSE, HTTP stream, custom)
67
+ * - **ConnectConnectionAdapter** — Streaming transport (SSE, HTTP stream, custom)
68
68
  * - **Fetcher** — Direct async function call
69
69
  *
70
70
  * @example
@@ -1,7 +1,7 @@
1
1
  import { useGeneration } from './use-generation'
2
2
  import type { StreamChunk, TTSResult } from '@tanstack/ai'
3
3
  import type {
4
- ConnectionAdapter,
4
+ ConnectConnectionAdapter,
5
5
  GenerationClientState,
6
6
  GenerationFetcher,
7
7
  InferGenerationOutput,
@@ -14,13 +14,13 @@ import type {
14
14
  * @template TOutput - The output type after optional transform (defaults to TTSResult)
15
15
  */
16
16
  export interface UseGenerateSpeechOptions<TOutput = TTSResult> {
17
- /** Connection adapter for streaming transport (SSE, HTTP stream, custom) */
18
- connection?: ConnectionAdapter
17
+ /** Connect-based adapter for streaming transport (SSE, HTTP stream, custom) */
18
+ connection?: ConnectConnectionAdapter
19
19
  /** Direct async function for speech generation */
20
20
  fetcher?: GenerationFetcher<SpeechGenerateInput, TTSResult>
21
21
  /** Unique identifier for this generation instance */
22
22
  id?: string
23
- /** Additional body parameters to send with ConnectionAdapter requests */
23
+ /** Additional body parameters to send with connect-based adapter requests */
24
24
  body?: Record<string, any>
25
25
  /**
26
26
  * Callback when speech is generated. Can optionally return a transformed value.
@@ -34,7 +34,7 @@ export interface UseGenerateSpeechOptions<TOutput = TTSResult> {
34
34
  onError?: (error: Error) => void
35
35
  /** Callback when progress is reported (0-100) */
36
36
  onProgress?: (progress: number, message?: string) => void
37
- /** Callback for each stream chunk (ConnectionAdapter mode only) */
37
+ /** Callback for each stream chunk (connect-based adapter mode only) */
38
38
  onChunk?: (chunk: StreamChunk) => void
39
39
  }
40
40
 
@@ -2,7 +2,7 @@ import { VideoGenerationClient } from '@tanstack/ai-client'
2
2
  import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react'
3
3
  import type { StreamChunk } from '@tanstack/ai'
4
4
  import type {
5
- ConnectionAdapter,
5
+ ConnectConnectionAdapter,
6
6
  GenerationClientState,
7
7
  GenerationFetcher,
8
8
  InferGenerationOutput,
@@ -15,13 +15,13 @@ import type {
15
15
  * Options for the useGenerateVideo hook.
16
16
  */
17
17
  export interface UseGenerateVideoOptions<TOutput = VideoGenerateResult> {
18
- /** Connection adapter for streaming transport (server handles polling) */
19
- connection?: ConnectionAdapter
18
+ /** Connect-based adapter for streaming transport (server handles polling) */
19
+ connection?: ConnectConnectionAdapter
20
20
  /** Direct async function that returns a completed video result */
21
21
  fetcher?: GenerationFetcher<VideoGenerateInput, VideoGenerateResult>
22
22
  /** Unique identifier for this generation instance */
23
23
  id?: string
24
- /** Additional body parameters to send with ConnectionAdapter requests */
24
+ /** Additional body parameters to send with connect-based adapter requests */
25
25
  body?: Record<string, any>
26
26
  /**
27
27
  * Callback when video generation completes. Can optionally return a transformed value.
@@ -39,7 +39,7 @@ export interface UseGenerateVideoOptions<TOutput = VideoGenerateResult> {
39
39
  onJobCreated?: (jobId: string) => void
40
40
  /** Callback on each status update */
41
41
  onStatusUpdate?: (status: VideoStatusInfo) => void
42
- /** Callback for each stream chunk (ConnectionAdapter mode only) */
42
+ /** Callback for each stream chunk (connect-based adapter mode only) */
43
43
  onChunk?: (chunk: StreamChunk) => void
44
44
  }
45
45
 
@@ -2,7 +2,7 @@ import { GenerationClient } from '@tanstack/ai-client'
2
2
  import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react'
3
3
  import type { StreamChunk } from '@tanstack/ai'
4
4
  import type {
5
- ConnectionAdapter,
5
+ ConnectConnectionAdapter,
6
6
  GenerationClientOptions,
7
7
  GenerationClientState,
8
8
  GenerationFetcher,
@@ -19,13 +19,13 @@ import type {
19
19
  * @template TOutput - The output type after optional transform (defaults to TResult)
20
20
  */
21
21
  export interface UseGenerationOptions<TInput, TResult, TOutput = TResult> {
22
- /** Connection adapter for streaming transport (SSE, HTTP stream, custom) */
23
- connection?: ConnectionAdapter
22
+ /** Connect-based adapter for streaming transport (SSE, HTTP stream, custom) */
23
+ connection?: ConnectConnectionAdapter
24
24
  /** Direct async function for one-shot generation (no streaming protocol needed) */
25
25
  fetcher?: GenerationFetcher<TInput, TResult>
26
26
  /** Unique identifier for this generation instance */
27
27
  id?: string
28
- /** Additional body parameters to send with ConnectionAdapter requests */
28
+ /** Additional body parameters to send with connect-based adapter requests */
29
29
  body?: Record<string, any>
30
30
  /**
31
31
  * Callback when a result is received. Can optionally return a transformed value.
@@ -39,7 +39,7 @@ export interface UseGenerationOptions<TInput, TResult, TOutput = TResult> {
39
39
  onError?: (error: Error) => void
40
40
  /** Callback when progress is reported (0-100) */
41
41
  onProgress?: (progress: number, message?: string) => void
42
- /** Callback for each stream chunk (ConnectionAdapter mode only) */
42
+ /** Callback for each stream chunk (connect-based adapter mode only) */
43
43
  onChunk?: (chunk: StreamChunk) => void
44
44
  }
45
45
 
@@ -0,0 +1,277 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react'
2
+ import { RealtimeClient } from '@tanstack/ai-client'
3
+ import type {
4
+ RealtimeMessage,
5
+ RealtimeMode,
6
+ RealtimeStatus,
7
+ } from '@tanstack/ai'
8
+ import type {
9
+ UseRealtimeChatOptions,
10
+ UseRealtimeChatReturn,
11
+ } from './realtime-types'
12
+
13
+ // Empty frequency data for when client is not connected
14
+ const emptyFrequencyData = new Uint8Array(128)
15
+ const emptyTimeDomainData = new Uint8Array(128).fill(128)
16
+
17
+ /**
18
+ * React hook for realtime voice conversations.
19
+ *
20
+ * Provides a simple interface for voice-to-voice AI interactions
21
+ * with support for multiple providers (OpenAI, ElevenLabs, etc.).
22
+ *
23
+ * @param options - Configuration options including adapter and callbacks
24
+ * @returns Hook return value with state and control methods
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * import { useRealtimeChat } from '@tanstack/ai-react'
29
+ * import { openaiRealtime } from '@tanstack/ai-openai'
30
+ *
31
+ * function VoiceChat() {
32
+ * const {
33
+ * status,
34
+ * mode,
35
+ * messages,
36
+ * connect,
37
+ * disconnect,
38
+ * inputLevel,
39
+ * outputLevel,
40
+ * } = useRealtimeChat({
41
+ * getToken: () => fetch('/api/realtime-token').then(r => r.json()),
42
+ * adapter: openaiRealtime(),
43
+ * })
44
+ *
45
+ * return (
46
+ * <div>
47
+ * <p>Status: {status}</p>
48
+ * <p>Mode: {mode}</p>
49
+ * <button onClick={status === 'idle' ? connect : disconnect}>
50
+ * {status === 'idle' ? 'Start' : 'Stop'}
51
+ * </button>
52
+ * </div>
53
+ * )
54
+ * }
55
+ * ```
56
+ */
57
+ export function useRealtimeChat(
58
+ options: UseRealtimeChatOptions,
59
+ ): UseRealtimeChatReturn {
60
+ // State
61
+ const [status, setStatus] = useState<RealtimeStatus>('idle')
62
+ const [mode, setMode] = useState<RealtimeMode>('idle')
63
+ const [messages, setMessages] = useState<Array<RealtimeMessage>>([])
64
+ const [pendingUserTranscript, setPendingUserTranscript] = useState<
65
+ string | null
66
+ >(null)
67
+ const [pendingAssistantTranscript, setPendingAssistantTranscript] = useState<
68
+ string | null
69
+ >(null)
70
+ const [error, setError] = useState<Error | null>(null)
71
+ const [inputLevel, setInputLevel] = useState(0)
72
+ const [outputLevel, setOutputLevel] = useState(0)
73
+ const [vadMode, setVADModeState] = useState<'server' | 'semantic' | 'manual'>(
74
+ options.vadMode ?? 'server',
75
+ )
76
+
77
+ // Refs
78
+ const clientRef = useRef<RealtimeClient | null>(null)
79
+ const optionsRef = useRef(options)
80
+ optionsRef.current = options
81
+ const animationFrameRef = useRef<number | null>(null)
82
+
83
+ // Create client instance - use ref to ensure we reuse the same instance
84
+ // This handles React StrictMode double-rendering
85
+ if (!clientRef.current) {
86
+ clientRef.current = new RealtimeClient({
87
+ getToken: optionsRef.current.getToken,
88
+ adapter: optionsRef.current.adapter,
89
+ tools: optionsRef.current.tools,
90
+ instructions: optionsRef.current.instructions,
91
+ voice: optionsRef.current.voice,
92
+ autoPlayback: optionsRef.current.autoPlayback,
93
+ autoCapture: optionsRef.current.autoCapture,
94
+ vadMode: optionsRef.current.vadMode,
95
+ outputModalities: optionsRef.current.outputModalities,
96
+ temperature: optionsRef.current.temperature,
97
+ maxOutputTokens: optionsRef.current.maxOutputTokens,
98
+ semanticEagerness: optionsRef.current.semanticEagerness,
99
+ onStatusChange: (newStatus) => {
100
+ setStatus(newStatus)
101
+ },
102
+ onModeChange: (newMode) => {
103
+ setMode(newMode)
104
+ optionsRef.current.onModeChange?.(newMode)
105
+ },
106
+ onMessage: (message) => {
107
+ setMessages((prev) => [...prev, message])
108
+ optionsRef.current.onMessage?.(message)
109
+ },
110
+ onError: (err) => {
111
+ setError(err)
112
+ optionsRef.current.onError?.(err)
113
+ },
114
+ onConnect: () => {
115
+ setError(null)
116
+ optionsRef.current.onConnect?.()
117
+ },
118
+ onDisconnect: () => {
119
+ optionsRef.current.onDisconnect?.()
120
+ },
121
+ onInterrupted: () => {
122
+ setPendingAssistantTranscript(null)
123
+ optionsRef.current.onInterrupted?.()
124
+ },
125
+ })
126
+
127
+ // Subscribe to state changes for transcripts
128
+ clientRef.current.onStateChange((state) => {
129
+ setPendingUserTranscript(state.pendingUserTranscript)
130
+ setPendingAssistantTranscript(state.pendingAssistantTranscript)
131
+ })
132
+ }
133
+
134
+ const client = clientRef.current
135
+
136
+ // Audio level animation loop
137
+ useEffect(() => {
138
+ function updateLevels() {
139
+ if (clientRef.current?.audio) {
140
+ setInputLevel(clientRef.current.audio.inputLevel)
141
+ setOutputLevel(clientRef.current.audio.outputLevel)
142
+ }
143
+ animationFrameRef.current = requestAnimationFrame(updateLevels)
144
+ }
145
+
146
+ if (status === 'connected') {
147
+ updateLevels()
148
+ }
149
+
150
+ return () => {
151
+ if (animationFrameRef.current) {
152
+ cancelAnimationFrame(animationFrameRef.current)
153
+ animationFrameRef.current = null
154
+ }
155
+ }
156
+ }, [status])
157
+
158
+ // Cleanup on unmount
159
+ useEffect(() => {
160
+ return () => {
161
+ clientRef.current?.destroy()
162
+ }
163
+ }, [])
164
+
165
+ // Connection methods
166
+ const connect = useCallback(async () => {
167
+ setError(null)
168
+ setMessages([])
169
+ setPendingUserTranscript(null)
170
+ setPendingAssistantTranscript(null)
171
+ await client.connect()
172
+ }, [client])
173
+
174
+ const disconnect = useCallback(async () => {
175
+ await client.disconnect()
176
+ }, [client])
177
+
178
+ // Voice control methods
179
+ const startListening = useCallback(() => {
180
+ client.startListening()
181
+ }, [client])
182
+
183
+ const stopListening = useCallback(() => {
184
+ client.stopListening()
185
+ }, [client])
186
+
187
+ const interrupt = useCallback(() => {
188
+ client.interrupt()
189
+ }, [client])
190
+
191
+ // Text input
192
+ const sendText = useCallback(
193
+ (text: string) => {
194
+ client.sendText(text)
195
+ },
196
+ [client],
197
+ )
198
+
199
+ // Image input
200
+ const sendImage = useCallback(
201
+ (imageData: string, mimeType: string) => {
202
+ client.sendImage(imageData, mimeType)
203
+ },
204
+ [client],
205
+ )
206
+
207
+ // Audio visualization
208
+ const getInputFrequencyData = useCallback(() => {
209
+ return (
210
+ clientRef.current?.audio?.getInputFrequencyData() ?? emptyFrequencyData
211
+ )
212
+ }, [])
213
+
214
+ const getOutputFrequencyData = useCallback(() => {
215
+ return (
216
+ clientRef.current?.audio?.getOutputFrequencyData() ?? emptyFrequencyData
217
+ )
218
+ }, [])
219
+
220
+ const getInputTimeDomainData = useCallback(() => {
221
+ return (
222
+ clientRef.current?.audio?.getInputTimeDomainData() ?? emptyTimeDomainData
223
+ )
224
+ }, [])
225
+
226
+ const getOutputTimeDomainData = useCallback(() => {
227
+ return (
228
+ clientRef.current?.audio?.getOutputTimeDomainData() ?? emptyTimeDomainData
229
+ )
230
+ }, [])
231
+
232
+ // VAD mode control
233
+ const setVADMode = useCallback(
234
+ (newMode: 'server' | 'semantic' | 'manual') => {
235
+ setVADModeState(newMode)
236
+ // TODO: Update session config if connected
237
+ },
238
+ [],
239
+ )
240
+
241
+ return {
242
+ // Connection state
243
+ status,
244
+ error,
245
+ connect,
246
+ disconnect,
247
+
248
+ // Conversation state
249
+ mode,
250
+ messages,
251
+ pendingUserTranscript,
252
+ pendingAssistantTranscript,
253
+
254
+ // Voice control
255
+ startListening,
256
+ stopListening,
257
+ interrupt,
258
+
259
+ // Text input
260
+ sendText,
261
+
262
+ // Image input
263
+ sendImage,
264
+
265
+ // Audio visualization
266
+ inputLevel,
267
+ outputLevel,
268
+ getInputFrequencyData,
269
+ getOutputFrequencyData,
270
+ getInputTimeDomainData,
271
+ getOutputTimeDomainData,
272
+
273
+ // VAD control
274
+ vadMode,
275
+ setVADMode,
276
+ }
277
+ }
@@ -1,7 +1,7 @@
1
1
  import { useGeneration } from './use-generation'
2
2
  import type { StreamChunk, SummarizationResult } from '@tanstack/ai'
3
3
  import type {
4
- ConnectionAdapter,
4
+ ConnectConnectionAdapter,
5
5
  GenerationClientState,
6
6
  GenerationFetcher,
7
7
  InferGenerationOutput,
@@ -14,13 +14,13 @@ import type {
14
14
  * @template TOutput - The output type after optional transform (defaults to SummarizationResult)
15
15
  */
16
16
  export interface UseSummarizeOptions<TOutput = SummarizationResult> {
17
- /** Connection adapter for streaming transport (SSE, HTTP stream, custom) */
18
- connection?: ConnectionAdapter
17
+ /** Connect-based adapter for streaming transport (SSE, HTTP stream, custom) */
18
+ connection?: ConnectConnectionAdapter
19
19
  /** Direct async function for summarization */
20
20
  fetcher?: GenerationFetcher<SummarizeGenerateInput, SummarizationResult>
21
21
  /** Unique identifier for this generation instance */
22
22
  id?: string
23
- /** Additional body parameters to send with ConnectionAdapter requests */
23
+ /** Additional body parameters to send with connect-based adapter requests */
24
24
  body?: Record<string, any>
25
25
  /**
26
26
  * Callback when summarization is complete. Can optionally return a transformed value.
@@ -34,7 +34,7 @@ export interface UseSummarizeOptions<TOutput = SummarizationResult> {
34
34
  onError?: (error: Error) => void
35
35
  /** Callback when progress is reported (0-100) */
36
36
  onProgress?: (progress: number, message?: string) => void
37
- /** Callback for each stream chunk (ConnectionAdapter mode only) */
37
+ /** Callback for each stream chunk (connect-based adapter mode only) */
38
38
  onChunk?: (chunk: StreamChunk) => void
39
39
  }
40
40
 
@@ -1,7 +1,7 @@
1
1
  import { useGeneration } from './use-generation'
2
2
  import type { StreamChunk, TranscriptionResult } from '@tanstack/ai'
3
3
  import type {
4
- ConnectionAdapter,
4
+ ConnectConnectionAdapter,
5
5
  GenerationClientState,
6
6
  GenerationFetcher,
7
7
  InferGenerationOutput,
@@ -14,13 +14,13 @@ import type {
14
14
  * @template TOutput - The output type after optional transform (defaults to TranscriptionResult)
15
15
  */
16
16
  export interface UseTranscriptionOptions<TOutput = TranscriptionResult> {
17
- /** Connection adapter for streaming transport (SSE, HTTP stream, custom) */
18
- connection?: ConnectionAdapter
17
+ /** Connect-based adapter for streaming transport (SSE, HTTP stream, custom) */
18
+ connection?: ConnectConnectionAdapter
19
19
  /** Direct async function for transcription */
20
20
  fetcher?: GenerationFetcher<TranscriptionGenerateInput, TranscriptionResult>
21
21
  /** Unique identifier for this generation instance */
22
22
  id?: string
23
- /** Additional body parameters to send with ConnectionAdapter requests */
23
+ /** Additional body parameters to send with connect-based adapter requests */
24
24
  body?: Record<string, any>
25
25
  /**
26
26
  * Callback when transcription is complete. Can optionally return a transformed value.
@@ -34,7 +34,7 @@ export interface UseTranscriptionOptions<TOutput = TranscriptionResult> {
34
34
  onError?: (error: Error) => void
35
35
  /** Callback when progress is reported (0-100) */
36
36
  onProgress?: (progress: number, message?: string) => void
37
- /** Callback for each stream chunk (ConnectionAdapter mode only) */
37
+ /** Callback for each stream chunk (connect-based adapter mode only) */
38
38
  onChunk?: (chunk: StreamChunk) => void
39
39
  }
40
40