Skip to content

Commit b75e0ad

Browse files
committed
Fix: Add google search function
1 parent 9f3bf87 commit b75e0ad

File tree

8 files changed

+88
-23
lines changed

8 files changed

+88
-23
lines changed

src/App.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,24 @@ function App() {
4646
return () => {};
4747
}, []);
4848

49+
// Handle link clicks
50+
useEffect(() => {
51+
const handleLinkClick = (e: MouseEvent) => {
52+
const target = (e.target as HTMLElement).closest('a');
53+
if (target && target.href && target.target !== '_self') {
54+
e.preventDefault();
55+
window.electron.openUrl(target.href);
56+
}
57+
};
58+
59+
document.addEventListener('click', handleLinkClick);
60+
61+
return () => {
62+
document.removeEventListener('click', handleLinkClick);
63+
};
64+
}, []);
65+
66+
4967
return (
5068
<DatabaseInitializer>
5169
<MainLayout>

src/components/chat/ChatMessageArea.tsx

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import MessageToolboxMenu, { ToolboxAction } from '../ui/MessageToolboxMenu';
66
import { MessageHelper } from '../../services/message-helper';
77
import { DatabaseIntegrationService } from '../../services/database-integration';
88
import { SettingsService } from '../../services/settings-service';
9+
import { ChatService } from '../../services/chat-service';
10+
import { AIServiceCapability } from '../../services/core/capabilities';
911

1012
interface ChatMessageAreaProps {
1113
activeConversation: Conversation | null;
@@ -182,6 +184,10 @@ export const ChatMessageArea: React.FC<ChatMessageAreaProps> = ({
182184
setWebSearchActive(!webSearchActive);
183185
SettingsService.getInstance().setWebSearchEnabled(!webSearchActive);
184186
}
187+
188+
const getWebSearchAllowed = () => {
189+
return ChatService.getInstance().getCurrentProviderModelCapabilities().includes(AIServiceCapability.WebSearch);
190+
}
185191

186192
// If no active conversation is selected
187193
if (!activeConversation) {
@@ -344,18 +350,34 @@ export const ChatMessageArea: React.FC<ChatMessageAreaProps> = ({
344350
/>
345351
</div>
346352

347-
<div className="flex flex-row items-center justify-between">
348-
<button
349-
type="button"
350-
onClick={handleToggleWebSearch}
351-
className={`flex items-center justify-center w-fit h-8 p-2 ml-2 transition-all duration-200 rounded-full outline outline-2 hover:outline
352-
${webSearchActive ? 'bg-blue-50 outline-blue-300 hover:bg-blue-200 hover:outline hover:outline-blue-500' : 'bg-white outline-gray-100 hover:bg-blue-50 hover:outline hover:outline-blue-300'}`}
353-
aria-label="Toggle Web Search"
354-
title="Toggle Web Search"
355-
>
356-
<Globe className={`mr-1 ${webSearchActive ? 'text-blue-500' : 'text-gray-400'} transition-all duration-200`} size={20} />
357-
<span className={`text-sm font-light ${webSearchActive ? 'text-blue-500' : 'text-gray-400'} transition-all duration-200`}>Web Search</span>
358-
</button>
353+
<div className="flex flex-row items-center justify-between px-2">
354+
{
355+
getWebSearchAllowed() ? (
356+
<button
357+
type="button"
358+
onClick={handleToggleWebSearch}
359+
className={`flex items-center justify-center w-fit h-8 p-2 transition-all duration-200 rounded-full outline outline-2 hover:outline
360+
${webSearchActive ? 'bg-blue-50 outline-blue-300 hover:bg-blue-200 hover:outline hover:outline-blue-500' : 'bg-white outline-gray-100 hover:bg-blue-50 hover:outline hover:outline-blue-300'}`}
361+
aria-label="Toggle Web Search"
362+
title="Toggle Web Search"
363+
>
364+
<Globe className={`mr-1 ${webSearchActive ? 'text-blue-500' : 'text-gray-400'} transition-all duration-200`} size={20} />
365+
<span className={`text-sm font-light ${webSearchActive ? 'text-blue-500' : 'text-gray-400'} transition-all duration-200`}>Web Search</span>
366+
</button>
367+
)
368+
:
369+
(
370+
<button
371+
type="button"
372+
className={`flex items-center justify-center bg-gray-100 w-fit h-8 p-2 ml-2 transition-all duration-200 rounded-full cursor-not-allowed`}
373+
aria-label="Toggle Web Search"
374+
title="Toggle Web Search"
375+
>
376+
<Globe className={`mr-1 text-gray-400 transition-all duration-200`} size={20} />
377+
<span className={`text-sm font-light text-gray-400 transition-all duration-200`}>Web Search (Not available)</span>
378+
</button>
379+
)
380+
}
359381

360382
{isCurrentlyStreaming || hasStreamingMessage ? (
361383
<button

src/pages/ChatPage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import ChatMessageArea from '../components/chat/ChatMessageArea';
44
import { Conversation } from '../types/chat';
55
import { SettingsService } from '../services/settings-service';
66
import { ChatService } from '../services/chat-service';
7-
7+
import { AIService } from '../services/ai-service';
88
interface ChatPageProps {
99
initialSelectedModel?: string;
1010
apiKey?: string;
@@ -32,7 +32,7 @@ export const ChatPage: React.FC<ChatPageProps> = ({
3232
chatServiceRef.current = chatService;
3333

3434
// Setup AI service state listener
35-
const aiService = chatService.getAIService();
35+
const aiService = AIService.getInstance();
3636
const unsubscribe = aiService.subscribe(() => {
3737
setIsLoading(aiService.isLoading);
3838
setError(aiService.error);

src/services/ai-service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export class AIService {
7474

7575
// console.log('Provider: ', provider, ' Provider settings: ', providerSettings);
7676

77-
if (providerSettings && providerSettings.apiKey && providerSettings.apiKey.length > 0) {
77+
if (!this.providers.has(provider) && providerSettings && providerSettings.apiKey && providerSettings.apiKey.length > 0) {
7878
const providerInstance = ProviderFactory.getNewProvider(provider as AIProvider);
7979
if (providerInstance) {
8080
this.providers.set(provider, providerInstance);
@@ -408,6 +408,8 @@ export class AIService {
408408
this.modelCache.clear();
409409
this.lastFetchTime.clear();
410410

411+
this.addProviders();
412+
411413
// Re-fetch all models
412414
await this.getCachedAllModels();
413415
}

src/services/chat-service.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { AIService } from './ai-service';
44
import { SettingsService } from './settings-service';
55
import { StreamControlHandler } from './streaming-control';
66
import { MessageHelper } from './message-helper';
7+
import { AIServiceCapability } from './core/capabilities';
8+
import { AIProvider as AIProviderType } from '../types/ai-providers';
79
/**
810
* Service for managing chat conversations
911
*/
@@ -636,11 +638,18 @@ export class ChatService {
636638
}
637639
}
638640

639-
/**
640-
* Get the AI service
641-
*/
642-
public getAIService(): AIService {
643-
return this.aiService;
641+
getCurrentProviderModelCapabilities(): AIServiceCapability[] {
642+
const settingsService = SettingsService.getInstance();
643+
const provider = settingsService.getSelectedProvider() as AIProviderType;
644+
const model = settingsService.getSelectedModel();
645+
646+
const providerService = AIService.getInstance().getProvider(provider);
647+
648+
if (!providerService) {
649+
return [];
650+
}
651+
652+
return providerService.getModelCapabilities(model);
644653
}
645654

646655
/**

src/services/providers/gemini-service.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { CommonProviderHelper } from './common-provider-service';
66
import { SettingsService } from '../settings-service';
77
import { AIServiceCapability } from '../core/capabilities';
88
import { mapModelCapabilities } from '../core/capabilities';
9+
import { LanguageModel } from 'ai';
910

1011
export const GEMINI_PROVIDER_NAME = 'Gemini';
1112

@@ -118,7 +119,21 @@ export class GeminiService implements AiServiceProvider {
118119
options: CompletionOptions,
119120
streamController: StreamControlHandler
120121
): Promise<Message> {
121-
const modelInstance = this.ProviderInstance.languageModel(options.model);
122+
const isWebSearchActive = SettingsService.getInstance().getWebSearchEnabled();
123+
124+
let modelInstance: LanguageModel;
125+
126+
if (isWebSearchActive) {
127+
modelInstance = this.ProviderInstance.languageModel(options.model, {
128+
useSearchGrounding: true,
129+
});
130+
131+
options.stream = false;
132+
}
133+
else {
134+
modelInstance = this.ProviderInstance.languageModel(options.model);
135+
}
136+
122137
return CommonProviderHelper.getChatCompletionByModel(modelInstance, messages, options, streamController);
123138
}
124139

src/services/providers/openai-service.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,9 @@ export class OpenAIService implements AiServiceProvider {
114114
options: CompletionOptions,
115115
streamController: StreamControlHandler
116116
): Promise<Message> {
117-
console.log("OPEN AI Getting chat completion");
118117
const isWebSearchActive = SettingsService.getInstance().getWebSearchEnabled();
119118

120119
if (isWebSearchActive) {
121-
console.log("Web search is active");
122120
return this.getChatCompletionWithWebSearch(messages, options, streamController);
123121
}
124122

src/types/window.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ interface Window {
1111
usedMemory: number;
1212
cpuUsage: number;
1313
}>;
14+
openUrl: (url: string) => Promise<void>;
1415
};
1516
}

0 commit comments

Comments
 (0)