@anuma/sdk 6.39.1 → 6.39.3

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.
@@ -21152,6 +21152,93 @@ function composeHooks(hooks) {
21152
21152
  };
21153
21153
  }
21154
21154
 
21155
+ // src/lib/chat/streamIdleTimeout.ts
21156
+ var StreamIdleTimeoutError = class extends Error {
21157
+ constructor(idleTimeoutMs) {
21158
+ super(`Stream timed out after ${idleTimeoutMs} ms without activity.`);
21159
+ this.name = "StreamIdleTimeoutError";
21160
+ this.idleTimeoutMs = idleTimeoutMs;
21161
+ }
21162
+ };
21163
+ function withStreamIdleTimeout(transport, idleTimeoutMs) {
21164
+ if (!(idleTimeoutMs > 0) || idleTimeoutMs === Infinity) return transport;
21165
+ return (options) => ({
21166
+ stream: (async function* () {
21167
+ const controller = new AbortController();
21168
+ let timer;
21169
+ let settled = false;
21170
+ let completed = false;
21171
+ let iterator;
21172
+ let interruption;
21173
+ let rejectPending;
21174
+ const disarm = () => {
21175
+ if (timer !== void 0) clearTimeout(timer);
21176
+ timer = void 0;
21177
+ };
21178
+ const interrupt = (error) => {
21179
+ if (interruption) return;
21180
+ interruption = error;
21181
+ rejectPending?.(error);
21182
+ controller.abort();
21183
+ };
21184
+ const arm = () => {
21185
+ if (settled || controller.signal.aborted) return;
21186
+ disarm();
21187
+ timer = setTimeout(() => {
21188
+ interrupt(new StreamIdleTimeoutError(idleTimeoutMs));
21189
+ }, idleTimeoutMs);
21190
+ };
21191
+ const onAbort = () => {
21192
+ controller.abort();
21193
+ };
21194
+ options.signal?.addEventListener("abort", onAbort, { once: true });
21195
+ try {
21196
+ if (options.signal?.aborted) {
21197
+ const error = new Error("Request aborted");
21198
+ error.name = "AbortError";
21199
+ throw error;
21200
+ }
21201
+ arm();
21202
+ iterator = transport({
21203
+ ...options,
21204
+ signal: controller.signal,
21205
+ onActivity: () => {
21206
+ arm();
21207
+ options.onActivity?.();
21208
+ }
21209
+ }).stream[Symbol.asyncIterator]();
21210
+ while (true) {
21211
+ if (interruption) throw interruption;
21212
+ const next = await new Promise((resolve, reject) => {
21213
+ rejectPending = reject;
21214
+ Promise.resolve(iterator.next()).then(resolve, reject);
21215
+ });
21216
+ rejectPending = void 0;
21217
+ if (next.done) {
21218
+ completed = true;
21219
+ break;
21220
+ }
21221
+ arm();
21222
+ yield next.value;
21223
+ }
21224
+ } finally {
21225
+ settled = true;
21226
+ rejectPending = void 0;
21227
+ disarm();
21228
+ options.signal?.removeEventListener("abort", onAbort);
21229
+ if (!completed) {
21230
+ controller.abort();
21231
+ try {
21232
+ void iterator?.return?.().catch(() => {
21233
+ });
21234
+ } catch {
21235
+ }
21236
+ }
21237
+ }
21238
+ })()
21239
+ });
21240
+ }
21241
+
21155
21242
  // src/lib/chat/useChat/utils.ts
21156
21243
  var import_jsonrepair = require("jsonrepair");
21157
21244
  init_logger();
@@ -23316,7 +23403,20 @@ var defaultTransport = (options) => {
23316
23403
  } catch {
23317
23404
  }
23318
23405
  }
23319
- return response;
23406
+ if (!response.body || !options.onActivity) return response;
23407
+ const body = response.body.pipeThrough(
23408
+ new TransformStream({
23409
+ transform(chunk, controller) {
23410
+ if (chunk.byteLength > 0) options.onActivity?.();
23411
+ controller.enqueue(chunk);
23412
+ }
23413
+ })
23414
+ );
23415
+ return new Response(body, {
23416
+ status: response.status,
23417
+ statusText: response.statusText,
23418
+ headers: response.headers
23419
+ });
23320
23420
  };
