@tanstack/ai-svelte 0.7.2 → 0.8.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.svelte.d.ts +2 -2
- package/dist/create-chat.svelte.js +33 -1
- package/dist/index.d.ts +1 -1
- package/dist/types.d.ts +39 -3
- package/package.json +5 -4
- package/src/create-chat.svelte.ts +53 -6
- package/src/index.ts +1 -0
- package/src/types.ts +55 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyClientTool } from '@tanstack/ai';
|
|
1
|
+
import type { AnyClientTool, SchemaInput } from '@tanstack/ai';
|
|
2
2
|
import type { CreateChatOptions, CreateChatReturn } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Creates a reactive chat instance for Svelte 5.
|
|
@@ -30,4 +30,4 @@ import type { CreateChatOptions, CreateChatReturn } from './types';
|
|
|
30
30
|
* </div>
|
|
31
31
|
* ```
|
|
32
32
|
*/
|
|
33
|
-
export declare function createChat<TTools extends ReadonlyArray<AnyClientTool> = any>(options: CreateChatOptions<TTools>): CreateChatReturn<TTools>;
|
|
33
|
+
export declare function createChat<TTools extends ReadonlyArray<AnyClientTool> = any, TSchema extends SchemaInput | undefined = undefined>(options: CreateChatOptions<TTools, TSchema>): CreateChatReturn<TTools, TSchema>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ChatClient } from '@tanstack/ai-client';
|
|
2
|
+
import { parsePartialJSON } from '@tanstack/ai';
|
|
2
3
|
/**
|
|
3
4
|
* Creates a reactive chat instance for Svelte 5.
|
|
4
5
|
*
|
|
@@ -41,6 +42,10 @@ export function createChat(options) {
|
|
|
41
42
|
let isSubscribed = $state(false);
|
|
42
43
|
let connectionStatus = $state('disconnected');
|
|
43
44
|
let sessionGenerating = $state(false);
|
|
45
|
+
let partial = $state({});
|
|
46
|
+
let final = $state(null);
|
|
47
|
+
// Raw JSON accumulator — not reactive, just a local buffer.
|
|
48
|
+
let rawJson = '';
|
|
44
49
|
// Create ChatClient instance.
|
|
45
50
|
// Note: Svelte's createChat runs once per instance and `options` is captured
|
|
46
51
|
// by reference. Callbacks are therefore frozen to whatever the caller passed
|
|
@@ -52,7 +57,28 @@ export function createChat(options) {
|
|
|
52
57
|
initialMessages: options.initialMessages,
|
|
53
58
|
body: options.body,
|
|
54
59
|
onResponse: options.onResponse,
|
|
55
|
-
onChunk:
|
|
60
|
+
onChunk: (chunk) => {
|
|
61
|
+
if (options.outputSchema !== undefined) {
|
|
62
|
+
if (chunk.type === 'RUN_STARTED') {
|
|
63
|
+
rawJson = '';
|
|
64
|
+
partial = {};
|
|
65
|
+
final = null;
|
|
66
|
+
}
|
|
67
|
+
else if (chunk.type === 'TEXT_MESSAGE_CONTENT' && chunk.delta) {
|
|
68
|
+
rawJson += chunk.delta;
|
|
69
|
+
const progressive = parsePartialJSON(rawJson);
|
|
70
|
+
if (progressive && typeof progressive === 'object') {
|
|
71
|
+
partial = progressive;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else if (chunk.type === 'CUSTOM' &&
|
|
75
|
+
chunk.name === 'structured-output.complete') {
|
|
76
|
+
const value = chunk.value;
|
|
77
|
+
final = value.object;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
options.onChunk?.(chunk);
|
|
81
|
+
},
|
|
56
82
|
onFinish: (message) => {
|
|
57
83
|
options.onFinish?.(message);
|
|
58
84
|
},
|
|
@@ -143,6 +169,12 @@ export function createChat(options) {
|
|
|
143
169
|
get sessionGenerating() {
|
|
144
170
|
return sessionGenerating;
|
|
145
171
|
},
|
|
172
|
+
get partial() {
|
|
173
|
+
return partial;
|
|
174
|
+
},
|
|
175
|
+
get final() {
|
|
176
|
+
return final;
|
|
177
|
+
},
|
|
146
178
|
sendMessage,
|
|
147
179
|
append,
|
|
148
180
|
reload,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createChat } from './create-chat.svelte';
|
|
2
|
-
export type { CreateChatOptions, CreateChatReturn, UIMessage, ChatRequestBody, } from './types';
|
|
2
|
+
export type { CreateChatOptions, CreateChatReturn, DeepPartial, UIMessage, ChatRequestBody, } from './types';
|
|
3
3
|
export { createGeneration } from './create-generation.svelte';
|
|
4
4
|
export type { CreateGenerationOptions, CreateGenerationReturn, } from './create-generation.svelte';
|
|
5
5
|
export { createGenerateImage } from './create-generate-image.svelte';
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import type { AnyClientTool, ModelMessage } from '@tanstack/ai';
|
|
1
|
+
import type { AnyClientTool, InferSchemaType, ModelMessage, SchemaInput } from '@tanstack/ai';
|
|
2
2
|
import type { ChatClientOptions, ChatClientState, ChatRequestBody, ConnectionStatus, MultimodalContent, UIMessage } from '@tanstack/ai-client';
|
|
3
3
|
export type { ChatRequestBody, MultimodalContent, UIMessage };
|
|
4
|
+
/**
|
|
5
|
+
* Recursive partial — every property and every nested array element is
|
|
6
|
+
* optional. Used to type the in-flight `partial` getter while a structured-
|
|
7
|
+
* output stream is still arriving.
|
|
8
|
+
*/
|
|
9
|
+
export type DeepPartial<T> = T extends ReadonlyArray<infer U> ? Array<DeepPartial<U>> : T extends object ? {
|
|
10
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
11
|
+
} : T;
|
|
4
12
|
/**
|
|
5
13
|
* Options for the createChat function.
|
|
6
14
|
*
|
|
@@ -14,13 +22,41 @@ export type { ChatRequestBody, MultimodalContent, UIMessage };
|
|
|
14
22
|
* All other callbacks (onResponse, onChunk, onFinish, onError) are
|
|
15
23
|
* passed through to the underlying ChatClient and can be used for side effects.
|
|
16
24
|
*
|
|
25
|
+
* When `outputSchema` is supplied, the return adds typed `partial` and `final`
|
|
26
|
+
* reactive getters. The schema is used purely for type inference; server-side
|
|
27
|
+
* validation still runs against the schema passed to `chat({ outputSchema })`
|
|
28
|
+
* on the server route.
|
|
29
|
+
*
|
|
17
30
|
* Note: Connection and body changes will recreate the ChatClient instance.
|
|
18
31
|
* To update these options, remount the component or use a key prop.
|
|
19
32
|
*/
|
|
20
|
-
export type CreateChatOptions<TTools extends ReadonlyArray<AnyClientTool> = any> = Omit<ChatClientOptions<TTools>, 'onMessagesChange' | 'onLoadingChange' | 'onErrorChange' | 'onStatusChange' | 'onSubscriptionChange' | 'onConnectionStatusChange' | 'onSessionGeneratingChange'> & {
|
|
33
|
+
export type CreateChatOptions<TTools extends ReadonlyArray<AnyClientTool> = any, TSchema extends SchemaInput | undefined = undefined> = Omit<ChatClientOptions<TTools>, 'onMessagesChange' | 'onLoadingChange' | 'onErrorChange' | 'onStatusChange' | 'onSubscriptionChange' | 'onConnectionStatusChange' | 'onSessionGeneratingChange'> & {
|
|
21
34
|
live?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Standard-schema-compatible schema (Zod, Valibot, ArkType, or plain JSON
|
|
37
|
+
* Schema). Used to infer the shape of `partial` and `final`.
|
|
38
|
+
*/
|
|
39
|
+
outputSchema?: TSchema;
|
|
22
40
|
};
|
|
23
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Discriminated return shape: when `outputSchema` is supplied, the return adds
|
|
43
|
+
* typed `partial` / `final` reactive getters; otherwise the return is
|
|
44
|
+
* unchanged.
|
|
45
|
+
*/
|
|
46
|
+
export type CreateChatReturn<TTools extends ReadonlyArray<AnyClientTool> = any, TSchema extends SchemaInput | undefined = undefined> = BaseCreateChatReturn<TTools> & (TSchema extends SchemaInput ? {
|
|
47
|
+
/**
|
|
48
|
+
* Live progressively-parsed structured output (reactive getter).
|
|
49
|
+
* Resets on every new run.
|
|
50
|
+
*/
|
|
51
|
+
readonly partial: DeepPartial<InferSchemaType<TSchema>>;
|
|
52
|
+
/**
|
|
53
|
+
* Final, schema-validated structured output (reactive getter). `null`
|
|
54
|
+
* until the terminal `structured-output.complete` event arrives.
|
|
55
|
+
* Resets on every new run.
|
|
56
|
+
*/
|
|
57
|
+
readonly final: InferSchemaType<TSchema> | null;
|
|
58
|
+
} : Record<never, never>);
|
|
59
|
+
interface BaseCreateChatReturn<TTools extends ReadonlyArray<AnyClientTool> = any> {
|
|
24
60
|
/**
|
|
25
61
|
* Current messages in the conversation (reactive getter)
|
|
26
62
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai-svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Svelte bindings for TanStack AI",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,13 +33,14 @@
|
|
|
33
33
|
"streaming"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@tanstack/ai-client": "0.9.
|
|
36
|
+
"@tanstack/ai-client": "0.9.2"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"svelte": "^5.0.0",
|
|
40
|
-
"@tanstack/ai": "^0.
|
|
40
|
+
"@tanstack/ai": "^0.17.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
+
"@standard-schema/spec": "^1.1.0",
|
|
43
44
|
"@sveltejs/package": "^2.3.10",
|
|
44
45
|
"@sveltejs/vite-plugin-svelte": "^5.1.1",
|
|
45
46
|
"@types/node": "^24.10.1",
|
|
@@ -49,7 +50,7 @@
|
|
|
49
50
|
"svelte-check": "^4.2.0",
|
|
50
51
|
"typescript": "5.9.3",
|
|
51
52
|
"vite": "^7.2.7",
|
|
52
|
-
"@tanstack/ai": "0.
|
|
53
|
+
"@tanstack/ai": "0.17.0"
|
|
53
54
|
},
|
|
54
55
|
"scripts": {
|
|
55
56
|
"clean": "rm -rf ./dist",
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import { ChatClient } from '@tanstack/ai-client'
|
|
2
|
+
import { parsePartialJSON } from '@tanstack/ai'
|
|
2
3
|
import type { ChatClientState, ConnectionStatus } from '@tanstack/ai-client'
|
|
3
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
AnyClientTool,
|
|
6
|
+
InferSchemaType,
|
|
7
|
+
ModelMessage,
|
|
8
|
+
SchemaInput,
|
|
9
|
+
StreamChunk,
|
|
10
|
+
} from '@tanstack/ai'
|
|
4
11
|
import type {
|
|
5
12
|
CreateChatOptions,
|
|
6
13
|
CreateChatReturn,
|
|
14
|
+
DeepPartial,
|
|
7
15
|
MultimodalContent,
|
|
8
16
|
UIMessage,
|
|
9
17
|
} from './types'
|
|
@@ -38,9 +46,12 @@ import type {
|
|
|
38
46
|
* </div>
|
|
39
47
|
* ```
|
|
40
48
|
*/
|
|
41
|
-
export function createChat<
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
export function createChat<
|
|
50
|
+
TTools extends ReadonlyArray<AnyClientTool> = any,
|
|
51
|
+
TSchema extends SchemaInput | undefined = undefined,
|
|
52
|
+
>(
|
|
53
|
+
options: CreateChatOptions<TTools, TSchema>,
|
|
54
|
+
): CreateChatReturn<TTools, TSchema> {
|
|
44
55
|
// Generate a unique ID for this chat instance
|
|
45
56
|
const clientId =
|
|
46
57
|
options.id ||
|
|
@@ -55,6 +66,15 @@ export function createChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
|
|
|
55
66
|
let connectionStatus = $state<ConnectionStatus>('disconnected')
|
|
56
67
|
let sessionGenerating = $state(false)
|
|
57
68
|
|
|
69
|
+
// Structured-output state. Runtime always tracks them — the conditional
|
|
70
|
+
// return type hides them when no `outputSchema` is supplied.
|
|
71
|
+
type Partial = DeepPartial<InferSchemaType<NonNullable<TSchema>>>
|
|
72
|
+
type Final = InferSchemaType<NonNullable<TSchema>>
|
|
73
|
+
let partial = $state<Partial>({} as Partial)
|
|
74
|
+
let final = $state<Final | null>(null)
|
|
75
|
+
// Raw JSON accumulator — not reactive, just a local buffer.
|
|
76
|
+
let rawJson = ''
|
|
77
|
+
|
|
58
78
|
// Create ChatClient instance.
|
|
59
79
|
// Note: Svelte's createChat runs once per instance and `options` is captured
|
|
60
80
|
// by reference. Callbacks are therefore frozen to whatever the caller passed
|
|
@@ -66,7 +86,28 @@ export function createChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
|
|
|
66
86
|
initialMessages: options.initialMessages,
|
|
67
87
|
body: options.body,
|
|
68
88
|
onResponse: options.onResponse,
|
|
69
|
-
onChunk:
|
|
89
|
+
onChunk: (chunk: StreamChunk) => {
|
|
90
|
+
if (options.outputSchema !== undefined) {
|
|
91
|
+
if (chunk.type === 'RUN_STARTED') {
|
|
92
|
+
rawJson = ''
|
|
93
|
+
partial = {} as Partial
|
|
94
|
+
final = null
|
|
95
|
+
} else if (chunk.type === 'TEXT_MESSAGE_CONTENT' && chunk.delta) {
|
|
96
|
+
rawJson += chunk.delta
|
|
97
|
+
const progressive = parsePartialJSON(rawJson)
|
|
98
|
+
if (progressive && typeof progressive === 'object') {
|
|
99
|
+
partial = progressive as Partial
|
|
100
|
+
}
|
|
101
|
+
} else if (
|
|
102
|
+
chunk.type === 'CUSTOM' &&
|
|
103
|
+
chunk.name === 'structured-output.complete'
|
|
104
|
+
) {
|
|
105
|
+
const value = chunk.value as { object: unknown }
|
|
106
|
+
final = value.object as Final
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
options.onChunk?.(chunk)
|
|
110
|
+
},
|
|
70
111
|
onFinish: (message) => {
|
|
71
112
|
options.onFinish?.(message)
|
|
72
113
|
},
|
|
@@ -178,6 +219,12 @@ export function createChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
|
|
|
178
219
|
get sessionGenerating() {
|
|
179
220
|
return sessionGenerating
|
|
180
221
|
},
|
|
222
|
+
get partial() {
|
|
223
|
+
return partial
|
|
224
|
+
},
|
|
225
|
+
get final() {
|
|
226
|
+
return final
|
|
227
|
+
},
|
|
181
228
|
sendMessage,
|
|
182
229
|
append,
|
|
183
230
|
reload,
|
|
@@ -187,5 +234,5 @@ export function createChat<TTools extends ReadonlyArray<AnyClientTool> = any>(
|
|
|
187
234
|
addToolResult,
|
|
188
235
|
addToolApprovalResponse,
|
|
189
236
|
updateBody,
|
|
190
|
-
}
|
|
237
|
+
} as unknown as CreateChatReturn<TTools, TSchema>
|
|
191
238
|
}
|
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
AnyClientTool,
|
|
3
|
+
InferSchemaType,
|
|
4
|
+
ModelMessage,
|
|
5
|
+
SchemaInput,
|
|
6
|
+
} from '@tanstack/ai'
|
|
2
7
|
import type {
|
|
3
8
|
ChatClientOptions,
|
|
4
9
|
ChatClientState,
|
|
@@ -11,6 +16,18 @@ import type {
|
|
|
11
16
|
// Re-export types from ai-client
|
|
12
17
|
export type { ChatRequestBody, MultimodalContent, UIMessage }
|
|
13
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Recursive partial — every property and every nested array element is
|
|
21
|
+
* optional. Used to type the in-flight `partial` getter while a structured-
|
|
22
|
+
* output stream is still arriving.
|
|
23
|
+
*/
|
|
24
|
+
export type DeepPartial<T> =
|
|
25
|
+
T extends ReadonlyArray<infer U>
|
|
26
|
+
? Array<DeepPartial<U>>
|
|
27
|
+
: T extends object
|
|
28
|
+
? { [K in keyof T]?: DeepPartial<T[K]> }
|
|
29
|
+
: T
|
|
30
|
+
|
|
14
31
|
/**
|
|
15
32
|
* Options for the createChat function.
|
|
16
33
|
*
|
|
@@ -24,11 +41,17 @@ export type { ChatRequestBody, MultimodalContent, UIMessage }
|
|
|
24
41
|
* All other callbacks (onResponse, onChunk, onFinish, onError) are
|
|
25
42
|
* passed through to the underlying ChatClient and can be used for side effects.
|
|
26
43
|
*
|
|
44
|
+
* When `outputSchema` is supplied, the return adds typed `partial` and `final`
|
|
45
|
+
* reactive getters. The schema is used purely for type inference; server-side
|
|
46
|
+
* validation still runs against the schema passed to `chat({ outputSchema })`
|
|
47
|
+
* on the server route.
|
|
48
|
+
*
|
|
27
49
|
* Note: Connection and body changes will recreate the ChatClient instance.
|
|
28
50
|
* To update these options, remount the component or use a key prop.
|
|
29
51
|
*/
|
|
30
52
|
export type CreateChatOptions<
|
|
31
53
|
TTools extends ReadonlyArray<AnyClientTool> = any,
|
|
54
|
+
TSchema extends SchemaInput | undefined = undefined,
|
|
32
55
|
> = Omit<
|
|
33
56
|
ChatClientOptions<TTools>,
|
|
34
57
|
| 'onMessagesChange'
|
|
@@ -40,9 +63,39 @@ export type CreateChatOptions<
|
|
|
40
63
|
| 'onSessionGeneratingChange'
|
|
41
64
|
> & {
|
|
42
65
|
live?: boolean
|
|
66
|
+
/**
|
|
67
|
+
* Standard-schema-compatible schema (Zod, Valibot, ArkType, or plain JSON
|
|
68
|
+
* Schema). Used to infer the shape of `partial` and `final`.
|
|
69
|
+
*/
|
|
70
|
+
outputSchema?: TSchema
|
|
43
71
|
}
|
|
44
72
|
|
|
45
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Discriminated return shape: when `outputSchema` is supplied, the return adds
|
|
75
|
+
* typed `partial` / `final` reactive getters; otherwise the return is
|
|
76
|
+
* unchanged.
|
|
77
|
+
*/
|
|
78
|
+
export type CreateChatReturn<
|
|
79
|
+
TTools extends ReadonlyArray<AnyClientTool> = any,
|
|
80
|
+
TSchema extends SchemaInput | undefined = undefined,
|
|
81
|
+
> = BaseCreateChatReturn<TTools> &
|
|
82
|
+
(TSchema extends SchemaInput
|
|
83
|
+
? {
|
|
84
|
+
/**
|
|
85
|
+
* Live progressively-parsed structured output (reactive getter).
|
|
86
|
+
* Resets on every new run.
|
|
87
|
+
*/
|
|
88
|
+
readonly partial: DeepPartial<InferSchemaType<TSchema>>
|
|
89
|
+
/**
|
|
90
|
+
* Final, schema-validated structured output (reactive getter). `null`
|
|
91
|
+
* until the terminal `structured-output.complete` event arrives.
|
|
92
|
+
* Resets on every new run.
|
|
93
|
+
*/
|
|
94
|
+
readonly final: InferSchemaType<TSchema> | null
|
|
95
|
+
}
|
|
96
|
+
: Record<never, never>)
|
|
97
|
+
|
|
98
|
+
interface BaseCreateChatReturn<
|
|
46
99
|
TTools extends ReadonlyArray<AnyClientTool> = any,
|
|
47
100
|
> {
|
|
48
101
|
/**
|