@tanstack/ai-svelte 0.10.1 → 0.10.3
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.js +22 -8
- package/dist/create-generate-video.svelte.js +4 -0
- package/dist/create-generation.svelte.js +5 -0
- package/package.json +4 -4
- package/src/create-chat.svelte.ts +23 -9
- package/src/create-generate-video.svelte.ts +4 -0
- package/src/create-generation.svelte.ts +5 -0
|
@@ -46,13 +46,22 @@ export function createChat(options) {
|
|
|
46
46
|
// by reference. Callbacks are therefore frozen to whatever the caller passed
|
|
47
47
|
// at creation — to swap them dynamically, mutate the options object
|
|
48
48
|
// in-place or call `client.updateOptions(...)` imperatively.
|
|
49
|
+
// Optional fields use conditional spread because the target
|
|
50
|
+
// `ChatClientOptions` declares them as `field?: T` (absent vs. present)
|
|
51
|
+
// rather than `field?: T | undefined`. Under `exactOptionalPropertyTypes`,
|
|
52
|
+
// passing an explicit `undefined` for an absent-only optional is a type
|
|
53
|
+
// error, so we omit the key when the caller's value is undefined.
|
|
49
54
|
const client = new ChatClient({
|
|
50
55
|
connection: options.connection,
|
|
51
56
|
id: clientId,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
...(options.initialMessages !== undefined && {
|
|
58
|
+
initialMessages: options.initialMessages,
|
|
59
|
+
}),
|
|
60
|
+
...(options.body !== undefined && { body: options.body }),
|
|
61
|
+
...(options.forwardedProps !== undefined && {
|
|
62
|
+
forwardedProps: options.forwardedProps,
|
|
63
|
+
}),
|
|
64
|
+
...(options.onResponse !== undefined && { onResponse: options.onResponse }),
|
|
56
65
|
onChunk: (chunk) => {
|
|
57
66
|
options.onChunk?.(chunk);
|
|
58
67
|
},
|
|
@@ -63,8 +72,12 @@ export function createChat(options) {
|
|
|
63
72
|
options.onError?.(err);
|
|
64
73
|
},
|
|
65
74
|
tools: options.tools,
|
|
66
|
-
|
|
67
|
-
|
|
75
|
+
...(options.onCustomEvent !== undefined && {
|
|
76
|
+
onCustomEvent: options.onCustomEvent,
|
|
77
|
+
}),
|
|
78
|
+
...(options.streamProcessor !== undefined && {
|
|
79
|
+
streamProcessor: options.streamProcessor,
|
|
80
|
+
}),
|
|
68
81
|
onMessagesChange: (newMessages) => {
|
|
69
82
|
messages = newMessages;
|
|
70
83
|
},
|
|
@@ -138,7 +151,7 @@ export function createChat(options) {
|
|
|
138
151
|
const activeStructuredPart = $derived.by(() => {
|
|
139
152
|
let lastUserIndex = -1;
|
|
140
153
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
141
|
-
if (messages[i]
|
|
154
|
+
if (messages[i]?.role === 'user') {
|
|
142
155
|
lastUserIndex = i;
|
|
143
156
|
break;
|
|
144
157
|
}
|
|
@@ -147,7 +160,7 @@ export function createChat(options) {
|
|
|
147
160
|
return null;
|
|
148
161
|
for (let i = messages.length - 1; i > lastUserIndex; i--) {
|
|
149
162
|
const m = messages[i];
|
|
150
|
-
if (m
|
|
163
|
+
if (m?.role !== 'assistant')
|
|
151
164
|
continue;
|
|
152
165
|
const part = m.parts.find((p) => p.type === 'structured-output');
|
|
153
166
|
if (part)
|
|
@@ -166,6 +179,7 @@ export function createChat(options) {
|
|
|
166
179
|
: null);
|
|
167
180
|
// Return the chat interface with reactive getters
|
|
168
181
|
// Using getters allows Svelte to track reactivity without needing $ prefix
|
|
182
|
+
// eslint-disable-next-line no-restricted-syntax -- rune return shape diverges from generic CreateChatReturn<TTools, TSchema> due to TSchema conditional partial/final fields; TS can't structurally narrow.
|
|
169
183
|
return {
|
|
170
184
|
get messages() {
|
|
171
185
|
return messages;
|
|
@@ -39,6 +39,10 @@ export function createGenerateVideo(options) {
|
|
|
39
39
|
let isLoading = $state(false);
|
|
40
40
|
let error = $state(undefined);
|
|
41
41
|
let status = $state('idle');
|
|
42
|
+
// `body` uses a conditional spread because `VideoGenerationClientOptions.body`
|
|
43
|
+
// is declared `body?: Record<string, any>` (absent vs. present) under
|
|
44
|
+
// `exactOptionalPropertyTypes`. The optional caller `options.body` may be
|
|
45
|
+
// undefined, in which case we want the key to be absent on the target.
|
|
42
46
|
const baseOptions = {
|
|
43
47
|
id: clientId,
|
|
44
48
|
body: options.body,
|
|
@@ -37,6 +37,11 @@ export function createGeneration(options) {
|
|
|
37
37
|
let isLoading = $state(false);
|
|
38
38
|
let error = $state(undefined);
|
|
39
39
|
let status = $state('idle');
|
|
40
|
+
// `body` uses a conditional spread because `GenerationClientOptions.body`
|
|
41
|
+
// is declared `body?: Record<string, any>` (absent vs. present) under
|
|
42
|
+
// `exactOptionalPropertyTypes`. Assigning `undefined` directly would be
|
|
43
|
+
// rejected — the optional caller `options.body` may be undefined, in which
|
|
44
|
+
// case we want the key to be absent.
|
|
40
45
|
const clientOptions = {
|
|
41
46
|
id: clientId,
|
|
42
47
|
body: options.body,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai-svelte",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.3",
|
|
4
4
|
"description": "Svelte bindings for TanStack AI",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"streaming"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@tanstack/ai-client": "0.11.
|
|
36
|
+
"@tanstack/ai-client": "0.11.3"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"svelte": "^5.0.0",
|
|
40
|
-
"@tanstack/ai": "^0.
|
|
40
|
+
"@tanstack/ai": "^0.20.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@standard-schema/spec": "^1.1.0",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"svelte-check": "^4.2.0",
|
|
51
51
|
"typescript": "5.9.3",
|
|
52
52
|
"vite": "^7.3.3",
|
|
53
|
-
"@tanstack/ai": "0.
|
|
53
|
+
"@tanstack/ai": "0.20.1"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"clean": "rm -rf ./dist",
|
|
@@ -81,13 +81,22 @@ export function createChat<
|
|
|
81
81
|
// by reference. Callbacks are therefore frozen to whatever the caller passed
|
|
82
82
|
// at creation — to swap them dynamically, mutate the options object
|
|
83
83
|
// in-place or call `client.updateOptions(...)` imperatively.
|
|
84
|
+
// Optional fields use conditional spread because the target
|
|
85
|
+
// `ChatClientOptions` declares them as `field?: T` (absent vs. present)
|
|
86
|
+
// rather than `field?: T | undefined`. Under `exactOptionalPropertyTypes`,
|
|
87
|
+
// passing an explicit `undefined` for an absent-only optional is a type
|
|
88
|
+
// error, so we omit the key when the caller's value is undefined.
|
|
84
89
|
const client = new ChatClient({
|
|
85
90
|
connection: options.connection,
|
|
86
91
|
id: clientId,
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
...(options.initialMessages !== undefined && {
|
|
93
|
+
initialMessages: options.initialMessages,
|
|
94
|
+
}),
|
|
95
|
+
...(options.body !== undefined && { body: options.body }),
|
|
96
|
+
...(options.forwardedProps !== undefined && {
|
|
97
|
+
forwardedProps: options.forwardedProps,
|
|
98
|
+
}),
|
|
99
|
+
...(options.onResponse !== undefined && { onResponse: options.onResponse }),
|
|
91
100
|
onChunk: (chunk: StreamChunk) => {
|
|
92
101
|
options.onChunk?.(chunk)
|
|
93
102
|
},
|
|
@@ -98,8 +107,12 @@ export function createChat<
|
|
|
98
107
|
options.onError?.(err)
|
|
99
108
|
},
|
|
100
109
|
tools: options.tools,
|
|
101
|
-
|
|
102
|
-
|
|
110
|
+
...(options.onCustomEvent !== undefined && {
|
|
111
|
+
onCustomEvent: options.onCustomEvent,
|
|
112
|
+
}),
|
|
113
|
+
...(options.streamProcessor !== undefined && {
|
|
114
|
+
streamProcessor: options.streamProcessor,
|
|
115
|
+
}),
|
|
103
116
|
onMessagesChange: (newMessages: Array<UIMessage<TTools>>) => {
|
|
104
117
|
messages = newMessages
|
|
105
118
|
},
|
|
@@ -195,15 +208,15 @@ export function createChat<
|
|
|
195
208
|
const activeStructuredPart: StructuredOutputPart | null = $derived.by(() => {
|
|
196
209
|
let lastUserIndex = -1
|
|
197
210
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
198
|
-
if (messages[i]
|
|
211
|
+
if (messages[i]?.role === 'user') {
|
|
199
212
|
lastUserIndex = i
|
|
200
213
|
break
|
|
201
214
|
}
|
|
202
215
|
}
|
|
203
216
|
if (lastUserIndex === -1) return null
|
|
204
217
|
for (let i = messages.length - 1; i > lastUserIndex; i--) {
|
|
205
|
-
const m = messages[i]
|
|
206
|
-
if (m
|
|
218
|
+
const m = messages[i]
|
|
219
|
+
if (m?.role !== 'assistant') continue
|
|
207
220
|
const part = m.parts.find(
|
|
208
221
|
(p): p is StructuredOutputPart => p.type === 'structured-output',
|
|
209
222
|
)
|
|
@@ -226,6 +239,7 @@ export function createChat<
|
|
|
226
239
|
|
|
227
240
|
// Return the chat interface with reactive getters
|
|
228
241
|
// Using getters allows Svelte to track reactivity without needing $ prefix
|
|
242
|
+
// eslint-disable-next-line no-restricted-syntax -- rune return shape diverges from generic CreateChatReturn<TTools, TSchema> due to TSchema conditional partial/final fields; TS can't structurally narrow.
|
|
229
243
|
return {
|
|
230
244
|
get messages() {
|
|
231
245
|
return messages
|
|
@@ -125,6 +125,10 @@ export function createGenerateVideo<
|
|
|
125
125
|
let error = $state<Error | undefined>(undefined)
|
|
126
126
|
let status = $state<GenerationClientState>('idle')
|
|
127
127
|
|
|
128
|
+
// `body` uses a conditional spread because `VideoGenerationClientOptions.body`
|
|
129
|
+
// is declared `body?: Record<string, any>` (absent vs. present) under
|
|
130
|
+
// `exactOptionalPropertyTypes`. The optional caller `options.body` may be
|
|
131
|
+
// undefined, in which case we want the key to be absent on the target.
|
|
128
132
|
const baseOptions = {
|
|
129
133
|
id: clientId,
|
|
130
134
|
body: options.body,
|
|
@@ -116,6 +116,11 @@ export function createGeneration<
|
|
|
116
116
|
let error = $state<Error | undefined>(undefined)
|
|
117
117
|
let status = $state<GenerationClientState>('idle')
|
|
118
118
|
|
|
119
|
+
// `body` uses a conditional spread because `GenerationClientOptions.body`
|
|
120
|
+
// is declared `body?: Record<string, any>` (absent vs. present) under
|
|
121
|
+
// `exactOptionalPropertyTypes`. Assigning `undefined` directly would be
|
|
122
|
+
// rejected — the optional caller `options.body` may be undefined, in which
|
|
123
|
+
// case we want the key to be absent.
|
|
119
124
|
const clientOptions: GenerationClientOptions<TInput, TResult, TOutput> = {
|
|
120
125
|
id: clientId,
|
|
121
126
|
body: options.body,
|