@getpaseo/server 0.1.27 → 0.1.29

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 (149) hide show
  1. package/dist/server/client/daemon-client.d.ts +1 -1
  2. package/dist/server/client/daemon-client.d.ts.map +1 -1
  3. package/dist/server/client/daemon-client.js +1 -1
  4. package/dist/server/client/daemon-client.js.map +1 -1
  5. package/dist/server/server/agent/agent-response-loop.js +1 -1
  6. package/dist/server/server/agent/agent-response-loop.js.map +1 -1
  7. package/dist/server/server/agent/provider-launch-config.d.ts +13 -2
  8. package/dist/server/server/agent/provider-launch-config.d.ts.map +1 -1
  9. package/dist/server/server/agent/provider-launch-config.js +17 -9
  10. package/dist/server/server/agent/provider-launch-config.js.map +1 -1
  11. package/dist/server/server/agent/provider-manifest.d.ts.map +1 -1
  12. package/dist/server/server/agent/provider-manifest.js +10 -5
  13. package/dist/server/server/agent/provider-manifest.js.map +1 -1
  14. package/dist/server/server/agent/providers/claude-agent.d.ts +3 -1
  15. package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -1
  16. package/dist/server/server/agent/providers/claude-agent.js +5 -1
  17. package/dist/server/server/agent/providers/claude-agent.js.map +1 -1
  18. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
  19. package/dist/server/server/agent/providers/codex-app-server-agent.js +30 -1
  20. package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
  21. package/dist/server/server/agent/providers/opencode-agent.d.ts +1 -0
  22. package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
  23. package/dist/server/server/agent/providers/opencode-agent.js +110 -9
  24. package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
  25. package/dist/server/server/agent/tts-manager.d.ts +8 -1
  26. package/dist/server/server/agent/tts-manager.d.ts.map +1 -1
  27. package/dist/server/server/agent/tts-manager.js +215 -108
  28. package/dist/server/server/agent/tts-manager.js.map +1 -1
  29. package/dist/server/server/bootstrap.d.ts +2 -2
  30. package/dist/server/server/bootstrap.d.ts.map +1 -1
  31. package/dist/server/server/bootstrap.js +26 -5
  32. package/dist/server/server/bootstrap.js.map +1 -1
  33. package/dist/server/server/exports.d.ts +1 -0
  34. package/dist/server/server/exports.d.ts.map +1 -1
  35. package/dist/server/server/exports.js +2 -0
  36. package/dist/server/server/exports.js.map +1 -1
  37. package/dist/server/server/persisted-config.d.ts +25 -0
  38. package/dist/server/server/persisted-config.d.ts.map +1 -1
  39. package/dist/server/server/persisted-config.js +6 -0
  40. package/dist/server/server/persisted-config.js.map +1 -1
  41. package/dist/server/server/session.d.ts +16 -19
  42. package/dist/server/server/session.d.ts.map +1 -1
  43. package/dist/server/server/session.js +171 -237
  44. package/dist/server/server/session.js.map +1 -1
  45. package/dist/server/server/speech/providers/local/runtime.d.ts +2 -0
  46. package/dist/server/server/speech/providers/local/runtime.d.ts.map +1 -1
  47. package/dist/server/server/speech/providers/local/runtime.js +7 -0
  48. package/dist/server/server/speech/providers/local/runtime.js.map +1 -1
  49. package/dist/server/server/speech/providers/local/sherpa/assets/silero_vad.onnx +0 -0
  50. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts +2 -0
  51. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts.map +1 -1
  52. package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js.map +1 -1
  53. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.d.ts +13 -0
  54. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.d.ts.map +1 -0
  55. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.js +23 -0
  56. package/dist/server/server/speech/providers/local/sherpa/silero-vad-provider.js.map +1 -0
  57. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.d.ts +32 -0
  58. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.d.ts.map +1 -0
  59. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.js +107 -0
  60. package/dist/server/server/speech/providers/local/sherpa/silero-vad-session.js.map +1 -0
  61. package/dist/server/server/speech/providers/openai/runtime.d.ts +2 -0
  62. package/dist/server/server/speech/providers/openai/runtime.d.ts.map +1 -1
  63. package/dist/server/server/speech/providers/openai/runtime.js +2 -0
  64. package/dist/server/server/speech/providers/openai/runtime.js.map +1 -1
  65. package/dist/server/server/speech/speech-config-resolver.d.ts.map +1 -1
  66. package/dist/server/server/speech/speech-config-resolver.js +35 -14
  67. package/dist/server/server/speech/speech-config-resolver.js.map +1 -1
  68. package/dist/server/server/speech/speech-runtime.d.ts +3 -1
  69. package/dist/server/server/speech/speech-runtime.d.ts.map +1 -1
  70. package/dist/server/server/speech/speech-runtime.js +39 -6
  71. package/dist/server/server/speech/speech-runtime.js.map +1 -1
  72. package/dist/server/server/speech/speech-types.d.ts +1 -0
  73. package/dist/server/server/speech/speech-types.d.ts.map +1 -1
  74. package/dist/server/server/speech/turn-detection-provider.d.ts +22 -0
  75. package/dist/server/server/speech/turn-detection-provider.d.ts.map +1 -0
  76. package/dist/server/server/speech/turn-detection-provider.js +2 -0
  77. package/dist/server/server/speech/turn-detection-provider.js.map +1 -0
  78. package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.d.ts +16 -0
  79. package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.d.ts.map +1 -0
  80. package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.js +35 -0
  81. package/dist/server/server/voice/fixed-duration-pcm-ring-buffer.js.map +1 -0
  82. package/dist/server/server/voice/voice-turn-controller.d.ts +34 -0
  83. package/dist/server/server/voice/voice-turn-controller.d.ts.map +1 -0
  84. package/dist/server/server/voice/voice-turn-controller.js +161 -0
  85. package/dist/server/server/voice/voice-turn-controller.js.map +1 -0
  86. package/dist/server/server/websocket-server.d.ts +3 -0
  87. package/dist/server/server/websocket-server.d.ts.map +1 -1
  88. package/dist/server/server/websocket-server.js +5 -1
  89. package/dist/server/server/websocket-server.js.map +1 -1
  90. package/dist/server/server/workspace-registry.d.ts +2 -0
  91. package/dist/server/server/workspace-registry.d.ts.map +1 -1
  92. package/dist/server/server/workspace-registry.js +11 -4
  93. package/dist/server/server/workspace-registry.js.map +1 -1
  94. package/dist/server/shared/messages.d.ts +97 -0
  95. package/dist/server/shared/messages.d.ts.map +1 -1
  96. package/dist/server/shared/messages.js +7 -0
  97. package/dist/server/shared/messages.js.map +1 -1
  98. package/dist/server/shared/tool-call-display.d.ts.map +1 -1
  99. package/dist/server/shared/tool-call-display.js +58 -39
  100. package/dist/server/shared/tool-call-display.js.map +1 -1
  101. package/dist/src/server/agent/agent-response-loop.js +1 -1
  102. package/dist/src/server/agent/agent-response-loop.js.map +1 -1
  103. package/dist/src/server/agent/provider-launch-config.js +17 -9
  104. package/dist/src/server/agent/provider-launch-config.js.map +1 -1
  105. package/dist/src/server/agent/provider-manifest.js +10 -5
  106. package/dist/src/server/agent/provider-manifest.js.map +1 -1
  107. package/dist/src/server/agent/providers/claude-agent.js +5 -1
  108. package/dist/src/server/agent/providers/claude-agent.js.map +1 -1
  109. package/dist/src/server/agent/providers/codex-app-server-agent.js +30 -1
  110. package/dist/src/server/agent/providers/codex-app-server-agent.js.map +1 -1
  111. package/dist/src/server/agent/providers/opencode-agent.js +110 -9
  112. package/dist/src/server/agent/providers/opencode-agent.js.map +1 -1
  113. package/dist/src/server/agent/tts-manager.js +215 -108
  114. package/dist/src/server/agent/tts-manager.js.map +1 -1
  115. package/dist/src/server/bootstrap.js +26 -5
  116. package/dist/src/server/bootstrap.js.map +1 -1
  117. package/dist/src/server/persisted-config.js +6 -0
  118. package/dist/src/server/persisted-config.js.map +1 -1
  119. package/dist/src/server/session.js +171 -237
  120. package/dist/src/server/session.js.map +1 -1
  121. package/dist/src/server/speech/providers/local/runtime.js +7 -0
  122. package/dist/src/server/speech/providers/local/runtime.js.map +1 -1
  123. package/dist/src/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js.map +1 -1
  124. package/dist/src/server/speech/providers/local/sherpa/silero-vad-provider.js +23 -0
  125. package/dist/src/server/speech/providers/local/sherpa/silero-vad-provider.js.map +1 -0
  126. package/dist/src/server/speech/providers/local/sherpa/silero-vad-session.js +107 -0
  127. package/dist/src/server/speech/providers/local/sherpa/silero-vad-session.js.map +1 -0
  128. package/dist/src/server/speech/providers/openai/runtime.js +2 -0
  129. package/dist/src/server/speech/providers/openai/runtime.js.map +1 -1
  130. package/dist/src/server/speech/speech-config-resolver.js +35 -14
  131. package/dist/src/server/speech/speech-config-resolver.js.map +1 -1
  132. package/dist/src/server/speech/speech-runtime.js +39 -6
  133. package/dist/src/server/speech/speech-runtime.js.map +1 -1
  134. package/dist/src/server/speech/turn-detection-provider.js +2 -0
  135. package/dist/src/server/speech/turn-detection-provider.js.map +1 -0
  136. package/dist/src/server/voice/fixed-duration-pcm-ring-buffer.js +35 -0
  137. package/dist/src/server/voice/fixed-duration-pcm-ring-buffer.js.map +1 -0
  138. package/dist/src/server/voice/voice-turn-controller.js +161 -0
  139. package/dist/src/server/voice/voice-turn-controller.js.map +1 -0
  140. package/dist/src/server/websocket-server.js +5 -1
  141. package/dist/src/server/websocket-server.js.map +1 -1
  142. package/dist/src/server/workspace-registry.js +11 -4
  143. package/dist/src/server/workspace-registry.js.map +1 -1
  144. package/dist/src/shared/messages.js +7 -0
  145. package/dist/src/shared/messages.js.map +1 -1
  146. package/dist/src/shared/tool-call-display.js +58 -39
  147. package/dist/src/shared/tool-call-display.js.map +1 -1
  148. package/package.json +4 -3
  149. package/src/server/speech/providers/local/sherpa/assets/silero_vad.onnx +0 -0
