@tanstack/ai-client 0.18.4 → 0.18.5

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.
Files changed (48) hide show
  1. package/package.json +3 -3
  2. package/dist/esm/chat-client.d.ts +0 -264
  3. package/dist/esm/chat-client.js +0 -1097
  4. package/dist/esm/chat-client.js.map +0 -1
  5. package/dist/esm/client-persistor.d.ts +0 -86
  6. package/dist/esm/client-persistor.js +0 -243
  7. package/dist/esm/client-persistor.js.map +0 -1
  8. package/dist/esm/connection-adapters.d.ts +0 -203
  9. package/dist/esm/connection-adapters.js +0 -611
  10. package/dist/esm/connection-adapters.js.map +0 -1
  11. package/dist/esm/devtools-noop.d.ts +0 -63
  12. package/dist/esm/devtools-noop.js +0 -141
  13. package/dist/esm/devtools-noop.js.map +0 -1
  14. package/dist/esm/devtools.d.ts +0 -276
  15. package/dist/esm/devtools.js +0 -1178
  16. package/dist/esm/devtools.js.map +0 -1
  17. package/dist/esm/events.d.ts +0 -129
  18. package/dist/esm/events.js +0 -227
  19. package/dist/esm/events.js.map +0 -1
  20. package/dist/esm/generation-client.d.ts +0 -99
  21. package/dist/esm/generation-client.js +0 -325
  22. package/dist/esm/generation-client.js.map +0 -1
  23. package/dist/esm/generation-types.d.ts +0 -242
  24. package/dist/esm/generation-types.js +0 -14
  25. package/dist/esm/generation-types.js.map +0 -1
  26. package/dist/esm/index.d.ts +0 -16
  27. package/dist/esm/index.js +0 -44
  28. package/dist/esm/index.js.map +0 -1
  29. package/dist/esm/realtime-client.d.ts +0 -98
  30. package/dist/esm/realtime-client.js +0 -403
  31. package/dist/esm/realtime-client.js.map +0 -1
  32. package/dist/esm/realtime-types.d.ts +0 -78
  33. package/dist/esm/response-stream.d.ts +0 -7
  34. package/dist/esm/response-stream.js +0 -32
  35. package/dist/esm/response-stream.js.map +0 -1
  36. package/dist/esm/sse-parser.d.ts +0 -8
  37. package/dist/esm/sse-parser.js +0 -52
  38. package/dist/esm/sse-parser.js.map +0 -1
  39. package/dist/esm/sse-utils.d.ts +0 -1
  40. package/dist/esm/sse-utils.js +0 -11
  41. package/dist/esm/sse-utils.js.map +0 -1
  42. package/dist/esm/tool-types.d.ts +0 -20
  43. package/dist/esm/types.d.ts +0 -419
  44. package/dist/esm/types.js +0 -11
  45. package/dist/esm/types.js.map +0 -1
  46. package/dist/esm/video-generation-client.d.ts +0 -110
  47. package/dist/esm/video-generation-client.js +0 -382
  48. package/dist/esm/video-generation-client.js.map +0 -1
