@tanstack/ai-devtools-core 0.3.6 → 0.3.8

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 (86) hide show
  1. package/dist/Shell/GHXECDJV.js +5056 -0
  2. package/dist/Shell/MUFU35SY.js +4242 -0
  3. package/dist/dev.js +11 -0
  4. package/dist/{esm/index.d.ts → index.d.ts} +7 -5
  5. package/dist/index.js +11 -0
  6. package/dist/production/Shell/GHXECDJV.js +5056 -0
  7. package/dist/production/Shell/MUFU35SY.js +4242 -0
  8. package/dist/production/dev.js +8 -0
  9. package/dist/production/index.d.ts +12 -0
  10. package/dist/production/index.js +8 -0
  11. package/dist/production/server.js +8 -0
  12. package/dist/server.js +11 -0
  13. package/package.json +45 -11
  14. package/src/{core.tsx → core.ts} +4 -5
  15. package/dist/esm/components/ConversationDetails.d.ts +0 -2
  16. package/dist/esm/components/ConversationDetails.js +0 -192
  17. package/dist/esm/components/ConversationDetails.js.map +0 -1
  18. package/dist/esm/components/ConversationsList.d.ts +0 -2
  19. package/dist/esm/components/ConversationsList.js +0 -30
  20. package/dist/esm/components/ConversationsList.js.map +0 -1
  21. package/dist/esm/components/Shell.d.ts +0 -1
  22. package/dist/esm/components/Shell.js +0 -94
  23. package/dist/esm/components/Shell.js.map +0 -1
  24. package/dist/esm/components/conversation/ActivityEventsTab.d.ts +0 -8
  25. package/dist/esm/components/conversation/ActivityEventsTab.js +0 -72
  26. package/dist/esm/components/conversation/ActivityEventsTab.js.map +0 -1
  27. package/dist/esm/components/conversation/ChunkBadges.d.ts +0 -7
  28. package/dist/esm/components/conversation/ChunkBadges.js +0 -54
  29. package/dist/esm/components/conversation/ChunkBadges.js.map +0 -1
  30. package/dist/esm/components/conversation/ChunkItem.d.ts +0 -9
  31. package/dist/esm/components/conversation/ChunkItem.js +0 -247
  32. package/dist/esm/components/conversation/ChunkItem.js.map +0 -1
  33. package/dist/esm/components/conversation/ChunksCollapsible.d.ts +0 -7
  34. package/dist/esm/components/conversation/ChunksCollapsible.js +0 -77
  35. package/dist/esm/components/conversation/ChunksCollapsible.js.map +0 -1
  36. package/dist/esm/components/conversation/ChunksTab.d.ts +0 -8
  37. package/dist/esm/components/conversation/ChunksTab.js +0 -87
  38. package/dist/esm/components/conversation/ChunksTab.js.map +0 -1
  39. package/dist/esm/components/conversation/ConversationHeader.d.ts +0 -7
  40. package/dist/esm/components/conversation/ConversationHeader.js +0 -230
  41. package/dist/esm/components/conversation/ConversationHeader.js.map +0 -1
  42. package/dist/esm/components/conversation/ConversationTabs.d.ts +0 -10
  43. package/dist/esm/components/conversation/ConversationTabs.js +0 -176
  44. package/dist/esm/components/conversation/ConversationTabs.js.map +0 -1
  45. package/dist/esm/components/conversation/MessageCard.d.ts +0 -7
  46. package/dist/esm/components/conversation/MessageCard.js +0 -207
  47. package/dist/esm/components/conversation/MessageCard.js.map +0 -1
  48. package/dist/esm/components/conversation/MessageGroup.d.ts +0 -15
  49. package/dist/esm/components/conversation/MessageGroup.js +0 -119
  50. package/dist/esm/components/conversation/MessageGroup.js.map +0 -1
  51. package/dist/esm/components/conversation/MessagesTab.d.ts +0 -7
  52. package/dist/esm/components/conversation/MessagesTab.js +0 -37
  53. package/dist/esm/components/conversation/MessagesTab.js.map +0 -1
  54. package/dist/esm/components/conversation/SummariesTab.d.ts +0 -7
  55. package/dist/esm/components/conversation/SummariesTab.js +0 -110
  56. package/dist/esm/components/conversation/SummariesTab.js.map +0 -1
  57. package/dist/esm/components/conversation/ToolCallDisplay.d.ts +0 -7
  58. package/dist/esm/components/conversation/ToolCallDisplay.js +0 -123
  59. package/dist/esm/components/conversation/ToolCallDisplay.js.map +0 -1
  60. package/dist/esm/components/conversation/index.d.ts +0 -7
  61. package/dist/esm/components/list/ConversationRow.d.ts +0 -7
  62. package/dist/esm/components/list/ConversationRow.js +0 -122
  63. package/dist/esm/components/list/ConversationRow.js.map +0 -1
  64. package/dist/esm/components/list/index.d.ts +0 -1
  65. package/dist/esm/components/utils/format.d.ts +0 -6
  66. package/dist/esm/components/utils/format.js +0 -68
  67. package/dist/esm/components/utils/format.js.map +0 -1
  68. package/dist/esm/components/utils/index.d.ts +0 -1
  69. package/dist/esm/core.d.ts +0 -22
  70. package/dist/esm/core.js +0 -9
  71. package/dist/esm/core.js.map +0 -1
  72. package/dist/esm/index.js +0 -6
  73. package/dist/esm/index.js.map +0 -1
  74. package/dist/esm/production.d.ts +0 -2
  75. package/dist/esm/production.js +0 -5
  76. package/dist/esm/production.js.map +0 -1
  77. package/dist/esm/store/ai-context.d.ts +0 -135
  78. package/dist/esm/store/ai-context.js +0 -1238
  79. package/dist/esm/store/ai-context.js.map +0 -1
  80. package/dist/esm/store/ai-store.d.ts +0 -1
  81. package/dist/esm/styles/tokens.d.ts +0 -298
  82. package/dist/esm/styles/tokens.js +0 -107
  83. package/dist/esm/styles/tokens.js.map +0 -1
  84. package/dist/esm/styles/use-styles.d.ts +0 -233
  85. package/dist/esm/styles/use-styles.js +0 -1602
  86. package/dist/esm/styles/use-styles.js.map +0 -1
