feat(dictate): support configurable ASR backends

This commit is contained in:
jb
2026-09-03 00:08:00 -04:00
parent 67877297d0
commit 2c3ee1f014
40 changed files with 7055 additions and 489 deletions
+58 -2
View File
@@ -195,10 +195,66 @@ function serviceFrame(
test("registers main-editor shortcuts, cancel command, and shutdown cleanup", () => {
const harness = createHarness();
assert.deepEqual([...harness.shortcuts.keys()], ["alt+m", "alt+n"]);
assert.deepEqual([...harness.commands.keys()], ["dictate-cancel"]);
assert.deepEqual([...harness.commands.keys()], ["dictate-cancel", "dictate-status"]);
assert.ok(harness.events.has("session_shutdown"));
});
test("status command negotiates a short read-only connection and reports backend diagnostics", async () => {
const harness = createHarness();
await harness.command("dictate-status")(
"",
harness.context as ExtensionCommandContext,
);
const socket = harness.sockets[0];
assert.ok(socket);
socket.connect();
const hello = harness.sentFrames(socket)[0];
assert.equal(hello?.type, "hello");
socket.frame({
version: PROTOCOL_VERSION,
type: "pong",
requestId: hello?.requestId,
backend: "openai",
model: "gpt-live-transcribe",
});
const ping = harness.sentFrames(socket)[1];
assert.equal(ping?.type, "ping");
socket.frame({
version: PROTOCOL_VERSION,
type: "pong",
requestId: ping?.requestId,
});
assert.deepEqual(harness.notifications, [
{
message: "Dictation backend: openai; model: gpt-live-transcribe",
type: "info",
},
]);
assert.equal(socket.endCount, 1);
});
test("status diagnostics reject control characters without exposing them", async () => {
const harness = createHarness();
await harness.command("dictate-status")(
"",
harness.context as ExtensionCommandContext,
);
const socket = harness.sockets[0];
assert.ok(socket);
socket.connect();
const hello = harness.sentFrames(socket)[0];
socket.frame({
version: PROTOCOL_VERSION,
type: "pong",
requestId: hello?.requestId,
backend: "openai\nsecret",
});
assert.match(harness.notifications[0]?.message ?? "", /diagnostic backend is invalid/i);
assert.equal(socket.destroyCount, 1);
});
test("connection errors return to idle and the next start uses a fresh socket", async () => {
const harness = createHarness();
await harness.shortcut("alt+m")(harness.context);
@@ -277,7 +333,7 @@ test("renders authoritative service states and sends a bounded stop command", as
serviceFrame(socket, generationId, "state", { state: "transcribing" });
assert.deepEqual(harness.statuses, [
"loading model...",
"preparing transcription...",
"● listening ▁▁▁▁▁▁▁▁▁▁▁▁",
"stopping...",
"transcribing...",