@tanstack/ai 0.2.2 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/esm/activities/chat/index.js +264 -186
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.js +22 -0
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/stream/index.d.ts +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +22 -43
- package/dist/esm/activities/chat/stream/processor.js +93 -157
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +22 -21
- package/dist/esm/activities/chat/tools/tool-calls.js +40 -27
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/generateImage/index.js +41 -1
- package/dist/esm/activities/generateImage/index.js.map +1 -1
- package/dist/esm/activities/generateSpeech/index.js +33 -1
- package/dist/esm/activities/generateSpeech/index.js.map +1 -1
- package/dist/esm/activities/generateTranscription/index.js +29 -1
- package/dist/esm/activities/generateTranscription/index.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.js +50 -0
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/summarize/index.js +9 -8
- package/dist/esm/activities/summarize/index.js.map +1 -1
- package/dist/esm/event-client.d.ts +378 -254
- package/dist/esm/event-client.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/stream-to-response.d.ts +1 -1
- package/dist/esm/stream-to-response.js +5 -3
- package/dist/esm/stream-to-response.js.map +1 -1
- package/dist/esm/types.d.ts +162 -46
- package/package.json +1 -1
- package/src/activities/chat/index.ts +362 -216
- package/src/activities/chat/messages.ts +40 -1
- package/src/activities/chat/stream/index.ts +1 -5
- package/src/activities/chat/stream/processor.ts +142 -270
- package/src/activities/chat/tools/tool-calls.ts +55 -49
- package/src/activities/generateImage/index.ts +47 -2
- package/src/activities/generateSpeech/index.ts +37 -1
- package/src/activities/generateTranscription/index.ts +33 -1
- package/src/activities/generateVideo/index.ts +54 -0
- package/src/activities/summarize/index.ts +10 -9
- package/src/event-client.ts +460 -256
- package/src/index.ts +2 -3
- package/src/stream-to-response.ts +8 -6
- package/src/types.ts +209 -65
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import { isStandardSchema, parseWithStandardSchema } from './schema-converter'
|
|
2
2
|
import type {
|
|
3
|
-
DoneStreamChunk,
|
|
4
3
|
ModelMessage,
|
|
4
|
+
RunFinishedEvent,
|
|
5
5
|
Tool,
|
|
6
6
|
ToolCall,
|
|
7
|
-
|
|
7
|
+
ToolCallArgsEvent,
|
|
8
|
+
ToolCallEndEvent,
|
|
9
|
+
ToolCallStartEvent,
|
|
8
10
|
} from '../../../types'
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Manages tool call accumulation and execution for the chat() method's automatic tool execution loop.
|
|
12
14
|
*
|
|
13
15
|
* Responsibilities:
|
|
14
|
-
* - Accumulates streaming tool call
|
|
16
|
+
* - Accumulates streaming tool call events (ID, name, arguments)
|
|
15
17
|
* - Validates tool calls (filters out incomplete ones)
|
|
16
18
|
* - Executes tool `execute` functions with parsed arguments
|
|
17
|
-
* - Emits `
|
|
19
|
+
* - Emits `TOOL_CALL_END` events for client visibility
|
|
18
20
|
* - Returns tool result messages for conversation history
|
|
19
21
|
*
|
|
20
22
|
* This class is used internally by the AI.chat() method to handle the automatic
|
|
@@ -26,14 +28,16 @@ import type {
|
|
|
26
28
|
*
|
|
27
29
|
* // During streaming, accumulate tool calls
|
|
28
30
|
* for await (const chunk of stream) {
|
|
29
|
-
* if (chunk.type ===
|
|
30
|
-
* manager.
|
|
31
|
+
* if (chunk.type === 'TOOL_CALL_START') {
|
|
32
|
+
* manager.addToolCallStartEvent(chunk);
|
|
33
|
+
* } else if (chunk.type === 'TOOL_CALL_ARGS') {
|
|
34
|
+
* manager.addToolCallArgsEvent(chunk);
|
|
31
35
|
* }
|
|
32
36
|
* }
|
|
33
37
|
*
|
|
34
38
|
* // After stream completes, execute tools
|
|
35
39
|
* if (manager.hasToolCalls()) {
|
|
36
|
-
* const toolResults = yield* manager.executeTools(
|
|
40
|
+
* const toolResults = yield* manager.executeTools(finishEvent);
|
|
37
41
|
* messages = [...messages, ...toolResults];
|
|
38
42
|
* manager.clear();
|
|
39
43
|
* }
|
|
@@ -48,43 +52,44 @@ export class ToolCallManager {
|
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
/**
|
|
51
|
-
* Add a
|
|
52
|
-
* Handles streaming tool calls by accumulating arguments
|
|
55
|
+
* Add a TOOL_CALL_START event to begin tracking a tool call (AG-UI)
|
|
53
56
|
*/
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
addToolCallStartEvent(event: ToolCallStartEvent): void {
|
|
58
|
+
const index = event.index ?? this.toolCallsMap.size
|
|
59
|
+
this.toolCallsMap.set(index, {
|
|
60
|
+
id: event.toolCallId,
|
|
61
|
+
type: 'function',
|
|
58
62
|
function: {
|
|
59
|
-
name:
|
|
60
|
-
arguments:
|
|
63
|
+
name: event.toolName,
|
|
64
|
+
arguments: '',
|
|
65
|
+
},
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Add a TOOL_CALL_ARGS event to accumulate arguments (AG-UI)
|
|
71
|
+
*/
|
|
72
|
+
addToolCallArgsEvent(event: ToolCallArgsEvent): void {
|
|
73
|
+
// Find the tool call by ID
|
|
74
|
+
for (const [, toolCall] of this.toolCallsMap.entries()) {
|
|
75
|
+
if (toolCall.id === event.toolCallId) {
|
|
76
|
+
toolCall.function.arguments += event.delta
|
|
77
|
+
break
|
|
61
78
|
}
|
|
62
79
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
arguments: chunk.toolCall.function.arguments || '',
|
|
77
|
-
},
|
|
78
|
-
})
|
|
79
|
-
}
|
|
80
|
-
} else {
|
|
81
|
-
// Update name if it wasn't set before
|
|
82
|
-
if (chunk.toolCall.function.name && !existing.function.name) {
|
|
83
|
-
existing.function.name = chunk.toolCall.function.name
|
|
84
|
-
}
|
|
85
|
-
// Accumulate arguments for streaming tool calls
|
|
86
|
-
if (chunk.toolCall.function.arguments) {
|
|
87
|
-
existing.function.arguments += chunk.toolCall.function.arguments
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Complete a tool call with its final input
|
|
84
|
+
* Called when TOOL_CALL_END is received
|
|
85
|
+
*/
|
|
86
|
+
completeToolCall(event: ToolCallEndEvent): void {
|
|
87
|
+
for (const [, toolCall] of this.toolCallsMap.entries()) {
|
|
88
|
+
if (toolCall.id === event.toolCallId) {
|
|
89
|
+
if (event.input !== undefined) {
|
|
90
|
+
toolCall.function.arguments = JSON.stringify(event.input)
|
|
91
|
+
}
|
|
92
|
+
break
|
|
88
93
|
}
|
|
89
94
|
}
|
|
90
95
|
}
|
|
@@ -107,11 +112,12 @@ export class ToolCallManager {
|
|
|
107
112
|
|
|
108
113
|
/**
|
|
109
114
|
* Execute all tool calls and return tool result messages
|
|
110
|
-
*
|
|
115
|
+
* Yields TOOL_CALL_END events for streaming
|
|
116
|
+
* @param finishEvent - RUN_FINISHED event from the stream
|
|
111
117
|
*/
|
|
112
118
|
async *executeTools(
|
|
113
|
-
|
|
114
|
-
): AsyncGenerator<
|
|
119
|
+
finishEvent: RunFinishedEvent,
|
|
120
|
+
): AsyncGenerator<ToolCallEndEvent, Array<ModelMessage>, void> {
|
|
115
121
|
const toolCallsArray = this.getToolCalls()
|
|
116
122
|
const toolResults: Array<ModelMessage> = []
|
|
117
123
|
|
|
@@ -182,14 +188,14 @@ export class ToolCallManager {
|
|
|
182
188
|
toolResultContent = `Tool ${toolCall.function.name} does not have an execute function`
|
|
183
189
|
}
|
|
184
190
|
|
|
185
|
-
// Emit
|
|
191
|
+
// Emit TOOL_CALL_END event
|
|
186
192
|
yield {
|
|
187
|
-
type: '
|
|
188
|
-
id: doneChunk.id,
|
|
189
|
-
model: doneChunk.model,
|
|
190
|
-
timestamp: Date.now(),
|
|
193
|
+
type: 'TOOL_CALL_END',
|
|
191
194
|
toolCallId: toolCall.id,
|
|
192
|
-
|
|
195
|
+
toolName: toolCall.function.name,
|
|
196
|
+
model: finishEvent.model,
|
|
197
|
+
timestamp: Date.now(),
|
|
198
|
+
result: toolResultContent,
|
|
193
199
|
}
|
|
194
200
|
|
|
195
201
|
// Add tool result message
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* This is a self-contained module with implementation, types, and JSDoc.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { aiEventClient } from '../../event-client.js'
|
|
8
9
|
import type { ImageAdapter } from './adapter'
|
|
9
10
|
import type { ImageGenerationResult } from '../../types'
|
|
10
11
|
|
|
@@ -82,6 +83,10 @@ export interface ImageActivityOptions<
|
|
|
82
83
|
/** Result type for the image activity */
|
|
83
84
|
export type ImageActivityResult = Promise<ImageGenerationResult>
|
|
84
85
|
|
|
86
|
+
function createId(prefix: string): string {
|
|
87
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
|
|
88
|
+
}
|
|
89
|
+
|
|
85
90
|
// ===========================
|
|
86
91
|
// Activity Implementation
|
|
87
92
|
// ===========================
|
|
@@ -136,8 +141,48 @@ export async function generateImage<
|
|
|
136
141
|
>(options: ImageActivityOptions<TAdapter>): ImageActivityResult {
|
|
137
142
|
const { adapter, ...rest } = options
|
|
138
143
|
const model = adapter.model
|
|
139
|
-
|
|
140
|
-
|
|
144
|
+
const requestId = createId('image')
|
|
145
|
+
const startTime = Date.now()
|
|
146
|
+
|
|
147
|
+
aiEventClient.emit('image:request:started', {
|
|
148
|
+
requestId,
|
|
149
|
+
provider: adapter.name,
|
|
150
|
+
model,
|
|
151
|
+
prompt: rest.prompt,
|
|
152
|
+
numberOfImages: rest.numberOfImages,
|
|
153
|
+
size: rest.size as string | undefined,
|
|
154
|
+
modelOptions: rest.modelOptions as Record<string, unknown> | undefined,
|
|
155
|
+
timestamp: startTime,
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
return adapter.generateImages({ ...rest, model }).then((result) => {
|
|
159
|
+
const duration = Date.now() - startTime
|
|
160
|
+
|
|
161
|
+
aiEventClient.emit('image:request:completed', {
|
|
162
|
+
requestId,
|
|
163
|
+
provider: adapter.name,
|
|
164
|
+
model,
|
|
165
|
+
images: result.images.map((image) => ({
|
|
166
|
+
url: image.url,
|
|
167
|
+
b64Json: image.b64Json,
|
|
168
|
+
})),
|
|
169
|
+
duration,
|
|
170
|
+
modelOptions: rest.modelOptions as Record<string, unknown> | undefined,
|
|
171
|
+
timestamp: Date.now(),
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
if (result.usage) {
|
|
175
|
+
aiEventClient.emit('image:usage', {
|
|
176
|
+
requestId,
|
|
177
|
+
model,
|
|
178
|
+
usage: result.usage,
|
|
179
|
+
modelOptions: rest.modelOptions as Record<string, unknown> | undefined,
|
|
180
|
+
timestamp: Date.now(),
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return result
|
|
185
|
+
})
|
|
141
186
|
}
|
|
142
187
|
|
|
143
188
|
// ===========================
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* This is a self-contained module with implementation, types, and JSDoc.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { aiEventClient } from '../../event-client.js'
|
|
8
9
|
import type { TTSAdapter } from './adapter'
|
|
9
10
|
import type { TTSResult } from '../../types'
|
|
10
11
|
|
|
@@ -61,6 +62,10 @@ export interface TTSActivityOptions<
|
|
|
61
62
|
/** Result type for the TTS activity */
|
|
62
63
|
export type TTSActivityResult = Promise<TTSResult>
|
|
63
64
|
|
|
65
|
+
function createId(prefix: string): string {
|
|
66
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
|
|
67
|
+
}
|
|
68
|
+
|
|
64
69
|
// ===========================
|
|
65
70
|
// Activity Implementation
|
|
66
71
|
// ===========================
|
|
@@ -100,8 +105,39 @@ export async function generateSpeech<
|
|
|
100
105
|
>(options: TTSActivityOptions<TAdapter>): TTSActivityResult {
|
|
101
106
|
const { adapter, ...rest } = options
|
|
102
107
|
const model = adapter.model
|
|
108
|
+
const requestId = createId('speech')
|
|
109
|
+
const startTime = Date.now()
|
|
110
|
+
|
|
111
|
+
aiEventClient.emit('speech:request:started', {
|
|
112
|
+
requestId,
|
|
113
|
+
provider: adapter.name,
|
|
114
|
+
model,
|
|
115
|
+
text: rest.text,
|
|
116
|
+
voice: rest.voice,
|
|
117
|
+
format: rest.format,
|
|
118
|
+
speed: rest.speed,
|
|
119
|
+
modelOptions: rest.modelOptions as Record<string, unknown> | undefined,
|
|
120
|
+
timestamp: startTime,
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
return adapter.generateSpeech({ ...rest, model }).then((result) => {
|
|
124
|
+
const duration = Date.now() - startTime
|
|
125
|
+
|
|
126
|
+
aiEventClient.emit('speech:request:completed', {
|
|
127
|
+
requestId,
|
|
128
|
+
provider: adapter.name,
|
|
129
|
+
model,
|
|
130
|
+
audio: result.audio,
|
|
131
|
+
format: result.format,
|
|
132
|
+
audioDuration: result.duration,
|
|
133
|
+
contentType: result.contentType,
|
|
134
|
+
duration,
|
|
135
|
+
modelOptions: rest.modelOptions as Record<string, unknown> | undefined,
|
|
136
|
+
timestamp: Date.now(),
|
|
137
|
+
})
|
|
103
138
|
|
|
104
|
-
|
|
139
|
+
return result
|
|
140
|
+
})
|
|
105
141
|
}
|
|
106
142
|
|
|
107
143
|
// ===========================
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* This is a self-contained module with implementation, types, and JSDoc.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { aiEventClient } from '../../event-client.js'
|
|
8
9
|
import type { TranscriptionAdapter } from './adapter'
|
|
9
10
|
import type { TranscriptionResult } from '../../types'
|
|
10
11
|
|
|
@@ -61,6 +62,10 @@ export interface TranscriptionActivityOptions<
|
|
|
61
62
|
/** Result type for the transcription activity */
|
|
62
63
|
export type TranscriptionActivityResult = Promise<TranscriptionResult>
|
|
63
64
|
|
|
65
|
+
function createId(prefix: string): string {
|
|
66
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
|
|
67
|
+
}
|
|
68
|
+
|
|
64
69
|
// ===========================
|
|
65
70
|
// Activity Implementation
|
|
66
71
|
// ===========================
|
|
@@ -104,8 +109,35 @@ export async function generateTranscription<
|
|
|
104
109
|
): TranscriptionActivityResult {
|
|
105
110
|
const { adapter, ...rest } = options
|
|
106
111
|
const model = adapter.model
|
|
112
|
+
const requestId = createId('transcription')
|
|
113
|
+
const startTime = Date.now()
|
|
114
|
+
|
|
115
|
+
aiEventClient.emit('transcription:request:started', {
|
|
116
|
+
requestId,
|
|
117
|
+
provider: adapter.name,
|
|
118
|
+
model,
|
|
119
|
+
language: rest.language,
|
|
120
|
+
prompt: rest.prompt,
|
|
121
|
+
responseFormat: rest.responseFormat,
|
|
122
|
+
modelOptions: rest.modelOptions as Record<string, unknown> | undefined,
|
|
123
|
+
timestamp: startTime,
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
const result = await adapter.transcribe({ ...rest, model })
|
|
127
|
+
const duration = Date.now() - startTime
|
|
128
|
+
|
|
129
|
+
aiEventClient.emit('transcription:request:completed', {
|
|
130
|
+
requestId,
|
|
131
|
+
provider: adapter.name,
|
|
132
|
+
model,
|
|
133
|
+
text: result.text,
|
|
134
|
+
language: result.language,
|
|
135
|
+
duration,
|
|
136
|
+
modelOptions: rest.modelOptions as Record<string, unknown> | undefined,
|
|
137
|
+
timestamp: Date.now(),
|
|
138
|
+
})
|
|
107
139
|
|
|
108
|
-
return
|
|
140
|
+
return result
|
|
109
141
|
}
|
|
110
142
|
|
|
111
143
|
// ===========================
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* @experimental Video generation is an experimental feature and may change.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { aiEventClient } from '../../event-client.js'
|
|
10
11
|
import type { VideoAdapter } from './adapter'
|
|
11
12
|
import type {
|
|
12
13
|
VideoJobResult,
|
|
@@ -35,6 +36,10 @@ export type VideoProviderOptions<TAdapter> =
|
|
|
35
36
|
|
|
36
37
|
// ===========================
|
|
37
38
|
// Activity Options Types
|
|
39
|
+
|
|
40
|
+
function createId(prefix: string): string {
|
|
41
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
|
|
42
|
+
}
|
|
38
43
|
// ===========================
|
|
39
44
|
|
|
40
45
|
/**
|
|
@@ -207,6 +212,17 @@ export async function getVideoJobStatus<
|
|
|
207
212
|
error?: string
|
|
208
213
|
}> {
|
|
209
214
|
const { adapter, jobId } = options
|
|
215
|
+
const requestId = createId('video-status')
|
|
216
|
+
const startTime = Date.now()
|
|
217
|
+
|
|
218
|
+
aiEventClient.emit('video:request:started', {
|
|
219
|
+
requestId,
|
|
220
|
+
provider: adapter.name,
|
|
221
|
+
model: adapter.model,
|
|
222
|
+
requestType: 'status',
|
|
223
|
+
jobId,
|
|
224
|
+
timestamp: startTime,
|
|
225
|
+
})
|
|
210
226
|
|
|
211
227
|
// Get status first
|
|
212
228
|
const statusResult = await adapter.getVideoStatus(jobId)
|
|
@@ -215,12 +231,37 @@ export async function getVideoJobStatus<
|
|
|
215
231
|
if (statusResult.status === 'completed') {
|
|
216
232
|
try {
|
|
217
233
|
const urlResult = await adapter.getVideoUrl(jobId)
|
|
234
|
+
aiEventClient.emit('video:request:completed', {
|
|
235
|
+
requestId,
|
|
236
|
+
provider: adapter.name,
|
|
237
|
+
model: adapter.model,
|
|
238
|
+
requestType: 'status',
|
|
239
|
+
jobId,
|
|
240
|
+
status: statusResult.status,
|
|
241
|
+
progress: statusResult.progress,
|
|
242
|
+
url: urlResult.url,
|
|
243
|
+
duration: Date.now() - startTime,
|
|
244
|
+
timestamp: Date.now(),
|
|
245
|
+
})
|
|
218
246
|
return {
|
|
219
247
|
status: statusResult.status,
|
|
220
248
|
progress: statusResult.progress,
|
|
221
249
|
url: urlResult.url,
|
|
222
250
|
}
|
|
223
251
|
} catch (error) {
|
|
252
|
+
aiEventClient.emit('video:request:completed', {
|
|
253
|
+
requestId,
|
|
254
|
+
provider: adapter.name,
|
|
255
|
+
model: adapter.model,
|
|
256
|
+
requestType: 'status',
|
|
257
|
+
jobId,
|
|
258
|
+
status: statusResult.status,
|
|
259
|
+
progress: statusResult.progress,
|
|
260
|
+
error:
|
|
261
|
+
error instanceof Error ? error.message : 'Failed to get video URL',
|
|
262
|
+
duration: Date.now() - startTime,
|
|
263
|
+
timestamp: Date.now(),
|
|
264
|
+
})
|
|
224
265
|
// If URL fetch fails, still return status
|
|
225
266
|
return {
|
|
226
267
|
status: statusResult.status,
|
|
@@ -231,6 +272,19 @@ export async function getVideoJobStatus<
|
|
|
231
272
|
}
|
|
232
273
|
}
|
|
233
274
|
|
|
275
|
+
aiEventClient.emit('video:request:completed', {
|
|
276
|
+
requestId,
|
|
277
|
+
provider: adapter.name,
|
|
278
|
+
model: adapter.model,
|
|
279
|
+
requestType: 'status',
|
|
280
|
+
jobId,
|
|
281
|
+
status: statusResult.status,
|
|
282
|
+
progress: statusResult.progress,
|
|
283
|
+
error: statusResult.error,
|
|
284
|
+
duration: Date.now() - startTime,
|
|
285
|
+
timestamp: Date.now(),
|
|
286
|
+
})
|
|
287
|
+
|
|
234
288
|
// Return status for non-completed jobs
|
|
235
289
|
return {
|
|
236
290
|
status: statusResult.status,
|
|
@@ -180,8 +180,9 @@ async function runSummarize(
|
|
|
180
180
|
const inputLength = text.length
|
|
181
181
|
const startTime = Date.now()
|
|
182
182
|
|
|
183
|
-
aiEventClient.emit('summarize:started', {
|
|
183
|
+
aiEventClient.emit('summarize:request:started', {
|
|
184
184
|
requestId,
|
|
185
|
+
provider: adapter.name,
|
|
185
186
|
model,
|
|
186
187
|
inputLength,
|
|
187
188
|
timestamp: startTime,
|
|
@@ -200,8 +201,9 @@ async function runSummarize(
|
|
|
200
201
|
const duration = Date.now() - startTime
|
|
201
202
|
const outputLength = result.summary.length
|
|
202
203
|
|
|
203
|
-
aiEventClient.emit('summarize:completed', {
|
|
204
|
+
aiEventClient.emit('summarize:request:completed', {
|
|
204
205
|
requestId,
|
|
206
|
+
provider: adapter.name,
|
|
205
207
|
model,
|
|
206
208
|
inputLength,
|
|
207
209
|
outputLength,
|
|
@@ -240,21 +242,20 @@ async function* runStreamingSummarize(
|
|
|
240
242
|
// Fall back to non-streaming and yield as a single chunk
|
|
241
243
|
const result = await adapter.summarize(summarizeOptions)
|
|
242
244
|
|
|
243
|
-
// Yield
|
|
245
|
+
// Yield TEXT_MESSAGE_CONTENT event with the summary
|
|
244
246
|
yield {
|
|
245
|
-
type: '
|
|
246
|
-
|
|
247
|
+
type: 'TEXT_MESSAGE_CONTENT',
|
|
248
|
+
messageId: result.id,
|
|
247
249
|
model: result.model,
|
|
248
250
|
timestamp: Date.now(),
|
|
249
251
|
delta: result.summary,
|
|
250
252
|
content: result.summary,
|
|
251
|
-
role: 'assistant',
|
|
252
253
|
}
|
|
253
254
|
|
|
254
|
-
// Yield
|
|
255
|
+
// Yield RUN_FINISHED event
|
|
255
256
|
yield {
|
|
256
|
-
type: '
|
|
257
|
-
|
|
257
|
+
type: 'RUN_FINISHED',
|
|
258
|
+
runId: result.id,
|
|
258
259
|
model: result.model,
|
|
259
260
|
timestamp: Date.now(),
|
|
260
261
|
finishReason: 'stop',
|