@@ -1,68 +1,84 @@
1
1
  import { v4 as uuidv4 } from "uuid";
2
2
  import { toResolver } from "../speech/provider-resolver.js";
3
- const MAX_TTS_SEGMENT_CHARS = 400;
4
- function splitTextForTts(text, maxChars) {
5
- const normalized = text.trim().replace(/\s+/g, " ");
6
- if (!normalized) {
7
- throw new Error("Cannot synthesize empty text");
3
+ const MAX_TTS_SEGMENT_CHARS = 260;
4
+ const TTS_PREFETCH_SEGMENTS = 2;
5
+ const CLOSED_AUDIO_ID_TTL_MS = 10000;
6
+ function splitOversizedFragment(fragment, maxChars) {
7
+ const trimmed = fragment.trim();
8
+ if (!trimmed) {
9
+ return [];
8
10
  }
9
- if (normalized.length <= maxChars) {
10
- return [normalized];
11
+ if (trimmed.length <= maxChars) {
12
+ return [trimmed];
11
13
  }
12
- const parts = [];
13
- const sentenceChunks = normalized.split(/(?<=[.!?])\s+/);
14
- let current = "";
15
- const pushCurrent = () => {
16
- const trimmed = current.trim();
17
- if (trimmed.length > 0) {
18
- parts.push(trimmed);
19
- }
20
- current = "";
21
- };
22
- const appendFragment = (fragment) => {
23
- const trimmed = fragment.trim();
24
- if (!trimmed) {
25
- return;
14
+ const clauseChunks = trimmed.split(/(?<=[,;:])\s+/);
15
+ if (clauseChunks.length > 1) {
16
+ const parts = [];
17
+ let current = "";
18
+ const pushCurrent = () => {
19
+ const value = current.trim();
20
+ if (value) {
21
+ parts.push(value);
22
+ }
23
+ current = "";
24
+ };
25
+ for (const clause of clauseChunks) {
26
+ const clauseText = clause.trim();
27
+ if (!clauseText) {
28
+ continue;
29
+ }
30
+ if (clauseText.length > maxChars) {
31
+ pushCurrent();
32
+ parts.push(...splitOversizedFragment(clauseText, maxChars));
33
+ continue;
34
+ }
35
+ if (!current) {
36
+ current = clauseText;
37
+ continue;
38
+ }
39
+ const candidate = `${current} ${clauseText}`;
40
+ if (candidate.length <= maxChars) {
41
+ current = candidate;
42
+ continue;
43
+ }
44
+ pushCurrent();
45
+ current = clauseText;
26
46
  }
27
- if (!current) {
28
- current = trimmed;
29
- return;
47
+ pushCurrent();
48
+ if (parts.length > 1 || parts[0] !== trimmed) {
49
+ return parts;
30
50
  }
31
- const candidate = `${current} ${trimmed}`;
32
- if (candidate.length <= maxChars) {
33
- current = candidate;
34
- return;
51
+ }
52
+ const parts = [];
53
+ let remaining = trimmed;
54
+ while (remaining.length > maxChars) {
55
+ let idx = remaining.lastIndexOf(" ", maxChars);
56
+ if (idx < Math.floor(maxChars * 0.5)) {
57
+ idx = maxChars;
35
58
  }
36
- pushCurrent();
37
- current = trimmed;
38
- };
39
- const splitLargeFragment = (fragment) => {
40
- const trimmed = fragment.trim();
41
- if (trimmed.length <= maxChars) {
42
- return [trimmed];
43
- }
44
- const out = [];
45
- let remaining = trimmed;
46
- while (remaining.length > maxChars) {
47
- let idx = remaining.lastIndexOf(" ", maxChars);
48
- if (idx < Math.floor(maxChars * 0.5)) {
49
- idx = maxChars;
50
- }
51
- out.push(remaining.slice(0, idx).trim());
52
- remaining = remaining.slice(idx).trim();
53
- }
54
- if (remaining.length > 0) {
55
- out.push(remaining);
56
- }
57
- return out;
58
- };
59
- for (const sentence of sentenceChunks) {
60
- const fragments = splitLargeFragment(sentence);
59
+ parts.push(remaining.slice(0, idx).trim());
60
+ remaining = remaining.slice(idx).trim();
61
+ }
62
+ if (remaining.length > 0) {
63
+ parts.push(remaining);
64
+ }
65
+ return parts;
66
+ }
67
+ function splitTextForTts(text) {
68
+ const normalized = text.trim().replace(/\s+/g, " ");
69
+ if (!normalized) {
70
+ throw new Error("Cannot synthesize empty text");
71
+ }
72
+ const sentences = normalized.split(/(?<=[.!?])\s+/);
73
+ const parts = [];
74
+ let segmentIndex = 0;
75
+ for (const sentence of sentences) {
76
+ const fragments = splitOversizedFragment(sentence, MAX_TTS_SEGMENT_CHARS);
61
77
  for (const fragment of fragments) {
62
- appendFragment(fragment);
78
+ parts.push({ index: segmentIndex, text: fragment });
79
+ segmentIndex += 1;
63
80
  }
64
81
  }
65
- pushCurrent();
66
82
  return parts;
67
83
  }
68
84
  /**
@@ -72,6 +88,7 @@ function splitTextForTts(text, maxChars) {
72
88
  export class TTSManager {
73
89
  constructor(sessionId, logger, tts) {
74
90
  this.pendingPlaybacks = new Map();
91
+ this.recentlyClosedAudioIds = new Map();
75
92
  this.logger = logger.child({ module: "agent", component: "tts-manager", sessionId });
76
93
  this.resolveTts = toResolver(tts);
77
94
  }
@@ -80,35 +97,128 @@ export class TTSManager {
80
97
  * Returns a Promise that resolves when the client confirms playback completed
81
98
  */
82
99
  async generateAndWaitForPlayback(text, emitMessage, abortSignal, isVoiceMode) {
100
+ const ttsStartMs = Date.now();
83
101
  this.logger.info({
84
102
  isVoiceMode,
85
103
  textLength: text.length,
86
104
  text,
87
105
  }, "TTS input text");
88
- const segments = splitTextForTts(text, MAX_TTS_SEGMENT_CHARS);
89
- for (const segment of segments) {
90
- if (abortSignal.aborted) {
91
- this.logger.debug("Aborted before generating segmented audio");
92
- return;
106
+ const segments = splitTextForTts(text);
107
+ this.logger.info({ segmentCount: segments.length, segments: segments.map((s) => ({ index: s.index, chars: s.text.length, text: s.text.slice(0, 80) })) }, `TTS split into ${segments.length} segment(s)`);
108
+ const inflight = new Map();
109
+ let nextSegmentToSchedule = 0;
110
+ const scheduleNextSegments = () => {
111
+ while (nextSegmentToSchedule < segments.length &&
112
+ inflight.size < TTS_PREFETCH_SEGMENTS) {
113
+ const segment = segments[nextSegmentToSchedule];
114
+ inflight.set(segment.index, this.scheduleSegmentSynthesis(segment, abortSignal));
115
+ nextSegmentToSchedule += 1;
116
+ }
117
+ };
118
+ scheduleNextSegments();
119
+ try {
120
+ for (const segment of segments) {
121
+ if (abortSignal.aborted) {
122
+ this.logger.debug("Aborted before emitting segmented audio");
123
+ return;
124
+ }
125
+ const synthWaitStart = Date.now();
126
+ const result = await inflight.get(segment.index);
127
+ const synthWaitMs = Date.now() - synthWaitStart;
128
+ inflight.delete(segment.index);
129
+ scheduleNextSegments();
130
+ if (result.kind === "aborted") {
131
+ return;
132
+ }
133
+ if (result.kind === "error") {
134
+ throw result.error;
135
+ }
136
+ this.logger.info({ segmentIndex: segment.index, synthWaitMs, totalElapsedMs: Date.now() - ttsStartMs, chars: segment.text.length }, `TTS segment ${segment.index} synthesis ready (waited ${synthWaitMs}ms, total ${Date.now() - ttsStartMs}ms)`);
137
+ const emitStart = Date.now();
138
+ await this.emitPreparedSegment({
139
+ prepared: result.prepared,
140
+ emitMessage,
141
+ abortSignal,
142
+ isVoiceMode,
143
+ });
144
+ this.logger.info({ segmentIndex: segment.index, emitAndPlayMs: Date.now() - emitStart, totalElapsedMs: Date.now() - ttsStartMs }, `TTS segment ${segment.index} playback confirmed (emit+play ${Date.now() - emitStart}ms, total ${Date.now() - ttsStartMs}ms)`);
145
+ scheduleNextSegments();
93
146
  }
94
- await this.generateSegmentAndWaitForPlayback(segment, emitMessage, abortSignal, isVoiceMode);
147
+ }
148
+ finally {
149
+ this.cleanupPrefetchedSegments(inflight);
150
+ this.logger.info({ totalMs: Date.now() - ttsStartMs }, `TTS generateAndWaitForPlayback done (${Date.now() - ttsStartMs}ms)`);
95
151
  }
96
152
  }
97
- async generateSegmentAndWaitForPlayback(text, emitMessage, abortSignal, isVoiceMode) {
153
+ async synthesizeSegment(segment, abortSignal) {
154
+ const resolveStart = Date.now();
98
155
  const tts = this.resolveTts();
99
156
  if (!tts) {
100
157
  throw new Error("TTS not configured");
101
158
  }
159
+ const resolveMs = Date.now() - resolveStart;
102
160
  if (abortSignal.aborted) {
103
- this.logger.debug("Aborted before generating audio");
104
- return;
161
+ throw new Error("TTS synthesis aborted");
105
162
  }
106
- // Generate TTS audio stream
107
- const { stream, format } = await tts.synthesizeSpeech(text);
163
+ const synthStart = Date.now();
164
+ const { stream, format } = await tts.synthesizeSpeech(segment.text);
165
+ this.logger.info({ segmentIndex: segment.index, resolveMs, synthMs: Date.now() - synthStart, chars: segment.text.length }, `TTS segment ${segment.index} synthesized (resolve=${resolveMs}ms, synth=${Date.now() - synthStart}ms, ${segment.text.length} chars)`);
108
166
  if (abortSignal.aborted) {
109
- this.logger.debug("Aborted after generating audio");
167
+ this.destroySpeechStream(stream);
168
+ throw new Error("TTS synthesis aborted");
169
+ }
170
+ return {
171
+ ...segment,
172
+ stream,
173
+ format,
174
+ };
175
+ }
176
+ scheduleSegmentSynthesis(segment, abortSignal) {
177
+ return this.synthesizeSegment(segment, abortSignal).then((prepared) => {
178
+ if (abortSignal.aborted) {
179
+ this.destroySpeechStream(prepared.stream);
180
+ return { kind: "aborted" };
181
+ }
182
+ return { kind: "prepared", prepared };
183
+ }, (error) => {
184
+ if (abortSignal.aborted) {
185
+ return { kind: "aborted" };
186
+ }
187
+ return { kind: "error", error };
188
+ });
189
+ }
190
+ cleanupPrefetchedSegments(inflight) {
191
+ if (inflight.size === 0) {
110
192
  return;
111
193
  }
194
+ for (const pending of inflight.values()) {
195
+ void pending.then((result) => {
196
+ if (result.kind === "prepared") {
197
+ this.destroySpeechStream(result.prepared.stream);
198
+ }
199
+ });
200
+ }
201
+ }
202
+ destroySpeechStream(stream) {
203
+ if (typeof stream.destroy === "function" && !stream.destroyed) {
204
+ stream.destroy();
205
+ }
206
+ }
207
+ pruneRecentlyClosedAudioIds(now) {
208
+ for (const [audioId, expiresAt] of this.recentlyClosedAudioIds.entries()) {
209
+ if (expiresAt <= now) {
210
+ this.recentlyClosedAudioIds.delete(audioId);
211
+ }
212
+ }
213
+ }
214
+ rememberClosedAudioId(audioId) {
215
+ const now = Date.now();
216
+ this.pruneRecentlyClosedAudioIds(now);
217
+ this.recentlyClosedAudioIds.set(audioId, now + CLOSED_AUDIO_ID_TTL_MS);
218
+ }
219
+ async emitPreparedSegment(params) {
220
+ const { prepared, emitMessage, abortSignal, isVoiceMode } = params;
221
+ const { stream, format, text } = prepared;
112
222
  const audioId = uuidv4();
113
223
  let playbackResolve;
114
224
  let playbackReject;
@@ -124,59 +234,46 @@ export class TTSManager {
124
234
  };
125
235
  this.pendingPlaybacks.set(audioId, pendingPlayback);
126
236
  let onAbort;
127
- const destroyStream = () => {
128
- if (typeof stream.destroy === "function" && !stream.destroyed) {
129
- stream.destroy();
130
- }
131
- };
132
237
  onAbort = () => {
133
238
  this.logger.debug("Aborted while waiting for playback");
134
239
  pendingPlayback.streamEnded = true;
135
240
  pendingPlayback.pendingChunks = 0;
136
241
  this.pendingPlaybacks.delete(audioId);
242
+ this.rememberClosedAudioId(audioId);
137
243
  playbackResolve();
138
- destroyStream();
244
+ this.destroySpeechStream(stream);
139
245
  };
140
246
  abortSignal.addEventListener("abort", onAbort, { once: true });
141
247
  try {
142
- const iterator = stream[Symbol.asyncIterator]();
143
- let chunkIndex = 0;
144
- let current = await iterator.next();
145
- if (!current.done) {
146
- let next = await iterator.next();
147
- while (true) {
148
- if (abortSignal.aborted) {
149
- this.logger.debug("Aborted during stream emission");
150
- break;
151
- }
152
- const chunkBuffer = Buffer.isBuffer(current.value)
153
- ? current.value
154
- : Buffer.from(current.value);
155
- const chunkId = `${audioId}:${chunkIndex}`;
156
- pendingPlayback.pendingChunks += 1;
157
- emitMessage({
158
- type: "audio_output",
159
- payload: {
160
- id: chunkId,
161
- groupId: audioId,
162
- chunkIndex,
163
- isLastChunk: next.done,
164
- audio: chunkBuffer.toString("base64"),
165
- format,
166
- isVoiceMode,
167
- },
168
- });
169
- chunkIndex += 1;
170
- if (next.done) {
171
- break;
172
- }
173
- current = next;
174
- next = await iterator.next();
248
+ const buffers = [];
249
+ for await (const chunk of stream) {
250
+ if (abortSignal.aborted) {
251
+ this.logger.debug("Aborted during stream collection");
252
+ break;
175
253
  }
254
+ buffers.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
255
+ }
256
+ if (!abortSignal.aborted && buffers.length > 0) {
257
+ const fullBuffer = Buffer.concat(buffers);
258
+ const chunkId = `${audioId}:0`;
259
+ pendingPlayback.pendingChunks = 1;
260
+ emitMessage({
261
+ type: "audio_output",
262
+ payload: {
263
+ id: chunkId,
264
+ groupId: audioId,
265
+ chunkIndex: 0,
266
+ isLastChunk: true,
267
+ audio: fullBuffer.toString("base64"),
268
+ format,
269
+ isVoiceMode,
270
+ },
271
+ });
176
272
  }
177
273
  pendingPlayback.streamEnded = true;
178
274
  if (pendingPlayback.pendingChunks === 0) {
179
275
  this.pendingPlaybacks.delete(audioId);
276
+ this.rememberClosedAudioId(audioId);
180
277
  playbackResolve();
181
278
  }
182
279
  await playbackPromise;
@@ -195,12 +292,12 @@ export class TTSManager {
195
292
  if (onAbort) {
196
293
  abortSignal.removeEventListener("abort", onAbort);
197
294
  }
198
- destroyStream();
295
+ this.destroySpeechStream(stream);
199
296
  }
200
297
  if (abortSignal.aborted) {
201
298
  return;
202
299
  }
203
- this.logger.debug({ audioId }, "Audio playback confirmed");
300
+ this.logger.debug({ audioId, textLength: text.length }, "Audio playback confirmed");
204
301
  }
205
302
  /**
206
303
  * Called when client confirms audio playback completed
@@ -212,6 +309,13 @@ export class TTSManager {
212
309
  : [chunkId];
213
310
  const pending = this.pendingPlaybacks.get(audioId);
214
311
  if (!pending) {
312
+ const now = Date.now();
313
+ this.pruneRecentlyClosedAudioIds(now);
314
+ const expiresAt = this.recentlyClosedAudioIds.get(audioId);
315
+ if (expiresAt && expiresAt > now) {
316
+ this.logger.debug({ chunkId }, "Ignoring late confirmation for recently closed audio ID");
317
+ return;
318
+ }
215
319
  this.logger.warn({ chunkId }, "Received confirmation for unknown audio ID");
216
320
  return;
217
321
  }
@@ -219,6 +323,7 @@ export class TTSManager {
219
323
  if (pending.pendingChunks === 0 && pending.streamEnded) {
220
324
  pending.resolve();
221
325
  this.pendingPlaybacks.delete(audioId);
326
+ this.rememberClosedAudioId(audioId);
222
327
  }
223
328
  }
224
329
  /**
@@ -232,6 +337,7 @@ export class TTSManager {
232
337
  for (const [audioId, pending] of this.pendingPlaybacks.entries()) {
233
338
  pending.resolve();
234
339
  this.pendingPlaybacks.delete(audioId);
340
+ this.rememberClosedAudioId(audioId);
235
341
  this.logger.debug({ audioId }, "Cleared pending playback");
236
342
  }
237
343
  }
@@ -243,6 +349,7 @@ export class TTSManager {
243
349
  for (const [audioId, pending] of this.pendingPlaybacks.entries()) {
244
350
  pending.reject(new Error("Session closed"));
245
351
  this.pendingPlaybacks.delete(audioId);
352
+ this.rememberClosedAudioId(audioId);
246
353
  }
247
354
  }
248
355
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tts-manager.js","sourceRoot":"","sources":["../../../../src/server/agent/tts-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tts-manager.js","sourceRoot":"","sources":["../../../../src/server/agent/tts-manager.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { Logger } from "pino";
2
- type ListenTarget = {
2
+ export type ListenTarget = {
3
3
  type: "tcp";
4
4
  host: string;
5
5
  port: number;
@@ -71,7 +71,7 @@ export interface PaseoDaemon {
71
71
  terminalManager: TerminalManager;
72
72
  start(): Promise<void>;
73
73
  stop(): Promise<void>;
74
+ getListenTarget(): ListenTarget | null;
74
75
  }
75
76
  export declare function createPaseoDaemon(config: PaseoDaemonConfig, rootLogger: Logger): Promise<PaseoDaemon>;
76
- export {};
77
77
  //# sourceMappingURL=bootstrap.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../../src/server/bootstrap.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../../src/server/bootstrap.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,20 @@ import path from "node:path";
7
7
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
8
8
  import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
9
9
  import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
10
+ function resolveBoundListenTarget(listenTarget, httpServer) {
11
+ if (listenTarget.type !== "tcp") {
12
+ return listenTarget;
13
+ }
14
+ const address = httpServer.address();
15
+ if (!address || typeof address === "string") {
16
+ throw new Error("HTTP server did not expose a TCP address after listening");
17
+ }
18
+ return {
19
+ type: "tcp",
20
+ host: listenTarget.host,
21
+ port: address.port,
22
+ };
23
+ }
10
24
  export function parseListenString(listen) {
11
25
  if (listen.startsWith("\\\\.\\pipe\\") || listen.startsWith("pipe://")) {
12
26
  return {
@@ -95,6 +109,7 @@ export async function createPaseoDaemon(config, rootLogger) {
95
109
  const downloadTokenStore = new DownloadTokenStore({ ttlMs: downloadTokenTtlMs });
96
110
  const listenTarget = parseListenString(config.listen);
97
111
  const app = express();
112
+ let boundListenTarget = null;
98
113
  // Host allowlist / DNS rebinding protection (vite-like semantics).
99
114
  // For non-TCP (unix sockets), skip host validation.
100
115
  if (listenTarget.type === "tcp") {
@@ -362,13 +377,13 @@ export async function createPaseoDaemon(config, rootLogger) {
362
377
  });
363
378
  },
364
379
  });
365
- const { resolveVoiceStt, resolveVoiceTts, resolveDictationStt, getSpeechReadiness, subscribeSpeechReadiness, cleanup: cleanupSpeechRuntime, localModelConfig, } = await initializeSpeechRuntime({
380
+ const { resolveVoiceTurnDetection, resolveVoiceStt, resolveVoiceTts, resolveDictationStt, getSpeechReadiness, subscribeSpeechReadiness, cleanup: cleanupSpeechRuntime, localModelConfig, } = await initializeSpeechRuntime({
366
381
  logger,
367
382
  openaiConfig: config.openai,
368
383
  speechConfig: config.speech,
369
384
  });
370
385
  logger.info({ elapsed: elapsed() }, "Speech runtime initialized");
371
- wsServer = new VoiceAssistantWebSocketServer(httpServer, logger, serverId, agentManager, agentStorage, downloadTokenStore, config.paseoHome, createInMemoryAgentMcpTransport, { allowedOrigins, allowedHosts: config.allowedHosts }, { stt: resolveVoiceStt, tts: resolveVoiceTts }, terminalManager, {
386
+ wsServer = new VoiceAssistantWebSocketServer(httpServer, logger, serverId, agentManager, agentStorage, downloadTokenStore, config.paseoHome, createInMemoryAgentMcpTransport, { allowedOrigins, allowedHosts: config.allowedHosts }, { turnDetection: resolveVoiceTurnDetection, stt: resolveVoiceStt, tts: resolveVoiceTts }, terminalManager, {
372
387
  voiceAgentMcpStdio: {
373
388
  command: voiceMcpBridgeCommand.command,
374
389
  baseArgs: [...voiceMcpBridgeCommand.baseArgs],
@@ -406,15 +421,20 @@ export async function createPaseoDaemon(config, rootLogger) {
406
421
  const onListening = () => {
407
422
  httpServer.off("error", onError);
408
423
  const logAndResolve = async () => {
424
+ boundListenTarget = resolveBoundListenTarget(listenTarget, httpServer);
409
425
  const relayEnabled = config.relayEnabled ?? true;
410
426
  const relayEndpoint = config.relayEndpoint ?? "relay.paseo.sh:443";
411
427
  const relayPublicEndpoint = config.relayPublicEndpoint ?? relayEndpoint;
412
428
  const appBaseUrl = config.appBaseUrl ?? "https://app.paseo.sh";
413
- if (listenTarget.type === "tcp") {
414
- logger.info({ host: listenTarget.host, port: listenTarget.port, elapsed: elapsed() }, `Server listening on http://${listenTarget.host}:${listenTarget.port}`);
429
+ if (boundListenTarget.type === "tcp") {
430
+ logger.info({
431
+ host: boundListenTarget.host,
432
+ port: boundListenTarget.port,
433
+ elapsed: elapsed(),
434
+ }, `Server listening on http://${boundListenTarget.host}:${boundListenTarget.port}`);
415
435
  }
416
436
  else {
417
- logger.info({ path: listenTarget.path, elapsed: elapsed() }, `Server listening on ${listenTarget.path}`);
437
+ logger.info({ path: boundListenTarget.path, elapsed: elapsed() }, `Server listening on ${boundListenTarget.path}`);
418
438
  }
419
439
  if (relayEnabled) {
420
440
  const offer = await createConnectionOfferV2({
@@ -494,6 +514,7 @@ export async function createPaseoDaemon(config, rootLogger) {
494
514
  terminalManager,
495
515
  start,
496
516
  stop,
517
+ getListenTarget: () => boundListenTarget,
497
518
  };
498
519
  }
499
520
  catch (err) {