@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.
Files changed (95) hide show
  1. package/dist/esm/activities/chat/agents/define-agent.d.ts +81 -0
  2. package/dist/esm/activities/chat/agents/define-agent.js +34 -0
  3. package/dist/esm/activities/chat/agents/define-agent.js.map +1 -0
  4. package/dist/esm/activities/chat/agents/route.d.ts +53 -0
  5. package/dist/esm/activities/chat/agents/route.js +59 -0
  6. package/dist/esm/activities/chat/agents/route.js.map +1 -0
  7. package/dist/esm/activities/chat/agents/spawn.d.ts +124 -0
  8. package/dist/esm/activities/chat/agents/spawn.js +490 -0
  9. package/dist/esm/activities/chat/agents/spawn.js.map +1 -0
  10. package/dist/esm/activities/chat/agents/turn.d.ts +36 -0
  11. package/dist/esm/activities/chat/agents/turn.js +78 -0
  12. package/dist/esm/activities/chat/agents/turn.js.map +1 -0
  13. package/dist/esm/activities/chat/index.d.ts +13 -3
  14. package/dist/esm/activities/chat/index.js +345 -19
  15. package/dist/esm/activities/chat/index.js.map +1 -1
  16. package/dist/esm/activities/chat/messages.d.ts +7 -1
  17. package/dist/esm/activities/chat/messages.js +94 -18
  18. package/dist/esm/activities/chat/messages.js.map +1 -1
  19. package/dist/esm/activities/chat/middleware/run-store.d.ts +43 -7
  20. package/dist/esm/activities/chat/middleware/run-store.js +8 -1
  21. package/dist/esm/activities/chat/middleware/run-store.js.map +1 -1
  22. package/dist/esm/activities/chat/middleware/types.d.ts +50 -3
  23. package/dist/esm/activities/chat/middleware/types.js.map +1 -1
  24. package/dist/esm/activities/chat/stream/processor.d.ts +46 -0
  25. package/dist/esm/activities/chat/stream/processor.js +280 -7
  26. package/dist/esm/activities/chat/stream/processor.js.map +1 -1
  27. package/dist/esm/activities/chat/tools/tool-calls.d.ts +17 -3
  28. package/dist/esm/activities/chat/tools/tool-calls.js +56 -7
  29. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  30. package/dist/esm/activities/generateAudio/index.js +1 -1
  31. package/dist/esm/activities/generateImage/index.js +1 -1
  32. package/dist/esm/activities/generateLiveVideo/index.js +1 -1
  33. package/dist/esm/activities/generateSpeech/index.js +1 -1
  34. package/dist/esm/activities/generateTranscription/index.js +1 -1
  35. package/dist/esm/activities/generateVoice/index.js +1 -1
  36. package/dist/esm/activities/generateWorld/index.js +1 -1
  37. package/dist/esm/activities/index.d.ts +3 -0
  38. package/dist/esm/activities/index.js +5 -3
  39. package/dist/esm/activities/summarize/index.js +1 -1
  40. package/dist/esm/client.d.ts +5 -36
  41. package/dist/esm/client.js +4 -37
  42. package/dist/esm/client.js.map +1 -1
  43. package/dist/esm/index.d.ts +5 -0
  44. package/dist/esm/index.js +7 -4
  45. package/dist/esm/middlewares/content-guard.js.map +1 -1
  46. package/dist/esm/stream-to-response.js +12 -6
  47. package/dist/esm/stream-to-response.js.map +1 -1
  48. package/dist/esm/strip-to-spec-middleware.js +2 -1
  49. package/dist/esm/strip-to-spec-middleware.js.map +1 -1
  50. package/dist/esm/types.d.ts +128 -89
  51. package/dist/esm/utilities/adapter-yield-chunk.d.ts +5 -1
  52. package/dist/esm/utilities/ag-ui-usage.d.ts +9 -9
  53. package/dist/esm/utilities/ag-ui-usage.js +66 -3
  54. package/dist/esm/utilities/ag-ui-usage.js.map +1 -1
  55. package/dist/esm/utilities/ag-ui-wire.js +56 -0
  56. package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
  57. package/dist/esm/utilities/durability-batch.d.ts +8 -0
  58. package/dist/esm/utilities/durability-batch.js +45 -0
  59. package/dist/esm/utilities/durability-batch.js.map +1 -0
  60. package/dist/esm/utilities/normalize-stream-chunk.js +7 -2
  61. package/dist/esm/utilities/normalize-stream-chunk.js.map +1 -1
  62. package/dist/esm/utilities/spec-event-keys.js +13 -8
  63. package/dist/esm/utilities/spec-event-keys.js.map +1 -1
  64. package/dist/esm/utilities/subagent-wire.d.ts +36 -0
  65. package/dist/esm/utilities/subagent-wire.js +131 -0
  66. package/dist/esm/utilities/subagent-wire.js.map +1 -0
  67. package/package.json +4 -4
  68. package/skills/ai-core/adapter-configuration/references/grok-adapter.md +1 -1
  69. package/skills/ai-core/media-generation/SKILL.md +2 -2
  70. package/skills/ai-core/middleware/SKILL.md +7 -4
  71. package/src/activities/chat/agents/define-agent.ts +121 -0
  72. package/src/activities/chat/agents/route.ts +115 -0
  73. package/src/activities/chat/agents/spawn.ts +806 -0
  74. package/src/activities/chat/agents/turn.ts +151 -0
  75. package/src/activities/chat/index.ts +540 -16
  76. package/src/activities/chat/messages.ts +125 -15
  77. package/src/activities/chat/middleware/run-store.ts +56 -7
  78. package/src/activities/chat/middleware/types.ts +55 -2
  79. package/src/activities/chat/stream/processor.ts +428 -8
  80. package/src/activities/chat/tools/tool-calls.ts +92 -16
  81. package/src/activities/index.ts +15 -0
  82. package/src/client.ts +22 -35
  83. package/src/index.ts +23 -0
  84. package/src/middlewares/content-guard.ts +7 -5
  85. package/src/stream-to-response.ts +16 -6
  86. package/src/strip-to-spec-middleware.ts +2 -1
  87. package/src/types.ts +177 -95
  88. package/src/utilities/adapter-yield-chunk.ts +10 -2
  89. package/src/utilities/ag-ui-usage.test.ts +38 -0
  90. package/src/utilities/ag-ui-usage.ts +98 -11
  91. package/src/utilities/ag-ui-wire.ts +74 -0
  92. package/src/utilities/durability-batch.ts +48 -0
  93. package/src/utilities/normalize-stream-chunk.ts +10 -2
  94. package/src/utilities/spec-event-keys.ts +34 -7
  95. package/src/utilities/subagent-wire.ts +184 -0
