@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.
- package/dist/create-chat-hook.d.ts +39 -0
- package/dist/create-chat-hook.js +38 -0
- package/dist/create-chat-hook.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/package.json +16 -4
- package/src/chat-ui/chat-input.tsx +168 -0
- package/src/chat-ui/chat-message.tsx +261 -0
- package/src/chat-ui/chat-messages.tsx +91 -0
- package/src/chat-ui/chat.tsx +95 -0
- package/src/chat-ui/create-chat-hook.tsx +77 -0
- package/src/chat-ui/create-ui-contexts.tsx +52 -0
- package/src/chat-ui/create-ui.tsx +718 -0
- package/src/chat-ui/markdown-plugins.ts +48 -0
- package/src/chat-ui/text-part.tsx +71 -0
- package/src/chat-ui/thinking-part.tsx +79 -0
- package/src/chat-ui/tool-approval.tsx +121 -0
- package/src/create-chat-hook.ts +67 -0
- package/src/index.ts +1 -0
- package/src/ui.ts +39 -0
|
@@ -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()
|