diff --git a/packages/cli/src/ui/hooks/useAgentStream.test.tsx b/packages/cli/src/ui/hooks/useAgentStream.test.tsx index 82fe921bf6..5c0ae48edd 100644 --- a/packages/cli/src/ui/hooks/useAgentStream.test.tsx +++ b/packages/cli/src/ui/hooks/useAgentStream.test.tsx @@ -292,6 +292,53 @@ describe('useAgentStream', () => { }); }); + it('should display error message when a tool call requires approval', async () => { + let eventHandler: (event: any) => void = () => {}; + vi.spyOn(mockLegacyAgentSession, 'subscribe').mockImplementation((handler) => { + eventHandler = handler; + return () => {}; + }); + + await renderHookWithProviders(() => + useAgentStream( + {} as any, + [], + mockAddItem, + mockConfig, + mockSettings, + mockOnDebugMessage, + mockHandleSlashCommand, + false, + () => undefined, + mockOnAuthError, + mockPerformMemoryRefresh, + false, + mockSetModelSwitchedFromQuotaError, + mockOnCancelSubmit, + mockSetShellInputFocused, + 80, + 24, + ), + ); + + act(() => { + eventHandler({ + type: 'error', + status: 'UNIMPLEMENTED', + message: 'TODO: Tool approvals not yet implemented, please switch to YOLO mode to test.', + fatal: true, + }); + }); + + expect(mockAddItem).toHaveBeenCalledWith( + expect.objectContaining({ + type: MessageType.ERROR, + text: 'TODO: Tool approvals not yet implemented, please switch to YOLO mode to test.', + }), + expect.any(Number), + ); + }); + it('should call session.abort when cancelOngoingRequest is called', async () => { const { result } = await renderHookWithProviders(() => useAgentStream( diff --git a/packages/cli/src/ui/hooks/useAgentStream.ts b/packages/cli/src/ui/hooks/useAgentStream.ts index 9400651653..52bcbb626c 100644 --- a/packages/cli/src/ui/hooks/useAgentStream.ts +++ b/packages/cli/src/ui/hooks/useAgentStream.ts @@ -218,7 +218,7 @@ export const useAgentStream = ( isClientInitiated: false, originalRequestName: event.name, }, - status: 'executing', + status: 'scheduled', tool: { displayName: (event._meta?.['displayName'] as string) ?? event.name, isOutputMarkdown: (event._meta?.['isOutputMarkdown'] as boolean) ?? false, @@ -236,13 +236,27 @@ export const useAgentStream = ( tc.request.callId === event.requestId ? ({ ...tc, - liveOutput: event.displayContent?.[0]?.type === 'text' ? event.displayContent[0].text : undefined, - progressMessage: event.data?.['progressMessage'] as string | undefined, - progress: event.data?.['progress'] as number | undefined, - progressTotal: event.data?.['progressTotal'] as number | undefined, - pid: event.data?.['pid'] as number | undefined, + status: (event.data?.['status'] as any) ?? tc.status, + liveOutput: + event.displayContent?.[0]?.type === 'text' + ? event.displayContent[0].text + : (tc as any).liveOutput, + progressMessage: + (event.data?.['progressMessage'] as string | undefined) ?? + (tc as any).progressMessage, + progress: + (event.data?.['progress'] as number | undefined) ?? + (tc as any).progress, + progressTotal: + (event.data?.['progressTotal'] as number | undefined) ?? + (tc as any).progressTotal, + pid: + (event.data?.['pid'] as number | undefined) ?? + (tc as any).pid, invocation: { - getDescription: () => (event._meta?.['description'] as string) ?? (tc as any).invocation?.getDescription(), + getDescription: () => + (event._meta?.['description'] as string) ?? + (tc as any).invocation?.getDescription(), }, } as unknown as TrackedToolCall) : tc, @@ -257,7 +271,11 @@ export const useAgentStream = ( ...tc, status: event.isError ? 'error' : 'success', response: { - resultDisplay: event._meta?.['resultDisplay'] ?? (event.displayContent?.[0]?.type === 'text' ? event.displayContent[0].text : undefined), + resultDisplay: + event._meta?.['resultDisplay'] ?? + (event.displayContent?.[0]?.type === 'text' + ? event.displayContent[0].text + : undefined), outputFile: event._meta?.['outputFile'] as string | undefined, }, responseSubmittedToGemini: true, diff --git a/packages/core/src/agent/legacy-agent-session.ts b/packages/core/src/agent/legacy-agent-session.ts index 975134969d..6286305634 100644 --- a/packages/core/src/agent/legacy-agent-session.ts +++ b/packages/core/src/agent/legacy-agent-session.ts @@ -168,6 +168,19 @@ class LegacyAgentProtocol implements AgentProtocol { const handleToolCallsUpdate = (event: ToolCallsUpdateMessage) => { const toolUpdates: AgentEvent[] = []; for (const tc of event.toolCalls) { + if (tc.status === 'awaiting_approval') { + this._emit([ + this._makeErrorEvent({ + status: 'UNIMPLEMENTED', + message: + 'TODO: Tool approvals not yet implemented, please switch to YOLO mode to test.', + fatal: true, + }), + ]); + void this.abort(); + return; + } + if (tc.status === 'executing') { toolUpdates.push( this._makeToolUpdateEvent({