@tanstack/ai 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/activities/chat/adapter.d.ts +20 -3
- package/dist/esm/activities/chat/adapter.js.map +1 -1
- package/dist/esm/activities/chat/index.d.ts +16 -6
- package/dist/esm/activities/chat/index.js +235 -9
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.js +4 -2
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/stream/message-updaters.d.ts +1 -0
- package/dist/esm/activities/chat/stream/message-updaters.js +3 -1
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.js +12 -4
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/stream/types.d.ts +5 -0
- package/dist/esm/activities/chat/tools/tool-calls.js +1 -3
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/error-payload.d.ts +0 -8
- package/dist/esm/activities/error-payload.js +20 -2
- package/dist/esm/activities/error-payload.js.map +1 -1
- package/dist/esm/activities/generateImage/adapter.d.ts +2 -2
- package/dist/esm/activities/generateImage/adapter.js.map +1 -1
- package/dist/esm/activities/generateVideo/adapter.d.ts +2 -2
- package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
- package/dist/esm/activities/index.d.ts +1 -0
- package/dist/esm/activities/index.js +2 -0
- package/dist/esm/activities/index.js.map +1 -1
- package/dist/esm/activities/stream-generation-result.js +0 -2
- package/dist/esm/activities/stream-generation-result.js.map +1 -1
- package/dist/esm/activities/summarize/adapter.d.ts +4 -4
- package/dist/esm/activities/summarize/adapter.js.map +1 -1
- package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +45 -0
- package/dist/esm/activities/summarize/chat-stream-summarize.js +148 -0
- package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -0
- package/dist/esm/activities/summarize/index.d.ts +1 -0
- package/dist/esm/activities/summarize/index.js +4 -2
- package/dist/esm/activities/summarize/index.js.map +1 -1
- package/dist/esm/types.d.ts +109 -10
- package/package.json +2 -2
- package/skills/ai-core/structured-outputs/SKILL.md +92 -1
- package/src/activities/chat/adapter.ts +25 -2
- package/src/activities/chat/index.ts +368 -26
- package/src/activities/chat/messages.ts +6 -0
- package/src/activities/chat/stream/message-updaters.ts +8 -0
- package/src/activities/chat/stream/processor.ts +12 -0
- package/src/activities/chat/stream/types.ts +5 -0
- package/src/activities/chat/tools/tool-calls.ts +1 -3
- package/src/activities/error-payload.ts +31 -2
- package/src/activities/generateImage/adapter.ts +8 -2
- package/src/activities/generateVideo/adapter.ts +8 -2
- package/src/activities/index.ts +5 -0
- package/src/activities/stream-generation-result.ts +4 -6
- package/src/activities/summarize/adapter.ts +8 -4
- package/src/activities/summarize/chat-stream-summarize.ts +238 -0
- package/src/activities/summarize/index.ts +12 -9
- package/src/types.ts +122 -10
package/src/activities/index.ts
CHANGED
|
@@ -60,6 +60,11 @@ export {
|
|
|
60
60
|
type SummarizeAdapterConfig,
|
|
61
61
|
type AnySummarizeAdapter,
|
|
62
62
|
} from './summarize/adapter'
|
|
63
|
+
export {
|
|
64
|
+
ChatStreamSummarizeAdapter,
|
|
65
|
+
type ChatStreamCapable,
|
|
66
|
+
type InferTextProviderOptions,
|
|
67
|
+
} from './summarize/chat-stream-summarize'
|
|
63
68
|
|
|
64
69
|
// ===========================
|
|
65
70
|
// Image Activity
|
|
@@ -34,7 +34,7 @@ export async function* streamGenerationResult<TResult>(
|
|
|
34
34
|
runId,
|
|
35
35
|
threadId,
|
|
36
36
|
timestamp: Date.now(),
|
|
37
|
-
}
|
|
37
|
+
}
|
|
38
38
|
|
|
39
39
|
try {
|
|
40
40
|
const result = await generator()
|
|
@@ -44,7 +44,7 @@ export async function* streamGenerationResult<TResult>(
|
|
|
44
44
|
name: 'generation:result',
|
|
45
45
|
value: result as unknown,
|
|
46
46
|
timestamp: Date.now(),
|
|
47
|
-
}
|
|
47
|
+
}
|
|
48
48
|
|
|
49
49
|
yield {
|
|
50
50
|
type: EventType.RUN_FINISHED,
|
|
@@ -52,18 +52,16 @@ export async function* streamGenerationResult<TResult>(
|
|
|
52
52
|
threadId,
|
|
53
53
|
finishReason: 'stop',
|
|
54
54
|
timestamp: Date.now(),
|
|
55
|
-
}
|
|
55
|
+
}
|
|
56
56
|
} catch (error: unknown) {
|
|
57
57
|
const payload = toRunErrorPayload(error, 'Generation failed')
|
|
58
58
|
yield {
|
|
59
59
|
type: EventType.RUN_ERROR,
|
|
60
|
-
runId,
|
|
61
|
-
threadId,
|
|
62
60
|
message: payload.message,
|
|
63
61
|
code: payload.code,
|
|
64
62
|
// Deprecated nested form for backward compatibility
|
|
65
63
|
error: payload,
|
|
66
64
|
timestamp: Date.now(),
|
|
67
|
-
}
|
|
65
|
+
}
|
|
68
66
|
}
|
|
69
67
|
}
|
|
@@ -46,7 +46,9 @@ export interface SummarizeAdapter<
|
|
|
46
46
|
/**
|
|
47
47
|
* Summarize the given text
|
|
48
48
|
*/
|
|
49
|
-
summarize: (
|
|
49
|
+
summarize: (
|
|
50
|
+
options: SummarizationOptions<TProviderOptions>,
|
|
51
|
+
) => Promise<SummarizationResult>
|
|
50
52
|
|
|
51
53
|
/**
|
|
52
54
|
* Stream summarization of the given text.
|
|
@@ -54,7 +56,7 @@ export interface SummarizeAdapter<
|
|
|
54
56
|
* non-streaming summarize and yield the result as a single chunk.
|
|
55
57
|
*/
|
|
56
58
|
summarizeStream?: (
|
|
57
|
-
options: SummarizationOptions
|
|
59
|
+
options: SummarizationOptions<TProviderOptions>,
|
|
58
60
|
) => AsyncIterable<StreamChunk>
|
|
59
61
|
}
|
|
60
62
|
|
|
@@ -91,7 +93,7 @@ export abstract class BaseSummarizeAdapter<
|
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
abstract summarize(
|
|
94
|
-
options: SummarizationOptions
|
|
96
|
+
options: SummarizationOptions<TProviderOptions>,
|
|
95
97
|
): Promise<SummarizationResult>
|
|
96
98
|
|
|
97
99
|
/**
|
|
@@ -99,7 +101,9 @@ export abstract class BaseSummarizeAdapter<
|
|
|
99
101
|
* Override this method in concrete implementations to enable streaming.
|
|
100
102
|
* If not overridden, the activity layer will fall back to non-streaming.
|
|
101
103
|
*/
|
|
102
|
-
summarizeStream?(
|
|
104
|
+
summarizeStream?(
|
|
105
|
+
options: SummarizationOptions<TProviderOptions>,
|
|
106
|
+
): AsyncIterable<StreamChunk>
|
|
103
107
|
|
|
104
108
|
protected generateId(): string {
|
|
105
109
|
return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { EventType } from '@ag-ui/core'
|
|
2
|
+
import { toRunErrorPayload } from '../error-payload'
|
|
3
|
+
import { BaseSummarizeAdapter } from './adapter'
|
|
4
|
+
import type {
|
|
5
|
+
StreamChunk,
|
|
6
|
+
SummarizationOptions,
|
|
7
|
+
SummarizationResult,
|
|
8
|
+
TextOptions,
|
|
9
|
+
} from '../../types'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Minimal contract for a text adapter that supports `chatStream`. Lets
|
|
13
|
+
* `ChatStreamSummarizeAdapter` work with any text adapter without coupling
|
|
14
|
+
* to a specific implementation.
|
|
15
|
+
*
|
|
16
|
+
* The provider-options shape is intentionally `any` here — the wrapper only
|
|
17
|
+
* forwards `modelOptions` straight through, so a text adapter with a richer
|
|
18
|
+
* per-model options type (e.g. `ResolveProviderOptions<TModel>`) is still
|
|
19
|
+
* acceptable. Summarize-level type safety is enforced via
|
|
20
|
+
* `SummarizationOptions<TProviderOptions>` on the wrapper itself.
|
|
21
|
+
*/
|
|
22
|
+
export interface ChatStreamCapable {
|
|
23
|
+
chatStream: (options: TextOptions<any>) => AsyncIterable<StreamChunk>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Extract the per-model `modelOptions` type a text adapter accepts. Used by
|
|
28
|
+
* provider summarize factories so their `modelOptions` IntelliSense matches
|
|
29
|
+
* what the underlying text adapter actually understands.
|
|
30
|
+
*/
|
|
31
|
+
export type InferTextProviderOptions<TAdapter> = TAdapter extends {
|
|
32
|
+
'~types': { providerOptions: infer P }
|
|
33
|
+
}
|
|
34
|
+
? P extends object
|
|
35
|
+
? P
|
|
36
|
+
: object
|
|
37
|
+
: object
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Summarize adapter that wraps any `ChatStreamCapable` text adapter and
|
|
41
|
+
* prompts it for summarization. Not tied to any wire format.
|
|
42
|
+
*/
|
|
43
|
+
export class ChatStreamSummarizeAdapter<
|
|
44
|
+
TModel extends string,
|
|
45
|
+
TProviderOptions extends object = Record<string, unknown>,
|
|
46
|
+
> extends BaseSummarizeAdapter<TModel, TProviderOptions> {
|
|
47
|
+
readonly name: string
|
|
48
|
+
|
|
49
|
+
private textAdapter: ChatStreamCapable
|
|
50
|
+
|
|
51
|
+
constructor(
|
|
52
|
+
textAdapter: ChatStreamCapable,
|
|
53
|
+
model: TModel,
|
|
54
|
+
name: string = 'chat-stream-summarize',
|
|
55
|
+
) {
|
|
56
|
+
super({}, model)
|
|
57
|
+
this.name = name
|
|
58
|
+
this.textAdapter = textAdapter
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async summarize(
|
|
62
|
+
options: SummarizationOptions<TProviderOptions>,
|
|
63
|
+
): Promise<SummarizationResult> {
|
|
64
|
+
const systemPrompt = this.buildSummarizationPrompt(options)
|
|
65
|
+
|
|
66
|
+
let summary = ''
|
|
67
|
+
const id = this.generateId()
|
|
68
|
+
let model = options.model
|
|
69
|
+
let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 }
|
|
70
|
+
|
|
71
|
+
options.logger.request(
|
|
72
|
+
`activity=summarize provider=${this.name} model=${options.model} text-length=${options.text.length} maxLength=${options.maxLength ?? 'unset'}`,
|
|
73
|
+
{ provider: this.name, model: options.model },
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
for await (const chunk of this.textAdapter.chatStream(
|
|
78
|
+
this.buildTextOptions(options, systemPrompt),
|
|
79
|
+
)) {
|
|
80
|
+
if (chunk.type === 'TEXT_MESSAGE_CONTENT') {
|
|
81
|
+
if (chunk.content) {
|
|
82
|
+
summary = chunk.content
|
|
83
|
+
} else if (chunk.delta) {
|
|
84
|
+
// Append delta only when present — a content-less chunk with no
|
|
85
|
+
// delta would otherwise concat literal `'undefined'`.
|
|
86
|
+
summary += chunk.delta
|
|
87
|
+
}
|
|
88
|
+
model = chunk.model || model
|
|
89
|
+
}
|
|
90
|
+
if (chunk.type === 'RUN_FINISHED') {
|
|
91
|
+
if (chunk.usage) {
|
|
92
|
+
usage = chunk.usage
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Surface failures: the underlying chatStream emits RUN_ERROR instead
|
|
96
|
+
// of throwing, so without this branch summarize() would return an
|
|
97
|
+
// empty summary and pretend a failed run succeeded.
|
|
98
|
+
if (chunk.type === 'RUN_ERROR') {
|
|
99
|
+
const message =
|
|
100
|
+
(chunk.error && typeof chunk.error.message === 'string'
|
|
101
|
+
? chunk.error.message
|
|
102
|
+
: null) ?? 'Summarization failed'
|
|
103
|
+
const code =
|
|
104
|
+
chunk.error && typeof chunk.error.code === 'string'
|
|
105
|
+
? chunk.error.code
|
|
106
|
+
: undefined
|
|
107
|
+
const err = new Error(message)
|
|
108
|
+
if (code) {
|
|
109
|
+
;(err as Error & { code?: string }).code = code
|
|
110
|
+
}
|
|
111
|
+
throw err
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
} catch (error: unknown) {
|
|
115
|
+
// Narrow before logging: raw SDK errors can carry request metadata
|
|
116
|
+
// (including auth headers) which we must never surface to user loggers.
|
|
117
|
+
options.logger.errors(`${this.name}.summarize fatal`, {
|
|
118
|
+
error: toRunErrorPayload(error, `${this.name}.summarize failed`),
|
|
119
|
+
source: `${this.name}.summarize`,
|
|
120
|
+
})
|
|
121
|
+
throw error
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return { id, model, summary, usage }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async *summarizeStream(
|
|
128
|
+
options: SummarizationOptions<TProviderOptions>,
|
|
129
|
+
): AsyncIterable<StreamChunk> {
|
|
130
|
+
const systemPrompt = this.buildSummarizationPrompt(options)
|
|
131
|
+
|
|
132
|
+
options.logger.request(
|
|
133
|
+
`activity=summarizeStream provider=${this.name} model=${options.model} text-length=${options.text.length} maxLength=${options.maxLength ?? 'unset'}`,
|
|
134
|
+
{ provider: this.name, model: options.model },
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
const id = this.generateId()
|
|
138
|
+
let summary = ''
|
|
139
|
+
let model = options.model
|
|
140
|
+
let usage: SummarizationResult['usage'] = {
|
|
141
|
+
promptTokens: 0,
|
|
142
|
+
completionTokens: 0,
|
|
143
|
+
totalTokens: 0,
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
for await (const chunk of this.textAdapter.chatStream(
|
|
148
|
+
this.buildTextOptions(options, systemPrompt),
|
|
149
|
+
)) {
|
|
150
|
+
// Accumulate the same way `summarize()` does so consumers see deltas
|
|
151
|
+
// AND the terminal `generation:result` event below carries the same
|
|
152
|
+
// final summary that non-streaming returns.
|
|
153
|
+
if (chunk.type === 'TEXT_MESSAGE_CONTENT') {
|
|
154
|
+
if (chunk.content) {
|
|
155
|
+
summary = chunk.content
|
|
156
|
+
} else if (chunk.delta) {
|
|
157
|
+
summary += chunk.delta
|
|
158
|
+
}
|
|
159
|
+
if (chunk.model) model = chunk.model
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Emit the GenerationClient-shaped result event just before the
|
|
163
|
+
// terminal RUN_FINISHED so subscribers (useSummarize) populate
|
|
164
|
+
// `result` before flipping `status` to success.
|
|
165
|
+
if (chunk.type === 'RUN_FINISHED') {
|
|
166
|
+
if (chunk.usage) usage = chunk.usage
|
|
167
|
+
if (chunk.model) model = chunk.model
|
|
168
|
+
yield {
|
|
169
|
+
type: EventType.CUSTOM,
|
|
170
|
+
name: 'generation:result',
|
|
171
|
+
value: { id, model, summary, usage } satisfies SummarizationResult,
|
|
172
|
+
model,
|
|
173
|
+
timestamp: Date.now(),
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
yield chunk
|
|
178
|
+
}
|
|
179
|
+
} catch (error: unknown) {
|
|
180
|
+
options.logger.errors(`${this.name}.summarizeStream fatal`, {
|
|
181
|
+
error: toRunErrorPayload(error, `${this.name}.summarizeStream failed`),
|
|
182
|
+
source: `${this.name}.summarizeStream`,
|
|
183
|
+
})
|
|
184
|
+
throw error
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Build the TextOptions passed to the underlying chatStream. Provider
|
|
190
|
+
* `modelOptions` from the summarize call are forwarded as-is so knobs like
|
|
191
|
+
* Anthropic cache headers, Gemini safety settings, or Ollama tuning params
|
|
192
|
+
* still reach the wire layer.
|
|
193
|
+
*/
|
|
194
|
+
protected buildTextOptions(
|
|
195
|
+
options: SummarizationOptions<TProviderOptions>,
|
|
196
|
+
systemPrompt: string,
|
|
197
|
+
): TextOptions<TProviderOptions> {
|
|
198
|
+
return {
|
|
199
|
+
model: options.model,
|
|
200
|
+
messages: [{ role: 'user', content: options.text }],
|
|
201
|
+
systemPrompts: [systemPrompt],
|
|
202
|
+
maxTokens: options.maxLength,
|
|
203
|
+
temperature: 0.3,
|
|
204
|
+
modelOptions: options.modelOptions,
|
|
205
|
+
logger: options.logger,
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
protected buildSummarizationPrompt(
|
|
210
|
+
options: SummarizationOptions<TProviderOptions>,
|
|
211
|
+
): string {
|
|
212
|
+
let prompt = 'You are a professional summarizer. '
|
|
213
|
+
|
|
214
|
+
switch (options.style) {
|
|
215
|
+
case 'bullet-points':
|
|
216
|
+
prompt += 'Provide a summary in bullet point format. '
|
|
217
|
+
break
|
|
218
|
+
case 'paragraph':
|
|
219
|
+
prompt += 'Provide a summary in paragraph format. '
|
|
220
|
+
break
|
|
221
|
+
case 'concise':
|
|
222
|
+
prompt += 'Provide a very concise summary in 1-2 sentences. '
|
|
223
|
+
break
|
|
224
|
+
default:
|
|
225
|
+
prompt += 'Provide a clear and concise summary. '
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (options.focus && options.focus.length > 0) {
|
|
229
|
+
prompt += `Focus on the following aspects: ${options.focus.join(', ')}. `
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (options.maxLength) {
|
|
233
|
+
prompt += `Keep the summary under ${options.maxLength} tokens. `
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return prompt
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -11,11 +11,7 @@ import { resolveDebugOption } from '../../logger/resolve'
|
|
|
11
11
|
import type { InternalLogger } from '../../logger/internal-logger'
|
|
12
12
|
import type { DebugOption } from '../../logger/types'
|
|
13
13
|
import type { SummarizeAdapter } from './adapter'
|
|
14
|
-
import type {
|
|
15
|
-
StreamChunk,
|
|
16
|
-
SummarizationOptions,
|
|
17
|
-
SummarizationResult,
|
|
18
|
-
} from '../../types'
|
|
14
|
+
import type { StreamChunk, SummarizationResult } from '../../types'
|
|
19
15
|
|
|
20
16
|
// ===========================
|
|
21
17
|
// Activity Kind
|
|
@@ -184,7 +180,7 @@ export function summarize<
|
|
|
184
180
|
async function runSummarize(
|
|
185
181
|
options: SummarizeActivityOptions<SummarizeAdapter<string, object>, false>,
|
|
186
182
|
): Promise<SummarizationResult> {
|
|
187
|
-
const { adapter, text, maxLength, style, focus } = options
|
|
183
|
+
const { adapter, text, maxLength, style, focus, modelOptions } = options
|
|
188
184
|
const model = adapter.model
|
|
189
185
|
const requestId = createId('summarize')
|
|
190
186
|
const inputLength = text.length
|
|
@@ -205,12 +201,13 @@ async function runSummarize(
|
|
|
205
201
|
inputLength,
|
|
206
202
|
})
|
|
207
203
|
|
|
208
|
-
const summarizeOptions
|
|
204
|
+
const summarizeOptions = {
|
|
209
205
|
model,
|
|
210
206
|
text,
|
|
211
207
|
maxLength,
|
|
212
208
|
style,
|
|
213
209
|
focus,
|
|
210
|
+
modelOptions,
|
|
214
211
|
logger,
|
|
215
212
|
}
|
|
216
213
|
|
|
@@ -253,7 +250,7 @@ async function runSummarize(
|
|
|
253
250
|
async function* runStreamingSummarize(
|
|
254
251
|
options: SummarizeActivityOptions<SummarizeAdapter<string, object>, true>,
|
|
255
252
|
): AsyncIterable<StreamChunk> {
|
|
256
|
-
const { adapter, text, maxLength, style, focus } = options
|
|
253
|
+
const { adapter, text, maxLength, style, focus, modelOptions } = options
|
|
257
254
|
const model = adapter.model
|
|
258
255
|
const logger: InternalLogger = resolveDebugOption(options.debug)
|
|
259
256
|
|
|
@@ -263,12 +260,13 @@ async function* runStreamingSummarize(
|
|
|
263
260
|
stream: true,
|
|
264
261
|
})
|
|
265
262
|
|
|
266
|
-
const summarizeOptions
|
|
263
|
+
const summarizeOptions = {
|
|
267
264
|
model,
|
|
268
265
|
text,
|
|
269
266
|
maxLength,
|
|
270
267
|
style,
|
|
271
268
|
focus,
|
|
269
|
+
modelOptions,
|
|
272
270
|
logger,
|
|
273
271
|
}
|
|
274
272
|
|
|
@@ -313,3 +311,8 @@ export type {
|
|
|
313
311
|
AnySummarizeAdapter,
|
|
314
312
|
} from './adapter'
|
|
315
313
|
export { BaseSummarizeAdapter } from './adapter'
|
|
314
|
+
export {
|
|
315
|
+
ChatStreamSummarizeAdapter,
|
|
316
|
+
type ChatStreamCapable,
|
|
317
|
+
type InferTextProviderOptions,
|
|
318
|
+
} from './chat-stream-summarize'
|
package/src/types.ts
CHANGED
|
@@ -111,15 +111,17 @@ export type SchemaInput = StandardJSONSchemaV1<any, any> | JSONSchema
|
|
|
111
111
|
export type InferSchemaType<T> =
|
|
112
112
|
T extends StandardJSONSchemaV1<infer TInput, unknown> ? TInput : unknown
|
|
113
113
|
|
|
114
|
-
export interface ToolCall {
|
|
114
|
+
export interface ToolCall<TMetadata = unknown> {
|
|
115
115
|
id: string
|
|
116
116
|
type: 'function'
|
|
117
117
|
function: {
|
|
118
118
|
name: string
|
|
119
119
|
arguments: string // JSON string
|
|
120
120
|
}
|
|
121
|
-
/** Provider-specific metadata to carry through the tool call lifecycle
|
|
122
|
-
|
|
121
|
+
/** Provider-specific metadata to carry through the tool call lifecycle.
|
|
122
|
+
* Typed per-adapter via `TToolCallMetadata`. For example,
|
|
123
|
+
* `@tanstack/ai-gemini` sets this to `{ thoughtSignature?: string }`. */
|
|
124
|
+
metadata?: TMetadata
|
|
123
125
|
}
|
|
124
126
|
|
|
125
127
|
// ============================================================================
|
|
@@ -309,7 +311,7 @@ export interface TextPart<TMetadata = unknown> {
|
|
|
309
311
|
metadata?: TMetadata
|
|
310
312
|
}
|
|
311
313
|
|
|
312
|
-
export interface ToolCallPart {
|
|
314
|
+
export interface ToolCallPart<TMetadata = unknown> {
|
|
313
315
|
type: 'tool-call'
|
|
314
316
|
id: string
|
|
315
317
|
name: string
|
|
@@ -323,6 +325,9 @@ export interface ToolCallPart {
|
|
|
323
325
|
}
|
|
324
326
|
/** Tool execution output (for client tools or after approval) */
|
|
325
327
|
output?: any
|
|
328
|
+
/** Provider-specific metadata that round-trips with the tool call.
|
|
329
|
+
* Typed per-adapter via `TToolCallMetadata`. */
|
|
330
|
+
metadata?: TMetadata
|
|
326
331
|
}
|
|
327
332
|
|
|
328
333
|
export interface ToolResultPart {
|
|
@@ -892,7 +897,7 @@ export interface TextMessageEndEvent extends AGUITextMessageEndEvent {
|
|
|
892
897
|
* Emitted when a tool call starts.
|
|
893
898
|
*
|
|
894
899
|
* @ag-ui/core provides: `toolCallId`, `toolCallName`, `parentMessageId?`
|
|
895
|
-
* TanStack AI adds: `model?`, `toolName` (deprecated alias), `index?`, `
|
|
900
|
+
* TanStack AI adds: `model?`, `toolName` (deprecated alias), `index?`, `metadata?`
|
|
896
901
|
*/
|
|
897
902
|
export interface ToolCallStartEvent extends AGUIToolCallStartEvent {
|
|
898
903
|
/** Model identifier for multi-model support */
|
|
@@ -904,8 +909,11 @@ export interface ToolCallStartEvent extends AGUIToolCallStartEvent {
|
|
|
904
909
|
toolName: string
|
|
905
910
|
/** Index for parallel tool calls */
|
|
906
911
|
index?: number
|
|
907
|
-
/** Provider-specific metadata to carry into the ToolCall
|
|
908
|
-
|
|
912
|
+
/** Provider-specific metadata to carry into the ToolCall.
|
|
913
|
+
* Untyped at the event layer because events flow through a discriminated
|
|
914
|
+
* union that does not survive generics; adapters cast it to their typed
|
|
915
|
+
* `TToolCallMetadata` shape when emitting. */
|
|
916
|
+
metadata?: Record<string, unknown>
|
|
909
917
|
}
|
|
910
918
|
|
|
911
919
|
/**
|
|
@@ -1049,6 +1057,106 @@ export interface CustomEvent extends AGUICustomEvent {
|
|
|
1049
1057
|
model?: string
|
|
1050
1058
|
}
|
|
1051
1059
|
|
|
1060
|
+
/**
|
|
1061
|
+
* Final event of a streaming structured-output run. Carries the validated
|
|
1062
|
+
* `object` (typed as `T` after the orchestrator runs Standard Schema parsing),
|
|
1063
|
+
* the `raw` JSON text that produced it, and — for thinking/reasoning models —
|
|
1064
|
+
* the accumulated reasoning text. Adapters emit this with `T = unknown`; the
|
|
1065
|
+
* chat orchestrator narrows to the schema's inferred type after validation.
|
|
1066
|
+
*
|
|
1067
|
+
* `reasoning` is `undefined` when the model produced none (most non-thinking
|
|
1068
|
+
* models) and when the underlying adapter doesn't expose reasoning streams.
|
|
1069
|
+
*
|
|
1070
|
+
* `name` is a string literal so consumers can narrow directly:
|
|
1071
|
+
*
|
|
1072
|
+
* ```ts
|
|
1073
|
+
* if (chunk.type === 'CUSTOM' && chunk.name === 'structured-output.complete') {
|
|
1074
|
+
* chunk.value.object // typed as T
|
|
1075
|
+
* }
|
|
1076
|
+
* ```
|
|
1077
|
+
*/
|
|
1078
|
+
export interface StructuredOutputCompleteEvent<T = unknown> extends Omit<
|
|
1079
|
+
CustomEvent,
|
|
1080
|
+
'name' | 'value'
|
|
1081
|
+
> {
|
|
1082
|
+
name: 'structured-output.complete'
|
|
1083
|
+
value: { object: T; raw: string; reasoning?: string }
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
/**
|
|
1087
|
+
* Emitted when a server tool requires approval before execution. The agent
|
|
1088
|
+
* loop yields this and pauses — `structured-output.complete` will not fire
|
|
1089
|
+
* for that run. The shape is fixed by the orchestrator's tool-approval flow
|
|
1090
|
+
* (see `buildApprovalChunks` in `activities/chat/index.ts`).
|
|
1091
|
+
*/
|
|
1092
|
+
export interface ApprovalRequestedEvent extends Omit<
|
|
1093
|
+
CustomEvent,
|
|
1094
|
+
'name' | 'value'
|
|
1095
|
+
> {
|
|
1096
|
+
name: 'approval-requested'
|
|
1097
|
+
value: {
|
|
1098
|
+
toolCallId: string
|
|
1099
|
+
toolName: string
|
|
1100
|
+
input: unknown
|
|
1101
|
+
approval: { id: string; needsApproval: true }
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
/**
|
|
1106
|
+
* Emitted when a client tool is invoked. The agent loop yields this and
|
|
1107
|
+
* pauses to let the caller run the tool client-side — `structured-output.complete`
|
|
1108
|
+
* will not fire for that run. Shape fixed by `buildClientToolChunks` in
|
|
1109
|
+
* `activities/chat/index.ts`.
|
|
1110
|
+
*/
|
|
1111
|
+
export interface ToolInputAvailableEvent extends Omit<
|
|
1112
|
+
CustomEvent,
|
|
1113
|
+
'name' | 'value'
|
|
1114
|
+
> {
|
|
1115
|
+
name: 'tool-input-available'
|
|
1116
|
+
value: {
|
|
1117
|
+
toolCallId: string
|
|
1118
|
+
toolName: string
|
|
1119
|
+
input: unknown
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
/**
|
|
1124
|
+
* Public type for streams returned by `chat({ outputSchema, stream: true })`.
|
|
1125
|
+
*
|
|
1126
|
+
* Yields all standard `StreamChunk` lifecycle events plus the three tagged
|
|
1127
|
+
* `CUSTOM` events the orchestrator can emit through this path:
|
|
1128
|
+
* - `structured-output.complete` — terminal event with typed `value.object: T`
|
|
1129
|
+
* - `approval-requested` — server tool needs approval (pauses the run)
|
|
1130
|
+
* - `tool-input-available` — client tool invocation (pauses the run)
|
|
1131
|
+
*
|
|
1132
|
+
* Each variant has a literal `name`, so a single discriminated narrow gives
|
|
1133
|
+
* you a typed `value` with no helper or cast:
|
|
1134
|
+
*
|
|
1135
|
+
* ```ts
|
|
1136
|
+
* for await (const chunk of stream) {
|
|
1137
|
+
* if (chunk.type === 'CUSTOM' && chunk.name === 'structured-output.complete') {
|
|
1138
|
+
* chunk.value.object // typed as T
|
|
1139
|
+
* } else if (chunk.type === 'CUSTOM' && chunk.name === 'approval-requested') {
|
|
1140
|
+
* chunk.value.toolCallId // typed as string
|
|
1141
|
+
* }
|
|
1142
|
+
* }
|
|
1143
|
+
* ```
|
|
1144
|
+
*
|
|
1145
|
+
* Caveat: tools can emit arbitrary user-defined custom events via the
|
|
1146
|
+
* `emitCustomEvent(name, value)` context API. Those flow through this stream
|
|
1147
|
+
* at runtime but are intentionally absent from this type — including a bare
|
|
1148
|
+
* `CustomEvent` (whose `value: any` would poison the union) would collapse
|
|
1149
|
+
* `chunk.value` back to `any` after the narrow. If you rely on
|
|
1150
|
+
* `emitCustomEvent` plus `outputSchema + stream: true`, branch on `CUSTOM`
|
|
1151
|
+
* outside the literal-`name` narrows or cast explicitly.
|
|
1152
|
+
*/
|
|
1153
|
+
export type StructuredOutputStream<T = unknown> = AsyncIterable<
|
|
1154
|
+
| Exclude<StreamChunk, CustomEvent>
|
|
1155
|
+
| StructuredOutputCompleteEvent<T>
|
|
1156
|
+
| ApprovalRequestedEvent
|
|
1157
|
+
| ToolInputAvailableEvent
|
|
1158
|
+
>
|
|
1159
|
+
|
|
1052
1160
|
// ============================================================================
|
|
1053
1161
|
// AG-UI Reasoning Event Interfaces
|
|
1054
1162
|
// ============================================================================
|
|
@@ -1171,12 +1279,16 @@ export interface TextCompletionChunk {
|
|
|
1171
1279
|
}
|
|
1172
1280
|
}
|
|
1173
1281
|
|
|
1174
|
-
export interface SummarizationOptions
|
|
1282
|
+
export interface SummarizationOptions<
|
|
1283
|
+
TProviderOptions extends object = Record<string, unknown>,
|
|
1284
|
+
> {
|
|
1175
1285
|
model: string
|
|
1176
1286
|
text: string
|
|
1177
1287
|
maxLength?: number
|
|
1178
1288
|
style?: 'bullet-points' | 'paragraph' | 'concise'
|
|
1179
1289
|
focus?: Array<string>
|
|
1290
|
+
/** Provider-specific options forwarded by the summarize() activity. */
|
|
1291
|
+
modelOptions?: TProviderOptions
|
|
1180
1292
|
/**
|
|
1181
1293
|
* Internal logger threaded from the summarize() entry point. Adapters must
|
|
1182
1294
|
* call logger.request() before the SDK call and logger.errors() in catch blocks.
|
|
@@ -1205,7 +1317,7 @@ export interface SummarizationResult {
|
|
|
1205
1317
|
*/
|
|
1206
1318
|
export interface ImageGenerationOptions<
|
|
1207
1319
|
TProviderOptions extends object = object,
|
|
1208
|
-
TSize extends string = string,
|
|
1320
|
+
TSize extends string | undefined = string,
|
|
1209
1321
|
> {
|
|
1210
1322
|
/** The model to use for image generation */
|
|
1211
1323
|
model: string
|
|
@@ -1335,7 +1447,7 @@ export interface AudioGenerationResult {
|
|
|
1335
1447
|
*/
|
|
1336
1448
|
export interface VideoGenerationOptions<
|
|
1337
1449
|
TProviderOptions extends object = object,
|
|
1338
|
-
TSize extends string = string,
|
|
1450
|
+
TSize extends string | undefined = string,
|
|
1339
1451
|
> {
|
|
1340
1452
|
/** The model to use for video generation */
|
|
1341
1453
|
model: string
|