23321
23421
  return createSseClient({
23322
23422
  method: options.method ?? "POST",
@@ -23373,6 +23473,7 @@ async function runToolLoop(options) {
23373
23473
  conversationId,
23374
23474
  smoothing,
23375
23475
  signal,
23476
+ idleTimeoutMs = 12e4,
23376
23477
  resumable,
23377
23478
  detachSignal,
23378
23479
  onStreamMeta,
@@ -23386,13 +23487,14 @@ async function runToolLoop(options) {
23386
23487
  onStepFinish,
23387
23488
  onRequest,
23388
23489
  onStreamRetry,
23389
- transport: makeStreamingRequest = defaultTransport,
23490
+ transport = defaultTransport,
23390
23491
  preProcessors,
23391
23492
  maxConnectorCalls = 2,
23392
23493
  hooks: hooksOption,
23393
23494
  piiRedaction,
23394
23495
  onPiiRedacted
23395
23496
  } = options;
23497
+ const makeStreamingRequest = withStreamIdleTimeout(transport, idleTimeoutMs);
23396
23498
  const hooks = Array.isArray(hooksOption) ? composeHooks(hooksOption) : hooksOption;
23397
23499
  const runId = generateRunId();
23398
23500
  let messages = options.messages;
@@ -2041,6 +2041,12 @@ type RunToolLoopOptions = {
2041
2041
  smoothing?: StreamSmoothingConfig | boolean;
2042
2042
  /** AbortSignal to cancel the request. */
2043
2043
  signal?: AbortSignal;
2044
+ /**
2045
+ * Maximum interval without stream activity, in milliseconds, for each request attempt.
2046
+ * Data chunks and keep-alive bytes reset the interval. Set 0 or Infinity to disable.
2047
+ * @default 120000
2048
+ */
2049
+ idleTimeoutMs?: number;
2044
2050
  /**
2045
2051
  * Opt into resumable streaming. Sends `X-Stream-Resumable: 1` on every
2046
2052
  * streaming request so the portal keeps generating into its buffer after a
@@ -2275,12 +2281,10 @@ type StreamingTransportOptions = {
2275
2281
  inferenceId: string;
2276
2282
  }) => void;
2277
2283
  /**
2278
- * Fires whenever bytes arrive on the wire — data frames AND the keep-alive
2279
- * comment lines (`: ...`) the SSE parser otherwise discards. A pure liveness
2280
- * signal: a consumer running an idle watchdog uses it to tell a slow-but-alive
2281
- * stream (the server still heart-beating through a long reasoning silence)
2282
- * apart from a dead connection (no bytes at all). Not every transport emits it
2283
- * — the xhr transport does; treat its absence as "no extra liveness info".
2284
+ * Fires when the transport receives bytes, including SSE keep-alive comments.
2285
+ * Consumers can use this callback to reset the idle timeout.
2286
+ * The fetch and XHR transports emit it.
2287
+ * Custom transports can omit it if they cannot report byte activity.
2284
2288
  */
2285
2289
  onActivity?: () => void;
2286
2290
  };
@@ -2041,6 +2041,12 @@ type RunToolLoopOptions = {
2041
2041
  smoothing?: StreamSmoothingConfig | boolean;
2042
2042
  /** AbortSignal to cancel the request. */
2043
2043
  signal?: AbortSignal;
2044
+ /**
2045
+ * Maximum interval without stream activity, in milliseconds, for each request attempt.
2046
+ * Data chunks and keep-alive bytes reset the interval. Set 0 or Infinity to disable.
2047
+ * @default 120000
2048
+ */
2049
+ idleTimeoutMs?: number;
2044
2050
  /**
2045
2051
  * Opt into resumable streaming. Sends `X-Stream-Resumable: 1` on every
2046
2052
  * streaming request so the portal keeps generating into its buffer after a
@@ -2275,12 +2281,10 @@ type StreamingTransportOptions = {
2275
2281
  inferenceId: string;
2276
2282
  }) => void;
2277
2283
  /**
2278
- * Fires whenever bytes arrive on the wire — data frames AND the keep-alive
2279
- * comment lines (`: ...`) the SSE parser otherwise discards. A pure liveness
2280
- * signal: a consumer running an idle watchdog uses it to tell a slow-but-alive
2281
- * stream (the server still heart-beating through a long reasoning silence)
2282
- * apart from a dead connection (no bytes at all). Not every transport emits it
2283
- * — the xhr transport does; treat its absence as "no extra liveness info".
2284
+ * Fires when the transport receives bytes, including SSE keep-alive comments.
2285
+ * Consumers can use this callback to reset the idle timeout.
2286
+ * The fetch and XHR transports emit it.
2287
+ * Custom transports can omit it if they cannot report byte activity.
2284
2288
  */
2285
2289
  onActivity?: () => void;
2286
2290
  };
@@ -19482,6 +19482,93 @@ function composeHooks(hooks) {
19482
19482
  };
19483
19483
  }
19484
19484
 
19485
+ // src/lib/chat/streamIdleTimeout.ts
19486
+ var StreamIdleTimeoutError = class extends Error {
19487
+ constructor(idleTimeoutMs) {
19488
+ super(`Stream timed out after ${idleTimeoutMs} ms without activity.`);
19489
+ this.name = "StreamIdleTimeoutError";
19490
+ this.idleTimeoutMs = idleTimeoutMs;
19491
+ }
19492
+ };
19493
+ function withStreamIdleTimeout(transport, idleTimeoutMs) {
19494
+ if (!(idleTimeoutMs > 0) || idleTimeoutMs === Infinity) return transport;
19495
+ return (options) => ({
19496
+ stream: (async function* () {
19497
+ const controller = new AbortController();
19498
+ let timer;
19499
+ let settled = false;
19500
+ let completed = false;
19501
+ let iterator;
19502
+ let interruption;
19503
+ let rejectPending;
19504
+ const disarm = () => {
19505
+ if (timer !== void 0) clearTimeout(timer);
19506
+ timer = void 0;
19507
+ };
19508
+ const interrupt = (error) => {
19509
+ if (interruption) return;
19510
+ interruption = error;
19511
+ rejectPending?.(error);
19512
+ controller.abort();
19513
+ };
19514
+ const arm = () => {
19515
+ if (settled || controller.signal.aborted) return;
19516
+ disarm();
19517
+ timer = setTimeout(() => {
19518
+ interrupt(new StreamIdleTimeoutError(idleTimeoutMs));
19519
+ }, idleTimeoutMs);
19520
+ };
19521
+ const onAbort = () => {
19522
+ controller.abort();
19523
+ };
19524
+ options.signal?.addEventListener("abort", onAbort, { once: true });
19525
+ try {
19526
+ if (options.signal?.aborted) {
19527
+ const error = new Error("Request aborted");
19528
+ error.name = "AbortError";
19529
+ throw error;
19530
+ }
19531
+ arm();
19532
+ iterator = transport({
19533
+ ...options,
19534
+ signal: controller.signal,
19535
+ onActivity: () => {
19536
+ arm();
19537
+ options.onActivity?.();
19538
+ }
19539
+ }).stream[Symbol.asyncIterator]();
19540
+ while (true) {
19541
+ if (interruption) throw interruption;
19542
+ const next = await new Promise((resolve, reject) => {
19543
+ rejectPending = reject;
19544
+ Promise.resolve(iterator.next()).then(resolve, reject);
19545
+ });
19546
+ rejectPending = void 0;
19547
+ if (next.done) {
19548
+ completed = true;
19549
+ break;
19550
+ }
19551
+ arm();
19552
+ yield next.value;
19553
+ }
19554
+ } finally {
19555
+ settled = true;
19556
+ rejectPending = void 0;
19557
+ disarm();
19558
+ options.signal?.removeEventListener("abort", onAbort);
19559
+ if (!completed) {
19560
+ controller.abort();
19561
+ try {
19562
+ void iterator?.return?.().catch(() => {
19563
+ });
19564
+ } catch {
19565
+ }
19566
+ }
19567
+ }
19568
+ })()
19569
+ });
19570
+ }
19571
+
19485
19572
  // src/lib/chat/useChat/utils.ts
19486
19573
  import { jsonrepair } from "jsonrepair";
19487
19574
  function parseToolArguments(raw) {
@@ -21645,7 +21732,20 @@ var defaultTransport = (options) => {
21645
21732
  } catch {
21646
21733
  }
21647
21734
  }
21648
- return response;
21735
+ if (!response.body || !options.onActivity) return response;
21736
+ const body = response.body.pipeThrough(
21737
+ new TransformStream({
21738
+ transform(chunk, controller) {
21739
+ if (chunk.byteLength > 0) options.onActivity?.();
21740
+ controller.enqueue(chunk);
21741
+ }
21742
+ })
21743
+ );
21744
+ return new Response(body, {
21745
+ status: response.status,
21746
+ statusText: response.statusText,
21747
+ headers: response.headers
21748
+ });
21649
21749
  };
21650
21750
  return createSseClient({
21651
21751
  method: options.method ?? "POST",
@@ -21702,6 +21802,7 @@ async function runToolLoop(options) {
21702
21802
  conversationId,
21703
21803
  smoothing,
21704
21804
  signal,
21805
+ idleTimeoutMs = 12e4,
21705
21806
  resumable,
21706
21807
  detachSignal,
21707
21808
  onStreamMeta,
@@ -21715,13 +21816,14 @@ async function runToolLoop(options) {
21715
21816
  onStepFinish,
21716
21817
  onRequest,
21717
21818
  onStreamRetry,
21718
- transport: makeStreamingRequest = defaultTransport,
21819
+ transport = defaultTransport,
21719
21820
  preProcessors,
21720
21821
  maxConnectorCalls = 2,
21721
21822
  hooks: hooksOption,
21722
21823
  piiRedaction,
21723
21824
  onPiiRedacted
21724
21825
  } = options;
21826
+ const makeStreamingRequest = withStreamIdleTimeout(transport, idleTimeoutMs);
21725
21827
  const hooks = Array.isArray(hooksOption) ? composeHooks(hooksOption) : hooksOption;
21726
21828
  const runId = generateRunId();
21727
21829
  let messages = options.messages;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anuma/sdk",
3
- "version": "6.39.1",
3
+ "version": "6.39.3",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",