From 0803007c8f7fd80e945995b27d55f25d18e77e00 Mon Sep 17 00:00:00 2001 From: joshualitt Date: Tue, 5 May 2026 12:32:13 -0700 Subject: [PATCH] fix(core): Minor fixes for generalist profile. (#26357) --- packages/core/src/context/config/profiles.ts | 5 ++-- packages/core/src/context/config/schema.ts | 5 ++++ packages/core/src/context/config/types.ts | 5 ++++ packages/core/src/context/contextManager.ts | 26 ++++++++++++------- .../src/context/utils/snapshotGenerator.ts | 4 +-- packages/core/src/core/client.test.ts | 1 + packages/core/src/core/geminiChat.ts | 5 +++- 7 files changed, 37 insertions(+), 14 deletions(-) diff --git a/packages/core/src/context/config/profiles.ts b/packages/core/src/context/config/profiles.ts index 3948a85f64..446caa2296 100644 --- a/packages/core/src/context/config/profiles.ts +++ b/packages/core/src/context/config/profiles.ts @@ -78,6 +78,7 @@ export const generalistProfile: ContextProfile = { budget: { retainedTokens: 65000, maxTokens: 150000, + coalescingThresholdTokens: 5000, }, }, @@ -117,14 +118,14 @@ export const generalistProfile: ContextProfile = { 'NodeDistillation', env, resolveProcessorOptions(config, 'NodeDistillation', { - nodeThresholdTokens: 1000, + nodeThresholdTokens: 3000, }), ), createNodeTruncationProcessor( 'NodeTruncation', env, resolveProcessorOptions(config, 'NodeTruncation', { - maxTokensPerNode: 1200, + maxTokensPerNode: 4000, }), ), ], diff --git a/packages/core/src/context/config/schema.ts b/packages/core/src/context/config/schema.ts index 823063fb14..69c12ee8ef 100644 --- a/packages/core/src/context/config/schema.ts +++ b/packages/core/src/context/config/schema.ts @@ -42,6 +42,11 @@ export function getContextManagementConfigSchema( description: 'The absolute maximum token count allowed before synchronous truncation kicks in.', }, + coalescingThresholdTokens: { + type: 'number', + description: + 'Only trigger background consolidation (snapshots) when at least this many tokens have aged out. Prevents "turn-by-turn" utility model churn.', + }, }, }, processorOptions: { diff --git a/packages/core/src/context/config/types.ts b/packages/core/src/context/config/types.ts index 4a7bd54264..caa3aecfec 100644 --- a/packages/core/src/context/config/types.ts +++ b/packages/core/src/context/config/types.ts @@ -29,6 +29,11 @@ export interface AsyncPipelineDef { export interface ContextBudget { retainedTokens: number; maxTokens: number; + /** + * Only trigger background consolidation (snapshots) when at least this many + * tokens have aged out. Prevents "turn-by-turn" utility model churn. + */ + coalescingThresholdTokens?: number; } /** diff --git a/packages/core/src/context/contextManager.ts b/packages/core/src/context/contextManager.ts index 3042789242..bc037747ac 100644 --- a/packages/core/src/context/contextManager.ts +++ b/packages/core/src/context/contextManager.ts @@ -141,15 +141,23 @@ export class ContextManager { } if (agedOutNodes.size > 0) { - this.env.tokenCalculator.garbageCollectCache( - new Set(this.buffer.nodes.map((n) => n.id)), - ); - this.eventBus.emitConsolidationNeeded({ - nodes: this.buffer.nodes, - targetDeficit: - currentTokens - this.sidecar.config.budget.retainedTokens, - targetNodeIds: agedOutNodes, - }); + const targetDeficit = + currentTokens - this.sidecar.config.budget.retainedTokens; + + // Respect coalescing threshold for background work + const threshold = + this.sidecar.config.budget.coalescingThresholdTokens || 0; + + if (targetDeficit >= threshold) { + this.env.tokenCalculator.garbageCollectCache( + new Set(this.buffer.nodes.map((n) => n.id)), + ); + this.eventBus.emitConsolidationNeeded({ + nodes: this.buffer.nodes, + targetDeficit, + targetNodeIds: agedOutNodes, + }); + } } } } diff --git a/packages/core/src/context/utils/snapshotGenerator.ts b/packages/core/src/context/utils/snapshotGenerator.ts index 188cbbd79a..03ef665e86 100644 --- a/packages/core/src/context/utils/snapshotGenerator.ts +++ b/packages/core/src/context/utils/snapshotGenerator.ts @@ -17,9 +17,9 @@ export class SnapshotGenerator { const systemPrompt = systemInstruction ?? `You are an expert Context Memory Manager. You will be provided with a raw transcript of older conversation turns between a user and an AI assistant. -Your task is to synthesize these turns into a single, dense, factual snapshot that preserves all critical context, preferences, active tasks, and factual knowledge, but discards conversational filler, pleasantries, and redundant back-and-forth iterations. +Your task is to synthesize these turns into a single, dense, factual snapshot that preserves all critical context, preferences, active tasks, and factual knowledge. -Output ONLY the raw factual snapshot, formatted compactly. Do not include markdown wrappers, prefixes like "Here is the snapshot", or conversational elements.`; +Discard conversational filler, pleasantries, and redundant back-and-forth iterations. Output ONLY the raw factual snapshot, formatted compactly. Do not include markdown wrappers, prefixes like "Here is the snapshot", or conversational elements.`; let userPromptText = 'TRANSCRIPT TO SNAPSHOT:\n\n'; for (const node of nodes) { diff --git a/packages/core/src/core/client.test.ts b/packages/core/src/core/client.test.ts index ece8353b29..535f751ae7 100644 --- a/packages/core/src/core/client.test.ts +++ b/packages/core/src/core/client.test.ts @@ -289,6 +289,7 @@ describe('Gemini Client (client.ts)', () => { resetTurn: vi.fn(), isAutoDistillationEnabled: vi.fn().mockReturnValue(false), + isContextManagementEnabled: vi.fn().mockReturnValue(false), getContextManagementConfig: vi.fn().mockReturnValue({ enabled: false }), getModelAvailabilityService: vi .fn() diff --git a/packages/core/src/core/geminiChat.ts b/packages/core/src/core/geminiChat.ts index 16006ad160..f973988ad1 100644 --- a/packages/core/src/core/geminiChat.ts +++ b/packages/core/src/core/geminiChat.ts @@ -827,7 +827,10 @@ export class GeminiChat { const history = curated ? extractCuratedHistory([...this.agentHistory.get()]) : this.agentHistory.get(); - return [...history]; + + return this.context.config.isContextManagementEnabled() + ? scrubHistory([...history]) + : [...history]; } /**