@@ -0,0 +1,121 @@
1
+ import type { SubagentInfo as AGUISubagentInfo } from '@ag-ui/core'
2
+ import type { InterruptDefinition } from '../../../interrupt-definition'
3
+ import type {
4
+ AnyTool,
5
+ ModelMessage,
6
+ RunAgentResumeItem,
7
+ SchemaInput,
8
+ StreamChunk,
9
+ UIMessage,
10
+ } from '../../../types'
11
+ import type { AnyClientTool } from '../tools/tool-definition'
12
+
13
+ /**
14
+ * Context the library passes into {@link defineAgent} `run`.
15
+ */
16
+ export interface SubagentRunContext {
17
+ messages: Array<UIMessage | ModelMessage>
18
+ abortSignal?: AbortSignal
19
+ threadId: string
20
+ /** Run id for the child `chat()`. */
21
+ runId: string
22
+ /**
23
+ * The run this child run continues. It is the parent chat run on the first
24
+ * run, and the interrupted parent run on a resume. Pass it to the child
25
+ * `chat()`.
26
+ */
27
+ parentRunId: string
28
+ /** Answers to this child's interrupts. Pass it to the child `chat()`. */
29
+ resume?: Array<RunAgentResumeItem>
30
+ /**
31
+ * The child's AG-UI run id. Stays the same when an interrupted child
32
+ * continues. Pass it to the child `chat()` so its middleware sees
33
+ * `ctx.subagentRunId`.
34
+ */
35
+ subagentRunId: string
36
+ parentSubagentRunId?: string
37
+ }
38
+
39
+ /**
40
+ * A tool a child agent can carry into client part types.
41
+ * Server tools and client tools both qualify.
42
+ */
43
+ export type SubagentTool = AnyTool | AnyClientTool
44
+
45
+ /**
46
+ * A named child agent. `run` is a `chat()` call (or any stream of AG-UI chunks).
47
+ * `TTools` and `TSchema` stay on the object so `useChat({ subagents })` can
48
+ * type that child's parts.
49
+ */
50
+ export interface DefinedAgent<
51
+ TName extends string = string,
52
+ TTools extends ReadonlyArray<SubagentTool> = ReadonlyArray<SubagentTool>,
53
+ TSchema extends SchemaInput | undefined = SchemaInput | undefined,
54
+ TInterrupts extends ReadonlyArray<InterruptDefinition<any, any, any, any>> =
55
+ ReadonlyArray<InterruptDefinition<any, any, any, any>>,
56
+ > extends AGUISubagentInfo {
57
+ name: TName
58
+ /** Required here: the router and the synthetic tool both read it. */
59
+ description: string
60
+ run: (
61
+ ctx: SubagentRunContext,
62
+ ) => AsyncIterable<StreamChunk> | Promise<AsyncIterable<StreamChunk>>
63
+ tools?: TTools
64
+ interrupts?: TInterrupts
65
+ outputSchema?: TSchema
66
+ subagents?: unknown
67
+ }
68
+
69
+ /**
70
+ * Choice options for a `decide()` router. `main` is required plus every agent name.
71
+ */
72
+ export type SubagentChoiceOptions<TAgents extends ReadonlyArray<DefinedAgent>> =
73
+ { main: string } & {
74
+ [K in TAgents[number]['name']]: string
75
+ }
76
+
77
+ /**
78
+ * Define a named child agent. Pass the same object to `chat({ subagents })`.
79
+ * Pass the agents array to `useChat({ subagents })` when you render parts
80
+ * yourself. The hook uses it for types only. It does not call `run`.
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * const researcher = defineAgent({
85
+ * name: 'researcher',
86
+ * description: 'Looks up facts',
87
+ * run: (ctx) =>
88
+ * chat({
89
+ * adapter: openaiText('gpt-5.6'),
90
+ * messages: ctx.messages,
91
+ * threadId: ctx.threadId,
92
+ * runId: ctx.runId,
93
+ * parentRunId: ctx.parentRunId,
94
+ * subagentRunId: ctx.subagentRunId,
95
+ * resume: ctx.resume,
96
+ * }),
97
+ * })
98
+ * ```
99
+ */
100
+ export function defineAgent<
101
+ const TName extends string,
102
+ const TTools extends ReadonlyArray<SubagentTool> = readonly [],
103
+ TSchema extends SchemaInput | undefined = undefined,
104
+ const TInterrupts extends ReadonlyArray<
105
+ InterruptDefinition<any, any, any, any>
106
+ > = readonly [],
107
+ >(agent: DefinedAgent<TName, TTools, TSchema, TInterrupts>) {
108
+ if (agent.name.trim() === '') {
109
+ throw new Error('defineAgent requires a non-empty name')
110
+ }
111
+ // A router returns 'main' to keep the turn on the parent.
112
+ if (agent.name.trim() === 'main') {
113
+ throw new Error(
114
+ "defineAgent cannot use the name 'main'. A router uses it for the parent.",
115
+ )
116
+ }
117
+ if (agent.description.trim() === '') {
118
+ throw new Error('defineAgent requires a non-empty description')
119
+ }
120
+ return agent
121
+ }
@@ -0,0 +1,115 @@
1
+ import { boolean, choice } from '../../evaluate/index'
2
+ import type { DefinedAgent } from './define-agent'
3
+ import type { SubagentOrder, SubagentRouterPick } from './spawn'
4
+
5
+ const ORDER_KEY = 'order'
6
+
7
+ export interface SubagentRouteOptions<
8
+ TAgents extends ReadonlyArray<DefinedAgent>,
9
+ > {
10
+ /**
11
+ * Question text for every agent. The key is the agent name.
12
+ * Omit this and each question uses that agent's description.
13
+ */
14
+ when?: { [K in TAgents[number]['name']]: string }
15
+ /**
16
+ * Agents that run after the other selected agents. The lead group starts
17
+ * together. The `then` agents then run one after another in list order, and
18
+ * each reads the text so far. Used only when the router picks at least one
19
+ * agent from each group. Otherwise `pick` returns `{ names, order }`.
20
+ */
21
+ then?: ReadonlyArray<TAgents[number]['name']>
22
+ }
23
+
24
+ type RouteQuestions<TAgents extends ReadonlyArray<DefinedAgent>> = {
25
+ [K in TAgents[number]['name']]: ReturnType<typeof boolean>
26
+ } & {
27
+ order: ReturnType<
28
+ typeof choice<{
29
+ parallel: string
30
+ sequence: string
31
+ }>
32
+ >
33
+ }
34
+
35
+ type RouteAnswers<TAgents extends ReadonlyArray<DefinedAgent>> = {
36
+ [K in TAgents[number]['name']]: { value: boolean }
37
+ } & {
38
+ order: { value: SubagentOrder }
39
+ }
40
+
41
+ /**
42
+ * Build `decide()` questions for a subagent router.
43
+ *
44
+ * One yes/no question per agent, plus an `order` choice.
45
+ * `pick` returns `main`, one name, `{ names, order }`, or `{ steps }`.
46
+ * Names follow the `agents` array order.
47
+ * `{ names, order }` overrides `subagents.order` for that turn.
48
+ * `then`: agents that run after the other selected agents. The lead group
49
+ * starts together. The `then` agents then run one after another in list
50
+ * order, and each reads the text so far. Used only when the router picks at
51
+ * least one agent from each group. Otherwise `pick` returns `{ names, order }`.
52
+ */
53
+ export function subagentRoute<
54
+ const TAgents extends ReadonlyArray<DefinedAgent>,
55
+ >(agents: TAgents, options?: SubagentRouteOptions<TAgents>) {
56
+ const namesInList = new Set(agents.map((agent) => agent.name))
57
+ for (const agent of agents) {
58
+ if (agent.name === ORDER_KEY) {
59
+ throw new Error(
60
+ 'subagentRoute cannot use an agent named "order". Rename that agent.',
61
+ )
62
+ }
63
+ }
64
+ for (const name of options?.then ?? []) {
65
+ if (!namesInList.has(name)) {
66
+ throw new Error(`subagentRoute then includes unknown agent "${name}".`)
67
+ }
68
+ }
69
+
70
+ const questions: Record<string, unknown> = {
71
+ order: choice({
72
+ instructions: 'When more than one agent runs, how must they run?',
73
+ options: {
74
+ parallel:
75
+ 'Start them together. Use this when no agent must read text from another agent. Working on the same topic is not a reason to wait.',
76
+ sequence:
77
+ 'Run them in agent-list order. Use this only when a later agent must read the earlier agent text, such as research notes and then a draft article.',
78
+ },
79
+ }),
80
+ }
81
+
82
+ for (const agent of agents) {
83
+ const when = options?.when?.[agent.name as TAgents[number]['name']]
84
+ questions[agent.name] = boolean({
85
+ instructions: when ?? agent.description,
86
+ })
87
+ }
88
+
89
+ function pick(result: RouteAnswers<TAgents>): SubagentRouterPick {
90
+ const names = agents
91
+ .map((agent) => agent.name)
92
+ .filter((name) => result[name as TAgents[number]['name']].value)
93
+ if (names.length === 0) return 'main'
94
+ const only = names.length === 1 ? names[0] : undefined
95
+ if (only !== undefined) return only
96
+ const later = new Set(options?.then ?? [])
97
+ const lead = names.filter((name) => !later.has(name))
98
+ const tail = names.filter((name) => later.has(name))
99
+ if (lead.length === 0 || tail.length === 0) {
100
+ return { names, order: result.order.value }
101
+ }
102
+ return {
103
+ steps: [
104
+ lead.length > 1
105
+ ? { names: lead, order: 'parallel' as const }
106
+ : { names: lead },
107
+ tail.length > 1
108
+ ? { names: tail, order: 'sequence' as const }
109
+ : { names: tail },
110
+ ],
111
+ }
112
+ }
113
+
114
+ return { questions: questions as RouteQuestions<TAgents>, pick }
115
+ }