@tanstack/ai-remix 0.0.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.
@@ -0,0 +1,105 @@
1
+ import { createGeneration } from './create-generation.ts'
2
+ import { reconstructTranscriptionResult } from '@tanstack/ai-client'
3
+ import type { Handle } from 'remix/ui'
4
+ import type { TranscriptionResult } from '@tanstack/ai'
5
+ import type {
6
+ GenerationPersistenceOptions,
7
+ TranscriptionGenerateInput,
8
+ } from '@tanstack/ai-client'
9
+ import type {
10
+ CreateGenerationOptions,
11
+ CreateGenerationReturn,
12
+ } from './create-generation.ts'
13
+
14
+ /**
15
+ * Options for the createTranscription helper.
16
+ *
17
+ * Handle is the first argument of the helper. It is not part of this type.
18
+ *
19
+ * @template TOutput - The output type after optional transform (defaults to TranscriptionResult)
20
+ */
21
+ export type CreateTranscriptionOptions<TOutput = TranscriptionResult> = Omit<
22
+ CreateGenerationOptions<
23
+ TranscriptionGenerateInput,
24
+ TranscriptionResult,
25
+ TOutput
26
+ >,
27
+ 'onResult' | 'reconstructResult'
28
+ > & {
29
+ onResult?: (result: TranscriptionResult) => TOutput | null | void
30
+ }
31
+
32
+ /**
33
+ * Return type for the createTranscription helper.
34
+ *
35
+ * @template TOutput - The output type (after optional transform)
36
+ */
37
+ export type CreateTranscriptionReturn<TOutput = TranscriptionResult> =
38
+ CreateGenerationReturn<TOutput, TranscriptionGenerateInput>
39
+
40
+ /**
41
+ * Creates an audio transcription helper for Remix setup.
42
+ *
43
+ * Call this in a Remix component setup function. Pass the component Handle as
44
+ * the first argument.
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * import { createTranscription } from '@tanstack/ai-remix'
49
+ * import { fetchServerSentEvents } from '@tanstack/ai-client'
50
+ * import type { Handle } from 'remix/ui'
51
+ *
52
+ * function Transcriber(handle: Handle) {
53
+ * const transcription = createTranscription(handle, {
54
+ * connection: fetchServerSentEvents('/api/transcribe'),
55
+ * })
56
+ *
57
+ * return () => (
58
+ * <div>
59
+ * <input
60
+ * type="file"
61
+ * accept="audio/*"
62
+ * onChange={(event) => {
63
+ * const file = event.currentTarget.files?.[0]
64
+ * if (!file) return
65
+ * const reader = new FileReader()
66
+ * reader.onload = () => {
67
+ * const audio = reader.result
68
+ * if (typeof audio === 'string') {
69
+ * transcription.generate({ audio, language: 'en' })
70
+ * }
71
+ * }
72
+ * reader.readAsDataURL(file)
73
+ * }}
74
+ * />
75
+ * {transcription.isLoading ? <p>Transcribing...</p> : null}
76
+ * {transcription.result ? <p>{transcription.result.text}</p> : null}
77
+ * </div>
78
+ * )
79
+ * }
80
+ * ```
81
+ */
82
+ export function createTranscription<TTransformed = void>(
83
+ handle: Pick<Handle, 'id' | 'update' | 'signal'>,
84
+ options: Omit<
85
+ CreateTranscriptionOptions,
86
+ 'onResult' | 'persistence' | 'threadId'
87
+ > & {
88
+ onResult?: (result: TranscriptionResult) => TTransformed
89
+ } & GenerationPersistenceOptions,
90
+ ) {
91
+ const devtools = {
92
+ ...options.devtools,
93
+ hookName: 'createTranscription',
94
+ outputKind: 'text' as const,
95
+ }
96
+ return createGeneration<
97
+ TranscriptionGenerateInput,
98
+ TranscriptionResult,
99
+ TTransformed
100
+ >(handle, {
101
+ ...options,
102
+ devtools,
103
+ reconstructResult: reconstructTranscriptionResult,
104
+ })
105
+ }
package/src/index.ts ADDED
@@ -0,0 +1,92 @@
1
+ export { createChat } from './create-chat.ts'
2
+ export { createByok } from './create-byok.ts'
3
+ export { createRealtimeChat } from './create-realtime-chat.ts'
4
+ export { createMcpAppBridge } from './create-mcp-app-bridge.ts'
5
+ export type { CreateMcpAppBridgeOptions } from './create-mcp-app-bridge.ts'
6
+ export type {
7
+ DeepPartial,
8
+ CreateChatOptions,
9
+ CreateChatReturn,
10
+ UIMessage,
11
+ ChatRequestBody,
12
+ QueuedMessage,
13
+ SendMessageOptions,
14
+ WhenBusy,
15
+ QueueConfig,
16
+ QueueStrategy,
17
+ QueueOption,
18
+ } from './types.ts'
19
+ export type {
20
+ CreateRealtimeChatOptions,
21
+ CreateRealtimeChatReturn,
22
+ } from './realtime-types.ts'
23
+
24
+ export { createGeneration } from './create-generation.ts'
25
+ export type {
26
+ CreateGenerationOptions,
27
+ CreateGenerationReturn,
28
+ } from './create-generation.ts'
29
+ export { createGenerateImage } from './create-generate-image.ts'
30
+ export type {
31
+ CreateGenerateImageOptions,
32
+ CreateGenerateImageReturn,
33
+ } from './create-generate-image.ts'
34
+ export { createGenerateAudio } from './create-generate-audio.ts'
35
+ export type {
36
+ CreateGenerateAudioOptions,
37
+ CreateGenerateAudioReturn,
38
+ } from './create-generate-audio.ts'
39
+ export { createGenerateSpeech } from './create-generate-speech.ts'
40
+ export type {
41
+ CreateGenerateSpeechOptions,
42
+ CreateGenerateSpeechReturn,
43
+ } from './create-generate-speech.ts'
44
+ export { createTranscription } from './create-transcription.ts'
45
+ export type {
46
+ CreateTranscriptionOptions,
47
+ CreateTranscriptionReturn,
48
+ } from './create-transcription.ts'
49
+ export { createSummarize } from './create-summarize.ts'
50
+ export type {
51
+ CreateSummarizeOptions,
52
+ CreateSummarizeReturn,
53
+ } from './create-summarize.ts'
54
+ export { createGenerateVideo } from './create-generate-video.ts'
55
+ export type {
56
+ CreateGenerateVideoOptions,
57
+ CreateGenerateVideoReturn,
58
+ } from './create-generate-video.ts'
59
+ export { createAudioRecorder } from './create-audio-recorder.ts'
60
+ export type { CreateAudioRecorderOptions } from './create-audio-recorder.ts'
61
+
62
+ // Re-export from ai-client for convenience (mirror octane index.ts).
63
+ // createMcpAppBridge / CreateMcpAppBridgeOptions come from ./create-mcp-app-bridge.
64
+ export {
65
+ fetchServerSentEvents,
66
+ fetchHttpStream,
67
+ xhrServerSentEvents,
68
+ xhrHttpStream,
69
+ stream,
70
+ rpcStream,
71
+ createChatClientOptions,
72
+ type McpAppBridge,
73
+ type ChatFetcher,
74
+ type ChatFetcherInput,
75
+ type ChatFetcherOptions,
76
+ type ConnectionAdapter,
77
+ type ConnectConnectionAdapter,
78
+ type SubscribeConnectionAdapter,
79
+ type RunAgentInputContext,
80
+ type FetchConnectionOptions,
81
+ type XhrConnectionOptions,
82
+ type InferChatMessages,
83
+ type GenerationClientState,
84
+ type ImageGenerateInput,
85
+ type AudioGenerateInput,
86
+ type SpeechGenerateInput,
87
+ type TranscriptionGenerateInput,
88
+ type SummarizeGenerateInput,
89
+ type VideoGenerateInput,
90
+ type VideoGenerateResult,
91
+ type VideoStatusInfo,
92
+ } from '@tanstack/ai-client'
@@ -0,0 +1,150 @@
1
+ import type {
2
+ AnyClientTool,
3
+ RealtimeMessage,
4
+ RealtimeMode,
5
+ RealtimeSessionConfig,
6
+ RealtimeStatus,
7
+ RealtimeToken,
8
+ UsageInfo,
9
+ } from '@tanstack/ai'
10
+ import type { RealtimeAdapter } from '@tanstack/ai-client'
11
+
12
+ /**
13
+ * Options for the createRealtimeChat helper.
14
+ *
15
+ * Called in Remix setup with Handle. Handle is not part of this type.
16
+ */
17
+ export interface CreateRealtimeChatOptions {
18
+ /**
19
+ * Function to fetch a realtime token from the server.
20
+ * Called on connect and when token needs refresh.
21
+ */
22
+ getToken: () => Promise<RealtimeToken>
23
+
24
+ /**
25
+ * The realtime adapter to use (e.g., openaiRealtime())
26
+ */
27
+ adapter: RealtimeAdapter
28
+
29
+ /**
30
+ * Client-side tools with execution logic
31
+ */
32
+ tools?: ReadonlyArray<AnyClientTool>
33
+
34
+ /**
35
+ * Auto-play assistant audio (default: true)
36
+ */
37
+ autoPlayback?: boolean
38
+
39
+ /**
40
+ * Request microphone access on connect (default: true)
41
+ */
42
+ autoCapture?: boolean
43
+
44
+ /**
45
+ * System instructions for the assistant
46
+ */
47
+ instructions?: string
48
+
49
+ /**
50
+ * Voice to use for audio output
51
+ */
52
+ voice?: string
53
+
54
+ /**
55
+ * Voice activity detection mode (default: 'server')
56
+ */
57
+ vadMode?: 'server' | 'semantic' | 'manual'
58
+
59
+ /**
60
+ * Output modalities for responses (e.g., ['audio', 'text'])
61
+ */
62
+ outputModalities?: Array<'audio' | 'text'>
63
+
64
+ /**
65
+ * Temperature for generation (provider-specific range)
66
+ */
67
+ temperature?: number
68
+
69
+ /**
70
+ * Maximum number of tokens in a response
71
+ */
72
+ maxOutputTokens?: number | 'inf'
73
+
74
+ /**
75
+ * Eagerness level for semantic VAD ('low', 'medium', 'high')
76
+ */
77
+ semanticEagerness?: 'low' | 'medium' | 'high'
78
+
79
+ // Callbacks
80
+ onConnect?: () => void
81
+ onDisconnect?: () => void
82
+ onError?: (error: Error) => void
83
+ onMessage?: (message: RealtimeMessage) => void
84
+ onModeChange?: (mode: RealtimeMode) => void
85
+ onInterrupted?: () => void
86
+ onUsage?: (usage: UsageInfo) => void
87
+ onGoAway?: (timeLeft?: string) => void
88
+ onStatusChange?: (status: RealtimeStatus) => void
89
+ }
90
+
91
+ /**
92
+ * Return type for the createRealtimeChat helper.
93
+ *
94
+ * Called in Remix setup with Handle. Fields are plain values.
95
+ */
96
+ export interface CreateRealtimeChatReturn {
97
+ // Connection state
98
+ /** Current connection status */
99
+ status: RealtimeStatus
100
+ /** Current error, if any */
101
+ error: Error | null
102
+ /** Connect to the realtime session */
103
+ connect: () => Promise<void>
104
+ /** Disconnect from the realtime session */
105
+ disconnect: () => Promise<void>
106
+
107
+ // Conversation state
108
+ /** Current mode (idle, listening, thinking, speaking) */
109
+ mode: RealtimeMode
110
+ /** Conversation messages */
111
+ messages: Array<RealtimeMessage>
112
+ /** User transcript while speaking (before finalized) */
113
+ pendingUserTranscript: string | null
114
+ /** Assistant transcript while speaking (before finalized) */
115
+ pendingAssistantTranscript: string | null
116
+
117
+ // Voice control
118
+ /** Start listening for voice input (manual VAD mode) */
119
+ startListening: () => void
120
+ /** Stop listening for voice input (manual VAD mode) */
121
+ stopListening: () => void
122
+ /** Interrupt the current assistant response */
123
+ interrupt: () => void
124
+
125
+ // Text input
126
+ /** Send a text message instead of voice */
127
+ sendText: (text: string) => void
128
+
129
+ // Image input
130
+ /** Send an image to the conversation */
131
+ sendImage: (imageData: string, mimeType: string) => void
132
+
133
+ // Audio visualization (0-1 normalized)
134
+ /** Current input (microphone) volume level */
135
+ inputLevel: number
136
+ /** Current output (speaker) volume level */
137
+ outputLevel: number
138
+ /** Get frequency data for input audio visualization */
139
+ getInputFrequencyData: () => Uint8Array
140
+ /** Get frequency data for output audio visualization */
141
+ getOutputFrequencyData: () => Uint8Array
142
+ /** Get time domain data for input waveform */
143
+ getInputTimeDomainData: () => Uint8Array
144
+ /** Get time domain data for output waveform */
145
+ getOutputTimeDomainData: () => Uint8Array
146
+
147
+ // Session control
148
+ /** Update the active session and persist the configuration for reconnects. */
149
+ updateSession: (config: RealtimeSessionConfig) => void
150
+ }
package/src/types.ts ADDED
@@ -0,0 +1,313 @@
1
+ import type {
2
+ AnyClientTool,
3
+ InterruptDefinition,
4
+ InferSchemaType,
5
+ ModelMessage,
6
+ RunAgentResumeItem,
7
+ SchemaInput,
8
+ } from '@tanstack/ai/client'
9
+ import type {
10
+ AIDevtoolsDisplayOptions,
11
+ BoundInterrupts,
12
+ ChatClientOptions,
13
+ ChatClientState,
14
+ ResolvableChatInterrupt,
15
+ ChatInterruptState,
16
+ ChatRequestBody,
17
+ ChatResumeState,
18
+ ClientContextOptionFromTools,
19
+ ConnectionStatus,
20
+ DistributedOmit,
21
+ InferredClientContext,
22
+ MultimodalContent,
23
+ QueueConfig,
24
+ QueueOption,
25
+ QueueStrategy,
26
+ QueuedMessage,
27
+ SendMessageOptions,
28
+ UIMessage,
29
+ WhenBusy,
30
+ } from '@tanstack/ai-client'
31
+
32
+ // Re-export types from ai-client
33
+ export type {
34
+ ChatRequestBody,
35
+ MultimodalContent,
36
+ QueueConfig,
37
+ QueuedMessage,
38
+ QueueOption,
39
+ QueueStrategy,
40
+ SendMessageOptions,
41
+ UIMessage,
42
+ WhenBusy,
43
+ }
44
+
45
+ /**
46
+ * Recursive partial. Every property and every nested array element is optional.
47
+ * Used to type the in-flight `partial` value the helper exposes while a
48
+ * structured output stream is still arriving (the JSON has shape but is
49
+ * incomplete).
50
+ */
51
+ export type DeepPartial<T> =
52
+ T extends ReadonlyArray<infer U>
53
+ ? Array<DeepPartial<U>>
54
+ : T extends object
55
+ ? { [K in keyof T]?: DeepPartial<T[K]> }
56
+ : T
57
+
58
+ /**
59
+ * Options for the createChat helper.
60
+ *
61
+ * Call `createChat(handle, options)` in Remix setup with Handle from
62
+ * `remix/ui`. Handle is the first argument of the helper. It is not part of
63
+ * this type. The default id is `options.threadId ?? handle.id`.
64
+ *
65
+ * Pass either `connection` or `fetcher`. The XOR is enforced at the type
66
+ * level via `ChatTransport`.
67
+ *
68
+ * This extends ChatClientOptions but omits the state change callbacks that
69
+ * createChat manages internally:
70
+ * - `onMessagesChange` - Managed internally (exposed as `messages`)
71
+ * - `onLoadingChange` - Managed internally (exposed as `isLoading`)
72
+ * - `onErrorChange` - Managed internally (exposed as `error`)
73
+ * - `onStatusChange` - Managed internally (exposed as `status`)
74
+ *
75
+ * All other callbacks (onResponse, onChunk, onFinish, onError) are
76
+ * passed through to the underlying ChatClient and can be used for side effects.
77
+ *
78
+ * When `outputSchema` is supplied, the helper returns a typed `partial` (live
79
+ * progressive object, updated from `TEXT_MESSAGE_CONTENT` deltas via
80
+ * `parsePartialJSON`) and `final` (validated terminal payload from the
81
+ * `structured-output.complete` event). The schema is used purely for type
82
+ * inference on the client. Server-side validation still runs against the
83
+ * schema you pass to `chat({ outputSchema })` on the server route.
84
+ *
85
+ * Changing `connection` or `fetcher` updates the active ChatClient in place,
86
+ * preserving its state. Changing `threadId` creates a fresh client.
87
+ */
88
+ export type CreateChatOptions<
89
+ TTools extends ReadonlyArray<AnyClientTool> = any,
90
+ TSchema extends SchemaInput | undefined = undefined,
91
+ TContext = InferredClientContext<TTools>,
92
+ TInterrupts extends ReadonlyArray<InterruptDefinition<any, any, any, any>> =
93
+ readonly [],
94
+ > = DistributedOmit<
95
+ ChatClientOptions<TTools, TContext, TInterrupts>,
96
+ | 'onMessagesChange'
97
+ | 'onLoadingChange'
98
+ | 'onErrorChange'
99
+ | 'onStatusChange'
100
+ | 'onSubscriptionChange'
101
+ | 'onConnectionStatusChange'
102
+ | 'onSessionGeneratingChange'
103
+ | 'onQueueChange'
104
+ | 'onResumeStateChange'
105
+ | 'onRunIdChange'
106
+ | 'context'
107
+ | 'devtools'
108
+ > & {
109
+ /** Display options for TanStack AI Devtools. */
110
+ devtools?: AIDevtoolsDisplayOptions
111
+ /**
112
+ * Opt into live subscription behavior when the helper is called in Remix
113
+ * setup with Handle. When enabled, the helper subscribes on setup and
114
+ * unsubscribes on dispose.
115
+ */
116
+ live?: boolean
117
+ /**
118
+ * Standard-schema-compatible schema (Zod, Valibot, ArkType, or a plain JSON
119
+ * Schema). Used to infer the shape of `partial` and `final` in the return.
120
+ * The schema is **not** sent to the server. Server-side validation runs
121
+ * against the schema passed to `chat({ outputSchema })` on the server route.
122
+ */
123
+ outputSchema?: TSchema
124
+ } & ClientContextOptionFromTools<TTools, TContext>
125
+
126
+ /**
127
+ * Discriminated return shape from the createChat helper. When `outputSchema`
128
+ * is supplied, the helper adds typed `partial` / `final` fields. When it is
129
+ * omitted (default), the return is unchanged. Fields are plain values.
130
+ */
131
+ export type CreateChatReturn<
132
+ TTools extends ReadonlyArray<AnyClientTool> = any,
133
+ TSchema extends SchemaInput | undefined = undefined,
134
+ TInterrupts extends ReadonlyArray<InterruptDefinition<any, any, any, any>> =
135
+ readonly [],
136
+ > = BaseCreateChatReturn<
137
+ TTools,
138
+ TSchema extends SchemaInput ? InferSchemaType<TSchema> : unknown,
139
+ TInterrupts
140
+ > &
141
+ (TSchema extends SchemaInput
142
+ ? {
143
+ /**
144
+ * Live, progressively-parsed structured output. Updated from
145
+ * `TEXT_MESSAGE_CONTENT` deltas via `parsePartialJSON` while the stream
146
+ * is still arriving, and snapped to the validated payload when
147
+ * `structured-output.complete` fires. Resets on every new run
148
+ * (`sendMessage` / `reload`).
149
+ */
150
+ partial: DeepPartial<InferSchemaType<TSchema>>
151
+ /**
152
+ * Final, schema-validated structured output. `null` until the terminal
153
+ * `structured-output.complete` event arrives. Resets on every new run.
154
+ */
155
+ final: InferSchemaType<TSchema> | null
156
+ }
157
+ : Record<never, never>)
158
+
159
+ interface BaseCreateChatReturn<
160
+ TTools extends ReadonlyArray<AnyClientTool> = any,
161
+ TData = unknown,
162
+ TInterrupts extends ReadonlyArray<InterruptDefinition<any, any, any, any>> =
163
+ readonly [],
164
+ > {
165
+ /**
166
+ * Current messages in the conversation. When `outputSchema` is supplied,
167
+ * `messages[i].parts.find(p => p.type === 'structured-output')` is typed
168
+ * with the schema's inferred shape: `data: T`, `partial: DeepPartial<T>`.
169
+ */
170
+ messages: Array<UIMessage<TTools, TData>>
171
+
172
+ /**
173
+ * Send a message and get a response.
174
+ * Can be a simple string or multimodal content with images, audio, etc.
175
+ * By default, sends while busy are queued until the run settles successfully
176
+ * (`queue: 'drop'` restores the old drop-while-busy behavior).
177
+ * Pass `{ whenBusy }` to override the policy for a single send, or
178
+ * `{ body }` to merge per-call JSON into this request's `forwardedProps`.
179
+ */
180
+ sendMessage: (
181
+ content: string | MultimodalContent,
182
+ options?: SendMessageOptions,
183
+ ) => Promise<void>
184
+
185
+ /**
186
+ * Pending messages queued while the client is busy (streaming, claiming a
187
+ * send, or draining). Separate from `messages` until they drain.
188
+ */
189
+ queue: Array<QueuedMessage>
190
+
191
+ /**
192
+ * Cancel a queued message before it drains. No-op if already sent.
193
+ */
194
+ cancelQueued: (id: string) => void
195
+
196
+ /**
197
+ * Append a message to the conversation
198
+ */
199
+ append: (message: ModelMessage | UIMessage<TTools, TData>) => Promise<void>
200
+
201
+ /**
202
+ * Add the result of a client-side tool execution
203
+ */
204
+ addToolResult: (result: {
205
+ toolCallId: string
206
+ tool: string
207
+ output: any
208
+ state?: 'output-available' | 'output-error'
209
+ errorText?: string
210
+ }) => Promise<void>
211
+
212
+ /**
213
+ * @deprecated Use a bound `tool-approval` interrupt and
214
+ * `interrupt.resolveInterrupt`.
215
+ */
216
+ addToolApprovalResponse: (response: {
217
+ id: string // approval.id, not toolCallId
218
+ approved: boolean
219
+ }) => Promise<void>
220
+
221
+ /**
222
+ * The id of the run this client has in flight (one it started or rejoined),
223
+ * or `null` when there is none (including while a run sits paused on an
224
+ * interrupt, waiting on approval).
225
+ *
226
+ * A run is one turn of the conversation, so this changes from turn to turn. A
227
+ * whole tool loop stays inside one run, while resuming after an interrupt
228
+ * continues the turn under a new id — so one user message can produce several
229
+ * run ids. Use it to talk to your own server about that run (cancel it, poll
230
+ * it, correlate a log line).
231
+ */
232
+ runId: string | null
233
+ interrupts: BoundInterrupts<TTools, TInterrupts>
234
+ /** @deprecated Use `interrupts`. */
235
+ pendingInterrupts: BoundInterrupts<TTools, TInterrupts>
236
+ interruptErrors: ChatInterruptState<TTools, TInterrupts>['interruptErrors']
237
+ resuming: boolean
238
+ resolveInterrupts: {
239
+ (approved: boolean): void
240
+ (
241
+ resolver: (
242
+ interrupt: ResolvableChatInterrupt<TTools, TInterrupts>,
243
+ ) => undefined,
244
+ ): void
245
+ }
246
+ cancelInterrupts: () => void
247
+ retryInterrupts: () => void
248
+ resumeInterruptsUnsafe: (
249
+ resume: Array<RunAgentResumeItem>,
250
+ state?: ChatResumeState,
251
+ ) => Promise<boolean>
252
+ /** @deprecated Use bound interrupt methods or `resumeInterruptsUnsafe`. */
253
+ resumeInterrupts: (
254
+ resume: Array<RunAgentResumeItem>,
255
+ state?: ChatResumeState,
256
+ ) => Promise<boolean>
257
+
258
+ /**
259
+ * Reload the last assistant message
260
+ */
261
+ reload: () => Promise<void>
262
+
263
+ /**
264
+ * Stop the current response generation
265
+ */
266
+ stop: () => void
267
+
268
+ /**
269
+ * Whether a response is currently being generated
270
+ */
271
+ isLoading: boolean
272
+
273
+ /**
274
+ * Current error, if any
275
+ */
276
+ error: Error | undefined
277
+
278
+ /**
279
+ * Current status of the chat client
280
+ */
281
+ status: ChatClientState
282
+
283
+ /**
284
+ * Whether the subscription loop is currently active
285
+ */
286
+ isSubscribed: boolean
287
+
288
+ /**
289
+ * Current connection lifecycle status
290
+ */
291
+ connectionStatus: ConnectionStatus
292
+
293
+ /**
294
+ * Whether the shared session is actively generating.
295
+ * Derived from stream run events (RUN_STARTED / RUN_FINISHED / RUN_ERROR).
296
+ * Unlike `isLoading` (request-local), this reflects shared generation
297
+ * activity visible to all subscribers (e.g. across tabs/devices).
298
+ */
299
+ sessionGenerating: boolean
300
+
301
+ /**
302
+ * Set messages manually
303
+ */
304
+ setMessages: (messages: Array<UIMessage<TTools, TData>>) => void
305
+
306
+ /**
307
+ * Clear all messages
308
+ */
309
+ clear: () => void
310
+ }
311
+
312
+ // createChatClientOptions and InferChatMessages live in @tanstack/ai-client
313
+ // and are re-exported from there.
package/src/ui.ts ADDED
@@ -0,0 +1,41 @@
1
+ // Barrel entry for the `@tanstack/ai-remix/ui` subpath.
2
+ export {
3
+ createChatUI,
4
+ type ChatUIComponents,
5
+ type ChatUIFactoryConfig,
6
+ type ChatUIHost,
7
+ type ChatUIQueueItem,
8
+ type InputProps,
9
+ type InterruptProps,
10
+ type LayoutProps,
11
+ type MessageProps,
12
+ type PartProps,
13
+ type QueueProps,
14
+ type ToolProps,
15
+ } from './chat-ui/create-ui.tsx'
16
+ export { createChatHook } from './chat-ui/create-chat-hook.ts'
17
+ export { Chat, useChatContext, type ChatProps } from './chat-ui/chat.tsx'
18
+ export {
19
+ ChatMessages,
20
+ type ChatMessagesProps,
21
+ } from './chat-ui/chat-messages.tsx'
22
+ export {
23
+ ChatMessage,
24
+ type ChatMessageProps,
25
+ type ToolCallRenderProps,
26
+ } from './chat-ui/chat-message.tsx'
27
+ export {
28
+ ChatInput,
29
+ type ChatInputProps,
30
+ type ChatInputRenderProps,
31
+ } from './chat-ui/chat-input.tsx'
32
+ export {
33
+ ToolApproval,
34
+ type ToolApprovalProps,
35
+ type ToolApprovalRenderProps,
36
+ } from './chat-ui/tool-approval.tsx'
37
+ export { TextPart, type TextPartProps } from './chat-ui/text-part.tsx'
38
+ export {
39
+ ThinkingPart,
40
+ type ThinkingPartProps,
41
+ } from './chat-ui/thinking-part.tsx'