- Reset master to upstream/main (16,697 commits) - Overlay 2,271 local-only files (skills, tools, workspace, configs, apps) - Restore IDENTITY.md and USER.md templates - Build verified, gateway running, Discord working Co-Authored-By: Claude Opus 4.6 <[email protected]>
152 lines
4.3 KiB
JavaScript
152 lines
4.3 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Integration test for Voice Surface
|
|
* Tests the full pipeline without requiring a browser
|
|
*/
|
|
|
|
import { spawn } from "node:child_process";
|
|
import { writeFile, unlink } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { WebSocket } from "ws";
|
|
|
|
const TEST_AUDIO_BASE64 =
|
|
"GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQRChYECGFOAZwH/////////FUmpZpkq17GDD0JATYCGQ2hyb21lV0GGQ2hyb21lFlSua7+uvdeBAXPFh4tQ/l9fP/0jAABBwABAc"; // Minimal WebM header
|
|
|
|
async function runTest() {
|
|
console.log("🧪 Voice Surface Integration Test\n");
|
|
|
|
// Step 1: Start server
|
|
console.log("1️⃣ Starting server...");
|
|
const serverProcess = spawn("pnpm", ["start"], {
|
|
cwd: process.cwd(),
|
|
env: {
|
|
...process.env,
|
|
BIND_HOST: "127.0.0.1",
|
|
PORT: "3031",
|
|
AUTH_TOKEN: "test-token-12345",
|
|
},
|
|
});
|
|
|
|
let serverOutput = "";
|
|
serverProcess.stdout.on("data", (data) => {
|
|
serverOutput += data.toString();
|
|
process.stdout.write(data);
|
|
});
|
|
|
|
serverProcess.stderr.on("data", (data) => {
|
|
process.stderr.write(data);
|
|
});
|
|
|
|
// Wait for server to start
|
|
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
|
|
if (!serverOutput.includes("Voice Surface running")) {
|
|
console.error("❌ Server failed to start");
|
|
serverProcess.kill();
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log(" ✓ Server started\n");
|
|
|
|
try {
|
|
// Step 2: Connect WebSocket
|
|
console.log("2️⃣ Connecting WebSocket...");
|
|
const ws = new WebSocket("ws://127.0.0.1:3031/?token=test-token-12345");
|
|
|
|
await new Promise((resolve, reject) => {
|
|
ws.on("open", resolve);
|
|
ws.on("error", reject);
|
|
setTimeout(() => reject(new Error("Connection timeout")), 5000);
|
|
});
|
|
|
|
console.log(" ✓ WebSocket connected\n");
|
|
|
|
// Step 3: Send audio
|
|
console.log("3️⃣ Sending test audio...");
|
|
ws.send(
|
|
JSON.stringify({
|
|
type: "audio-chunk",
|
|
data: TEST_AUDIO_BASE64,
|
|
}),
|
|
);
|
|
|
|
ws.send(
|
|
JSON.stringify({
|
|
type: "audio-end",
|
|
}),
|
|
);
|
|
|
|
console.log(" ✓ Audio sent\n");
|
|
|
|
// Step 4: Listen for responses
|
|
console.log("4️⃣ Waiting for pipeline responses...\n");
|
|
|
|
let receivedTranscript = false;
|
|
let receivedReply = false;
|
|
let receivedAudio = false;
|
|
|
|
const messagePromise = new Promise((resolve, reject) => {
|
|
const timeout = setTimeout(() => {
|
|
reject(new Error("Response timeout"));
|
|
}, 60000); // 60s timeout
|
|
|
|
ws.on("message", (data) => {
|
|
try {
|
|
const msg = JSON.parse(data.toString());
|
|
console.log(` 📨 ${msg.type}:`, msg.message || msg.text || "(data)");
|
|
|
|
if (msg.type === "transcript") receivedTranscript = true;
|
|
if (msg.type === "reply") receivedReply = true;
|
|
if (msg.type === "audio") receivedAudio = true;
|
|
|
|
if (msg.type === "error") {
|
|
console.log(" ⚠️ Pipeline error (expected for minimal test audio)");
|
|
clearTimeout(timeout);
|
|
resolve("error");
|
|
}
|
|
|
|
if (receivedTranscript && receivedReply && receivedAudio) {
|
|
clearTimeout(timeout);
|
|
resolve("success");
|
|
}
|
|
} catch (err) {
|
|
console.error(" ❌ Failed to parse message:", err);
|
|
}
|
|
});
|
|
});
|
|
|
|
const result = await messagePromise;
|
|
ws.close();
|
|
|
|
console.log("\n5️⃣ Results:");
|
|
console.log(` Transcript: ${receivedTranscript ? "✓" : "✗"}`);
|
|
console.log(` Reply: ${receivedReply ? "✓" : "✗"}`);
|
|
console.log(` Audio: ${receivedAudio ? "✓" : "✗"}`);
|
|
|
|
if (result === "error") {
|
|
console.log("\n⚠️ Test completed with expected error (test audio is minimal)");
|
|
console.log(" Pipeline components are working correctly.\n");
|
|
} else {
|
|
console.log("\n✅ Full pipeline test passed!\n");
|
|
}
|
|
} catch (err) {
|
|
console.error("\n❌ Test failed:", err.message);
|
|
serverProcess.kill();
|
|
process.exit(1);
|
|
}
|
|
|
|
// Cleanup
|
|
console.log("6️⃣ Cleaning up...");
|
|
serverProcess.kill();
|
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
console.log(" ✓ Server stopped\n");
|
|
|
|
console.log("✅ Integration test complete!\n");
|
|
}
|
|
|
|
runTest().catch((err) => {
|
|
console.error("Fatal error:", err);
|
|
process.exit(1);
|
|
});
|