@tanstack/ai 0.40.0 → 0.42.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/agent-loop-strategies.d.ts +40 -3
- package/dist/esm/activities/chat/agent-loop-strategies.js +4 -0
- package/dist/esm/activities/chat/agent-loop-strategies.js.map +1 -1
- package/dist/esm/activities/chat/index.d.ts +5 -0
- package/dist/esm/activities/chat/index.js +102 -33
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.js +7 -0
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/stream/message-updaters.d.ts +2 -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 +18 -1
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-definition.d.ts +14 -11
- package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -1
- package/dist/esm/activities/generateAudio/index.d.ts +1 -1
- package/dist/esm/activities/generateAudio/index.js.map +1 -1
- package/dist/esm/activities/generateImage/index.d.ts +1 -1
- package/dist/esm/activities/generateImage/index.js +1 -1
- package/dist/esm/activities/generateImage/index.js.map +1 -1
- package/dist/esm/activities/generateSpeech/index.d.ts +1 -1
- package/dist/esm/activities/generateSpeech/index.js.map +1 -1
- package/dist/esm/activities/generateTranscription/index.d.ts +1 -1
- package/dist/esm/activities/generateTranscription/index.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.d.ts +12 -12
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js +4 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/realtime/event-emitter.d.ts +5 -0
- package/dist/esm/realtime/event-emitter.js +27 -0
- package/dist/esm/realtime/event-emitter.js.map +1 -0
- package/dist/esm/realtime/index.d.ts +1 -0
- package/dist/esm/realtime/index.js.map +1 -1
- package/dist/esm/realtime/types.d.ts +9 -1
- package/dist/esm/types.d.ts +43 -2
- package/package.json +1 -1
- package/skills/ai-core/chat-experience/SKILL.md +58 -0
- package/skills/ai-core/media-generation/SKILL.md +42 -2
- package/skills/ai-core/middleware/SKILL.md +18 -3
- package/skills/ai-core/tool-calling/SKILL.md +15 -1
- package/src/activities/chat/agent-loop-strategies.ts +43 -3
- package/src/activities/chat/index.ts +144 -36
- package/src/activities/chat/messages.ts +9 -0
- package/src/activities/chat/stream/message-updaters.ts +7 -1
- package/src/activities/chat/stream/processor.ts +30 -2
- package/src/activities/chat/tools/tool-definition.ts +33 -11
- package/src/activities/generateAudio/index.ts +2 -2
- package/src/activities/generateImage/index.ts +2 -2
- package/src/activities/generateSpeech/index.ts +2 -2
- package/src/activities/generateTranscription/index.ts +2 -2
- package/src/activities/generateVideo/index.ts +29 -15
- package/src/index.ts +3 -1
- package/src/realtime/event-emitter.ts +46 -0
- package/src/realtime/index.ts +2 -0
- package/src/realtime/types.ts +9 -0
- package/src/types.ts +43 -2
|
@@ -17,10 +17,10 @@ import {
|
|
|
17
17
|
runGenerationFinish,
|
|
18
18
|
runGenerationStart,
|
|
19
19
|
runGenerationUsage,
|
|
20
|
-
} from '../middleware'
|
|
20
|
+
} from '../middleware/run'
|
|
21
21
|
import type { InternalLogger } from '../../logger/internal-logger'
|
|
22
22
|
import type { DebugOption } from '../../logger/types'
|
|
23
|
-
import type { GenerationMiddleware } from '../middleware'
|
|
23
|
+
import type { GenerationMiddleware } from '../middleware/types'
|
|
24
24
|
import type { VideoAdapter } from './adapter'
|
|
25
25
|
import type {
|
|
26
26
|
MediaPrompt,
|
|
@@ -47,7 +47,7 @@ export const kind = 'video' as const
|
|
|
47
47
|
* Extract provider options from a VideoAdapter via ~types.
|
|
48
48
|
*/
|
|
49
49
|
export type VideoProviderOptions<TAdapter> =
|
|
50
|
-
TAdapter extends VideoAdapter<any, any, any, any>
|
|
50
|
+
TAdapter extends VideoAdapter<any, any, any, any, any, any>
|
|
51
51
|
? TAdapter['~types']['providerOptions']
|
|
52
52
|
: object
|
|
53
53
|
|
|
@@ -55,7 +55,14 @@ export type VideoProviderOptions<TAdapter> =
|
|
|
55
55
|
* Extract the size type for a VideoAdapter's model via ~types.
|
|
56
56
|
*/
|
|
57
57
|
export type VideoSizeForAdapter<TAdapter> =
|
|
58
|
-
TAdapter extends VideoAdapter<
|
|
58
|
+
TAdapter extends VideoAdapter<
|
|
59
|
+
infer TModel,
|
|
60
|
+
any,
|
|
61
|
+
any,
|
|
62
|
+
infer TSizeMap,
|
|
63
|
+
any,
|
|
64
|
+
any
|
|
65
|
+
>
|
|
59
66
|
? TModel extends keyof TSizeMap
|
|
60
67
|
? TSizeMap[TModel]
|
|
61
68
|
: string
|
|
@@ -68,7 +75,14 @@ export type VideoSizeForAdapter<TAdapter> =
|
|
|
68
75
|
* without a map fall back to the full MediaPrompt.
|
|
69
76
|
*/
|
|
70
77
|
export type VideoPromptForAdapter<TAdapter> =
|
|
71
|
-
TAdapter extends VideoAdapter<
|
|
78
|
+
TAdapter extends VideoAdapter<
|
|
79
|
+
infer TModel,
|
|
80
|
+
any,
|
|
81
|
+
any,
|
|
82
|
+
any,
|
|
83
|
+
infer ModsByName,
|
|
84
|
+
any
|
|
85
|
+
>
|
|
72
86
|
? string extends keyof ModsByName
|
|
73
87
|
? MediaPrompt
|
|
74
88
|
: TModel extends keyof ModsByName
|
|
@@ -108,7 +122,7 @@ function createId(prefix: string): string {
|
|
|
108
122
|
* The model is extracted from the adapter's model property.
|
|
109
123
|
*/
|
|
110
124
|
interface VideoActivityBaseOptions<
|
|
111
|
-
TAdapter extends VideoAdapter<string, any, any, any>,
|
|
125
|
+
TAdapter extends VideoAdapter<string, any, any, any, any, any>,
|
|
112
126
|
> {
|
|
113
127
|
/** The video adapter to use (must be created with a model) */
|
|
114
128
|
adapter: TAdapter & { kind: typeof kind }
|
|
@@ -124,7 +138,7 @@ interface VideoActivityBaseOptions<
|
|
|
124
138
|
* @experimental Video generation is an experimental feature and may change.
|
|
125
139
|
*/
|
|
126
140
|
export type VideoCreateOptions<
|
|
127
|
-
TAdapter extends VideoAdapter<string, any, any, any>,
|
|
141
|
+
TAdapter extends VideoAdapter<string, any, any, any, any, any>,
|
|
128
142
|
TStream extends boolean = false,
|
|
129
143
|
> = VideoActivityBaseOptions<TAdapter> & {
|
|
130
144
|
/** Request type - create a new job (default if not specified) */
|
|
@@ -191,7 +205,7 @@ export type VideoCreateOptions<
|
|
|
191
205
|
* @experimental Video generation is an experimental feature and may change.
|
|
192
206
|
*/
|
|
193
207
|
export interface VideoStatusOptions<
|
|
194
|
-
TAdapter extends VideoAdapter<string, any, any, any>,
|
|
208
|
+
TAdapter extends VideoAdapter<string, any, any, any, any, any>,
|
|
195
209
|
> extends VideoActivityBaseOptions<TAdapter> {
|
|
196
210
|
/** Request type - get job status */
|
|
197
211
|
request: 'status'
|
|
@@ -205,7 +219,7 @@ export interface VideoStatusOptions<
|
|
|
205
219
|
* @experimental Video generation is an experimental feature and may change.
|
|
206
220
|
*/
|
|
207
221
|
export interface VideoUrlOptions<
|
|
208
|
-
TAdapter extends VideoAdapter<string, any, any, any>,
|
|
222
|
+
TAdapter extends VideoAdapter<string, any, any, any, any, any>,
|
|
209
223
|
> extends VideoActivityBaseOptions<TAdapter> {
|
|
210
224
|
/** Request type - get video URL */
|
|
211
225
|
request: 'url'
|
|
@@ -220,7 +234,7 @@ export interface VideoUrlOptions<
|
|
|
220
234
|
* @experimental Video generation is an experimental feature and may change.
|
|
221
235
|
*/
|
|
222
236
|
export type VideoActivityOptions<
|
|
223
|
-
TAdapter extends VideoAdapter<string, any, any, any>,
|
|
237
|
+
TAdapter extends VideoAdapter<string, any, any, any, any, any>,
|
|
224
238
|
TRequest extends 'create' | 'status' | 'url' = 'create',
|
|
225
239
|
TStream extends boolean = false,
|
|
226
240
|
> = TRequest extends 'status'
|
|
@@ -296,7 +310,7 @@ export type VideoActivityResult<
|
|
|
296
310
|
* ```
|
|
297
311
|
*/
|
|
298
312
|
export function generateVideo<
|
|
299
|
-
TAdapter extends VideoAdapter<string, any, any, any>,
|
|
313
|
+
TAdapter extends VideoAdapter<string, any, any, any, any, any>,
|
|
300
314
|
TStream extends boolean = false,
|
|
301
315
|
>(
|
|
302
316
|
options: VideoCreateOptions<TAdapter, TStream>,
|
|
@@ -314,7 +328,7 @@ export function generateVideo<
|
|
|
314
328
|
* Internal implementation of non-streaming video job creation.
|
|
315
329
|
*/
|
|
316
330
|
async function runCreateVideoJob<
|
|
317
|
-
TAdapter extends VideoAdapter<string, any, any, any>,
|
|
331
|
+
TAdapter extends VideoAdapter<string, any, any, any, any, any>,
|
|
318
332
|
>(options: VideoCreateOptions<TAdapter, boolean>): Promise<VideoJobResult> {
|
|
319
333
|
const { adapter, prompt, size, duration, modelOptions, middleware } = options
|
|
320
334
|
const model = adapter.model
|
|
@@ -383,7 +397,7 @@ function sleep(ms: number): Promise<void> {
|
|
|
383
397
|
* Handles the full job lifecycle: create job → poll for status → stream updates → yield final result.
|
|
384
398
|
*/
|
|
385
399
|
async function* runStreamingVideoGeneration<
|
|
386
|
-
TAdapter extends VideoAdapter<string, any, any, any>,
|
|
400
|
+
TAdapter extends VideoAdapter<string, any, any, any, any, any>,
|
|
387
401
|
>(options: VideoCreateOptions<TAdapter, true>): AsyncIterable<StreamChunk> {
|
|
388
402
|
const { adapter, prompt, size, duration, modelOptions, middleware } = options
|
|
389
403
|
const model = adapter.model
|
|
@@ -582,7 +596,7 @@ async function* runStreamingVideoGeneration<
|
|
|
582
596
|
* ```
|
|
583
597
|
*/
|
|
584
598
|
export async function getVideoJobStatus<
|
|
585
|
-
TAdapter extends VideoAdapter<string, any, any, any>,
|
|
599
|
+
TAdapter extends VideoAdapter<string, any, any, any, any, any>,
|
|
586
600
|
>(options: {
|
|
587
601
|
adapter: TAdapter & { kind: typeof kind }
|
|
588
602
|
jobId: string
|
|
@@ -692,7 +706,7 @@ export async function getVideoJobStatus<
|
|
|
692
706
|
* Create typed options for the generateVideo() function without executing.
|
|
693
707
|
*/
|
|
694
708
|
export function createVideoOptions<
|
|
695
|
-
TAdapter extends VideoAdapter<string, any, any, any>,
|
|
709
|
+
TAdapter extends VideoAdapter<string, any, any, any, any, any>,
|
|
696
710
|
TStream extends boolean = false,
|
|
697
711
|
>(
|
|
698
712
|
options: VideoCreateOptions<TAdapter, TStream>,
|
package/src/index.ts
CHANGED
|
@@ -93,6 +93,7 @@ export { brandProviderTool } from './tools/provider-tool'
|
|
|
93
93
|
// Agent loop strategies
|
|
94
94
|
export {
|
|
95
95
|
maxIterations,
|
|
96
|
+
maxToolCalls,
|
|
96
97
|
untilFinishReason,
|
|
97
98
|
combineStrategies,
|
|
98
99
|
} from './activities/chat/agent-loop-strategies'
|
|
@@ -179,12 +180,13 @@ export { normalizeSystemPrompts } from './system-prompts'
|
|
|
179
180
|
export { detectImageMimeType } from './utils'
|
|
180
181
|
|
|
181
182
|
// Realtime
|
|
182
|
-
export { realtimeToken } from './realtime/index'
|
|
183
|
+
export { realtimeToken, createRealtimeEventEmitter } from './realtime/index'
|
|
183
184
|
export type {
|
|
184
185
|
RealtimeToken,
|
|
185
186
|
RealtimeTokenAdapter,
|
|
186
187
|
RealtimeTokenOptions,
|
|
187
188
|
RealtimeSessionConfig,
|
|
189
|
+
RealtimeToolConfig,
|
|
188
190
|
VADConfig,
|
|
189
191
|
RealtimeMessage,
|
|
190
192
|
RealtimeMessagePart,
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
RealtimeEvent,
|
|
3
|
+
RealtimeEventHandler,
|
|
4
|
+
RealtimeEventPayloads,
|
|
5
|
+
} from './types'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Handlers are stored with a `never` payload so any specific
|
|
9
|
+
* `RealtimeEventHandler<TEvent>` is assignable in (contravariance), keeping the
|
|
10
|
+
* heterogeneous handler map type-safe without `any`. `emit` narrows back to the
|
|
11
|
+
* event's real payload type via its signature; the lone `as never` at the call
|
|
12
|
+
* site is the inverse of that stored `never`.
|
|
13
|
+
*/
|
|
14
|
+
type StoredHandler = (payload: never) => void
|
|
15
|
+
|
|
16
|
+
export function createRealtimeEventEmitter() {
|
|
17
|
+
const eventHandlers = new Map<RealtimeEvent, Set<StoredHandler>>()
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
emit<TEvent extends RealtimeEvent>(
|
|
21
|
+
event: TEvent,
|
|
22
|
+
payload: RealtimeEventPayloads[TEvent],
|
|
23
|
+
) {
|
|
24
|
+
const handlers = eventHandlers.get(event)
|
|
25
|
+
if (!handlers) return
|
|
26
|
+
for (const handler of handlers) {
|
|
27
|
+
handler(payload as never)
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
on<TEvent extends RealtimeEvent>(
|
|
31
|
+
event: TEvent,
|
|
32
|
+
handler: RealtimeEventHandler<TEvent>,
|
|
33
|
+
): () => void {
|
|
34
|
+
let handlers = eventHandlers.get(event)
|
|
35
|
+
if (!handlers) {
|
|
36
|
+
handlers = new Set<StoredHandler>()
|
|
37
|
+
eventHandlers.set(event, handlers)
|
|
38
|
+
}
|
|
39
|
+
handlers.add(handler)
|
|
40
|
+
|
|
41
|
+
return () => {
|
|
42
|
+
handlers.delete(handler)
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/realtime/index.ts
CHANGED
package/src/realtime/types.ts
CHANGED
|
@@ -4,6 +4,8 @@ import type { AnyClientTool } from '../activities/chat/tools/tool-definition'
|
|
|
4
4
|
// Token Types
|
|
5
5
|
// ============================================================================
|
|
6
6
|
|
|
7
|
+
import type { UsageInfo } from '../activities/chat/middleware/types'
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* Voice activity detection configuration
|
|
9
11
|
*/
|
|
@@ -24,6 +26,7 @@ export interface RealtimeToolConfig {
|
|
|
24
26
|
name: string
|
|
25
27
|
description: string
|
|
26
28
|
inputSchema?: Record<string, any>
|
|
29
|
+
outputSchema?: Record<string, any>
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
/**
|
|
@@ -246,6 +249,8 @@ export type RealtimeEvent =
|
|
|
246
249
|
| 'message_complete'
|
|
247
250
|
| 'interrupted'
|
|
248
251
|
| 'error'
|
|
252
|
+
| 'go_away' // Event that signals that the current connection will soon be terminated
|
|
253
|
+
| 'usage'
|
|
249
254
|
|
|
250
255
|
/**
|
|
251
256
|
* Event payloads for realtime events
|
|
@@ -263,6 +268,8 @@ export interface RealtimeEventPayloads {
|
|
|
263
268
|
message_complete: { message: RealtimeMessage }
|
|
264
269
|
interrupted: { messageId?: string }
|
|
265
270
|
error: { error: Error }
|
|
271
|
+
go_away: { timeLeft?: string }
|
|
272
|
+
usage: UsageInfo
|
|
266
273
|
}
|
|
267
274
|
|
|
268
275
|
/**
|
|
@@ -355,6 +362,8 @@ export interface RealtimeConnection {
|
|
|
355
362
|
// Session management
|
|
356
363
|
/** Update session configuration */
|
|
357
364
|
updateSession: (config: Partial<RealtimeSessionConfig>) => void
|
|
365
|
+
/** Update the ephemeral token (e.g. on refresh); provider may reconnect */
|
|
366
|
+
updateToken?: (token: RealtimeToken) => void
|
|
358
367
|
/** Interrupt the current response */
|
|
359
368
|
interrupt: () => void
|
|
360
369
|
|
package/src/types.ts
CHANGED
|
@@ -372,6 +372,15 @@ export interface ToolCallPart<TMetadata = unknown> {
|
|
|
372
372
|
id: string
|
|
373
373
|
name: string
|
|
374
374
|
arguments: string // JSON string (may be incomplete)
|
|
375
|
+
/**
|
|
376
|
+
* Parsed tool input. Set from the parsed arguments once they are complete
|
|
377
|
+
* (`state: 'input-complete'` and later). `undefined` while the raw
|
|
378
|
+
* `arguments` string is still streaming, and may stay `undefined` for a call
|
|
379
|
+
* that terminates in an error state — the raw `arguments` string is always
|
|
380
|
+
* available as a fallback. Typed per-tool on the client `ToolCallPart` (see
|
|
381
|
+
* `@tanstack/ai-client`); `unknown` on this base type.
|
|
382
|
+
*/
|
|
383
|
+
input?: unknown
|
|
375
384
|
state: ToolCallState
|
|
376
385
|
/** Approval metadata if tool requires user approval */
|
|
377
386
|
approval?: {
|
|
@@ -822,12 +831,24 @@ export interface ResponseFormat<TData = any> {
|
|
|
822
831
|
* State passed to agent loop strategy for determining whether to continue
|
|
823
832
|
*/
|
|
824
833
|
export interface AgentLoopState {
|
|
825
|
-
/** Current iteration count (0-indexed) */
|
|
834
|
+
/** Current iteration count (0-indexed). One iteration = one model turn. */
|
|
826
835
|
iterationCount: number
|
|
827
836
|
/** Current messages array */
|
|
828
837
|
messages: Array<ModelMessage>
|
|
829
838
|
/** Finish reason from the last response */
|
|
830
839
|
finishReason: string | null
|
|
840
|
+
/**
|
|
841
|
+
* Cumulative tool calls counted so far in this run (model-emitted during the
|
|
842
|
+
* agent loop, including ones skipped by `maxToolCallsPerTurn`, and pending
|
|
843
|
+
* tools from the inbound message list when resumed). Not a recount of full
|
|
844
|
+
* message history; not model turns.
|
|
845
|
+
*/
|
|
846
|
+
toolCallCount: number
|
|
847
|
+
/**
|
|
848
|
+
* Tool calls in the most recent budgeted batch — a live model turn or a
|
|
849
|
+
* pending/resume batch (0 when the last phase produced no tool calls).
|
|
850
|
+
*/
|
|
851
|
+
lastTurnToolCallCount: number
|
|
831
852
|
}
|
|
832
853
|
|
|
833
854
|
/**
|
|
@@ -838,8 +859,10 @@ export interface AgentLoopState {
|
|
|
838
859
|
*
|
|
839
860
|
* @example
|
|
840
861
|
* ```typescript
|
|
841
|
-
* // Continue for up to 5 iterations
|
|
862
|
+
* // Continue for up to 5 iterations (model turns, not tool calls)
|
|
842
863
|
* const strategy: AgentLoopStrategy = ({ iterationCount }) => iterationCount < 5;
|
|
864
|
+
* // Cap total tool calls across the run
|
|
865
|
+
* const byTools: AgentLoopStrategy = ({ toolCallCount }) => toolCallCount < 20;
|
|
843
866
|
* ```
|
|
844
867
|
*/
|
|
845
868
|
export type AgentLoopStrategy = (state: AgentLoopState) => boolean
|
|
@@ -876,6 +899,24 @@ export interface TextOptions<
|
|
|
876
899
|
*/
|
|
877
900
|
systemPrompts?: Array<SystemPrompt>
|
|
878
901
|
agentLoopStrategy?: AgentLoopStrategy
|
|
902
|
+
/**
|
|
903
|
+
* Maximum number of tool calls to **execute** from a single model turn (or
|
|
904
|
+
* pending/resume batch). `0` skips all execution for that batch.
|
|
905
|
+
*
|
|
906
|
+
* Models can emit many parallel tool calls in one turn. `agentLoopStrategy`
|
|
907
|
+
* (including `maxIterations` / `maxToolCalls`) is only evaluated between
|
|
908
|
+
* turns, so without this cap a single runaway turn can still execute an
|
|
909
|
+
* unbounded fan-out.
|
|
910
|
+
*
|
|
911
|
+
* When set, only the first `maxToolCallsPerTurn` calls are executed; the
|
|
912
|
+
* remainder receive error tool results so the message history stays
|
|
913
|
+
* consistent. Unset means no per-turn execution cap. Must be a non-negative
|
|
914
|
+
* finite number when set.
|
|
915
|
+
*
|
|
916
|
+
* Pair with the `maxToolCalls(n)` strategy for a cumulative **emitted**-call
|
|
917
|
+
* budget across the run (skipped calls still count toward that budget).
|
|
918
|
+
*/
|
|
919
|
+
maxToolCallsPerTurn?: number
|
|
879
920
|
/**
|
|
880
921
|
* Optional configuration for lazy-tool discovery (tools marked `lazy: true`).
|
|
881
922
|
* Tunes how much of each lazy tool's description appears in the discovery
|