@@ -1,1238 +0,0 @@
1
- import { createComponent } from "solid-js/web";
2
- import { onMount, onCleanup, createContext, useContext, batch } from "solid-js";
3
- import { createStore, produce } from "solid-js/store";
4
- import { aiEventClient } from "@tanstack/ai/event-client";
5
- const AIContext = createContext();
6
- function useAIStore() {
7
- const context = useContext(AIContext);
8
- if (!context) {
9
- throw new Error("useAIStore must be used within an AIProvider");
10
- }
11
- return context;
12
- }
13
- const AIProvider = (props) => {
14
- const [state, setState] = createStore({
15
- conversations: {},
16
- activeConversationId: null
17
- });
18
- const streamToConversation = /* @__PURE__ */ new Map();
19
- const requestToConversation = /* @__PURE__ */ new Map();
20
- const pendingConversationChunks = /* @__PURE__ */ new Map();
21
- const pendingMessageChunks = /* @__PURE__ */ new Map();
22
- let batchScheduled = false;
23
- function scheduleBatchFlush() {
24
- if (batchScheduled) return;
25
- batchScheduled = true;
26
- queueMicrotask(flushPendingChunks);
27
- }
28
- function isMergeableChunkType(type) {
29
- return type === "content" || type === "thinking";
30
- }
31
- function mergeChunks(existing, pending) {
32
- for (const chunk of pending) {
33
- const lastChunk = existing[existing.length - 1];
34
- if (lastChunk && lastChunk.type === chunk.type && isMergeableChunkType(chunk.type) && lastChunk.messageId === chunk.messageId) {
35
- lastChunk.content = chunk.content || lastChunk.content;
36
- lastChunk.delta = chunk.delta;
37
- lastChunk.chunkCount += chunk.chunkCount;
38
- } else {
39
- existing.push(chunk);
40
- }
41
- }
42
- }
43
- function flushPendingChunks() {
44
- batchScheduled = false;
45
- batch(() => {
46
- for (const [conversationId, {
47
- chunks,
48
- newChunkCount
49
- }] of pendingConversationChunks) {
50
- const conv = state.conversations[conversationId];
51
- if (conv) {
52
- setState("conversations", conversationId, "chunks", produce((arr) => {
53
- mergeChunks(arr, chunks);
54
- }));
55
- }
56
- }
57
- pendingConversationChunks.clear();
58
- for (const [conversationId, messageMap] of pendingMessageChunks) {
59
- const conv = state.conversations[conversationId];
60
- if (!conv) continue;
61
- for (const [messageIndex, {
62
- chunks,
63
- newChunkCount
64
- }] of messageMap) {
65
- const message = conv.messages[messageIndex];
66
- if (message) {
67
- setState("conversations", conversationId, "messages", messageIndex, "chunks", produce((arr) => {
68
- if (!arr) {
69
- return chunks;
70
- }
71
- mergeChunks(arr, chunks);
72
- return arr;
73
- }));
74
- const currentTotal = message.totalChunkCount || 0;
75
- setState("conversations", conversationId, "messages", messageIndex, "totalChunkCount", currentTotal + newChunkCount);
76
- }
77
- }
78
- }
79
- pendingMessageChunks.clear();
80
- });
81
- }
82
- function queueChunk(conversationId, chunk) {
83
- if (!pendingConversationChunks.has(conversationId)) {
84
- pendingConversationChunks.set(conversationId, {
85
- chunks: [],
86
- newChunkCount: 0
87
- });
88
- }
89
- const pending = pendingConversationChunks.get(conversationId);
90
- const lastPending = pending.chunks[pending.chunks.length - 1];
91
- if (lastPending && lastPending.type === chunk.type && isMergeableChunkType(chunk.type) && lastPending.messageId === chunk.messageId) {
92
- lastPending.content = chunk.content || lastPending.content;
93
- lastPending.delta = chunk.delta;
94
- lastPending.chunkCount += chunk.chunkCount;
95
- } else {
96
- pending.chunks.push(chunk);
97
- }
98
- pending.newChunkCount += chunk.chunkCount;
99
- scheduleBatchFlush();
100
- }
101
- function queueMessageChunk(conversationId, messageIndex, chunk) {
102
- if (!pendingMessageChunks.has(conversationId)) {
103
- pendingMessageChunks.set(conversationId, /* @__PURE__ */ new Map());
104
- }
105
- const messageMap = pendingMessageChunks.get(conversationId);
106
- if (!messageMap.has(messageIndex)) {
107
- messageMap.set(messageIndex, {
108
- chunks: [],
109
- newChunkCount: 0
110
- });
111
- }
112
- const pending = messageMap.get(messageIndex);
113
- const lastPending = pending.chunks[pending.chunks.length - 1];
114
- if (lastPending && lastPending.type === chunk.type && isMergeableChunkType(chunk.type) && lastPending.messageId === chunk.messageId) {
115
- lastPending.content = chunk.content || lastPending.content;
116
- lastPending.delta = chunk.delta;
117
- lastPending.chunkCount += chunk.chunkCount;
118
- } else {
119
- pending.chunks.push(chunk);
120
- }
121
- pending.newChunkCount += chunk.chunkCount;
122
- scheduleBatchFlush();
123
- }
124
- function getOrCreateConversation(id, type, label) {
125
- if (!state.conversations[id]) {
126
- setState("conversations", id, {
127
- id,
128
- type,
129
- label,
130
- messages: [],
131
- chunks: [],
132
- imageEvents: [],
133
- speechEvents: [],
134
- transcriptionEvents: [],
135
- videoEvents: [],
136
- status: "active",
137
- startedAt: Date.now()
138
- });
139
- if (!state.activeConversationId) {
140
- setState("activeConversationId", id);
141
- }
142
- }
143
- }
144
- function addMessage(conversationId, message) {
145
- const conv = state.conversations[conversationId];
146
- if (!conv) return;
147
- setState("conversations", conversationId, "messages", conv.messages.length, message);
148
- }
149
- function addChunkToMessage(conversationId, chunk) {
150
- const conv = state.conversations[conversationId];
151
- if (!conv) return;
152
- if (chunk.messageId) {
153
- const messageIndex = conv.messages.findIndex((msg) => msg.id === chunk.messageId);
154
- if (messageIndex !== -1) {
155
- queueMessageChunk(conversationId, messageIndex, chunk);
156
- return;
157
- } else {
158
- const newMessage = {
159
- id: chunk.messageId,
160
- role: "assistant",
161
- content: "",
162
- timestamp: chunk.timestamp,
163
- model: conv.model,
164
- chunks: [chunk]
165
- };
166
- setState("conversations", conversationId, "messages", conv.messages.length, newMessage);
167
- return;
168
- }
169
- }
170
- for (let i = conv.messages.length - 1; i >= 0; i--) {
171
- const message = conv.messages[i];
172
- if (message && message.role === "assistant") {
173
- queueMessageChunk(conversationId, i, chunk);
174
- return;
175
- }
176
- }
177
- addChunk(conversationId, chunk);
178
- }
179
- function updateMessageUsage(conversationId, messageId, cumulativeUsage) {
180
- const conv = state.conversations[conversationId];
181
- if (!conv) return;
182
- let previousPromptTokens = 0;
183
- let previousCompletionTokens = 0;
184
- let targetMessageIndex = -1;
185
- if (messageId) {
186
- targetMessageIndex = conv.messages.findIndex((msg) => msg.id === messageId);
187
- } else {
188
- for (let i = conv.messages.length - 1; i >= 0; i--) {
189
- if (conv.messages[i]?.role === "assistant") {
190
- targetMessageIndex = i;
191
- break;
192
- }
193
- }
194
- }
195
- if (targetMessageIndex === -1) return;
196
- for (let i = 0; i < targetMessageIndex; i++) {
197
- const msg = conv.messages[i];
198
- if (msg?.role === "assistant" && msg.usage) {
199
- previousPromptTokens += msg.usage.promptTokens;
200
- previousCompletionTokens += msg.usage.completionTokens;
201
- }
202
- }
203
- const deltaUsage = {
204
- promptTokens: Math.max(0, cumulativeUsage.promptTokens - previousPromptTokens),
205
- completionTokens: Math.max(0, cumulativeUsage.completionTokens - previousCompletionTokens),
206
- totalTokens: 0
207
- };
208
- deltaUsage.totalTokens = deltaUsage.promptTokens + deltaUsage.completionTokens;
209
- setState("conversations", conversationId, "messages", targetMessageIndex, "usage", deltaUsage);
210
- }
211
- function clearAllConversations() {
212
- setState("conversations", {});
213
- setState("activeConversationId", null);
214
- streamToConversation.clear();
215
- requestToConversation.clear();
216
- pendingConversationChunks.clear();
217
- pendingMessageChunks.clear();
218
- }
219
- function selectConversation(id) {
220
- setState("activeConversationId", id);
221
- }
222
- function updateConversation(conversationId, updates) {
223
- if (!state.conversations[conversationId]) return;
224
- for (const [key, value] of Object.entries(updates)) {
225
- setState("conversations", conversationId, key, value);
226
- }
227
- }
228
- function updateMessage(conversationId, messageIndex, updates) {
229
- const conv = state.conversations[conversationId];
230
- if (!conv || !conv.messages[messageIndex]) return;
231
- for (const [key, value] of Object.entries(updates)) {
232
- setState("conversations", conversationId, "messages", messageIndex, key, value);
233
- }
234
- }
235
- function updateToolCall(conversationId, messageIndex, toolCallIndex, updates) {
236
- const conv = state.conversations[conversationId];
237
- if (!conv?.messages[messageIndex]?.toolCalls?.[toolCallIndex]) return;
238
- setState("conversations", conversationId, "messages", messageIndex, "toolCalls", toolCallIndex, produce((tc) => Object.assign(tc, updates)));
239
- }
240
- function setToolCalls(conversationId, messageIndex, toolCalls) {
241
- if (!state.conversations[conversationId]?.messages[messageIndex]) return;
242
- setState("conversations", conversationId, "messages", messageIndex, "toolCalls", toolCalls);
243
- }
244
- function addChunk(conversationId, chunk) {
245
- if (!state.conversations[conversationId]) return;
246
- queueChunk(conversationId, chunk);
247
- }
248
- function addActivityEvent(conversationId, activity, event) {
249
- if (!state.conversations[conversationId]) return;
250
- setState("conversations", conversationId, activity, produce((events) => {
251
- if (!events) return [event];
252
- events.push(event);
253
- return events;
254
- }));
255
- const activityFlagMap = {
256
- imageEvents: "hasImage",
257
- speechEvents: "hasSpeech",
258
- transcriptionEvents: "hasTranscription",
259
- videoEvents: "hasVideo"
260
- };
261
- setState("conversations", conversationId, activityFlagMap[activity], true);
262
- }
263
- function ensureMessageForChunk(conversationId, messageId, timestamp) {
264
- if (!messageId) return;
265
- const conv = state.conversations[conversationId];
266
- if (!conv || conv.type === "client") return;
267
- const existingMessage = conv.messages.find((m) => m.id === messageId);
268
- if (existingMessage) return;
269
- addMessage(conversationId, {
270
- id: messageId,
271
- role: "assistant",
272
- content: "",
273
- timestamp,
274
- source: "server"
275
- });
276
- }
277
- onMount(() => {
278
- const cleanupFns = [];
279
- cleanupFns.push(aiEventClient.on("client:created", (e) => {
280
- const clientId = e.payload.clientId;
281
- getOrCreateConversation(clientId, "client", `Client Chat (${clientId.substring(0, 8)})`);
282
- updateConversation(clientId, {
283
- model: void 0,
284
- provider: "Client"
285
- });
286
- }));
287
- cleanupFns.push(aiEventClient.on("text:message:created", (e) => {
288
- const {
289
- clientId,
290
- streamId,
291
- messageId,
292
- role,
293
- content,
294
- timestamp
295
- } = e.payload;
296
- const conversationId = clientId || (streamId ? streamToConversation.get(streamId) : void 0);
297
- if (!conversationId) return;
298
- if (role === "tool" || role === "system") return;
299
- if (!state.conversations[conversationId]) {
300
- getOrCreateConversation(conversationId, clientId ? "client" : "server", clientId ? `Client Chat (${conversationId.substring(0, 8)})` : `Server Chat (${conversationId.substring(0, 8)})`);
301
- }
302
- const conv = state.conversations[conversationId];
303
- if (!conv) return;
304
- const existingIndex = conv.messages.findIndex((message) => message.id === messageId);
305
- const parts = e.payload.parts?.map((part) => {
306
- if (part.type === "text") {
307
- return {
308
- type: "text",
309
- content: part.content
310
- };
311
- }
312
- if (part.type === "tool-call") {
313
- return {
314
- type: "tool-call",
315
- toolCallId: part.id,
316
- toolName: part.name,
317
- arguments: part.arguments,
318
- state: part.state,
319
- output: part.output,
320
- content: part.approval ? JSON.stringify(part.approval) : void 0
321
- };
322
- }
323
- if (part.type === "tool-result") {
324
- return {
325
- type: "tool-result",
326
- toolCallId: part.toolCallId,
327
- content: part.content,
328
- state: part.state,
329
- error: part.error
330
- };
331
- }
332
- if (part.type === "thinking") {
333
- return {
334
- type: "thinking",
335
- content: part.content
336
- };
337
- }
338
- if (part.type === "image" || part.type === "audio" || part.type === "video" || // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
339
- part.type === "document") {
340
- return {
341
- type: part.type,
342
- source: part.source,
343
- metadata: part.metadata
344
- };
345
- }
346
- return null;
347
- }).filter((part) => part !== null);
348
- const toolCalls = e.payload.toolCalls?.map((toolCall) => ({
349
- id: toolCall.id,
350
- name: toolCall.function.name,
351
- arguments: toolCall.function.arguments,
352
- state: "input-complete"
353
- }));
354
- const source = e.payload.source ?? (clientId ? "client" : "server");
355
- if (role === "user" && conv.type === "client" && source === "server") {
356
- return;
357
- }
358
- if (role === "assistant" && source === "client" && !content && (!toolCalls || toolCalls.length === 0)) {
359
- return;
360
- }
361
- const messagePayload = {
362
- id: messageId,
363
- role,
364
- content,
365
- timestamp,
366
- parts,
367
- toolCalls,
368
- source
369
- };
370
- if (existingIndex >= 0) {
371
- updateMessage(conversationId, existingIndex, messagePayload);
372
- } else {
373
- addMessage(conversationId, messagePayload);
374
- }
375
- updateConversation(conversationId, {
376
- status: "active",
377
- hasChat: true
378
- });
379
- }));
380
- cleanupFns.push(aiEventClient.on("text:message:user", (e) => {
381
- const {
382
- clientId,
383
- streamId,
384
- messageId,
385
- content,
386
- timestamp
387
- } = e.payload;
388
- const conversationId = clientId || (streamId ? streamToConversation.get(streamId) : void 0);
389
- if (!conversationId) return;
390
- const conv = state.conversations[conversationId];
391
- if (!conv) return;
392
- const existingIndex = conv.messages.findIndex((message) => message.id === messageId);
393
- if (existingIndex >= 0) return;
394
- const source = e.payload.source ?? (clientId ? "client" : "server");
395
- if (conv.type === "client" && source === "server") {
396
- return;
397
- }
398
- addMessage(conversationId, {
399
- id: messageId,
400
- role: "user",
401
- content,
402
- timestamp,
403
- source
404
- });
405
- }));
406
- cleanupFns.push(aiEventClient.on("client:loading:changed", (e) => {
407
- const clientId = e.payload.clientId;
408
- if (state.conversations[clientId]) {
409
- updateConversation(clientId, {
410
- status: e.payload.isLoading ? "active" : "completed"
411
- });
412
- }
413
- }));
414
- cleanupFns.push(aiEventClient.on("client:stopped", (e) => {
415
- const clientId = e.payload.clientId;
416
- if (state.conversations[clientId]) {
417
- updateConversation(clientId, {
418
- status: "completed",
419
- completedAt: e.payload.timestamp
420
- });
421
- }
422
- }));
423
- cleanupFns.push(aiEventClient.on("client:messages:cleared", (e) => {
424
- const clientId = e.payload.clientId;
425
- if (state.conversations[clientId]) {
426
- updateConversation(clientId, {
427
- messages: [],
428
- chunks: [],
429
- usage: void 0
430
- });
431
- }
432
- }));
433
- cleanupFns.push(aiEventClient.on("client:reloaded", (e) => {
434
- const clientId = e.payload.clientId;
435
- const conv = state.conversations[clientId];
436
- if (conv) {
437
- updateConversation(clientId, {
438
- messages: conv.messages.slice(0, e.payload.fromMessageIndex),
439
- status: "active"
440
- });
441
- }
442
- }));
443
- cleanupFns.push(aiEventClient.on("client:error:changed", (e) => {
444
- const clientId = e.payload.clientId;
445
- if (state.conversations[clientId] && e.payload.error) {
446
- updateConversation(clientId, {
447
- status: "error"
448
- });
449
- }
450
- }));
451
- cleanupFns.push(aiEventClient.on("tools:result:added", (e) => {
452
- const {
453
- clientId,
454
- toolCallId,
455
- toolName,
456
- output,
457
- state: resultState,
458
- timestamp
459
- } = e.payload;
460
- if (!clientId) return;
461
- if (!state.conversations[clientId]) return;
462
- const conv = state.conversations[clientId];
463
- const chunk = {
464
- id: `chunk-tool-result-${toolCallId}-${Date.now()}`,
465
- type: "tool_result",
466
- toolCallId,
467
- toolName,
468
- result: output,
469
- timestamp,
470
- chunkCount: 1,
471
- isClientTool: true
472
- };
473
- for (let messageIndex = conv.messages.length - 1; messageIndex >= 0; messageIndex--) {
474
- const message = conv.messages[messageIndex];
475
- if (!message?.toolCalls) continue;
476
- const toolCallIndex = message.toolCalls.findIndex((t) => t.id === toolCallId);
477
- if (toolCallIndex >= 0) {
478
- updateToolCall(clientId, messageIndex, toolCallIndex, {
479
- result: output,
480
- state: resultState === "output-error" ? "error" : "complete"
481
- });
482
- chunk.messageId = message.id;
483
- addChunkToMessage(clientId, chunk);
484
- return;
485
- }
486
- }
487
- addChunkToMessage(clientId, chunk);
488
- }));
489
- cleanupFns.push(aiEventClient.on("tools:approval:responded", (e) => {
490
- const {
491
- clientId,
492
- toolCallId,
493
- approved
494
- } = e.payload;
495
- if (!clientId) return;
496
- if (!state.conversations[clientId]) return;
497
- const conv = state.conversations[clientId];
498
- for (let messageIndex = conv.messages.length - 1; messageIndex >= 0; messageIndex--) {
499
- const message = conv.messages[messageIndex];
500
- if (!message?.toolCalls) continue;
501
- const toolCallIndex = message.toolCalls.findIndex((t) => t.id === toolCallId);
502
- if (toolCallIndex >= 0) {
503
- updateToolCall(clientId, messageIndex, toolCallIndex, {
504
- state: approved ? "approved" : "denied",
505
- approvalRequired: false
506
- });
507
- return;
508
- }
509
- }
510
- }));
511
- cleanupFns.push(aiEventClient.on("tools:call:updated", (e) => {
512
- const {
513
- clientId,
514
- streamId,
515
- messageId,
516
- toolCallId,
517
- toolName,
518
- state: toolCallState,
519
- arguments: args
520
- } = e.payload;
521
- const conversationId = clientId || (streamId ? streamToConversation.get(streamId) : void 0);
522
- if (!conversationId || !state.conversations[conversationId]) return;
523
- const conv = state.conversations[conversationId];
524
- const messageIndex = conv.messages.findIndex((m) => m.id === messageId);
525
- if (messageIndex === -1) return;
526
- const message = conv.messages[messageIndex];
527
- if (!message) return;
528
- const toolCalls = message.toolCalls || [];
529
- const existingToolIndex = toolCalls.findIndex((t) => t.id === toolCallId);
530
- const toolCall = {
531
- id: toolCallId,
532
- name: toolName,
533
- arguments: args,
534
- state: toolCallState
535
- };
536
- if (existingToolIndex >= 0) {
537
- updateToolCall(conversationId, messageIndex, existingToolIndex, toolCall);
538
- } else {
539
- setToolCalls(conversationId, messageIndex, [...toolCalls, toolCall]);
540
- }
541
- }));
542
- cleanupFns.push(aiEventClient.on("tools:input:available", (e) => {
543
- const {
544
- streamId,
545
- messageId,
546
- toolCallId,
547
- toolName,
548
- input,
549
- timestamp,
550
- clientId
551
- } = e.payload;
552
- const conversationId = clientId || (streamId ? streamToConversation.get(streamId) : void 0);
553
- if (!conversationId) return;
554
- const chunk = {
555
- id: `chunk-${Date.now()}-${Math.random()}`,
556
- type: "tool_call",
557
- messageId,
558
- toolCallId,
559
- toolName,
560
- arguments: JSON.stringify(input),
561
- timestamp,
562
- chunkCount: 1
563
- };
564
- const conv = state.conversations[conversationId];
565
- if (conv?.type === "client") {
566
- addChunkToMessage(conversationId, chunk);
567
- } else {
568
- addChunk(conversationId, chunk);
569
- }
570
- }));
571
- cleanupFns.push(aiEventClient.on("tools:call:completed", (e) => {
572
- const {
573
- streamId,
574
- toolCallId,
575
- toolName,
576
- result,
577
- duration,
578
- messageId,
579
- timestamp,
580
- clientId
581
- } = e.payload;
582
- const conversationId = clientId || (streamId ? streamToConversation.get(streamId) : void 0);
583
- if (!conversationId || !state.conversations[conversationId]) return;
584
- const conv = state.conversations[conversationId];
585
- const chunk = {
586
- id: `chunk-tool-result-${toolCallId}-${Date.now()}`,
587
- type: "tool_result",
588
- messageId,
589
- toolCallId,
590
- toolName,
591
- result,
592
- duration,
593
- timestamp,
594
- chunkCount: 1
595
- };
596
- if (conv.type === "client" && messageId) {
597
- const messageIndex = conv.messages.findIndex((m) => m.id === messageId);
598
- if (messageIndex !== -1) {
599
- queueMessageChunk(conversationId, messageIndex, chunk);
600
- } else {
601
- for (let i = conv.messages.length - 1; i >= 0; i--) {
602
- if (conv.messages[i]?.role === "assistant") {
603
- queueMessageChunk(conversationId, i, chunk);
604
- break;
605
- }
606
- }
607
- }
608
- } else {
609
- addChunk(conversationId, chunk);
610
- }
611
- for (let i = conv.messages.length - 1; i >= 0; i--) {
612
- const message = conv.messages[i];
613
- if (!message?.toolCalls) continue;
614
- const toolCallIndex = message.toolCalls.findIndex((t) => t.id === toolCallId);
615
- if (toolCallIndex >= 0) {
616
- updateToolCall(conversationId, i, toolCallIndex, {
617
- duration,
618
- result
619
- });
620
- return;
621
- }
622
- }
623
- }));
624
- cleanupFns.push(aiEventClient.on("text:chunk:content", (e) => {
625
- const streamId = e.payload.streamId;
626
- const conversationId = streamToConversation.get(streamId);
627
- if (!conversationId) return;
628
- const chunk = {
629
- id: `chunk-${Date.now()}-${Math.random()}`,
630
- type: "content",
631
- messageId: e.payload.messageId,
632
- content: e.payload.content,
633
- delta: e.payload.delta,
634
- timestamp: e.payload.timestamp,
635
- chunkCount: 1
636
- };
637
- const conv = state.conversations[conversationId];
638
- if (conv?.type === "client") {
639
- addChunkToMessage(conversationId, chunk);
640
- } else {
641
- ensureMessageForChunk(conversationId, e.payload.messageId, e.payload.timestamp);
642
- addChunk(conversationId, chunk);
643
- }
644
- if (e.payload.messageId) {
645
- const messageIndex = conv?.messages.findIndex((msg) => msg.id === e.payload.messageId);
646
- if (messageIndex !== void 0 && messageIndex >= 0) {
647
- updateMessage(conversationId, messageIndex, {
648
- content: e.payload.content
649
- });
650
- }
651
- }
652
- }));
653
- cleanupFns.push(aiEventClient.on("text:chunk:tool-call", (e) => {
654
- const streamId = e.payload.streamId;
655
- const conversationId = streamToConversation.get(streamId);
656
- if (!conversationId) return;
657
- const chunk = {
658
- id: `chunk-${Date.now()}-${Math.random()}`,
659
- type: "tool_call",
660
- messageId: e.payload.messageId,
661
- toolCallId: e.payload.toolCallId,
662
- toolName: e.payload.toolName,
663
- arguments: e.payload.arguments,
664
- timestamp: e.payload.timestamp,
665
- chunkCount: 1
666
- };
667
- const conv = state.conversations[conversationId];
668
- if (conv?.type === "client") {
669
- addChunkToMessage(conversationId, chunk);
670
- } else {
671
- ensureMessageForChunk(conversationId, e.payload.messageId, e.payload.timestamp);
672
- addChunk(conversationId, chunk);
673
- }
674
- if (e.payload.messageId) {
675
- const messageIndex = conv?.messages.findIndex((msg) => msg.id === e.payload.messageId);
676
- if (messageIndex !== void 0 && messageIndex >= 0) {
677
- const message = conv?.messages[messageIndex];
678
- if (!message) return;
679
- const toolCalls = message.toolCalls || [];
680
- const existingToolIndex = toolCalls.findIndex((t) => t.id === e.payload.toolCallId);
681
- const toolCall = {
682
- id: e.payload.toolCallId,
683
- name: e.payload.toolName,
684
- arguments: e.payload.arguments,
685
- state: "input-streaming"
686
- };
687
- if (existingToolIndex >= 0) {
688
- updateToolCall(conversationId, messageIndex, existingToolIndex, toolCall);
689
- } else {
690
- setToolCalls(conversationId, messageIndex, [...toolCalls, toolCall]);
691
- }
692
- }
693
- }
694
- }));
695
- cleanupFns.push(aiEventClient.on("text:chunk:tool-result", (e) => {
696
- const streamId = e.payload.streamId;
697
- const conversationId = streamToConversation.get(streamId);
698
- if (!conversationId) return;
699
- const chunk = {
700
- id: `chunk-${Date.now()}-${Math.random()}`,
701
- type: "tool_result",
702
- messageId: e.payload.messageId,
703
- toolCallId: e.payload.toolCallId,
704
- result: e.payload.result,
705
- timestamp: e.payload.timestamp,
706
- chunkCount: 1
707
- };
708
- const conv = state.conversations[conversationId];
709
- if (conv?.type === "client") {
710
- addChunkToMessage(conversationId, chunk);
711
- } else {
712
- ensureMessageForChunk(conversationId, e.payload.messageId, e.payload.timestamp);
713
- addChunk(conversationId, chunk);
714
- }
715
- if (conv && e.payload.toolCallId) {
716
- for (let i = conv.messages.length - 1; i >= 0; i--) {
717
- const message = conv.messages[i];
718
- if (!message?.toolCalls) continue;
719
- const toolCallIndex = message.toolCalls.findIndex((t) => t.id === e.payload.toolCallId);
720
- if (toolCallIndex >= 0) {
721
- updateToolCall(conversationId, i, toolCallIndex, {
722
- result: e.payload.result,
723
- state: "complete"
724
- });
725
- break;
726
- }
727
- }
728
- }
729
- }));
730
- cleanupFns.push(aiEventClient.on("text:chunk:thinking", (e) => {
731
- const streamId = e.payload.streamId;
732
- const conversationId = streamToConversation.get(streamId);
733
- if (!conversationId) return;
734
- const chunk = {
735
- id: `chunk-${Date.now()}-${Math.random()}`,
736
- type: "thinking",
737
- messageId: e.payload.messageId,
738
- content: e.payload.content,
739
- delta: e.payload.delta,
740
- timestamp: e.payload.timestamp,
741
- chunkCount: 1
742
- };
743
- const conv = state.conversations[conversationId];
744
- if (conv?.type === "client") {
745
- addChunkToMessage(conversationId, chunk);
746
- if (e.payload.messageId) {
747
- const messageIndex = conv.messages.findIndex((msg) => msg.id === e.payload.messageId);
748
- if (messageIndex !== -1) {
749
- updateMessage(conversationId, messageIndex, {
750
- thinkingContent: e.payload.content
751
- });
752
- }
753
- }
754
- } else {
755
- ensureMessageForChunk(conversationId, e.payload.messageId, e.payload.timestamp);
756
- addChunk(conversationId, chunk);
757
- }
758
- }));
759
- cleanupFns.push(aiEventClient.on("text:chunk:done", (e) => {
760
- const streamId = e.payload.streamId;
761
- const conversationId = streamToConversation.get(streamId);
762
- if (!conversationId) return;
763
- const chunk = {
764
- id: `chunk-${Date.now()}-${Math.random()}`,
765
- type: "done",
766
- messageId: e.payload.messageId,
767
- finishReason: e.payload.finishReason || void 0,
768
- timestamp: e.payload.timestamp,
769
- chunkCount: 1
770
- };
771
- if (e.payload.usage) {
772
- updateConversation(conversationId, {
773
- usage: e.payload.usage
774
- });
775
- updateMessageUsage(conversationId, e.payload.messageId, e.payload.usage);
776
- }
777
- const conv = state.conversations[conversationId];
778
- if (conv?.type === "client") {
779
- addChunkToMessage(conversationId, chunk);
780
- } else {
781
- ensureMessageForChunk(conversationId, e.payload.messageId, e.payload.timestamp);
782
- addChunk(conversationId, chunk);
783
- }
784
- updateConversation(conversationId, {
785
- status: "completed",
786
- completedAt: e.payload.timestamp
787
- });
788
- }));
789
- cleanupFns.push(aiEventClient.on("text:chunk:error", (e) => {
790
- const streamId = e.payload.streamId;
791
- const conversationId = streamToConversation.get(streamId);
792
- if (!conversationId) return;
793
- const chunk = {
794
- id: `chunk-${Date.now()}-${Math.random()}`,
795
- type: "error",
796
- messageId: e.payload.messageId,
797
- error: e.payload.error,
798
- timestamp: e.payload.timestamp,
799
- chunkCount: 1
800
- };
801
- const conv = state.conversations[conversationId];
802
- if (conv?.type === "client") {
803
- addChunkToMessage(conversationId, chunk);
804
- } else {
805
- ensureMessageForChunk(conversationId, e.payload.messageId, e.payload.timestamp);
806
- addChunk(conversationId, chunk);
807
- }
808
- updateConversation(conversationId, {
809
- status: "error",
810
- completedAt: e.payload.timestamp
811
- });
812
- }));
813
- cleanupFns.push(aiEventClient.on("tools:approval:requested", (e) => {
814
- const {
815
- streamId,
816
- messageId,
817
- toolCallId,
818
- toolName,
819
- input,
820
- approvalId,
821
- timestamp,
822
- clientId
823
- } = e.payload;
824
- const conversationId = clientId || streamToConversation.get(streamId) || "";
825
- if (!conversationId) return;
826
- const conv = state.conversations[conversationId];
827
- if (!conv) return;
828
- const chunk = {
829
- id: `chunk-${Date.now()}-${Math.random()}`,
830
- type: "approval",
831
- messageId,
832
- toolCallId,
833
- toolName,
834
- approvalId,
835
- input,
836
- timestamp,
837
- chunkCount: 1
838
- };
839
- if (conv.type === "client") {
840
- addChunkToMessage(conversationId, chunk);
841
- } else {
842
- addChunk(conversationId, chunk);
843
- }
844
- for (let i = conv.messages.length - 1; i >= 0; i--) {
845
- const message = conv.messages[i];
846
- if (!message) continue;
847
- if (message.role === "assistant" && message.toolCalls) {
848
- const toolCallIndex = message.toolCalls.findIndex((t) => t.id === toolCallId);
849
- if (toolCallIndex >= 0) {
850
- updateToolCall(conversationId, i, toolCallIndex, {
851
- approvalRequired: true,
852
- approvalId,
853
- state: "approval-requested"
854
- });
855
- return;
856
- }
857
- }
858
- }
859
- }));
860
- cleanupFns.push(aiEventClient.on("text:request:started", (e) => {
861
- const streamId = e.payload.streamId;
862
- const model = e.payload.model;
863
- e.payload.provider;
864
- const clientId = e.payload.clientId;
865
- if (clientId && state.conversations[clientId]) {
866
- streamToConversation.set(streamId, clientId);
867
- requestToConversation.set(e.payload.requestId, clientId);
868
- updateConversation(clientId, {
869
- status: "active",
870
- ...e.payload,
871
- systemPrompts: e.payload.systemPrompts,
872
- hasChat: true
873
- });
874
- return;
875
- }
876
- const activeClient = Object.values(state.conversations).find((c) => c.type === "client" && c.status === "active" && !c.model);
877
- if (activeClient) {
878
- streamToConversation.set(streamId, activeClient.id);
879
- requestToConversation.set(e.payload.requestId, activeClient.id);
880
- updateConversation(activeClient.id, {
881
- ...e.payload,
882
- systemPrompts: e.payload.systemPrompts,
883
- hasChat: true
884
- });
885
- } else {
886
- const existingServerConv = Object.values(state.conversations).find((c) => c.type === "server" && c.model === model);
887
- if (existingServerConv) {
888
- streamToConversation.set(streamId, existingServerConv.id);
889
- requestToConversation.set(e.payload.requestId, existingServerConv.id);
890
- updateConversation(existingServerConv.id, {
891
- status: "active",
892
- ...e.payload,
893
- systemPrompts: e.payload.systemPrompts,
894
- hasChat: true
895
- });
896
- } else {
897
- const serverId = `server-${model}`;
898
- getOrCreateConversation(serverId, "server", `${model} Server`);
899
- streamToConversation.set(streamId, serverId);
900
- requestToConversation.set(e.payload.requestId, serverId);
901
- updateConversation(serverId, {
902
- ...e.payload,
903
- systemPrompts: e.payload.systemPrompts,
904
- hasChat: true
905
- });
906
- }
907
- }
908
- }));
909
- cleanupFns.push(aiEventClient.on("text:request:completed", (e) => {
910
- const {
911
- requestId,
912
- usage
913
- } = e.payload;
914
- const conversationId = requestToConversation.get(requestId);
915
- if (conversationId && state.conversations[conversationId]) {
916
- const updates = {
917
- status: "completed",
918
- completedAt: e.payload.timestamp
919
- };
920
- if (usage) {
921
- updates.usage = usage;
922
- }
923
- updateConversation(conversationId, updates);
924
- if (usage) {
925
- updateMessageUsage(conversationId, e.payload.messageId, usage);
926
- }
927
- }
928
- }));
929
- cleanupFns.push(aiEventClient.on("text:usage", (e) => {
930
- const {
931
- requestId,
932
- usage,
933
- messageId
934
- } = e.payload;
935
- const conversationId = requestToConversation.get(requestId);
936
- if (conversationId && state.conversations[conversationId]) {
937
- updateConversation(conversationId, {
938
- usage
939
- });
940
- updateMessageUsage(conversationId, messageId, usage);
941
- }
942
- }));
943
- cleanupFns.push(aiEventClient.on("summarize:request:started", (e) => {
944
- const {
945
- requestId,
946
- model,
947
- inputLength,
948
- timestamp,
949
- clientId
950
- } = e.payload;
951
- let conversationId = clientId;
952
- if (!conversationId || !state.conversations[conversationId]) {
953
- const activeClients = Object.values(state.conversations).filter((c) => c.type === "client" && c.status === "active").sort((a, b) => b.startedAt - a.startedAt);
954
- if (activeClients.length > 0 && activeClients[0]) {
955
- conversationId = activeClients[0].id;
956
- } else {
957
- conversationId = `summarize-${requestId}`;
958
- getOrCreateConversation(conversationId, "server", `Summarize (${model})`);
959
- updateConversation(conversationId, {
960
- model
961
- });
962
- }
963
- }
964
- requestToConversation.set(requestId, conversationId);
965
- const summarizeOp = {
966
- id: requestId,
967
- model,
968
- inputLength,
969
- timestamp,
970
- status: "started"
971
- };
972
- const conv = state.conversations[conversationId];
973
- if (conv) {
974
- const summaries = conv.summaries || [];
975
- setState("conversations", conversationId, "summaries", [...summaries, summarizeOp]);
976
- setState("conversations", conversationId, "hasSummarize", true);
977
- }
978
- }));
979
- cleanupFns.push(aiEventClient.on("summarize:request:completed", (e) => {
980
- const {
981
- requestId,
982
- outputLength,
983
- duration
984
- } = e.payload;
985
- const conversationId = requestToConversation.get(requestId);
986
- if (!conversationId || !state.conversations[conversationId]) return;
987
- const conv = state.conversations[conversationId];
988
- if (!conv.summaries) return;
989
- const summaryIndex = conv.summaries.findIndex((op) => op.id === requestId);
990
- if (summaryIndex >= 0) {
991
- setState("conversations", conversationId, "summaries", summaryIndex, produce((op) => {
992
- op.duration = duration;
993
- op.outputLength = outputLength;
994
- op.status = "completed";
995
- }));
996
- }
997
- }));
998
- cleanupFns.push(aiEventClient.on("image:request:started", (e) => {
999
- const {
1000
- requestId,
1001
- clientId,
1002
- timestamp
1003
- } = e.payload;
1004
- let conversationId = clientId;
1005
- if (!conversationId || !state.conversations[conversationId]) {
1006
- conversationId = `image-${requestId}`;
1007
- getOrCreateConversation(conversationId, "server", `Image (${requestId.substring(0, 8)})`);
1008
- }
1009
- addActivityEvent(conversationId, "imageEvents", {
1010
- id: requestId,
1011
- name: "image:request:started",
1012
- timestamp,
1013
- payload: e.payload
1014
- });
1015
- }));
1016
- cleanupFns.push(aiEventClient.on("image:request:completed", (e) => {
1017
- const {
1018
- requestId,
1019
- clientId,
1020
- timestamp
1021
- } = e.payload;
1022
- let conversationId = clientId;
1023
- if (!conversationId || !state.conversations[conversationId]) {
1024
- conversationId = `image-${requestId}`;
1025
- getOrCreateConversation(conversationId, "server", `Image (${requestId.substring(0, 8)})`);
1026
- }
1027
- addActivityEvent(conversationId, "imageEvents", {
1028
- id: requestId,
1029
- name: "image:request:completed",
1030
- timestamp,
1031
- payload: e.payload
1032
- });
1033
- }));
1034
- cleanupFns.push(aiEventClient.on("image:usage", (e) => {
1035
- const {
1036
- requestId,
1037
- clientId,
1038
- timestamp
1039
- } = e.payload;
1040
- let conversationId = clientId;
1041
- if (!conversationId || !state.conversations[conversationId]) {
1042
- conversationId = `image-${requestId}`;
1043
- getOrCreateConversation(conversationId, "server", `Image (${requestId.substring(0, 8)})`);
1044
- }
1045
- addActivityEvent(conversationId, "imageEvents", {
1046
- id: requestId,
1047
- name: "image:usage",
1048
- timestamp,
1049
- payload: e.payload
1050
- });
1051
- }));
1052
- cleanupFns.push(aiEventClient.on("speech:request:started", (e) => {
1053
- const {
1054
- requestId,
1055
- clientId,
1056
- timestamp
1057
- } = e.payload;
1058
- let conversationId = clientId;
1059
- if (!conversationId || !state.conversations[conversationId]) {
1060
- conversationId = `speech-${requestId}`;
1061
- getOrCreateConversation(conversationId, "server", `Speech (${requestId.substring(0, 8)})`);
1062
- }
1063
- addActivityEvent(conversationId, "speechEvents", {
1064
- id: requestId,
1065
- name: "speech:request:started",
1066
- timestamp,
1067
- payload: e.payload
1068
- });
1069
- }));
1070
- cleanupFns.push(aiEventClient.on("speech:request:completed", (e) => {
1071
- const {
1072
- requestId,
1073
- clientId,
1074
- timestamp
1075
- } = e.payload;
1076
- let conversationId = clientId;
1077
- if (!conversationId || !state.conversations[conversationId]) {
1078
- conversationId = `speech-${requestId}`;
1079
- getOrCreateConversation(conversationId, "server", `Speech (${requestId.substring(0, 8)})`);
1080
- }
1081
- addActivityEvent(conversationId, "speechEvents", {
1082
- id: requestId,
1083
- name: "speech:request:completed",
1084
- timestamp,
1085
- payload: e.payload
1086
- });
1087
- }));
1088
- cleanupFns.push(aiEventClient.on("speech:usage", (e) => {
1089
- const {
1090
- requestId,
1091
- clientId,
1092
- timestamp
1093
- } = e.payload;
1094
- let conversationId = clientId;
1095
- if (!conversationId || !state.conversations[conversationId]) {
1096
- conversationId = `speech-${requestId}`;
1097
- getOrCreateConversation(conversationId, "server", `Speech (${requestId.substring(0, 8)})`);
1098
- }
1099
- addActivityEvent(conversationId, "speechEvents", {
1100
- id: requestId,
1101
- name: "speech:usage",
1102
- timestamp,
1103
- payload: e.payload
1104
- });
1105
- }));
1106
- cleanupFns.push(aiEventClient.on("transcription:request:started", (e) => {
1107
- const {
1108
- requestId,
1109
- clientId,
1110
- timestamp
1111
- } = e.payload;
1112
- let conversationId = clientId;
1113
- if (!conversationId || !state.conversations[conversationId]) {
1114
- conversationId = `transcription-${requestId}`;
1115
- getOrCreateConversation(conversationId, "server", `Transcription (${requestId.substring(0, 8)})`);
1116
- }
1117
- addActivityEvent(conversationId, "transcriptionEvents", {
1118
- id: requestId,
1119
- name: "transcription:request:started",
1120
- timestamp,
1121
- payload: e.payload
1122
- });
1123
- }));
1124
- cleanupFns.push(aiEventClient.on("transcription:request:completed", (e) => {
1125
- const {
1126
- requestId,
1127
- clientId,
1128
- timestamp
1129
- } = e.payload;
1130
- let conversationId = clientId;
1131
- if (!conversationId || !state.conversations[conversationId]) {
1132
- conversationId = `transcription-${requestId}`;
1133
- getOrCreateConversation(conversationId, "server", `Transcription (${requestId.substring(0, 8)})`);
1134
- }
1135
- addActivityEvent(conversationId, "transcriptionEvents", {
1136
- id: requestId,
1137
- name: "transcription:request:completed",
1138
- timestamp,
1139
- payload: e.payload
1140
- });
1141
- }));
1142
- cleanupFns.push(aiEventClient.on("transcription:usage", (e) => {
1143
- const {
1144
- requestId,
1145
- clientId,
1146
- timestamp
1147
- } = e.payload;
1148
- let conversationId = clientId;
1149
- if (!conversationId || !state.conversations[conversationId]) {
1150
- conversationId = `transcription-${requestId}`;
1151
- getOrCreateConversation(conversationId, "server", `Transcription (${requestId.substring(0, 8)})`);
1152
- }
1153
- addActivityEvent(conversationId, "transcriptionEvents", {
1154
- id: requestId,
1155
- name: "transcription:usage",
1156
- timestamp,
1157
- payload: e.payload
1158
- });
1159
- }));
1160
- cleanupFns.push(aiEventClient.on("video:request:started", (e) => {
1161
- const {
1162
- requestId,
1163
- clientId,
1164
- timestamp
1165
- } = e.payload;
1166
- let conversationId = clientId;
1167
- if (!conversationId || !state.conversations[conversationId]) {
1168
- conversationId = `video-${requestId}`;
1169
- getOrCreateConversation(conversationId, "server", `Video (${requestId.substring(0, 8)})`);
1170
- }
1171
- addActivityEvent(conversationId, "videoEvents", {
1172
- id: requestId,
1173
- name: "video:request:started",
1174
- timestamp,
1175
- payload: e.payload
1176
- });
1177
- }));
1178
- cleanupFns.push(aiEventClient.on("video:request:completed", (e) => {
1179
- const {
1180
- requestId,
1181
- clientId,
1182
- timestamp
1183
- } = e.payload;
1184
- let conversationId = clientId;
1185
- if (!conversationId || !state.conversations[conversationId]) {
1186
- conversationId = `video-${requestId}`;
1187
- getOrCreateConversation(conversationId, "server", `Video (${requestId.substring(0, 8)})`);
1188
- }
1189
- addActivityEvent(conversationId, "videoEvents", {
1190
- id: requestId,
1191
- name: "video:request:completed",
1192
- timestamp,
1193
- payload: e.payload
1194
- });
1195
- }));
1196
- cleanupFns.push(aiEventClient.on("video:usage", (e) => {
1197
- const {
1198
- requestId,
1199
- clientId,
1200
- timestamp
1201
- } = e.payload;
1202
- let conversationId = clientId;
1203
- if (!conversationId || !state.conversations[conversationId]) {
1204
- conversationId = `video-${requestId}`;
1205
- getOrCreateConversation(conversationId, "server", `Video (${requestId.substring(0, 8)})`);
1206
- }
1207
- addActivityEvent(conversationId, "videoEvents", {
1208
- id: requestId,
1209
- name: "video:usage",
1210
- timestamp,
1211
- payload: e.payload
1212
- });
1213
- }));
1214
- onCleanup(() => {
1215
- for (const cleanup of cleanupFns) {
1216
- cleanup();
1217
- }
1218
- streamToConversation.clear();
1219
- requestToConversation.clear();
1220
- });
1221
- });
1222
- const contextValue = {
1223
- state,
1224
- clearAllConversations,
1225
- selectConversation
1226
- };
1227
- return createComponent(AIContext.Provider, {
1228
- value: contextValue,
1229
- get children() {
1230
- return props.children;
1231
- }
1232
- });
1233
- };
1234
- export {
1235
- AIProvider,
1236
- useAIStore
1237
- };
1238
- //# sourceMappingURL=ai-context.js.map