@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.
@@ -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;
@@ -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
- this.connection = normalizeConnectionAdapter(resolveTransport(options));
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
- if (options?.resolveProcessing !== false) this.resolveProcessing();
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
- this.connection = normalizeConnectionAdapter(resolveTransport({
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;