@tanstack/ai 0.51.0 → 0.52.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 +94 -23
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/middleware/compose.js +4 -2
- package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
- package/dist/esm/activities/chat/middleware/index.d.ts +2 -0
- package/dist/esm/activities/chat/middleware/metadata.d.ts +16 -0
- package/dist/esm/activities/chat/middleware/metadata.js +8 -0
- package/dist/esm/activities/chat/middleware/metadata.js.map +1 -0
- package/dist/esm/activities/chat/middleware/types.d.ts +9 -0
- package/dist/esm/activities/chat/middleware/types.js.map +1 -1
- package/dist/esm/activities/chat/tools/schema-converter.js +21 -10
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +2 -1
- package/package.json +2 -2
- package/src/activities/chat/index.ts +139 -44
- package/src/activities/chat/middleware/compose.ts +14 -2
- package/src/activities/chat/middleware/index.ts +3 -0
- package/src/activities/chat/middleware/metadata.ts +20 -0
- package/src/activities/chat/middleware/types.ts +9 -0
- package/src/activities/chat/tools/schema-converter.ts +30 -17
- package/src/index.ts +4 -0
|
@@ -115,6 +115,7 @@ var TextEngine = class {
|
|
|
115
115
|
effectiveRequest;
|
|
116
116
|
effectiveSignal;
|
|
117
117
|
messages;
|
|
118
|
+
providerMessages;
|
|
118
119
|
iterationCount = 0;
|
|
119
120
|
/** Cumulative tool calls counted in this run (emitted + pending resume). */
|
|
120
121
|
toolCallCount = 0;
|
|
@@ -156,6 +157,9 @@ var TextEngine = class {
|
|
|
156
157
|
middlewareRunner;
|
|
157
158
|
middlewareCtx;
|
|
158
159
|
sandboxFileQueue = [];
|
|
160
|
+
middlewareCustomQueue = [];
|
|
161
|
+
middlewareCustomWaiters = [];
|
|
162
|
+
drainingMiddlewareCustom = false;
|
|
159
163
|
deferredPromises = [];
|
|
160
164
|
abortReason;
|
|
161
165
|
middlewareAbortController;
|
|
@@ -193,6 +197,7 @@ var TextEngine = class {
|
|
|
193
197
|
this.initialApprovals = approvals;
|
|
194
198
|
this.initialClientToolResults = clientToolResults;
|
|
195
199
|
this.messages = convertMessagesToModelMessages(config.params.messages);
|
|
200
|
+
this.providerMessages = this.messages;
|
|
196
201
|
assertUniqueToolNames(config.params.tools || []);
|
|
197
202
|
this.lazyToolManager = new LazyToolManager(config.params.tools || [], this.messages, config.params.lazyToolsConfig);
|
|
198
203
|
this.tools = this.lazyToolManager.getActiveTools();
|
|
@@ -223,6 +228,12 @@ var TextEngine = class {
|
|
|
223
228
|
this.abortReason = reason;
|
|
224
229
|
this.middlewareAbortController?.abort(reason);
|
|
225
230
|
},
|
|
231
|
+
emitCustomEvent: (name, value) => {
|
|
232
|
+
this.middlewareCustomQueue.push(this.createCustomEventChunk(name, value));
|
|
233
|
+
const waiters = this.middlewareCustomWaiters;
|
|
234
|
+
this.middlewareCustomWaiters = [];
|
|
235
|
+
for (const waiter of waiters) waiter();
|
|
236
|
+
},
|
|
226
237
|
context: config.context,
|
|
227
238
|
defer: (promise) => {
|
|
228
239
|
this.deferredPromises.push(promise);
|
|
@@ -304,14 +315,14 @@ var TextEngine = class {
|
|
|
304
315
|
this.beforeRun();
|
|
305
316
|
this.logger.agentLoop("run started", { threadId: this.middlewareCtx.threadId });
|
|
306
317
|
try {
|
|
307
|
-
|
|
318
|
+
yield* this.runWhileYielding(this.middlewareRunner.runSetup(this.middlewareCtx));
|
|
308
319
|
this.middlewareCtx.phase = "init";
|
|
309
320
|
const initialConfig = this.buildMiddlewareConfig();
|
|
310
|
-
const transformedConfig =
|
|
321
|
+
const transformedConfig = yield* this.runWhileYielding(this.middlewareRunner.runOnConfig(this.middlewareCtx, initialConfig));
|
|
311
322
|
this.applyMiddlewareConfig(transformedConfig);
|
|
312
323
|
await this.applyEphemeralInterruptResume(transformedConfig);
|
|
313
324
|
await this.applyDurableGenericInterruptResolution();
|
|
314
|
-
|
|
325
|
+
yield* this.runWhileYielding(this.middlewareRunner.runOnStart(this.middlewareCtx));
|
|
315
326
|
if (this.earlyTermination) {
|
|
316
327
|
yield* this.emitSuccessfulEarlyTermination();
|
|
317
328
|
if (!this.terminalHookCalled) {
|
|
@@ -330,12 +341,12 @@ var TextEngine = class {
|
|
|
330
341
|
if (this.earlyTermination) break;
|
|
331
342
|
if (this.isCancelled()) return;
|
|
332
343
|
this.logger.agentLoop(`iteration=${this.middlewareCtx.iteration}`, { iteration: this.middlewareCtx.iteration });
|
|
333
|
-
|
|
344
|
+
yield* this.runWhileYielding(this.beginCycle());
|
|
334
345
|
if (this.cyclePhase === "processText") {
|
|
335
346
|
this.middlewareCtx.phase = "beforeModel";
|
|
336
347
|
this.middlewareCtx.iteration = this.iterationCount;
|
|
337
348
|
const iterConfig = this.buildMiddlewareConfig();
|
|
338
|
-
const iterTransformedConfig =
|
|
349
|
+
const iterTransformedConfig = yield* this.runWhileYielding(this.middlewareRunner.runOnConfig(this.middlewareCtx, iterConfig));
|
|
339
350
|
this.applyMiddlewareConfig(iterTransformedConfig);
|
|
340
351
|
if (yield* this.emitBoundaryInterrupts("beforeModel", this.createSyntheticFinishedEvent())) {
|
|
341
352
|
this.setToolPhase("wait");
|
|
@@ -353,7 +364,7 @@ var TextEngine = class {
|
|
|
353
364
|
} else yield* this.flushDeferredModelRunFinishedChunks();
|
|
354
365
|
} else yield* this.processToolCalls();
|
|
355
366
|
this.endCycle();
|
|
356
|
-
} while (
|
|
367
|
+
} while (yield* this.runWhileYielding(this.shouldContinue()));
|
|
357
368
|
this.logger.agentLoop("run finished", { finishReason: this.lastFinishReason });
|
|
358
369
|
if (this.finalStructuredOutput && this.toolPhase !== "wait" && !this.isCancelled() && !this.finalizationError && !this.earlyTermination) {
|
|
359
370
|
if (this.finalStructuredOutput.nativeCombined === true) yield* this.harvestCombinedStructuredOutput();
|
|
@@ -505,7 +516,7 @@ var TextEngine = class {
|
|
|
505
516
|
for (const [approvalId, resolution] of approvals) adapterApprovals.set(approvalId, typeof resolution === "boolean" ? resolution : resolution.approved);
|
|
506
517
|
for await (const raw of this.adapter.chatStream({
|
|
507
518
|
model: this.params.model,
|
|
508
|
-
messages: this.
|
|
519
|
+
messages: this.providerMessages,
|
|
509
520
|
tools: toolsWithJsonSchemas,
|
|
510
521
|
metadata,
|
|
511
522
|
request: this.effectiveRequest,
|
|
@@ -581,16 +592,21 @@ var TextEngine = class {
|
|
|
581
592
|
this.deferredToolCallRunFinishedChunks.push(spec);
|
|
582
593
|
continue;
|
|
583
594
|
}
|
|
584
|
-
if (spec.type === EventType.RUN_STARTED)
|
|
595
|
+
if (spec.type === EventType.RUN_STARTED) {
|
|
596
|
+
if (this.hasPublicRunStarted) continue;
|
|
597
|
+
this.hasPublicRunStarted = true;
|
|
598
|
+
}
|
|
585
599
|
this.logger.output(`type=${spec.type}`, { chunk: spec });
|
|
586
600
|
yield spec;
|
|
587
601
|
this.middlewareCtx.chunkIndex++;
|
|
588
602
|
}
|
|
589
603
|
if (raw.type === EventType.RUN_FINISHED) await this.runOnUsageFromChunk(raw);
|
|
590
604
|
yield* this.drainSandboxFileQueue();
|
|
605
|
+
yield* this.drainMiddlewareCustomQueue();
|
|
591
606
|
if (this.earlyTermination) break;
|
|
592
607
|
}
|
|
593
608
|
yield* this.drainSandboxFileQueue();
|
|
609
|
+
yield* this.drainMiddlewareCustomQueue();
|
|
594
610
|
}
|
|
595
611
|
handleStreamChunk(chunk) {
|
|
596
612
|
switch (chunk.type) {
|
|
@@ -810,12 +826,12 @@ var TextEngine = class {
|
|
|
810
826
|
return "stop";
|
|
811
827
|
}
|
|
812
828
|
const allResults = [...executionResult.results, ...deferredErrorResults];
|
|
813
|
-
|
|
829
|
+
yield* this.runWhileYielding(this.middlewareRunner.runOnToolPhaseComplete(this.middlewareCtx, {
|
|
814
830
|
toolCalls: pendingToolCalls,
|
|
815
831
|
results: allResults,
|
|
816
832
|
needsApproval: executionResult.needsApproval,
|
|
817
833
|
needsClientExecution: executionResult.needsClientExecution
|
|
818
|
-
});
|
|
834
|
+
}));
|
|
819
835
|
if (executionResult.needsApproval.length > 0 || executionResult.needsClientExecution.length > 0) {
|
|
820
836
|
this.discardDeferredToolCallRunFinishedChunks();
|
|
821
837
|
if (allResults.length > 0) for (const chunk of this.buildToolResultChunks(allResults, finishEvent)) yield* this.pipeThroughMiddleware(chunk);
|
|
@@ -903,14 +919,14 @@ var TextEngine = class {
|
|
|
903
919
|
return;
|
|
904
920
|
}
|
|
905
921
|
const allResults = [...executionResult.results, ...deferredErrorResults];
|
|
906
|
-
|
|
922
|
+
yield* this.runWhileYielding(this.middlewareRunner.runOnToolPhaseComplete(this.middlewareCtx, {
|
|
907
923
|
toolCalls,
|
|
908
924
|
results: allResults,
|
|
909
925
|
needsApproval: executionResult.needsApproval,
|
|
910
926
|
needsClientExecution: executionResult.needsClientExecution
|
|
911
|
-
});
|
|
927
|
+
}));
|
|
912
928
|
const afterToolBoundaryChunks = this.buildToolResultChunks(allResults, finishEvent);
|
|
913
|
-
const afterToolRequests =
|
|
929
|
+
const afterToolRequests = yield* this.runWhileYielding(this.middlewareRunner.runOnInterruptBoundary(this.middlewareCtx));
|
|
914
930
|
if (afterToolRequests.length > 0) {
|
|
915
931
|
for (const chunk of afterToolBoundaryChunks) yield* this.pipeThroughMiddleware(chunk);
|
|
916
932
|
yield* this.emitBoundaryInterrupts("afterTools", finishEvent, toolCalls, afterToolRequests);
|
|
@@ -1286,7 +1302,7 @@ var TextEngine = class {
|
|
|
1286
1302
|
}
|
|
1287
1303
|
async *emitBoundaryInterrupts(phase, finishEvent, toolCalls = [], requests) {
|
|
1288
1304
|
this.middlewareCtx.phase = phase;
|
|
1289
|
-
const boundaryRequests = requests ??
|
|
1305
|
+
const boundaryRequests = requests ?? (yield* this.runWhileYielding(this.middlewareRunner.runOnInterruptBoundary(this.middlewareCtx)));
|
|
1290
1306
|
if (boundaryRequests.length === 0) return false;
|
|
1291
1307
|
for (const request of boundaryRequests) if (this.interruptDefinitions.get(request.definition.id) !== request.definition) throw new Error(`Generic interrupt definition ${request.definition.id} is not registered on this chat.`);
|
|
1292
1308
|
if (phase === "afterModel") {
|
|
@@ -1625,17 +1641,17 @@ var TextEngine = class {
|
|
|
1625
1641
|
...baseWithoutTools,
|
|
1626
1642
|
outputSchema: this.finalStructuredOutput.jsonSchema
|
|
1627
1643
|
};
|
|
1628
|
-
structuredConfig =
|
|
1644
|
+
structuredConfig = yield* this.runWhileYielding(this.middlewareRunner.runOnStructuredOutputConfig(this.middlewareCtx, structuredConfig));
|
|
1629
1645
|
const { outputSchema: pinnedSchema, ...chatConfigSlice } = structuredConfig;
|
|
1630
|
-
const postOnConfig =
|
|
1646
|
+
const postOnConfig = yield* this.runWhileYielding(this.middlewareRunner.runOnConfig(this.middlewareCtx, {
|
|
1631
1647
|
...chatConfigSlice,
|
|
1632
1648
|
tools: baseConfig.tools
|
|
1633
|
-
});
|
|
1649
|
+
}));
|
|
1634
1650
|
this.applyMiddlewareConfig(postOnConfig);
|
|
1635
1651
|
const structuredCallOptions = {
|
|
1636
1652
|
chatOptions: {
|
|
1637
1653
|
model: this.params.model,
|
|
1638
|
-
messages: this.
|
|
1654
|
+
messages: this.providerMessages,
|
|
1639
1655
|
metadata: postOnConfig.metadata,
|
|
1640
1656
|
modelOptions: postOnConfig.modelOptions,
|
|
1641
1657
|
systemPrompts: postOnConfig.systemPrompts,
|
|
@@ -1859,6 +1875,7 @@ var TextEngine = class {
|
|
|
1859
1875
|
buildMiddlewareConfig() {
|
|
1860
1876
|
return {
|
|
1861
1877
|
messages: this.messages,
|
|
1878
|
+
providerMessages: this.messages,
|
|
1862
1879
|
systemPrompts: [...this.systemPrompts],
|
|
1863
1880
|
tools: [...this.tools],
|
|
1864
1881
|
resume: this.params.resume,
|
|
@@ -2072,6 +2089,7 @@ var TextEngine = class {
|
|
|
2072
2089
|
applyMiddlewareConfig(config) {
|
|
2073
2090
|
this.applyResumeToolState(config.resumeToolState);
|
|
2074
2091
|
this.messages = config.messages;
|
|
2092
|
+
this.providerMessages = config.providerMessages ?? config.messages;
|
|
2075
2093
|
this.systemPrompts = config.systemPrompts;
|
|
2076
2094
|
assertUniqueToolNames(config.tools);
|
|
2077
2095
|
this.tools = config.tools;
|
|
@@ -2096,7 +2114,10 @@ var TextEngine = class {
|
|
|
2096
2114
|
*emitPublicChunks(outputs) {
|
|
2097
2115
|
for (const output of outputs) for (const spec of normalizeStreamChunk(output)) {
|
|
2098
2116
|
restorePublicUsage(spec);
|
|
2099
|
-
if (spec.type === EventType.RUN_STARTED)
|
|
2117
|
+
if (spec.type === EventType.RUN_STARTED) {
|
|
2118
|
+
if (this.hasPublicRunStarted) continue;
|
|
2119
|
+
this.hasPublicRunStarted = true;
|
|
2120
|
+
}
|
|
2100
2121
|
yield spec;
|
|
2101
2122
|
this.middlewareCtx.chunkIndex++;
|
|
2102
2123
|
}
|
|
@@ -2108,6 +2129,55 @@ var TextEngine = class {
|
|
|
2108
2129
|
async *pipeThroughMiddleware(chunk) {
|
|
2109
2130
|
const afterMw = await this.middlewareRunner.runOnChunk(this.middlewareCtx, chunk);
|
|
2110
2131
|
yield* this.emitPublicChunks(afterMw);
|
|
2132
|
+
if (!this.drainingMiddlewareCustom) yield* this.drainMiddlewareCustomQueue();
|
|
2133
|
+
}
|
|
2134
|
+
/**
|
|
2135
|
+
* Drain CUSTOM chunks pushed by `ctx.emitCustomEvent` through middleware
|
|
2136
|
+
* and into the public stream. If the run has not yet sent `RUN_STARTED`,
|
|
2137
|
+
* emit that first so CUSTOM events are not the first wire event.
|
|
2138
|
+
*/
|
|
2139
|
+
async *drainMiddlewareCustomQueue() {
|
|
2140
|
+
if (this.drainingMiddlewareCustom) return;
|
|
2141
|
+
if (this.middlewareCustomQueue.length === 0) return;
|
|
2142
|
+
this.drainingMiddlewareCustom = true;
|
|
2143
|
+
try {
|
|
2144
|
+
yield* this.emitSyntheticRunStarted(this.createSyntheticFinishedEvent());
|
|
2145
|
+
while (this.middlewareCustomQueue.length > 0) {
|
|
2146
|
+
const chunk = this.middlewareCustomQueue.shift();
|
|
2147
|
+
if (chunk) yield* this.pipeThroughMiddleware(chunk);
|
|
2148
|
+
}
|
|
2149
|
+
} finally {
|
|
2150
|
+
this.drainingMiddlewareCustom = false;
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
/**
|
|
2154
|
+
* Await `work` while yielding any `emitCustomEvent` chunks as they arrive.
|
|
2155
|
+
*/
|
|
2156
|
+
async *runWhileYielding(work) {
|
|
2157
|
+
let settled = false;
|
|
2158
|
+
let result;
|
|
2159
|
+
let error;
|
|
2160
|
+
const done = work.then((value) => {
|
|
2161
|
+
settled = true;
|
|
2162
|
+
result = value;
|
|
2163
|
+
}, (err) => {
|
|
2164
|
+
settled = true;
|
|
2165
|
+
error = err;
|
|
2166
|
+
});
|
|
2167
|
+
while (!settled) {
|
|
2168
|
+
yield* this.drainMiddlewareCustomQueue();
|
|
2169
|
+
if (settled) break;
|
|
2170
|
+
await Promise.race([done, new Promise((resolve) => {
|
|
2171
|
+
if (this.middlewareCustomQueue.length > 0) {
|
|
2172
|
+
resolve();
|
|
2173
|
+
return;
|
|
2174
|
+
}
|
|
2175
|
+
this.middlewareCustomWaiters.push(resolve);
|
|
2176
|
+
})]);
|
|
2177
|
+
}
|
|
2178
|
+
yield* this.drainMiddlewareCustomQueue();
|
|
2179
|
+
if (error !== void 0) throw error;
|
|
2180
|
+
return result;
|
|
2111
2181
|
}
|
|
2112
2182
|
/**
|
|
2113
2183
|
* Drain queued `sandbox.file` chunks (emitted via the SandboxRuntime sink)
|
|
@@ -2124,12 +2194,13 @@ var TextEngine = class {
|
|
|
2124
2194
|
* through the middleware pipeline and returning the final ExecuteToolCallsResult.
|
|
2125
2195
|
*/
|
|
2126
2196
|
async *drainToolCallGenerator(generator) {
|
|
2127
|
-
let
|
|
2128
|
-
while (
|
|
2197
|
+
let pending = generator.next();
|
|
2198
|
+
while (true) {
|
|
2199
|
+
const next = yield* this.runWhileYielding(pending);
|
|
2200
|
+
if (next.done) return next.value;
|
|
2129
2201
|
yield* this.pipeThroughMiddleware(next.value);
|
|
2130
|
-
|
|
2202
|
+
pending = generator.next();
|
|
2131
2203
|
}
|
|
2132
|
-
return next.value;
|
|
2133
2204
|
}
|
|
2134
2205
|
createCustomEventChunk(eventName, value) {
|
|
2135
2206
|
return {
|