Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
ac4bbe1
fix(voice): retain active transcript routes
johnmatthewtennant Aug 28, 2026
9326f01
fix(voice): release invalid transcript routes
johnmatthewtennant Aug 28, 2026
336824d
fix(voice): release routes on admission blocks
johnmatthewtennant Aug 28, 2026
939cdf5
fix(voice): discard speech blocked by admission
johnmatthewtennant Aug 28, 2026
b137a9c
fix(voice): defer transcripts during admission
johnmatthewtennant Aug 28, 2026
448f23c
fix(voice): defer blocked transcripts without rejection
johnmatthewtennant Aug 28, 2026
6894313
fix(voice): preserve deferred transcript state
johnmatthewtennant Aug 29, 2026
d310920
fix(voice): clear permanently unavailable routes
johnmatthewtennant Aug 29, 2026
2a7c40f
fix(voice): scope transcript blocking to route owners
johnmatthewtennant Aug 29, 2026
a6fc47d
fix(voice): preserve routes across view navigation
johnmatthewtennant Aug 29, 2026
b5dac26
fix(voice): abort stale conversation starts
johnmatthewtennant Aug 29, 2026
7dfd480
fix(voice): release stale route blocks on navigation
johnmatthewtennant Aug 29, 2026
cf078e9
fix(voice): stop starts after eligibility revocation
johnmatthewtennant Aug 29, 2026
ba19ff1
fix(voice): preserve admission blocks across navigation
johnmatthewtennant Aug 29, 2026
13db6b3
fix(voice): scope stale-start lifecycle cleanup
johnmatthewtennant Aug 29, 2026
589254e
fix(voice): honor live admission blocks before start
johnmatthewtennant Aug 29, 2026
7050b5d
fix(voice): report blocked conversation replacements
johnmatthewtennant Aug 29, 2026
96a91d9
fix(voice): preserve replacement failure outcomes
johnmatthewtennant Aug 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions src/features/chat/ui/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,18 @@ export function ChatView({
voiceInput.backend,
voiceOutput.backend,
);
const voiceAdmissionPermanentlyBlocked =
composerBinding.target.kind === "existingSession" &&
Boolean(composerBinding.target.admission.blockingReason);
const voiceDeliveryTemporarilyBlocked =
!voiceAdmissionPermanentlyBlocked &&
((composerBinding.target.kind === "existingSession" &&
composerBinding.target.admission.securityConfirmationPending) ||
controller.projectMetadataPending ||
controller.isCompactingContext ||
controller.isLoadingHistory ||
!controller.workspaceContextReady ||
controller.queue.queuedMessage !== null);
const voiceConversation = useVoiceConversationController({
sessionId,
// Voice delivery only needs to wait for admission. Holding its per-session
Expand All @@ -264,13 +276,9 @@ export function ChatView({
});
},
readOnly: Boolean(readOnlyStatus),
disabled:
admissionBlocked ||
controller.projectMetadataPending ||
controller.isCompactingContext ||
controller.isLoadingHistory ||
!controller.workspaceContextReady ||
controller.queue.queuedMessage !== null,
routeBlocked: voiceDeliveryTemporarilyBlocked,
routeUnavailable: voiceAdmissionPermanentlyBlocked,
disabled: admissionBlocked || voiceDeliveryTemporarilyBlocked,
});
const isAgentBuilderOpen = agentBuilderOpenForLayout;
const patchSession = useChatSessionStore((s) => s.patchSession);
Expand Down
9 changes: 9 additions & 0 deletions src/features/chat/ui/__tests__/ChatView.mcpApp.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ describe("ChatView MCP app messaging", () => {
projectMetadataPending: false,
isCompactingContext: false,
workspaceSetupInProgress: false,
workspaceContextReady: true,
queue: { queuedMessage: null, dismiss: vi.fn() },
draftValue: "",
handleDraftChange: mocks.handleDraftChange,
Expand Down Expand Up @@ -687,8 +688,12 @@ describe("ChatView MCP app messaging", () => {
const voiceOptions = mocks.voiceControllerSpy.mock.calls.at(-1)?.[0] as {
onSend: (text: string) => boolean;
disabled: boolean;
routeBlocked: boolean;
routeUnavailable: boolean;
};
expect(voiceOptions.disabled).toBe(true);
expect(voiceOptions.routeBlocked).toBe(true);
expect(voiceOptions.routeUnavailable).toBe(false);
expect(voiceOptions.onSend("blocked voice")).toBe(false);
expect(mocks.handleSend).not.toHaveBeenCalled();
});
Expand Down Expand Up @@ -1389,8 +1394,12 @@ describe("ChatView MCP app messaging", () => {
const voiceOptions = mocks.voiceControllerSpy.mock.calls.at(-1)?.[0] as {
onSend: (text: string) => boolean;
disabled: boolean;
routeBlocked: boolean;
routeUnavailable: boolean;
};
expect(voiceOptions.disabled).toBe(true);
expect(voiceOptions.routeBlocked).toBe(false);
expect(voiceOptions.routeUnavailable).toBe(true);
expect(voiceOptions.onSend("blocked voice")).toBe(false);
expect(mocks.handleSend).not.toHaveBeenCalled();
});
Expand Down
Loading