Fix provider refresh scope and self-healing

This commit is contained in:
Mohamed Boudra
2026-04-21 12:41:28 +07:00
parent 92e701be8f
commit b01e274cce
54 changed files with 2057 additions and 694 deletions
@@ -3,6 +3,7 @@ import pino from "pino";
import { DaemonClient } from "../src/server/test-utils/daemon-client.js";
import { OpenAITTS } from "../src/server/speech/providers/openai/tts.js";
import { withTimeout } from "../src/utils/promise-timeout.js";
type RoundTripResult = {
voiceAgentId: string;
@@ -10,10 +11,6 @@ type RoundTripResult = {
audioChunks: number;
};
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function streamToBuffer(stream: AsyncIterable<unknown>): Promise<Buffer> {
const chunks: Buffer[] = [];
for await (const chunk of stream) {
@@ -103,13 +100,7 @@ async function runVoiceRoundTrip(params: {
}
try {
await Promise.race([
done,
(async () => {
await sleep(params.timeoutMs);
throw new Error("Timed out waiting for audio_output");
})(),
]);
await withTimeout(done, params.timeoutMs, "Timed out waiting for audio_output");
} finally {
offStream();
await client.setVoiceMode(false).catch(() => undefined);
@@ -16,6 +16,7 @@ import type {
import { buildVoiceAgentMcpServerConfig } from "../src/server/session.js";
import { createAgentMcpServer } from "../src/server/agent/mcp-server.js";
import { createVoiceMcpSocketBridgeManager } from "../src/server/voice-mcp-bridge.js";
import { withTimeout } from "../src/utils/promise-timeout.js";
type CliOptions = {
provider: AgentProvider;
@@ -54,17 +55,13 @@ async function streamWithTimeout(
timeoutMs: number,
onEvent: (event: AgentStreamEvent) => Promise<void> | void,
): Promise<void> {
const timeout = new Promise<never>((_, reject) => {
setTimeout(() => reject(new Error(`Timed out after ${timeoutMs}ms`)), timeoutMs);
});
const consume = (async () => {
for await (const event of iterator) {
await onEvent(event);
}
})();
await Promise.race([consume, timeout]);
await withTimeout(consume, timeoutMs, `Timed out after ${timeoutMs}ms`);
}
async function main(): Promise<void> {
@@ -6,6 +6,7 @@ import pino from "pino";
import { createTestPaseoDaemon } from "../src/server/test-utils/paseo-daemon.js";
import { DaemonClient } from "../src/server/test-utils/daemon-client.js";
import { OpenAITTS } from "../src/server/speech/providers/openai/tts.js";
import { withTimeout } from "../src/utils/promise-timeout.js";
async function streamToBuffer(stream: AsyncIterable<unknown>): Promise<Buffer> {
const chunks: Buffer[] = [];
@@ -151,18 +152,8 @@ async function main(): Promise<void> {
);
}
await Promise.race([
firstAudio,
new Promise((_, reject) =>
setTimeout(() => reject(new Error("Timed out waiting for first audio_output")), 120000),
),
]);
await Promise.race([
lastAudio,
new Promise((_, reject) =>
setTimeout(() => reject(new Error("Timed out waiting for final audio_output")), 120000),
),
]);
await withTimeout(firstAudio, 120000, "Timed out waiting for first audio_output");
await withTimeout(lastAudio, 120000, "Timed out waiting for final audio_output");
console.log("success", { audioChunkCount });
await client.setVoiceMode(false);