diff --git a/ui/desktop/src/components/EnhancedMentionPopover.tsx b/ui/desktop/src/components/EnhancedMentionPopover.tsx index 5e486a024b..c63373132d 100644 --- a/ui/desktop/src/components/EnhancedMentionPopover.tsx +++ b/ui/desktop/src/components/EnhancedMentionPopover.tsx @@ -84,19 +84,44 @@ const EnhancedMentionPopover = forwardRef< const mentionItems = useMemo((): MentionItem[] => { const items: MentionItem[] = []; - // Add "goose" as a special mention for AI reinitialization - const gooseScore = fuzzyMatch(query, 'goose'); - if (gooseScore > 0 || !query.trim()) { - items.push({ - id: 'goose', - type: 'friend', // Use friend type for consistent styling - name: 'goose', - displayText: 'goose', - secondaryText: 'Reinitialize AI assistance', - userId: 'goose', - matchScore: gooseScore + 100, // Highest priority for goose - }); - } + // Add "goose" commands as special mentions for AI control + const gooseCommands = [ + { + command: 'goose', + description: 'Enable AI assistance', + emoji: '🦆' + }, + { + command: 'goose off', + description: 'Disable AI assistance', + emoji: '🦆💤' + }, + { + command: 'goose stop', + description: 'Stop AI assistance', + emoji: '🦆🛑' + }, + { + command: 'goose quiet', + description: 'Make AI quiet', + emoji: '🦆🤫' + } + ]; + + gooseCommands.forEach(({ command, description, emoji }) => { + const score = fuzzyMatch(query, command); + if (score > 0 || !query.trim()) { + items.push({ + id: command, + type: 'friend', // Use friend type for consistent styling + name: command, + displayText: command, + secondaryText: description, + userId: command, + matchScore: score + 100, // Highest priority for goose commands + }); + } + }); // Add friends (prioritize if connected) if (isConnected && friends.length > 0) { @@ -251,9 +276,12 @@ const EnhancedMentionPopover = forwardRef< {/* Icon */}
{item.type === 'friend' ? ( - item.userId === 'goose' ? ( + item.userId?.startsWith('goose') ? (
- 🦆 + + {item.userId === 'goose' ? '🦆' : + item.userId.includes('off') || item.userId.includes('stop') || item.userId.includes('quiet') ? '🦆💤' : '🦆'} +
) : (
@@ -286,11 +314,11 @@ const EnhancedMentionPopover = forwardRef<
- {item.userId === 'goose' ? 'Mention' : 'Invite'} + {item.userId?.startsWith('goose') ? 'Mention' : 'Invite'}
)}
diff --git a/ui/desktop/src/hooks/useChatEngine.ts b/ui/desktop/src/hooks/useChatEngine.ts index dd30a2a868..56edb3c5cc 100644 --- a/ui/desktop/src/hooks/useChatEngine.ts +++ b/ui/desktop/src/hooks/useChatEngine.ts @@ -185,8 +185,33 @@ export const useChatEngine = ({ : ''; const containsGooseMention = /@goose\b/i.test(messageText); - // If @goose is mentioned, enable AI for this session - if (containsGooseMention && !aiEnabled) { + // Check for @goose off/disable/stop commands + const gooseOffPattern = /@goose\s+(off|disable|stop|quiet|sleep)\b/i; + const isGooseOffCommand = gooseOffPattern.test(messageText); + + // If @goose off is mentioned, disable AI for this session + if (isGooseOffCommand && aiEnabled) { + console.log('🦆💤 @goose off mentioned - disabling AI for session:', { + sessionId: chat.sessionId, + messageId: message.id, + contentPreview: messageText.substring(0, 50) + '...' + }); + + // Update the chat to disable AI + setChat((prevChat: ChatType) => ({ ...prevChat, aiEnabled: false })); + + // Add the message to the chat without triggering AI response + setMessages(prevMessages => [...prevMessages, message]); + + // Store in history if it's a user message + storeMessageInHistory(message); + + // Return a promise that resolves immediately (to match originalAppend's interface) + return Promise.resolve(); + } + + // If @goose is mentioned (but not an off command), enable AI for this session + if (containsGooseMention && !isGooseOffCommand && !aiEnabled) { console.log('🦆 @goose mentioned - enabling AI for session:', { sessionId: chat.sessionId, messageId: message.id,