@tanstack/ai 0.32.0 → 0.34.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/index.js +47 -20
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +7 -0
- package/dist/esm/activities/chat/tools/lazy-tool-manager.d.ts +25 -1
- package/dist/esm/activities/chat/tools/lazy-tool-manager.js +26 -2
- package/dist/esm/activities/chat/tools/lazy-tool-manager.js.map +1 -1
- package/dist/esm/activities/chat/tools/schema-converter.d.ts +13 -0
- package/dist/esm/activities/chat/tools/schema-converter.js +61 -33
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
- package/dist/esm/activities/generateAudio/index.d.ts +7 -0
- package/dist/esm/activities/generateAudio/index.js +26 -1
- package/dist/esm/activities/generateAudio/index.js.map +1 -1
- package/dist/esm/activities/generateImage/index.d.ts +7 -0
- package/dist/esm/activities/generateImage/index.js +26 -1
- package/dist/esm/activities/generateImage/index.js.map +1 -1
- package/dist/esm/activities/generateSpeech/index.d.ts +7 -0
- package/dist/esm/activities/generateSpeech/index.js +26 -1
- package/dist/esm/activities/generateSpeech/index.js.map +1 -1
- package/dist/esm/activities/generateTranscription/index.d.ts +7 -0
- package/dist/esm/activities/generateTranscription/index.js +26 -1
- package/dist/esm/activities/generateTranscription/index.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.d.ts +9 -0
- package/dist/esm/activities/generateVideo/index.js +52 -2
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/middleware/index.d.ts +2 -0
- package/dist/esm/activities/middleware/run.d.ts +20 -0
- package/dist/esm/activities/middleware/run.js +42 -0
- package/dist/esm/activities/middleware/run.js.map +1 -0
- package/dist/esm/activities/middleware/types.d.ts +118 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/middlewares/otel.d.ts +8 -2
- package/dist/esm/middlewares/otel.js +145 -95
- package/dist/esm/middlewares/otel.js.map +1 -1
- package/dist/esm/middlewares/usage-attributes.d.ts +24 -0
- package/dist/esm/middlewares/usage-attributes.js +43 -0
- package/dist/esm/middlewares/usage-attributes.js.map +1 -0
- package/dist/esm/types.d.ts +7 -7
- package/dist/esm/utilities/errors.d.ts +13 -0
- package/dist/esm/utilities/errors.js +22 -0
- package/dist/esm/utilities/errors.js.map +1 -0
- package/dist/esm/utilities/numbers.d.ts +8 -0
- package/dist/esm/utilities/numbers.js +12 -0
- package/dist/esm/utilities/numbers.js.map +1 -0
- package/package.json +3 -2
- package/src/activities/chat/index.ts +125 -35
- package/src/activities/chat/middleware/types.ts +7 -0
- package/src/activities/chat/tools/lazy-tool-manager.ts +46 -4
- package/src/activities/chat/tools/schema-converter.ts +146 -93
- package/src/activities/generateAudio/index.ts +42 -1
- package/src/activities/generateImage/index.ts +42 -1
- package/src/activities/generateSpeech/index.ts +42 -1
- package/src/activities/generateTranscription/index.ts +42 -1
- package/src/activities/generateVideo/index.ts +88 -2
- package/src/activities/middleware/index.ts +20 -0
- package/src/activities/middleware/run.ts +88 -0
- package/src/activities/middleware/types.ts +173 -0
- package/src/index.ts +19 -0
- package/src/middlewares/otel.ts +195 -120
- package/src/middlewares/usage-attributes.ts +65 -0
- package/src/types.ts +7 -7
- package/src/utilities/errors.ts +29 -0
- package/src/utilities/numbers.ts +15 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { devtoolsMiddleware } from "@tanstack/ai-event-client";
|
|
2
|
+
import { undoNullWidening } from "@tanstack/ai-utils";
|
|
2
3
|
import { stripToSpecMiddleware } from "../../strip-to-spec-middleware.js";
|
|
3
4
|
import { streamToText } from "../../stream-to-response.js";
|
|
4
5
|
import { resolveDebugOption } from "../../logger/resolve.js";
|
|
5
6
|
import { normalizeToolResult } from "../../utilities/tool-result.js";
|
|
6
7
|
import { LazyToolManager } from "./tools/lazy-tool-manager.js";
|
|
7
8
|
import { ToolCallManager, MiddlewareAbortError, executeToolCalls } from "./tools/tool-calls.js";
|
|
8
|
-
import {
|
|
9
|
+
import { convertSchemaForStructuredOutput, isStandardSchema, parseWithStandardSchema, convertSchemaToJsonSchema } from "./tools/schema-converter.js";
|
|
9
10
|
import { maxIterations } from "./agent-loop-strategies.js";
|
|
10
11
|
import { convertMessagesToModelMessages, generateMessageId } from "./messages.js";
|
|
11
12
|
import { MiddlewareRunner } from "./middleware/compose.js";
|
|
@@ -90,8 +91,8 @@ class TextEngine {
|
|
|
90
91
|
// to carry, so the client matches it to the streaming text deltas.
|
|
91
92
|
combinedStructuredMessageId = null;
|
|
92
93
|
// Holds the validated value when `finalStructuredOutput.validate` is provided
|
|
93
|
-
// and succeeds. Distinct from `structuredOutputResult.data` (the
|
|
94
|
-
// unvalidated payload from the structured-output.complete chunk).
|
|
94
|
+
// and succeeds. Distinct from `structuredOutputResult.data` (the normalized
|
|
95
|
+
// but unvalidated payload from the structured-output.complete chunk).
|
|
95
96
|
validatedStructuredOutput = void 0;
|
|
96
97
|
hasValidatedStructuredOutput = false;
|
|
97
98
|
finalizationError = null;
|
|
@@ -155,6 +156,7 @@ class TextEngine {
|
|
|
155
156
|
this.deferredPromises.push(promise);
|
|
156
157
|
},
|
|
157
158
|
// Provider / adapter info
|
|
159
|
+
activity: "chat",
|
|
158
160
|
provider: config.adapter.name,
|
|
159
161
|
model: config.params.model,
|
|
160
162
|
source: "server",
|
|
@@ -525,6 +527,20 @@ class TextEngine {
|
|
|
525
527
|
this.currentThinkingSignature = chunk.signature;
|
|
526
528
|
}
|
|
527
529
|
}
|
|
530
|
+
/**
|
|
531
|
+
* Tools available for execution this turn. The discovery tool is dropped
|
|
532
|
+
* from the advertised set (`this.tools`) once every lazy tool is discovered,
|
|
533
|
+
* but a model may still re-request discovery; this widens execution lookup
|
|
534
|
+
* to include it so such calls don't fail with "Unknown tool". Centralised so
|
|
535
|
+
* both execution sites (`processToolCalls` and `checkForPendingToolCalls`)
|
|
536
|
+
* stay in sync.
|
|
537
|
+
*/
|
|
538
|
+
resolveExecutableTools(toolCalls) {
|
|
539
|
+
return this.lazyToolManager.getExecutableTools(
|
|
540
|
+
this.tools,
|
|
541
|
+
toolCalls.map((tc) => tc.function.name)
|
|
542
|
+
);
|
|
543
|
+
}
|
|
528
544
|
async *checkForPendingToolCalls() {
|
|
529
545
|
const pendingToolCalls = this.getPendingToolCallsFromMessages();
|
|
530
546
|
if (pendingToolCalls.length === 0) {
|
|
@@ -562,7 +578,7 @@ class TextEngine {
|
|
|
562
578
|
const { approvals, clientToolResults } = this.collectClientState();
|
|
563
579
|
const generator = executeToolCalls(
|
|
564
580
|
executablePendingCalls,
|
|
565
|
-
this.
|
|
581
|
+
this.resolveExecutableTools(executablePendingCalls),
|
|
566
582
|
approvals,
|
|
567
583
|
clientToolResults,
|
|
568
584
|
(eventName, data) => this.createCustomEventChunk(eventName, data),
|
|
@@ -694,7 +710,7 @@ class TextEngine {
|
|
|
694
710
|
const { approvals, clientToolResults } = this.collectClientState();
|
|
695
711
|
const generator = executeToolCalls(
|
|
696
712
|
executableToolCalls,
|
|
697
|
-
this.
|
|
713
|
+
this.resolveExecutableTools(executableToolCalls),
|
|
698
714
|
approvals,
|
|
699
715
|
clientToolResults,
|
|
700
716
|
(eventName, data) => this.createCustomEventChunk(eventName, data),
|
|
@@ -1125,13 +1141,16 @@ class TextEngine {
|
|
|
1125
1141
|
}
|
|
1126
1142
|
}
|
|
1127
1143
|
}
|
|
1144
|
+
let outboundChunk = chunk;
|
|
1128
1145
|
if (chunk.type === EventType.CUSTOM && chunk.name === "structured-output.complete") {
|
|
1129
1146
|
const parsed = readStructuredOutputCompleteValue(chunk.value);
|
|
1130
1147
|
if (parsed) {
|
|
1131
|
-
this.
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1148
|
+
const object = this.finalStructuredOutput.normalize ? this.finalStructuredOutput.normalize(parsed.object) : parsed.object;
|
|
1149
|
+
this.structuredOutputResult = { data: object, rawText: parsed.raw };
|
|
1150
|
+
const value = chunk.value;
|
|
1151
|
+
if (object !== parsed.object && value && typeof value === "object") {
|
|
1152
|
+
outboundChunk = { ...chunk, value: { ...value, object } };
|
|
1153
|
+
}
|
|
1135
1154
|
}
|
|
1136
1155
|
}
|
|
1137
1156
|
if (chunk.type === EventType.RUN_FINISHED && chunk.usage) {
|
|
@@ -1146,7 +1165,7 @@ class TextEngine {
|
|
|
1146
1165
|
}
|
|
1147
1166
|
const outputChunks = await this.middlewareRunner.runOnChunk(
|
|
1148
1167
|
this.middlewareCtx,
|
|
1149
|
-
|
|
1168
|
+
outboundChunk
|
|
1150
1169
|
);
|
|
1151
1170
|
if (this.finalStructuredOutput.yieldChunks) {
|
|
1152
1171
|
for (const outputChunk of outputChunks) {
|
|
@@ -1252,7 +1271,8 @@ class TextEngine {
|
|
|
1252
1271
|
} else {
|
|
1253
1272
|
try {
|
|
1254
1273
|
const parsed = JSON.parse(rawText);
|
|
1255
|
-
this.
|
|
1274
|
+
const data = this.finalStructuredOutput.normalize ? this.finalStructuredOutput.normalize(parsed) : parsed;
|
|
1275
|
+
this.structuredOutputResult = { data, rawText };
|
|
1256
1276
|
} catch (err) {
|
|
1257
1277
|
const detail = rawText.slice(0, 200) + (rawText.length > 200 ? "..." : "");
|
|
1258
1278
|
this.finalizationError = {
|
|
@@ -1493,12 +1513,11 @@ async function runAgenticStructuredOutput(options) {
|
|
|
1493
1513
|
if (!outputSchema) {
|
|
1494
1514
|
throw new Error("outputSchema is required for structured output");
|
|
1495
1515
|
}
|
|
1496
|
-
const jsonSchema =
|
|
1497
|
-
forStructuredOutput: true
|
|
1498
|
-
});
|
|
1516
|
+
const { jsonSchema, nullWideningMap } = convertSchemaForStructuredOutput(outputSchema);
|
|
1499
1517
|
if (!jsonSchema) {
|
|
1500
1518
|
throw new Error("Failed to convert output schema to JSON Schema");
|
|
1501
1519
|
}
|
|
1520
|
+
const normalize = (data) => undoNullWidening(data, nullWideningMap);
|
|
1502
1521
|
const validate = isStandardSchema(outputSchema) ? (data) => parseWithStandardSchema(outputSchema, data) : void 0;
|
|
1503
1522
|
const nativeCombined = adapter.supportsCombinedToolsAndSchema?.(options.modelOptions) === true;
|
|
1504
1523
|
const mcpManager = MCPManager.from(mcp);
|
|
@@ -1515,6 +1534,7 @@ async function runAgenticStructuredOutput(options) {
|
|
|
1515
1534
|
finalStructuredOutput: {
|
|
1516
1535
|
jsonSchema,
|
|
1517
1536
|
yieldChunks: false,
|
|
1537
|
+
normalize,
|
|
1518
1538
|
...validate ? { validate } : {},
|
|
1519
1539
|
...nativeCombined ? { nativeCombined: true } : {}
|
|
1520
1540
|
}
|
|
@@ -1629,7 +1649,13 @@ async function* fallbackStructuredOutputStream(adapter, options, onAdapterError)
|
|
|
1629
1649
|
threadId,
|
|
1630
1650
|
model,
|
|
1631
1651
|
timestamp,
|
|
1632
|
-
finishReason: "stop"
|
|
1652
|
+
finishReason: "stop",
|
|
1653
|
+
// Forward adapter-reported token usage so consumers reading
|
|
1654
|
+
// `RUN_FINISHED.usage` (and the engine's `runOnUsage` middleware hook) see
|
|
1655
|
+
// it on the fallback path, mirroring the native streaming path. The
|
|
1656
|
+
// conditional spread avoids emitting `usage: undefined` for adapters that
|
|
1657
|
+
// don't report it. See #758.
|
|
1658
|
+
...result.usage ? { usage: result.usage } : {}
|
|
1633
1659
|
};
|
|
1634
1660
|
}
|
|
1635
1661
|
function runStreamingStructuredOutput(options) {
|
|
@@ -1637,18 +1663,18 @@ function runStreamingStructuredOutput(options) {
|
|
|
1637
1663
|
if (!outputSchema) {
|
|
1638
1664
|
throw new Error("outputSchema is required for streaming structured output");
|
|
1639
1665
|
}
|
|
1640
|
-
const jsonSchema =
|
|
1641
|
-
forStructuredOutput: true
|
|
1642
|
-
});
|
|
1666
|
+
const { jsonSchema, nullWideningMap } = convertSchemaForStructuredOutput(outputSchema);
|
|
1643
1667
|
if (!jsonSchema) {
|
|
1644
1668
|
throw new Error("Failed to convert output schema to JSON Schema");
|
|
1645
1669
|
}
|
|
1670
|
+
const normalize = (data) => undoNullWidening(data, nullWideningMap);
|
|
1646
1671
|
return runStreamingStructuredOutputImpl(
|
|
1647
1672
|
options,
|
|
1648
|
-
jsonSchema
|
|
1673
|
+
jsonSchema,
|
|
1674
|
+
normalize
|
|
1649
1675
|
);
|
|
1650
1676
|
}
|
|
1651
|
-
async function* runStreamingStructuredOutputImpl(options, jsonSchema) {
|
|
1677
|
+
async function* runStreamingStructuredOutputImpl(options, jsonSchema, normalize) {
|
|
1652
1678
|
const {
|
|
1653
1679
|
adapter,
|
|
1654
1680
|
outputSchema,
|
|
@@ -1675,6 +1701,7 @@ async function* runStreamingStructuredOutputImpl(options, jsonSchema) {
|
|
|
1675
1701
|
finalStructuredOutput: {
|
|
1676
1702
|
jsonSchema,
|
|
1677
1703
|
yieldChunks: true,
|
|
1704
|
+
normalize,
|
|
1678
1705
|
...nativeCombined ? { nativeCombined: true } : {}
|
|
1679
1706
|
}
|
|
1680
1707
|
},
|