/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { type GenerateContentConfig, type PartListUnion, type Content, GenerateContentResponse, type SendMessageParameters } from '@google/genai'; import { Turn, type ServerGeminiStreamEvent } from './turn.js'; import { Config } from '../config/config.js'; import { UserTierId } from '../code_assist/types.js'; import { GeminiChat } from './geminiChat.js'; import { HistoryService } from '../services/history/HistoryService.js'; import { type ContentGenerator, type ContentGeneratorConfig } from './contentGenerator.js'; import type { AgentRuntimeState } from '../runtime/AgentRuntimeState.js'; import type { IContent } from '../services/history/IContent.js'; export declare function isThinkingSupported(model: string): boolean; /** * Returns the index of the content after the fraction of the total characters in the history. * * Exported for testing purposes. */ export declare function findCompressSplitPoint(contents: Content[], fraction: number): number; export declare class GeminiClient { private readonly config; private chat?; private contentGenerator?; private embeddingModel; private logger; private generateContentConfig; private sessionTurnCount; private readonly MAX_TURNS; private _pendingConfig?; private _previousHistory?; private _storedHistoryService?; private currentSequenceModel; private readonly loopDetector; private lastPromptId?; private readonly complexityAnalyzer; private readonly todoReminderService; private todoToolsAvailable; private lastComplexitySuggestionTime; private readonly complexitySuggestionCooldown; private lastSentIdeContext; private forceFullIdeContext; private lastTodoToolTurn?; private consecutiveComplexTurns; private lastComplexitySuggestionTurn?; private toolActivityCount; private toolCallReminderLevel; private lastTodoSnapshot?; /** * Runtime state for stateless operation (Phase 5) * @plan PLAN-20251027-STATELESS5.P10 * @requirement REQ-STAT5-003.1 * @pseudocode gemini-runtime.md lines 21-42 */ private readonly runtimeState; private _historyService?; private _unsubscribe?; /** * BaseLLMClient for stateless utility operations (generateJson, embeddings, etc.) * Lazily initialized when needed */ private _baseLlmClient?; /** * @plan PLAN-20251027-STATELESS5.P10 * @requirement REQ-STAT5-003.1 * @pseudocode gemini-runtime.md lines 11-66 * * Phase 5 constructor: Accept optional AgentRuntimeState and HistoryService * When provided, client operates in stateless mode using runtime state * Otherwise falls back to Config-based operation (backward compatibility) */ constructor(config: Config, runtimeState: AgentRuntimeState, historyService?: HistoryService); dispose(): void; initialize(contentGeneratorConfig: ContentGeneratorConfig): Promise; private lazyInitialize; getContentGenerator(): ContentGenerator; getUserTier(): UserTierId | undefined; /** * Get or create the BaseLLMClient for stateless utility operations. * This is lazily initialized to avoid creating it when not needed. */ private getBaseLlmClient; private processComplexityAnalysis; private shouldEscalateReminder; private isTodoToolCall; private appendTodoSuffixToRequest; private recordModelActivity; private readTodoSnapshot; private getActiveTodos; private areTodoSnapshotsEqual; private getTodoReminderForCurrentState; private appendSystemReminderToRequest; private shouldDeferStreamEvent; private isTodoPauseResponse; addHistory(content: Content): Promise; updateSystemInstruction(): Promise; /** * Builds the full system instruction by combining environment context with * the core system prompt. Shared by both startChat and * updateSystemInstruction so the prompt is assembled consistently. */ private buildSystemInstruction; getChat(): GeminiChat; /** * Get the HistoryService from the current chat session * @returns The HistoryService instance, or null if chat is not initialized */ getHistoryService(): HistoryService | null; hasChatInitialized(): boolean; isInitialized(): boolean; /** * Extract text from a PartListUnion for hook consumption */ private extractPromptText; getHistory(): Promise; setHistory(history: Content[], { stripThoughts }?: { stripThoughts?: boolean; }): Promise; /** * Store history for later use when the client is initialized. * This is used when resuming a chat before authentication. * The history will be restored when lazyInitialize() is called. */ storeHistoryForLaterUse(history: Content[]): void; /** * Store HistoryService instance for reuse after refreshAuth. * This preserves the UI's conversation display across provider switches. */ storeHistoryServiceForReuse(historyService: HistoryService): void; setTools(): Promise; clearTools(): void; /** * Updates the UI telemetry service with the current prompt token count from chat. * This decouples GeminiChat from directly knowing about uiTelemetryService. */ private updateTelemetryTokenCount; resetChat(): Promise; /** * Restore history from a session by ensuring chat and content generator are fully initialized, * then adding history items to the HistoryService. * * P0 Fix: Synchronously initializes chat/content generator if needed before attempting history restore. * This ensures the history service is available immediately after the call completes. * * @param historyItems Array of IContent items from persisted session * @returns Promise that resolves when history is fully restored and chat is ready * @throws Error if initialization fails (e.g., auth not ready, config missing) */ restoreHistory(historyItems: IContent[]): Promise; getCurrentSequenceModel(): string | null; addDirectoryContext(): Promise; generateDirectMessage(params: SendMessageParameters, promptId: string): Promise; startChat(extraHistory?: Content[]): Promise; private getIdeContextParts; private _getEffectiveModelForCurrentTurn; sendMessageStream(initialRequest: PartListUnion, signal: AbortSignal, prompt_id: string, turns?: number, isInvalidStreamRetry?: boolean): AsyncGenerator; generateJson(contents: Content[], schema: Record, abortSignal: AbortSignal, model: string, config?: GenerateContentConfig): Promise>; generateContent(contents: Content[], generationConfig: GenerateContentConfig, abortSignal: AbortSignal, model: string): Promise; generateEmbedding(texts: string[]): Promise; private getToolGovernanceEphemerals; private readToolList; private buildToolDeclarationsFromView; private getEnabledToolNamesForPrompt; private shouldIncludeSubagentDelegation; private updateTodoToolAvailabilityFromDeclarations; }