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,137 @@
import type { WorkspaceTabDescriptor } from "@/screens/workspace/workspace-tabs-types";
export type WorkspaceTabMenuSurface = "desktop" | "mobile";
export type WorkspaceTabMenuEntry =
| {
kind: "item";
key: string;
label: string;
disabled?: boolean;
destructive?: boolean;
testID: string;
onSelect: () => void;
}
| {
kind: "separator";
key: string;
};
interface BuildWorkspaceTabMenuEntriesInput {
surface: WorkspaceTabMenuSurface;
tab: WorkspaceTabDescriptor;
index: number;
tabCount: number;
menuTestIDBase: string;
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
onCopyAgentId: (agentId: string) => Promise<void> | void;
onCloseTab: (tabId: string) => Promise<void> | void;
onCloseTabsBefore: (tabId: string) => Promise<void> | void;
onCloseTabsAfter: (tabId: string) => Promise<void> | void;
onCloseOtherTabs: (tabId: string) => Promise<void> | void;
}
function buildCloseBeforeLabel(surface: WorkspaceTabMenuSurface): string {
return surface === "mobile" ? "Close tabs above" : "Close to the left";
}
function buildCloseAfterLabel(surface: WorkspaceTabMenuSurface): string {
return surface === "mobile" ? "Close tabs below" : "Close to the right";
}
function buildCloseBeforeTestIDSuffix(surface: WorkspaceTabMenuSurface): string {
return surface === "mobile" ? "close-above" : "close-left";
}
function buildCloseAfterTestIDSuffix(surface: WorkspaceTabMenuSurface): string {
return surface === "mobile" ? "close-below" : "close-right";
}
export function buildWorkspaceTabMenuEntries(
input: BuildWorkspaceTabMenuEntriesInput
): WorkspaceTabMenuEntry[] {
const {
surface,
tab,
index,
tabCount,
menuTestIDBase,
onCopyResumeCommand,
onCopyAgentId,
onCloseTab,
onCloseTabsBefore,
onCloseTabsAfter,
onCloseOtherTabs,
} = input;
const isFirstTab = index === 0;
const isLastTab = index === tabCount - 1;
const isOnlyTab = tabCount <= 1;
const entries: WorkspaceTabMenuEntry[] = [];
if (tab.kind === "agent") {
entries.push({
kind: "item",
key: "copy-resume-command",
label: "Copy resume command",
testID: `${menuTestIDBase}-copy-resume-command`,
onSelect: () => {
void onCopyResumeCommand(tab.agentId);
},
});
entries.push({
kind: "item",
key: "copy-agent-id",
label: "Copy agent id",
testID: `${menuTestIDBase}-copy-agent-id`,
onSelect: () => {
void onCopyAgentId(tab.agentId);
},
});
entries.push({
kind: "separator",
key: "copy-separator",
});
}
entries.push({
kind: "item",
key: "close-before",
label: buildCloseBeforeLabel(surface),
disabled: isFirstTab,
testID: `${menuTestIDBase}-${buildCloseBeforeTestIDSuffix(surface)}`,
onSelect: () => {
void onCloseTabsBefore(tab.tabId);
},
});
entries.push({
kind: "item",
key: "close-after",
label: buildCloseAfterLabel(surface),
disabled: isLastTab,
testID: `${menuTestIDBase}-${buildCloseAfterTestIDSuffix(surface)}`,
onSelect: () => {
void onCloseTabsAfter(tab.tabId);
},
});
entries.push({
kind: "item",
key: "close-others",
label: "Close other tabs",
disabled: isOnlyTab,
testID: `${menuTestIDBase}-close-others`,
onSelect: () => {
void onCloseOtherTabs(tab.tabId);
},
});
entries.push({
kind: "item",
key: "close",
label: "Close",
testID: `${menuTestIDBase}-close`,
onSelect: () => {
void onCloseTab(tab.tabId);
},
});
return entries;
}