Compare commits

...

2 Commits

Author SHA1 Message Date
claude-code-best
056893ebb0 fix: tighten as any usage in performanceShim and clarify fileHistory cap
- performanceShim: replace 'as any' on the onresourcetimingbufferfull
  getter/setter and the globalThis install guard with typed intersection
  casts, per the project's TS guideline.
- fileHistory: clarify the MAX_SNAPSHOTS comment so it reflects that
  checkpointing is throttled (cap reduced from 100 to 20), not disabled.
2026-05-05 13:25:35 +00:00
claude-code-best
a5ca2c1a97 fix: address coderabbit review feedback on PR #413
- performanceShim: add no-arg getEntries() so the 'as typeof performance'
  cast is accurate for callers (Bun, OTel, dev tooling).
- scripts/dev: make production NODE_ENV opt-in via CLAUDE_CODE_FORCE_NODE_ENV
  so dev-only diagnostics (DevBar, doctorDiagnostic, AutoUpdater dev
  branches, etc.) keep working by default.
- gemini/index: switch deep-relative Tools import to the src/* path alias.
- screens/REPL: drop the unnecessary 'as any' on the getPipeIpc selector to
  match other call sites.
2026-05-05 13:23:35 +00:00
5 changed files with 31 additions and 12 deletions

View File

@@ -14,11 +14,20 @@ const __dirname = dirname(__filename)
const projectRoot = join(__dirname, '..') const projectRoot = join(__dirname, '..')
const cliPath = join(projectRoot, 'src/entrypoints/cli.tsx') 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 = { const defines = {
...getMacroDefines(), ...getMacroDefines(),
// React production mode — prevents 6,889+ _debugStack Error objects 'process.env.NODE_ENV': JSON.stringify(forcedNodeEnv),
// (12MB) from accumulating during long-running sessions.
'process.env.NODE_ENV': JSON.stringify('production'),
} }
const defineArgs = Object.entries(defines).flatMap(([k, v]) => [ const defineArgs = Object.entries(defines).flatMap(([k, v]) => [

View File

@@ -4937,7 +4937,7 @@ export function REPL({
useMailboxBridge({ isLoading, onSubmitMessage: handleIncomingPrompt }); useMailboxBridge({ isLoading, onSubmitMessage: handleIncomingPrompt });
useMasterMonitor(); useMasterMonitor();
useSlaveNotifications(); useSlaveNotifications();
const _pipeIpcState = useAppState(s => getPipeIpc(s as any)); const _pipeIpcState = useAppState(s => getPipeIpc(s));
usePipePermissionForward({ store, tools, setMessages, setToolUseConfirmQueue, getToolUseContext, mainLoopModel }); usePipePermissionForward({ store, tools, setMessages, setToolUseConfirmQueue, getToolUseContext, mainLoopModel });
usePipeMuteSync({ setToolUseConfirmQueue }); usePipeMuteSync({ setToolUseConfirmQueue });

View File

@@ -6,7 +6,7 @@ import type {
StreamEvent, StreamEvent,
SystemAPIErrorMessage, SystemAPIErrorMessage,
} from '../../../types/message.js' } from '../../../types/message.js'
import { type Tools } from '../../../Tool.js' import type { Tools } from 'src/Tool.js'
import { toolToAPISchema } from '../../../utils/api.js' import { toolToAPISchema } from '../../../utils/api.js'
import { logForDebugging } from '../../../utils/debug.js' import { logForDebugging } from '../../../utils/debug.js'
import { import {

View File

@@ -51,8 +51,9 @@ export type FileHistoryState = {
snapshotSequence: number snapshotSequence: number
} }
// Disabled: file checkpointing causes unbounded memory growth (100 snapshots × full file backups). // Throttled: file checkpointing remains enabled (gated by fileHistoryEnabled())
// See heap snapshot analysis — re-enable only after switching to incremental diffs. // 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 const MAX_SNAPSHOTS = 20
export type DiffStats = export type DiffStats =
| { | {

View File

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