Skip to content
Merged
Changes from all commits
Commits
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
71 changes: 67 additions & 4 deletions ui/desktop/src/components/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,20 @@
import { Card } from './ui/card';
import { ScrollArea, ScrollAreaHandle } from './ui/scroll-area';
import UserMessage from './UserMessage';
import { askAi } from '../utils/askAI';

Check warning on line 14 in ui/desktop/src/components/ChatView.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

'askAi' is defined but never used. Allowed unused vars must match /^_/u
import Splash from './Splash';
import 'react-toastify/dist/ReactToastify.css';
import { useMessageStream } from '../hooks/useMessageStream';
import { Message, createUserMessage, getTextContent } from '../types/message';
import {
Message,
createUserMessage,
ToolCall,
ToolCallResult,
ToolRequestMessageContent,
ToolResponseMessageContent,
ToolConfirmationRequestMessageContent,
getTextContent,

Check warning on line 26 in ui/desktop/src/components/ChatView.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

'getTextContent' is defined but never used. Allowed unused vars must match /^_/u
} from '../types/message';

export interface ChatType {
id: number;
Expand Down Expand Up @@ -182,16 +191,70 @@

// Handle stopping the message stream
const lastMessage = messages[messages.length - 1];
if (lastMessage && lastMessage.role === 'user') {

// isUserMessage also checks if the message is a toolConfirmationRequest
if (lastMessage && isUserMessage(lastMessage)) {
// Remove the last user message if it's the most recent one
if (messages.length > 1) {
setMessages(messages.slice(0, -1));
} else {
setMessages([]);
}
} else if (!isUserMessage(lastMessage)) {
// check if we have any tool requests or tool confirmation requests
const toolRequests: [string, ToolCallResult<ToolCall>][] = lastMessage.content
.filter(
(content): content is ToolRequestMessageContent | ToolConfirmationRequestMessageContent =>
content.type === 'toolRequest' || content.type === 'toolConfirmationRequest'
)
.map((content) => {
if (content.type === 'toolRequest') {
return [content.id, content.toolCall];
} else {
// extract tool call from confirmation
const toolCall: ToolCallResult<ToolCall> = {
status: 'success',
value: {
name: content.toolName,
arguments: content.arguments,
},
};
return [content.id, toolCall];
}
});

if (toolRequests.length !== 0) {
// This means we were interrupted during a tool request
// Create tool responses for all interrupted tool requests

let responseMessage: Message = {
role: 'user',
created: Date.now(),
content: [],
};

// get the last tool's name or just "tool"
const lastToolName = toolRequests.at(-1)?.[1].value?.name ?? 'tool';
const notification = 'Interrupted by the user to make a correction';

// generate a response saying it was interrupted for each tool request
for (const [reqId, _] of toolRequests) {
const toolResponse: ToolResponseMessageContent = {
type: 'toolResponse',
id: reqId,
toolResult: {
status: 'error',
error: notification,
},
};

responseMessage.content.push(toolResponse);
}

// Use an immutable update to add the response message to the messages array
setMessages([...messages, responseMessage]);
}
}
// Note: Tool call interruption handling would need to be implemented
// differently with the new message format
};

// Filter out standalone tool response messages for rendering
Expand Down
Loading