refactor(core): Introduce LlmUtilityService and promptIdContext (#7952)

This commit is contained in:
Abhi
2025-09-09 01:14:15 -04:00
committed by GitHub
parent 471cbcd450
commit 1eaf21f6a2
12 changed files with 943 additions and 165 deletions
+59
View File
@@ -122,6 +122,10 @@ vi.mock('../ide/ide-client.js', () => ({
},
}));
import { BaseLlmClient } from '../core/baseLlmClient.js';
vi.mock('../core/baseLlmClient.js');
describe('Server Config (config.ts)', () => {
const MODEL = 'gemini-pro';
const SANDBOX: SandboxConfig = {
@@ -774,3 +778,58 @@ describe('setApprovalMode with folder trust', () => {
});
});
});
describe('BaseLlmClient Lifecycle', () => {
const MODEL = 'gemini-pro';
const SANDBOX: SandboxConfig = {
command: 'docker',
image: 'gemini-cli-sandbox',
};
const TARGET_DIR = '/path/to/target';
const DEBUG_MODE = false;
const QUESTION = 'test question';
const FULL_CONTEXT = false;
const USER_MEMORY = 'Test User Memory';
const TELEMETRY_SETTINGS = { enabled: false };
const EMBEDDING_MODEL = 'gemini-embedding';
const SESSION_ID = 'test-session-id';
const baseParams: ConfigParameters = {
cwd: '/tmp',
embeddingModel: EMBEDDING_MODEL,
sandbox: SANDBOX,
targetDir: TARGET_DIR,
debugMode: DEBUG_MODE,
question: QUESTION,
fullContext: FULL_CONTEXT,
userMemory: USER_MEMORY,
telemetry: TELEMETRY_SETTINGS,
sessionId: SESSION_ID,
model: MODEL,
usageStatisticsEnabled: false,
};
it('should throw an error if getBaseLlmClient is called before refreshAuth', () => {
const config = new Config(baseParams);
expect(() => config.getBaseLlmClient()).toThrow(
'BaseLlmClient not initialized. Ensure authentication has occurred and ContentGenerator is ready.',
);
});
it('should successfully initialize BaseLlmClient after refreshAuth is called', async () => {
const config = new Config(baseParams);
const authType = AuthType.USE_GEMINI;
const mockContentConfig = { model: 'gemini-flash', apiKey: 'test-key' };
vi.mocked(createContentGeneratorConfig).mockReturnValue(mockContentConfig);
await config.refreshAuth(authType);
// Should not throw
const llmService = config.getBaseLlmClient();
expect(llmService).toBeDefined();
expect(BaseLlmClient).toHaveBeenCalledWith(
config.getContentGenerator(),
config,
);
});
});
+25
View File
@@ -31,6 +31,7 @@ import { ReadManyFilesTool } from '../tools/read-many-files.js';
import { MemoryTool, setGeminiMdFilename } from '../tools/memoryTool.js';
import { WebSearchTool } from '../tools/web-search.js';
import { GeminiClient } from '../core/client.js';
import { BaseLlmClient } from '../core/baseLlmClient.js';
import { FileDiscoveryService } from '../services/fileDiscoveryService.js';
import { GitService } from '../services/gitService.js';
import type { TelemetryTarget } from '../telemetry/index.js';
@@ -257,6 +258,7 @@ export class Config {
private readonly telemetrySettings: TelemetrySettings;
private readonly usageStatisticsEnabled: boolean;
private geminiClient!: GeminiClient;
private baseLlmClient!: BaseLlmClient;
private readonly fileFiltering: {
respectGitIgnore: boolean;
respectGeminiIgnore: boolean;
@@ -455,6 +457,9 @@ export class Config {
// Only assign to instance properties after successful initialization
this.contentGeneratorConfig = newContentGeneratorConfig;
// Initialize BaseLlmClient now that the ContentGenerator is available
this.baseLlmClient = new BaseLlmClient(this.contentGenerator, this);
// Reset the session flag since we're explicitly changing auth and using default model
this.inFallbackMode = false;
}
@@ -463,6 +468,26 @@ export class Config {
return this.contentGenerator?.userTier;
}
/**
* Provides access to the BaseLlmClient for stateless LLM operations.
*/
getBaseLlmClient(): BaseLlmClient {
if (!this.baseLlmClient) {
// Handle cases where initialization might be deferred or authentication failed
if (this.contentGenerator) {
this.baseLlmClient = new BaseLlmClient(
this.getContentGenerator(),
this,
);
} else {
throw new Error(
'BaseLlmClient not initialized. Ensure authentication has occurred and ContentGenerator is ready.',
);
}
}
return this.baseLlmClient;
}
getSessionId(): string {
return this.sessionId;
}