@tanstack/ai-client 0.28.0 → 0.29.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/chat-client.d.ts +3 -0
- package/dist/esm/chat-client.js +33 -11
- package/dist/esm/chat-client.js.map +1 -1
- package/dist/esm/connection-adapters.js +2 -1
- package/dist/esm/connection-adapters.js.map +1 -1
- package/dist/esm/message-date-normalizer.d.ts +3 -0
- package/dist/esm/message-date-normalizer.js +35 -0
- package/dist/esm/message-date-normalizer.js.map +1 -0
- package/dist/esm/storage-adapters.js +13 -1
- package/dist/esm/storage-adapters.js.map +1 -1
- package/dist/esm/types.d.ts +5 -0
- package/dist/esm/types.js.map +1 -1
- package/package.json +3 -3
- package/src/chat-client.ts +70 -7
- package/src/connection-adapters.ts +5 -2
- package/src/message-date-normalizer.ts +29 -0
- package/src/storage-adapters.ts +13 -2
- package/src/types.ts +5 -0
|
@@ -125,6 +125,8 @@ export declare class ChatClient<TTools extends ReadonlyArray<AnyClientTool> = an
|
|
|
125
125
|
private processingResolve;
|
|
126
126
|
private errorReportedGeneration;
|
|
127
127
|
private streamGeneration;
|
|
128
|
+
private continuationGeneration;
|
|
129
|
+
private streamContinuationGeneration;
|
|
128
130
|
private continuationSkipped;
|
|
129
131
|
private draining;
|
|
130
132
|
private sessionGenerating;
|
|
@@ -239,6 +241,7 @@ export declare class ChatClient<TTools extends ReadonlyArray<AnyClientTool> = an
|
|
|
239
241
|
retryInterrupts(): void;
|
|
240
242
|
/** Unsafe low-level resume escape hatch. Prefer bound interrupt methods. */
|
|
241
243
|
resumeInterruptsUnsafe(resume: Array<RunAgentResumeItem>, state?: ChatResumeState): Promise<boolean>;
|
|
244
|
+
private resumeInterruptsUnsafeForGeneration;
|
|
242
245
|
/** @deprecated Use bound interrupt methods or resumeInterruptsUnsafe(). */
|
|
243
246
|
resumeInterrupts(resume: Array<RunAgentResumeItem>, state?: ChatResumeState): Promise<boolean>;
|
|
244
247
|
private submitInterruptBatch;
|
package/dist/esm/chat-client.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { prepareResolvedByokHeaders, resolveByokProviderId } from "./byok/resolve.js";
|
|
2
2
|
import { createNoOpChatDevtoolsBridge } from "./devtools-noop.js";
|
|
3
|
+
import { normalizeMessagesDates } from "./message-date-normalizer.js";
|
|
3
4
|
import { fetcherToConnectionAdapter, getChunkRunId as getChunkRunId$1, normalizeConnectionAdapter } from "./connection-adapters.js";
|
|
4
5
|
import { ChatPersistor } from "./client-persistor.js";
|
|
5
6
|
import { ClearedStreamTracker } from "./cleared-stream-tracker.js";
|
|
@@ -205,6 +206,8 @@ var ChatClient = class {
|
|
|
205
206
|
processingResolve = null;
|
|
206
207
|
errorReportedGeneration = null;
|
|
207
208
|
streamGeneration = 0;
|
|
209
|
+
continuationGeneration = 0;
|
|
210
|
+
streamContinuationGeneration = 0;
|
|
208
211
|
continuationSkipped = false;
|
|
209
212
|
draining = false;
|
|
210
213
|
sessionGenerating = false;
|
|
@@ -333,6 +336,7 @@ var ChatClient = class {
|
|
|
333
336
|
const clientTool = (this.activeClientTools ?? this.clientToolsRef.current).get(args.toolName);
|
|
334
337
|
const executeFunc = clientTool?.execute;
|
|
335
338
|
if (executeFunc) {
|
|
339
|
+
const continuationGeneration = this.continuationGeneration;
|
|
336
340
|
const runEventContext = this.devtoolsBridge.getCurrentRunEventContext();
|
|
337
341
|
const executionPromise = (async () => {
|
|
338
342
|
try {
|
|
@@ -347,7 +351,7 @@ var ChatClient = class {
|
|
|
347
351
|
tool: args.toolName,
|
|
348
352
|
output,
|
|
349
353
|
state: "output-available"
|
|
350
|
-
}, clientTool, runEventContext);
|
|
354
|
+
}, clientTool, continuationGeneration, runEventContext);
|
|
351
355
|
} catch (error) {
|
|
352
356
|
await this.addToolResultForClientTool({
|
|
353
357
|
toolCallId: args.toolCallId,
|
|
@@ -355,7 +359,7 @@ var ChatClient = class {
|
|
|
355
359
|
output: null,
|
|
356
360
|
state: "output-error",
|
|
357
361
|
errorText: error.message
|
|
358
|
-
}, clientTool, runEventContext);
|
|
362
|
+
}, clientTool, continuationGeneration, runEventContext);
|
|
359
363
|
} finally {
|
|
360
364
|
this.pendingToolExecutions.delete(args.toolCallId);
|
|
361
365
|
}
|
|
@@ -491,7 +495,7 @@ var ChatClient = class {
|
|
|
491
495
|
}
|
|
492
496
|
if (this.disposed || !this.tailing) return;
|
|
493
497
|
if (this.isLoading || this.abortController) return;
|
|
494
|
-
if (result.messages.length > 0) this.processor.setMessages(result.messages);
|
|
498
|
+
if (result.messages.length > 0) this.processor.setMessages(normalizeMessagesDates(result.messages));
|
|
495
499
|
if (result.interrupts && result.interrupts.pending.length > 0) this.applyResumeSnapshot({
|
|
496
500
|
resumeState: {
|
|
497
501
|
threadId: this.threadId,
|
|
@@ -649,10 +653,14 @@ var ChatClient = class {
|
|
|
649
653
|
resumeInterruptsUnsafe(resume, state) {
|
|
650
654
|
const target = state ?? this.lastResume;
|
|
651
655
|
if (!target) return Promise.resolve(false);
|
|
656
|
+
return this.resumeInterruptsUnsafeForGeneration(resume, target, this.continuationGeneration);
|
|
657
|
+
}
|
|
658
|
+
resumeInterruptsUnsafeForGeneration(resume, target, continuationGeneration) {
|
|
659
|
+
if (continuationGeneration !== this.continuationGeneration) return Promise.resolve(false);
|
|
652
660
|
if (this.isLoading) return new Promise((resolve, reject) => {
|
|
653
661
|
this.queuePostStreamAction(async () => {
|
|
654
662
|
try {
|
|
655
|
-
resolve(await this.
|
|
663
|
+
resolve(await this.resumeInterruptsUnsafeForGeneration(resume, target, continuationGeneration));
|
|
656
664
|
} catch (error) {
|
|
657
665
|
reject(error);
|
|
658
666
|
}
|
|
@@ -668,6 +676,7 @@ var ChatClient = class {
|
|
|
668
676
|
return this.resumeInterruptsUnsafe(resume, state);
|
|
669
677
|
}
|
|
670
678
|
async submitInterruptBatch(submission) {
|
|
679
|
+
const continuationGeneration = this.continuationGeneration;
|
|
671
680
|
this.activeInterruptSubmission = submission;
|
|
672
681
|
this.interruptSubmissionFailure = void 0;
|
|
673
682
|
for (const resolution of submission.resolutions) {
|
|
@@ -676,12 +685,13 @@ var ChatClient = class {
|
|
|
676
685
|
const approvalId = resolution.interruptId;
|
|
677
686
|
this.processor.addToolApprovalResponse(approvalId, approved);
|
|
678
687
|
}
|
|
679
|
-
const resumed = await this.
|
|
688
|
+
const resumed = await this.resumeInterruptsUnsafeForGeneration([...submission.resolutions], {
|
|
680
689
|
threadId: submission.threadId,
|
|
681
690
|
runId: submission.interruptedRunId
|
|
682
|
-
}).finally(() => {
|
|
683
|
-
this.activeInterruptSubmission = void 0;
|
|
691
|
+
}, continuationGeneration).finally(() => {
|
|
692
|
+
if (this.activeInterruptSubmission === submission) this.activeInterruptSubmission = void 0;
|
|
684
693
|
});
|
|
694
|
+
if (continuationGeneration !== this.continuationGeneration) return;
|
|
685
695
|
const failure = this.takeInterruptSubmissionFailure();
|
|
686
696
|
if (failure !== void 0) throw { errors: failure.errors };
|
|
687
697
|
if (!resumed) throw new Error("Interrupt continuation could not be started.");
|
|
@@ -906,6 +916,7 @@ var ChatClient = class {
|
|
|
906
916
|
threadId: this.threadId,
|
|
907
917
|
runId
|
|
908
918
|
};
|
|
919
|
+
this.streamContinuationGeneration = this.continuationGeneration;
|
|
909
920
|
this.setIsLoading(true);
|
|
910
921
|
this.setStatus("streaming");
|
|
911
922
|
(async () => {
|
|
@@ -1224,6 +1235,7 @@ var ChatClient = class {
|
|
|
1224
1235
|
async streamResponse() {
|
|
1225
1236
|
if (this.isLoading) return false;
|
|
1226
1237
|
const generation = ++this.streamGeneration;
|
|
1238
|
+
this.streamContinuationGeneration = this.continuationGeneration;
|
|
1227
1239
|
const resumeThreadId = this.pendingResumeThreadId;
|
|
1228
1240
|
const resumeParentRunId = this.pendingResumeParentRunId;
|
|
1229
1241
|
const resumeItems = this.pendingResumeItems;
|
|
@@ -1390,9 +1402,13 @@ var ChatClient = class {
|
|
|
1390
1402
|
* Stop the current stream
|
|
1391
1403
|
*/
|
|
1392
1404
|
stop() {
|
|
1405
|
+
this.continuationGeneration++;
|
|
1393
1406
|
const hadLocalStream = this.abortController !== null;
|
|
1394
1407
|
this.cancelInFlightStream({ setReadyStatus: true });
|
|
1395
1408
|
this.discardPendingSends();
|
|
1409
|
+
this.lastResume = null;
|
|
1410
|
+
this.activeInterruptSubmission = void 0;
|
|
1411
|
+
this.interruptManager.reset();
|
|
1396
1412
|
if (hadLocalStream) this.resetSessionGenerating();
|
|
1397
1413
|
this.events.stopped();
|
|
1398
1414
|
}
|
|
@@ -1427,9 +1443,9 @@ var ChatClient = class {
|
|
|
1427
1443
|
*/
|
|
1428
1444
|
async addToolResult(result) {
|
|
1429
1445
|
const clientTool = this.clientToolsRef.current.get(result.tool);
|
|
1430
|
-
await this.addToolResultForClientTool(result, clientTool);
|
|
1446
|
+
await this.addToolResultForClientTool(result, clientTool, this.streamContinuationGeneration);
|
|
1431
1447
|
}
|
|
1432
|
-
async addToolResultForClientTool(result, clientTool, context) {
|
|
1448
|
+
async addToolResultForClientTool(result, clientTool, continuationGeneration, context) {
|
|
1433
1449
|
if (clientTool && result.state !== "output-error") try {
|
|
1434
1450
|
result = {
|
|
1435
1451
|
...result,
|
|
@@ -1444,11 +1460,12 @@ var ChatClient = class {
|
|
|
1444
1460
|
};
|
|
1445
1461
|
}
|
|
1446
1462
|
this.events.toolResultAdded(result.toolCallId, result.tool, result.output, result.state || "output-available", context);
|
|
1463
|
+
if (continuationGeneration !== this.continuationGeneration) return;
|
|
1447
1464
|
this.processor.addToolResult(result.toolCallId, result.output, result.state === "output-error" ? result.errorText || "Tool execution failed" : void 0);
|
|
1448
1465
|
this.devtoolsBridge.emitSnapshot();
|
|
1449
1466
|
if (this.interruptManager.resolveClientToolOutput(result.toolCallId, result.state === "output-error" ? { error: result.errorText || "Tool execution failed" } : result.output)) return;
|
|
1450
1467
|
if (this.isLoading) {
|
|
1451
|
-
this.queuePostStreamAction(() => this.checkForContinuation());
|
|
1468
|
+
this.queuePostStreamAction(() => continuationGeneration === this.continuationGeneration ? this.checkForContinuation() : Promise.resolve());
|
|
1452
1469
|
return;
|
|
1453
1470
|
}
|
|
1454
1471
|
await this.checkForContinuation();
|
|
@@ -1486,7 +1503,11 @@ var ChatClient = class {
|
|
|
1486
1503
|
* Queue an action to be executed after the current stream ends
|
|
1487
1504
|
*/
|
|
1488
1505
|
queuePostStreamAction(action) {
|
|
1489
|
-
this.
|
|
1506
|
+
const continuationGeneration = this.continuationGeneration;
|
|
1507
|
+
this.postStreamActions.push(async () => {
|
|
1508
|
+
if (continuationGeneration !== this.continuationGeneration) return;
|
|
1509
|
+
await action();
|
|
1510
|
+
});
|
|
1490
1511
|
}
|
|
1491
1512
|
/**
|
|
1492
1513
|
* Drain and execute all queued post-stream actions
|
|
@@ -1505,6 +1526,7 @@ var ChatClient = class {
|
|
|
1505
1526
|
* Check if we should continue the flow and do so if needed
|
|
1506
1527
|
*/
|
|
1507
1528
|
async checkForContinuation() {
|
|
1529
|
+
if (this.streamContinuationGeneration !== this.continuationGeneration) return;
|
|
1508
1530
|
if (this.hasPendingInterrupts()) return;
|
|
1509
1531
|
if (this.continuationPending || this.isLoading) {
|
|
1510
1532
|
this.continuationSkipped = true;
|