@tanstack/ai 0.57.0 → 0.59.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/agents/define-agent.d.ts +81 -0
- package/dist/esm/activities/chat/agents/define-agent.js +34 -0
- package/dist/esm/activities/chat/agents/define-agent.js.map +1 -0
- package/dist/esm/activities/chat/agents/route.d.ts +53 -0
- package/dist/esm/activities/chat/agents/route.js +59 -0
- package/dist/esm/activities/chat/agents/route.js.map +1 -0
- package/dist/esm/activities/chat/agents/spawn.d.ts +124 -0
- package/dist/esm/activities/chat/agents/spawn.js +490 -0
- package/dist/esm/activities/chat/agents/spawn.js.map +1 -0
- package/dist/esm/activities/chat/agents/turn.d.ts +36 -0
- package/dist/esm/activities/chat/agents/turn.js +78 -0
- package/dist/esm/activities/chat/agents/turn.js.map +1 -0
- package/dist/esm/activities/chat/index.d.ts +13 -3
- package/dist/esm/activities/chat/index.js +345 -19
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.d.ts +7 -1
- package/dist/esm/activities/chat/messages.js +94 -18
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/middleware/run-store.d.ts +43 -7
- package/dist/esm/activities/chat/middleware/run-store.js +8 -1
- package/dist/esm/activities/chat/middleware/run-store.js.map +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +50 -3
- package/dist/esm/activities/chat/middleware/types.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +46 -0
- package/dist/esm/activities/chat/stream/processor.js +280 -7
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +17 -3
- package/dist/esm/activities/chat/tools/tool-calls.js +56 -7
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/generateAudio/index.js +1 -1
- package/dist/esm/activities/generateImage/index.js +1 -1
- package/dist/esm/activities/generateLiveVideo/index.js +1 -1
- package/dist/esm/activities/generateSpeech/index.js +1 -1
- package/dist/esm/activities/generateTranscription/index.js +1 -1
- package/dist/esm/activities/generateVoice/index.js +1 -1
- package/dist/esm/activities/generateWorld/index.js +1 -1
- package/dist/esm/activities/index.d.ts +3 -0
- package/dist/esm/activities/index.js +5 -3
- package/dist/esm/activities/summarize/index.js +1 -1
- package/dist/esm/client.d.ts +5 -36
- package/dist/esm/client.js +4 -37
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +7 -4
- package/dist/esm/middlewares/content-guard.js.map +1 -1
- package/dist/esm/stream-to-response.js +12 -6
- package/dist/esm/stream-to-response.js.map +1 -1
- package/dist/esm/strip-to-spec-middleware.js +2 -1
- package/dist/esm/strip-to-spec-middleware.js.map +1 -1
- package/dist/esm/types.d.ts +128 -89
- package/dist/esm/utilities/adapter-yield-chunk.d.ts +5 -1
- package/dist/esm/utilities/ag-ui-usage.d.ts +9 -9
- package/dist/esm/utilities/ag-ui-usage.js +66 -3
- package/dist/esm/utilities/ag-ui-usage.js.map +1 -1
- package/dist/esm/utilities/ag-ui-wire.js +56 -0
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/durability-batch.d.ts +8 -0
- package/dist/esm/utilities/durability-batch.js +45 -0
- package/dist/esm/utilities/durability-batch.js.map +1 -0
- package/dist/esm/utilities/normalize-stream-chunk.js +7 -2
- package/dist/esm/utilities/normalize-stream-chunk.js.map +1 -1
- package/dist/esm/utilities/spec-event-keys.js +13 -8
- package/dist/esm/utilities/spec-event-keys.js.map +1 -1
- package/dist/esm/utilities/subagent-wire.d.ts +36 -0
- package/dist/esm/utilities/subagent-wire.js +131 -0
- package/dist/esm/utilities/subagent-wire.js.map +1 -0
- package/package.json +4 -4
- package/skills/ai-core/adapter-configuration/references/grok-adapter.md +1 -1
- package/skills/ai-core/media-generation/SKILL.md +2 -2
- package/skills/ai-core/middleware/SKILL.md +7 -4
- package/src/activities/chat/agents/define-agent.ts +121 -0
- package/src/activities/chat/agents/route.ts +115 -0
- package/src/activities/chat/agents/spawn.ts +806 -0
- package/src/activities/chat/agents/turn.ts +151 -0
- package/src/activities/chat/index.ts +540 -16
- package/src/activities/chat/messages.ts +125 -15
- package/src/activities/chat/middleware/run-store.ts +56 -7
- package/src/activities/chat/middleware/types.ts +55 -2
- package/src/activities/chat/stream/processor.ts +428 -8
- package/src/activities/chat/tools/tool-calls.ts +92 -16
- package/src/activities/index.ts +15 -0
- package/src/client.ts +22 -35
- package/src/index.ts +23 -0
- package/src/middlewares/content-guard.ts +7 -5
- package/src/stream-to-response.ts +16 -6
- package/src/strip-to-spec-middleware.ts +2 -1
- package/src/types.ts +177 -95
- package/src/utilities/adapter-yield-chunk.ts +10 -2
- package/src/utilities/ag-ui-usage.test.ts +38 -0
- package/src/utilities/ag-ui-usage.ts +98 -11
- package/src/utilities/ag-ui-wire.ts +74 -0
- package/src/utilities/durability-batch.ts +48 -0
- package/src/utilities/normalize-stream-chunk.ts +10 -2
- package/src/utilities/spec-event-keys.ts +34 -7
- package/src/utilities/subagent-wire.ts +184 -0
|
@@ -7,8 +7,11 @@ import type {
|
|
|
7
7
|
AnyTool,
|
|
8
8
|
ContentPart,
|
|
9
9
|
CustomEvent,
|
|
10
|
+
EmitCustomEventOptions,
|
|
11
|
+
Interrupt,
|
|
10
12
|
ModelMessage,
|
|
11
13
|
RunFinishedEvent,
|
|
14
|
+
StreamChunk,
|
|
12
15
|
Tool,
|
|
13
16
|
ToolCall,
|
|
14
17
|
ToolCallArgsEvent,
|
|
@@ -37,6 +40,25 @@ function safeJsonParse(value: string): unknown {
|
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
42
|
|
|
43
|
+
/** Marks the synthetic tool that runs a subagent. */
|
|
44
|
+
export const SUBAGENT_TOOL = Symbol.for('tanstack.ai.subagentTool')
|
|
45
|
+
|
|
46
|
+
/** Set on the tool context of a subagent tool. Streams a child chunk live. */
|
|
47
|
+
export const EMIT_STREAM_CHUNK = Symbol.for('tanstack.ai.emitStreamChunk')
|
|
48
|
+
|
|
49
|
+
/** What a subagent tool's `execute` returns. */
|
|
50
|
+
export interface SubagentToolOutcome {
|
|
51
|
+
subagentRunId: string
|
|
52
|
+
text: string
|
|
53
|
+
error?: string
|
|
54
|
+
/** Set when the child stopped for outside input. The tool call stays open. */
|
|
55
|
+
interrupts?: Array<Interrupt>
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isSubagentTool(tool: AnyTool): boolean {
|
|
59
|
+
return (tool as { [SUBAGENT_TOOL]?: true })[SUBAGENT_TOOL] === true
|
|
60
|
+
}
|
|
61
|
+
|
|
40
62
|
/**
|
|
41
63
|
* MCP Apps metadata attached to a server tool at discovery (see
|
|
42
64
|
* `@tanstack/ai-mcp` discovery + `MCPManager.discover()`).
|
|
@@ -504,6 +526,8 @@ interface ExecuteToolCallsResult {
|
|
|
504
526
|
needsApproval: Array<ApprovalRequest>
|
|
505
527
|
/** Tools that need client-side execution */
|
|
506
528
|
needsClientExecution: Array<ClientToolRequest>
|
|
529
|
+
/** Interrupts raised by subagents that run as tools */
|
|
530
|
+
subagentInterrupts: Array<Interrupt>
|
|
507
531
|
}
|
|
508
532
|
|
|
509
533
|
/**
|
|
@@ -513,8 +537,8 @@ interface ExecuteToolCallsResult {
|
|
|
513
537
|
*/
|
|
514
538
|
async function* executeWithEventPolling<T>(
|
|
515
539
|
executionPromise: Promise<T>,
|
|
516
|
-
pendingEvents: Array<CustomEvent>,
|
|
517
|
-
): AsyncGenerator<CustomEvent, T, void> {
|
|
540
|
+
pendingEvents: Array<CustomEvent | StreamChunk>,
|
|
541
|
+
): AsyncGenerator<CustomEvent | StreamChunk, T, void> {
|
|
518
542
|
// Use an object to track mutable state across the async boundary
|
|
519
543
|
const state = { done: false, result: undefined as T }
|
|
520
544
|
const executionWithFlag = executionPromise.then((r) => {
|
|
@@ -531,14 +555,14 @@ async function* executeWithEventPolling<T>(
|
|
|
531
555
|
])
|
|
532
556
|
|
|
533
557
|
// Flush any pending events
|
|
534
|
-
let event: CustomEvent | undefined
|
|
558
|
+
let event: CustomEvent | StreamChunk | undefined
|
|
535
559
|
while ((event = pendingEvents.shift()) !== undefined) {
|
|
536
560
|
yield event
|
|
537
561
|
}
|
|
538
562
|
}
|
|
539
563
|
|
|
540
564
|
// Final flush in case events were emitted right at completion
|
|
541
|
-
let event: CustomEvent | undefined
|
|
565
|
+
let event: CustomEvent | StreamChunk | undefined
|
|
542
566
|
while ((event = pendingEvents.shift()) !== undefined) {
|
|
543
567
|
yield event
|
|
544
568
|
}
|
|
@@ -611,19 +635,59 @@ export async function* executeServerTool<TContext = unknown>(
|
|
|
611
635
|
toolName: string,
|
|
612
636
|
input: unknown,
|
|
613
637
|
context: ToolExecutionContext<TContext>,
|
|
614
|
-
pendingEvents: Array<CustomEvent>,
|
|
638
|
+
pendingEvents: Array<CustomEvent | StreamChunk>,
|
|
615
639
|
results: Array<ToolResult>,
|
|
616
640
|
middlewareHooks?: ToolExecutionMiddlewareHooks,
|
|
617
|
-
|
|
641
|
+
subagentInterrupts?: Array<Interrupt>,
|
|
642
|
+
): AsyncGenerator<CustomEvent | StreamChunk, void, void> {
|
|
618
643
|
const startTime = Date.now()
|
|
619
644
|
try {
|
|
620
645
|
if (!tool.execute) {
|
|
621
646
|
throw new Error(`Tool ${toolName} has no execute() implementation`)
|
|
622
647
|
}
|
|
648
|
+
const subagent = isSubagentTool(tool)
|
|
649
|
+
if (subagent) {
|
|
650
|
+
Object.assign(context, {
|
|
651
|
+
[EMIT_STREAM_CHUNK]: (chunk: StreamChunk) => pendingEvents.push(chunk),
|
|
652
|
+
})
|
|
653
|
+
}
|
|
623
654
|
const executionPromise = Promise.resolve(tool.execute(input, context))
|
|
624
655
|
let result = yield* executeWithEventPolling(executionPromise, pendingEvents)
|
|
625
656
|
const duration = Date.now() - startTime
|
|
626
657
|
|
|
658
|
+
if (subagent) {
|
|
659
|
+
const outcome = result as SubagentToolOutcome
|
|
660
|
+
if (outcome.interrupts?.length) {
|
|
661
|
+
// The child waits for outside input. Leave the call open so the
|
|
662
|
+
// resume run executes it again and continues the same child.
|
|
663
|
+
subagentInterrupts?.push(...outcome.interrupts)
|
|
664
|
+
return
|
|
665
|
+
}
|
|
666
|
+
const modelResult = outcome.error
|
|
667
|
+
? { subagentRunId: outcome.subagentRunId, error: outcome.error }
|
|
668
|
+
: { subagentRunId: outcome.subagentRunId, result: outcome.text }
|
|
669
|
+
results.push({
|
|
670
|
+
toolCallId: toolCall.id,
|
|
671
|
+
toolName,
|
|
672
|
+
result: modelResult,
|
|
673
|
+
input,
|
|
674
|
+
output: modelResult,
|
|
675
|
+
duration,
|
|
676
|
+
...(outcome.error ? { state: 'output-error' as const } : {}),
|
|
677
|
+
})
|
|
678
|
+
await middlewareHooks?.onAfterToolCall?.({
|
|
679
|
+
toolCall,
|
|
680
|
+
tool,
|
|
681
|
+
toolName,
|
|
682
|
+
toolCallId: toolCall.id,
|
|
683
|
+
duration,
|
|
684
|
+
...(outcome.error
|
|
685
|
+
? { ok: false as const, error: new Error(outcome.error) }
|
|
686
|
+
: { ok: true as const, result: modelResult }),
|
|
687
|
+
})
|
|
688
|
+
return
|
|
689
|
+
}
|
|
690
|
+
|
|
627
691
|
// MCP Apps: if this tool links a ui:// resource, eagerly read it and queue
|
|
628
692
|
// a `ui-resource` CUSTOM event. The MCP source stays live until the run
|
|
629
693
|
// drains (MCPManager's `connection:'close'` policy disposes on completion),
|
|
@@ -632,7 +696,7 @@ export async function* executeServerTool<TContext = unknown>(
|
|
|
632
696
|
await emitUiResourceIfLinked(tool, context)
|
|
633
697
|
|
|
634
698
|
// Flush remaining events (including any queued ui-resource event)
|
|
635
|
-
let pendingEvent: CustomEvent | undefined
|
|
699
|
+
let pendingEvent: CustomEvent | StreamChunk | undefined
|
|
636
700
|
while ((pendingEvent = pendingEvents.shift()) !== undefined) {
|
|
637
701
|
yield pendingEvent
|
|
638
702
|
}
|
|
@@ -670,7 +734,7 @@ export async function* executeServerTool<TContext = unknown>(
|
|
|
670
734
|
const duration = Date.now() - startTime
|
|
671
735
|
|
|
672
736
|
// Flush remaining events
|
|
673
|
-
let pendingEvent: CustomEvent | undefined
|
|
737
|
+
let pendingEvent: CustomEvent | StreamChunk | undefined
|
|
674
738
|
while ((pendingEvent = pendingEvents.shift()) !== undefined) {
|
|
675
739
|
yield pendingEvent
|
|
676
740
|
}
|
|
@@ -760,15 +824,17 @@ export async function* executeToolCalls<TContext = unknown>(
|
|
|
760
824
|
createCustomEventChunk?: (
|
|
761
825
|
eventName: string,
|
|
762
826
|
value: Record<string, any>,
|
|
827
|
+
options?: EmitCustomEventOptions,
|
|
763
828
|
) => CustomEvent,
|
|
764
829
|
middlewareHooks?: ToolExecutionMiddlewareHooks,
|
|
765
830
|
userContext?: TContext,
|
|
766
831
|
abortSignal?: AbortSignal,
|
|
767
832
|
resumeState?: ToolResumeExecutionState,
|
|
768
|
-
): AsyncGenerator<CustomEvent, ExecuteToolCallsResult, void> {
|
|
833
|
+
): AsyncGenerator<CustomEvent | StreamChunk, ExecuteToolCallsResult, void> {
|
|
769
834
|
const results: Array<ToolResult> = []
|
|
770
835
|
const needsApproval: Array<ApprovalRequest> = []
|
|
771
836
|
const needsClientExecution: Array<ClientToolRequest> = []
|
|
837
|
+
const subagentInterrupts: Array<Interrupt> = []
|
|
772
838
|
|
|
773
839
|
// Create tool lookup map
|
|
774
840
|
const toolMap = new Map<string, AnyTool>()
|
|
@@ -869,18 +935,26 @@ export async function* executeToolCalls<TContext = unknown>(
|
|
|
869
935
|
}
|
|
870
936
|
|
|
871
937
|
// Create a ToolExecutionContext for this tool call with event emission
|
|
872
|
-
const pendingEvents: Array<CustomEvent> = []
|
|
938
|
+
const pendingEvents: Array<CustomEvent | StreamChunk> = []
|
|
873
939
|
const context = {
|
|
874
940
|
toolCallId: toolCall.id,
|
|
875
941
|
context: userContext,
|
|
876
942
|
abortSignal,
|
|
877
|
-
emitCustomEvent: (
|
|
943
|
+
emitCustomEvent: (
|
|
944
|
+
eventName: string,
|
|
945
|
+
value: Record<string, any>,
|
|
946
|
+
options?: EmitCustomEventOptions,
|
|
947
|
+
) => {
|
|
878
948
|
if (createCustomEventChunk) {
|
|
879
949
|
pendingEvents.push(
|
|
880
|
-
createCustomEventChunk(
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
950
|
+
createCustomEventChunk(
|
|
951
|
+
eventName,
|
|
952
|
+
{
|
|
953
|
+
...value,
|
|
954
|
+
toolCallId: toolCall.id,
|
|
955
|
+
},
|
|
956
|
+
options,
|
|
957
|
+
),
|
|
884
958
|
)
|
|
885
959
|
}
|
|
886
960
|
},
|
|
@@ -997,6 +1071,7 @@ export async function* executeToolCalls<TContext = unknown>(
|
|
|
997
1071
|
pendingEvents,
|
|
998
1072
|
results,
|
|
999
1073
|
middlewareHooks,
|
|
1074
|
+
subagentInterrupts,
|
|
1000
1075
|
)
|
|
1001
1076
|
} else {
|
|
1002
1077
|
// User declined
|
|
@@ -1045,8 +1120,9 @@ export async function* executeToolCalls<TContext = unknown>(
|
|
|
1045
1120
|
pendingEvents,
|
|
1046
1121
|
results,
|
|
1047
1122
|
middlewareHooks,
|
|
1123
|
+
subagentInterrupts,
|
|
1048
1124
|
)
|
|
1049
1125
|
}
|
|
1050
1126
|
|
|
1051
|
-
return { results, needsApproval, needsClientExecution }
|
|
1127
|
+
return { results, needsApproval, needsClientExecution, subagentInterrupts }
|
|
1052
1128
|
}
|
package/src/activities/index.ts
CHANGED
|
@@ -39,6 +39,21 @@ export {
|
|
|
39
39
|
type TextActivityResult,
|
|
40
40
|
} from './chat/index'
|
|
41
41
|
|
|
42
|
+
export {
|
|
43
|
+
defineAgent,
|
|
44
|
+
type DefinedAgent,
|
|
45
|
+
type SubagentChoiceOptions,
|
|
46
|
+
type SubagentRunContext,
|
|
47
|
+
} from './chat/agents/define-agent'
|
|
48
|
+
export { subagentRoute, type SubagentRouteOptions } from './chat/agents/route'
|
|
49
|
+
export type {
|
|
50
|
+
SubagentOrder,
|
|
51
|
+
SubagentRouterPick,
|
|
52
|
+
SubagentRouterPlan,
|
|
53
|
+
SubagentStep,
|
|
54
|
+
SubagentStepsPlan,
|
|
55
|
+
} from './chat/agents/spawn'
|
|
56
|
+
|
|
42
57
|
export {
|
|
43
58
|
BaseTextAdapter,
|
|
44
59
|
type AnyTextAdapter,
|
package/src/client.ts
CHANGED
|
@@ -224,41 +224,25 @@ export async function generationParamsFromRequest<TKind extends GenerationKind>(
|
|
|
224
224
|
return generationParamsFromBody(kind, body)
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
export
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
ACTIVITY_DELTA = 'ACTIVITY_DELTA',
|
|
247
|
-
RAW = 'RAW',
|
|
248
|
-
CUSTOM = 'CUSTOM',
|
|
249
|
-
RUN_STARTED = 'RUN_STARTED',
|
|
250
|
-
RUN_FINISHED = 'RUN_FINISHED',
|
|
251
|
-
RUN_ERROR = 'RUN_ERROR',
|
|
252
|
-
STEP_STARTED = 'STEP_STARTED',
|
|
253
|
-
STEP_FINISHED = 'STEP_FINISHED',
|
|
254
|
-
REASONING_START = 'REASONING_START',
|
|
255
|
-
REASONING_MESSAGE_START = 'REASONING_MESSAGE_START',
|
|
256
|
-
REASONING_MESSAGE_CONTENT = 'REASONING_MESSAGE_CONTENT',
|
|
257
|
-
REASONING_MESSAGE_END = 'REASONING_MESSAGE_END',
|
|
258
|
-
REASONING_MESSAGE_CHUNK = 'REASONING_MESSAGE_CHUNK',
|
|
259
|
-
REASONING_END = 'REASONING_END',
|
|
260
|
-
REASONING_ENCRYPTED_VALUE = 'REASONING_ENCRYPTED_VALUE',
|
|
261
|
-
}
|
|
227
|
+
export { EventType } from '@ag-ui/core'
|
|
228
|
+
|
|
229
|
+
export {
|
|
230
|
+
defineAgent,
|
|
231
|
+
type DefinedAgent,
|
|
232
|
+
type SubagentChoiceOptions,
|
|
233
|
+
type SubagentRunContext,
|
|
234
|
+
} from './activities/chat/agents/define-agent'
|
|
235
|
+
export {
|
|
236
|
+
subagentRoute,
|
|
237
|
+
type SubagentRouteOptions,
|
|
238
|
+
} from './activities/chat/agents/route'
|
|
239
|
+
export type {
|
|
240
|
+
SubagentOrder,
|
|
241
|
+
SubagentRouterPick,
|
|
242
|
+
SubagentRouterPlan,
|
|
243
|
+
SubagentStep,
|
|
244
|
+
SubagentStepsPlan,
|
|
245
|
+
} from './activities/chat/agents/spawn'
|
|
262
246
|
|
|
263
247
|
export {
|
|
264
248
|
toolDefinition,
|
|
@@ -349,6 +333,9 @@ export type {
|
|
|
349
333
|
AudioPart,
|
|
350
334
|
ContentPart,
|
|
351
335
|
ContentPartDataSource,
|
|
336
|
+
ContentPartFileSource,
|
|
337
|
+
SubagentHandleData,
|
|
338
|
+
SubagentStatus,
|
|
352
339
|
ContentPartSource,
|
|
353
340
|
ContentPartUrlSource,
|
|
354
341
|
CustomEvent,
|
package/src/index.ts
CHANGED
|
@@ -78,6 +78,24 @@ export { BaseRerankAdapter } from './activities/rerank/adapter'
|
|
|
78
78
|
// Evaluate adapter base + types
|
|
79
79
|
export { BaseEvaluateAdapter } from './activities/evaluate/adapter'
|
|
80
80
|
|
|
81
|
+
export {
|
|
82
|
+
defineAgent,
|
|
83
|
+
type DefinedAgent,
|
|
84
|
+
type SubagentChoiceOptions,
|
|
85
|
+
type SubagentRunContext,
|
|
86
|
+
} from './activities/chat/agents/define-agent'
|
|
87
|
+
export {
|
|
88
|
+
subagentRoute,
|
|
89
|
+
type SubagentRouteOptions,
|
|
90
|
+
} from './activities/chat/agents/route'
|
|
91
|
+
export type {
|
|
92
|
+
SubagentOrder,
|
|
93
|
+
SubagentRouterPick,
|
|
94
|
+
SubagentRouterPlan,
|
|
95
|
+
SubagentStep,
|
|
96
|
+
SubagentStepsPlan,
|
|
97
|
+
} from './activities/chat/agents/spawn'
|
|
98
|
+
|
|
81
99
|
// Tool definition
|
|
82
100
|
export {
|
|
83
101
|
toolDefinition,
|
|
@@ -494,6 +512,11 @@ export { generationParamsFromBody, generationParamsFromRequest } from './client'
|
|
|
494
512
|
|
|
495
513
|
// AG-UI wire serialization (used internally by @tanstack/ai-client)
|
|
496
514
|
export { uiMessagesToWire } from './utilities/ag-ui-wire'
|
|
515
|
+
export type { SubagentWireInfo } from './utilities/subagent-wire'
|
|
516
|
+
export {
|
|
517
|
+
subagentHostMessageId,
|
|
518
|
+
wireSubagentInfo,
|
|
519
|
+
} from './utilities/subagent-wire'
|
|
497
520
|
export { mergeMetadata, withTanstackMetadata } from './utilities/merge-metadata'
|
|
498
521
|
export { fromSpecTokenUsage, toSpecTokenUsage } from './utilities/ag-ui-usage'
|
|
499
522
|
export type { SpecTokenUsage } from './utilities/ag-ui-usage'
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
ChatMiddlewareContext,
|
|
4
4
|
} from '../activities/chat/middleware/types'
|
|
5
5
|
import type { StreamChunk } from '../types'
|
|
6
|
+
import type { AdapterYieldChunk } from '../utilities/adapter-yield-chunk'
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* A content guard rule — either a regex pattern with replacement, or a transform function.
|
|
@@ -142,11 +143,12 @@ function createDeltaStrategy(
|
|
|
142
143
|
|
|
143
144
|
if (blockOnMatch) return null // drop chunk
|
|
144
145
|
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
// Drop the adapter-era content field; the replacement event carries only
|
|
147
|
+
// the filtered delta.
|
|
148
|
+
const { content: _strippedContent, ...rest } = chunk as Extract<
|
|
149
|
+
AdapterYieldChunk,
|
|
150
|
+
{ type: 'TEXT_MESSAGE_CONTENT' }
|
|
151
|
+
>
|
|
150
152
|
void _strippedContent
|
|
151
153
|
return {
|
|
152
154
|
...rest,
|
|
@@ -9,6 +9,10 @@ import { notifyRunDisconnected } from './delivery-disconnect'
|
|
|
9
9
|
import { resolveResumeRunId } from './stream-durability'
|
|
10
10
|
import { EventType } from './types'
|
|
11
11
|
import { toWireChunk } from './strip-to-spec-middleware'
|
|
12
|
+
import {
|
|
13
|
+
isDurabilityBatchedCustom,
|
|
14
|
+
stripDurabilityBatchHint,
|
|
15
|
+
} from './utilities/durability-batch'
|
|
12
16
|
import { resolveDebugOption } from './logger/resolve'
|
|
13
17
|
import { runErrorEventToError } from './utilities/errors'
|
|
14
18
|
import type { LockStore } from './activities/chat/middleware/locks'
|
|
@@ -319,23 +323,29 @@ function resolveBatchSize(batch: number | undefined): number {
|
|
|
319
323
|
|
|
320
324
|
/**
|
|
321
325
|
* Boundaries at which the batching producer flushes early, regardless of the
|
|
322
|
-
* batch size
|
|
323
|
-
*
|
|
324
|
-
* meaningful points.
|
|
326
|
+
* batch size: run-start, terminals, tool-call ends, and CUSTOM events that
|
|
327
|
+
* are not high-volume adapter output.
|
|
325
328
|
*
|
|
326
329
|
* `RUN_STARTED` matters especially for one-shot activities (image, speech,
|
|
327
330
|
* transcription, summarize): they emit `RUN_STARTED`, then await the provider
|
|
328
331
|
* for seconds, then a terminal. Without flushing `RUN_STARTED` the log stays
|
|
329
332
|
* empty for the whole run, so a mount-time `joinRun` finds nothing and its
|
|
330
|
-
* empty-log deadline fast-fails as "run gone"
|
|
333
|
+
* empty-log deadline fast-fails as "run gone" even though the run is alive.
|
|
331
334
|
* Flushing it immediately makes the run resumable from the instant it starts.
|
|
335
|
+
*
|
|
336
|
+
* CUSTOM progress events (compaction, tool progress, middleware) flush at
|
|
337
|
+
* emit time so a live indicator can render. `process.stdout`,
|
|
338
|
+
* `process.stderr`, `sandbox.file`, and `sandbox.file.diff` stay batched.
|
|
339
|
+
* `emitCustomEvent(name, value, { batch: true })` opts a single event into
|
|
340
|
+
* that same batch.
|
|
332
341
|
*/
|
|
333
342
|
function isDurabilityFlushBoundary(chunk: StreamChunk): boolean {
|
|
334
343
|
return (
|
|
335
344
|
chunk.type === 'RUN_STARTED' ||
|
|
336
345
|
chunk.type === 'RUN_FINISHED' ||
|
|
337
346
|
chunk.type === 'RUN_ERROR' ||
|
|
338
|
-
chunk.type === 'TOOL_CALL_END'
|
|
347
|
+
chunk.type === 'TOOL_CALL_END' ||
|
|
348
|
+
(chunk.type === 'CUSTOM' && !isDurabilityBatchedCustom(chunk))
|
|
339
349
|
)
|
|
340
350
|
}
|
|
341
351
|
|
|
@@ -446,7 +456,7 @@ export function durableStreamSource<TOffset extends string>(
|
|
|
446
456
|
|
|
447
457
|
async function* flush(): AsyncIterable<StreamChunk> {
|
|
448
458
|
if (batch.length === 0) return
|
|
449
|
-
const toForward = batch
|
|
459
|
+
const toForward = batch.map(stripDurabilityBatchHint)
|
|
450
460
|
batch = []
|
|
451
461
|
// Tag each chunk with the exact backend offset. Requiring one opaque
|
|
452
462
|
// token per chunk preserves exact-once resume at any batch size.
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
tanstackMetadata,
|
|
7
7
|
withTanstackMetadata,
|
|
8
8
|
} from './utilities/merge-metadata'
|
|
9
|
+
import { stripDurabilityBatchHint } from './utilities/durability-batch'
|
|
9
10
|
import { normalizeStreamChunk } from './utilities/normalize-stream-chunk'
|
|
10
11
|
import { isSpecTopLevelKey } from './utilities/spec-event-keys'
|
|
11
12
|
|
|
@@ -54,5 +55,5 @@ export function toWireChunk(
|
|
|
54
55
|
chunk: StreamChunk | AdapterYieldChunk,
|
|
55
56
|
): StreamChunk {
|
|
56
57
|
const [normalized] = normalizeStreamChunk(chunk)
|
|
57
|
-
return stripToSpec(normalized ?? chunk)
|
|
58
|
+
return stripDurabilityBatchHint(stripToSpec(normalized ?? chunk))
|
|
58
59
|
}
|