Skip to content

Commit f109d68

Browse files
authored
More enhancements and big fixes (#20)
- Improved markdown viewer - Added web agent - minor fixes
1 parent ab8c828 commit f109d68

27 files changed

+3003
-380
lines changed

config/gni/devtools_grd_files.gni

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,7 @@ grd_files_bundled_sources = [
665665
"front_end/panels/ai_chat/evaluation/test-cases/research-agent-tests.js",
666666
"front_end/panels/ai_chat/evaluation/test-cases/schema-extractor-tests.js",
667667
"front_end/panels/ai_chat/evaluation/test-cases/streamlined-schema-extractor-tests.js",
668+
"front_end/panels/ai_chat/evaluation/test-cases/web-task-agent-tests.js",
668669
"front_end/panels/ai_chat/evaluation/utils/ErrorHandlingUtils.js",
669670
"front_end/panels/ai_chat/evaluation/utils/EvaluationTypes.js",
670671
"front_end/panels/ai_chat/evaluation/utils/PromptTemplates.js",

front_end/panels/ai_chat/BUILD.gn

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ devtools_module("ai_chat") {
7575
"evaluation/test-cases/streamlined-schema-extractor-tests.ts",
7676
"evaluation/test-cases/research-agent-tests.ts",
7777
"evaluation/test-cases/action-agent-tests.ts",
78+
"evaluation/test-cases/web-task-agent-tests.ts",
7879
"evaluation/runner/EvaluationRunner.ts",
7980
"evaluation/runner/VisionAgentEvaluationRunner.ts",
8081
"common/MarkdownViewerUtil.ts",
@@ -96,6 +97,7 @@ devtools_module("ai_chat") {
9697
"../../models/logs:bundle",
9798
"../../ui/components/helpers:bundle",
9899
"../../ui/components/markdown_view:bundle",
100+
"../../ui/components/snackbars:bundle",
99101
"../../ui/components/text_editor:bundle",
100102
"../../ui/legacy:bundle",
101103
"../../ui/lit:bundle",
@@ -164,6 +166,7 @@ _ai_chat_sources = [
164166
"evaluation/test-cases/streamlined-schema-extractor-tests.ts",
165167
"evaluation/test-cases/research-agent-tests.ts",
166168
"evaluation/test-cases/action-agent-tests.ts",
169+
"evaluation/test-cases/web-task-agent-tests.ts",
167170
"evaluation/runner/EvaluationRunner.ts",
168171
"evaluation/runner/VisionAgentEvaluationRunner.ts",
169172
"common/MarkdownViewerUtil.ts",

front_end/panels/ai_chat/LLM/GroqProvider.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,4 +427,34 @@ export class GroqProvider extends LLMBaseProvider {
427427
};
428428
}
429429
}
430+
431+
/**
432+
* Validate that required credentials are available for Groq
433+
*/
434+
validateCredentials(): {isValid: boolean, message: string, missingItems?: string[]} {
435+
const storageKeys = this.getCredentialStorageKeys();
436+
const apiKey = localStorage.getItem(storageKeys.apiKey!);
437+
438+
if (!apiKey) {
439+
return {
440+
isValid: false,
441+
message: 'Groq API key is required. Please add your API key in Settings.',
442+
missingItems: ['API Key']
443+
};
444+
}
445+
446+
return {
447+
isValid: true,
448+
message: 'Groq credentials are configured correctly.'
449+
};
450+
}
451+
452+
/**
453+
* Get the storage keys this provider uses for credentials
454+
*/
455+
getCredentialStorageKeys(): {apiKey: string} {
456+
return {
457+
apiKey: 'ai_chat_groq_api_key'
458+
};
459+
}
430460
}

front_end/panels/ai_chat/LLM/LLMClient.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,4 +339,43 @@ export class LLMClient {
339339
return provider.testConnection(modelName);
340340
}
341341

342+
/**
343+
* Static method to validate credentials for a specific provider
344+
*/
345+
static validateProviderCredentials(providerType: string): {isValid: boolean, message: string, missingItems?: string[]} {
346+
try {
347+
// Create temporary provider instance for validation (no API key needed for validation)
348+
let provider;
349+
350+
switch (providerType) {
351+
case 'openai':
352+
provider = new OpenAIProvider('');
353+
break;
354+
case 'litellm':
355+
provider = new LiteLLMProvider('', '');
356+
break;
357+
case 'groq':
358+
provider = new GroqProvider('');
359+
break;
360+
case 'openrouter':
361+
provider = new OpenRouterProvider('');
362+
break;
363+
default:
364+
return {
365+
isValid: false,
366+
message: `Unknown provider type: ${providerType}`,
367+
missingItems: ['Valid provider selection']
368+
};
369+
}
370+
371+
return provider.validateCredentials();
372+
} catch (error) {
373+
return {
374+
isValid: false,
375+
message: `Failed to validate ${providerType} credentials: ${error instanceof Error ? error.message : String(error)}`,
376+
missingItems: ['Provider configuration']
377+
};
378+
}
379+
}
380+
342381
}

front_end/panels/ai_chat/LLM/LLMProvider.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ export interface LLMProviderInterface {
4444
* Test connection to a specific model (optional)
4545
*/
4646
testConnection?(modelId: string): Promise<{success: boolean, message: string}>;
47+
48+
/**
49+
* Validate that required credentials are available for this provider
50+
* @returns Object with validation result and user-friendly message
51+
*/
52+
validateCredentials(): {isValid: boolean, message: string, missingItems?: string[]};
53+
54+
/**
55+
* Get the storage keys this provider uses for credentials
56+
* @returns Array of localStorage keys this provider needs
57+
*/
58+
getCredentialStorageKeys(): {apiKey?: string, endpoint?: string, [key: string]: string | undefined};
4759
}
4860

4961
/**
@@ -71,6 +83,10 @@ export abstract class LLMBaseProvider implements LLMProviderInterface {
7183

7284
abstract parseResponse(response: LLMResponse): any;
7385

86+
abstract validateCredentials(): {isValid: boolean, message: string, missingItems?: string[]};
87+
88+
abstract getCredentialStorageKeys(): {apiKey?: string, endpoint?: string, [key: string]: string | undefined};
89+
7490
/**
7591
* Helper method to handle provider-specific errors
7692
*/

front_end/panels/ai_chat/LLM/LiteLLMProvider.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,4 +374,45 @@ export class LiteLLMProvider extends LLMBaseProvider {
374374
};
375375
}
376376
}
377+
378+
/**
379+
* Validate that required credentials are available for LiteLLM
380+
*/
381+
validateCredentials(): {isValid: boolean, message: string, missingItems?: string[]} {
382+
const storageKeys = this.getCredentialStorageKeys();
383+
const endpoint = localStorage.getItem(storageKeys.endpoint!);
384+
const apiKey = localStorage.getItem(storageKeys.apiKey!) || localStorage.getItem('ai_chat_api_key');
385+
386+
const missingItems: string[] = [];
387+
388+
if (!endpoint) {
389+
missingItems.push('Endpoint URL');
390+
}
391+
392+
if (missingItems.length > 0) {
393+
return {
394+
isValid: false,
395+
message: `LiteLLM configuration incomplete. Missing: ${missingItems.join(', ')}. Please configure in Settings.`,
396+
missingItems
397+
};
398+
}
399+
400+
// Note: API key is optional for LiteLLM
401+
return {
402+
isValid: true,
403+
message: apiKey ?
404+
'LiteLLM credentials are configured correctly.' :
405+
'LiteLLM endpoint configured. API key is optional but may be required for some models.'
406+
};
407+
}
408+
409+
/**
410+
* Get the storage keys this provider uses for credentials
411+
*/
412+
getCredentialStorageKeys(): {apiKey: string, endpoint: string} {
413+
return {
414+
apiKey: 'ai_chat_litellm_api_key',
415+
endpoint: 'ai_chat_litellm_endpoint'
416+
};
417+
}
377418
}

