source dump of claude code
at main 77 lines 3.8 kB view raw
1import { feature } from 'bun:bundle' 2import type { QuerySource } from '../../constants/querySource.js' 3import { clearSystemPromptSections } from '../../constants/systemPromptSections.js' 4import { getUserContext } from '../../context.js' 5import { clearSpeculativeChecks } from '../../tools/BashTool/bashPermissions.js' 6import { clearClassifierApprovals } from '../../utils/classifierApprovals.js' 7import { resetGetMemoryFilesCache } from '../../utils/claudemd.js' 8import { clearSessionMessagesCache } from '../../utils/sessionStorage.js' 9import { clearBetaTracingState } from '../../utils/telemetry/betaSessionTracing.js' 10import { resetMicrocompactState } from './microCompact.js' 11 12/** 13 * Run cleanup of caches and tracking state after compaction. 14 * Call this after both auto-compact and manual /compact to free memory 15 * held by tracking structures that are invalidated by compaction. 16 * 17 * Note: We intentionally do NOT clear invoked skill content here. 18 * Skill content must survive across multiple compactions so that 19 * createSkillAttachmentIfNeeded() can include the full skill text 20 * in subsequent compaction attachments. 21 * 22 * querySource: pass the compacting query's source so we can skip 23 * resets that would clobber main-thread module-level state. Subagents 24 * (agent:*) run in the same process and share module-level state 25 * (context-collapse store, getMemoryFiles one-shot hook flag, 26 * getUserContext cache); resetting those when a SUBAGENT compacts 27 * would corrupt the MAIN thread's state. All compaction callers should 28 * pass querySource — undefined is only safe for callers that are 29 * genuinely main-thread-only (/compact, /clear). 30 */ 31export function runPostCompactCleanup(querySource?: QuerySource): void { 32 // Subagents (agent:*) run in the same process and share module-level 33 // state with the main thread. Only reset main-thread module-level state 34 // (context-collapse, memory file cache) for main-thread compacts. 35 // Same startsWith pattern as isMainThread (index.ts:188). 36 const isMainThreadCompact = 37 querySource === undefined || 38 querySource.startsWith('repl_main_thread') || 39 querySource === 'sdk' 40 41 resetMicrocompactState() 42 if (feature('CONTEXT_COLLAPSE')) { 43 if (isMainThreadCompact) { 44 /* eslint-disable @typescript-eslint/no-require-imports */ 45 ;( 46 require('../contextCollapse/index.js') as typeof import('../contextCollapse/index.js') 47 ).resetContextCollapse() 48 /* eslint-enable @typescript-eslint/no-require-imports */ 49 } 50 } 51 if (isMainThreadCompact) { 52 // getUserContext is a memoized outer layer wrapping getClaudeMds() → 53 // getMemoryFiles(). If only the inner getMemoryFiles cache is cleared, 54 // the next turn hits the getUserContext cache and never reaches 55 // getMemoryFiles(), so the armed InstructionsLoaded hook never fires. 56 // Manual /compact already clears this explicitly at its call sites; 57 // auto-compact and reactive-compact did not — this centralizes the 58 // clear so all compaction paths behave consistently. 59 getUserContext.cache.clear?.() 60 resetGetMemoryFilesCache('compact') 61 } 62 clearSystemPromptSections() 63 clearClassifierApprovals() 64 clearSpeculativeChecks() 65 // Intentionally NOT calling resetSentSkillNames(): re-injecting the full 66 // skill_listing (~4K tokens) post-compact is pure cache_creation. The 67 // model still has SkillTool in schema, invoked_skills preserves used 68 // skills, and dynamic additions are handled by skillChangeDetector / 69 // cacheUtils resets. See compactConversation() for full rationale. 70 clearBetaTracingState() 71 if (feature('COMMIT_ATTRIBUTION')) { 72 void import('../../utils/attributionHooks.js').then(m => 73 m.sweepFileContentCache(), 74 ) 75 } 76 clearSessionMessagesCache() 77}