@tanstack/ai 0.17.0 → 0.19.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/README.md +0 -4
- package/dist/esm/activities/chat/index.d.ts +12 -3
- package/dist/esm/activities/chat/index.js +75 -7
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.js +41 -2
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/middleware/compose.js +1 -1
- package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +12 -1
- package/dist/esm/activities/chat/stream/message-updaters.d.ts +35 -0
- package/dist/esm/activities/chat/stream/message-updaters.js +95 -0
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +1 -0
- package/dist/esm/activities/chat/stream/processor.js +90 -2
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/tools/schema-converter.js +5 -0
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
- package/dist/esm/adapter-internals.d.ts +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +8 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types.d.ts +86 -16
- package/dist/esm/utilities/ag-ui-wire.d.ts +44 -0
- package/dist/esm/utilities/ag-ui-wire.js +104 -0
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -0
- package/dist/esm/utilities/chat-params.d.ts +80 -0
- package/dist/esm/utilities/chat-params.js +96 -0
- package/dist/esm/utilities/chat-params.js.map +1 -0
- package/package.json +3 -3
- package/skills/ai-core/ag-ui-protocol/SKILL.md +46 -3
- package/skills/ai-core/structured-outputs/SKILL.md +240 -47
- package/src/activities/chat/index.ts +144 -10
- package/src/activities/chat/messages.ts +70 -4
- package/src/activities/chat/middleware/compose.ts +1 -1
- package/src/activities/chat/middleware/types.ts +12 -1
- package/src/activities/chat/stream/message-updaters.ts +171 -0
- package/src/activities/chat/stream/processor.ts +137 -2
- package/src/activities/chat/tools/schema-converter.ts +14 -0
- package/src/adapter-internals.ts +1 -0
- package/src/index.ts +11 -0
- package/src/types.ts +104 -15
- package/src/utilities/ag-ui-wire.ts +201 -0
- package/src/utilities/chat-params.ts +199 -0
package/README.md
CHANGED
|
@@ -49,10 +49,6 @@ A powerful, type-safe AI SDK for building AI-powered applications.
|
|
|
49
49
|
|
|
50
50
|
### <a href="https://tanstack.com/ai">Read the docs →</a>
|
|
51
51
|
|
|
52
|
-
## Requirements
|
|
53
|
-
|
|
54
|
-
- **Node.js v24+** is required to avoid compatibility issues with `isolated-vm`.
|
|
55
|
-
|
|
56
52
|
## Tree-Shakeable Adapters
|
|
57
53
|
|
|
58
54
|
Import only the functionality you need for smaller bundle sizes:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AnyTextAdapter } from './adapter.js';
|
|
2
|
-
import { ConstrainedModelMessage, InferSchemaType, SchemaInput, StreamChunk, StructuredOutputStream, TextOptions, Tool } from '../../types.js';
|
|
2
|
+
import { ConstrainedModelMessage, InferSchemaType, ModelMessage, SchemaInput, StreamChunk, StructuredOutputStream, TextOptions, Tool, UIMessage } from '../../types.js';
|
|
3
3
|
import { ChatMiddleware } from './middleware/types.js';
|
|
4
4
|
import { DebugOption } from '../../logger/types.js';
|
|
5
5
|
import { ProviderTool } from '../../tools/provider-tool.js';
|
|
@@ -16,8 +16,15 @@ export declare const kind: "text";
|
|
|
16
16
|
export interface TextActivityOptions<TAdapter extends AnyTextAdapter, TSchema extends SchemaInput | undefined, TStream extends boolean> {
|
|
17
17
|
/** The text adapter to use (created by a provider function like openaiText('gpt-4o')) */
|
|
18
18
|
adapter: TAdapter;
|
|
19
|
-
/**
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Conversation messages. Accepts:
|
|
21
|
+
* - `ConstrainedModelMessage` — content types constrained by the adapter's input modalities.
|
|
22
|
+
* - `ModelMessage` — unconstrained model message (e.g., forwarded from an AG-UI wire payload).
|
|
23
|
+
* - `UIMessage` — parts-based UI representation; converted internally via `convertMessagesToModelMessages`.
|
|
24
|
+
*
|
|
25
|
+
* The three shapes can be mixed in a single array (e.g., when forwarding a wire payload that includes both anchor UIMessages and AG-UI fan-out ModelMessages).
|
|
26
|
+
*/
|
|
27
|
+
messages?: Array<UIMessage | ModelMessage | ConstrainedModelMessage<{
|
|
21
28
|
inputModalities: TAdapter['~types']['inputModalities'];
|
|
22
29
|
messageMetadataByModality: TAdapter['~types']['messageMetadataByModality'];
|
|
23
30
|
}>>;
|
|
@@ -56,6 +63,8 @@ export interface TextActivityOptions<TAdapter extends AnyTextAdapter, TSchema ex
|
|
|
56
63
|
threadId?: TextOptions['threadId'];
|
|
57
64
|
/** Run ID override for AG-UI protocol. Auto-generated by adapter if not provided. */
|
|
58
65
|
runId?: TextOptions['runId'];
|
|
66
|
+
/** Parent run ID for AG-UI protocol nested run correlation. */
|
|
67
|
+
parentRunId?: TextOptions['parentRunId'];
|
|
59
68
|
/**
|
|
60
69
|
* Optional Standard Schema for structured output.
|
|
61
70
|
* When provided, the activity will:
|
|
@@ -6,7 +6,7 @@ import { LazyToolManager } from "./tools/lazy-tool-manager.js";
|
|
|
6
6
|
import { ToolCallManager, MiddlewareAbortError, executeToolCalls } from "./tools/tool-calls.js";
|
|
7
7
|
import { convertSchemaToJsonSchema, isStandardSchema, parseWithStandardSchema } from "./tools/schema-converter.js";
|
|
8
8
|
import { maxIterations } from "./agent-loop-strategies.js";
|
|
9
|
-
import { convertMessagesToModelMessages } from "./messages.js";
|
|
9
|
+
import { convertMessagesToModelMessages, generateMessageId } from "./messages.js";
|
|
10
10
|
import { MiddlewareRunner } from "./middleware/compose.js";
|
|
11
11
|
import { EventType } from "@ag-ui/core";
|
|
12
12
|
const kind = "text";
|
|
@@ -54,8 +54,9 @@ class TextEngine {
|
|
|
54
54
|
this.streamId = this.createId("stream");
|
|
55
55
|
this.effectiveRequest = config.params.abortController ? { signal: config.params.abortController.signal } : void 0;
|
|
56
56
|
this.effectiveSignal = config.params.abortController?.signal;
|
|
57
|
-
this.threadId = config.params.threadId || this.createId("thread");
|
|
57
|
+
this.threadId = config.params.threadId || config.params.conversationId || this.createId("thread");
|
|
58
58
|
this.runIdOverride = config.params.runId;
|
|
59
|
+
this.parentRunIdOverride = config.params.parentRunId;
|
|
59
60
|
const allMiddleware = [
|
|
60
61
|
devtoolsMiddleware(),
|
|
61
62
|
...config.middleware || [],
|
|
@@ -66,7 +67,10 @@ class TextEngine {
|
|
|
66
67
|
this.middlewareCtx = {
|
|
67
68
|
requestId: this.requestId,
|
|
68
69
|
streamId: this.streamId,
|
|
69
|
-
|
|
70
|
+
threadId: this.threadId,
|
|
71
|
+
// Legacy alias kept on the ctx so middleware that reads
|
|
72
|
+
// `ctx.conversationId` keeps working. Always equals `threadId`.
|
|
73
|
+
conversationId: this.threadId,
|
|
70
74
|
phase: "init",
|
|
71
75
|
iteration: 0,
|
|
72
76
|
chunkIndex: 0,
|
|
@@ -111,7 +115,7 @@ class TextEngine {
|
|
|
111
115
|
async *run() {
|
|
112
116
|
this.beforeRun();
|
|
113
117
|
this.logger.agentLoop("run started", {
|
|
114
|
-
|
|
118
|
+
threadId: this.middlewareCtx.threadId
|
|
115
119
|
});
|
|
116
120
|
try {
|
|
117
121
|
this.middlewareCtx.phase = "init";
|
|
@@ -173,7 +177,7 @@ class TextEngine {
|
|
|
173
177
|
} else {
|
|
174
178
|
this.logger.errors("chat run failed", {
|
|
175
179
|
error,
|
|
176
|
-
|
|
180
|
+
threadId: this.middlewareCtx.threadId
|
|
177
181
|
});
|
|
178
182
|
await this.middlewareRunner.runOnError(this.middlewareCtx, {
|
|
179
183
|
error,
|
|
@@ -269,7 +273,8 @@ class TextEngine {
|
|
|
269
273
|
systemPrompts: this.systemPrompts,
|
|
270
274
|
logger: this.logger,
|
|
271
275
|
threadId: this.threadId,
|
|
272
|
-
runId: this.runIdOverride
|
|
276
|
+
runId: this.runIdOverride,
|
|
277
|
+
parentRunId: this.parentRunIdOverride
|
|
273
278
|
})) {
|
|
274
279
|
if (this.isCancelled()) {
|
|
275
280
|
break;
|
|
@@ -1189,7 +1194,57 @@ async function* runStreamingStructuredOutputImpl(options, jsonSchema) {
|
|
|
1189
1194
|
chatOptions: structuredChatOptions,
|
|
1190
1195
|
outputSchema: jsonSchema
|
|
1191
1196
|
});
|
|
1197
|
+
let structuredMessageId = null;
|
|
1198
|
+
let startEmitted = false;
|
|
1199
|
+
const extractMessageId = (c) => {
|
|
1200
|
+
const id = c.messageId;
|
|
1201
|
+
return typeof id === "string" && id !== "" ? id : null;
|
|
1202
|
+
};
|
|
1203
|
+
const emitStartIfNeeded = function* (referenceChunk) {
|
|
1204
|
+
if (startEmitted) return;
|
|
1205
|
+
const idForStart = structuredMessageId ?? generateMessageId();
|
|
1206
|
+
structuredMessageId = idForStart;
|
|
1207
|
+
startEmitted = true;
|
|
1208
|
+
yield {
|
|
1209
|
+
type: EventType.CUSTOM,
|
|
1210
|
+
name: "structured-output.start",
|
|
1211
|
+
value: { messageId: idForStart },
|
|
1212
|
+
model: "model" in referenceChunk ? referenceChunk.model ?? model : model,
|
|
1213
|
+
timestamp: "timestamp" in referenceChunk ? referenceChunk.timestamp ?? Date.now() : Date.now(),
|
|
1214
|
+
runId
|
|
1215
|
+
};
|
|
1216
|
+
};
|
|
1192
1217
|
for await (const chunk of stream) {
|
|
1218
|
+
if (!structuredMessageId) {
|
|
1219
|
+
if (chunk.type === EventType.TEXT_MESSAGE_START || chunk.type === EventType.TEXT_MESSAGE_CONTENT) {
|
|
1220
|
+
structuredMessageId = extractMessageId(chunk);
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
if (chunk.type === EventType.RUN_ERROR && !startEmitted) {
|
|
1224
|
+
yield* emitStartIfNeeded(chunk);
|
|
1225
|
+
}
|
|
1226
|
+
if (!structuredMessageId && chunk.type === EventType.TEXT_MESSAGE_CONTENT) {
|
|
1227
|
+
yield {
|
|
1228
|
+
type: EventType.RUN_ERROR,
|
|
1229
|
+
runId,
|
|
1230
|
+
model,
|
|
1231
|
+
timestamp: Date.now(),
|
|
1232
|
+
message: "Structured-output stream produced text content without a messageId; adapter is not honoring the AG-UI contract.",
|
|
1233
|
+
code: "structured-output-missing-message-id"
|
|
1234
|
+
};
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
if (!startEmitted && structuredMessageId && (chunk.type === EventType.TEXT_MESSAGE_START || chunk.type === EventType.TEXT_MESSAGE_CONTENT)) {
|
|
1238
|
+
startEmitted = true;
|
|
1239
|
+
yield {
|
|
1240
|
+
type: EventType.CUSTOM,
|
|
1241
|
+
name: "structured-output.start",
|
|
1242
|
+
value: { messageId: structuredMessageId },
|
|
1243
|
+
model: "model" in chunk ? chunk.model ?? model : model,
|
|
1244
|
+
timestamp: "timestamp" in chunk ? chunk.timestamp ?? Date.now() : Date.now(),
|
|
1245
|
+
runId
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1193
1248
|
if (chunk.type === EventType.CUSTOM && chunk.name === "structured-output.complete") {
|
|
1194
1249
|
const value = chunk.value;
|
|
1195
1250
|
if (isStandardSchema(outputSchema)) {
|
|
@@ -1202,10 +1257,13 @@ async function* runStreamingStructuredOutputImpl(options, jsonSchema) {
|
|
|
1202
1257
|
...chunk,
|
|
1203
1258
|
// Forward `reasoning` through schema validation so consumers that
|
|
1204
1259
|
// only listen for the terminal event don't lose chain-of-thought.
|
|
1260
|
+
// Tag with messageId so the client processor can snap the right
|
|
1261
|
+
// assistant message's structured-output part.
|
|
1205
1262
|
value: {
|
|
1206
1263
|
object: validated,
|
|
1207
1264
|
raw: value.raw,
|
|
1208
|
-
...value.reasoning ? { reasoning: value.reasoning } : {}
|
|
1265
|
+
...value.reasoning ? { reasoning: value.reasoning } : {},
|
|
1266
|
+
...structuredMessageId ? { messageId: structuredMessageId } : {}
|
|
1209
1267
|
}
|
|
1210
1268
|
};
|
|
1211
1269
|
continue;
|
|
@@ -1237,6 +1295,16 @@ async function* runStreamingStructuredOutputImpl(options, jsonSchema) {
|
|
|
1237
1295
|
return;
|
|
1238
1296
|
}
|
|
1239
1297
|
}
|
|
1298
|
+
if (structuredMessageId) {
|
|
1299
|
+
yield {
|
|
1300
|
+
...chunk,
|
|
1301
|
+
value: {
|
|
1302
|
+
...chunk.value,
|
|
1303
|
+
messageId: structuredMessageId
|
|
1304
|
+
}
|
|
1305
|
+
};
|
|
1306
|
+
continue;
|
|
1307
|
+
}
|
|
1240
1308
|
yield chunk;
|
|
1241
1309
|
continue;
|
|
1242
1310
|
}
|