@tanstack/ai-client 0.22.1 → 0.23.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.
Files changed (72) hide show
  1. package/README.md +15 -1
  2. package/dist/esm/audio-recorder.js +190 -213
  3. package/dist/esm/audio-recorder.js.map +1 -1
  4. package/dist/esm/chat-client.d.ts +172 -3
  5. package/dist/esm/chat-client.js +1656 -1386
  6. package/dist/esm/chat-client.js.map +1 -1
  7. package/dist/esm/cleared-stream-tracker.d.ts +23 -0
  8. package/dist/esm/cleared-stream-tracker.js +97 -0
  9. package/dist/esm/cleared-stream-tracker.js.map +1 -0
  10. package/dist/esm/client-persistor.d.ts +25 -12
  11. package/dist/esm/client-persistor.js +260 -235
  12. package/dist/esm/client-persistor.js.map +1 -1
  13. package/dist/esm/connection-adapters.d.ts +231 -10
  14. package/dist/esm/connection-adapters.js +989 -574
  15. package/dist/esm/connection-adapters.js.map +1 -1
  16. package/dist/esm/devtools-noop.d.ts +1 -0
  17. package/dist/esm/devtools-noop.js +79 -139
  18. package/dist/esm/devtools-noop.js.map +1 -1
  19. package/dist/esm/devtools.d.ts +31 -1
  20. package/dist/esm/devtools.js +977 -1127
  21. package/dist/esm/devtools.js.map +1 -1
  22. package/dist/esm/events.js +224 -226
  23. package/dist/esm/events.js.map +1 -1
  24. package/dist/esm/generation-client.d.ts +145 -2
  25. package/dist/esm/generation-client.js +659 -321
  26. package/dist/esm/generation-client.js.map +1 -1
  27. package/dist/esm/generation-reconstruct.d.ts +21 -0
  28. package/dist/esm/generation-reconstruct.js +85 -0
  29. package/dist/esm/generation-reconstruct.js.map +1 -0
  30. package/dist/esm/generation-types.d.ts +289 -3
  31. package/dist/esm/generation-types.js +356 -13
  32. package/dist/esm/generation-types.js.map +1 -1
  33. package/dist/esm/index.d.ts +9 -4
  34. package/dist/esm/index.js +7 -39
  35. package/dist/esm/interrupt-manager.d.ts +77 -0
  36. package/dist/esm/interrupt-manager.js +787 -0
  37. package/dist/esm/interrupt-manager.js.map +1 -0
  38. package/dist/esm/mcp-app-bridge.js +56 -64
  39. package/dist/esm/mcp-app-bridge.js.map +1 -1
  40. package/dist/esm/realtime-client.js +366 -440
  41. package/dist/esm/realtime-client.js.map +1 -1
  42. package/dist/esm/response-stream.js +19 -26
  43. package/dist/esm/response-stream.js.map +1 -1
  44. package/dist/esm/sse-parser.js +44 -47
  45. package/dist/esm/sse-parser.js.map +1 -1
  46. package/dist/esm/sse-utils.js +8 -9
  47. package/dist/esm/sse-utils.js.map +1 -1
  48. package/dist/esm/storage-adapters.d.ts +62 -0
  49. package/dist/esm/storage-adapters.js +174 -0
  50. package/dist/esm/storage-adapters.js.map +1 -0
  51. package/dist/esm/types.d.ts +212 -10
  52. package/dist/esm/types.js +38 -7
  53. package/dist/esm/types.js.map +1 -1
  54. package/dist/esm/video-generation-client.d.ts +113 -2
  55. package/dist/esm/video-generation-client.js +665 -379
  56. package/dist/esm/video-generation-client.js.map +1 -1
  57. package/package.json +7 -7
  58. package/src/chat-client.ts +1079 -61
  59. package/src/cleared-stream-tracker.ts +151 -0
  60. package/src/client-persistor.ts +102 -33
  61. package/src/connection-adapters.ts +1185 -142
  62. package/src/devtools-noop.ts +4 -3
  63. package/src/devtools.ts +121 -3
  64. package/src/generation-client.ts +563 -13
  65. package/src/generation-reconstruct.ts +121 -0
  66. package/src/generation-types.ts +727 -3
  67. package/src/index.ts +56 -1
  68. package/src/interrupt-manager.ts +1440 -0
  69. package/src/storage-adapters.ts +242 -0
  70. package/src/types.ts +301 -9
  71. package/src/video-generation-client.ts +479 -13
  72. package/dist/esm/index.js.map +0 -1
