@tanstack/ai 0.58.0 → 0.61.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 +9 -0
- package/dist/esm/activities/chat/adapter.js +1 -0
- package/dist/esm/activities/chat/adapter.js.map +1 -1
- 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 +462 -26
- 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 +99 -19
- 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 +47 -1
- package/dist/esm/activities/chat/middleware/types.js.map +1 -1
- package/dist/esm/activities/chat/stream/message-updaters.js +9 -2
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +46 -1
- package/dist/esm/activities/chat/stream/processor.js +294 -18
- 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 -5
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/embed/adapter.d.ts +7 -0
- package/dist/esm/activities/embed/adapter.js +1 -0
- package/dist/esm/activities/embed/adapter.js.map +1 -1
- package/dist/esm/activities/embed/index.js +2 -0
- package/dist/esm/activities/embed/index.js.map +1 -1
- package/dist/esm/activities/files/adapter.d.ts +97 -0
- package/dist/esm/activities/files/adapter.js +45 -0
- package/dist/esm/activities/files/adapter.js.map +1 -0
- package/dist/esm/activities/files/index.d.ts +66 -0
- package/dist/esm/activities/files/index.js +78 -0
- package/dist/esm/activities/files/index.js.map +1 -0
- package/dist/esm/activities/generateAudio/index.js +1 -1
- package/dist/esm/activities/generateImage/adapter.d.ts +8 -0
- package/dist/esm/activities/generateImage/adapter.js +1 -0
- package/dist/esm/activities/generateImage/adapter.js.map +1 -1
- package/dist/esm/activities/generateImage/index.js +3 -1
- package/dist/esm/activities/generateImage/index.js.map +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/generateVideo/adapter.d.ts +8 -0
- package/dist/esm/activities/generateVideo/adapter.js +1 -0
- package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.js +3 -0
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/generateVoice/index.js +1 -1
- package/dist/esm/activities/generateWorld/adapter.d.ts +4 -2
- package/dist/esm/activities/generateWorld/adapter.js.map +1 -1
- package/dist/esm/activities/generateWorld/index.d.ts +4 -3
- package/dist/esm/activities/generateWorld/index.js +6 -5
- package/dist/esm/activities/generateWorld/index.js.map +1 -1
- package/dist/esm/activities/index.d.ts +9 -3
- package/dist/esm/activities/index.js +17 -13
- package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +2 -0
- package/dist/esm/activities/summarize/chat-stream-summarize.js +8 -8
- package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
- package/dist/esm/activities/summarize/index.js +1 -1
- package/dist/esm/client.d.ts +7 -36
- package/dist/esm/client.js +5 -37
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +8 -2
- package/dist/esm/index.js +9 -4
- package/dist/esm/middlewares/content-guard.js.map +1 -1
- package/dist/esm/types.d.ts +179 -98
- 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 +90 -13
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/content-source.d.ts +60 -0
- package/dist/esm/utilities/content-source.js +85 -0
- package/dist/esm/utilities/content-source.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/provider-executed.d.ts +7 -0
- package/dist/esm/utilities/provider-executed.js +10 -1
- package/dist/esm/utilities/provider-executed.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/dist/esm/utilities/tool-result.d.ts +12 -2
- package/dist/esm/utilities/tool-result.js +23 -3
- package/dist/esm/utilities/tool-result.js.map +1 -1
- package/package.json +3 -3
- package/skills/ai-core/adapter-configuration/SKILL.md +62 -0
- package/skills/ai-core/adapter-configuration/references/grok-adapter.md +1 -1
- package/skills/ai-core/chat-experience/SKILL.md +14 -0
- package/skills/ai-core/media-generation/SKILL.md +10 -2
- package/skills/ai-core/middleware/SKILL.md +7 -4
- package/src/activities/chat/adapter.ts +10 -0
- 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 +734 -30
- package/src/activities/chat/messages.ts +137 -16
- package/src/activities/chat/middleware/run-store.ts +56 -7
- package/src/activities/chat/middleware/types.ts +47 -0
- package/src/activities/chat/stream/message-updaters.ts +24 -2
- package/src/activities/chat/stream/processor.ts +452 -30
- package/src/activities/chat/tools/tool-calls.ts +83 -11
- package/src/activities/embed/adapter.ts +7 -0
- package/src/activities/embed/index.ts +5 -0
- package/src/activities/files/adapter.ts +120 -0
- package/src/activities/files/index.ts +113 -0
- package/src/activities/generateImage/adapter.ts +8 -0
- package/src/activities/generateImage/index.ts +4 -0
- package/src/activities/generateVideo/adapter.ts +8 -0
- package/src/activities/generateVideo/index.ts +7 -0
- package/src/activities/generateWorld/adapter.ts +4 -2
- package/src/activities/generateWorld/index.ts +7 -6
- package/src/activities/index.ts +40 -1
- package/src/activities/summarize/chat-stream-summarize.ts +22 -12
- package/src/client.ts +29 -35
- package/src/index.ts +39 -0
- package/src/middlewares/content-guard.ts +7 -5
- package/src/types.ts +226 -103
- 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 +134 -16
- package/src/utilities/content-source.ts +138 -0
- package/src/utilities/normalize-stream-chunk.ts +10 -2
- package/src/utilities/provider-executed.ts +13 -0
- package/src/utilities/spec-event-keys.ts +34 -7
- package/src/utilities/subagent-wire.ts +184 -0
- package/src/utilities/tool-result.ts +38 -2
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import type { SubagentInfo as AGUISubagentInfo } from '@ag-ui/core'
|
|
2
|
+
import type { SubagentHandleData } from '../types'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Card data that travels on each child wire message, in
|
|
6
|
+
* `metadata.tanstack.subagent`. The messages carry the AG-UI `subagentRunId`.
|
|
7
|
+
*/
|
|
8
|
+
export interface SubagentWireInfo
|
|
9
|
+
extends
|
|
10
|
+
AGUISubagentInfo,
|
|
11
|
+
Pick<
|
|
12
|
+
SubagentHandleData,
|
|
13
|
+
| 'status'
|
|
14
|
+
| 'error'
|
|
15
|
+
| 'interruptIds'
|
|
16
|
+
| 'parentSubagentRunId'
|
|
17
|
+
| 'parentToolCallId'
|
|
18
|
+
| 'metadata'
|
|
19
|
+
> {
|
|
20
|
+
/** The child has no messages yet. This wire message only holds the card. */
|
|
21
|
+
placeholder?: true
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface SubagentWireGroup<T> {
|
|
25
|
+
id: string
|
|
26
|
+
info: SubagentWireInfo
|
|
27
|
+
/** The child's messages without its own tag. Nested children keep theirs. */
|
|
28
|
+
messages: Array<T>
|
|
29
|
+
/** Index in `top` of the last message before this child, or -1. */
|
|
30
|
+
hostIndex: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
34
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function wireSubagentRunId(message: unknown): string | undefined {
|
|
38
|
+
if (!isRecord(message) || 'parts' in message) return undefined
|
|
39
|
+
const id = message.subagentRunId
|
|
40
|
+
return typeof id === 'string' && id !== '' ? id : undefined
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function wireSubagentInfo(
|
|
44
|
+
message: unknown,
|
|
45
|
+
): SubagentWireInfo | undefined {
|
|
46
|
+
if (!isRecord(message) || !isRecord(message.metadata)) return undefined
|
|
47
|
+
const tanstack = message.metadata.tanstack
|
|
48
|
+
if (!isRecord(tanstack) || !isRecord(tanstack.subagent)) return undefined
|
|
49
|
+
// Wire data comes from the client. Keep only well-formed fields.
|
|
50
|
+
const { name, status, error, interruptIds } = tanstack.subagent
|
|
51
|
+
if (typeof name !== 'string' || !isStatus(status)) return undefined
|
|
52
|
+
const {
|
|
53
|
+
description,
|
|
54
|
+
parentSubagentRunId,
|
|
55
|
+
parentToolCallId,
|
|
56
|
+
metadata,
|
|
57
|
+
placeholder,
|
|
58
|
+
} = tanstack.subagent
|
|
59
|
+
return {
|
|
60
|
+
name,
|
|
61
|
+
status,
|
|
62
|
+
...(typeof description === 'string' && { description }),
|
|
63
|
+
...(isRecord(error) &&
|
|
64
|
+
typeof error.message === 'string' && {
|
|
65
|
+
error: {
|
|
66
|
+
message: error.message,
|
|
67
|
+
...(typeof error.code === 'string' && { code: error.code }),
|
|
68
|
+
},
|
|
69
|
+
}),
|
|
70
|
+
...(Array.isArray(interruptIds) && {
|
|
71
|
+
interruptIds: interruptIds.filter(
|
|
72
|
+
(id): id is string => typeof id === 'string',
|
|
73
|
+
),
|
|
74
|
+
}),
|
|
75
|
+
...(typeof parentSubagentRunId === 'string' && { parentSubagentRunId }),
|
|
76
|
+
...(typeof parentToolCallId === 'string' && { parentToolCallId }),
|
|
77
|
+
...(isRecord(metadata) && { metadata }),
|
|
78
|
+
...(placeholder === true && { placeholder: true as const }),
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function isStatus(value: unknown): value is SubagentWireInfo['status'] {
|
|
83
|
+
return (
|
|
84
|
+
value === 'running' ||
|
|
85
|
+
value === 'finished' ||
|
|
86
|
+
value === 'error' ||
|
|
87
|
+
value === 'suspended'
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function untag<T>(message: T): T {
|
|
92
|
+
if (!isRecord(message)) return message
|
|
93
|
+
const { subagentRunId: _id, ...rest } = message
|
|
94
|
+
void _id
|
|
95
|
+
const metadata = isRecord(rest.metadata) ? rest.metadata : undefined
|
|
96
|
+
const tanstack = isRecord(metadata?.tanstack) ? metadata.tanstack : undefined
|
|
97
|
+
if (!metadata || !tanstack || !('subagent' in tanstack)) return rest as T
|
|
98
|
+
const { subagent: _info, ...tanstackRest } = tanstack
|
|
99
|
+
void _info
|
|
100
|
+
return { ...rest, metadata: { ...metadata, tanstack: tanstackRest } } as T
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Split wire messages into the parent's own messages and one group per direct
|
|
105
|
+
* child. A nested child's messages stay inside its parent's group.
|
|
106
|
+
*/
|
|
107
|
+
export function splitSubagentWire<T>(messages: ReadonlyArray<T>): {
|
|
108
|
+
top: Array<T>
|
|
109
|
+
groups: Array<SubagentWireGroup<T>>
|
|
110
|
+
} {
|
|
111
|
+
const parentOf = new Map<string, string | undefined>()
|
|
112
|
+
for (const message of messages) {
|
|
113
|
+
const id = wireSubagentRunId(message)
|
|
114
|
+
if (id !== undefined && !parentOf.has(id)) {
|
|
115
|
+
parentOf.set(id, wireSubagentInfo(message)?.parentSubagentRunId)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const rootOf = (id: string) => {
|
|
119
|
+
let current = id
|
|
120
|
+
for (let depth = 0; depth < 64; depth++) {
|
|
121
|
+
const parent = parentOf.get(current)
|
|
122
|
+
if (parent === undefined || !parentOf.has(parent)) return current
|
|
123
|
+
current = parent
|
|
124
|
+
}
|
|
125
|
+
return current
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const top: Array<T> = []
|
|
129
|
+
const groups = new Map<string, SubagentWireGroup<T>>()
|
|
130
|
+
for (const message of messages) {
|
|
131
|
+
const id = wireSubagentRunId(message)
|
|
132
|
+
if (id === undefined) {
|
|
133
|
+
top.push(message)
|
|
134
|
+
continue
|
|
135
|
+
}
|
|
136
|
+
const root = rootOf(id)
|
|
137
|
+
let group = groups.get(root)
|
|
138
|
+
if (!group) {
|
|
139
|
+
group = {
|
|
140
|
+
id: root,
|
|
141
|
+
info: { name: 'subagent', status: 'finished' },
|
|
142
|
+
messages: [],
|
|
143
|
+
hostIndex: top.length - 1,
|
|
144
|
+
}
|
|
145
|
+
groups.set(root, group)
|
|
146
|
+
}
|
|
147
|
+
if (id !== root) {
|
|
148
|
+
group.messages.push(message)
|
|
149
|
+
continue
|
|
150
|
+
}
|
|
151
|
+
const info = wireSubagentInfo(message)
|
|
152
|
+
if (info) group.info = info
|
|
153
|
+
if (!info?.placeholder) group.messages.push(untag(message))
|
|
154
|
+
}
|
|
155
|
+
return { top, groups: [...groups.values()] }
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Text a child wrote, for the parent model and for a later child. */
|
|
159
|
+
export function subagentWireText(messages: ReadonlyArray<unknown>): string {
|
|
160
|
+
const blocks: Array<string> = []
|
|
161
|
+
for (const message of messages) {
|
|
162
|
+
if (!isRecord(message) || message.role !== 'assistant') continue
|
|
163
|
+
if (wireSubagentRunId(message) !== undefined) continue
|
|
164
|
+
const content = message.content
|
|
165
|
+
if (typeof content === 'string' && content.trim() !== '') {
|
|
166
|
+
blocks.push(content.trim())
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const nested = splitSubagentWire(messages).groups
|
|
170
|
+
for (const group of nested) {
|
|
171
|
+
const text = subagentWireText(group.messages)
|
|
172
|
+
if (text !== '') blocks.push(`${group.info.name}:\n${text}`)
|
|
173
|
+
}
|
|
174
|
+
return blocks.join('\n\n')
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* The id of the parent assistant message that hosts a routed turn's cards.
|
|
179
|
+
* The persistence recorder writes that message, and a handoff run passes the
|
|
180
|
+
* same id so the stored thread keeps one copy.
|
|
181
|
+
*/
|
|
182
|
+
export function subagentHostMessageId(runId: string) {
|
|
183
|
+
return `assistant:${runId}`
|
|
184
|
+
}
|
|
@@ -10,8 +10,9 @@ const CONTENT_PART_TYPES = new Set([
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Structural check for a single `ContentPart`. A text part must carry a string
|
|
13
|
-
* `content
|
|
14
|
-
*
|
|
13
|
+
* `content`. Every other part carries a source with a string `value`; a file
|
|
14
|
+
* source's `value` is a non-empty opaque handle, and its optional `provider`
|
|
15
|
+
* is a string.
|
|
15
16
|
*/
|
|
16
17
|
export function isContentPart(value: unknown): value is ContentPart {
|
|
17
18
|
if (typeof value !== 'object' || value === null) return false
|
|
@@ -26,6 +27,14 @@ export function isContentPart(value: unknown): value is ContentPart {
|
|
|
26
27
|
if (typeof source !== 'object' || source === null) return false
|
|
27
28
|
const src = source as Record<string, unknown>
|
|
28
29
|
if (typeof src.value !== 'string') return false
|
|
30
|
+
// `file` sources carry an opaque handle in `value`; `provider`, when set,
|
|
31
|
+
// names the issuer.
|
|
32
|
+
if (src.type === 'file') {
|
|
33
|
+
return (
|
|
34
|
+
src.value.length > 0 &&
|
|
35
|
+
(src.provider === undefined || typeof src.provider === 'string')
|
|
36
|
+
)
|
|
37
|
+
}
|
|
29
38
|
// `data` sources require a mimeType (matches ContentPartDataSource); `url`
|
|
30
39
|
// sources don't. Requiring it here keeps the runtime guard consistent with
|
|
31
40
|
// the type and avoids emitting `data:undefined;base64,...` downstream.
|
|
@@ -45,6 +54,33 @@ export function isContentPartArray(
|
|
|
45
54
|
return Array.isArray(value) && value.length > 0 && value.every(isContentPart)
|
|
46
55
|
}
|
|
47
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Error text for a failed tool result: `output.error` when it is a string,
|
|
59
|
+
* else the output itself when it is a string, else a generic message.
|
|
60
|
+
* `StreamProcessor` and `chat()` history share it, so a reload shows the
|
|
61
|
+
* same text as the live stream.
|
|
62
|
+
*/
|
|
63
|
+
export function toolResultErrorText(output: unknown): string {
|
|
64
|
+
if (
|
|
65
|
+
output &&
|
|
66
|
+
typeof output === 'object' &&
|
|
67
|
+
'error' in output &&
|
|
68
|
+
typeof output.error === 'string'
|
|
69
|
+
) {
|
|
70
|
+
return output.error
|
|
71
|
+
}
|
|
72
|
+
return typeof output === 'string' ? output : 'Tool execution failed'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Parse tool result content as JSON. Plain text stays a string. */
|
|
76
|
+
export function parseToolOutput(content: string): unknown {
|
|
77
|
+
try {
|
|
78
|
+
return JSON.parse(content)
|
|
79
|
+
} catch {
|
|
80
|
+
return content
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
48
84
|
/**
|
|
49
85
|
* Normalize a tool's return value for transport:
|
|
50
86
|
* - string → unchanged
|