@absolutejs/voice 0.0.22-beta.559 → 0.0.22-beta.560

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/index.js CHANGED
@@ -45089,13 +45089,15 @@ var parseToolArgs = (raw) => {
45089
45089
  return {};
45090
45090
  }
45091
45091
  };
45092
- var readServerSentEvents = async (response, onEvent) => {
45092
+ var readServerSentEvents = async (response, onEvent, abortOptions) => {
45093
45093
  const reader = response.body?.getReader();
45094
45094
  if (!reader) {
45095
45095
  throw new Error("streaming response has no body");
45096
45096
  }
45097
45097
  const decoder = new TextDecoder;
45098
45098
  let buffer = "";
45099
+ const signal = abortOptions?.signal;
45100
+ const inactivityMs = abortOptions?.inactivityMs ?? 1e4;
45099
45101
  const drain = (block) => {
45100
45102
  for (const line of block.split(`
45101
45103
  `)) {
@@ -45110,8 +45112,37 @@ var readServerSentEvents = async (response, onEvent) => {
45110
45112
  } catch {}
45111
45113
  }
45112
45114
  };
45115
+ const readWithRace = async () => {
45116
+ if (signal?.aborted) {
45117
+ try {
45118
+ await reader.cancel();
45119
+ } catch {}
45120
+ throw new Error("SSE read aborted by signal");
45121
+ }
45122
+ let inactivityTimer = null;
45123
+ let onAbort = null;
45124
+ return new Promise((resolve2, reject) => {
45125
+ inactivityTimer = setTimeout(() => {
45126
+ reader.cancel().catch(() => {});
45127
+ reject(new Error(`SSE read inactivity timeout (${inactivityMs}ms with no chunk)`));
45128
+ }, inactivityMs);
45129
+ if (signal) {
45130
+ onAbort = () => {
45131
+ reader.cancel().catch(() => {});
45132
+ reject(new Error("SSE read aborted by signal"));
45133
+ };
45134
+ signal.addEventListener("abort", onAbort);
45135
+ }
45136
+ reader.read().then((result) => resolve2(result), (err) => reject(err));
45137
+ }).finally(() => {
45138
+ if (inactivityTimer)
45139
+ clearTimeout(inactivityTimer);
45140
+ if (signal && onAbort)
45141
+ signal.removeEventListener("abort", onAbort);
45142
+ });
45143
+ };
45113
45144
  for (;; ) {
45114
- const { done, value } = await reader.read();
45145
+ const { done, value } = await readWithRace();
45115
45146
  if (done)
45116
45147
  break;
45117
45148
  buffer += decoder.decode(value, { stream: true });
@@ -45134,7 +45165,7 @@ var finalizeToolCalls = (calls) => [...calls.values()].filter((call) => call.nam
45134
45165
  id: call.id,
45135
45166
  name: call.name
45136
45167
  }));
45137
- var consumeOpenAIResponsesStream = async (response, onTextDelta) => {
45168
+ var consumeOpenAIResponsesStream = async (response, onTextDelta, abortOptions) => {
45138
45169
  let assistantText = "";
45139
45170
  let usage;
45140
45171
  const calls = new Map;
@@ -45164,7 +45195,7 @@ var consumeOpenAIResponsesStream = async (response, onTextDelta) => {
45164
45195
  usage = completed.usage;
45165
45196
  }
45166
45197
  }
45167
- });
45198
+ }, abortOptions);
45168
45199
  return { assistantText, toolCalls: finalizeToolCalls(calls), usage };
45169
45200
  };