@@ -1,99 +0,0 @@
1
- import { ConnectConnectionAdapter } from './connection-adapters.js';
2
- import { GenerationClientOptions, GenerationClientState, GenerationFetcher } from './generation-types.js';
3
- /**
4
- * A lightweight, generic client for one-shot generation tasks
5
- * (image, speech, transcription, summarize).
6
- *
7
- * Supports two transport modes:
8
- * - **ConnectConnectionAdapter** — Streaming transport (SSE, HTTP stream, custom).
9
- * Server wraps results in StreamChunk events with CUSTOM event names.
10
- * - **Fetcher** — Direct async function call. No streaming protocol needed.
11
- *
12
- * @template TInput - The input type for the generation request
13
- * @template TResult - The result type returned by the generation
14
- *
15
- * @example
16
- * ```typescript
17
- * // With streaming connection adapter
18
- * const client = new GenerationClient<ImageGenerateInput, ImageGenerationResult>({
19
- * connection: fetchServerSentEvents('/api/generate/image'),
20
- * onResultChange: setResult,
21
- * onLoadingChange: setIsLoading,
22
- * })
23
- *
24
- * // With fetcher (direct)
25
- * const client = new GenerationClient<ImageGenerateInput, ImageGenerationResult>({
26
- * fetcher: async (input) => {
27
- * const res = await fetch('/api/generate/image', {
28
- * method: 'POST',
29
- * body: JSON.stringify(input),
30
- * })
31
- * return res.json()
32
- * },
33
- * })
34
- *
35
- * await client.generate({ prompt: 'A sunset over mountains' })
36
- * ```
37
- */
38
- export declare class GenerationClient<TInput extends Record<string, any>, TResult, TOutput = TResult> {
39
- private readonly connection;
40
- private readonly fetcher;
41
- private readonly uniqueId;
42
- private readonly devtoolsMetadata;
43
- private readonly devtoolsBridge;
44
- private readonly threadId;
45
- private body;
46
- private result;
47
- private input;
48
- private progress;
49
- private isLoading;
50
- private error;
51
- private status;
52
- private abortController;
53
- private readonly callbacksRef;
54
- private devtoolsMounted;
55
- constructor(options: GenerationClientOptions<TInput, TResult, TOutput> & ({
56
- connection: ConnectConnectionAdapter;
57
- fetcher?: never;
58
- } | {
59
- fetcher: GenerationFetcher<TInput, TResult>;
60
- connection?: never;
61
- }));
62
- private buildDevtoolsBridgeOptions;
63
- mountDevtools(): void;
64
- /**
65
- * Trigger a generation request.
66
- * Only one generation can be in-flight at a time; calling generate()
67
- * while already generating will be a no-op.
68
- */
69
- generate(input: TInput): Promise<void>;
70
- /**
71
- * Process a stream of AG-UI events from the streaming connection adapter.
72
- */
73
- private processStream;
74
- /**
75
- * Abort any in-flight generation request.
76
- */
77
- stop(): void;
78
- /**
79
- * Clear the result, error, and return to idle state.
80
- */
81
- reset(): void;
82
- /**
83
- * Update options without recreating the client.
84
- */
85
- updateOptions(options: Partial<Pick<GenerationClientOptions<TInput, TResult, TOutput>, 'body' | 'onResult' | 'onError' | 'onProgress' | 'onChunk'>>): void;
86
- dispose(): void;
87
- getResult(): TOutput | null;
88
- getIsLoading(): boolean;
89
- getError(): Error | undefined;
90
- getStatus(): GenerationClientState;
91
- private setResult;
92
- private setIsLoading;
93
- private setError;
94
- private setStatus;
95
- private setProgress;
96
- private createDevtoolsMetadata;
97
- private generateUniqueId;
98
- private createRunContext;
99
- }
@@ -1,325 +0,0 @@
1
- import { GENERATION_EVENTS } from "./generation-types.js";
2
- import { createNoOpGenerationDevtoolsBridge } from "./devtools-noop.js";
3
- import { parseSSEResponse } from "./sse-parser.js";
4
- class GenerationClient {
5
- connection;
6
- fetcher;
7
- uniqueId;
8
- devtoolsMetadata;
9
- devtoolsBridge;
10
- threadId;
11
- body;
12
- result = null;
13
- input = null;
14
- progress = null;
15
- isLoading = false;
16
- error = void 0;
17
- status = "idle";
18
- abortController = null;
19
- callbacksRef;
20
- devtoolsMounted = false;
21
- constructor(options) {
22
- this.uniqueId = options.id ?? this.generateUniqueId("generation");
23
- this.threadId = this.uniqueId;
24
- this.connection = options.connection;
25
- this.fetcher = options.fetcher;
26
- this.body = options.body ?? {};
27
- this.callbacksRef = {
28
- onResult: options.onResult,
29
- onError: options.onError,
30
- onProgress: options.onProgress,
31
- onChunk: options.onChunk,
32
- onResultChange: options.onResultChange,
33
- onLoadingChange: options.onLoadingChange,
34
- onErrorChange: options.onErrorChange,
35
- onStatusChange: options.onStatusChange
36
- };
37
- this.devtoolsMetadata = this.createDevtoolsMetadata(options.devtools);
38
- this.devtoolsBridge = (options.devtoolsBridgeFactory ?? createNoOpGenerationDevtoolsBridge)(this.buildDevtoolsBridgeOptions());
39
- }
40
- buildDevtoolsBridgeOptions() {
41
- return {
42
- hookId: this.uniqueId,
43
- clientId: this.uniqueId,
44
- threadId: this.threadId,
45
- metadata: this.devtoolsMetadata,
46
- getCoreState: () => ({
47
- input: this.input,
48
- result: this.result,
49
- progress: this.progress,
50
- status: this.status,
51
- isLoading: this.isLoading,
52
- ...this.error ? { error: this.error.message } : {}
53
- })
54
- };
55
- }
56
- mountDevtools() {
57
- if (this.devtoolsMounted) {
58
- return;
59
- }
60
- this.devtoolsMounted = true;
61
- this.devtoolsBridge.emitRegistered();
62
- this.devtoolsBridge.emitSnapshot();
63
- }
64
- /**
65
- * Trigger a generation request.
66
- * Only one generation can be in-flight at a time; calling generate()
67
- * while already generating will be a no-op.
68
- */
69
- async generate(input) {
70
- this.mountDevtools();
71
- if (this.isLoading) return;
72
- this.input = input;
73
- this.progress = null;
74
- const runId = this.devtoolsBridge.beginRun(input);
75
- this.setIsLoading(true);
76
- this.setStatus("generating");
77
- this.setError(void 0);
78
- const abortController = new AbortController();
79
- this.abortController = abortController;
80
- const { signal } = abortController;
81
- try {
82
- if (this.fetcher) {
83
- const result = await this.fetcher(input, { signal });
84
- if (signal.aborted) return;
85
- if (result instanceof Response) {
86
- await this.processStream(parseSSEResponse(result, signal), runId);
87
- } else {
88
- this.devtoolsBridge.ensureRunStarted(runId);
89
- this.setResult(result);
90
- this.setStatus("success");
91
- }
92
- } else if (this.connection) {
93
- const mergedData = { ...this.body, ...input };
94
- const stream = this.connection.connect(
95
- [],
96
- mergedData,
97
- signal,
98
- this.createRunContext(runId)
99
- );
100
- await this.processStream(stream, runId);
101
- } else {
102
- throw new Error(
103
- "GenerationClient requires either a connection or fetcher option"
104
- );
105
- }
106
- if (!signal.aborted && this.status === "success") {
107
- this.progress = completeProgressValue(this.progress);
108
- this.devtoolsBridge.finishRun(
109
- this.devtoolsBridge.getActiveRunId() ?? runId,
110
- "run:completed",
111
- "completed"
112
- );
113
- }
114
- } catch (err) {
115
- if (signal.aborted) return;
116
- const error = err instanceof Error ? err : new Error(String(err));
117
- this.setError(error);
118
- this.setStatus("error");
119
- this.devtoolsBridge.finishRun(
120
- this.devtoolsBridge.getActiveRunId() ?? runId,
121
- "run:errored",
122
- "errored",
123
- error.message
124
- );
125
- this.callbacksRef.onError?.(error);
126
- } finally {
127
- this.abortController = null;
128
- this.setIsLoading(false);
129
- }
130
- }
131
- /**
132
- * Process a stream of AG-UI events from the streaming connection adapter.
133
- */
134
- async processStream(source, fallbackRunId) {
135
- let streamRunId;
136
- for await (const chunk of source) {
137
- if (this.abortController?.signal.aborted) break;
138
- this.callbacksRef.onChunk?.(chunk);
139
- const chunkRunId = "runId" in chunk && typeof chunk.runId === "string" ? chunk.runId : void 0;
140
- switch (chunk.type) {
141
- case "RUN_STARTED": {
142
- streamRunId = chunk.runId;
143
- this.devtoolsBridge.ensureRunStarted(chunk.runId);
144
- break;
145
- }
146
- case "CUSTOM": {
147
- this.devtoolsBridge.ensureRunStarted(streamRunId ?? fallbackRunId);
148
- if (chunk.name === GENERATION_EVENTS.RESULT) {
149
- this.setResult(chunk.value);
150
- } else if (chunk.name === GENERATION_EVENTS.PROGRESS) {
151
- const { progress, message } = chunk.value;
152
- this.setProgress(progress, message);
153
- }
154
- break;
155
- }
156
- case "RUN_FINISHED": {
157
- streamRunId = chunk.runId;
158
- this.devtoolsBridge.ensureRunStarted(chunk.runId);
159
- this.setStatus("success");
160
- break;
161
- }
162
- case "RUN_ERROR": {
163
- this.devtoolsBridge.ensureRunStarted(
164
- chunkRunId ?? streamRunId ?? fallbackRunId
165
- );
166
- const msg = chunk.message || chunk.error?.message || "An error occurred";
167
- throw new Error(msg);
168
- }
169
- }
170
- }
171
- }
172
- /**
173
- * Abort any in-flight generation request.
174
- */
175
- stop() {
176
- const runId = this.devtoolsBridge.getActiveRunId();
177
- if (this.abortController) {
178
- this.abortController.abort();
179
- this.abortController = null;
180
- }
181
- this.setIsLoading(false);
182
- if (this.status === "generating") {
183
- this.setStatus("idle");
184
- if (runId) {
185
- this.devtoolsBridge.finishRun(runId, "run:cancelled", "cancelled");
186
- }
187
- }
188
- }
189
- /**
190
- * Clear the result, error, and return to idle state.
191
- */
192
- reset() {
193
- this.stop();
194
- this.setResult(null);
195
- this.input = null;
196
- this.progress = null;
197
- this.devtoolsBridge.resetRuns();
198
- this.setError(void 0);
199
- this.setStatus("idle");
200
- this.devtoolsBridge.emitState();
201
- }
202
- /**
203
- * Update options without recreating the client.
204
- */
205
- updateOptions(options) {
206
- if (options.body !== void 0) {
207
- this.body = options.body ?? {};
208
- }
209
- if (options.onResult !== void 0) {
210
- this.callbacksRef.onResult = options.onResult;
211
- }
212
- if (options.onError !== void 0) {
213
- this.callbacksRef.onError = options.onError;
214
- }
215
- if (options.onProgress !== void 0) {
216
- this.callbacksRef.onProgress = options.onProgress;
217
- }
218
- if (options.onChunk !== void 0) {
219
- this.callbacksRef.onChunk = options.onChunk;
220
- }
221
- }
222
- dispose() {
223
- this.stop();
224
- this.devtoolsBridge.dispose();
225
- this.devtoolsMounted = false;
226
- }
227
- // ===========================
228
- // Getters
229
- // ===========================
230
- getResult() {
231
- return this.result;
232
- }
233
- getIsLoading() {
234
- return this.isLoading;
235
- }
236
- getError() {
237
- return this.error;
238
- }
239
- getStatus() {
240
- return this.status;
241
- }
242
- // ===========================
243
- // Private state setters
244
- // ===========================
245
- setResult(rawResult) {
246
- if (rawResult === null) {
247
- this.result = null;
248
- this.callbacksRef.onResultChange?.(null);
249
- this.devtoolsBridge.recordResultChange();
250
- return;
251
- }
252
- if (this.callbacksRef.onResult) {
253
- const transformed = this.callbacksRef.onResult(rawResult);
254
- if (transformed === null) {
255
- this.devtoolsBridge.emitState();
256
- return;
257
- }
258
- if (transformed !== void 0) {
259
- this.result = transformed;
260
- this.callbacksRef.onResultChange?.(this.result);
261
- this.devtoolsBridge.recordResultChange();
262
- return;
263
- }
264
- }
265
- this.result = rawResult;
266
- this.callbacksRef.onResultChange?.(this.result);
267
- this.devtoolsBridge.recordResultChange();
268
- }
269
- setIsLoading(isLoading) {
270
- this.isLoading = isLoading;
271
- this.callbacksRef.onLoadingChange?.(isLoading);
272
- this.devtoolsBridge.recordLoadingChange();
273
- }
274
- setError(error) {
275
- this.error = error;
276
- this.callbacksRef.onErrorChange?.(error);
277
- this.devtoolsBridge.recordErrorChange(error);
278
- }
279
- setStatus(status) {
280
- this.status = status;
281
- this.callbacksRef.onStatusChange?.(status);
282
- this.devtoolsBridge.recordStatusChange(status);
283
- }
284
- setProgress(value, message) {
285
- this.progress = {
286
- value,
287
- ...message ? { message } : {}
288
- };
289
- if (message === void 0) {
290
- this.callbacksRef.onProgress?.(value);
291
- } else {
292
- this.callbacksRef.onProgress?.(value, message);
293
- }
294
- this.devtoolsBridge.recordProgressChange();
295
- }
296
- createDevtoolsMetadata(metadata) {
297
- return {
298
- hookName: metadata?.hookName ?? "useGeneration",
299
- ...metadata?.framework ? { framework: metadata.framework } : {},
300
- ...metadata?.outputKind ? { outputKind: metadata.outputKind } : {},
301
- ...metadata?.name ? { name: metadata.name } : {}
302
- };
303
- }
304
- generateUniqueId(prefix) {
305
- return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
306
- }
307
- createRunContext(runId) {
308
- return {
309
- threadId: this.threadId,
310
- runId
311
- };
312
- }
313
- }
314
- function completeProgressValue(progress) {
315
- if (!progress) return null;
316
- const message = progress.message;
317
- return {
318
- value: 100,
319
- ...message ? { message } : {}
320
- };
321
- }
322
- export {
323
- GenerationClient
324
- };
325
- //# sourceMappingURL=generation-client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generation-client.js","sources":["../../src/generation-client.ts"],"sourcesContent":["import { GENERATION_EVENTS } from './generation-types'\nimport { createNoOpGenerationDevtoolsBridge } 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 GenerationDevtoolsBridge,\n GenerationDevtoolsBridgeOptions,\n} from './devtools'\nimport type {\n GenerationClientOptions,\n GenerationClientState,\n GenerationFetcher,\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 GenerationCallbacks<TResult, TOutput> {\n onResult?: ((result: TResult) => TOutput | null | void) | undefined\n onError?: ((error: Error) => void) | undefined\n onProgress?: ((progress: number, message?: string) => void) | undefined\n onChunk?: ((chunk: StreamChunk) => 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}\n\n/**\n * A lightweight, generic client for one-shot generation tasks\n * (image, speech, transcription, summarize).\n *\n * Supports two transport modes:\n * - **ConnectConnectionAdapter** — Streaming transport (SSE, HTTP stream, custom).\n * Server wraps results in StreamChunk events with CUSTOM event names.\n * - **Fetcher** — Direct async function call. No streaming protocol needed.\n *\n * @template TInput - The input type for the generation request\n * @template TResult - The result type returned by the generation\n *\n * @example\n * ```typescript\n * // With streaming connection adapter\n * const client = new GenerationClient<ImageGenerateInput, ImageGenerationResult>({\n * connection: fetchServerSentEvents('/api/generate/image'),\n * onResultChange: setResult,\n * onLoadingChange: setIsLoading,\n * })\n *\n * // With fetcher (direct)\n * const client = new GenerationClient<ImageGenerateInput, ImageGenerationResult>({\n * fetcher: async (input) => {\n * const res = await fetch('/api/generate/image', {\n * method: 'POST',\n * body: JSON.stringify(input),\n * })\n * return res.json()\n * },\n * })\n *\n * await client.generate({ prompt: 'A sunset over mountains' })\n * ```\n */\nexport class GenerationClient<\n TInput extends Record<string, any>,\n TResult,\n TOutput = TResult,\n> {\n private readonly connection: ConnectConnectionAdapter | undefined\n private readonly fetcher: GenerationFetcher<TInput, TResult> | undefined\n private readonly uniqueId: string\n private readonly devtoolsMetadata: AIDevtoolsClientMetadata\n private readonly devtoolsBridge: GenerationDevtoolsBridge<TOutput>\n private readonly threadId: string\n private body: Record<string, any>\n private result: TOutput | null = null\n private input: TInput | null = null\n private progress: AIDevtoolsGenerationProgress | 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: GenerationCallbacks<TResult, TOutput>\n private devtoolsMounted = false\n\n constructor(\n options: GenerationClientOptions<TInput, TResult, TOutput> &\n (\n | { connection: ConnectConnectionAdapter; fetcher?: never }\n | {\n fetcher: GenerationFetcher<TInput, TResult>\n connection?: never\n }\n ),\n ) {\n this.uniqueId = options.id ?? this.generateUniqueId('generation')\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 onResultChange: options.onResultChange,\n onLoadingChange: options.onLoadingChange,\n onErrorChange: options.onErrorChange,\n onStatusChange: options.onStatusChange,\n }\n\n this.devtoolsMetadata = this.createDevtoolsMetadata(options.devtools)\n this.devtoolsBridge = (\n options.devtoolsBridgeFactory ?? createNoOpGenerationDevtoolsBridge\n )<TOutput>(this.buildDevtoolsBridgeOptions())\n }\n\n private buildDevtoolsBridgeOptions(): GenerationDevtoolsBridgeOptions<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 ...(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 a generation request.\n * Only one generation can be in-flight at a time; calling generate()\n * while already generating will be a no-op.\n */\n async generate(input: TInput): 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\n const abortController = new AbortController()\n this.abortController = abortController\n const { signal } = abortController\n\n try {\n if (this.fetcher) {\n // Direct fetch path\n const result = await this.fetcher(input, { signal })\n if (signal.aborted) return\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 } else if (this.connection) {\n // Streaming adapter path\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 'GenerationClient requires either a connection or fetcher option',\n )\n }\n if (!signal.aborted && this.status === 'success') {\n // Bump progress to 100 on successful completion so devtools\n // snapshots reflect the final state. The bridge mirrors this in\n // the run's recorded progress, but the snapshot reads `progress`\n // from the client's core state.\n this.progress = completeProgressValue(this.progress)\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 * Process a stream of AG-UI events from the streaming connection adapter.\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 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.RESULT) {\n this.setResult(chunk.value as TResult)\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 request.\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 the result, error, and return to idle state.\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.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 GenerationClientOptions<TInput, TResult, TOutput>,\n 'body' | 'onResult' | 'onError' | 'onProgress' | 'onChunk'\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 }\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 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: TResult | null): void {\n if (rawResult === null) {\n this.result = null\n this.callbacksRef.onResultChange?.(null)\n this.devtoolsBridge.recordResultChange()\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, 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 `TResult`, so the runtime cast is sound.\n // eslint-disable-next-line no-restricted-syntax -- TOutput defaults to TResult 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 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 createDevtoolsMetadata(\n metadata?: Partial<AIDevtoolsClientMetadata>,\n ): AIDevtoolsClientMetadata {\n return {\n hookName: metadata?.hookName ?? 'useGeneration',\n ...(metadata?.framework ? { framework: metadata.framework } : {}),\n ...(metadata?.outputKind ? { outputKind: metadata.outputKind } : {}),\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\nfunction completeProgressValue(\n progress: AIDevtoolsGenerationProgress | null,\n): AIDevtoolsGenerationProgress | null {\n if (!progress) return null\n const message = progress.message\n return {\n value: 100,\n ...(message ? { message } : {}),\n }\n}\n"],"names":[],"mappings":";;;AAwEO,MAAM,iBAIX;AAAA,EACiB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACA,SAAyB;AAAA,EACzB,QAAuB;AAAA,EACvB,WAAgD;AAAA,EAChD,YAAY;AAAA,EACZ,QAA2B;AAAA,EAC3B,SAAgC;AAAA,EAChC,kBAA0C;AAAA,EACjC;AAAA,EACT,kBAAkB;AAAA,EAE1B,YACE,SAQA;AACA,SAAK,WAAW,QAAQ,MAAM,KAAK,iBAAiB,YAAY;AAChE,SAAK,WAAW,KAAK;AACrB,SAAK,aAAa,QAAQ;AAC1B,SAAK,UAAU,QAAQ;AACvB,SAAK,OAAO,QAAQ,QAAQ,CAAA;AAE5B,SAAK,eAAe;AAAA,MAClB,UAAU,QAAQ;AAAA,MAClB,SAAS,QAAQ;AAAA,MACjB,YAAY,QAAQ;AAAA,MACpB,SAAS,QAAQ;AAAA,MACjB,gBAAgB,QAAQ;AAAA,MACxB,iBAAiB,QAAQ;AAAA,MACzB,eAAe,QAAQ;AAAA,MACvB,gBAAgB,QAAQ;AAAA,IAAA;AAG1B,SAAK,mBAAmB,KAAK,uBAAuB,QAAQ,QAAQ;AACpE,SAAK,kBACH,QAAQ,yBAAyB,oCACxB,KAAK,4BAA4B;AAAA,EAC9C;AAAA,EAEQ,6BAAuE;AAC7E,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf,cAAc,OAAO;AAAA,QACnB,OAAO,KAAK;AAAA,QACZ,QAAQ,KAAK;AAAA,QACb,UAAU,KAAK;AAAA,QACf,QAAQ,KAAK;AAAA,QACb,WAAW,KAAK;AAAA,QAChB,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,YAAY,CAAA;AAAA,MAAC;AAAA,IACpD;AAAA,EAEJ;AAAA,EAEA,gBAAsB;AACpB,QAAI,KAAK,iBAAiB;AACxB;AAAA,IACF;AAEA,SAAK,kBAAkB;AACvB,SAAK,eAAe,eAAA;AACpB,SAAK,eAAe,aAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAAS,OAA8B;AAC3C,SAAK,cAAA;AACL,QAAI,KAAK,UAAW;AAEpB,SAAK,QAAQ;AACb,SAAK,WAAW;AAChB,UAAM,QAAQ,KAAK,eAAe,SAAS,KAAK;AAChD,SAAK,aAAa,IAAI;AACtB,SAAK,UAAU,YAAY;AAC3B,SAAK,SAAS,MAAS;AAEvB,UAAM,kBAAkB,IAAI,gBAAA;AAC5B,SAAK,kBAAkB;AACvB,UAAM,EAAE,WAAW;AAEnB,QAAI;AACF,UAAI,KAAK,SAAS;AAEhB,cAAM,SAAS,MAAM,KAAK,QAAQ,OAAO,EAAE,QAAQ;AACnD,YAAI,OAAO,QAAS;AACpB,YAAI,kBAAkB,UAAU;AAE9B,gBAAM,KAAK,cAAc,iBAAiB,QAAQ,MAAM,GAAG,KAAK;AAAA,QAClE,OAAO;AACL,eAAK,eAAe,iBAAiB,KAAK;AAC1C,eAAK,UAAU,MAAM;AACrB,eAAK,UAAU,SAAS;AAAA,QAC1B;AAAA,MACF,WAAW,KAAK,YAAY;AAE1B,cAAM,aAAa,EAAE,GAAG,KAAK,MAAM,GAAG,MAAA;AACtC,cAAM,SAAS,KAAK,WAAW;AAAA,UAC7B,CAAA;AAAA,UACA;AAAA,UACA;AAAA,UACA,KAAK,iBAAiB,KAAK;AAAA,QAAA;AAE7B,cAAM,KAAK,cAAc,QAAQ,KAAK;AAAA,MACxC,OAAO;AACL,cAAM,IAAI;AAAA,UACR;AAAA,QAAA;AAAA,MAEJ;AACA,UAAI,CAAC,OAAO,WAAW,KAAK,WAAW,WAAW;AAKhD,aAAK,WAAW,sBAAsB,KAAK,QAAQ;AACnD,aAAK,eAAe;AAAA,UAClB,KAAK,eAAe,eAAA,KAAoB;AAAA,UACxC;AAAA,UACA;AAAA,QAAA;AAAA,MAEJ;AAAA,IACF,SAAS,KAAc;AACrB,UAAI,OAAO,QAAS;AACpB,YAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAChE,WAAK,SAAS,KAAK;AACnB,WAAK,UAAU,OAAO;AACtB,WAAK,eAAe;AAAA,QAClB,KAAK,eAAe,eAAA,KAAoB;AAAA,QACxC;AAAA,QACA;AAAA,QACA,MAAM;AAAA,MAAA;AAER,WAAK,aAAa,UAAU,KAAK;AAAA,IACnC,UAAA;AACE,WAAK,kBAAkB;AACvB,WAAK,aAAa,KAAK;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cACZ,QACA,eACe;AACf,QAAI;AAEJ,qBAAiB,SAAS,QAAQ;AAChC,UAAI,KAAK,iBAAiB,OAAO,QAAS;AAE1C,WAAK,aAAa,UAAU,KAAK;AACjC,YAAM,aACJ,WAAW,SAAS,OAAO,MAAM,UAAU,WACvC,MAAM,QACN;AAGN,cAAQ,MAAM,MAAA;AAAA,QACZ,KAAK,eAAe;AAClB,wBAAc,MAAM;AACpB,eAAK,eAAe,iBAAiB,MAAM,KAAK;AAChD;AAAA,QACF;AAAA,QACA,KAAK,UAAU;AACb,eAAK,eAAe,iBAAiB,eAAe,aAAa;AACjE,cAAI,MAAM,SAAS,kBAAkB,QAAQ;AAC3C,iBAAK,UAAU,MAAM,KAAgB;AAAA,UACvC,WAAW,MAAM,SAAS,kBAAkB,UAAU;AACpD,kBAAM,EAAE,UAAU,QAAA,IAAY,MAAM;AAIpC,iBAAK,YAAY,UAAU,OAAO;AAAA,UACpC;AACA;AAAA,QACF;AAAA,QACA,KAAK,gBAAgB;AACnB,wBAAc,MAAM;AACpB,eAAK,eAAe,iBAAiB,MAAM,KAAK;AAChD,eAAK,UAAU,SAAS;AACxB;AAAA,QACF;AAAA,QACA,KAAK,aAAa;AAChB,eAAK,eAAe;AAAA,YAClB,cAAc,eAAe;AAAA,UAAA;AAG/B,gBAAM,MACH,MAAM,WACP,MAAM,OAAO,WACb;AACF,gBAAM,IAAI,MAAM,GAAG;AAAA,QACrB;AAAA,MAEE;AAAA,IAEN;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAa;AACX,UAAM,QAAQ,KAAK,eAAe,eAAA;AAClC,QAAI,KAAK,iBAAiB;AACxB,WAAK,gBAAgB,MAAA;AACrB,WAAK,kBAAkB;AAAA,IACzB;AACA,SAAK,aAAa,KAAK;AACvB,QAAI,KAAK,WAAW,cAAc;AAChC,WAAK,UAAU,MAAM;AACrB,UAAI,OAAO;AACT,aAAK,eAAe,UAAU,OAAO,iBAAiB,WAAW;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,KAAA;AACL,SAAK,UAAU,IAAI;AACnB,SAAK,QAAQ;AACb,SAAK,WAAW;AAChB,SAAK,eAAe,UAAA;AACpB,SAAK,SAAS,MAAS;AACvB,SAAK,UAAU,MAAM;AACrB,SAAK,eAAe,UAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,cACE,SAMM;AACN,QAAI,QAAQ,SAAS,QAAW;AAC9B,WAAK,OAAO,QAAQ,QAAQ,CAAA;AAAA,IAC9B;AACA,QAAI,QAAQ,aAAa,QAAW;AAClC,WAAK,aAAa,WAAW,QAAQ;AAAA,IACvC;AACA,QAAI,QAAQ,YAAY,QAAW;AACjC,WAAK,aAAa,UAAU,QAAQ;AAAA,IACtC;AACA,QAAI,QAAQ,eAAe,QAAW;AACpC,WAAK,aAAa,aAAa,QAAQ;AAAA,IACzC;AACA,QAAI,QAAQ,YAAY,QAAW;AACjC,WAAK,aAAa,UAAU,QAAQ;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,KAAA;AACL,SAAK,eAAe,QAAA;AACpB,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAMA,YAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,eAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,WAA8B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,YAAmC;AACjC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAMQ,UAAU,WAAiC;AACjD,QAAI,cAAc,MAAM;AACtB,WAAK,SAAS;AACd,WAAK,aAAa,iBAAiB,IAAI;AACvC,WAAK,eAAe,mBAAA;AACpB;AAAA,IACF;AAEA,QAAI,KAAK,aAAa,UAAU;AAC9B,YAAM,cAAc,KAAK,aAAa,SAAS,SAAS;AACxD,UAAI,gBAAgB,MAAM;AAExB,aAAK,eAAe,UAAA;AACpB;AAAA,MACF;AACA,UAAI,gBAAgB,QAAW;AAE7B,aAAK,SAAS;AACd,aAAK,aAAa,iBAAiB,KAAK,MAAM;AAC9C,aAAK,eAAe,mBAAA;AACpB;AAAA,MACF;AAAA,IACF;AAMA,SAAK,SAAS;AACd,SAAK,aAAa,iBAAiB,KAAK,MAAM;AAC9C,SAAK,eAAe,mBAAA;AAAA,EACtB;AAAA,EAEQ,aAAa,WAA0B;AAC7C,SAAK,YAAY;AACjB,SAAK,aAAa,kBAAkB,SAAS;AAC7C,SAAK,eAAe,oBAAA;AAAA,EACtB;AAAA,EAEQ,SAAS,OAAgC;AAC/C,SAAK,QAAQ;AACb,SAAK,aAAa,gBAAgB,KAAK;AACvC,SAAK,eAAe,kBAAkB,KAAK;AAAA,EAC7C;AAAA,EAEQ,UAAU,QAAqC;AACrD,SAAK,SAAS;AACd,SAAK,aAAa,iBAAiB,MAAM;AACzC,SAAK,eAAe,mBAAmB,MAAM;AAAA,EAC/C;AAAA,EAEQ,YAAY,OAAe,SAAwB;AACzD,SAAK,WAAW;AAAA,MACd;AAAA,MACA,GAAI,UAAU,EAAE,YAAY,CAAA;AAAA,IAAC;AAE/B,QAAI,YAAY,QAAW;AACzB,WAAK,aAAa,aAAa,KAAK;AAAA,IACtC,OAAO;AACL,WAAK,aAAa,aAAa,OAAO,OAAO;AAAA,IAC/C;AACA,SAAK,eAAe,qBAAA;AAAA,EACtB;AAAA,EAEQ,uBACN,UAC0B;AAC1B,WAAO;AAAA,MACL,UAAU,UAAU,YAAY;AAAA,MAChC,GAAI,UAAU,YAAY,EAAE,WAAW,SAAS,UAAA,IAAc,CAAA;AAAA,MAC9D,GAAI,UAAU,aAAa,EAAE,YAAY,SAAS,WAAA,IAAe,CAAA;AAAA,MACjE,GAAI,UAAU,OAAO,EAAE,MAAM,SAAS,KAAA,IAAS,CAAA;AAAA,IAAC;AAAA,EAEpD;AAAA,EAEQ,iBAAiB,QAAwB;AAC/C,WAAO,GAAG,MAAM,IAAI,KAAK,KAAK,IAAI,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,UAAU,CAAC,CAAC;AAAA,EAC3E;AAAA,EAEQ,iBAAiB,OAAqC;AAC5D,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf;AAAA,IAAA;AAAA,EAEJ;AACF;AAEA,SAAS,sBACP,UACqC;AACrC,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,UAAU,SAAS;AACzB,SAAO;AAAA,IACL,OAAO;AAAA,IACP,GAAI,UAAU,EAAE,YAAY,CAAA;AAAA,EAAC;AAEjC;"}