@absolutejs/voice 0.0.22-beta.604 → 0.0.22-beta.606

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
@@ -3756,7 +3756,7 @@ var STREAM_CLAUSE_BOUNDARY = /[,;:]\s/g;
3756
3756
  var MAX_TTS_CHUNK_CHARS = 320;
3757
3757
  var STREAM_SENTENCE_END = /[.!?\u2026]['")\]]*$/;
3758
3758
  var STREAM_IDLE_FLUSH_MS = 350;
3759
- var SPECULATIVE_DELAY_MS = 350;
3759
+ var SPECULATIVE_DELAY_MS = 500;
3760
3760
  var nextSpeakableBoundary = (buffer) => {
3761
3761
  const match = STREAM_SENTENCE_BOUNDARY.exec(buffer);
3762
3762
  return match ? match.index + match[0].length : -1;
@@ -3940,9 +3940,8 @@ var createVoiceSession = (options) => {
3940
3940
  const complete = Math.max(0, Math.min(1, lastTurnCompleteConfidence));
3941
3941
  return Math.round(minSilenceMs + (silenceMs - minSilenceMs) * (1 - complete));
3942
3942
  };
3943
- let speculativeReply = null;
3943
+ let speculation = null;
3944
3944
  let speculationAttempted = false;
3945
- console.info(`[voice][p3dbg] session ${options.id} route.speculate wired=${Boolean(options.route.speculate)}`);
3946
3945
  const sttFallback = options.sttFallback ? {
3947
3946
  adapter: options.sttFallback.adapter,
3948
3947
  completionTimeoutMs: options.sttFallback.completionTimeoutMs ?? DEFAULT_FALLBACK_COMPLETION_TIMEOUT_MS,
@@ -4476,11 +4475,11 @@ var createVoiceSession = (options) => {
4476
4475
  }, delayMs);
4477
4476
  };
4478
4477
  const clearSpeculation = () => {
4479
- speculativeReply = null;
4478
+ speculation = null;
4480
4479
  speculationAttempted = false;
4481
4480
  };
4482
4481
  const runSpeculation = async () => {
4483
- if (!options.route.speculate || speculativeReply) {
4482
+ if (!options.route.speculate || speculation) {
4484
4483
  return;
4485
4484
  }
4486
4485
  const session = await readSession();
@@ -4497,20 +4496,21 @@ var createVoiceSession = (options) => {
4497
4496
  text: pendingText,
4498
4497
  transcripts: session.currentTurn.transcripts
4499
4498
  };
4500
- try {
4501
- const result = await Promise.resolve(options.route.speculate({
4502
- api,
4503
- context: options.context,
4504
- session,
4505
- turn: provisionalTurn
4506
- }));
4507
- console.info(`[voice][p3] speculate fired session=${session.id} -> ${result?.text ? `${result.text.length} chars` : "null"} for "${pendingText.slice(0, 30)}"`);
4508
- if (result && result.text.trim() && !speculativeReply) {
4509
- speculativeReply = { pendingText, text: result.text };
4510
- }
4511
- } catch (error) {
4499
+ const startedAt = Date.now();
4500
+ const speculate = options.route.speculate;
4501
+ const promise = Promise.resolve(speculate({
4502
+ api,
4503
+ context: options.context,
4504
+ session,
4505
+ turn: provisionalTurn
4506
+ })).then((result) => {
4507
+ console.info(`[voice][p3] speculate done session=${session.id} -> ${result?.text ? `${result.text.length} chars` : "null"} in ${Date.now() - startedAt}ms for "${pendingText.slice(0, 30)}"`);
4508
+ return result && result.text.trim() ? { text: result.text } : null;
4509
+ }).catch((error) => {
4512
4510
  console.info(`[voice][p3] speculate error: ${error instanceof Error ? error.message : String(error)}`);
4513
- }
4511
+ return null;
4512
+ });
4513
+ speculation = { pendingText, promise };
4514
4514
  };
4515
4515
  const scheduleSilenceCommit = (delayMs = adaptiveSilenceMs(), reset = true) => {
4516
4516
  scheduleTurnCommit(delayMs, "silence", reset);
@@ -5696,8 +5696,20 @@ var createVoiceSession = (options) => {
5696
5696
  let committedOutput;
5697
5697
  const onTurnStartedAt = Date.now();
5698
5698
  logVoiceTiming(session.id, "session.commit-to-onturn", onTurnStartedAt - (turn.committedAt || onTurnStartedAt), { fillerScheduled: fillerTimer !== null });
5699
- const reusableSpeculation = speculativeReply && speculativeReply.pendingText === turn.text ? { text: speculativeReply.text } : undefined;
5699
+ const pendingSpeculation = speculation;
5700
5700
  clearSpeculation();
5701
+ let reusableSpeculation;
5702
+ if (pendingSpeculation && pendingSpeculation.pendingText === turn.text) {
5703
+ const speculated = await pendingSpeculation.promise;
5704
+ if (speculated?.text) {
5705
+ reusableSpeculation = { text: speculated.text };
5706
+ logVoiceTiming(session.id, "p3.adopted-speculation", 0, {
5707
+ chars: speculated.text.length
5708
+ });
5709
+ }
5710
+ } else {
5711
+ pendingSpeculation?.promise;
5712
+ }
5701
5713
  try {
5702
5714
  const onTurnPromise = options.route.onTurn({
5703
5715
  api,
@@ -5983,7 +5983,7 @@ var STREAM_CLAUSE_BOUNDARY = /[,;:]\s/g;
5983
5983
  var MAX_TTS_CHUNK_CHARS = 320;
5984
5984
  var STREAM_SENTENCE_END = /[.!?\u2026]['")\]]*$/;
5985
5985
  var STREAM_IDLE_FLUSH_MS = 350;
5986
- var SPECULATIVE_DELAY_MS = 350;
5986
+ var SPECULATIVE_DELAY_MS = 500;
5987
5987
  var nextSpeakableBoundary = (buffer) => {
5988
5988
  const match = STREAM_SENTENCE_BOUNDARY.exec(buffer);
5989
5989
  return match ? match.index + match[0].length : -1;
@@ -6167,9 +6167,8 @@ var createVoiceSession = (options) => {
6167
6167
  const complete = Math.max(0, Math.min(1, lastTurnCompleteConfidence));
6168
6168
  return Math.round(minSilenceMs + (silenceMs - minSilenceMs) * (1 - complete));
6169
6169
  };
6170
- let speculativeReply = null;
6170
+ let speculation = null;
6171
6171
  let speculationAttempted = false;
6172
- console.info(`[voice][p3dbg] session ${options.id} route.speculate wired=${Boolean(options.route.speculate)}`);
6173
6172
  const sttFallback = options.sttFallback ? {
6174
6173
  adapter: options.sttFallback.adapter,
6175
6174
  completionTimeoutMs: options.sttFallback.completionTimeoutMs ?? DEFAULT_FALLBACK_COMPLETION_TIMEOUT_MS,
@@ -6703,11 +6702,11 @@ var createVoiceSession = (options) => {
6703
6702
  }, delayMs);
6704
6703
  };
6705
6704
  const clearSpeculation = () => {
6706
- speculativeReply = null;
6705
+ speculation = null;
6707
6706
  speculationAttempted = false;
6708
6707
  };
6709
6708
  const runSpeculation = async () => {
6710
- if (!options.route.speculate || speculativeReply) {
6709
+ if (!options.route.speculate || speculation) {
6711
6710
  return;
6712
6711
  }
6713
6712
  const session = await readSession();
@@ -6724,20 +6723,21 @@ var createVoiceSession = (options) => {
6724
6723
  text: pendingText,
6725
6724
  transcripts: session.currentTurn.transcripts
6726
6725
  };
6727
- try {
6728
- const result = await Promise.resolve(options.route.speculate({
6729
- api,
6730
- context: options.context,
6731
- session,
6732
- turn: provisionalTurn
6733
- }));
6734
- console.info(`[voice][p3] speculate fired session=${session.id} -> ${result?.text ? `${result.text.length} chars` : "null"} for "${pendingText.slice(0, 30)}"`);
6735
- if (result && result.text.trim() && !speculativeReply) {
6736
- speculativeReply = { pendingText, text: result.text };
6737
- }
6738
- } catch (error) {
6726
+ const startedAt = Date.now();
6727
+ const speculate = options.route.speculate;
6728
+ const promise = Promise.resolve(speculate({
6729
+ api,
6730
+ context: options.context,
6731
+ session,
6732
+ turn: provisionalTurn
6733
+ })).then((result) => {
6734
+ console.info(`[voice][p3] speculate done session=${session.id} -> ${result?.text ? `${result.text.length} chars` : "null"} in ${Date.now() - startedAt}ms for "${pendingText.slice(0, 30)}"`);
6735
+ return result && result.text.trim() ? { text: result.text } : null;
6736
+ }).catch((error) => {
6739
6737
  console.info(`[voice][p3] speculate error: ${error instanceof Error ? error.message : String(error)}`);
6740
- }
6738
+ return null;
6739
+ });
6740
+ speculation = { pendingText, promise };
6741
6741
  };
6742
6742
  const scheduleSilenceCommit = (delayMs = adaptiveSilenceMs(), reset = true) => {
6743
6743
  scheduleTurnCommit(delayMs, "silence", reset);
@@ -7923,8 +7923,20 @@ var createVoiceSession = (options) => {
7923
7923
  let committedOutput;
7924
7924
  const onTurnStartedAt = Date.now();
7925
7925
  logVoiceTiming(session.id, "session.commit-to-onturn", onTurnStartedAt - (turn.committedAt || onTurnStartedAt), { fillerScheduled: fillerTimer !== null });
7926
- const reusableSpeculation = speculativeReply && speculativeReply.pendingText === turn.text ? { text: speculativeReply.text } : undefined;
7926
+ const pendingSpeculation = speculation;
7927
7927
  clearSpeculation();
7928
+ let reusableSpeculation;
7929
+ if (pendingSpeculation && pendingSpeculation.pendingText === turn.text) {
7930
+ const speculated = await pendingSpeculation.promise;
7931
+ if (speculated?.text) {
7932
+ reusableSpeculation = { text: speculated.text };
7933
+ logVoiceTiming(session.id, "p3.adopted-speculation", 0, {
7934
+ chars: speculated.text.length
7935
+ });
7936
+ }
7937
+ } else {
7938
+ pendingSpeculation?.promise;
7939
+ }
7928
7940
  try {
7929
7941
  const onTurnPromise = options.route.onTurn({
7930
7942
  api,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.604",
3
+ "version": "0.0.22-beta.606",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",