feat(voice): implement turn-detection and real-time audio streaming

This commit is contained in:
Mohamed Boudra
2026-03-14 13:46:10 +07:00
parent c45b414476
commit fc7369384b
43 changed files with 3367 additions and 1476 deletions
@@ -0,0 +1,107 @@
import { describe, expect, it, vi } from "vitest";
import { buildWorkspaceTabMenuEntries } from "@/screens/workspace/workspace-tab-menu";
import type { WorkspaceTabDescriptor } from "@/screens/workspace/workspace-tabs-types";
function createAgentTab(): WorkspaceTabDescriptor {
return {
key: "agent_123",
tabId: "agent_123",
kind: "agent",
agentId: "agent-123",
provider: "codex",
label: "Agent 123",
subtitle: "/repo",
titleState: "ready",
};
}
describe("buildWorkspaceTabMenuEntries", () => {
it("uses desktop tab ordering labels for desktop menus", () => {
const onCopyResumeCommand = vi.fn();
const onCopyAgentId = vi.fn();
const onCloseTab = vi.fn();
const onCloseTabsBefore = vi.fn();
const onCloseTabsAfter = vi.fn();
const onCloseOtherTabs = vi.fn();
const entries = buildWorkspaceTabMenuEntries({
surface: "desktop",
tab: createAgentTab(),
index: 1,
tabCount: 3,
menuTestIDBase: "workspace-tab-context-agent_123",
onCopyResumeCommand,
onCopyAgentId,
onCloseTab,
onCloseTabsBefore,
onCloseTabsAfter,
onCloseOtherTabs,
});
expect(
entries.filter((entry) => entry.kind === "item").map((entry) => entry.label)
).toEqual([
"Copy resume command",
"Copy agent id",
"Close to the left",
"Close to the right",
"Close other tabs",
"Close",
]);
});
it("uses stacked ordering labels for mobile menus", () => {
const entries = buildWorkspaceTabMenuEntries({
surface: "mobile",
tab: createAgentTab(),
index: 1,
tabCount: 3,
menuTestIDBase: "workspace-tab-menu-agent_123",
onCopyResumeCommand: vi.fn(),
onCopyAgentId: vi.fn(),
onCloseTab: vi.fn(),
onCloseTabsBefore: vi.fn(),
onCloseTabsAfter: vi.fn(),
onCloseOtherTabs: vi.fn(),
});
expect(
entries.filter((entry) => entry.kind === "item").map((entry) => entry.label)
).toEqual([
"Copy resume command",
"Copy agent id",
"Close tabs above",
"Close tabs below",
"Close other tabs",
"Close",
]);
});
it("omits agent copy actions for non-agent tabs", () => {
const entries = buildWorkspaceTabMenuEntries({
surface: "mobile",
tab: {
key: "draft_123",
tabId: "draft_123",
kind: "draft",
draftId: "draft_123",
label: "New agent",
subtitle: "/repo",
},
index: 0,
tabCount: 1,
menuTestIDBase: "workspace-tab-menu-draft_123",
onCopyResumeCommand: vi.fn(),
onCopyAgentId: vi.fn(),
onCloseTab: vi.fn(),
onCloseTabsBefore: vi.fn(),
onCloseTabsAfter: vi.fn(),
onCloseOtherTabs: vi.fn(),
});
expect(entries.some((entry) => entry.kind === "item" && entry.label === "Copy agent id")).toBe(
false
);
expect(entries.some((entry) => entry.kind === "separator")).toBe(false);
});
});