45170
45201
  var createOpenAIVoiceAssistantModel = (options) => {
@@ -45222,7 +45253,10 @@ var createOpenAIVoiceAssistantModel = (options) => {
45222
45253
  let toolCalls;
45223
45254
  let usage;
45224
45255
  try {
45225
- ({ assistantText, toolCalls, usage } = await consumeOpenAIResponsesStream(response, input.onTextDelta));
45256
+ ({ assistantText, toolCalls, usage } = await consumeOpenAIResponsesStream(response, input.onTextDelta, {
45257
+ signal: ac.signal,
45258
+ inactivityMs: 1e4
45259
+ }));
45226
45260
  } finally {
45227
45261
  clearTimeout(timer);
45228
45262
  }
@@ -4518,13 +4518,15 @@ var parseToolArgs = (raw) => {
4518
4518
  return {};
4519
4519
  }
4520
4520
  };
4521
- var readServerSentEvents = async (response, onEvent) => {
4521
+ var readServerSentEvents = async (response, onEvent, abortOptions) => {
4522
4522
  const reader = response.body?.getReader();
4523
4523
  if (!reader) {
4524
4524
  throw new Error("streaming response has no body");
4525
4525
  }
4526
4526
  const decoder = new TextDecoder;
4527
4527
  let buffer = "";
4528
+ const signal = abortOptions?.signal;
4529
+ const inactivityMs = abortOptions?.inactivityMs ?? 1e4;
4528
4530
  const drain = (block) => {
4529
4531
  for (const line of block.split(`
4530
4532
  `)) {
@@ -4539,8 +4541,37 @@ var readServerSentEvents = async (response, onEvent) => {
4539
4541
  } catch {}
4540
4542
  }
4541
4543
  };
4544
+ const readWithRace = async () => {
4545
+ if (signal?.aborted) {
4546
+ try {
4547
+ await reader.cancel();
4548
+ } catch {}
4549
+ throw new Error("SSE read aborted by signal");
4550
+ }
4551
+ let inactivityTimer = null;
4552
+ let onAbort = null;
4553
+ return new Promise((resolve2, reject) => {
4554
+ inactivityTimer = setTimeout(() => {
4555
+ reader.cancel().catch(() => {});
4556
+ reject(new Error(`SSE read inactivity timeout (${inactivityMs}ms with no chunk)`));
4557
+ }, inactivityMs);
4558
+ if (signal) {
4559
+ onAbort = () => {
4560
+ reader.cancel().catch(() => {});
4561
+ reject(new Error("SSE read aborted by signal"));
4562
+ };
4563
+ signal.addEventListener("abort", onAbort);
4564
+ }
4565
+ reader.read().then((result) => resolve2(result), (err) => reject(err));
4566
+ }).finally(() => {
4567
+ if (inactivityTimer)
4568
+ clearTimeout(inactivityTimer);
4569
+ if (signal && onAbort)
4570
+ signal.removeEventListener("abort", onAbort);
4571
+ });
4572
+ };
4542
4573
  for (;; ) {
4543
- const { done, value } = await reader.read();
4574
+ const { done, value } = await readWithRace();
4544
4575
  if (done)
4545
4576
  break;
4546
4577
  buffer += decoder.decode(value, { stream: true });
@@ -4563,7 +4594,7 @@ var finalizeToolCalls = (calls) => [...calls.values()].filter((call) => call.nam
4563
4594
  id: call.id,
4564
4595
  name: call.name
4565
4596
  }));
4566
- var consumeOpenAIResponsesStream = async (response, onTextDelta) => {
4597
+ var consumeOpenAIResponsesStream = async (response, onTextDelta, abortOptions) => {
4567
4598
  let assistantText = "";
4568
4599
  let usage;
4569
4600
  const calls = new Map;
@@ -4593,7 +4624,7 @@ var consumeOpenAIResponsesStream = async (response, onTextDelta) => {
4593
4624
  usage = completed.usage;
4594
4625
  }
4595
4626
  }
4596
- });
4627
+ }, abortOptions);
4597
4628
  return { assistantText, toolCalls: finalizeToolCalls(calls), usage };
4598
4629
  };
4599
4630
  var createOpenAIVoiceAssistantModel = (options) => {
@@ -4651,7 +4682,10 @@ var createOpenAIVoiceAssistantModel = (options) => {
4651
4682
  let toolCalls;
4652
4683
  let usage;
4653
4684
  try {
4654
- ({ assistantText, toolCalls, usage } = await consumeOpenAIResponsesStream(response, input.onTextDelta));
4685
+ ({ assistantText, toolCalls, usage } = await consumeOpenAIResponsesStream(response, input.onTextDelta, {
4686
+ signal: ac.signal,
4687
+ inactivityMs: 1e4
4688
+ }));
4655
4689
  } finally {
4656
4690
  clearTimeout(timer);
4657
4691
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.559",
3
+ "version": "0.0.22-beta.560",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",