@tanstack/ai-client 0.26.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.
Files changed (56) hide show
  1. package/dist/esm/byok/client.d.ts +52 -0
  2. package/dist/esm/byok/client.js +300 -0
  3. package/dist/esm/byok/client.js.map +1 -0
  4. package/dist/esm/byok/passkey.d.ts +43 -0
  5. package/dist/esm/byok/passkey.js +251 -0
  6. package/dist/esm/byok/passkey.js.map +1 -0
  7. package/dist/esm/byok/resolve.d.ts +8 -0
  8. package/dist/esm/byok/resolve.js +20 -0
  9. package/dist/esm/byok/resolve.js.map +1 -0
  10. package/dist/esm/byok/storage.d.ts +15 -0
  11. package/dist/esm/byok/storage.js +16 -0
  12. package/dist/esm/byok/storage.js.map +1 -0
  13. package/dist/esm/byok.d.ts +8 -0
  14. package/dist/esm/byok.js +5 -0
  15. package/dist/esm/chat-client.d.ts +19 -3
  16. package/dist/esm/chat-client.js +82 -42
  17. package/dist/esm/chat-client.js.map +1 -1
  18. package/dist/esm/connection-adapters.d.ts +2 -0
  19. package/dist/esm/connection-adapters.js +35 -10
  20. package/dist/esm/connection-adapters.js.map +1 -1
  21. package/dist/esm/generation-client.d.ts +3 -1
  22. package/dist/esm/generation-client.js +23 -4
  23. package/dist/esm/generation-client.js.map +1 -1
  24. package/dist/esm/generation-types.d.ts +14 -0
  25. package/dist/esm/generation-types.js.map +1 -1
  26. package/dist/esm/interrupt-manager.d.ts +1 -0
  27. package/dist/esm/interrupt-manager.js +15 -6
  28. package/dist/esm/interrupt-manager.js.map +1 -1
  29. package/dist/esm/message-date-normalizer.d.ts +3 -0
  30. package/dist/esm/message-date-normalizer.js +35 -0
  31. package/dist/esm/message-date-normalizer.js.map +1 -0
  32. package/dist/esm/sse-parser.js +8 -1
  33. package/dist/esm/sse-parser.js.map +1 -1
  34. package/dist/esm/storage-adapters.js +13 -1
  35. package/dist/esm/storage-adapters.js.map +1 -1
  36. package/dist/esm/types.d.ts +34 -3
  37. package/dist/esm/types.js.map +1 -1
  38. package/dist/esm/video-generation-client.d.ts +3 -1
  39. package/dist/esm/video-generation-client.js +25 -6
  40. package/dist/esm/video-generation-client.js.map +1 -1
  41. package/package.json +7 -3
  42. package/src/byok/client.ts +360 -0
  43. package/src/byok/passkey.ts +399 -0
  44. package/src/byok/resolve.ts +30 -0
  45. package/src/byok/storage.ts +29 -0
  46. package/src/byok.ts +20 -0
  47. package/src/chat-client.ts +165 -72
  48. package/src/connection-adapters.ts +46 -14
  49. package/src/generation-client.ts +48 -4
  50. package/src/generation-types.ts +16 -0
  51. package/src/interrupt-manager.ts +20 -6
  52. package/src/message-date-normalizer.ts +29 -0
  53. package/src/sse-parser.ts +10 -0
  54. package/src/storage-adapters.ts +13 -2
  55. package/src/types.ts +36 -3
  56. package/src/video-generation-client.ts +45 -4
@@ -94,6 +94,8 @@ export interface RunAgentInputContext {
94
94
  }>;
95
95
  /** Arbitrary user-controlled passthrough data. */
96
96
  forwardedProps?: Record<string, unknown>;
97
+ /** Extra request headers for this run (e.g. BYOK keys). POST only. */
98
+ headers?: Record<string, string>;
97
99
  }
98
100
  export interface ConnectConnectionAdapter {
99
101
  /**
@@ -1,6 +1,8 @@
1
1
  import { createResponseStreamTextDecoder, getResponseStreamReader } from "./response-stream.js";
2
2
  import { parseSseDataLine } from "./sse-utils.js";
3
+ import { normalizeMessagesDates } from "./message-date-normalizer.js";
3
4
  import { EventType, getChunkRunId, restoreInboundChunk, tanstackMetadata, uiMessagesToWire, withTanstackMetadata } from "@tanstack/ai/client";
5
+ import { ByokMissingError, isByokMissingBody } from "@tanstack/ai/byok";
4
6
  //#region src/connection-adapters.ts
5
7
  /**
6
8
  * Associates connect-wrapped chunks with the run they were produced under.
@@ -287,8 +289,25 @@ async function* linesToNdjsonEvents(lines) {
287
289
  else yield { chunk: restoreInboundUsage(parsed) };
288
290
  }
289
291
  }
290
- function assertResponseOk(response) {
291
- if (!response.ok) throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
292
+ async function assertResponseOk(response) {
293
+ if (response.ok) return;
294
+ if (response.status === 401) {
295
+ const body = await response.clone().json().catch(() => null);
296
+ if (isByokMissingBody(body)) throw new ByokMissingError(body.error.provider);
297
+ }
298
+ throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
299
+ }
300
+ function errorFromXhrStatus(xhr) {
301
+ if (xhr.status === 401) {
302
+ let parsed = null;
303
+ try {
304
+ parsed = JSON.parse(xhr.responseText);
305
+ } catch {
306
+ parsed = null;
307
+ }
308
+ if (isByokMissingBody(parsed)) return new ByokMissingError(parsed.error.provider);
309
+ }
310
+ return /* @__PURE__ */ new Error(`XHR error! status: ${xhr.status} ${xhr.statusText}`);
292
311
  }
