@absolutejs/voice 0.0.22-beta.583 → 0.0.22-beta.584

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.
@@ -0,0 +1,3 @@
1
+ export declare const hardenFetch: (baseFetch?: typeof fetch) => ((input: Parameters<typeof fetch>[0], init: Parameters<typeof fetch>[1]) => Promise<Response>) & {
2
+ preconnect: typeof fetch.preconnect;
3
+ };
package/dist/index.d.ts CHANGED
@@ -72,6 +72,7 @@ export { createVoiceAgent, createVoiceAgentSquad, createVoiceAgentTool, } from "
72
72
  export { createPersonaVoiceCaller, createScriptedVoiceCaller, renderVoiceSimulationTranscript, runVoiceConversationSimulation, } from "./core/conversationSimulator";
73
73
  export type { RunVoiceConversationSimulationInput, VoiceConversationSimulationEndedReason, VoiceConversationSimulationResult, VoicePersonaCallerCompletion, VoiceScriptedCallerStep, VoiceSimulatedSpeaker, VoiceSimulatedTurn, VoiceSimulatorCaller, VoiceSimulatorCallerModel, VoiceSimulatorCallerReply, } from "./core/conversationSimulator";
74
74
  export { logVoiceTiming, startVoiceTimer, voiceTimingEnabled, } from "./core/debugTiming";
75
+ export { hardenFetch } from "./core/hardenedFetch";
75
76
  export { createVoiceMCPToolset } from "./core/mcpToolset";
76
77
  export type { CreateVoiceMCPToolsetOptions, MCPClientLike, MCPToolCallResult, MCPToolContentBlock, MCPToolDefinition, VoiceMCPToolResult, } from "./core/mcpToolset";
77
78
  export { createAIVoiceModel } from "./core/aiVoiceModel";
package/dist/index.js CHANGED
@@ -40842,6 +40842,44 @@ Respond with only your spoken line. When your goal is met or you want to hang up
40842
40842
  persona: options.persona
40843
40843
  };
40844
40844
  };
40845
+ // src/core/hardenedFetch.ts
40846
+ var ATTEMPT_TIMEOUT_MS = 6000;
40847
+ var isBun = "Bun" in globalThis;
40848
+ var oneAttempt = async (baseFetch, input, init) => {
40849
+ const controller = new AbortController;
40850
+ const callerSignal = init?.signal ?? undefined;
40851
+ const onCallerAbort = () => controller.abort(callerSignal?.reason);
40852
+ if (callerSignal?.aborted)
40853
+ controller.abort(callerSignal.reason);
40854
+ else
40855
+ callerSignal?.addEventListener("abort", onCallerAbort, { once: true });
40856
+ const timer = setTimeout(() => {
40857
+ controller.abort(new Error(`fetch exceeded ${ATTEMPT_TIMEOUT_MS}ms before response headers (stale Bun keep-alive socket?)`));
40858
+ }, ATTEMPT_TIMEOUT_MS);
40859
+ const headers = new Headers(init?.headers);
40860
+ if (isBun)
40861
+ headers.set("Connection", "close");
40862
+ try {
40863
+ return await baseFetch(input, {
40864
+ ...init,
40865
+ headers,
40866
+ signal: controller.signal
40867
+ });
40868
+ } finally {
40869
+ clearTimeout(timer);
40870
+ callerSignal?.removeEventListener("abort", onCallerAbort);
40871
+ }
40872
+ };
40873
+ var hardenFetch = (baseFetch = globalThis.fetch) => Object.assign(async (input, init) => {
40874
+ try {
40875
+ return await oneAttempt(baseFetch, input, init);
40876
+ } catch (error) {
40877
+ if (init?.signal?.aborted)
40878
+ throw error;
40879
+ console.warn(`[voice] hardened fetch retrying on a fresh connection: ${error instanceof Error ? error.message : String(error)}`);
40880
+ return oneAttempt(baseFetch, input, init);
40881
+ }
40882
+ }, { preconnect: baseFetch.preconnect.bind(baseFetch) });
40845
40883
  // src/core/mcpToolset.ts
40846
40884
  var flattenContent = (result) => {
40847
40885
  const blocks = result.content ?? [];
@@ -45390,7 +45428,7 @@ var consumeOpenAIResponsesStream = async (response, onTextDelta, abortOptions) =
45390
45428
  return { assistantText, toolCalls: finalizeToolCalls(calls), usage };
45391
45429
  };
