@tanstack/ai-client 0.12.0 → 0.14.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/esm/chat-client.d.ts +16 -2
- package/dist/esm/chat-client.js +197 -31
- package/dist/esm/chat-client.js.map +1 -1
- package/dist/esm/connection-adapters.d.ts +21 -1
- package/dist/esm/connection-adapters.js +262 -68
- package/dist/esm/connection-adapters.js.map +1 -1
- package/dist/esm/devtools-noop.d.ts +60 -0
- package/dist/esm/devtools-noop.js +135 -0
- package/dist/esm/devtools-noop.js.map +1 -0
- package/dist/esm/devtools.d.ts +276 -0
- package/dist/esm/devtools.js +1178 -0
- package/dist/esm/devtools.js.map +1 -0
- package/dist/esm/events.d.ts +51 -8
- package/dist/esm/events.js +65 -20
- package/dist/esm/events.js.map +1 -1
- package/dist/esm/generation-client.d.ts +14 -0
- package/dist/esm/generation-client.js +135 -5
- package/dist/esm/generation-client.js.map +1 -1
- package/dist/esm/generation-types.d.ts +16 -2
- package/dist/esm/generation-types.js.map +1 -1
- package/dist/esm/index.d.ts +6 -4
- package/dist/esm/index.js +9 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/realtime-client.d.ts +1 -1
- package/dist/esm/realtime-client.js +1 -1
- package/dist/esm/realtime-client.js.map +1 -1
- package/dist/esm/realtime-types.d.ts +1 -1
- package/dist/esm/response-stream.d.ts +7 -0
- package/dist/esm/response-stream.js +32 -0
- package/dist/esm/response-stream.js.map +1 -0
- package/dist/esm/sse-parser.d.ts +1 -1
- package/dist/esm/sse-parser.js +5 -6
- package/dist/esm/sse-parser.js.map +1 -1
- package/dist/esm/sse-utils.d.ts +1 -0
- package/dist/esm/sse-utils.js +11 -0
- package/dist/esm/sse-utils.js.map +1 -0
- package/dist/esm/tool-types.d.ts +1 -1
- package/dist/esm/types.d.ts +23 -5
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/video-generation-client.d.ts +15 -0
- package/dist/esm/video-generation-client.js +147 -8
- package/dist/esm/video-generation-client.js.map +1 -1
- package/package.json +7 -3
- package/src/chat-client.ts +250 -33
- package/src/connection-adapters.ts +360 -68
- package/src/devtools-noop.ts +205 -0
- package/src/devtools.ts +1866 -0
- package/src/events.ts +143 -12
- package/src/generation-client.ts +177 -10
- package/src/generation-types.ts +24 -5
- package/src/index.ts +16 -3
- package/src/realtime-client.ts +2 -2
- package/src/realtime-types.ts +1 -1
- package/src/response-stream.ts +42 -0
- package/src/sse-parser.ts +9 -7
- package/src/sse-utils.ts +8 -0
- package/src/tool-types.ts +1 -1
- package/src/types.ts +31 -4
- package/src/video-generation-client.ts +187 -12
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { GENERATION_EVENTS } from "./generation-types.js";
|
|
2
|
+
import { createNoOpVideoDevtoolsBridge } from "./devtools-noop.js";
|
|
2
3
|
import { parseSSEResponse } from "./sse-parser.js";
|
|
3
4
|
class VideoGenerationClient {
|
|
4
5
|
connection;
|
|
5
6
|
fetcher;
|
|
7
|
+
uniqueId;
|
|
8
|
+
devtoolsMetadata;
|
|
9
|
+
devtoolsBridge;
|
|
10
|
+
threadId;
|
|
6
11
|
body;
|
|
7
12
|
result = null;
|
|
13
|
+
input = null;
|
|
14
|
+
progress = null;
|
|
8
15
|
jobId = null;
|
|
9
16
|
videoStatus = null;
|
|
10
17
|
isLoading = false;
|
|
@@ -12,7 +19,10 @@ class VideoGenerationClient {
|
|
|
12
19
|
status = "idle";
|
|
13
20
|
abortController = null;
|
|
14
21
|
callbacksRef;
|
|
22
|
+
devtoolsMounted = false;
|
|
15
23
|
constructor(options) {
|
|
24
|
+
this.uniqueId = options.id ?? this.generateUniqueId("video");
|
|
25
|
+
this.threadId = this.uniqueId;
|
|
16
26
|
this.connection = options.connection;
|
|
17
27
|
this.fetcher = options.fetcher;
|
|
18
28
|
this.body = options.body ?? {};
|
|
@@ -30,13 +40,45 @@ class VideoGenerationClient {
|
|
|
30
40
|
onJobIdChange: options.onJobIdChange,
|
|
31
41
|
onVideoStatusChange: options.onVideoStatusChange
|
|
32
42
|
};
|
|
43
|
+
this.devtoolsMetadata = this.createDevtoolsMetadata(options.devtools);
|
|
44
|
+
this.devtoolsBridge = (options.devtoolsBridgeFactory ?? createNoOpVideoDevtoolsBridge)(this.buildDevtoolsBridgeOptions());
|
|
45
|
+
}
|
|
46
|
+
buildDevtoolsBridgeOptions() {
|
|
47
|
+
return {
|
|
48
|
+
hookId: this.uniqueId,
|
|
49
|
+
clientId: this.uniqueId,
|
|
50
|
+
threadId: this.threadId,
|
|
51
|
+
metadata: this.devtoolsMetadata,
|
|
52
|
+
getCoreState: () => ({
|
|
53
|
+
input: this.input,
|
|
54
|
+
result: this.result,
|
|
55
|
+
progress: this.progress,
|
|
56
|
+
status: this.status,
|
|
57
|
+
isLoading: this.isLoading,
|
|
58
|
+
jobId: this.jobId,
|
|
59
|
+
videoStatus: this.videoStatus,
|
|
60
|
+
...this.error ? { error: this.error.message } : {}
|
|
61
|
+
})
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
mountDevtools() {
|
|
65
|
+
if (this.devtoolsMounted) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.devtoolsMounted = true;
|
|
69
|
+
this.devtoolsBridge.emitRegistered();
|
|
70
|
+
this.devtoolsBridge.emitSnapshot();
|
|
33
71
|
}
|
|
34
72
|
/**
|
|
35
73
|
* Trigger video generation.
|
|
36
74
|
* Only one generation can be in-flight at a time.
|
|
37
75
|
*/
|
|
38
76
|
async generate(input) {
|
|
77
|
+
this.mountDevtools();
|
|
39
78
|
if (this.isLoading) return;
|
|
79
|
+
this.input = input;
|
|
80
|
+
this.progress = null;
|
|
81
|
+
const runId = this.devtoolsBridge.beginRun(input);
|
|
40
82
|
this.setIsLoading(true);
|
|
41
83
|
this.setStatus("generating");
|
|
42
84
|
this.setError(void 0);
|
|
@@ -47,21 +89,39 @@ class VideoGenerationClient {
|
|
|
47
89
|
const { signal } = abortController;
|
|
48
90
|
try {
|
|
49
91
|
if (this.fetcher) {
|
|
50
|
-
await this.generateWithFetcher(input, signal);
|
|
92
|
+
await this.generateWithFetcher(input, signal, runId);
|
|
51
93
|
} else if (this.connection) {
|
|
52
94
|
const mergedData = { ...this.body, ...input };
|
|
53
|
-
const stream = this.connection.connect(
|
|
54
|
-
|
|
95
|
+
const stream = this.connection.connect(
|
|
96
|
+
[],
|
|
97
|
+
mergedData,
|
|
98
|
+
signal,
|
|
99
|
+
this.createRunContext(runId)
|
|
100
|
+
);
|
|
101
|
+
await this.processStream(stream, runId);
|
|
55
102
|
} else {
|
|
56
103
|
throw new Error(
|
|
57
104
|
"VideoGenerationClient requires either a connection or fetcher option"
|
|
58
105
|
);
|
|
59
106
|
}
|
|
107
|
+
if (!signal.aborted && this.status === "success") {
|
|
108
|
+
this.devtoolsBridge.finishRun(
|
|
109
|
+
this.devtoolsBridge.getActiveRunId() ?? runId,
|
|
110
|
+
"run:completed",
|
|
111
|
+
"completed"
|
|
112
|
+
);
|
|
113
|
+
}
|
|
60
114
|
} catch (err) {
|
|
61
115
|
if (signal.aborted) return;
|
|
62
116
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
63
117
|
this.setError(error);
|
|
64
118
|
this.setStatus("error");
|
|
119
|
+
this.devtoolsBridge.finishRun(
|
|
120
|
+
this.devtoolsBridge.getActiveRunId() ?? runId,
|
|
121
|
+
"run:errored",
|
|
122
|
+
"errored",
|
|
123
|
+
error.message
|
|
124
|
+
);
|
|
65
125
|
this.callbacksRef.onError?.(error);
|
|
66
126
|
} finally {
|
|
67
127
|
this.abortController = null;
|
|
@@ -71,13 +131,14 @@ class VideoGenerationClient {
|
|
|
71
131
|
/**
|
|
72
132
|
* Direct fetcher mode: call fetcher and set result.
|
|
73
133
|
*/
|
|
74
|
-
async generateWithFetcher(input, signal) {
|
|
134
|
+
async generateWithFetcher(input, signal, runId) {
|
|
75
135
|
if (!this.fetcher) return;
|
|
76
136
|
const result = await this.fetcher(input, { signal });
|
|
77
137
|
if (signal.aborted) return;
|
|
78
138
|
if (result instanceof Response) {
|
|
79
|
-
await this.processStream(parseSSEResponse(result, signal));
|
|
139
|
+
await this.processStream(parseSSEResponse(result, signal), runId);
|
|
80
140
|
} else {
|
|
141
|
+
this.devtoolsBridge.ensureRunStarted(runId);
|
|
81
142
|
this.setResult(result);
|
|
82
143
|
this.setStatus("success");
|
|
83
144
|
}
|
|
@@ -86,12 +147,20 @@ class VideoGenerationClient {
|
|
|
86
147
|
* Process a stream of AG-UI events from the streaming connection adapter.
|
|
87
148
|
* The server handles the polling loop and streams status updates.
|
|
88
149
|
*/
|
|
89
|
-
async processStream(source) {
|
|
150
|
+
async processStream(source, fallbackRunId) {
|
|
151
|
+
let streamRunId;
|
|
90
152
|
for await (const chunk of source) {
|
|
91
153
|
if (this.abortController?.signal.aborted) break;
|
|
92
154
|
this.callbacksRef.onChunk?.(chunk);
|
|
155
|
+
const chunkRunId = "runId" in chunk && typeof chunk.runId === "string" ? chunk.runId : void 0;
|
|
93
156
|
switch (chunk.type) {
|
|
157
|
+
case "RUN_STARTED": {
|
|
158
|
+
streamRunId = chunk.runId;
|
|
159
|
+
this.devtoolsBridge.ensureRunStarted(chunk.runId);
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
94
162
|
case "CUSTOM": {
|
|
163
|
+
this.devtoolsBridge.ensureRunStarted(streamRunId ?? fallbackRunId);
|
|
95
164
|
if (chunk.name === GENERATION_EVENTS.VIDEO_JOB_CREATED) {
|
|
96
165
|
const { jobId } = chunk.value;
|
|
97
166
|
this.setJobId(jobId);
|
|
@@ -101,21 +170,26 @@ class VideoGenerationClient {
|
|
|
101
170
|
this.setVideoStatus(statusInfo);
|
|
102
171
|
this.callbacksRef.onStatusUpdate?.(statusInfo);
|
|
103
172
|
if (statusInfo.progress !== void 0) {
|
|
104
|
-
this.
|
|
173
|
+
this.setProgress(statusInfo.progress);
|
|
105
174
|
}
|
|
106
175
|
} else if (chunk.name === GENERATION_EVENTS.RESULT) {
|
|
107
176
|
this.setResult(chunk.value);
|
|
108
177
|
} else if (chunk.name === GENERATION_EVENTS.PROGRESS) {
|
|
109
178
|
const { progress, message } = chunk.value;
|
|
110
|
-
this.
|
|
179
|
+
this.setProgress(progress, message);
|
|
111
180
|
}
|
|
112
181
|
break;
|
|
113
182
|
}
|
|
114
183
|
case "RUN_FINISHED": {
|
|
184
|
+
streamRunId = chunk.runId;
|
|
185
|
+
this.devtoolsBridge.ensureRunStarted(chunk.runId);
|
|
115
186
|
this.setStatus("success");
|
|
116
187
|
break;
|
|
117
188
|
}
|
|
118
189
|
case "RUN_ERROR": {
|
|
190
|
+
this.devtoolsBridge.ensureRunStarted(
|
|
191
|
+
chunkRunId ?? streamRunId ?? fallbackRunId
|
|
192
|
+
);
|
|
119
193
|
const msg = chunk.message || chunk.error?.message || "An error occurred";
|
|
120
194
|
throw new Error(msg);
|
|
121
195
|
}
|
|
@@ -126,6 +200,7 @@ class VideoGenerationClient {
|
|
|
126
200
|
* Abort any in-flight generation or polling.
|
|
127
201
|
*/
|
|
128
202
|
stop() {
|
|
203
|
+
const runId = this.devtoolsBridge.getActiveRunId();
|
|
129
204
|
if (this.abortController) {
|
|
130
205
|
this.abortController.abort();
|
|
131
206
|
this.abortController = null;
|
|
@@ -133,6 +208,9 @@ class VideoGenerationClient {
|
|
|
133
208
|
this.setIsLoading(false);
|
|
134
209
|
if (this.status === "generating") {
|
|
135
210
|
this.setStatus("idle");
|
|
211
|
+
if (runId) {
|
|
212
|
+
this.devtoolsBridge.finishRun(runId, "run:cancelled", "cancelled");
|
|
213
|
+
}
|
|
136
214
|
}
|
|
137
215
|
}
|
|
138
216
|
/**
|
|
@@ -141,10 +219,14 @@ class VideoGenerationClient {
|
|
|
141
219
|
reset() {
|
|
142
220
|
this.stop();
|
|
143
221
|
this.setResult(null);
|
|
222
|
+
this.input = null;
|
|
223
|
+
this.progress = null;
|
|
224
|
+
this.devtoolsBridge.resetRuns();
|
|
144
225
|
this.setJobId(null);
|
|
145
226
|
this.setVideoStatus(null);
|
|
146
227
|
this.setError(void 0);
|
|
147
228
|
this.setStatus("idle");
|
|
229
|
+
this.devtoolsBridge.emitState();
|
|
148
230
|
}
|
|
149
231
|
/**
|
|
150
232
|
* Update options without recreating the client.
|
|
@@ -172,6 +254,11 @@ class VideoGenerationClient {
|
|
|
172
254
|
this.callbacksRef.onStatusUpdate = options.onStatusUpdate;
|
|
173
255
|
}
|
|
174
256
|
}
|
|
257
|
+
dispose() {
|
|
258
|
+
this.stop();
|
|
259
|
+
this.devtoolsBridge.dispose();
|
|
260
|
+
this.devtoolsMounted = false;
|
|
261
|
+
}
|
|
175
262
|
// ===========================
|
|
176
263
|
// Getters
|
|
177
264
|
// ===========================
|
|
@@ -200,41 +287,93 @@ class VideoGenerationClient {
|
|
|
200
287
|
if (rawResult === null) {
|
|
201
288
|
this.result = null;
|
|
202
289
|
this.callbacksRef.onResultChange?.(null);
|
|
290
|
+
this.devtoolsBridge.recordResultChange();
|
|
203
291
|
return;
|
|
204
292
|
}
|
|
293
|
+
const completedStatus = this.createCompletedVideoStatus(rawResult);
|
|
294
|
+
if (this.progress?.value !== 100) {
|
|
295
|
+
this.setProgress(100, this.progress?.message);
|
|
296
|
+
}
|
|
297
|
+
this.setJobId(rawResult.jobId);
|
|
298
|
+
this.setVideoStatus(completedStatus);
|
|
205
299
|
if (this.callbacksRef.onResult) {
|
|
206
300
|
const transformed = this.callbacksRef.onResult(rawResult);
|
|
207
301
|
if (transformed === null) {
|
|
302
|
+
this.devtoolsBridge.emitState();
|
|
208
303
|
return;
|
|
209
304
|
}
|
|
210
305
|
if (transformed !== void 0) {
|
|
211
306
|
this.result = transformed;
|
|
212
307
|
this.callbacksRef.onResultChange?.(this.result);
|
|
308
|
+
this.devtoolsBridge.recordResultChange();
|
|
213
309
|
return;
|
|
214
310
|
}
|
|
215
311
|
}
|
|
216
312
|
this.result = rawResult;
|
|
217
313
|
this.callbacksRef.onResultChange?.(this.result);
|
|
314
|
+
this.devtoolsBridge.recordResultChange();
|
|
218
315
|
}
|
|
219
316
|
setJobId(jobId) {
|
|
220
317
|
this.jobId = jobId;
|
|
221
318
|
this.callbacksRef.onJobIdChange?.(jobId);
|
|
319
|
+
this.devtoolsBridge.recordJobIdChange();
|
|
222
320
|
}
|
|
223
321
|
setVideoStatus(status) {
|
|
224
322
|
this.videoStatus = status;
|
|
225
323
|
this.callbacksRef.onVideoStatusChange?.(status);
|
|
324
|
+
this.devtoolsBridge.recordVideoStatusChange();
|
|
226
325
|
}
|
|
227
326
|
setIsLoading(isLoading) {
|
|
228
327
|
this.isLoading = isLoading;
|
|
229
328
|
this.callbacksRef.onLoadingChange?.(isLoading);
|
|
329
|
+
this.devtoolsBridge.recordLoadingChange();
|
|
230
330
|
}
|
|
231
331
|
setError(error) {
|
|
232
332
|
this.error = error;
|
|
233
333
|
this.callbacksRef.onErrorChange?.(error);
|
|
334
|
+
this.devtoolsBridge.recordErrorChange(error);
|
|
234
335
|
}
|
|
235
336
|
setStatus(status) {
|
|
236
337
|
this.status = status;
|
|
237
338
|
this.callbacksRef.onStatusChange?.(status);
|
|
339
|
+
this.devtoolsBridge.recordStatusChange(status);
|
|
340
|
+
}
|
|
341
|
+
setProgress(value, message) {
|
|
342
|
+
this.progress = {
|
|
343
|
+
value,
|
|
344
|
+
...message ? { message } : {}
|
|
345
|
+
};
|
|
346
|
+
if (message === void 0) {
|
|
347
|
+
this.callbacksRef.onProgress?.(value);
|
|
348
|
+
} else {
|
|
349
|
+
this.callbacksRef.onProgress?.(value, message);
|
|
350
|
+
}
|
|
351
|
+
this.devtoolsBridge.recordProgressChange();
|
|
352
|
+
}
|
|
353
|
+
createCompletedVideoStatus(result) {
|
|
354
|
+
return {
|
|
355
|
+
jobId: result.jobId,
|
|
356
|
+
status: result.status,
|
|
357
|
+
progress: 100,
|
|
358
|
+
url: result.url
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
createDevtoolsMetadata(metadata) {
|
|
362
|
+
return {
|
|
363
|
+
hookName: metadata?.hookName ?? "useGenerateVideo",
|
|
364
|
+
outputKind: metadata?.outputKind ?? "video",
|
|
365
|
+
...metadata?.framework ? { framework: metadata.framework } : {},
|
|
366
|
+
...metadata?.name ? { name: metadata.name } : {}
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
generateUniqueId(prefix) {
|
|
370
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
371
|
+
}
|
|
372
|
+
createRunContext(runId) {
|
|
373
|
+
return {
|
|
374
|
+
threadId: this.threadId,
|
|
375
|
+
runId
|
|
376
|
+
};
|
|
238
377
|
}
|
|
239
378
|
}
|
|
240
379
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video-generation-client.js","sources":["../../src/video-generation-client.ts"],"sourcesContent":["import { GENERATION_EVENTS } from './generation-types'\nimport { parseSSEResponse } from './sse-parser'\nimport type { StreamChunk } from '@tanstack/ai'\nimport type { ConnectConnectionAdapter } from './connection-adapters'\nimport type {\n GenerationClientState,\n GenerationFetcher,\n VideoGenerateInput,\n VideoGenerateResult,\n VideoGenerationClientOptions,\n VideoStatusInfo,\n} from './generation-types'\n\n/**\n * Callbacks stored in a ref so hooks can update them without recreating the client.\n */\n// All optional fields explicitly allow `| undefined` so callers can spread\n// option bags (where each callback may be `undefined`) into the callbacks\n// ref under `exactOptionalPropertyTypes`.\ninterface VideoCallbacks<TOutput> {\n onResult?:\n | ((result: VideoGenerateResult) => TOutput | null | void)\n | undefined\n onError?: ((error: Error) => void) | undefined\n onProgress?: ((progress: number, message?: string) => void) | undefined\n onChunk?: ((chunk: StreamChunk) => void) | undefined\n onJobCreated?: ((jobId: string) => void) | undefined\n onStatusUpdate?: ((status: VideoStatusInfo) => void) | undefined\n onResultChange?: ((result: TOutput | null) => void) | undefined\n onLoadingChange?: ((isLoading: boolean) => void) | undefined\n onErrorChange?: ((error: Error | undefined) => void) | undefined\n onStatusChange?: ((status: GenerationClientState) => void) | undefined\n onJobIdChange?: ((jobId: string | null) => void) | undefined\n onVideoStatusChange?: ((status: VideoStatusInfo | null) => void) | undefined\n}\n\n/**\n * A specialized client for job-based video generation.\n *\n * Video generation is asynchronous: a job is created, then polled for status\n * until completion. This client handles the full lifecycle.\n *\n * Supports two transport modes:\n * - **ConnectConnectionAdapter** — Server handles the polling loop internally and\n * streams status updates via CUSTOM events.\n * - **Fetcher** — Direct async function that returns a completed\n * `VideoGenerateResult`.\n *\n * @example\n * ```typescript\n * // With streaming connection adapter (server-driven polling)\n * const client = new VideoGenerationClient({\n * connection: fetchServerSentEvents('/api/generate/video'),\n * onResultChange: setResult,\n * onVideoStatusChange: setVideoStatus,\n * })\n *\n * // With fetcher (direct result)\n * const client = new VideoGenerationClient({\n * fetcher: async (input) => {\n * const res = await fetch('/api/video/generate', {\n * method: 'POST',\n * body: JSON.stringify(input),\n * })\n * return res.json() // { jobId, status: 'completed', url, expiresAt }\n * },\n * })\n *\n * await client.generate({ prompt: 'A flying car over a city' })\n * ```\n */\nexport class VideoGenerationClient<TOutput = VideoGenerateResult> {\n private readonly connection: ConnectConnectionAdapter | undefined\n private readonly fetcher:\n | GenerationFetcher<VideoGenerateInput, VideoGenerateResult>\n | undefined\n private body: Record<string, any>\n\n private result: TOutput | null = null\n private jobId: string | null = null\n private videoStatus: VideoStatusInfo | null = null\n private isLoading = false\n private error: Error | undefined = undefined\n private status: GenerationClientState = 'idle'\n private abortController: AbortController | null = null\n private readonly callbacksRef: VideoCallbacks<TOutput>\n\n constructor(\n options: VideoGenerationClientOptions<TOutput> &\n (\n | { connection: ConnectConnectionAdapter; fetcher?: never }\n | {\n fetcher: GenerationFetcher<VideoGenerateInput, VideoGenerateResult>\n connection?: never\n }\n ),\n ) {\n this.connection = options.connection\n this.fetcher = options.fetcher\n this.body = options.body ?? {}\n\n this.callbacksRef = {\n onResult: options.onResult,\n onError: options.onError,\n onProgress: options.onProgress,\n onChunk: options.onChunk,\n onJobCreated: options.onJobCreated,\n onStatusUpdate: options.onStatusUpdate,\n onResultChange: options.onResultChange,\n onLoadingChange: options.onLoadingChange,\n onErrorChange: options.onErrorChange,\n onStatusChange: options.onStatusChange,\n onJobIdChange: options.onJobIdChange,\n onVideoStatusChange: options.onVideoStatusChange,\n }\n }\n\n /**\n * Trigger video generation.\n * Only one generation can be in-flight at a time.\n */\n async generate(input: VideoGenerateInput): Promise<void> {\n if (this.isLoading) return\n\n this.setIsLoading(true)\n this.setStatus('generating')\n this.setError(undefined)\n this.setJobId(null)\n this.setVideoStatus(null)\n\n const abortController = new AbortController()\n this.abortController = abortController\n const { signal } = abortController\n\n try {\n if (this.fetcher) {\n await this.generateWithFetcher(input, signal)\n } else if (this.connection) {\n const mergedData = { ...this.body, ...input }\n const stream = this.connection.connect([], mergedData, signal)\n await this.processStream(stream)\n } else {\n throw new Error(\n 'VideoGenerationClient requires either a connection or fetcher option',\n )\n }\n } catch (err: any) {\n if (signal.aborted) return\n const error = err instanceof Error ? err : new Error(String(err))\n this.setError(error)\n this.setStatus('error')\n this.callbacksRef.onError?.(error)\n } finally {\n this.abortController = null\n this.setIsLoading(false)\n }\n }\n\n /**\n * Direct fetcher mode: call fetcher and set result.\n */\n private async generateWithFetcher(\n input: VideoGenerateInput,\n signal: AbortSignal,\n ): Promise<void> {\n if (!this.fetcher) return\n\n // Fetcher returns a completed result directly, or a Response with SSE body\n const result = await this.fetcher(input, { signal })\n if (signal.aborted) return\n\n if (result instanceof Response) {\n // Server function returned SSE Response — parse stream\n await this.processStream(parseSSEResponse(result, signal))\n } else {\n this.setResult(result)\n this.setStatus('success')\n }\n }\n\n /**\n * Process a stream of AG-UI events from the streaming connection adapter.\n * The server handles the polling loop and streams status updates.\n */\n private async processStream(\n source: AsyncIterable<StreamChunk>,\n ): Promise<void> {\n for await (const chunk of source) {\n if (this.abortController?.signal.aborted) break\n\n this.callbacksRef.onChunk?.(chunk)\n\n // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- AG-UI EventType has ~22 variants; this consumer only handles the subset relevant to video generation lifecycle.\n switch (chunk.type) {\n case 'CUSTOM': {\n if (chunk.name === GENERATION_EVENTS.VIDEO_JOB_CREATED) {\n const { jobId } = chunk.value as { jobId: string }\n this.setJobId(jobId)\n this.callbacksRef.onJobCreated?.(jobId)\n } else if (chunk.name === GENERATION_EVENTS.VIDEO_STATUS) {\n const statusInfo = chunk.value as VideoStatusInfo\n this.setVideoStatus(statusInfo)\n this.callbacksRef.onStatusUpdate?.(statusInfo)\n if (statusInfo.progress !== undefined) {\n this.callbacksRef.onProgress?.(statusInfo.progress)\n }\n } else if (chunk.name === GENERATION_EVENTS.RESULT) {\n this.setResult(chunk.value as VideoGenerateResult)\n } else if (chunk.name === GENERATION_EVENTS.PROGRESS) {\n const { progress, message } = chunk.value as {\n progress: number\n message?: string\n }\n this.callbacksRef.onProgress?.(progress, message)\n }\n break\n }\n case 'RUN_FINISHED': {\n this.setStatus('success')\n break\n }\n case 'RUN_ERROR': {\n // Prefer spec `message`; fall back to deprecated `error.message`\n const msg =\n (chunk.message as string | undefined) ||\n chunk.error?.message ||\n 'An error occurred'\n throw new Error(msg)\n }\n default:\n break\n }\n }\n }\n\n /**\n * Abort any in-flight generation or polling.\n */\n stop(): void {\n if (this.abortController) {\n this.abortController.abort()\n this.abortController = null\n }\n this.setIsLoading(false)\n if (this.status === 'generating') {\n this.setStatus('idle')\n }\n }\n\n /**\n * Clear all state and return to idle.\n */\n reset(): void {\n this.stop()\n this.setResult(null)\n this.setJobId(null)\n this.setVideoStatus(null)\n this.setError(undefined)\n this.setStatus('idle')\n }\n\n /**\n * Update options without recreating the client.\n */\n updateOptions(\n options: Partial<\n Pick<\n VideoGenerationClientOptions<TOutput>,\n | 'body'\n | 'onResult'\n | 'onError'\n | 'onProgress'\n | 'onChunk'\n | 'onJobCreated'\n | 'onStatusUpdate'\n >\n >,\n ): void {\n if (options.body !== undefined) {\n this.body = options.body ?? {}\n }\n if (options.onResult !== undefined) {\n this.callbacksRef.onResult = options.onResult\n }\n if (options.onError !== undefined) {\n this.callbacksRef.onError = options.onError\n }\n if (options.onProgress !== undefined) {\n this.callbacksRef.onProgress = options.onProgress\n }\n if (options.onChunk !== undefined) {\n this.callbacksRef.onChunk = options.onChunk\n }\n if (options.onJobCreated !== undefined) {\n this.callbacksRef.onJobCreated = options.onJobCreated\n }\n if (options.onStatusUpdate !== undefined) {\n this.callbacksRef.onStatusUpdate = options.onStatusUpdate\n }\n }\n\n // ===========================\n // Getters\n // ===========================\n\n getResult(): TOutput | null {\n return this.result\n }\n\n getJobId(): string | null {\n return this.jobId\n }\n\n getVideoStatus(): VideoStatusInfo | null {\n return this.videoStatus\n }\n\n getIsLoading(): boolean {\n return this.isLoading\n }\n\n getError(): Error | undefined {\n return this.error\n }\n\n getStatus(): GenerationClientState {\n return this.status\n }\n\n // ===========================\n // Private state setters\n // ===========================\n\n private setResult(rawResult: VideoGenerateResult | null): void {\n if (rawResult === null) {\n this.result = null\n this.callbacksRef.onResultChange?.(null)\n return\n }\n\n if (this.callbacksRef.onResult) {\n const transformed = this.callbacksRef.onResult(rawResult)\n if (transformed === null) {\n // null return → keep previous result unchanged\n return\n }\n if (transformed !== undefined) {\n // Non-null, non-undefined → use transformed value\n this.result = transformed\n this.callbacksRef.onResultChange?.(this.result)\n return\n }\n }\n\n // No onResult callback, or callback returned void → use raw value\n this.result = rawResult as TOutput\n this.callbacksRef.onResultChange?.(this.result)\n }\n\n private setJobId(jobId: string | null): void {\n this.jobId = jobId\n this.callbacksRef.onJobIdChange?.(jobId)\n }\n\n private setVideoStatus(status: VideoStatusInfo | null): void {\n this.videoStatus = status\n this.callbacksRef.onVideoStatusChange?.(status)\n }\n\n private setIsLoading(isLoading: boolean): void {\n this.isLoading = isLoading\n this.callbacksRef.onLoadingChange?.(isLoading)\n }\n\n private setError(error: Error | undefined): void {\n this.error = error\n this.callbacksRef.onErrorChange?.(error)\n }\n\n private setStatus(status: GenerationClientState): void {\n this.status = status\n this.callbacksRef.onStatusChange?.(status)\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"video-generation-client.js","sources":["../../src/video-generation-client.ts"],"sourcesContent":["import { GENERATION_EVENTS } from './generation-types'\nimport { createNoOpVideoDevtoolsBridge } from './devtools-noop'\nimport { parseSSEResponse } from './sse-parser'\nimport type { StreamChunk } from '@tanstack/ai/client'\nimport type {\n ConnectConnectionAdapter,\n RunAgentInputContext,\n} from './connection-adapters'\nimport type {\n AIDevtoolsClientMetadata,\n AIDevtoolsGenerationProgress,\n VideoDevtoolsBridge,\n VideoDevtoolsBridgeOptions,\n} from './devtools'\nimport type {\n GenerationClientState,\n GenerationFetcher,\n VideoGenerateInput,\n VideoGenerateResult,\n VideoGenerationClientOptions,\n VideoStatusInfo,\n} from './generation-types'\n\n/**\n * Callbacks stored in a ref so hooks can update them without recreating the client.\n */\n// All optional fields explicitly allow `| undefined` so callers can spread\n// option bags (where each callback may be `undefined`) into the callbacks\n// ref under `exactOptionalPropertyTypes`.\ninterface VideoCallbacks<TOutput> {\n onResult?:\n | ((result: VideoGenerateResult) => TOutput | null | void)\n | undefined\n onError?: ((error: Error) => void) | undefined\n onProgress?: ((progress: number, message?: string) => void) | undefined\n onChunk?: ((chunk: StreamChunk) => void) | undefined\n onJobCreated?: ((jobId: string) => void) | undefined\n onStatusUpdate?: ((status: VideoStatusInfo) => void) | undefined\n onResultChange?: ((result: TOutput | null) => void) | undefined\n onLoadingChange?: ((isLoading: boolean) => void) | undefined\n onErrorChange?: ((error: Error | undefined) => void) | undefined\n onStatusChange?: ((status: GenerationClientState) => void) | undefined\n onJobIdChange?: ((jobId: string | null) => void) | undefined\n onVideoStatusChange?: ((status: VideoStatusInfo | null) => void) | undefined\n}\n\n/**\n * A specialized client for job-based video generation.\n *\n * Video generation is asynchronous: a job is created, then polled for status\n * until completion. This client handles the full lifecycle.\n *\n * Supports two transport modes:\n * - **ConnectConnectionAdapter** — Server handles the polling loop internally and\n * streams status updates via CUSTOM events.\n * - **Fetcher** — Direct async function that returns a completed\n * `VideoGenerateResult`.\n *\n * @example\n * ```typescript\n * // With streaming connection adapter (server-driven polling)\n * const client = new VideoGenerationClient({\n * connection: fetchServerSentEvents('/api/generate/video'),\n * onResultChange: setResult,\n * onVideoStatusChange: setVideoStatus,\n * })\n *\n * // With fetcher (direct result)\n * const client = new VideoGenerationClient({\n * fetcher: async (input) => {\n * const res = await fetch('/api/video/generate', {\n * method: 'POST',\n * body: JSON.stringify(input),\n * })\n * return res.json() // { jobId, status: 'completed', url, expiresAt }\n * },\n * })\n *\n * await client.generate({ prompt: 'A flying car over a city' })\n * ```\n */\nexport class VideoGenerationClient<TOutput = VideoGenerateResult> {\n private readonly connection: ConnectConnectionAdapter | undefined\n private readonly fetcher:\n | GenerationFetcher<VideoGenerateInput, VideoGenerateResult>\n | undefined\n private readonly uniqueId: string\n private readonly devtoolsMetadata: AIDevtoolsClientMetadata\n private readonly devtoolsBridge: VideoDevtoolsBridge<TOutput>\n private readonly threadId: string\n private body: Record<string, any>\n\n private result: TOutput | null = null\n private input: VideoGenerateInput | null = null\n private progress: AIDevtoolsGenerationProgress | null = null\n private jobId: string | null = null\n private videoStatus: VideoStatusInfo | null = null\n private isLoading = false\n private error: Error | undefined = undefined\n private status: GenerationClientState = 'idle'\n private abortController: AbortController | null = null\n private readonly callbacksRef: VideoCallbacks<TOutput>\n private devtoolsMounted = false\n\n constructor(\n options: VideoGenerationClientOptions<TOutput> &\n (\n | { connection: ConnectConnectionAdapter; fetcher?: never }\n | {\n fetcher: GenerationFetcher<VideoGenerateInput, VideoGenerateResult>\n connection?: never\n }\n ),\n ) {\n this.uniqueId = options.id ?? this.generateUniqueId('video')\n this.threadId = this.uniqueId\n this.connection = options.connection\n this.fetcher = options.fetcher\n this.body = options.body ?? {}\n\n this.callbacksRef = {\n onResult: options.onResult,\n onError: options.onError,\n onProgress: options.onProgress,\n onChunk: options.onChunk,\n onJobCreated: options.onJobCreated,\n onStatusUpdate: options.onStatusUpdate,\n onResultChange: options.onResultChange,\n onLoadingChange: options.onLoadingChange,\n onErrorChange: options.onErrorChange,\n onStatusChange: options.onStatusChange,\n onJobIdChange: options.onJobIdChange,\n onVideoStatusChange: options.onVideoStatusChange,\n }\n\n this.devtoolsMetadata = this.createDevtoolsMetadata(options.devtools)\n this.devtoolsBridge = (\n options.devtoolsBridgeFactory ?? createNoOpVideoDevtoolsBridge\n )<TOutput>(this.buildDevtoolsBridgeOptions())\n }\n\n private buildDevtoolsBridgeOptions(): VideoDevtoolsBridgeOptions<TOutput> {\n return {\n hookId: this.uniqueId,\n clientId: this.uniqueId,\n threadId: this.threadId,\n metadata: this.devtoolsMetadata,\n getCoreState: () => ({\n input: this.input,\n result: this.result,\n progress: this.progress,\n status: this.status,\n isLoading: this.isLoading,\n jobId: this.jobId,\n videoStatus: this.videoStatus,\n ...(this.error ? { error: this.error.message } : {}),\n }),\n }\n }\n\n mountDevtools(): void {\n if (this.devtoolsMounted) {\n return\n }\n\n this.devtoolsMounted = true\n this.devtoolsBridge.emitRegistered()\n this.devtoolsBridge.emitSnapshot()\n }\n\n /**\n * Trigger video generation.\n * Only one generation can be in-flight at a time.\n */\n async generate(input: VideoGenerateInput): Promise<void> {\n this.mountDevtools()\n if (this.isLoading) return\n\n this.input = input\n this.progress = null\n const runId = this.devtoolsBridge.beginRun(input)\n this.setIsLoading(true)\n this.setStatus('generating')\n this.setError(undefined)\n this.setJobId(null)\n this.setVideoStatus(null)\n\n const abortController = new AbortController()\n this.abortController = abortController\n const { signal } = abortController\n\n try {\n if (this.fetcher) {\n await this.generateWithFetcher(input, signal, runId)\n } else if (this.connection) {\n const mergedData = { ...this.body, ...input }\n const stream = this.connection.connect(\n [],\n mergedData,\n signal,\n this.createRunContext(runId),\n )\n await this.processStream(stream, runId)\n } else {\n throw new Error(\n 'VideoGenerationClient requires either a connection or fetcher option',\n )\n }\n if (!signal.aborted && this.status === 'success') {\n this.devtoolsBridge.finishRun(\n this.devtoolsBridge.getActiveRunId() ?? runId,\n 'run:completed',\n 'completed',\n )\n }\n } catch (err: unknown) {\n if (signal.aborted) return\n const error = err instanceof Error ? err : new Error(String(err))\n this.setError(error)\n this.setStatus('error')\n this.devtoolsBridge.finishRun(\n this.devtoolsBridge.getActiveRunId() ?? runId,\n 'run:errored',\n 'errored',\n error.message,\n )\n this.callbacksRef.onError?.(error)\n } finally {\n this.abortController = null\n this.setIsLoading(false)\n }\n }\n\n /**\n * Direct fetcher mode: call fetcher and set result.\n */\n private async generateWithFetcher(\n input: VideoGenerateInput,\n signal: AbortSignal,\n runId: string,\n ): Promise<void> {\n if (!this.fetcher) return\n\n // Fetcher returns a completed result directly, or a Response with SSE body\n const result = await this.fetcher(input, { signal })\n if (signal.aborted) return\n\n if (result instanceof Response) {\n // Server function returned SSE Response — parse stream\n await this.processStream(parseSSEResponse(result, signal), runId)\n } else {\n this.devtoolsBridge.ensureRunStarted(runId)\n this.setResult(result)\n this.setStatus('success')\n }\n }\n\n /**\n * Process a stream of AG-UI events from the streaming connection adapter.\n * The server handles the polling loop and streams status updates.\n */\n private async processStream(\n source: AsyncIterable<StreamChunk>,\n fallbackRunId: string,\n ): Promise<void> {\n let streamRunId: string | undefined\n\n for await (const chunk of source) {\n if (this.abortController?.signal.aborted) break\n\n this.callbacksRef.onChunk?.(chunk)\n const chunkRunId =\n 'runId' in chunk && typeof chunk.runId === 'string'\n ? chunk.runId\n : undefined\n\n // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- AG-UI EventType has ~22 variants; this consumer only handles the subset relevant to video generation lifecycle.\n switch (chunk.type) {\n case 'RUN_STARTED': {\n streamRunId = chunk.runId\n this.devtoolsBridge.ensureRunStarted(chunk.runId)\n break\n }\n case 'CUSTOM': {\n this.devtoolsBridge.ensureRunStarted(streamRunId ?? fallbackRunId)\n if (chunk.name === GENERATION_EVENTS.VIDEO_JOB_CREATED) {\n const { jobId } = chunk.value as { jobId: string }\n this.setJobId(jobId)\n this.callbacksRef.onJobCreated?.(jobId)\n } else if (chunk.name === GENERATION_EVENTS.VIDEO_STATUS) {\n const statusInfo = chunk.value as VideoStatusInfo\n this.setVideoStatus(statusInfo)\n this.callbacksRef.onStatusUpdate?.(statusInfo)\n if (statusInfo.progress !== undefined) {\n this.setProgress(statusInfo.progress)\n }\n } else if (chunk.name === GENERATION_EVENTS.RESULT) {\n this.setResult(chunk.value as VideoGenerateResult)\n } else if (chunk.name === GENERATION_EVENTS.PROGRESS) {\n const { progress, message } = chunk.value as {\n progress: number\n message?: string\n }\n this.setProgress(progress, message)\n }\n break\n }\n case 'RUN_FINISHED': {\n streamRunId = chunk.runId\n this.devtoolsBridge.ensureRunStarted(chunk.runId)\n this.setStatus('success')\n break\n }\n case 'RUN_ERROR': {\n this.devtoolsBridge.ensureRunStarted(\n chunkRunId ?? streamRunId ?? fallbackRunId,\n )\n // Prefer spec `message`; fall back to deprecated `error.message`\n const msg =\n (chunk.message as string | undefined) ||\n chunk.error?.message ||\n 'An error occurred'\n throw new Error(msg)\n }\n default:\n break\n }\n }\n }\n\n /**\n * Abort any in-flight generation or polling.\n */\n stop(): void {\n const runId = this.devtoolsBridge.getActiveRunId()\n if (this.abortController) {\n this.abortController.abort()\n this.abortController = null\n }\n this.setIsLoading(false)\n if (this.status === 'generating') {\n this.setStatus('idle')\n if (runId) {\n this.devtoolsBridge.finishRun(runId, 'run:cancelled', 'cancelled')\n }\n }\n }\n\n /**\n * Clear all state and return to idle.\n */\n reset(): void {\n this.stop()\n this.setResult(null)\n this.input = null\n this.progress = null\n this.devtoolsBridge.resetRuns()\n this.setJobId(null)\n this.setVideoStatus(null)\n this.setError(undefined)\n this.setStatus('idle')\n this.devtoolsBridge.emitState()\n }\n\n /**\n * Update options without recreating the client.\n */\n updateOptions(\n options: Partial<\n Pick<\n VideoGenerationClientOptions<TOutput>,\n | 'body'\n | 'onResult'\n | 'onError'\n | 'onProgress'\n | 'onChunk'\n | 'onJobCreated'\n | 'onStatusUpdate'\n >\n >,\n ): void {\n if (options.body !== undefined) {\n this.body = options.body ?? {}\n }\n if (options.onResult !== undefined) {\n this.callbacksRef.onResult = options.onResult\n }\n if (options.onError !== undefined) {\n this.callbacksRef.onError = options.onError\n }\n if (options.onProgress !== undefined) {\n this.callbacksRef.onProgress = options.onProgress\n }\n if (options.onChunk !== undefined) {\n this.callbacksRef.onChunk = options.onChunk\n }\n if (options.onJobCreated !== undefined) {\n this.callbacksRef.onJobCreated = options.onJobCreated\n }\n if (options.onStatusUpdate !== undefined) {\n this.callbacksRef.onStatusUpdate = options.onStatusUpdate\n }\n }\n\n dispose(): void {\n this.stop()\n this.devtoolsBridge.dispose()\n this.devtoolsMounted = false\n }\n\n // ===========================\n // Getters\n // ===========================\n\n getResult(): TOutput | null {\n return this.result\n }\n\n getJobId(): string | null {\n return this.jobId\n }\n\n getVideoStatus(): VideoStatusInfo | null {\n return this.videoStatus\n }\n\n getIsLoading(): boolean {\n return this.isLoading\n }\n\n getError(): Error | undefined {\n return this.error\n }\n\n getStatus(): GenerationClientState {\n return this.status\n }\n\n // ===========================\n // Private state setters\n // ===========================\n\n private setResult(rawResult: VideoGenerateResult | null): void {\n if (rawResult === null) {\n this.result = null\n this.callbacksRef.onResultChange?.(null)\n this.devtoolsBridge.recordResultChange()\n return\n }\n\n const completedStatus = this.createCompletedVideoStatus(rawResult)\n if (this.progress?.value !== 100) {\n this.setProgress(100, this.progress?.message)\n }\n this.setJobId(rawResult.jobId)\n this.setVideoStatus(completedStatus)\n\n if (this.callbacksRef.onResult) {\n const transformed = this.callbacksRef.onResult(rawResult)\n if (transformed === null) {\n // null return → keep previous result unchanged, just re-emit\n this.devtoolsBridge.emitState()\n return\n }\n if (transformed !== undefined) {\n // Non-null, non-undefined → use transformed value\n this.result = transformed\n this.callbacksRef.onResultChange?.(this.result)\n this.devtoolsBridge.recordResultChange()\n return\n }\n }\n\n // No onResult callback, or callback returned void → use raw value as\n // TOutput. When the caller did not supply an onResult transform,\n // `TOutput` defaults to `VideoGenerateResult`, so the runtime cast is\n // sound.\n // eslint-disable-next-line no-restricted-syntax -- TOutput defaults to VideoGenerateResult when no onResult transform is supplied\n this.result = rawResult as unknown as TOutput\n this.callbacksRef.onResultChange?.(this.result)\n this.devtoolsBridge.recordResultChange()\n }\n\n private setJobId(jobId: string | null): void {\n this.jobId = jobId\n this.callbacksRef.onJobIdChange?.(jobId)\n this.devtoolsBridge.recordJobIdChange()\n }\n\n private setVideoStatus(status: VideoStatusInfo | null): void {\n this.videoStatus = status\n this.callbacksRef.onVideoStatusChange?.(status)\n this.devtoolsBridge.recordVideoStatusChange()\n }\n\n private setIsLoading(isLoading: boolean): void {\n this.isLoading = isLoading\n this.callbacksRef.onLoadingChange?.(isLoading)\n this.devtoolsBridge.recordLoadingChange()\n }\n\n private setError(error: Error | undefined): void {\n this.error = error\n this.callbacksRef.onErrorChange?.(error)\n this.devtoolsBridge.recordErrorChange(error)\n }\n\n private setStatus(status: GenerationClientState): void {\n this.status = status\n this.callbacksRef.onStatusChange?.(status)\n this.devtoolsBridge.recordStatusChange(status)\n }\n\n private setProgress(value: number, message?: string): void {\n this.progress = {\n value,\n ...(message ? { message } : {}),\n }\n if (message === undefined) {\n this.callbacksRef.onProgress?.(value)\n } else {\n this.callbacksRef.onProgress?.(value, message)\n }\n this.devtoolsBridge.recordProgressChange()\n }\n\n private createCompletedVideoStatus(\n result: VideoGenerateResult,\n ): VideoStatusInfo {\n return {\n jobId: result.jobId,\n status: result.status,\n progress: 100,\n url: result.url,\n }\n }\n\n private createDevtoolsMetadata(\n metadata?: Partial<AIDevtoolsClientMetadata>,\n ): AIDevtoolsClientMetadata {\n return {\n hookName: metadata?.hookName ?? 'useGenerateVideo',\n outputKind: metadata?.outputKind ?? 'video',\n ...(metadata?.framework ? { framework: metadata.framework } : {}),\n ...(metadata?.name ? { name: metadata.name } : {}),\n }\n }\n\n private generateUniqueId(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(7)}`\n }\n\n private createRunContext(runId: string): RunAgentInputContext {\n return {\n threadId: this.threadId,\n runId,\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Framework-agnostic headless client for TanStack AI chat, realtime sessions, streaming transports, and media generations.",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
".": {
|
|
31
31
|
"types": "./dist/esm/index.d.ts",
|
|
32
32
|
"import": "./dist/esm/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./devtools": {
|
|
35
|
+
"types": "./dist/esm/devtools.d.ts",
|
|
36
|
+
"import": "./dist/esm/devtools.js"
|
|
33
37
|
}
|
|
34
38
|
},
|
|
35
39
|
"files": [
|
|
@@ -37,8 +41,8 @@
|
|
|
37
41
|
"src"
|
|
38
42
|
],
|
|
39
43
|
"dependencies": {
|
|
40
|
-
"@tanstack/ai": "0.
|
|
41
|
-
"@tanstack/ai-event-client": "0.
|
|
44
|
+
"@tanstack/ai": "0.23.0",
|
|
45
|
+
"@tanstack/ai-event-client": "0.4.1"
|
|
42
46
|
},
|
|
43
47
|
"devDependencies": {
|
|
44
48
|
"@standard-schema/spec": "^1.1.0",
|