293
312
  /**
294
313
  * GET the hydration endpoint for a thread and parse its JSON `{ messages,
@@ -306,7 +325,7 @@ async function fetchThreadHydration(fetchClient, url, headers, credentials, thre
306
325
  },
307
326
  credentials
308
327
  });
309
- assertResponseOk(response);
328
+ await assertResponseOk(response);
310
329
  const data = await response.json();
311
330
  const activeRun = data.activeRun && typeof data.activeRun.runId === "string" ? { runId: data.activeRun.runId } : null;
312
331
  const interrupts = data.interrupts && typeof data.interrupts.runId === "string" && Array.isArray(data.interrupts.pending) && data.interrupts.pending.length > 0 ? {
@@ -314,7 +333,7 @@ async function fetchThreadHydration(fetchClient, url, headers, credentials, thre
314
333
  pending: data.interrupts.pending
315
334
  } : null;
316
335
  return {
317
- messages: Array.isArray(data.messages) ? data.messages : [],
336
+ messages: Array.isArray(data.messages) ? normalizeMessagesDates(data.messages) : [],
318
337
  activeRun,
319
338
  interrupts
320
339
  };
@@ -335,7 +354,7 @@ async function fetchGenerationHydration(fetchClient, url, headers, credentials,
335
354
  },
336
355
  credentials
337
356
  });
338
- assertResponseOk(response);
357
+ await assertResponseOk(response);
339
358
  const raw = await response.json();
340
359
  if (raw === null) return {
341
360
  resumeSnapshot: null,
@@ -351,12 +370,12 @@ async function fetchGenerationHydration(fetchClient, url, headers, credentials,
351
370
  }
352
371
  /** Yield SSE stream events (chunk + offset) from a fetch Response body. */
353
372
  async function* responseToSSEEvents(response, abortSignal, fallbackIds) {
354
- assertResponseOk(response);
373
+ await assertResponseOk(response);
355
374
  yield* linesToSSEEvents(readStreamLines(getResponseStreamReader(response), abortSignal), fallbackIds);
356
375
  }
357
376
  /** Yield NDJSON stream events (chunk + offset) from a fetch Response body. */
358
377
  async function* responseToNdjsonEvents(response, abortSignal) {
359
- assertResponseOk(response);
378
+ await assertResponseOk(response);
360
379
  yield* linesToNdjsonEvents(readStreamLines(getResponseStreamReader(response), abortSignal));
361
380
  }
362
381
  async function* responseToSSEChunks(response, abortSignal) {
@@ -588,6 +607,7 @@ function fetchServerSentEvents(url, options = {}) {
588
607
  const requestHeaders = {
589
608
  "Content-Type": "application/json",
590
609
  ...mergeHeaders(resolvedOptions.headers),
610
+ ...mergeHeaders(runContext?.headers),
591
611
  ...runIdHeader(runContext?.runId)
592
612
  };
593
613
  const requestBody = buildRunAgentInputBody(messages, data, runContext, resolvedOptions);
@@ -673,6 +693,7 @@ function fetchHttpStream(url, options = {}) {
673
693
  const requestHeaders = {
674
694
  "Content-Type": "application/json",
675
695
  ...mergeHeaders(resolvedOptions.headers),
696
+ ...mergeHeaders(runContext?.headers),
676
697
  ...runIdHeader(runContext?.runId)
677
698
  };
678
699
  const requestBody = buildRunAgentInputBody(messages, data, runContext, resolvedOptions);
@@ -739,7 +760,7 @@ function readXhrLines(xhr, abortSignal) {
739
760
  };
740
761
  const enqueueDelta = () => {
741
762
  if (xhr.status !== 0 && (xhr.status < 200 || xhr.status >= 300)) {
742
- error = /* @__PURE__ */ new Error(`XHR error! status: ${xhr.status} ${xhr.statusText}`);
763
+ error = errorFromXhrStatus(xhr);
743
764
  done = true;
744
765
  return;
745
766
  }
@@ -756,7 +777,7 @@ function readXhrLines(xhr, abortSignal) {
756
777
  };
757
778
  const finish = () => {
758
779
  enqueueDelta();
759
- if (xhr.status !== 0 && (xhr.status < 200 || xhr.status >= 300)) error = /* @__PURE__ */ new Error(`XHR error! status: ${xhr.status} ${xhr.statusText}`);
780
+ if (xhr.status !== 0 && (xhr.status < 200 || xhr.status >= 300)) error = errorFromXhrStatus(xhr);
760
781
  else if (buffer.trim() && !aborted) error = new StreamTruncatedError();
761
782
  done = true;
762
783
  wake();
@@ -813,6 +834,7 @@ function createConfiguredXhrRequest(url, options, messages, data, runContext, me
813
834
  const requestHeaders = {
814
835
  "Content-Type": "application/json",
815
836
  ...mergeHeaders(options.headers),
837
+ ...mergeHeaders(method === "POST" ? runContext?.headers : void 0),
816
838
  ...method === "POST" ? runIdHeader(runContext?.runId) : {},
817
839
  ...extraHeaders
818
840
  };
@@ -1211,7 +1233,10 @@ function fetcherToConnectionAdapter(fetcher) {
1211
1233
  runId: runContext.runId,
1212
1234
  ...runContext.parentRunId !== void 0 ? { parentRunId: runContext.parentRunId } : {},
1213
1235
  ...runContext.resume !== void 0 ? { resume: runContext.resume } : {}
1214
- }, { signal: abortSignal });
1236
+ }, {
1237
+ signal: abortSignal,
1238
+ headers: runContext.headers
1239
+ });
1215
1240
  if (result instanceof Response) yield* responseToSSEChunks(result, abortSignal);
1216
1241
  else yield* abortableIterable(result, abortSignal);
1217
1242
  } };