From bfebf0fb813cfe69e03c1c0f6371136b79ae6004 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Mon, 6 Jul 2026 10:06:54 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=B7=20chore:=20Expose=20Retain=20Recen?= =?UTF-8?q?t=20Summarization=20Config=20(#14134)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__tests__/run-summarization.test.ts | 2 ++ packages/api/src/agents/run.ts | 1 + .../specs/config-schemas.spec.ts | 30 +++++++++++++++++++ packages/data-provider/src/config.ts | 6 ++++ 4 files changed, 39 insertions(+) diff --git a/packages/api/src/agents/__tests__/run-summarization.test.ts b/packages/api/src/agents/__tests__/run-summarization.test.ts index d67d904b58..ffb16cbbcf 100644 --- a/packages/api/src/agents/__tests__/run-summarization.test.ts +++ b/packages/api/src/agents/__tests__/run-summarization.test.ts @@ -398,6 +398,7 @@ describe('summarizationConfig field passthrough', () => { updatePrompt: 'Update the existing summary with new messages', reserveRatio: 0.1, maxSummaryTokens: 4096, + retainRecent: { turns: 5, tokens: 40000 }, }, }); const config = agents[0].summarizationConfig as Record; @@ -413,6 +414,7 @@ describe('summarizationConfig field passthrough', () => { expect(config.updatePrompt).toBe('Update the existing summary with new messages'); expect(config.reserveRatio).toBe(0.1); expect(config.maxSummaryTokens).toBe(4096); + expect(config.retainRecent).toEqual({ turns: 5, tokens: 40000 }); }); it('uses self-summarize default when no config provided', async () => { diff --git a/packages/api/src/agents/run.ts b/packages/api/src/agents/run.ts index 0379fa1b85..f39a8479de 100644 --- a/packages/api/src/agents/run.ts +++ b/packages/api/src/agents/run.ts @@ -633,6 +633,7 @@ function shapeSummarizationConfig( updatePrompt: config?.updatePrompt, reserveRatio: config?.reserveRatio, maxSummaryTokens: config?.maxSummaryTokens, + retainRecent: config?.retainRecent, } satisfies AgentSummarizationConfig, contextPruning: config?.contextPruning as ContextPruningConfig | undefined, reserveRatio: config?.reserveRatio, diff --git a/packages/data-provider/specs/config-schemas.spec.ts b/packages/data-provider/specs/config-schemas.spec.ts index 96915b604d..19b9677b25 100644 --- a/packages/data-provider/specs/config-schemas.spec.ts +++ b/packages/data-provider/specs/config-schemas.spec.ts @@ -11,6 +11,7 @@ import { SKILL_SYNC_MAX_INTERVAL_MINUTES, summarizationTriggerSchema, summarizationConfigSchema, + retainRecentConfigSchema, MAX_SUBAGENTS, } from '../src/config'; import { @@ -1113,6 +1114,35 @@ describe('summarizationTriggerSchema', () => { }); }); +describe('retainRecentConfigSchema', () => { + it('accepts turn and token retention limits', () => { + const result = retainRecentConfigSchema.safeParse({ + turns: 5, + tokens: 40000, + }); + + expect(result.success).toBe(true); + }); + + it('rejects invalid turn and token retention limits', () => { + expect(retainRecentConfigSchema.safeParse({ turns: -1 }).success).toBe(false); + expect(retainRecentConfigSchema.safeParse({ turns: 21 }).success).toBe(false); + expect(retainRecentConfigSchema.safeParse({ tokens: 0 }).success).toBe(false); + }); + + it('parses inside the full summarization config', () => { + const result = summarizationConfigSchema.safeParse({ + enabled: true, + retainRecent: { turns: 5, tokens: 40000 }, + }); + + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.retainRecent).toEqual({ turns: 5, tokens: 40000 }); + } + }); +}); + describe('specsConfigSchema', () => { it('accepts an empty list (defaults applied)', () => { const result = specsConfigSchema.safeParse({ list: [] }); diff --git a/packages/data-provider/src/config.ts b/packages/data-provider/src/config.ts index 09ddd28d8f..f130e465c6 100644 --- a/packages/data-provider/src/config.ts +++ b/packages/data-provider/src/config.ts @@ -1781,6 +1781,11 @@ export const contextPruningSchema = z.object({ minPrunableToolChars: z.number().min(0).optional(), }); +export const retainRecentConfigSchema = z.object({ + turns: z.number().min(0).max(20).optional(), + tokens: z.number().positive().optional(), +}); + export const summarizationConfigSchema = z.object({ enabled: z.boolean().optional(), provider: z.string().optional(), @@ -1792,6 +1797,7 @@ export const summarizationConfigSchema = z.object({ reserveRatio: z.number().min(0).max(1).optional(), maxSummaryTokens: z.number().positive().optional(), contextPruning: contextPruningSchema.optional(), + retainRecent: retainRecentConfigSchema.optional(), }); export type SummarizationConfig = z.infer;