45392
45430
  var createOpenAIVoiceAssistantModel = (options) => {
45393
- const fetchImpl = options.fetch ?? globalThis.fetch;
45431
+ const fetchImpl = hardenFetch(options.fetch);
45394
45432
  const baseUrl = options.baseUrl ?? "https://api.openai.com/v1";
45395
45433
  const model = options.model ?? "gpt-4.1-mini";
45396
45434
  const timeoutMs = options.timeoutMs ?? 60000;
@@ -45515,7 +45553,7 @@ var consumeAnthropicStream = async (response, onTextDelta) => {
45515
45553
  return { assistantText, toolCalls: finalizeToolCalls(calls), usage };
45516
45554
  };
45517
45555
  var createAnthropicVoiceAssistantModel = (options) => {
45518
- const fetchImpl = options.fetch ?? globalThis.fetch;
45556
+ const fetchImpl = hardenFetch(options.fetch);
45519
45557
  const baseUrl = options.baseUrl ?? "https://api.anthropic.com/v1";
45520
45558
  const model = options.model ?? "claude-sonnet-4-5";
45521
45559
  return {
@@ -45601,7 +45639,7 @@ var consumeGeminiStream = async (response, onTextDelta) => {
45601
45639
  return { assistantText, toolCalls, usage };
45602
45640
  };
45603
45641
  var createGeminiVoiceAssistantModel = (options) => {
45604
- const fetchImpl = options.fetch ?? globalThis.fetch;
45642
+ const fetchImpl = hardenFetch(options.fetch);
45605
45643
  const baseUrl = options.baseUrl ?? "https://generativelanguage.googleapis.com/v1beta";
45606
45644
  const model = options.model ?? "gemini-2.5-flash";
45607
45645
  const maxRetries = Math.max(0, options.maxRetries ?? 2);
@@ -52711,6 +52749,7 @@ export {
52711
52749
  importVoiceCampaignRecipients,
52712
52750
  heartbeatVoiceOpsTask,
52713
52751
  hasVoiceOpsTaskSLABreach,
52752
+ hardenFetch,
52714
52753
  getVoiceProofTargetLogicalFailure,
52715
52754
  getVoiceLiveOpsControlStatus,
52716
52755
  getVoiceCampaignDialerProofStatus,
@@ -4210,6 +4210,45 @@ var startVoiceTimer = (sessionId) => {
4210
4210
  };
4211
4211
  var voiceTimingEnabled = () => timingEnabled();
4212
4212
 
4213
+ // src/core/hardenedFetch.ts
4214
+ var ATTEMPT_TIMEOUT_MS = 6000;
4215
+ var isBun = "Bun" in globalThis;
4216
+ var oneAttempt = async (baseFetch, input, init) => {
4217
+ const controller = new AbortController;
4218
+ const callerSignal = init?.signal ?? undefined;
4219
+ const onCallerAbort = () => controller.abort(callerSignal?.reason);
4220
+ if (callerSignal?.aborted)
4221
+ controller.abort(callerSignal.reason);
4222
+ else
4223
+ callerSignal?.addEventListener("abort", onCallerAbort, { once: true });
4224
+ const timer = setTimeout(() => {
4225
+ controller.abort(new Error(`fetch exceeded ${ATTEMPT_TIMEOUT_MS}ms before response headers (stale Bun keep-alive socket?)`));
4226
+ }, ATTEMPT_TIMEOUT_MS);
4227
+ const headers = new Headers(init?.headers);
4228
+ if (isBun)
4229
+ headers.set("Connection", "close");
4230
+ try {
4231
+ return await baseFetch(input, {
4232
+ ...init,
4233
+ headers,
4234
+ signal: controller.signal
4235
+ });
4236
+ } finally {
4237
+ clearTimeout(timer);
4238
+ callerSignal?.removeEventListener("abort", onCallerAbort);
4239
+ }
4240
+ };
4241
+ var hardenFetch = (baseFetch = globalThis.fetch) => Object.assign(async (input, init) => {
4242
+ try {
4243
+ return await oneAttempt(baseFetch, input, init);
4244
+ } catch (error) {
4245
+ if (init?.signal?.aborted)
4246
+ throw error;
4247
+ console.warn(`[voice] hardened fetch retrying on a fresh connection: ${error instanceof Error ? error.message : String(error)}`);
4248
+ return oneAttempt(baseFetch, input, init);
4249
+ }
4250
+ }, { preconnect: baseFetch.preconnect.bind(baseFetch) });
4251
+
4213
4252
  // src/core/modelAdapters.ts
4214
4253
  var isVoiceProviderRoutingPolicyPreset = (value) => value === "balanced" || value === "cost-cap" || value === "cost-first" || value === "latency-first" || value === "quality-first";
4215
4254
  var resolveVoiceProviderRoutingPolicyPreset = (preset, options = {}) => {
@@ -4914,7 +4953,7 @@ var consumeOpenAIResponsesStream = async (response, onTextDelta, abortOptions) =
4914
4953
  return { assistantText, toolCalls: finalizeToolCalls(calls), usage };
4915
4954
  };
4916
4955
  var createOpenAIVoiceAssistantModel = (options) => {
4917
- const fetchImpl = options.fetch ?? globalThis.fetch;
4956
+ const fetchImpl = hardenFetch(options.fetch);
4918
4957
  const baseUrl = options.baseUrl ?? "https://api.openai.com/v1";
4919
4958
  const model = options.model ?? "gpt-4.1-mini";
4920
4959
  const timeoutMs = options.timeoutMs ?? 60000;
@@ -5039,7 +5078,7 @@ var consumeAnthropicStream = async (response, onTextDelta) => {
5039
5078
  return { assistantText, toolCalls: finalizeToolCalls(calls), usage };
5040
5079
  };
5041
5080
  var createAnthropicVoiceAssistantModel = (options) => {
5042
- const fetchImpl = options.fetch ?? globalThis.fetch;
5081
+ const fetchImpl = hardenFetch(options.fetch);
5043
5082
  const baseUrl = options.baseUrl ?? "https://api.anthropic.com/v1";
5044
5083
  const model = options.model ?? "claude-sonnet-4-5";
5045
5084
  return {
@@ -5125,7 +5164,7 @@ var consumeGeminiStream = async (response, onTextDelta) => {
5125
5164
  return { assistantText, toolCalls, usage };
5126
5165
  };
5127
5166
  var createGeminiVoiceAssistantModel = (options) => {
5128
- const fetchImpl = options.fetch ?? globalThis.fetch;
5167
+ const fetchImpl = hardenFetch(options.fetch);
5129
5168
  const baseUrl = options.baseUrl ?? "https://generativelanguage.googleapis.com/v1beta";
5130
5169
  const model = options.model ?? "gemini-2.5-flash";
5131
5170
  const maxRetries = Math.max(0, options.maxRetries ?? 2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.583",
3
+ "version": "0.0.22-beta.584",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",