Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
6.1 kB · 207 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208/** * Session Memory utility functions that can be imported without circular dependencies. * These are separate from the main sessionMemory.ts to avoid importing runAgent. */
import { isFsInaccessible } from '../../utils/errors.js'import { getFsImplementation } from '../../utils/fsOperations.js'import { getSessionMemoryPath } from '../../utils/permissions/filesystem.js'import { sleep } from '../../utils/sleep.js'import { logEvent } from '../analytics/index.js'
const EXTRACTION_WAIT_TIMEOUT_MS = 15000const EXTRACTION_STALE_THRESHOLD_MS = 60000 // 1 minute
/** * Configuration for session memory extraction thresholds */export type SessionMemoryConfig = { /** Minimum context window tokens before initializing session memory. * Uses the same token counting as autocompact (input + output + cache tokens) * to ensure consistent behavior between the two features. */ minimumMessageTokensToInit: number /** Minimum context window growth (in tokens) between session memory updates. * Uses the same token counting as autocompact (tokenCountWithEstimation) * to measure actual context growth, not cumulative API usage. */ minimumTokensBetweenUpdate: number /** Number of tool calls between session memory updates */ toolCallsBetweenUpdates: number}
// Default configuration valuesexport const DEFAULT_SESSION_MEMORY_CONFIG: SessionMemoryConfig = { minimumMessageTokensToInit: 10000, minimumTokensBetweenUpdate: 5000, toolCallsBetweenUpdates: 3,}
// Current session memory configurationlet sessionMemoryConfig: SessionMemoryConfig = { ...DEFAULT_SESSION_MEMORY_CONFIG,}
// Track the last summarized message ID (shared state)let lastSummarizedMessageId: string | undefined
// Track extraction state with timestamp (set by sessionMemory.ts)let extractionStartedAt: number | undefined
// Track context size at last memory extraction (for minimumTokensBetweenUpdate)let tokensAtLastExtraction = 0
// Track whether session memory has been initialized (met minimumMessageTokensToInit)let sessionMemoryInitialized = false
/** * Get the message ID up to which the session memory is current */export function getLastSummarizedMessageId(): string | undefined { return lastSummarizedMessageId}
/** * Set the last summarized message ID (called from sessionMemory.ts) */export function setLastSummarizedMessageId( messageId: string | undefined,): void { lastSummarizedMessageId = messageId}
/** * Mark extraction as started (called from sessionMemory.ts) */export function markExtractionStarted(): void { extractionStartedAt = Date.now()}
/** * Mark extraction as completed (called from sessionMemory.ts) */export function markExtractionCompleted(): void { extractionStartedAt = undefined}
/** * Wait for any in-progress session memory extraction to complete (with 15s timeout) * Returns immediately if no extraction is in progress or if extraction is stale (>1min old). */export async function waitForSessionMemoryExtraction(): Promise<void> { const startTime = Date.now() while (extractionStartedAt) { const extractionAge = Date.now() - extractionStartedAt if (extractionAge > EXTRACTION_STALE_THRESHOLD_MS) { // Extraction is stale, don't wait return }
if (Date.now() - startTime > EXTRACTION_WAIT_TIMEOUT_MS) { // Timeout - continue anyway return }
await sleep(1000) }}
/** * Get the current session memory content */export async function getSessionMemoryContent(): Promise<string | null> { const fs = getFsImplementation() const memoryPath = getSessionMemoryPath()
try { const content = await fs.readFile(memoryPath, { encoding: 'utf-8' })
logEvent('tengu_session_memory_loaded', { content_length: content.length, })
return content } catch (e: unknown) { if (isFsInaccessible(e)) return null throw e }}
/** * Set the session memory configuration */export function setSessionMemoryConfig( config: Partial<SessionMemoryConfig>,): void { sessionMemoryConfig = { ...sessionMemoryConfig, ...config, }}
/** * Get the current session memory configuration */export function getSessionMemoryConfig(): SessionMemoryConfig { return { ...sessionMemoryConfig }}
/** * Record the context size at the time of extraction. * Used to measure context growth for minimumTokensBetweenUpdate threshold. */export function recordExtractionTokenCount(currentTokenCount: number): void { tokensAtLastExtraction = currentTokenCount}
/** * Check if session memory has been initialized (met minimumTokensToInit threshold) */export function isSessionMemoryInitialized(): boolean { return sessionMemoryInitialized}
/** * Mark session memory as initialized */export function markSessionMemoryInitialized(): void { sessionMemoryInitialized = true}
/** * Check if we've met the threshold to initialize session memory. * Uses total context window tokens (same as autocompact) for consistent behavior. */export function hasMetInitializationThreshold( currentTokenCount: number,): boolean { return currentTokenCount >= sessionMemoryConfig.minimumMessageTokensToInit}
/** * Check if we've met the threshold for the next update. * Measures actual context window growth since last extraction * (same metric as autocompact and initialization threshold). */export function hasMetUpdateThreshold(currentTokenCount: number): boolean { const tokensSinceLastExtraction = currentTokenCount - tokensAtLastExtraction return ( tokensSinceLastExtraction >= sessionMemoryConfig.minimumTokensBetweenUpdate )}
/** * Get the configured number of tool calls between updates */export function getToolCallsBetweenUpdates(): number { return sessionMemoryConfig.toolCallsBetweenUpdates}
/** * Reset session memory state (useful for testing) */export function resetSessionMemoryState(): void { sessionMemoryConfig = { ...DEFAULT_SESSION_MEMORY_CONFIG } tokensAtLastExtraction = 0 sessionMemoryInitialized = false lastSummarizedMessageId = undefined extractionStartedAt = undefined}