π File detail
services/compact/postCompactCleanup.ts
π― Use case
This file lives under βservices/β, which covers long-lived services (LSP, MCP, OAuth, tool execution, memory, compaction, voice, settings sync, β¦). On the API surface it exposes runPostCompactCleanup β mainly functions, hooks, or classes. Dependencies touch bun:bundle. It composes internal code from constants, context, tools, utils, and microCompact (relative imports).
Generated from folder role, exports, dependency roots, and inline comments β not hand-reviewed for every path.
π§ Inline summary
import { feature } from 'bun:bundle' import type { QuerySource } from '../../constants/querySource.js' import { clearSystemPromptSections } from '../../constants/systemPromptSections.js' import { getUserContext } from '../../context.js' import { clearSpeculativeChecks } from '../../tools/BashTool/bashPermissions.js'
π€ Exports (heuristic)
runPostCompactCleanup
π External import roots
Package roots from from "β¦" (relative paths omitted).
bun:bundle
π₯οΈ Source preview
import { feature } from 'bun:bundle'
import type { QuerySource } from '../../constants/querySource.js'
import { clearSystemPromptSections } from '../../constants/systemPromptSections.js'
import { getUserContext } from '../../context.js'
import { clearSpeculativeChecks } from '../../tools/BashTool/bashPermissions.js'
import { clearClassifierApprovals } from '../../utils/classifierApprovals.js'
import { resetGetMemoryFilesCache } from '../../utils/claudemd.js'
import { clearSessionMessagesCache } from '../../utils/sessionStorage.js'
import { clearBetaTracingState } from '../../utils/telemetry/betaSessionTracing.js'
import { resetMicrocompactState } from './microCompact.js'
/**
* Run cleanup of caches and tracking state after compaction.
* Call this after both auto-compact and manual /compact to free memory
* held by tracking structures that are invalidated by compaction.
*
* Note: We intentionally do NOT clear invoked skill content here.
* Skill content must survive across multiple compactions so that
* createSkillAttachmentIfNeeded() can include the full skill text
* in subsequent compaction attachments.
*
* querySource: pass the compacting query's source so we can skip
* resets that would clobber main-thread module-level state. Subagents
* (agent:*) run in the same process and share module-level state
* (context-collapse store, getMemoryFiles one-shot hook flag,
* getUserContext cache); resetting those when a SUBAGENT compacts
* would corrupt the MAIN thread's state. All compaction callers should
* pass querySource β undefined is only safe for callers that are
* genuinely main-thread-only (/compact, /clear).
*/
export function runPostCompactCleanup(querySource?: QuerySource): void {
// Subagents (agent:*) run in the same process and share module-level
// state with the main thread. Only reset main-thread module-level state
// (context-collapse, memory file cache) for main-thread compacts.
// Same startsWith pattern as isMainThread (index.ts:188).
const isMainThreadCompact =
querySource === undefined ||
querySource.startsWith('repl_main_thread') ||
querySource === 'sdk'
resetMicrocompactState()
if (feature('CONTEXT_COLLAPSE')) {
if (isMainThreadCompact) {
/* eslint-disable @typescript-eslint/no-require-imports */
;(
require('../contextCollapse/index.js') as typeof import('../contextCollapse/index.js')
).resetContextCollapse()
/* eslint-enable @typescript-eslint/no-require-imports */
}
}
if (isMainThreadCompact) {
// getUserContext is a memoized outer layer wrapping getClaudeMds() β
// getMemoryFiles(). If only the inner getMemoryFiles cache is cleared,
// the next turn hits the getUserContext cache and never reaches
// getMemoryFiles(), so the armed InstructionsLoaded hook never fires.
// Manual /compact already clears this explicitly at its call sites;
// auto-compact and reactive-compact did not β this centralizes the
// clear so all compaction paths behave consistently.
getUserContext.cache.clear?.()
resetGetMemoryFilesCache('compact')
}
clearSystemPromptSections()
clearClassifierApprovals()
clearSpeculativeChecks()
// Intentionally NOT calling resetSentSkillNames(): re-injecting the full
// skill_listing (~4K tokens) post-compact is pure cache_creation. The
// model still has SkillTool in schema, invoked_skills preserves used
// skills, and dynamic additions are handled by skillChangeDetector /
// cacheUtils resets. See compactConversation() for full rationale.
clearBetaTracingState()
if (feature('COMMIT_ATTRIBUTION')) {
void import('../../utils/attributionHooks.js').then(m =>
m.sweepFileContentCache(),
)
}
clearSessionMessagesCache()
}