fix(compaction): adjust instructions and structure to be more clear to smaller models like dsv4 flash (#42045)

Co-authored-by: akenra <37288280+akenra@users.noreply.github.com>
This commit is contained in:
Aiden Cline
2026-08-12 14:36:51 -05:00
committed by GitHub
parent 39fb919a05
commit dab2637217
8 changed files with 207 additions and 52 deletions
@@ -1,9 +1,5 @@
You are an anchored context summarization assistant for coding sessions.
Summarize only the conversation history you are given. The newest turns may be kept verbatim outside your summary, so focus on the older context that still matters for continuing the work.
If the prompt includes a <previous-summary> block, treat it as the current anchored summary. Update it with the new history by preserving still-true details, removing stale details, and merging in new facts.
You are a context summarization agent. You are given a conversation between a user and an agent. Your goal is to produce a structured summary matching the format specified so another coding agent can continue the work.
Always follow the exact output structure requested by the user prompt. Keep every section, preserve exact file paths and identifiers when known, and prefer terse bullets over paragraphs.
Do not answer the conversation itself. Do not mention that you are summarizing, compacting, or merging context. Respond in the same language as the conversation.
Do not continue the conversation. Do not respond to any questions in the conversation. Only output the structured summary in the exact format requested by the user prompt. Respond in the same language as the conversation.
+24 -17
View File
@@ -29,9 +29,8 @@ export const PRUNE_MINIMUM = 20_000
export const PRUNE_PROTECT = 40_000
const TOOL_OUTPUT_MAX_CHARS = 2_000
const PRUNE_PROTECTED_TOOLS = ["skill"]
const DEFAULT_TAIL_TURNS = 2
const MIN_PRESERVE_RECENT_TOKENS = 2_000
const MAX_PRESERVE_RECENT_TOKENS = 8_000
const MAX_PRESERVE_RECENT_TOKENS = 15_000
type Turn = {
start: number
end: number
@@ -226,27 +225,22 @@ const layer = Layer.effect(
cfg: ConfigV1.Info
model: Provider.Model
}) {
const limit = input.cfg.compaction?.tail_turns ?? DEFAULT_TAIL_TURNS
if (limit <= 0) return { head: input.messages, tail_start_id: undefined }
const limit = input.cfg.compaction?.tail_turns
if (limit !== undefined && limit <= 0) return { head: input.messages, tail_start_id: undefined }
const budget = preserveRecentBudget({ cfg: input.cfg, model: input.model })
const all = turns(input.messages)
if (!all.length) return { head: input.messages, tail_start_id: undefined }
const recent = all.slice(-limit)
const sizes = yield* Effect.forEach(
recent,
(turn) =>
estimate({
messages: input.messages.slice(turn.start, turn.end),
model: input.model,
}),
{ concurrency: 1 },
)
const recent = limit === undefined ? all : all.slice(-limit)
let total = 0
let keep: Tail | undefined
for (let i = recent.length - 1; i >= 0; i--) {
const turn = recent[i]!
const size = sizes[i]
// estimate lazily so cost stays proportional to the retained tail, not the whole session
const size = yield* estimate({
messages: input.messages.slice(turn.start, turn.end),
model: input.model,
})
if (total + size <= budget) {
total += size
keep = { start: turn.start, id: turn.id }
@@ -381,10 +375,20 @@ const layer = Layer.effect(
{ sessionID: input.sessionID },
{ context: [], prompt: undefined },
)
const nextPrompt = compacting.prompt ?? buildPrompt({ previousSummary, context: compacting.context })
const msgs = structuredClone(selected.head)
yield* plugin.trigger("experimental.chat.messages.transform", {}, { messages: msgs })
const conversation = msgs.map(serialize).filter(Boolean).join("\n\n")
const nextPrompt =
compacting.prompt ??
[
buildPrompt({
previousSummary,
context: [conversation],
}),
...compacting.context,
]
.filter(Boolean)
.join("\n\n")
const ctx = yield* InstanceState.context
const msg: SessionV1.Assistant = {
id: MessageID.ascending(),
@@ -430,7 +434,10 @@ const layer = Layer.effect(
content: [
{
type: "text",
text: [nextPrompt, "The following is the conversation history:", conversation]
text: [
nextPrompt,
...(compacting.prompt ? ["The following is the conversation history:", conversation] : []),
]
.filter(Boolean)
.join("\n\n"),
},