front_end/panels/ai_chat/LLM/OpenAIProvider.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,4 +468,34 @@ export class OpenAIProvider extends LLMBaseProvider {
468468
parseResponse(response: LLMResponse): ReturnType<typeof LLMResponseParser.parseResponse> {
469469
return LLMResponseParser.parseResponse(response);
470470
}
471+
472+
/**
473+
* Validate that required credentials are available for OpenAI
474+
*/
475+
validateCredentials(): {isValid: boolean, message: string, missingItems?: string[]} {
476+
const storageKeys = this.getCredentialStorageKeys();
477+
const apiKey = localStorage.getItem(storageKeys.apiKey!);
478+
479+
if (!apiKey) {
480+
return {
481+
isValid: false,
482+
message: 'OpenAI API key is required. Please add your API key in Settings.',
483+
missingItems: ['API Key']
484+
};
485+
}
486+
487+
return {
488+
isValid: true,
489+
message: 'OpenAI credentials are configured correctly.'
490+
};
491+
}
492+
493+
/**
494+
* Get the storage keys this provider uses for credentials
495+
*/
496+
getCredentialStorageKeys(): {apiKey: string} {
497+
return {
498+
apiKey: 'ai_chat_api_key'
499+
};
500+
}
471501
}

front_end/panels/ai_chat/LLM/OpenRouterProvider.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,4 +480,34 @@ export class OpenRouterProvider extends LLMBaseProvider {
480480
};
481481
}
482482
}
483+
484+
/**
485+
* Validate that required credentials are available for OpenRouter
486+
*/
487+
validateCredentials(): {isValid: boolean, message: string, missingItems?: string[]} {
488+
const storageKeys = this.getCredentialStorageKeys();
489+
const apiKey = localStorage.getItem(storageKeys.apiKey!);
490+
491+
if (!apiKey) {
492+
return {
493+
isValid: false,
494+
message: 'OpenRouter API key is required. Please add your API key in Settings.',
495+
missingItems: ['API Key']
496+
};
497+
}
498+
499+
return {
500+
isValid: true,
501+
message: 'OpenRouter credentials are configured correctly.'
502+
};
503+
}
504+
505+
/**
506+
* Get the storage keys this provider uses for credentials
507+
*/
508+
getCredentialStorageKeys(): {apiKey: string} {
509+
return {
510+
apiKey: 'ai_chat_openrouter_api_key'
511+
};
512+
}
483513
}

0 commit comments

Comments
 (0)