Keeping conversations alive beyond the token limit
import { feature } from 'bun:bundle'import type { UUID } from 'crypto'import uniqBy from 'lodash-es/uniqBy.js'
/* eslint-disable @typescript-eslint/no-require-imports */
const sessionTranscriptModule = feature('KAIROS') ? (require('../sessionTranscript/sessionTranscript.js') as typeof import('../sessionTranscript/sessionTranscript.js')): null
import { APIUserAbortError } from '@anthropic-ai/sdk'import { markPostCompaction } from 'src/bootstrap/state.js'import { getInvokedSkillsForAgent } from '../../bootstrap/state.js'import type { QuerySource } from '../../constants/querySource.js'import type { CanUseToolFn } from '../../hooks/useCanUseTool.js'import type { Tool, ToolUseContext } from '../../Tool.js'import type { LocalAgentTaskState } from '../../tasks/LocalAgentTask/LocalAgentTask.js'import { FileReadTool } from '../../tools/FileReadTool/FileReadTool.js'import {FILE_READ_TOOL_NAME,
FILE_UNCHANGED_STUB,
} from '../../tools/FileReadTool/prompt.js'
import { ToolSearchTool } from '../../tools/ToolSearchTool/ToolSearchTool.js'import type { AgentId } from '../../types/ids.js'import type {AssistantMessage,
AttachmentMessage,
HookResultMessage,
Message,
PartialCompactDirection,
SystemCompactBoundaryMessage,
SystemMessage,
UserMessage,
} from '../../types/message.js'
import {createAttachmentMessage,
generateFileAttachment,
getAgentListingDeltaAttachment,
getDeferredToolsDeltaAttachment,
getMcpInstructionsDeltaAttachment,
} from '../../utils/attachments.js'
import { getMemoryPath } from '../../utils/config.js'import { COMPACT_MAX_OUTPUT_TOKENS } from '../../utils/context.js'import {analyzeContext,
tokenStatsToStatsigMetrics,
} from '../../utils/contextAnalysis.js'
import { logForDebugging } from '../../utils/debug.js'import { hasExactErrorMessage } from '../../utils/errors.js'import { cacheToObject } from '../../utils/fileStateCache.js'import {type CacheSafeParams,
runForkedAgent,
} from '../../utils/forkedAgent.js'
import {executePostCompactHooks,
executePreCompactHooks,
} from '../../utils/hooks.js'
import { logError } from '../../utils/log.js'import { MEMORY_TYPE_VALUES } from '../../utils/memory/types.js'import {createCompactBoundaryMessage,
createUserMessage,
getAssistantMessageText,
getLastAssistantMessage,
getMessagesAfterCompactBoundary,
isCompactBoundaryMessage,
normalizeMessagesForAPI,
} from '../../utils/messages.js'
import { expandPath } from '../../utils/path.js'import { getPlan, getPlanFilePath } from '../../utils/plans.js'Long conversations eventually fill the context window. src/services/compact/compact.ts handles this by calling Claude itself to summarize the conversation — replacing the full history with a dense summary that preserves key decisions and results.
The compaction prompt is a meta-call to Claude: Claude summarizes what Claude has done so far. The prompt is tuned to preserve tool results and decision rationale — the most important parts for continuing a task.
Auto-compact (src/services/compact/autoCompact.ts) monitors token usage after each turn. When it crosses the threshold (~80%), it schedules a compact before the next user message. The user sees a brief notification but doesn't lose context.
MicroCompact is a lighter version that summarizes just the most recent tool calls rather than the entire history. It's used when the context is getting full but a full compact would be too disruptive to the current task.
Ask anything about Context Window Management
Powered by Groq · Enter to send, Shift+Enter for newline