MCPcopy Create free account
hub / github.com/agentforce314/clawcodex / startMemoryMonitor

Function startMemoryMonitor

ui-tui/src/lib/memoryMonitor.ts:90–188  ·  view source on GitHub ↗
({
  criticalBytes,
  highBytes,
  intervalMs = 10_000,
  onCritical,
  onHigh,
  onWarn,
  warnBytes = 600 * MB
}: MemoryMonitorOptions = {})

Source from the content-addressed store, hash-verified

88}
89
90export function startMemoryMonitor({
91 criticalBytes,
92 highBytes,
93 intervalMs = 10_000,
94 onCritical,
95 onHigh,
96 onWarn,
97 warnBytes = 600 * MB
98}: MemoryMonitorOptions = {}): () => void {
99 const { critical, high } = resolveThresholds(criticalBytes, highBytes)
100 const dumped = new Set<Exclude<MemoryLevel, 'normal'>>()
101 const inFlight = new Set<Exclude<MemoryLevel, 'normal'>>()
102
103 // Early-warning state (#34095): the silent-death regime is BELOW `high`, so
104 // the level machine above never sees it. Track the previous sample and fire
105 // onWarn at most once when heap both crosses a modest absolute floor AND is
106 // climbing steeply (≥150MB between 10s ticks) — the signature of a render-
107 // tree blowup — so the user gets a visible heads-up before Node OOMs under
108 // the exit threshold. Re-armed only after heap falls back below the floor.
109 // `lastHeap < 0` marks the un-seeded first sample so a cold start that opens
110 // already-high can't be mistaken for sudden growth (growth = current - last).
111 let lastHeap = -1
112 let warned = false
113 const WARN_GROWTH_STEP = 150 * MB
114
115 // Cooldown prevents repeated auto dumps when heap oscillates around the
116 // threshold (issue #21767). `dumped` alone is not enough — it clears on
117 // every transition back to `normal`.
118 const cooldownRaw = process.env.CLAWCODEX_AUTO_HEAPDUMP_COOLDOWN_MS?.trim()
119 const cooldownParsed = cooldownRaw ? Number(cooldownRaw) : NaN
120 const cooldownMs = Number.isFinite(cooldownParsed) && cooldownParsed >= 0 ? cooldownParsed : 600_000
121 let lastAutoDumpAt = 0
122
123 const tick = async () => {
124 const { heapUsed, rss } = process.memoryUsage()
125
126 // Sub-threshold abnormal-growth warning. Skip on the first (un-seeded)
127 // sample — we need a prior reading to measure a delta against.
128 if (heapUsed < high && lastHeap >= 0) {
129 if (!warned && heapUsed >= warnBytes && heapUsed - lastHeap >= WARN_GROWTH_STEP) {
130 warned = true
131 onWarn?.({ heapUsed, level: 'normal', rss })
132 } else if (heapUsed < warnBytes) {
133 warned = false
134 }
135 }
136
137 lastHeap = heapUsed
138
139 const level: MemoryLevel = heapUsed >= critical ? 'critical' : heapUsed >= high ? 'high' : 'normal'
140
141 if (level === 'normal') {
142 dumped.clear()
143
144 return
145 }
146
147 if (dumped.has(level) || inFlight.has(level)) {

Callers 2

entry.tsxFile · 0.85

Calls 3

resolveThresholdsFunction · 0.85
unrefMethod · 0.80
tickFunction · 0.70

Tested by

no test coverage detected