From e50bf6adad27777c449e8bfdfcdbc807926b428c Mon Sep 17 00:00:00 2001 From: joshualitt Date: Mon, 24 Nov 2025 12:24:45 -0800 Subject: [PATCH] feat(core): Migrate chatCompressionService to model configs. (#12863) --- docs/get-started/configuration.md | 20 +++++ .../core/src/config/defaultModelConfigs.ts | 20 +++++ .../services/chatCompressionService.test.ts | 75 +++++++++++-------- .../src/services/chatCompressionService.ts | 55 +++++++++----- .../test-data/resolved-aliases.golden.json | 16 ++++ schemas/settings.schema.json | 44 ++++++++++- 6 files changed, 177 insertions(+), 53 deletions(-) diff --git a/docs/get-started/configuration.md b/docs/get-started/configuration.md index a7a7213df2..e157f8ee6f 100644 --- a/docs/get-started/configuration.md +++ b/docs/get-started/configuration.md @@ -490,6 +490,26 @@ their corresponding top-level category object in your `settings.json` file. "next-speaker-checker": { "extends": "gemini-2.5-flash-base", "modelConfig": {} + }, + "chat-compression-3-pro": { + "modelConfig": { + "model": "gemini-3-pro-preview" + } + }, + "chat-compression-2.5-pro": { + "modelConfig": { + "model": "gemini-2.5-pro" + } + }, + "chat-compression-2.5-flash": { + "modelConfig": { + "model": "gemini-2.5-flash" + } + }, + "chat-compression-2.5-flash-lite": { + "modelConfig": { + "model": "gemini-2.5-flash-lite" + } } } ``` diff --git a/packages/core/src/config/defaultModelConfigs.ts b/packages/core/src/config/defaultModelConfigs.ts index 91ab827205..24fa8af79a 100644 --- a/packages/core/src/config/defaultModelConfigs.ts +++ b/packages/core/src/config/defaultModelConfigs.ts @@ -183,5 +183,25 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { extends: 'gemini-2.5-flash-base', modelConfig: {}, }, + 'chat-compression-3-pro': { + modelConfig: { + model: 'gemini-3-pro-preview', + }, + }, + 'chat-compression-2.5-pro': { + modelConfig: { + model: 'gemini-2.5-pro', + }, + }, + 'chat-compression-2.5-flash': { + modelConfig: { + model: 'gemini-2.5-flash', + }, + }, + 'chat-compression-2.5-flash-lite': { + modelConfig: { + model: 'gemini-2.5-flash-lite', + }, + }, }, }; diff --git a/packages/core/src/services/chatCompressionService.test.ts b/packages/core/src/services/chatCompressionService.test.ts index f4472f2301..f7d9193844 100644 --- a/packages/core/src/services/chatCompressionService.test.ts +++ b/packages/core/src/services/chatCompressionService.test.ts @@ -8,6 +8,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { ChatCompressionService, findCompressSplitPoint, + modelStringToModelConfigAlias, } from './chatCompressionService.js'; import type { Content, GenerateContentResponse } from '@google/genai'; import { CompressionStatus } from '../core/turn.js'; @@ -15,7 +16,7 @@ import { tokenLimit } from '../core/tokenLimits.js'; import type { GeminiChat } from '../core/geminiChat.js'; import type { Config } from '../config/config.js'; import { getInitialChatHistory } from '../utils/environmentContext.js'; -import type { ContentGenerator } from '../core/contentGenerator.js'; +import { DEFAULT_GEMINI_MODEL } from '../config/models.js'; vi.mock('../core/tokenLimits.js'); vi.mock('../telemetry/loggers.js'); @@ -101,11 +102,34 @@ describe('findCompressSplitPoint', () => { }); }); +describe('modelStringToModelConfigAlias', () => { + it('should return the default model for unexpected aliases', () => { + expect(modelStringToModelConfigAlias('gemini-flash-flash')).toBe( + DEFAULT_GEMINI_MODEL, + ); + }); + + it('should handle valid names', () => { + expect(modelStringToModelConfigAlias('gemini-3-pro-preview')).toBe( + 'chat-compression-3-pro', + ); + expect(modelStringToModelConfigAlias('gemini-2.5-pro')).toBe( + 'chat-compression-2.5-pro', + ); + expect(modelStringToModelConfigAlias('gemini-2.5-flash')).toBe( + 'chat-compression-2.5-flash', + ); + expect(modelStringToModelConfigAlias('gemini-2.5-flash-lite')).toBe( + 'chat-compression-2.5-flash-lite', + ); + }); +}); + describe('ChatCompressionService', () => { let service: ChatCompressionService; let mockChat: GeminiChat; let mockConfig: Config; - const mockModel = 'gemini-pro'; + const mockModel = 'gemini-2.5-pro'; const mockPromptId = 'test-prompt-id'; beforeEach(() => { @@ -114,9 +138,22 @@ describe('ChatCompressionService', () => { getHistory: vi.fn(), getLastPromptTokenCount: vi.fn().mockReturnValue(500), } as unknown as GeminiChat; + + const mockGenerateContent = vi.fn().mockResolvedValue({ + candidates: [ + { + content: { + parts: [{ text: 'Summary' }], + }, + }, + ], + } as unknown as GenerateContentResponse); + mockConfig = { getCompressionThreshold: vi.fn(), - getContentGenerator: vi.fn(), + getBaseLlmClient: vi.fn().mockReturnValue({ + generateContent: mockGenerateContent, + }), isInteractive: vi.fn().mockReturnValue(false), } as unknown as Config; @@ -190,18 +227,6 @@ describe('ChatCompressionService', () => { vi.mocked(mockChat.getHistory).mockReturnValue(history); vi.mocked(mockChat.getLastPromptTokenCount).mockReturnValue(800); vi.mocked(tokenLimit).mockReturnValue(1000); - const mockGenerateContent = vi.fn().mockResolvedValue({ - candidates: [ - { - content: { - parts: [{ text: 'Summary' }], - }, - }, - ], - } as unknown as GenerateContentResponse); - vi.mocked(mockConfig.getContentGenerator).mockReturnValue({ - generateContent: mockGenerateContent, - } as unknown as ContentGenerator); const result = await service.compress( mockChat, @@ -215,7 +240,7 @@ describe('ChatCompressionService', () => { expect(result.info.compressionStatus).toBe(CompressionStatus.COMPRESSED); expect(result.newHistory).not.toBeNull(); expect(result.newHistory![0].parts![0].text).toBe('Summary'); - expect(mockGenerateContent).toHaveBeenCalled(); + expect(mockConfig.getBaseLlmClient().generateContent).toHaveBeenCalled(); }); it('should force compress even if under threshold', async () => { @@ -229,19 +254,6 @@ describe('ChatCompressionService', () => { vi.mocked(mockChat.getLastPromptTokenCount).mockReturnValue(100); vi.mocked(tokenLimit).mockReturnValue(1000); - const mockGenerateContent = vi.fn().mockResolvedValue({ - candidates: [ - { - content: { - parts: [{ text: 'Summary' }], - }, - }, - ], - } as unknown as GenerateContentResponse); - vi.mocked(mockConfig.getContentGenerator).mockReturnValue({ - generateContent: mockGenerateContent, - } as unknown as ContentGenerator); - const result = await service.compress( mockChat, mockPromptId, @@ -265,7 +277,7 @@ describe('ChatCompressionService', () => { vi.mocked(tokenLimit).mockReturnValue(1000); const longSummary = 'a'.repeat(1000); // Long summary to inflate token count - const mockGenerateContent = vi.fn().mockResolvedValue({ + vi.mocked(mockConfig.getBaseLlmClient().generateContent).mockResolvedValue({ candidates: [ { content: { @@ -274,9 +286,6 @@ describe('ChatCompressionService', () => { }, ], } as unknown as GenerateContentResponse); - vi.mocked(mockConfig.getContentGenerator).mockReturnValue({ - generateContent: mockGenerateContent, - } as unknown as ContentGenerator); const result = await service.compress( mockChat, diff --git a/packages/core/src/services/chatCompressionService.ts b/packages/core/src/services/chatCompressionService.ts index 1c7868f8b3..004704d25f 100644 --- a/packages/core/src/services/chatCompressionService.ts +++ b/packages/core/src/services/chatCompressionService.ts @@ -14,6 +14,12 @@ import { getResponseText } from '../utils/partUtils.js'; import { logChatCompression } from '../telemetry/loggers.js'; import { makeChatCompressionEvent } from '../telemetry/types.js'; import { getInitialChatHistory } from '../utils/environmentContext.js'; +import { + DEFAULT_GEMINI_FLASH_LITE_MODEL, + DEFAULT_GEMINI_FLASH_MODEL, + DEFAULT_GEMINI_MODEL, + PREVIEW_GEMINI_MODEL, +} from '../config/models.js'; /** * Default threshold for compression token count as a fraction of the model's @@ -75,6 +81,21 @@ export function findCompressSplitPoint( return lastSplitPoint; } +export function modelStringToModelConfigAlias(model: string): string { + switch (model) { + case PREVIEW_GEMINI_MODEL: + return 'chat-compression-3-pro'; + case DEFAULT_GEMINI_MODEL: + return 'chat-compression-2.5-pro'; + case DEFAULT_GEMINI_FLASH_MODEL: + return 'chat-compression-2.5-flash'; + case DEFAULT_GEMINI_FLASH_LITE_MODEL: + return 'chat-compression-2.5-flash-lite'; + default: + return DEFAULT_GEMINI_MODEL; + } +} + export class ChatCompressionService { async compress( chat: GeminiChat, @@ -139,26 +160,24 @@ export class ChatCompressionService { }; } - const summaryResponse = await config.getContentGenerator().generateContent( - { - model, - contents: [ - ...historyToCompress, - { - role: 'user', - parts: [ - { - text: 'First, reason in your scratchpad. Then, generate the .', - }, - ], - }, - ], - config: { - systemInstruction: { text: getCompressionPrompt() }, + const summaryResponse = await config.getBaseLlmClient().generateContent({ + modelConfigKey: { model: modelStringToModelConfigAlias(model) }, + contents: [ + ...historyToCompress, + { + role: 'user', + parts: [ + { + text: 'First, reason in your scratchpad. Then, generate the .', + }, + ], }, - }, + ], + systemInstruction: { text: getCompressionPrompt() }, promptId, - ); + // TODO(joshualitt): wire up a sensible abort signal, + abortSignal: new AbortController().signal, + }); const summary = getResponseText(summaryResponse) ?? ''; const extraHistory: Content[] = [ diff --git a/packages/core/src/services/test-data/resolved-aliases.golden.json b/packages/core/src/services/test-data/resolved-aliases.golden.json index 984f3330d1..d098638b4a 100644 --- a/packages/core/src/services/test-data/resolved-aliases.golden.json +++ b/packages/core/src/services/test-data/resolved-aliases.golden.json @@ -198,5 +198,21 @@ "temperature": 0, "topP": 1 } + }, + "chat-compression-3-pro": { + "model": "gemini-3-pro-preview", + "generateContentConfig": {} + }, + "chat-compression-2.5-pro": { + "model": "gemini-2.5-pro", + "generateContentConfig": {} + }, + "chat-compression-2.5-flash": { + "model": "gemini-2.5-flash", + "generateContentConfig": {} + }, + "chat-compression-2.5-flash-lite": { + "model": "gemini-2.5-flash-lite", + "generateContentConfig": {} } } diff --git a/schemas/settings.schema.json b/schemas/settings.schema.json index 8f2f74f7f5..31913b7f59 100644 --- a/schemas/settings.schema.json +++ b/schemas/settings.schema.json @@ -436,7 +436,7 @@ "modelConfigs": { "title": "Model Configs", "description": "Model configurations.", - "markdownDescription": "Model configurations.\n\n- Category: `Model`\n- Requires restart: `no`\n- Default: `{\n \"aliases\": {\n \"base\": {\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"temperature\": 0,\n \"topP\": 1\n }\n }\n },\n \"chat-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"includeThoughts\": true\n },\n \"temperature\": 1,\n \"topP\": 0.95,\n \"topK\": 64\n }\n }\n },\n \"chat-base-2.5\": {\n \"extends\": \"chat-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 8192\n }\n }\n }\n },\n \"chat-base-3\": {\n \"extends\": \"chat-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingLevel\": \"HIGH\"\n }\n }\n }\n },\n \"gemini-3-pro-preview\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n },\n \"gemini-2.5-pro\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"gemini-2.5-flash\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"gemini-2.5-flash-lite\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\"\n }\n },\n \"gemini-2.5-flash-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"classifier\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 1024,\n \"thinkingConfig\": {\n \"thinkingBudget\": 512\n }\n }\n }\n },\n \"prompt-completion\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"temperature\": 0.3,\n \"maxOutputTokens\": 16000,\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"edit-corrector\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"summarizer-default\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"summarizer-shell\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"web-search\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"tools\": [\n {\n \"googleSearch\": {}\n }\n ]\n }\n }\n },\n \"web-fetch\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"tools\": [\n {\n \"urlContext\": {}\n }\n ]\n }\n }\n },\n \"web-fetch-fallback\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"loop-detection\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"loop-detection-double-check\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"llm-edit-fixer\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"next-speaker-checker\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n }\n }\n}`", + "markdownDescription": "Model configurations.\n\n- Category: `Model`\n- Requires restart: `no`\n- Default: `{\n \"aliases\": {\n \"base\": {\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"temperature\": 0,\n \"topP\": 1\n }\n }\n },\n \"chat-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"includeThoughts\": true\n },\n \"temperature\": 1,\n \"topP\": 0.95,\n \"topK\": 64\n }\n }\n },\n \"chat-base-2.5\": {\n \"extends\": \"chat-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 8192\n }\n }\n }\n },\n \"chat-base-3\": {\n \"extends\": \"chat-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingLevel\": \"HIGH\"\n }\n }\n }\n },\n \"gemini-3-pro-preview\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n },\n \"gemini-2.5-pro\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"gemini-2.5-flash\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"gemini-2.5-flash-lite\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\"\n }\n },\n \"gemini-2.5-flash-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"classifier\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 1024,\n \"thinkingConfig\": {\n \"thinkingBudget\": 512\n }\n }\n }\n },\n \"prompt-completion\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"temperature\": 0.3,\n \"maxOutputTokens\": 16000,\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"edit-corrector\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"summarizer-default\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"summarizer-shell\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"web-search\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"tools\": [\n {\n \"googleSearch\": {}\n }\n ]\n }\n }\n },\n \"web-fetch\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"tools\": [\n {\n \"urlContext\": {}\n }\n ]\n }\n }\n },\n \"web-fetch-fallback\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"loop-detection\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"loop-detection-double-check\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"llm-edit-fixer\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"next-speaker-checker\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"chat-compression-3-pro\": {\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n },\n \"chat-compression-2.5-pro\": {\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"chat-compression-2.5-flash\": {\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"chat-compression-2.5-flash-lite\": {\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\"\n }\n }\n }\n}`", "default": { "aliases": { "base": { @@ -609,6 +609,26 @@ "next-speaker-checker": { "extends": "gemini-2.5-flash-base", "modelConfig": {} + }, + "chat-compression-3-pro": { + "modelConfig": { + "model": "gemini-3-pro-preview" + } + }, + "chat-compression-2.5-pro": { + "modelConfig": { + "model": "gemini-2.5-pro" + } + }, + "chat-compression-2.5-flash": { + "modelConfig": { + "model": "gemini-2.5-flash" + } + }, + "chat-compression-2.5-flash-lite": { + "modelConfig": { + "model": "gemini-2.5-flash-lite" + } } } }, @@ -617,7 +637,7 @@ "aliases": { "title": "Model Config Aliases", "description": "Named presets for model configs. Can be used in place of a model name and can inherit from other aliases using an `extends` property.", - "markdownDescription": "Named presets for model configs. Can be used in place of a model name and can inherit from other aliases using an `extends` property.\n\n- Category: `Model`\n- Requires restart: `no`\n- Default: `{\n \"base\": {\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"temperature\": 0,\n \"topP\": 1\n }\n }\n },\n \"chat-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"includeThoughts\": true\n },\n \"temperature\": 1,\n \"topP\": 0.95,\n \"topK\": 64\n }\n }\n },\n \"chat-base-2.5\": {\n \"extends\": \"chat-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 8192\n }\n }\n }\n },\n \"chat-base-3\": {\n \"extends\": \"chat-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingLevel\": \"HIGH\"\n }\n }\n }\n },\n \"gemini-3-pro-preview\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n },\n \"gemini-2.5-pro\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"gemini-2.5-flash\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"gemini-2.5-flash-lite\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\"\n }\n },\n \"gemini-2.5-flash-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"classifier\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 1024,\n \"thinkingConfig\": {\n \"thinkingBudget\": 512\n }\n }\n }\n },\n \"prompt-completion\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"temperature\": 0.3,\n \"maxOutputTokens\": 16000,\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"edit-corrector\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"summarizer-default\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"summarizer-shell\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"web-search\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"tools\": [\n {\n \"googleSearch\": {}\n }\n ]\n }\n }\n },\n \"web-fetch\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"tools\": [\n {\n \"urlContext\": {}\n }\n ]\n }\n }\n },\n \"web-fetch-fallback\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"loop-detection\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"loop-detection-double-check\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"llm-edit-fixer\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"next-speaker-checker\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n }\n}`", + "markdownDescription": "Named presets for model configs. Can be used in place of a model name and can inherit from other aliases using an `extends` property.\n\n- Category: `Model`\n- Requires restart: `no`\n- Default: `{\n \"base\": {\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"temperature\": 0,\n \"topP\": 1\n }\n }\n },\n \"chat-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"includeThoughts\": true\n },\n \"temperature\": 1,\n \"topP\": 0.95,\n \"topK\": 64\n }\n }\n },\n \"chat-base-2.5\": {\n \"extends\": \"chat-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 8192\n }\n }\n }\n },\n \"chat-base-3\": {\n \"extends\": \"chat-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingLevel\": \"HIGH\"\n }\n }\n }\n },\n \"gemini-3-pro-preview\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n },\n \"gemini-2.5-pro\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"gemini-2.5-flash\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"gemini-2.5-flash-lite\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\"\n }\n },\n \"gemini-2.5-flash-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"classifier\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 1024,\n \"thinkingConfig\": {\n \"thinkingBudget\": 512\n }\n }\n }\n },\n \"prompt-completion\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"temperature\": 0.3,\n \"maxOutputTokens\": 16000,\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"edit-corrector\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"summarizer-default\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"summarizer-shell\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"web-search\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"tools\": [\n {\n \"googleSearch\": {}\n }\n ]\n }\n }\n },\n \"web-fetch\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"tools\": [\n {\n \"urlContext\": {}\n }\n ]\n }\n }\n },\n \"web-fetch-fallback\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"loop-detection\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"loop-detection-double-check\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"llm-edit-fixer\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"next-speaker-checker\": {\n \"extends\": \"gemini-2.5-flash-base\",\n \"modelConfig\": {}\n },\n \"chat-compression-3-pro\": {\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n },\n \"chat-compression-2.5-pro\": {\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"chat-compression-2.5-flash\": {\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"chat-compression-2.5-flash-lite\": {\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\"\n }\n }\n}`", "default": { "base": { "modelConfig": { @@ -789,6 +809,26 @@ "next-speaker-checker": { "extends": "gemini-2.5-flash-base", "modelConfig": {} + }, + "chat-compression-3-pro": { + "modelConfig": { + "model": "gemini-3-pro-preview" + } + }, + "chat-compression-2.5-pro": { + "modelConfig": { + "model": "gemini-2.5-pro" + } + }, + "chat-compression-2.5-flash": { + "modelConfig": { + "model": "gemini-2.5-flash" + } + }, + "chat-compression-2.5-flash-lite": { + "modelConfig": { + "model": "gemini-2.5-flash-lite" + } } }, "type": "object",