Skip to content

Commit a3d3ff1

Browse files
committed
more refactor
1 parent 15904b3 commit a3d3ff1

File tree

7 files changed

+108
-53
lines changed

7 files changed

+108
-53
lines changed

front_end/panels/ai_chat/core/AgentService.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import type { TracingProvider, TracingContext } from '../tracing/TracingProvider
1818
import { AgentRunnerEventBus } from '../agent_framework/AgentRunnerEventBus.js';
1919
import { AgentRunner } from '../agent_framework/AgentRunner.js';
2020
import type { AgentSession, AgentMessage } from '../agent_framework/AgentSessionTypes.js';
21-
import { AIChatPanel } from '../ui/AIChatPanel.js';
2221
import type { LLMProvider } from '../LLM/LLMTypes.js';
2322

2423
const logger = createLogger('AgentService');
@@ -166,13 +165,9 @@ export class AgentService extends Common.ObjectWrapper.ObjectWrapper<{
166165
/**
167166
* Initializes the agent with the given API key
168167
*/
169-
async initialize(apiKey: string | null, modelName?: string): Promise<void> {
168+
async initialize(apiKey: string | null, modelName: string, miniModel: string, nanoModel: string): Promise<void> {
170169
try {
171170
this.#apiKey = apiKey;
172-
173-
if (!modelName) {
174-
throw new Error('Model name is required for initialization');
175-
}
176171

177172
// Initialize LLM client first
178173
await this.#initializeLLMClient();
@@ -197,9 +192,7 @@ export class AgentService extends Common.ObjectWrapper.ObjectWrapper<{
197192
// Determine selected provider for primary graph execution
198193
const selectedProvider = (localStorage.getItem('ai_chat_provider') || 'openai') as LLMProvider;
199194

200-
// Get mini and nano models for tool execution
201-
const miniModel = AIChatPanel.getMiniModel();
202-
const nanoModel = AIChatPanel.getNanoModel();
195+
// Mini and nano models are injected by caller (validated upstream)
203196

204197
// Will throw error if model/provider configuration is invalid
205198
this.#graph = createAgentGraph(apiKey, modelName, selectedProvider, miniModel, nanoModel);

front_end/panels/ai_chat/evaluation/framework/judges/LLMEvaluator.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { ErrorHandlingUtils } from '../../utils/ErrorHandlingUtils.js';
99
import { PromptTemplates } from '../../utils/PromptTemplates.js';
1010
import { ResponseParsingUtils } from '../../utils/ResponseParsingUtils.js';
1111
import type { ScreenshotData, VisionMessage, TextContent, ImageContent } from '../../utils/EvaluationTypes.js';
12-
import { AIChatPanel } from '../../../ui/AIChatPanel.js';
1312

1413
const logger = createLogger('LLMEvaluator');
1514

@@ -21,11 +20,10 @@ export class LLMEvaluator {
2120
private apiKey: string;
2221
private defaultModel: string;
2322

24-
constructor(apiKey: string, defaultModel?: string) {
23+
constructor(apiKey: string, defaultModel: string) {
2524
this.apiKey = apiKey;
26-
// Use the provided model, or fall back to saved judge model, or finally to mini model
27-
const JUDGE_MODEL_STORAGE_KEY = 'ai_chat_judge_model';
28-
this.defaultModel = defaultModel || localStorage.getItem(JUDGE_MODEL_STORAGE_KEY) || AIChatPanel.getMiniModel();
25+
// Model must be provided by caller; no fallbacks
26+
this.defaultModel = defaultModel;
2927
}
3028

3129

@@ -89,8 +87,9 @@ export class LLMEvaluator {
8987
for (let attempt = 1; attempt <= maxRetries; attempt++) {
9088
try {
9189
const llm = LLMClient.getInstance();
90+
const provider = await this.#getProviderForModel(model);
9291
const llmResponse = await llm.call({
93-
provider: AIChatPanel.getProviderForModel(model),
92+
provider,
9493
model: model,
9594
messages: [
9695
{ role: 'system', content: PromptTemplates.buildSystemPrompt({ hasVision: false }) },
@@ -124,6 +123,25 @@ export class LLMEvaluator {
124123
throw lastError;
125124
}
126125

126+
/**
127+
* Resolve the provider for a given model using the LLM registry.
128+
* Falls back to the currently selected provider if unknown.
129+
*/
130+
async #getProviderForModel(modelId: string): Promise<'openai' | 'litellm' | 'groq' | 'openrouter'> {
131+
try {
132+
const llm = LLMClient.getInstance();
133+
const models = await llm.getAvailableModels();
134+
const found = models.find(m => m.id === modelId);
135+
if (found) {
136+
return found.provider as any;
137+
}
138+
} catch {
139+
// ignore and fall through to fallback
140+
}
141+
// Fallback: current selection or openai
142+
return (localStorage.getItem('ai_chat_provider') || 'openai') as any;
143+
}
144+
127145
/**
128146
* Vision-enhanced evaluation using multimodal LLM
129147
*/
@@ -342,4 +360,4 @@ export class LLMEvaluator {
342360

343361
return evaluations;
344362
}
345-
}
363+
}

front_end/panels/ai_chat/evaluation/remote/EvaluationAgent.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { createLogger } from '../../core/Logger.js';
1010
import { createTracingProvider, withTracingContext, isTracingEnabled, getTracingConfig } from '../../tracing/TracingConfig.js';
1111
import type { TracingProvider, TracingContext } from '../../tracing/TracingProvider.js';
1212
import type { ChatMessage } from '../../models/ChatTypes.js';
13-
import { AIChatPanel } from '../../ui/AIChatPanel.js';
1413
import {
1514
RegisterMessage,
1615
ReadyMessage,
@@ -40,6 +39,10 @@ export interface EvaluationAgentOptions {
4039
clientId: string;
4140
endpoint: string;
4241
secretKey?: string;
42+
// Explicit models to avoid UI coupling
43+
judgeModel: string;
44+
miniModel: string;
45+
nanoModel: string;
4346
}
4447

4548

@@ -56,11 +59,17 @@ export class EvaluationAgent {
5659
private authResolve: ((value?: void) => void) | null = null;
5760
private authReject: ((reason?: any) => void) | null = null;
5861
private tracingProvider: TracingProvider;
62+
private judgeModel: string;
63+
private miniModel: string;
64+
private nanoModel: string;
5965

6066
constructor(options: EvaluationAgentOptions) {
6167
this.clientId = options.clientId;
6268
this.endpoint = options.endpoint;
6369
this.secretKey = options.secretKey;
70+
this.judgeModel = options.judgeModel;
71+
this.miniModel = options.miniModel;
72+
this.nanoModel = options.nanoModel;
6473
this.tracingProvider = createTracingProvider();
6574

6675
logger.info('EvaluationAgent created with tracing provider', {
@@ -701,21 +710,19 @@ export class EvaluationAgent {
701710
// Get or create AgentService instance
702711
const agentService = AgentService.getInstance();
703712

704-
// Use the current model from localStorage (no override)
705-
let modelName = localStorage.getItem('ai_chat_model_selection');
706-
if (!modelName) {
707-
// Default model
708-
modelName = 'gpt-4o';
709-
}
713+
// Use explicit models from constructor
714+
const modelName = this.judgeModel;
715+
const miniModel = this.miniModel;
716+
const nanoModel = this.nanoModel;
710717

711718
logger.info('Initializing AgentService for chat evaluation', {
712719
modelName,
713720
hasApiKey: !!agentService.getApiKey(),
714721
isInitialized: agentService.isInitialized()
715722
});
716723

717-
// Always reinitialize with the current model
718-
await agentService.initialize(agentService.getApiKey(), modelName);
724+
// Always reinitialize with the current model and explicit mini/nano
725+
await agentService.initialize(agentService.getApiKey(), modelName, miniModel, nanoModel);
719726

720727
// Create a child observation for the chat execution
721728
if (tracingContext) {

front_end/panels/ai_chat/evaluation/runner/EvaluationRunner.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,27 @@ import type { LLMProviderConfig } from '../../LLM/LLMClient.js';
1313
import { TIMING_CONSTANTS } from '../../core/Constants.js';
1414
import { createTracingProvider, isTracingEnabled, getTracingConfig } from '../../tracing/TracingConfig.js';
1515
import type { TracingProvider, TracingContext } from '../../tracing/TracingProvider.js';
16-
import { AIChatPanel } from '../../ui/AIChatPanel.js';
1716

1817
const logger = createLogger('EvaluationRunner');
1918

2019
/**
2120
* Example runner for the evaluation framework
2221
*/
22+
export interface EvaluationRunnerOptions {
23+
judgeModel: string;
24+
mainModel: string;
25+
miniModel: string;
26+
nanoModel: string;
27+
}
28+
2329
export class EvaluationRunner {
2430
private evaluator: GenericToolEvaluator;
2531
private llmEvaluator: LLMEvaluator;
2632
private config: EvaluationConfig;
2733
private tracingProvider: TracingProvider;
2834
private sessionId: string;
2935

30-
constructor(judgeModel?: string) {
36+
constructor(options: EvaluationRunnerOptions) {
3137
// Get API key from AgentService
3238
const agentService = AgentService.getInstance();
3339
const apiKey = agentService.getApiKey();
@@ -36,14 +42,9 @@ export class EvaluationRunner {
3642
throw new Error('API key not configured. Please configure in AI Chat settings.');
3743
}
3844

39-
// Use provided judge model or default
40-
const evaluationModel = judgeModel || 'gpt-4.1-mini';
41-
42-
// Get the actual models configured in the UI for tools and agents
43-
// TODO: Use a more robust method to get these settings
44-
const mainModel = AIChatPanel.instance().getSelectedModel();
45-
const miniModel = AIChatPanel.getMiniModel();
46-
const nanoModel = AIChatPanel.getNanoModel();
45+
// Require explicit models from caller
46+
const { judgeModel, mainModel, miniModel, nanoModel } = options;
47+
const evaluationModel = judgeModel;
4748

4849
this.config = {
4950
extractionModel: evaluationModel,

front_end/panels/ai_chat/evaluation/runner/VisionAgentEvaluationRunner.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { createLogger } from '../../core/Logger.js';
1313
import { TIMING_CONSTANTS } from '../../core/Constants.js';
1414
import { createTracingProvider, isTracingEnabled } from '../../tracing/TracingConfig.js';
1515
import type { TracingProvider, TracingContext } from '../../tracing/TracingProvider.js';
16-
import { AIChatPanel } from '../../ui/AIChatPanel.js';
1716

1817
const logger = createLogger('VisionAgentEvaluationRunner');
1918

@@ -40,6 +39,14 @@ export interface VisionTestCase extends TestCase {
4039
* Unified agent evaluation runner that supports both standard and vision-based evaluation
4140
* This replaces AgentEvaluationRunner when vision capabilities are needed
4241
*/
42+
export interface VisionRunnerOptions {
43+
visionEnabled?: boolean;
44+
judgeModel: string;
45+
mainModel: string;
46+
miniModel: string;
47+
nanoModel: string;
48+
}
49+
4350
export class VisionAgentEvaluationRunner {
4451

4552
private llmEvaluator: LLMEvaluator;
@@ -48,7 +55,7 @@ export class VisionAgentEvaluationRunner {
4855
private globalVisionEnabled: boolean;
4956
private tracingProvider: TracingProvider;
5057

51-
constructor(visionEnabled: boolean = false, judgeModel?: string) {
58+
constructor(options: VisionRunnerOptions) {
5259
// Get API key from AgentService
5360
const agentService = AgentService.getInstance();
5461
const apiKey = agentService.getApiKey();
@@ -57,13 +64,9 @@ export class VisionAgentEvaluationRunner {
5764
throw new Error('API key not configured. Please configure in AI Chat settings.');
5865
}
5966

60-
// Use provided judge model or default
61-
const evaluationModel = judgeModel || 'gpt-4.1-mini';
62-
63-
// Get the actual models configured in the UI for tools and agents
64-
const mainModel = AIChatPanel.instance().getSelectedModel();
65-
const miniModel = AIChatPanel.getMiniModel();
66-
const nanoModel = AIChatPanel.getNanoModel();
67+
// Require explicit models from caller
68+
const { judgeModel, mainModel, miniModel, nanoModel } = options;
69+
const evaluationModel = judgeModel;
6770

6871
this.config = {
6972
extractionModel: evaluationModel,
@@ -82,7 +85,7 @@ export class VisionAgentEvaluationRunner {
8285

8386
this.llmEvaluator = new LLMEvaluator(this.config.evaluationApiKey, this.config.evaluationModel);
8487
this.screenshotTool = new TakeScreenshotTool();
85-
this.globalVisionEnabled = visionEnabled;
88+
this.globalVisionEnabled = Boolean(options.visionEnabled);
8689
this.tracingProvider = createTracingProvider();
8790
}
8891

@@ -467,4 +470,4 @@ export class VisionAgentEvaluationRunner {
467470
this.globalVisionEnabled = enabled;
468471
logger.info(`Global vision mode: ${enabled ? 'ENABLED' : 'DISABLED'}`);
469472
}
470-
}
473+
}

front_end/panels/ai_chat/ui/AIChatPanel.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,7 +1282,10 @@ export class AIChatPanel extends UI.Panel.Panel {
12821282
this.#evaluationAgent = new EvaluationAgent({
12831283
clientId: compositeClientId,
12841284
endpoint: config.endpoint,
1285-
secretKey: config.secretKey
1285+
secretKey: config.secretKey,
1286+
judgeModel: this.#selectedModel,
1287+
miniModel: this.#miniModel,
1288+
nanoModel: this.#nanoModel,
12861289
});
12871290

12881291
await this.#evaluationAgent.connect();
@@ -1351,7 +1354,14 @@ export class AIChatPanel extends UI.Panel.Panel {
13511354

13521355
// Initialize the agent service
13531356
logger.info('Calling agentService.initialize()...');
1354-
this.#agentService.initialize(apiKey, this.#selectedModel)
1357+
const miniForInit = this.#miniModel || this.#selectedModel;
1358+
const nanoForInit = this.#nanoModel || miniForInit;
1359+
this.#agentService.initialize(
1360+
apiKey,
1361+
this.#selectedModel,
1362+
miniForInit,
1363+
nanoForInit,
1364+
)
13551365
.then(() => {
13561366
logger.info('✅ Agent service initialized successfully');
13571367
this.#setCanSendMessagesState(true, "Agent service initialized successfully");

front_end/panels/ai_chat/ui/EvaluationDialog.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,13 +199,25 @@ export class EvaluationDialog {
199199

200200
// Initialize evaluation runners
201201
try {
202-
this.#evaluationRunner = new EvaluationRunner(this.#state.judgeModel);
202+
// Inject current UI-selected models into the runner to decouple from UI internals
203+
this.#evaluationRunner = new EvaluationRunner({
204+
judgeModel: this.#state.judgeModel,
205+
mainModel: AIChatPanel.instance().getSelectedModel(),
206+
miniModel: AIChatPanel.getMiniModel(),
207+
nanoModel: AIChatPanel.getNanoModel(),
208+
});
203209
} catch (error) {
204210
logger.error('Failed to initialize evaluation runner:', error);
205211
}
206212

207213
try {
208-
this.#agentEvaluationRunner = new VisionAgentEvaluationRunner(this.#state.visionEnabled, this.#state.judgeModel);
214+
this.#agentEvaluationRunner = new VisionAgentEvaluationRunner({
215+
visionEnabled: this.#state.visionEnabled,
216+
judgeModel: this.#state.judgeModel,
217+
mainModel: AIChatPanel.instance().getSelectedModel(),
218+
miniModel: AIChatPanel.getMiniModel(),
219+
nanoModel: AIChatPanel.getNanoModel(),
220+
});
209221
} catch (error) {
210222
logger.error('Failed to initialize agent evaluation runner:', error);
211223
}
@@ -885,13 +897,24 @@ export class EvaluationDialog {
885897

886898
// Reinitialize evaluation runners with new model
887899
try {
888-
this.#evaluationRunner = new EvaluationRunner(this.#state.judgeModel);
900+
this.#evaluationRunner = new EvaluationRunner({
901+
judgeModel: this.#state.judgeModel,
902+
mainModel: AIChatPanel.instance().getSelectedModel(),
903+
miniModel: AIChatPanel.getMiniModel(),
904+
nanoModel: AIChatPanel.getNanoModel(),
905+
});
889906
} catch (error) {
890907
logger.error('Failed to reinitialize evaluation runner:', error);
891908
}
892909

893910
try {
894-
this.#agentEvaluationRunner = new VisionAgentEvaluationRunner(this.#state.visionEnabled, this.#state.judgeModel);
911+
this.#agentEvaluationRunner = new VisionAgentEvaluationRunner({
912+
visionEnabled: this.#state.visionEnabled,
913+
judgeModel: this.#state.judgeModel,
914+
mainModel: AIChatPanel.instance().getSelectedModel(),
915+
miniModel: AIChatPanel.getMiniModel(),
916+
nanoModel: AIChatPanel.getNanoModel(),
917+
});
895918
} catch (error) {
896919
logger.error('Failed to reinitialize agent evaluation runner:', error);
897920
}
@@ -1837,4 +1860,4 @@ export class EvaluationDialog {
18371860
}
18381861
}
18391862

1840-
}
1863+
}

0 commit comments

Comments
 (0)