@tanstack/ai-client 0.29.0 → 0.29.1
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 +6 -0
- package/dist/esm/chat-client.js +27 -4
- package/dist/esm/chat-client.js.map +1 -1
- package/dist/esm/connection-adapters.js +15 -0
- package/dist/esm/connection-adapters.js.map +1 -1
- package/dist/esm/devtools-noop.d.ts +1 -0
- package/dist/esm/devtools-noop.js +1 -0
- package/dist/esm/devtools-noop.js.map +1 -1
- package/dist/esm/devtools.d.ts +5 -1
- package/dist/esm/devtools.js +54 -10
- package/dist/esm/devtools.js.map +1 -1
- package/package.json +3 -3
- package/src/chat-client.ts +43 -8
- package/src/connection-adapters.ts +23 -0
- package/src/devtools-noop.ts +1 -0
- package/src/devtools.ts +98 -12
|
@@ -123,6 +123,12 @@ export declare class ChatClient<TTools extends ReadonlyArray<AnyClientTool> = an
|
|
|
123
123
|
private continuationPending;
|
|
124
124
|
private subscriptionAbortController;
|
|
125
125
|
private processingResolve;
|
|
126
|
+
/**
|
|
127
|
+
* `connect()` adapters push the full HTTP body into the subscribe queue, then
|
|
128
|
+
* wait until that queue is idle. After `send()` returns, every chunk from this
|
|
129
|
+
* request has been processed. Subscribe/send sockets do not drain that way.
|
|
130
|
+
*/
|
|
131
|
+
private connectionDrainsOnSend;
|
|
126
132
|
private errorReportedGeneration;
|
|
127
133
|
private streamGeneration;
|
|
128
134
|
private continuationGeneration;
|
package/dist/esm/chat-client.js
CHANGED
|
@@ -22,6 +22,16 @@ function resolveTransport(transport) {
|
|
|
22
22
|
if (fetcher) return fetcherToConnectionAdapter(fetcher);
|
|
23
23
|
throw new Error("ChatClient: either `connection` or `fetcher` is required.");
|
|
24
24
|
}
|
|
25
|
+
function connectionDrainsOnSend(connection) {
|
|
26
|
+
return "connect" in connection;
|
|
27
|
+
}
|
|
28
|
+
function isIntermediateToolTurn(chunk) {
|
|
29
|
+
if (chunk.type !== "RUN_FINISHED") return false;
|
|
30
|
+
if (chunk.outcome?.type === "interrupt") return false;
|
|
31
|
+
const extra = chunk;
|
|
32
|
+
if (extra.finishReason !== void 0) return extra.finishReason === "tool_calls";
|
|
33
|
+
return tanstackMetadata(chunk)?.finishReason === "tool_calls";
|
|
34
|
+
}
|
|
25
35
|
function normalizeQueueOption(option) {
|
|
26
36
|
const base = {
|
|
27
37
|
whenBusy: "queue",
|
|
@@ -204,6 +214,12 @@ var ChatClient = class {
|
|
|
204
214
|
continuationPending = false;
|
|
205
215
|
subscriptionAbortController = null;
|
|
206
216
|
processingResolve = null;
|
|
217
|
+
/**
|
|
218
|
+
* `connect()` adapters push the full HTTP body into the subscribe queue, then
|
|
219
|
+
* wait until that queue is idle. After `send()` returns, every chunk from this
|
|
220
|
+
* request has been processed. Subscribe/send sockets do not drain that way.
|
|
221
|
+
*/
|
|
222
|
+
connectionDrainsOnSend = false;
|
|
207
223
|
errorReportedGeneration = null;
|
|
208
224
|
streamGeneration = 0;
|
|
209
225
|
continuationGeneration = 0;
|
|
@@ -239,7 +255,9 @@ var ChatClient = class {
|
|
|
239
255
|
this.byokProvider = options.byokProvider;
|
|
240
256
|
this.context = options.context;
|
|
241
257
|
this.queueConfig = normalizeQueueOption(options.queue);
|
|
242
|
-
|
|
258
|
+
const transport = resolveTransport(options);
|
|
259
|
+
this.connectionDrainsOnSend = connectionDrainsOnSend(transport);
|
|
260
|
+
this.connection = normalizeConnectionAdapter(transport);
|
|
243
261
|
this.clientToolsRef = { current: /* @__PURE__ */ new Map() };
|
|
244
262
|
if (options.tools) for (const tool of options.tools) this.clientToolsRef.current.set(tool.name, tool);
|
|
245
263
|
this.devtoolsBridge = (options.devtoolsBridgeFactory ?? createNoOpChatDevtoolsBridge)(this.buildDevtoolsBridgeOptions(options.devtools));
|
|
@@ -374,6 +392,7 @@ var ChatClient = class {
|
|
|
374
392
|
},
|
|
375
393
|
onCustomEvent: (eventType, data, context) => {
|
|
376
394
|
if (eventType === "memory:state") this.devtoolsBridge.recordMemoryState(data);
|
|
395
|
+
if (eventType === "skills:state") this.devtoolsBridge.recordSkillsState(data);
|
|
377
396
|
this.callbacksRef.current.onCustomEvent(eventType, data, context);
|
|
378
397
|
}
|
|
379
398
|
}
|
|
@@ -562,7 +581,8 @@ var ChatClient = class {
|
|
|
562
581
|
this.clearedStreamTracker.onSessionRunError();
|
|
563
582
|
}
|
|
564
583
|
this.setSessionGenerating(this.activeRunIds.size > 0);
|
|
565
|
-
|
|
584
|
+
const skipProcessingResolve = chunk.type === "RUN_FINISHED" && isIntermediateToolTurn(chunk);
|
|
585
|
+
if (options?.resolveProcessing !== false && !skipProcessingResolve) this.resolveProcessing();
|
|
566
586
|
}
|
|
567
587
|
/**
|
|
568
588
|
* Track interrupt state off the stream's terminal events. A RUN_FINISHED with
|
|
@@ -1302,6 +1322,7 @@ var ChatClient = class {
|
|
|
1302
1322
|
this.devtoolsBridge.emitSnapshot();
|
|
1303
1323
|
await this.connection.send(messages, mergedBody, signal, runContext);
|
|
1304
1324
|
if (generation !== this.streamGeneration || signal.aborted) return false;
|
|
1325
|
+
if (this.connectionDrainsOnSend) this.resolveProcessing();
|
|
1305
1326
|
await processingComplete;
|
|
1306
1327
|
if (generation !== this.streamGeneration) return false;
|
|
1307
1328
|
if (this.status === "error") {
|
|
@@ -1710,10 +1731,12 @@ var ChatClient = class {
|
|
|
1710
1731
|
this.resetSessionGenerating();
|
|
1711
1732
|
this.setIsSubscribed(false);
|
|
1712
1733
|
this.setConnectionStatus("disconnected");
|
|
1713
|
-
|
|
1734
|
+
const transport = resolveTransport({
|
|
1714
1735
|
connection: options.connection,
|
|
1715
1736
|
fetcher: options.fetcher
|
|
1716
|
-
})
|
|
1737
|
+
});
|
|
1738
|
+
this.connectionDrainsOnSend = connectionDrainsOnSend(transport);
|
|
1739
|
+
this.connection = normalizeConnectionAdapter(transport);
|
|
1717
1740
|
if (wasSubscribed) this.subscribe();
|
|
1718
1741
|
}
|
|
1719
1742
|
if (options.body !== void 0) this.bodyOption = options.body;
|