@@ -1,227 +1,225 @@
1
- import { createAIDevtoolsEventEnvelope, aiEventClient } from "@tanstack/ai-event-client";
2
- class ChatClientEventEmitter {
3
- clientId;
4
- constructor(clientId) {
5
- this.clientId = clientId;
6
- }
7
- /**
8
- * Emit client created event
9
- */
10
- clientCreated(initialMessageCount) {
11
- this.emitEvent("client:created", {
12
- initialMessageCount
13
- });
14
- }
15
- /**
16
- * Emit loading state changed event
17
- */
18
- loadingChanged(isLoading) {
19
- this.emitEvent("client:loading:changed", { isLoading });
20
- }
21
- /**
22
- * Emit error state changed event
23
- */
24
- errorChanged(error) {
25
- this.emitEvent("client:error:changed", {
26
- error
27
- });
28
- }
29
- /**
30
- * Emit text update events (combines processor and client events)
31
- */
32
- textUpdated(streamId, messageId, content, context) {
33
- this.emitEvent("text:chunk:content", {
34
- streamId,
35
- messageId,
36
- content,
37
- ...context
38
- });
39
- }
40
- /**
41
- * Emit tool call state change events (combines processor and client events)
42
- */
43
- toolCallStateChanged(streamId, messageId, toolCallId, toolName, state, args, context) {
44
- this.emitEvent("tools:call:updated", {
45
- streamId,
46
- messageId,
47
- toolCallId,
48
- toolName,
49
- state,
50
- arguments: args,
51
- ...context
52
- });
53
- }
54
- /**
55
- * Emit tool result state change event
56
- */
57
- /**
58
- * Emit thinking update event
59
- */
60
- thinkingUpdated(streamId, messageId, content, delta, context) {
61
- this.emitEvent("text:chunk:thinking", {
62
- streamId,
63
- messageId,
64
- content,
65
- delta,
66
- ...context
67
- });
68
- }
69
- structuredOutputChanged(eventName, streamId, messageId, output, context) {
70
- this.emitEvent(eventName, {
71
- streamId,
72
- messageId,
73
- ...output,
74
- ...context
75
- });
76
- }
77
- /**
78
- * Emit approval requested event
79
- */
80
- approvalRequested(streamId, messageId, toolCallId, toolName, input, approvalId, context) {
81
- this.emitEvent("tools:approval:requested", {
82
- streamId,
83
- messageId,
84
- toolCallId,
85
- toolName,
86
- input,
87
- approvalId,
88
- ...context
89
- });
90
- }
91
- /**
92
- * Emit message appended event
93
- */
94
- messageAppended(uiMessage, streamId, context) {
95
- const content = uiMessage.parts.filter((part) => part.type === "text").map((part) => part.content).join(" ");
96
- this.emitEvent("text:message:created", {
97
- streamId,
98
- messageId: uiMessage.id,
99
- role: uiMessage.role,
100
- content,
101
- parts: uiMessage.parts,
102
- ...context
103
- });
104
- }
105
- /**
106
- * Emit message sent event.
107
- * Supports both simple string content and multimodal content arrays.
108
- *
109
- * @param messageId - The ID of the sent message
110
- * @param content - The message content (string or array of ContentPart for multimodal)
111
- */
112
- messageSent(messageId, content) {
113
- const textContent = typeof content === "string" ? content : content.filter((part) => part.type === "text").map((part) => part.content).join("");
114
- this.emitEvent("text:message:created", {
115
- messageId,
116
- role: "user",
117
- content: textContent,
118
- // Include full content for multimodal messages
119
- ...Array.isArray(content) && { parts: content }
120
- });
121
- this.emitEvent("text:message:user", {
122
- messageId,
123
- role: "user",
124
- content: textContent,
125
- // Include full content for multimodal messages
126
- ...Array.isArray(content) && { parts: content }
127
- });
128
- }
129
- /**
130
- * Emit reloaded event
131
- */
132
- reloaded(fromMessageIndex) {
133
- this.emitEvent("client:reloaded", {
134
- fromMessageIndex
135
- });
136
- }
137
- /**
138
- * Emit stopped event
139
- */
140
- stopped() {
141
- this.emitEvent("client:stopped");
142
- }
143
- /**
144
- * Emit messages cleared event
145
- */
146
- messagesCleared() {
147
- this.emitEvent("client:messages:cleared");
148
- }
149
- /**
150
- * Emit tool result added event
151
- */
152
- toolResultAdded(toolCallId, toolName, output, state, context) {
153
- this.emitEvent("tools:result:added", {
154
- toolCallId,
155
- toolName,
156
- output,
157
- state,
158
- ...context
159
- });
160
- }
161
- /**
162
- * Emit tool approval responded event
163
- */
164
- toolApprovalResponded(approvalId, toolCallId, approved, context) {
165
- this.emitEvent("tools:approval:responded", {
166
- approvalId,
167
- toolCallId,
168
- approved,
169
- ...context
170
- });
171
- }
172
- /**
173
- * Emit tool fixture applied event.
174
- */
175
- toolFixtureApplied(fixture) {
176
- this.emitEvent("devtools:tool-fixture:applied", { ...fixture });
177
- }
178
- }
179
- class DefaultChatClientEventEmitter extends ChatClientEventEmitter {
180
- /**
181
- * Emit an event with automatic clientId and timestamp for client/tool events
182
- */
183
- emitEvent(eventName, data) {
184
- const timestamp = Date.now();
185
- const isUserVisibleEvent = eventName.startsWith("text:") || eventName.startsWith("tools:") || eventName.startsWith("structured-output:") || eventName === "devtools:tool-fixture:applied";
186
- const includesClientContext = eventName.startsWith("client:") || eventName.startsWith("tools:") || eventName.startsWith("text:") || eventName.startsWith("structured-output:") || eventName === "devtools:tool-fixture:applied";
187
- const visibility = isUserVisibleEvent ? "user-visible" : "client-state";
188
- const envelopeContext = {
189
- hookId: this.clientId,
190
- ...typeof data?.threadId === "string" ? { threadId: data.threadId } : {},
191
- ...typeof data?.runId === "string" ? { runId: data.runId } : {},
192
- ...typeof data?.streamId === "string" ? { streamId: data.streamId } : {},
193
- ...typeof data?.messageId === "string" ? { messageId: data.messageId } : {},
194
- ...typeof data?.toolCallId === "string" ? { toolCallId: data.toolCallId } : {}
195
- };
196
- if (includesClientContext) {
197
- const envelope = createAIDevtoolsEventEnvelope({
198
- eventType: eventName,
199
- clientId: this.clientId,
200
- ...envelopeContext,
201
- source: "client",
202
- visibility,
203
- timestamp
204
- });
205
- aiEventClient.emit(eventName, {
206
- ...data,
207
- ...envelope
208
- });
209
- } else {
210
- const envelope = createAIDevtoolsEventEnvelope({
211
- eventType: eventName,
212
- source: "client",
213
- visibility: "client-state",
214
- timestamp
215
- });
216
- aiEventClient.emit(eventName, {
217
- ...data,
218
- ...envelope
219
- });
220
- }
221
- }
222
- }
223
- export {
224
- ChatClientEventEmitter,
225
- DefaultChatClientEventEmitter
1
+ import { aiEventClient, createAIDevtoolsEventEnvelope } from "@tanstack/ai-event-client";
2
+ //#region src/events.ts
3
+ /**
4
+ * Abstract base class for ChatClient event emission
5
+ */
6
+ var ChatClientEventEmitter = class {
7
+ clientId;
8
+ constructor(clientId) {
9
+ this.clientId = clientId;
10
+ }
11
+ /**
12
+ * Emit client created event
13
+ */
14
+ clientCreated(initialMessageCount) {
15
+ this.emitEvent("client:created", { initialMessageCount });
16
+ }
17
+ /**
18
+ * Emit loading state changed event
19
+ */
20
+ loadingChanged(isLoading) {
21
+ this.emitEvent("client:loading:changed", { isLoading });
22
+ }
23
+ /**
24
+ * Emit error state changed event
25
+ */
26
+ errorChanged(error) {
27
+ this.emitEvent("client:error:changed", { error });
28
+ }
29
+ /**
30
+ * Emit text update events (combines processor and client events)
31
+ */
32
+ textUpdated(streamId, messageId, content, context) {
33
+ this.emitEvent("text:chunk:content", {
34
+ streamId,
35
+ messageId,
36
+ content,
37
+ ...context
38
+ });
39
+ }
40
+ /**
41
+ * Emit tool call state change events (combines processor and client events)
42
+ */
43
+ toolCallStateChanged(streamId, messageId, toolCallId, toolName, state, args, context) {
44
+ this.emitEvent("tools:call:updated", {
45
+ streamId,
46
+ messageId,
47
+ toolCallId,
48
+ toolName,
49
+ state,
50
+ arguments: args,
51
+ ...context
52
+ });
53
+ }
54
+ /**
55
+ * Emit tool result state change event
56
+ */
57
+ /**
58
+ * Emit thinking update event
59
+ */
60
+ thinkingUpdated(streamId, messageId, content, delta, context) {
61
+ this.emitEvent("text:chunk:thinking", {
62
+ streamId,
63
+ messageId,
64
+ content,
65
+ delta,
66
+ ...context
67
+ });
68
+ }
69
+ structuredOutputChanged(eventName, streamId, messageId, output, context) {
70
+ this.emitEvent(eventName, {
71
+ streamId,
72
+ messageId,
73
+ ...output,
74
+ ...context
75
+ });
76
+ }
77
+ /**
78
+ * Emit approval requested event
79
+ */
80
+ approvalRequested(streamId, messageId, toolCallId, toolName, input, approvalId, context) {
81
+ this.emitEvent("tools:approval:requested", {
82
+ streamId,
83
+ messageId,
84
+ toolCallId,
85
+ toolName,
86
+ input,
87
+ approvalId,
88
+ ...context
89
+ });
90
+ }
91
+ /**
92
+ * Emit message appended event
93
+ */
94
+ messageAppended(uiMessage, streamId, context) {
95
+ const content = uiMessage.parts.filter((part) => part.type === "text").map((part) => part.content).join(" ");
96
+ this.emitEvent("text:message:created", {
97
+ streamId,
98
+ messageId: uiMessage.id,
99
+ role: uiMessage.role,
100
+ content,
101
+ parts: uiMessage.parts,
102
+ ...context
103
+ });
104
+ }
105
+ /**
106
+ * Emit message sent event.
107
+ * Supports both simple string content and multimodal content arrays.
108
+ *
109
+ * @param messageId - The ID of the sent message
110
+ * @param content - The message content (string or array of ContentPart for multimodal)
111
+ */
112
+ messageSent(messageId, content) {
113
+ const textContent = typeof content === "string" ? content : content.filter((part) => part.type === "text").map((part) => part.content).join("");
114
+ this.emitEvent("text:message:created", {
115
+ messageId,
116
+ role: "user",
117
+ content: textContent,
118
+ ...Array.isArray(content) && { parts: content }
119
+ });
120
+ this.emitEvent("text:message:user", {
121
+ messageId,
122
+ role: "user",
123
+ content: textContent,
124
+ ...Array.isArray(content) && { parts: content }
125
+ });
126
+ }
127
+ /**
128
+ * Emit reloaded event
129
+ */
130
+ reloaded(fromMessageIndex) {
131
+ this.emitEvent("client:reloaded", { fromMessageIndex });
132
+ }
133
+ /**
134
+ * Emit stopped event
135
+ */
136
+ stopped() {
137
+ this.emitEvent("client:stopped");
138
+ }
139
+ /**
140
+ * Emit messages cleared event
141
+ */
142
+ messagesCleared() {
143
+ this.emitEvent("client:messages:cleared");
144
+ }
145
+ /**
146
+ * Emit tool result added event
147
+ */
148
+ toolResultAdded(toolCallId, toolName, output, state, context) {
149
+ this.emitEvent("tools:result:added", {
150
+ toolCallId,
151
+ toolName,
152
+ output,
153
+ state,
154
+ ...context
155
+ });
156
+ }
157
+ /**
158
+ * Emit tool approval responded event
159
+ */
160
+ toolApprovalResponded(approvalId, toolCallId, approved, context) {
161
+ this.emitEvent("tools:approval:responded", {
162
+ approvalId,
163
+ toolCallId,
164
+ approved,
165
+ ...context
166
+ });
167
+ }
168
+ /**
169
+ * Emit tool fixture applied event.
170
+ */
171
+ toolFixtureApplied(fixture) {
172
+ this.emitEvent("devtools:tool-fixture:applied", { ...fixture });
173
+ }
226
174
  };
227
- //# sourceMappingURL=events.js.map
175
+ /**
176
+ * Default implementation of ChatClientEventEmitter
177
+ */
178
+ var DefaultChatClientEventEmitter = class extends ChatClientEventEmitter {
179
+ /**
180
+ * Emit an event with automatic clientId and timestamp for client/tool events
181
+ */
182
+ emitEvent(eventName, data) {
183
+ const timestamp = Date.now();
184
+ const isUserVisibleEvent = eventName.startsWith("text:") || eventName.startsWith("tools:") || eventName.startsWith("structured-output:") || eventName === "devtools:tool-fixture:applied";
185
+ const includesClientContext = eventName.startsWith("client:") || eventName.startsWith("tools:") || eventName.startsWith("text:") || eventName.startsWith("structured-output:") || eventName === "devtools:tool-fixture:applied";
186
+ const visibility = isUserVisibleEvent ? "user-visible" : "client-state";
187
+ const envelopeContext = {
188
+ hookId: this.clientId,
189
+ ...typeof data?.threadId === "string" ? { threadId: data.threadId } : {},
190
+ ...typeof data?.runId === "string" ? { runId: data.runId } : {},
191
+ ...typeof data?.streamId === "string" ? { streamId: data.streamId } : {},
192
+ ...typeof data?.messageId === "string" ? { messageId: data.messageId } : {},
193
+ ...typeof data?.toolCallId === "string" ? { toolCallId: data.toolCallId } : {}
194
+ };
195
+ if (includesClientContext) {
196
+ const envelope = createAIDevtoolsEventEnvelope({
197
+ eventType: eventName,
198
+ clientId: this.clientId,
199
+ ...envelopeContext,
200
+ source: "client",
201
+ visibility,
202
+ timestamp
203
+ });
204
+ aiEventClient.emit(eventName, {
205
+ ...data,
206
+ ...envelope
207
+ });
208
+ } else {
209
+ const envelope = createAIDevtoolsEventEnvelope({
210
+ eventType: eventName,
211
+ source: "client",
212
+ visibility: "client-state",
213
+ timestamp
214
+ });
215
+ aiEventClient.emit(eventName, {
216
+ ...data,
217
+ ...envelope
218
+ });
219
+ }
220
+ }
221
+ };
222
+ //#endregion
223
+ export { ChatClientEventEmitter, DefaultChatClientEventEmitter };
224
+
225
+ //# sourceMappingURL=events.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sources":["../../src/events.ts"],"sourcesContent":["import {\n aiEventClient,\n createAIDevtoolsEventEnvelope,\n} from '@tanstack/ai-event-client'\nimport type { ContentPart } from '@tanstack/ai/client'\nimport type { UIMessage } from './types'\n\nexport interface ChatClientRunEventContext {\n threadId: string\n runId: string\n toolCallId?: string\n}\n\nexport interface ChatClientEventContext {\n threadId?: string\n runId?: string\n toolCallId?: string\n}\n\nexport interface ChatClientToolFixtureAppliedEvent {\n hookId: string\n threadId: string\n toolName: string\n input: unknown\n output: unknown\n execute?: boolean\n message?: {\n id: string\n role: 'system' | 'user' | 'assistant'\n parts: Array<unknown>\n createdAt?: number | string\n }\n messageId: string\n toolCallId: string\n runId?: string\n errorText?: string\n}\n\nexport interface ChatClientStructuredOutputEvent {\n status: 'streaming' | 'complete' | 'error'\n raw?: string\n partial?: unknown\n data?: unknown\n reasoning?: string\n errorMessage?: string\n delta?: string\n}\n\nexport type ChatClientStructuredOutputEventName =\n | 'structured-output:started'\n | 'structured-output:updated'\n | 'structured-output:completed'\n | 'structured-output:errored'\n\n/**\n * Abstract base class for ChatClient event emission\n */\nexport abstract class ChatClientEventEmitter {\n protected clientId: string\n\n constructor(clientId: string) {\n this.clientId = clientId\n }\n\n /**\n * Protected abstract method for emitting events\n * Implementations should handle adding clientId and timestamp\n */\n protected abstract emitEvent(\n eventName: string,\n data?: Record<string, unknown>,\n ): void\n\n /**\n * Emit client created event\n */\n clientCreated(initialMessageCount: number): void {\n this.emitEvent('client:created', {\n initialMessageCount,\n })\n }\n\n /**\n * Emit loading state changed event\n */\n loadingChanged(isLoading: boolean): void {\n this.emitEvent('client:loading:changed', { isLoading })\n }\n\n /**\n * Emit error state changed event\n */\n errorChanged(error: string | null): void {\n this.emitEvent('client:error:changed', {\n error,\n })\n }\n\n /**\n * Emit text update events (combines processor and client events)\n */\n textUpdated(\n streamId: string,\n messageId: string,\n content: string,\n context?: ChatClientRunEventContext,\n ): void {\n this.emitEvent('text:chunk:content', {\n streamId,\n messageId,\n content,\n ...context,\n })\n }\n\n /**\n * Emit tool call state change events (combines processor and client events)\n */\n toolCallStateChanged(\n streamId: string,\n messageId: string,\n toolCallId: string,\n toolName: string,\n state: string,\n args: string,\n context?: ChatClientRunEventContext,\n ): void {\n this.emitEvent('tools:call:updated', {\n streamId,\n messageId,\n toolCallId,\n toolName,\n state,\n arguments: args,\n ...context,\n })\n }\n\n /**\n * Emit tool result state change event\n */\n /**\n * Emit thinking update event\n */\n thinkingUpdated(\n streamId: string,\n messageId: string,\n content: string,\n delta?: string,\n context?: ChatClientRunEventContext,\n ): void {\n this.emitEvent('text:chunk:thinking', {\n streamId,\n messageId,\n content,\n delta,\n ...context,\n })\n }\n\n structuredOutputChanged(\n eventName: ChatClientStructuredOutputEventName,\n streamId: string,\n messageId: string,\n output: ChatClientStructuredOutputEvent,\n context?: ChatClientRunEventContext,\n ): void {\n this.emitEvent(eventName, {\n streamId,\n messageId,\n ...output,\n ...context,\n })\n }\n\n /**\n * Emit approval requested event\n */\n approvalRequested(\n streamId: string,\n messageId: string,\n toolCallId: string,\n toolName: string,\n input: unknown,\n approvalId: string,\n context?: ChatClientRunEventContext,\n ): void {\n this.emitEvent('tools:approval:requested', {\n streamId,\n messageId,\n toolCallId,\n toolName,\n input,\n approvalId,\n ...context,\n })\n }\n\n /**\n * Emit message appended event\n */\n messageAppended(\n uiMessage: UIMessage,\n streamId?: string,\n context?: ChatClientEventContext,\n ): void {\n const content = uiMessage.parts\n .filter((part) => part.type === 'text')\n .map((part) => part.content)\n .join(' ')\n\n this.emitEvent('text:message:created', {\n streamId,\n messageId: uiMessage.id,\n role: uiMessage.role,\n content,\n parts: uiMessage.parts,\n ...context,\n })\n }\n\n /**\n * Emit message sent event.\n * Supports both simple string content and multimodal content arrays.\n *\n * @param messageId - The ID of the sent message\n * @param content - The message content (string or array of ContentPart for multimodal)\n */\n messageSent(messageId: string, content: string | Array<ContentPart>): void {\n // For text content, extract it; for multimodal, provide the array\n const textContent =\n typeof content === 'string'\n ? content\n : content\n .filter((part) => part.type === 'text')\n .map((part) => (part as { type: 'text'; content: string }).content)\n .join('')\n\n this.emitEvent('text:message:created', {\n messageId,\n role: 'user',\n content: textContent,\n // Include full content for multimodal messages\n ...(Array.isArray(content) && { parts: content }),\n })\n\n this.emitEvent('text:message:user', {\n messageId,\n role: 'user',\n content: textContent,\n // Include full content for multimodal messages\n ...(Array.isArray(content) && { parts: content }),\n })\n }\n\n /**\n * Emit reloaded event\n */\n reloaded(fromMessageIndex: number): void {\n this.emitEvent('client:reloaded', {\n fromMessageIndex,\n })\n }\n /**\n * Emit stopped event\n */\n stopped(): void {\n this.emitEvent('client:stopped')\n }\n\n /**\n * Emit messages cleared event\n */\n messagesCleared(): void {\n this.emitEvent('client:messages:cleared')\n }\n\n /**\n * Emit tool result added event\n */\n toolResultAdded(\n toolCallId: string,\n toolName: string,\n output: unknown,\n state: string,\n context?: ChatClientEventContext,\n ): void {\n this.emitEvent('tools:result:added', {\n toolCallId,\n toolName,\n output,\n state,\n ...context,\n })\n }\n\n /**\n * Emit tool approval responded event\n */\n toolApprovalResponded(\n approvalId: string,\n toolCallId: string,\n approved: boolean,\n context?: ChatClientRunEventContext,\n ): void {\n this.emitEvent('tools:approval:responded', {\n approvalId,\n toolCallId,\n approved,\n ...context,\n })\n }\n\n /**\n * Emit tool fixture applied event.\n */\n toolFixtureApplied(fixture: ChatClientToolFixtureAppliedEvent): void {\n this.emitEvent('devtools:tool-fixture:applied', { ...fixture })\n }\n}\n\n/**\n * Default implementation of ChatClientEventEmitter\n */\nexport class DefaultChatClientEventEmitter extends ChatClientEventEmitter {\n /**\n * Emit an event with automatic clientId and timestamp for client/tool events\n */\n protected emitEvent(eventName: string, data?: Record<string, any>): void {\n const timestamp = Date.now()\n const isUserVisibleEvent =\n eventName.startsWith('text:') ||\n eventName.startsWith('tools:') ||\n eventName.startsWith('structured-output:') ||\n eventName === 'devtools:tool-fixture:applied'\n const includesClientContext =\n eventName.startsWith('client:') ||\n eventName.startsWith('tools:') ||\n eventName.startsWith('text:') ||\n eventName.startsWith('structured-output:') ||\n eventName === 'devtools:tool-fixture:applied'\n const visibility = isUserVisibleEvent ? 'user-visible' : 'client-state'\n const envelopeContext = {\n hookId: this.clientId,\n ...(typeof data?.threadId === 'string'\n ? { threadId: data.threadId }\n : {}),\n ...(typeof data?.runId === 'string' ? { runId: data.runId } : {}),\n ...(typeof data?.streamId === 'string'\n ? { streamId: data.streamId }\n : {}),\n ...(typeof data?.messageId === 'string'\n ? { messageId: data.messageId }\n : {}),\n ...(typeof data?.toolCallId === 'string'\n ? { toolCallId: data.toolCallId }\n : {}),\n }\n\n // For client:* and tool:* events, automatically add clientId and timestamp\n if (includesClientContext) {\n const envelope = createAIDevtoolsEventEnvelope({\n eventType: eventName,\n clientId: this.clientId,\n ...envelopeContext,\n source: 'client',\n visibility,\n timestamp,\n })\n aiEventClient.emit(eventName as any, {\n ...data,\n ...envelope,\n })\n } else {\n const envelope = createAIDevtoolsEventEnvelope({\n eventType: eventName,\n source: 'client',\n visibility: 'client-state',\n timestamp,\n })\n // For other events, just add timestamp\n aiEventClient.emit(eventName as any, {\n ...data,\n ...envelope,\n })\n }\n }\n}\n"],"names":[],"mappings":";AAyDO,MAAe,uBAAuB;AAAA,EACjC;AAAA,EAEV,YAAY,UAAkB;AAC5B,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAcA,cAAc,qBAAmC;AAC/C,SAAK,UAAU,kBAAkB;AAAA,MAC/B;AAAA,IAAA,CACD;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,WAA0B;AACvC,SAAK,UAAU,0BAA0B,EAAE,UAAA,CAAW;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,OAA4B;AACvC,SAAK,UAAU,wBAAwB;AAAA,MACrC;AAAA,IAAA,CACD;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,YACE,UACA,WACA,SACA,SACM;AACN,SAAK,UAAU,sBAAsB;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IAAA,CACJ;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,qBACE,UACA,WACA,YACA,UACA,OACA,MACA,SACM;AACN,SAAK,UAAU,sBAAsB;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX,GAAG;AAAA,IAAA,CACJ;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBACE,UACA,WACA,SACA,OACA,SACM;AACN,SAAK,UAAU,uBAAuB;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IAAA,CACJ;AAAA,EACH;AAAA,EAEA,wBACE,WACA,UACA,WACA,QACA,SACM;AACN,SAAK,UAAU,WAAW;AAAA,MACxB;AAAA,MACA;AAAA,MACA,GAAG;AAAA,MACH,GAAG;AAAA,IAAA,CACJ;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,kBACE,UACA,WACA,YACA,UACA,OACA,YACA,SACM;AACN,SAAK,UAAU,4BAA4B;AAAA,MACzC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IAAA,CACJ;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,gBACE,WACA,UACA,SACM;AACN,UAAM,UAAU,UAAU,MACvB,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM,EACrC,IAAI,CAAC,SAAS,KAAK,OAAO,EAC1B,KAAK,GAAG;AAEX,SAAK,UAAU,wBAAwB;AAAA,MACrC;AAAA,MACA,WAAW,UAAU;AAAA,MACrB,MAAM,UAAU;AAAA,MAChB;AAAA,MACA,OAAO,UAAU;AAAA,MACjB,GAAG;AAAA,IAAA,CACJ;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YAAY,WAAmB,SAA4C;AAEzE,UAAM,cACJ,OAAO,YAAY,WACf,UACA,QACG,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM,EACrC,IAAI,CAAC,SAAU,KAA2C,OAAO,EACjE,KAAK,EAAE;AAEhB,SAAK,UAAU,wBAAwB;AAAA,MACrC;AAAA,MACA,MAAM;AAAA,MACN,SAAS;AAAA;AAAA,MAET,GAAI,MAAM,QAAQ,OAAO,KAAK,EAAE,OAAO,QAAA;AAAA,IAAQ,CAChD;AAED,SAAK,UAAU,qBAAqB;AAAA,MAClC;AAAA,MACA,MAAM;AAAA,MACN,SAAS;AAAA;AAAA,MAET,GAAI,MAAM,QAAQ,OAAO,KAAK,EAAE,OAAO,QAAA;AAAA,IAAQ,CAChD;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,kBAAgC;AACvC,SAAK,UAAU,mBAAmB;AAAA,MAChC;AAAA,IAAA,CACD;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAIA,UAAgB;AACd,SAAK,UAAU,gBAAgB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAwB;AACtB,SAAK,UAAU,yBAAyB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,gBACE,YACA,UACA,QACA,OACA,SACM;AACN,SAAK,UAAU,sBAAsB;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IAAA,CACJ;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,sBACE,YACA,YACA,UACA,SACM;AACN,SAAK,UAAU,4BAA4B;AAAA,MACzC;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IAAA,CACJ;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,SAAkD;AACnE,SAAK,UAAU,iCAAiC,EAAE,GAAG,SAAS;AAAA,EAChE;AACF;AAKO,MAAM,sCAAsC,uBAAuB;AAAA;AAAA;AAAA;AAAA,EAI9D,UAAU,WAAmB,MAAkC;AACvE,UAAM,YAAY,KAAK,IAAA;AACvB,UAAM,qBACJ,UAAU,WAAW,OAAO,KAC5B,UAAU,WAAW,QAAQ,KAC7B,UAAU,WAAW,oBAAoB,KACzC,cAAc;AAChB,UAAM,wBACJ,UAAU,WAAW,SAAS,KAC9B,UAAU,WAAW,QAAQ,KAC7B,UAAU,WAAW,OAAO,KAC5B,UAAU,WAAW,oBAAoB,KACzC,cAAc;AAChB,UAAM,aAAa,qBAAqB,iBAAiB;AACzD,UAAM,kBAAkB;AAAA,MACtB,QAAQ,KAAK;AAAA,MACb,GAAI,OAAO,MAAM,aAAa,WAC1B,EAAE,UAAU,KAAK,SAAA,IACjB,CAAA;AAAA,MACJ,GAAI,OAAO,MAAM,UAAU,WAAW,EAAE,OAAO,KAAK,MAAA,IAAU,CAAA;AAAA,MAC9D,GAAI,OAAO,MAAM,aAAa,WAC1B,EAAE,UAAU,KAAK,SAAA,IACjB,CAAA;AAAA,MACJ,GAAI,OAAO,MAAM,cAAc,WAC3B,EAAE,WAAW,KAAK,UAAA,IAClB,CAAA;AAAA,MACJ,GAAI,OAAO,MAAM,eAAe,WAC5B,EAAE,YAAY,KAAK,eACnB,CAAA;AAAA,IAAC;AAIP,QAAI,uBAAuB;AACzB,YAAM,WAAW,8BAA8B;AAAA,QAC7C,WAAW;AAAA,QACX,UAAU,KAAK;AAAA,QACf,GAAG;AAAA,QACH,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,MAAA,CACD;AACD,oBAAc,KAAK,WAAkB;AAAA,QACnC,GAAG;AAAA,QACH,GAAG;AAAA,MAAA,CACJ;AAAA,IACH,OAAO;AACL,YAAM,WAAW,8BAA8B;AAAA,QAC7C,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ;AAAA,MAAA,CACD;AAED,oBAAc,KAAK,WAAkB;AAAA,QACnC,GAAG;AAAA,QACH,GAAG;AAAA,MAAA,CACJ;AAAA,IACH;AAAA,EACF;AACF;"}
1
+ {"version":3,"file":"events.js","names":[],"sources":["../../src/events.ts"],"sourcesContent":["import {\n aiEventClient,\n createAIDevtoolsEventEnvelope,\n} from '@tanstack/ai-event-client'\nimport type { ContentPart } from '@tanstack/ai/client'\nimport type { UIMessage } from './types'\n\nexport interface ChatClientRunEventContext {\n threadId: string\n runId: string\n toolCallId?: string\n}\n\nexport interface ChatClientEventContext {\n threadId?: string\n runId?: string\n toolCallId?: string\n}\n\nexport interface ChatClientToolFixtureAppliedEvent {\n hookId: string\n threadId: string\n toolName: string\n input: unknown\n output: unknown\n execute?: boolean\n message?: {\n id: string\n role: 'system' | 'user' | 'assistant'\n parts: Array<unknown>\n createdAt?: number | string\n }\n messageId: string\n toolCallId: string\n runId?: string\n errorText?: string\n}\n\nexport interface ChatClientStructuredOutputEvent {\n status: 'streaming' | 'complete' | 'error'\n raw?: string\n partial?: unknown\n data?: unknown\n reasoning?: string\n errorMessage?: string\n delta?: string\n}\n\nexport type ChatClientStructuredOutputEventName =\n | 'structured-output:started'\n | 'structured-output:updated'\n | 'structured-output:completed'\n | 'structured-output:errored'\n\n/**\n * Abstract base class for ChatClient event emission\n */\nexport abstract class ChatClientEventEmitter {\n protected clientId: string\n\n constructor(clientId: string) {\n this.clientId = clientId\n }\n\n /**\n * Protected abstract method for emitting events\n * Implementations should handle adding clientId and timestamp\n */\n protected abstract emitEvent(\n eventName: string,\n data?: Record<string, unknown>,\n ): void\n\n /**\n * Emit client created event\n */\n clientCreated(initialMessageCount: number): void {\n this.emitEvent('client:created', {\n initialMessageCount,\n })\n }\n\n /**\n * Emit loading state changed event\n */\n loadingChanged(isLoading: boolean): void {\n this.emitEvent('client:loading:changed', { isLoading })\n }\n\n /**\n * Emit error state changed event\n */\n errorChanged(error: string | null): void {\n this.emitEvent('client:error:changed', {\n error,\n })\n }\n\n /**\n * Emit text update events (combines processor and client events)\n */\n textUpdated(\n streamId: string,\n messageId: string,\n content: string,\n context?: ChatClientRunEventContext,\n ): void {\n this.emitEvent('text:chunk:content', {\n streamId,\n messageId,\n content,\n ...context,\n })\n }\n\n /**\n * Emit tool call state change events (combines processor and client events)\n */\n toolCallStateChanged(\n streamId: string,\n messageId: string,\n toolCallId: string,\n toolName: string,\n state: string,\n args: string,\n context?: ChatClientRunEventContext,\n ): void {\n this.emitEvent('tools:call:updated', {\n streamId,\n messageId,\n toolCallId,\n toolName,\n state,\n arguments: args,\n ...context,\n })\n }\n\n /**\n * Emit tool result state change event\n */\n /**\n * Emit thinking update event\n */\n thinkingUpdated(\n streamId: string,\n messageId: string,\n content: string,\n delta?: string,\n context?: ChatClientRunEventContext,\n ): void {\n this.emitEvent('text:chunk:thinking', {\n streamId,\n messageId,\n content,\n delta,\n ...context,\n })\n }\n\n structuredOutputChanged(\n eventName: ChatClientStructuredOutputEventName,\n streamId: string,\n messageId: string,\n output: ChatClientStructuredOutputEvent,\n context?: ChatClientRunEventContext,\n ): void {\n this.emitEvent(eventName, {\n streamId,\n messageId,\n ...output,\n ...context,\n })\n }\n\n /**\n * Emit approval requested event\n */\n approvalRequested(\n streamId: string,\n messageId: string,\n toolCallId: string,\n toolName: string,\n input: unknown,\n approvalId: string,\n context?: ChatClientRunEventContext,\n ): void {\n this.emitEvent('tools:approval:requested', {\n streamId,\n messageId,\n toolCallId,\n toolName,\n input,\n approvalId,\n ...context,\n })\n }\n\n /**\n * Emit message appended event\n */\n messageAppended(\n uiMessage: UIMessage,\n streamId?: string,\n context?: ChatClientEventContext,\n ): void {\n const content = uiMessage.parts\n .filter((part) => part.type === 'text')\n .map((part) => part.content)\n .join(' ')\n\n this.emitEvent('text:message:created', {\n streamId,\n messageId: uiMessage.id,\n role: uiMessage.role,\n content,\n parts: uiMessage.parts,\n ...context,\n })\n }\n\n /**\n * Emit message sent event.\n * Supports both simple string content and multimodal content arrays.\n *\n * @param messageId - The ID of the sent message\n * @param content - The message content (string or array of ContentPart for multimodal)\n */\n messageSent(messageId: string, content: string | Array<ContentPart>): void {\n // For text content, extract it; for multimodal, provide the array\n const textContent =\n typeof content === 'string'\n ? content\n : content\n .filter((part) => part.type === 'text')\n .map((part) => (part as { type: 'text'; content: string }).content)\n .join('')\n\n this.emitEvent('text:message:created', {\n messageId,\n role: 'user',\n content: textContent,\n // Include full content for multimodal messages\n ...(Array.isArray(content) && { parts: content }),\n })\n\n this.emitEvent('text:message:user', {\n messageId,\n role: 'user',\n content: textContent,\n // Include full content for multimodal messages\n ...(Array.isArray(content) && { parts: content }),\n })\n }\n\n /**\n * Emit reloaded event\n */\n reloaded(fromMessageIndex: number): void {\n this.emitEvent('client:reloaded', {\n fromMessageIndex,\n })\n }\n /**\n * Emit stopped event\n */\n stopped(): void {\n this.emitEvent('client:stopped')\n }\n\n /**\n * Emit messages cleared event\n */\n messagesCleared(): void {\n this.emitEvent('client:messages:cleared')\n }\n\n /**\n * Emit tool result added event\n */\n toolResultAdded(\n toolCallId: string,\n toolName: string,\n output: unknown,\n state: string,\n context?: ChatClientEventContext,\n ): void {\n this.emitEvent('tools:result:added', {\n toolCallId,\n toolName,\n output,\n state,\n ...context,\n })\n }\n\n /**\n * Emit tool approval responded event\n */\n toolApprovalResponded(\n approvalId: string,\n toolCallId: string,\n approved: boolean,\n context?: ChatClientRunEventContext,\n ): void {\n this.emitEvent('tools:approval:responded', {\n approvalId,\n toolCallId,\n approved,\n ...context,\n })\n }\n\n /**\n * Emit tool fixture applied event.\n */\n toolFixtureApplied(fixture: ChatClientToolFixtureAppliedEvent): void {\n this.emitEvent('devtools:tool-fixture:applied', { ...fixture })\n }\n}\n\n/**\n * Default implementation of ChatClientEventEmitter\n */\nexport class DefaultChatClientEventEmitter extends ChatClientEventEmitter {\n /**\n * Emit an event with automatic clientId and timestamp for client/tool events\n */\n protected emitEvent(eventName: string, data?: Record<string, any>): void {\n const timestamp = Date.now()\n const isUserVisibleEvent =\n eventName.startsWith('text:') ||\n eventName.startsWith('tools:') ||\n eventName.startsWith('structured-output:') ||\n eventName === 'devtools:tool-fixture:applied'\n const includesClientContext =\n eventName.startsWith('client:') ||\n eventName.startsWith('tools:') ||\n eventName.startsWith('text:') ||\n eventName.startsWith('structured-output:') ||\n eventName === 'devtools:tool-fixture:applied'\n const visibility = isUserVisibleEvent ? 'user-visible' : 'client-state'\n const envelopeContext = {\n hookId: this.clientId,\n ...(typeof data?.threadId === 'string'\n ? { threadId: data.threadId }\n : {}),\n ...(typeof data?.runId === 'string' ? { runId: data.runId } : {}),\n ...(typeof data?.streamId === 'string'\n ? { streamId: data.streamId }\n : {}),\n ...(typeof data?.messageId === 'string'\n ? { messageId: data.messageId }\n : {}),\n ...(typeof data?.toolCallId === 'string'\n ? { toolCallId: data.toolCallId }\n : {}),\n }\n\n // For client:* and tool:* events, automatically add clientId and timestamp\n if (includesClientContext) {\n const envelope = createAIDevtoolsEventEnvelope({\n eventType: eventName,\n clientId: this.clientId,\n ...envelopeContext,\n source: 'client',\n visibility,\n timestamp,\n })\n aiEventClient.emit(eventName as any, {\n ...data,\n ...envelope,\n })\n } else {\n const envelope = createAIDevtoolsEventEnvelope({\n eventType: eventName,\n source: 'client',\n visibility: 'client-state',\n timestamp,\n })\n // For other events, just add timestamp\n aiEventClient.emit(eventName as any, {\n ...data,\n ...envelope,\n })\n }\n }\n}\n"],"mappings":"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"}