From a2969ffd6c7c52725dfa1e290962d70f39c5c6fa Mon Sep 17 00:00:00 2001 From: Vellum Assistant Date: Wed, 25 Feb 2026 08:59:02 -0500 Subject: [PATCH] fix: type narrowing for nullable handleRecordingStart + add task_routed to else branch Co-Authored-By: Claude --- .../src/__tests__/recording-handler.test.ts | 25 ++++++++++++------- assistant/src/daemon/handlers/misc.ts | 1 + 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/assistant/src/__tests__/recording-handler.test.ts b/assistant/src/__tests__/recording-handler.test.ts index 2e2165f8ff0..0885bcb6d63 100644 --- a/assistant/src/__tests__/recording-handler.test.ts +++ b/assistant/src/__tests__/recording-handler.test.ts @@ -146,7 +146,7 @@ describe('handleRecordingStart', () => { const recordingId = handleRecordingStart(conversationId, undefined, fakeSocket, ctx); - expect(recordingId).toBeTruthy(); + expect(recordingId).not.toBeNull(); // UUID v4 format expect(recordingId).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i); @@ -201,14 +201,15 @@ describe('handleRecordingStop', () => { // Start a recording first const recordingId = handleRecordingStart(conversationId, undefined, fakeSocket, ctx); + expect(recordingId).not.toBeNull(); sent.length = 0; // Clear the start message const result = handleRecordingStop(conversationId, ctx); - expect(result).toBe(recordingId); + expect(result).toBe(recordingId!); expect(sent).toHaveLength(1); expect(sent[0].type).toBe('recording_stop'); - expect(sent[0].recordingId).toBe(recordingId); + expect(sent[0].recordingId).toBe(recordingId!); }); test('returns undefined when no active recording exists', () => { @@ -249,10 +250,11 @@ describe('recordingHandlers.recording_status', () => { const conversationId = 'conv-status-1'; const recordingId = handleRecordingStart(conversationId, undefined, fakeSocket, ctx); + expect(recordingId).not.toBeNull(); const statusMsg: RecordingStatus = { type: 'recording_status', - sessionId: recordingId, + sessionId: recordingId!, status: 'started', }; @@ -270,6 +272,7 @@ describe('recordingHandlers.recording_status', () => { ctx.socketToSession.set(fakeSocket, conversationId); const recordingId = handleRecordingStart(conversationId, undefined, fakeSocket, ctx); + expect(recordingId).not.toBeNull(); sent.length = 0; // Add a mock assistant message for the attachment to link to @@ -277,7 +280,7 @@ describe('recordingHandlers.recording_status', () => { const statusMsg: RecordingStatus = { type: 'recording_status', - sessionId: recordingId, + sessionId: recordingId!, status: 'stopped', filePath: '/tmp/recording.mov', durationMs: 5000, @@ -308,13 +311,14 @@ describe('recordingHandlers.recording_status', () => { ctx.socketToSession.set(fakeSocket, conversationId); const recordingId = handleRecordingStart(conversationId, undefined, fakeSocket, ctx); + expect(recordingId).not.toBeNull(); sent.length = 0; // No existing messages, handler should create one const statusMsg: RecordingStatus = { type: 'recording_status', - sessionId: recordingId, + sessionId: recordingId!, status: 'stopped', filePath: '/tmp/recording.mp4', durationMs: 3000, @@ -336,11 +340,12 @@ describe('recordingHandlers.recording_status', () => { mockFileExists = false; const recordingId = handleRecordingStart(conversationId, undefined, fakeSocket, ctx); + expect(recordingId).not.toBeNull(); sent.length = 0; const statusMsg: RecordingStatus = { type: 'recording_status', - sessionId: recordingId, + sessionId: recordingId!, status: 'stopped', filePath: '/tmp/nonexistent.mov', durationMs: 1000, @@ -362,11 +367,12 @@ describe('recordingHandlers.recording_status', () => { ctx.socketToSession.set(fakeSocket, conversationId); const recordingId = handleRecordingStart(conversationId, undefined, fakeSocket, ctx); + expect(recordingId).not.toBeNull(); sent.length = 0; const statusMsg: RecordingStatus = { type: 'recording_status', - sessionId: recordingId, + sessionId: recordingId!, status: 'failed', error: 'Permission denied', }; @@ -390,11 +396,12 @@ describe('recordingHandlers.recording_status', () => { ctx.socketToSession.set(fakeSocket, conversationId); const recordingId = handleRecordingStart(conversationId, undefined, fakeSocket, ctx); + expect(recordingId).not.toBeNull(); sent.length = 0; const statusMsg: RecordingStatus = { type: 'recording_status', - sessionId: recordingId, + sessionId: recordingId!, status: 'failed', }; diff --git a/assistant/src/daemon/handlers/misc.ts b/assistant/src/daemon/handlers/misc.ts index b30d1dadd3f..24345094ecf 100644 --- a/assistant/src/daemon/handlers/misc.ts +++ b/assistant/src/daemon/handlers/misc.ts @@ -107,6 +107,7 @@ export async function handleTaskSubmit( ctx.send(socket, { type: 'task_routed', sessionId: conversation.id, interactionType: 'text_qa' }); ctx.send(socket, { type: 'assistant_text_delta', text: 'Starting screen recording.', sessionId: conversation.id }); } else { + ctx.send(socket, { type: 'task_routed', sessionId: conversation.id, interactionType: 'text_qa' }); ctx.send(socket, { type: 'assistant_text_delta', text: 'A recording is already active.', sessionId: conversation.id }); } ctx.send(socket, { type: 'message_complete', sessionId: conversation.id });