@tanstack/ai-solid 0.19.4 → 0.20.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,95 @@
1
+ import { createContext, useContext } from 'solid-js'
2
+ import type { ConnectionAdapter } from '@tanstack/ai-client'
3
+ import { useChat } from '../use-chat'
4
+ import type { JSX } from 'solid-js'
5
+ import type { UIMessage, UseChatReturn } from '../types'
6
+
7
+ /**
8
+ * Chat context - provides chat state to all child components
9
+ */
10
+ const ChatContext = createContext<UseChatReturn | null>(null)
11
+
12
+ /**
13
+ * Hook to access chat context
14
+ * @throws Error if used outside of Chat component
15
+ */
16
+ /** @deprecated Use `createChatUI().useChat()` instead. Deprecated in 0.8.0. Removed in 1.0.0. */
17
+ export function useChatContext(): UseChatReturn {
18
+ const context = useContext(ChatContext)
19
+ if (!context) {
20
+ throw new Error(
21
+ "Chat components must be wrapped in <Chat>. Make sure you're using Chat.Messages, Chat.Input, etc. inside a <Chat> component.",
22
+ )
23
+ }
24
+ return context
25
+ }
26
+
27
+ /** @deprecated Use `createChatUI()` Chat/Provider instead. Deprecated in 0.8.0. Removed in 1.0.0. */
28
+ export interface ChatProps {
29
+ /** Child components (Chat.Messages, Chat.Input, etc.) */
30
+ children: JSX.Element
31
+ /** CSS class name for the root element */
32
+ class?: string
33
+ /** Connection adapter for communicating with your API */
34
+ connection: ConnectionAdapter
35
+ /** Initial messages to display */
36
+ initialMessages?: Array<UIMessage>
37
+ /** Custom message ID generator */
38
+ id?: string
39
+ /** Additional body data to send with requests */
40
+ body?: any
41
+ /** Callback when a response is received */
42
+ onResponse?: (response?: Response) => void | Promise<void>
43
+ /** Callback when each chunk arrives */
44
+ onChunk?: (chunk: any) => void
45
+ /** Callback when a message is complete */
46
+ onFinish?: (message: UIMessage) => void
47
+ /** Callback when an error occurs */
48
+ onError?: (error: Error) => void
49
+ /** Client-side tools with execute functions */
50
+ tools?: Array<any>
51
+ /** Custom tool components registry for rendering */
52
+ toolComponents?: Record<
53
+ string,
54
+ (props: { input: any; output?: any }) => JSX.Element
55
+ >
56
+ }
57
+
58
+ /**
59
+ * @deprecated Since 0.8.0. Use `createChatHook()` from `@tanstack/ai-solid/ui` instead.
60
+ * See https://tanstack.com/ai/latest/docs/ui/solid
61
+ * Removed in 1.0.0.
62
+ *
63
+ * Root Chat component - provides context for all chat subcomponents
64
+ *
65
+ * @example
66
+ * ```tsx
67
+ * <Chat connection={fetchServerSentEvents("/api/chat")}>
68
+ * <Chat.Messages />
69
+ * <Chat.Input />
70
+ * </Chat>
71
+ * ```
72
+ */
73
+ export function Chat(props: ChatProps) {
74
+ const chat = useChat({
75
+ connection: props.connection,
76
+ ...(props.initialMessages !== undefined && {
77
+ initialMessages: props.initialMessages,
78
+ }),
79
+ ...(props.id !== undefined && { id: props.id }),
80
+ ...(props.body !== undefined && { body: props.body }),
81
+ ...(props.onResponse !== undefined && { onResponse: props.onResponse }),
82
+ ...(props.onChunk !== undefined && { onChunk: props.onChunk }),
83
+ ...(props.onFinish !== undefined && { onFinish: props.onFinish }),
84
+ ...(props.onError !== undefined && { onError: props.onError }),
85
+ ...(props.tools !== undefined && { tools: props.tools }),
86
+ })
87
+
88
+ return (
89
+ <ChatContext.Provider value={chat}>
90
+ <div class={props.class} data-chat-root>
91
+ {props.children}
92
+ </div>
93
+ </ChatContext.Provider>
94
+ )
95
+ }
@@ -0,0 +1,77 @@
1
+ import type { Component } from 'solid-js'
2
+ import type { InferredClientContext } from '@tanstack/ai-client'
3
+ import type {
4
+ ChatUIInterruptsOf,
5
+ ChatUISchemaOf,
6
+ ChatUIToolsOf,
7
+ } from '@tanstack/ai-client/ui'
8
+ import { useChat as useUnboundChat } from '../use-chat'
9
+ import type { UseChatOptions } from '../types'
10
+ import { createChatUI } from './create-ui'
11
+ import type { ChatUIFactoryConfig, ChatUIHost, InputProps } from './create-ui'
12
+
13
+ type HeadlessOptions<TOptions> = UseChatOptions<
14
+ ChatUIToolsOf<TOptions>,
15
+ ChatUISchemaOf<TOptions>,
16
+ InferredClientContext<ChatUIToolsOf<TOptions>>,
17
+ ChatUIInterruptsOf<TOptions>
18
+ >
19
+
20
+ type ChatInstanceOverrides<TOptions> = {
21
+ threadId?: string
22
+ live?: boolean
23
+ forwardedProps?: Record<string, any>
24
+ body?: Record<string, any>
25
+ initialMessages?: HeadlessOptions<TOptions>['initialMessages']
26
+ }
27
+
28
+ /**
29
+ * Bind chat options and UI widgets once at module scope.
30
+ *
31
+ * This matches Form `createFormHook` and Table `createTableHook`. The
32
+ * returned `useAppChat` creates a chat instance. `chat.AppChat` renders it.
33
+ * Context `useChatContext` reads that instance. Part and interrupt
34
+ * widgets take `part` / `interrupt` as props.
35
+ *
36
+ * Pass instance overrides such as `threadId` into `useAppChat()`.
37
+ */
38
+ export function createChatHook<
39
+ const TOptions,
40
+ TInput extends Component<any> | undefined =
41
+ | Component<InputProps<NoInfer<TOptions>>>
42
+ | undefined,
43
+ >({
44
+ options,
45
+ ...chatComponents
46
+ }: {
47
+ options: TOptions
48
+ } & ChatUIFactoryConfig<NoInfer<TOptions>, TInput>) {
49
+ const ui = createChatUI(
50
+ options,
51
+ chatComponents as ChatUIFactoryConfig<NoInfer<TOptions>, TInput>,
52
+ )
53
+
54
+ function useAppChat(overrides?: ChatInstanceOverrides<TOptions>) {
55
+ const chat = (
56
+ overrides
57
+ ? useUnboundChat({
58
+ ...(options as HeadlessOptions<TOptions>),
59
+ ...overrides,
60
+ })
61
+ : useUnboundChat(options as HeadlessOptions<TOptions>)
62
+ ) as ChatUIHost<TOptions>
63
+
64
+ function AppChat() {
65
+ return <ui.Chat chat={chat} />
66
+ }
67
+
68
+ return Object.assign(chat, { AppChat }) as ChatUIHost<TOptions> & {
69
+ AppChat: Component
70
+ }
71
+ }
72
+
73
+ return {
74
+ useAppChat,
75
+ useChatContext: ui.useChatContext,
76
+ }
77
+ }
@@ -0,0 +1,52 @@
1
+ import { createContext, useContext } from 'solid-js'
2
+ import type { Context } from 'solid-js'
3
+ import type {
4
+ ChatUIInterrupt,
5
+ ChatUISelectedPart,
6
+ } from '@tanstack/ai-client/ui'
7
+ import type { UseChatReturn } from '../types'
8
+
9
+ export interface ChatUIContexts {
10
+ chatContext: Context<UseChatReturn<any, any, any> | undefined>
11
+ partContext: Context<ChatUISelectedPart | undefined>
12
+ interruptContext: Context<ChatUIInterrupt | undefined>
13
+ useChatContext: () => UseChatReturn<any, any, any>
14
+ }
15
+
16
+ /**
17
+ * Create a fresh set of chat UI contexts. This matches Form
18
+ * `createFormHookContexts` and Table `createTableHookContexts`.
19
+ *
20
+ * Most apps can skip this. `createChatHook` uses shared module contexts by
21
+ * default. Call this when a widget file cannot import the `createChatHook`
22
+ * result, or when nested chats need isolated providers.
23
+ *
24
+ * Prefer `useChatContext` from `createChatHook` when you can import that
25
+ * result. Part and interrupt widgets take `part` / `interrupt` as props.
26
+ */
27
+ export function createChatHookContexts(): ChatUIContexts {
28
+ const chatContext = createContext<UseChatReturn<any, any, any> | undefined>(
29
+ undefined,
30
+ )
31
+ const partContext = createContext<ChatUISelectedPart | undefined>(undefined)
32
+ const interruptContext = createContext<ChatUIInterrupt | undefined>(undefined)
33
+
34
+ function useChatContext() {
35
+ const chat = useContext(chatContext)
36
+ if (!chat) {
37
+ throw new Error(
38
+ '`useChatContext` must be used within `UI.Provider` or `UI.Chat`.',
39
+ )
40
+ }
41
+ return chat
42
+ }
43
+
44
+ return {
45
+ chatContext,
46
+ partContext,
47
+ interruptContext,
48
+ useChatContext,
49
+ }
50
+ }
51
+
52
+ export const defaultChatUIContexts = createChatHookContexts()