Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions scripts/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,20 @@ const __dirname = dirname(__filename)
const projectRoot = join(__dirname, '..')
const cliPath = join(projectRoot, 'src/entrypoints/cli.tsx')

// React production mode — prevents 6,889+ _debugStack Error objects
// (12MB) from accumulating during long-running sessions.
// Opt-in via CLAUDE_CODE_FORCE_NODE_ENV=production for dev sessions that
// need the memory optimization. Default keeps NODE_ENV='development' so
// dev-only diagnostics (DevBar, doctorDiagnostic, AutoUpdater dev branches,
// etc.) continue to work.
const forcedNodeEnv =
process.env.CLAUDE_CODE_FORCE_NODE_ENV ??
process.env.NODE_ENV ??
'development'

const defines = {
...getMacroDefines(),
// React production mode — prevents 6,889+ _debugStack Error objects
// (12MB) from accumulating during long-running sessions.
'process.env.NODE_ENV': JSON.stringify('production'),
'process.env.NODE_ENV': JSON.stringify(forcedNodeEnv),
}

const defineArgs = Object.entries(defines).flatMap(([k, v]) => [
Expand Down
2 changes: 1 addition & 1 deletion src/screens/REPL.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4937,7 +4937,7 @@ export function REPL({
useMailboxBridge({ isLoading, onSubmitMessage: handleIncomingPrompt });
useMasterMonitor();
useSlaveNotifications();
const _pipeIpcState = useAppState(s => getPipeIpc(s as any));
const _pipeIpcState = useAppState(s => getPipeIpc(s));

usePipePermissionForward({ store, tools, setMessages, setToolUseConfirmQueue, getToolUseContext, mainLoopModel });
usePipeMuteSync({ setToolUseConfirmQueue });
Expand Down
2 changes: 1 addition & 1 deletion src/services/api/gemini/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
StreamEvent,
SystemAPIErrorMessage,
} from '../../../types/message.js'
import { type Tools } from '../../../Tool.js'
import type { Tools } from 'src/Tool.js'
import { toolToAPISchema } from '../../../utils/api.js'
import { logForDebugging } from '../../../utils/debug.js'
import {
Expand Down
5 changes: 3 additions & 2 deletions src/utils/fileHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ export type FileHistoryState = {
snapshotSequence: number
}

// Disabled: file checkpointing causes unbounded memory growth (100 snapshots × full file backups).
// See heap snapshot analysis — re-enable only after switching to incremental diffs.
// Throttled: file checkpointing remains enabled (gated by fileHistoryEnabled())
// but capped to mitigate unbounded memory growth (full file backups x N snapshots).
// See heap snapshot analysis; only raise this cap after switching to incremental diffs.
const MAX_SNAPSHOTS = 20
export type DiffStats =
| {
Expand Down
19 changes: 14 additions & 5 deletions src/utils/performanceShim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ function getEntriesByName(name: string, type?: string): PerformanceEntryLike[] {
return entries.filter(e => e.name === name)
}

function getEntries(): PerformanceEntryLike[] {
return [...getEntriesByType('mark'), ...getEntriesByType('measure')]
}

function clearMarks(name?: string): void {
if (name !== undefined) {
marks.delete(name)
Expand All @@ -128,6 +132,7 @@ const shim = {
now,
mark,
measure: measure as typeof performance.measure,
getEntries: getEntries as typeof performance.getEntries,
getEntriesByType: getEntriesByType as typeof performance.getEntriesByType,
getEntriesByName: getEntriesByName as typeof performance.getEntriesByName,
clearMarks: clearMarks as typeof performance.clearMarks,
Expand All @@ -140,10 +145,11 @@ const shim = {
return original.timeOrigin
},
get onresourcetimingbufferfull() {
return (original as any).onresourcetimingbufferfull
return (original as Performance & { onresourcetimingbufferfull?: unknown })
.onresourcetimingbufferfull
},
set onresourcetimingbufferfull(_v: any) {
// no-op prevent accumulation
set onresourcetimingbufferfull(_v: unknown) {
// no-op to prevent accumulation
},
toJSON() {
return original.toJSON()
Expand All @@ -156,8 +162,11 @@ const shim = {
* native Performance reference.
*/
export function installPerformanceShim(): void {
if ((globalThis as any).__performanceShimInstalled) return
;(globalThis as any).__performanceShimInstalled = true
const g = globalThis as typeof globalThis & {
__performanceShimInstalled?: boolean
}
if (g.__performanceShimInstalled) return
g.__performanceShimInstalled = true
globalThis.performance = shim
}

Expand Down
Loading