@tanstack/ai-solid 0.2.2 → 0.4.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/types.d.ts +7 -2
- package/dist/use-chat.js +15 -2
- package/dist/use-chat.js.map +1 -1
- package/package.json +4 -4
- package/src/types.ts +10 -3
- package/src/use-chat.ts +20 -2
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Accessor } from "solid-js";
|
|
2
|
-
import { ChatClientOptions, ChatRequestBody, UIMessage } from "@tanstack/ai-client";
|
|
2
|
+
import { ChatClientOptions, ChatClientState, ChatRequestBody, UIMessage } from "@tanstack/ai-client";
|
|
3
3
|
import { AnyClientTool, ModelMessage } from "@tanstack/ai";
|
|
4
4
|
|
|
5
5
|
//#region src/types.d.ts
|
|
@@ -12,6 +12,7 @@ import { AnyClientTool, ModelMessage } from "@tanstack/ai";
|
|
|
12
12
|
* - `onMessagesChange` - Managed by Solid signal (exposed as `messages`)
|
|
13
13
|
* - `onLoadingChange` - Managed by Solid signal (exposed as `isLoading`)
|
|
14
14
|
* - `onErrorChange` - Managed by Solid signal (exposed as `error`)
|
|
15
|
+
* - `onStatusChange` - Managed by Solid signal (exposed as `status`)
|
|
15
16
|
*
|
|
16
17
|
* All other callbacks (onResponse, onChunk, onFinish, onError) are
|
|
17
18
|
* passed through to the underlying ChatClient and can be used for side effects.
|
|
@@ -19,7 +20,7 @@ import { AnyClientTool, ModelMessage } from "@tanstack/ai";
|
|
|
19
20
|
* Note: Connection and body changes will recreate the ChatClient instance.
|
|
20
21
|
* To update these options, remount the component or use a key prop.
|
|
21
22
|
*/
|
|
22
|
-
type UseChatOptions<TTools extends ReadonlyArray<AnyClientTool> = any> = Omit<ChatClientOptions<TTools>, 'onMessagesChange' | 'onLoadingChange' | 'onErrorChange'>;
|
|
23
|
+
type UseChatOptions<TTools extends ReadonlyArray<AnyClientTool> = any> = Omit<ChatClientOptions<TTools>, 'onMessagesChange' | 'onLoadingChange' | 'onErrorChange' | 'onStatusChange'>;
|
|
23
24
|
interface UseChatReturn<TTools extends ReadonlyArray<AnyClientTool> = any> {
|
|
24
25
|
/**
|
|
25
26
|
* Current messages in the conversation
|
|
@@ -74,6 +75,10 @@ interface UseChatReturn<TTools extends ReadonlyArray<AnyClientTool> = any> {
|
|
|
74
75
|
* Clear all messages
|
|
75
76
|
*/
|
|
76
77
|
clear: () => void;
|
|
78
|
+
/**
|
|
79
|
+
* Current generation status
|
|
80
|
+
*/
|
|
81
|
+
status: Accessor<ChatClientState>;
|
|
77
82
|
}
|
|
78
83
|
//#endregion
|
|
79
84
|
export { type ChatRequestBody, type UIMessage, UseChatOptions, UseChatReturn };
|
package/dist/use-chat.js
CHANGED
|
@@ -8,6 +8,7 @@ function useChat(options = {}) {
|
|
|
8
8
|
const [messages, setMessages] = createSignal(options.initialMessages || []);
|
|
9
9
|
const [isLoading, setIsLoading] = createSignal(false);
|
|
10
10
|
const [error, setError] = createSignal(void 0);
|
|
11
|
+
const [status, setStatus] = createSignal("ready");
|
|
11
12
|
const client = createMemo(() => {
|
|
12
13
|
return new ChatClient({
|
|
13
14
|
connection: options.connection,
|
|
@@ -16,8 +17,12 @@ function useChat(options = {}) {
|
|
|
16
17
|
body: options.body,
|
|
17
18
|
onResponse: options.onResponse,
|
|
18
19
|
onChunk: options.onChunk,
|
|
19
|
-
onFinish:
|
|
20
|
-
|
|
20
|
+
onFinish: (message) => {
|
|
21
|
+
options.onFinish?.(message);
|
|
22
|
+
},
|
|
23
|
+
onError: (err) => {
|
|
24
|
+
options.onError?.(err);
|
|
25
|
+
},
|
|
21
26
|
tools: options.tools,
|
|
22
27
|
streamProcessor: options.streamProcessor,
|
|
23
28
|
onMessagesChange: (newMessages) => {
|
|
@@ -26,11 +31,18 @@ function useChat(options = {}) {
|
|
|
26
31
|
onLoadingChange: (newIsLoading) => {
|
|
27
32
|
setIsLoading(newIsLoading);
|
|
28
33
|
},
|
|
34
|
+
onStatusChange: (newStatus) => {
|
|
35
|
+
setStatus(newStatus);
|
|
36
|
+
},
|
|
29
37
|
onErrorChange: (newError) => {
|
|
30
38
|
setError(newError);
|
|
31
39
|
}
|
|
32
40
|
});
|
|
33
41
|
}, [clientId]);
|
|
42
|
+
createEffect(() => {
|
|
43
|
+
const currentBody = options.body;
|
|
44
|
+
client().updateOptions({ body: currentBody });
|
|
45
|
+
});
|
|
34
46
|
createEffect(() => {
|
|
35
47
|
if (options.initialMessages && options.initialMessages.length > 0) {
|
|
36
48
|
if (messages().length === 0) client().setMessagesManually(options.initialMessages);
|
|
@@ -73,6 +85,7 @@ function useChat(options = {}) {
|
|
|
73
85
|
stop,
|
|
74
86
|
isLoading,
|
|
75
87
|
error,
|
|
88
|
+
status,
|
|
76
89
|
setMessages: setMessagesManually,
|
|
77
90
|
clear,
|
|
78
91
|
addToolResult,
|
package/dist/use-chat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-chat.js","names":[],"sources":["../src/use-chat.ts"],"sourcesContent":["import {\n createEffect,\n createMemo,\n createSignal,\n createUniqueId,\n} from 'solid-js'\nimport { ChatClient } from '@tanstack/ai-client'\nimport type { AnyClientTool, ModelMessage } from '@tanstack/ai'\nimport type { UIMessage, UseChatOptions, UseChatReturn } from './types'\n\nexport function useChat<TTools extends ReadonlyArray<AnyClientTool> = any>(\n options: UseChatOptions<TTools> = {} as UseChatOptions<TTools>,\n): UseChatReturn<TTools> {\n const hookId = createUniqueId()\n const clientId = options.id || hookId\n\n const [messages, setMessages] = createSignal<Array<UIMessage<TTools>>>(\n options.initialMessages || [],\n )\n const [isLoading, setIsLoading] = createSignal(false)\n const [error, setError] = createSignal<Error | undefined>(undefined)\n\n // Create ChatClient instance with callbacks to sync state\n // Note: Options are captured at client creation time.\n // The connection adapter can use functions for dynamic values (url, headers, etc.)\n // which are evaluated lazily on each request.\n const client = createMemo(() => {\n return new ChatClient({\n connection: options.connection,\n id: clientId,\n initialMessages: options.initialMessages,\n body: options.body,\n onResponse: options.onResponse,\n onChunk: options.onChunk,\n onFinish: options.onFinish,\n onError: options.onError,\n tools: options.tools,\n streamProcessor: options.streamProcessor,\n onMessagesChange: (newMessages: Array<UIMessage<TTools>>) => {\n setMessages(newMessages)\n },\n onLoadingChange: (newIsLoading: boolean) => {\n setIsLoading(newIsLoading)\n },\n onErrorChange: (newError: Error | undefined) => {\n setError(newError)\n },\n })\n // Only recreate when clientId changes\n // Connection and other options are captured at creation time\n }, [clientId])\n\n // Sync initial messages on mount only\n // Note: initialMessages are passed to ChatClient constructor, but we also\n // set them here to ensure React state is in sync\n createEffect(() => {\n if (options.initialMessages && options.initialMessages.length > 0) {\n // Only set if current messages are empty (initial state)\n if (messages().length === 0) {\n client().setMessagesManually(options.initialMessages)\n }\n }\n }) // Only run on mount - initialMessages are handled by ChatClient constructor\n\n // Cleanup on unmount: stop any in-flight requests\n // Note: We use createEffect with a cleanup return to handle component unmount.\n // The cleanup only runs on disposal (unmount), not on signal changes.\n createEffect(() => {\n return () => {\n // Stop any active generation when component unmounts\n client().stop()\n }\n })\n\n // Note: Callback options (onResponse, onChunk, onFinish, onError, onToolCall)\n // are captured at client creation time. Changes to these callbacks require\n // remounting the component or changing the connection to recreate the client.\n\n const sendMessage = async (content: string) => {\n await client().sendMessage(content)\n }\n\n const append = async (message: ModelMessage | UIMessage<TTools>) => {\n await client().append(message)\n }\n\n const reload = async () => {\n await client().reload()\n }\n\n const stop = () => {\n client().stop()\n }\n\n const clear = () => {\n client().clear()\n }\n\n const setMessagesManually = (newMessages: Array<UIMessage<TTools>>) => {\n client().setMessagesManually(newMessages)\n }\n\n const addToolResult = async (result: {\n toolCallId: string\n tool: string\n output: any\n state?: 'output-available' | 'output-error'\n errorText?: string\n }) => {\n await client().addToolResult(result)\n }\n\n const addToolApprovalResponse = async (response: {\n id: string\n approved: boolean\n }) => {\n await client().addToolApprovalResponse(response)\n }\n\n return {\n messages,\n sendMessage,\n append,\n reload,\n stop,\n isLoading,\n error,\n setMessages: setMessagesManually,\n clear,\n addToolResult,\n addToolApprovalResponse,\n }\n}\n"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"use-chat.js","names":[],"sources":["../src/use-chat.ts"],"sourcesContent":["import {\n createEffect,\n createMemo,\n createSignal,\n createUniqueId,\n} from 'solid-js'\n\nimport { ChatClient } from '@tanstack/ai-client'\nimport type { ChatClientState } from '@tanstack/ai-client'\nimport type { AnyClientTool, ModelMessage } from '@tanstack/ai'\nimport type { UIMessage, UseChatOptions, UseChatReturn } from './types'\n\nexport function useChat<TTools extends ReadonlyArray<AnyClientTool> = any>(\n options: UseChatOptions<TTools> = {} as UseChatOptions<TTools>,\n): UseChatReturn<TTools> {\n const hookId = createUniqueId()\n const clientId = options.id || hookId\n\n const [messages, setMessages] = createSignal<Array<UIMessage<TTools>>>(\n options.initialMessages || [],\n )\n const [isLoading, setIsLoading] = createSignal(false)\n const [error, setError] = createSignal<Error | undefined>(undefined)\n const [status, setStatus] = createSignal<ChatClientState>('ready')\n\n // Create ChatClient instance with callbacks to sync state\n // Note: Options are captured at client creation time.\n // The connection adapter can use functions for dynamic values (url, headers, etc.)\n // which are evaluated lazily on each request.\n const client = createMemo(() => {\n return new ChatClient({\n connection: options.connection,\n id: clientId,\n initialMessages: options.initialMessages,\n body: options.body,\n onResponse: options.onResponse,\n onChunk: options.onChunk,\n onFinish: (message) => {\n options.onFinish?.(message)\n },\n onError: (err) => {\n options.onError?.(err)\n },\n tools: options.tools,\n streamProcessor: options.streamProcessor,\n onMessagesChange: (newMessages: Array<UIMessage<TTools>>) => {\n setMessages(newMessages)\n },\n onLoadingChange: (newIsLoading: boolean) => {\n setIsLoading(newIsLoading)\n },\n onStatusChange: (newStatus: ChatClientState) => {\n setStatus(newStatus)\n },\n onErrorChange: (newError: Error | undefined) => {\n setError(newError)\n },\n })\n // Only recreate when clientId changes\n // Connection and other options are captured at creation time\n }, [clientId])\n\n // Sync body changes to the client\n // This allows dynamic body values (like model selection) to be updated without recreating the client\n createEffect(() => {\n const currentBody = options.body\n client().updateOptions({ body: currentBody })\n })\n\n // Sync initial messages on mount only\n // Note: initialMessages are passed to ChatClient constructor, but we also\n // set them here to ensure React state is in sync\n createEffect(() => {\n if (options.initialMessages && options.initialMessages.length > 0) {\n // Only set if current messages are empty (initial state)\n if (messages().length === 0) {\n client().setMessagesManually(options.initialMessages)\n }\n }\n }) // Only run on mount - initialMessages are handled by ChatClient constructor\n\n // Cleanup on unmount: stop any in-flight requests\n // Note: We use createEffect with a cleanup return to handle component unmount.\n // The cleanup only runs on disposal (unmount), not on signal changes.\n createEffect(() => {\n return () => {\n // Stop any active generation when component unmounts\n client().stop()\n }\n })\n\n // Note: Callback options (onResponse, onChunk, onFinish, onError, onToolCall)\n // are captured at client creation time. Changes to these callbacks require\n // remounting the component or changing the connection to recreate the client.\n\n const sendMessage = async (content: string) => {\n await client().sendMessage(content)\n }\n\n const append = async (message: ModelMessage | UIMessage<TTools>) => {\n await client().append(message)\n }\n\n const reload = async () => {\n await client().reload()\n }\n\n const stop = () => {\n client().stop()\n }\n\n const clear = () => {\n client().clear()\n }\n\n const setMessagesManually = (newMessages: Array<UIMessage<TTools>>) => {\n client().setMessagesManually(newMessages)\n }\n\n const addToolResult = async (result: {\n toolCallId: string\n tool: string\n output: any\n state?: 'output-available' | 'output-error'\n errorText?: string\n }) => {\n await client().addToolResult(result)\n }\n\n const addToolApprovalResponse = async (response: {\n id: string\n approved: boolean\n }) => {\n await client().addToolApprovalResponse(response)\n }\n\n return {\n messages,\n sendMessage,\n append,\n reload,\n stop,\n isLoading,\n error,\n status,\n setMessages: setMessagesManually,\n clear,\n addToolResult,\n addToolApprovalResponse,\n }\n}\n"],"mappings":";;;;AAYA,SAAgB,QACd,UAAkC,EAAE,EACb;CACvB,MAAM,SAAS,gBAAgB;CAC/B,MAAM,WAAW,QAAQ,MAAM;CAE/B,MAAM,CAAC,UAAU,eAAe,aAC9B,QAAQ,mBAAmB,EAAE,CAC9B;CACD,MAAM,CAAC,WAAW,gBAAgB,aAAa,MAAM;CACrD,MAAM,CAAC,OAAO,YAAY,aAAgC,OAAU;CACpE,MAAM,CAAC,QAAQ,aAAa,aAA8B,QAAQ;CAMlE,MAAM,SAAS,iBAAiB;AAC9B,SAAO,IAAI,WAAW;GACpB,YAAY,QAAQ;GACpB,IAAI;GACJ,iBAAiB,QAAQ;GACzB,MAAM,QAAQ;GACd,YAAY,QAAQ;GACpB,SAAS,QAAQ;GACjB,WAAW,YAAY;AACrB,YAAQ,WAAW,QAAQ;;GAE7B,UAAU,QAAQ;AAChB,YAAQ,UAAU,IAAI;;GAExB,OAAO,QAAQ;GACf,iBAAiB,QAAQ;GACzB,mBAAmB,gBAA0C;AAC3D,gBAAY,YAAY;;GAE1B,kBAAkB,iBAA0B;AAC1C,iBAAa,aAAa;;GAE5B,iBAAiB,cAA+B;AAC9C,cAAU,UAAU;;GAEtB,gBAAgB,aAAgC;AAC9C,aAAS,SAAS;;GAErB,CAAC;IAGD,CAAC,SAAS,CAAC;AAId,oBAAmB;EACjB,MAAM,cAAc,QAAQ;AAC5B,UAAQ,CAAC,cAAc,EAAE,MAAM,aAAa,CAAC;GAC7C;AAKF,oBAAmB;AACjB,MAAI,QAAQ,mBAAmB,QAAQ,gBAAgB,SAAS,GAE9D;OAAI,UAAU,CAAC,WAAW,EACxB,SAAQ,CAAC,oBAAoB,QAAQ,gBAAgB;;GAGzD;AAKF,oBAAmB;AACjB,eAAa;AAEX,WAAQ,CAAC,MAAM;;GAEjB;CAMF,MAAM,cAAc,OAAO,YAAoB;AAC7C,QAAM,QAAQ,CAAC,YAAY,QAAQ;;CAGrC,MAAM,SAAS,OAAO,YAA8C;AAClE,QAAM,QAAQ,CAAC,OAAO,QAAQ;;CAGhC,MAAM,SAAS,YAAY;AACzB,QAAM,QAAQ,CAAC,QAAQ;;CAGzB,MAAM,aAAa;AACjB,UAAQ,CAAC,MAAM;;CAGjB,MAAM,cAAc;AAClB,UAAQ,CAAC,OAAO;;CAGlB,MAAM,uBAAuB,gBAA0C;AACrE,UAAQ,CAAC,oBAAoB,YAAY;;CAG3C,MAAM,gBAAgB,OAAO,WAMvB;AACJ,QAAM,QAAQ,CAAC,cAAc,OAAO;;CAGtC,MAAM,0BAA0B,OAAO,aAGjC;AACJ,QAAM,QAAQ,CAAC,wBAAwB,SAAS;;AAGlD,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,aAAa;EACb;EACA;EACA;EACD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai-solid",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Solid hooks for TanStack AI",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
"streaming"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@tanstack/ai-client": "0.
|
|
34
|
+
"@tanstack/ai-client": "0.4.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"solid-js": ">=1.9.10",
|
|
38
|
-
"@tanstack/ai": "^0.
|
|
38
|
+
"@tanstack/ai": "^0.3.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@solidjs/testing-library": "^0.8.10",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"tsdown": "^0.17.0-beta.6",
|
|
47
47
|
"typescript": "5.9.3",
|
|
48
48
|
"vitest": "^4.0.14",
|
|
49
|
-
"@tanstack/ai": "0.
|
|
49
|
+
"@tanstack/ai": "0.3.1"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"clean": "premove ./build ./dist",
|
package/src/types.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import type { Accessor } from 'solid-js'
|
|
2
1
|
import type { AnyClientTool, ModelMessage } from '@tanstack/ai'
|
|
3
2
|
import type {
|
|
4
3
|
ChatClientOptions,
|
|
4
|
+
ChatClientState,
|
|
5
5
|
ChatRequestBody,
|
|
6
6
|
UIMessage,
|
|
7
7
|
} from '@tanstack/ai-client'
|
|
8
|
+
import type { Accessor } from 'solid-js'
|
|
8
9
|
|
|
9
10
|
// Re-export types from ai-client
|
|
10
|
-
export type {
|
|
11
|
+
export type { ChatRequestBody, UIMessage }
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Options for the useChat hook.
|
|
@@ -17,6 +18,7 @@ export type { UIMessage, ChatRequestBody }
|
|
|
17
18
|
* - `onMessagesChange` - Managed by Solid signal (exposed as `messages`)
|
|
18
19
|
* - `onLoadingChange` - Managed by Solid signal (exposed as `isLoading`)
|
|
19
20
|
* - `onErrorChange` - Managed by Solid signal (exposed as `error`)
|
|
21
|
+
* - `onStatusChange` - Managed by Solid signal (exposed as `status`)
|
|
20
22
|
*
|
|
21
23
|
* All other callbacks (onResponse, onChunk, onFinish, onError) are
|
|
22
24
|
* passed through to the underlying ChatClient and can be used for side effects.
|
|
@@ -27,7 +29,7 @@ export type { UIMessage, ChatRequestBody }
|
|
|
27
29
|
export type UseChatOptions<TTools extends ReadonlyArray<AnyClientTool> = any> =
|
|
28
30
|
Omit<
|
|
29
31
|
ChatClientOptions<TTools>,
|
|
30
|
-
'onMessagesChange' | 'onLoadingChange' | 'onErrorChange'
|
|
32
|
+
'onMessagesChange' | 'onLoadingChange' | 'onErrorChange' | 'onStatusChange'
|
|
31
33
|
>
|
|
32
34
|
|
|
33
35
|
export interface UseChatReturn<
|
|
@@ -96,6 +98,11 @@ export interface UseChatReturn<
|
|
|
96
98
|
* Clear all messages
|
|
97
99
|
*/
|
|
98
100
|
clear: () => void
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Current generation status
|
|
104
|
+
*/
|
|
105
|
+
status: Accessor<ChatClientState>
|
|
99
106
|
}
|
|
100
107
|
|
|
101
108
|
// Note: createChatClientOptions and InferChatMessages are now in @tanstack/ai-client
|
package/src/use-chat.ts
CHANGED
|
@@ -4,7 +4,9 @@ import {
|
|
|
4
4
|
createSignal,
|
|
5
5
|
createUniqueId,
|
|
6
6
|
} from 'solid-js'
|
|
7
|
+
|
|
7
8
|
import { ChatClient } from '@tanstack/ai-client'
|
|
9
|
+
import type { ChatClientState } from '@tanstack/ai-client'
|
|
8
10
|
import type { AnyClientTool, ModelMessage } from '@tanstack/ai'
|
|
9
11
|
import type { UIMessage, UseChatOptions, UseChatReturn } from './types'
|
|
10
12
|
|
|
@@ -19,6 +21,7 @@ export function useChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
|
|
|
19
21
|
)
|
|
20
22
|
const [isLoading, setIsLoading] = createSignal(false)
|
|
21
23
|
const [error, setError] = createSignal<Error | undefined>(undefined)
|
|
24
|
+
const [status, setStatus] = createSignal<ChatClientState>('ready')
|
|
22
25
|
|
|
23
26
|
// Create ChatClient instance with callbacks to sync state
|
|
24
27
|
// Note: Options are captured at client creation time.
|
|
@@ -32,8 +35,12 @@ export function useChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
|
|
|
32
35
|
body: options.body,
|
|
33
36
|
onResponse: options.onResponse,
|
|
34
37
|
onChunk: options.onChunk,
|
|
35
|
-
onFinish:
|
|
36
|
-
|
|
38
|
+
onFinish: (message) => {
|
|
39
|
+
options.onFinish?.(message)
|
|
40
|
+
},
|
|
41
|
+
onError: (err) => {
|
|
42
|
+
options.onError?.(err)
|
|
43
|
+
},
|
|
37
44
|
tools: options.tools,
|
|
38
45
|
streamProcessor: options.streamProcessor,
|
|
39
46
|
onMessagesChange: (newMessages: Array<UIMessage<TTools>>) => {
|
|
@@ -42,6 +49,9 @@ export function useChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
|
|
|
42
49
|
onLoadingChange: (newIsLoading: boolean) => {
|
|
43
50
|
setIsLoading(newIsLoading)
|
|
44
51
|
},
|
|
52
|
+
onStatusChange: (newStatus: ChatClientState) => {
|
|
53
|
+
setStatus(newStatus)
|
|
54
|
+
},
|
|
45
55
|
onErrorChange: (newError: Error | undefined) => {
|
|
46
56
|
setError(newError)
|
|
47
57
|
},
|
|
@@ -50,6 +60,13 @@ export function useChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
|
|
|
50
60
|
// Connection and other options are captured at creation time
|
|
51
61
|
}, [clientId])
|
|
52
62
|
|
|
63
|
+
// Sync body changes to the client
|
|
64
|
+
// This allows dynamic body values (like model selection) to be updated without recreating the client
|
|
65
|
+
createEffect(() => {
|
|
66
|
+
const currentBody = options.body
|
|
67
|
+
client().updateOptions({ body: currentBody })
|
|
68
|
+
})
|
|
69
|
+
|
|
53
70
|
// Sync initial messages on mount only
|
|
54
71
|
// Note: initialMessages are passed to ChatClient constructor, but we also
|
|
55
72
|
// set them here to ensure React state is in sync
|
|
@@ -125,6 +142,7 @@ export function useChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
|
|
|
125
142
|
stop,
|
|
126
143
|
isLoading,
|
|
127
144
|
error,
|
|
145
|
+
status,
|
|
128
146
|
setMessages: setMessagesManually,
|
|
129
147
|
clear,
|
|
130
148
|
addToolResult,
|