feat: 继续进行内存泄露修复及垃圾代码清理#413
Conversation
删除未使用的文件(BuiltinStatusLine.tsx、4 个重复的 .ts stub)、 移除约 55 个文件中未使用的 React 导入、 清理约 50 处未使用的导入/变量/参数。 净减少 ~296 行代码,precheck 4077 测试全部通过。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
移除 autonomyStatus/betas/claudemd/executorCrossPlatform 中 未使用的导入和参数。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
移除未使用的导入(getSubscriptionType、isEnvDefinedFalsy、 getClaudeConfigHomeDir 等)、未使用的常量(ACCENT_COLOR、 NAME_MATCH_BONUS、CLIPBOARD_THRESHOLD)和死函数 (getOpus41Option、pasteViaClipboard), 为未使用参数添加 _ 前缀。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
📝 WalkthroughWalkthroughThis PR performs large-scale codebase cleanup: enforces ChangesBuild-time Configuration & Performance Infrastructure
React & Import Modernization
Feature & Logic Refinements
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes This PR combines large-scale repetitive import cleanup (which is mechanically straightforward) with multiple independent logic changes, new infrastructure (performance shim), removed features, and wiring adjustments spread across many files. While individual hunks are often simple, the variety of change types (imports, parameters, deletions, new module, logic tweaks) and heterogeneity across ~120+ files demand careful per-domain review to catch any missed dependencies or breaking implications. Possibly related PRs
Suggested labels
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/utils/toolPool.ts (1)
52-59:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAlign JSDoc param name with the renamed argument.
@param modeno longer matches_mode, which can confuse API readers and tooling.Suggested diff
- * `@param` mode - The permission context mode. + * `@param` _mode - The permission context mode.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/utils/toolPool.ts` around lines 52 - 59, Update the JSDoc for mergeAndFilterTools to match the renamed parameter: change the `@param` entry from "mode" to "_mode" (or rename the function parameter to "mode" if you prefer consistency) so the docstring and the function signature align; ensure the description still references ToolPermissionContext['mode'] and that the `@param` name matches the actual parameter (_mode) used in the mergeAndFilterTools function.
🧹 Nitpick comments (7)
src/hooks/useSSHSession.ts (1)
24-24: ⚡ Quick winUse
src/*alias for this TypeScript importLine 24 still uses a relative import path. Please switch this changed import to the
src/*alias style to match repo conventions.As per coding guidelines: "Use
src/*path alias in imports; do not use relative paths like../../../."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/hooks/useSSHSession.ts` at line 24, The import for SSHSessionManager in useSSHSession.ts uses a relative path; update the import to use the project's src path alias (e.g., import type { SSHSessionManager } from 'src/ssh/SSHSessionManager') so it matches repo conventions and other imports; locate the import statement referencing SSHSessionManager in the useSSHSession.ts file and replace the relative path with the src/* alias.src/utils/betas.ts (1)
26-26: ⚡ Quick winUse
src/*alias for this import instead of a relative pathPlease switch this changed import to the repository alias style to match TS import conventions.
Suggested diff
-import { isEnvTruthy } from './envUtils.js' +import { isEnvTruthy } from 'src/utils/envUtils.js'As per coding guidelines, "Use
src/*path alias in imports; do not use relative paths like../../../."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/utils/betas.ts` at line 26, Update the import in src/utils/betas.ts to use the repository path alias instead of a relative path: replace the current relative import of isEnvTruthy with the aliased module import (e.g., import { isEnvTruthy } from 'src/utils/envUtils.js') so the symbol isEnvTruthy is imported via the src/* path alias.src/components/PromptInput/Notifications.tsx (1)
42-50: 🏗️ Heavy liftRemove obsolete auto-updater props from
Propsand component API surfaceThe underscore rename avoids local unused warnings, but these fields are still required by
Props, so callers must keep passing dead data/handlers. Since auto-updater UI plumbing is removed, please delete these props fromPropsand the parent callsites to finish the cleanup.Also applies to: 57-66
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/PromptInput/Notifications.tsx` around lines 42 - 50, Remove the obsolete auto-updater API from the Notifications component: delete the autoUpdaterResult: AutoUpdaterResult | null, isAutoUpdating: boolean, onAutoUpdaterResult: (result: AutoUpdaterResult) => void, and onChangeIsUpdating: (isUpdating: boolean) => void fields from the Props type and remove those same props from the Notifications component parameter list (and any underscore-prefixed variants). Also remove any remaining references to AutoUpdaterResult type and any internal use of those props (handlers or flags) inside Notifications.tsx, and update all parent callsites to stop passing these props. Ensure imports for AutoUpdaterResult are removed if no longer used.src/components/Spinner.tsx (1)
245-247: ⚡ Quick winComment/API contract is out of sync around TTFT.
Line 245 says
apiMetricsRefwas removed, butPropsstill declares it (Line 51-59). Please either remove the stale prop or update the comment and wire it intentionally; keeping both states creates ambiguous component API intent.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/Spinner.tsx` around lines 245 - 247, Props currently declares apiMetricsRef but the implementation comments and local variable _ttftText indicate apiMetricsRef was removed and TTFT support is disabled; pick one: either remove apiMetricsRef from the Props type (and any related tests/consumers) and update the comment to remove TTFT gating wording, or re-thread the prop by restoring usage in the Spinner component (use the apiMetricsRef to compute/set _ttftText and any metric updates) and update the comment to reflect active TTFT wiring; specifically edit the Props interface to remove or keep apiMetricsRef, and update Spinner (the _ttftText initialization and surrounding comment) to match that choice so the component API and implementation are consistent.src/query.ts (1)
71-74: ⚡ Quick winDead code:
_jobClassifieris loaded for no reason.The underscore prefix marks the binding as unused, yet
require('./jobs/classifier.js')still executes at module-eval time and pulls the classifier module (and its transitive imports) into the bundle on every cold start. Ifjobs/classifier.jshas no module-load side effects you intentionally rely on, drop the entire ternary. Otherwise, leave a comment so a future cleanup pass doesn't repeat this triage.♻️ Option 1: remove if no longer needed
-const _jobClassifier = feature('TEMPLATES') - ? (require('./jobs/classifier.js') as typeof import('./jobs/classifier.js')) - : null🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/query.ts` around lines 71 - 74, The binding _jobClassifier is unused but still causes require('./jobs/classifier.js') to execute at module-eval, pulling that module into the bundle; either remove the entire ternary and the _jobClassifier declaration if you don't need the classifier, or make the load lazy/conditional at use-time (e.g., call require('./jobs/classifier.js') inside the function that needs it) and keep feature('TEMPLATES') check there; if you intentionally rely on module-load side effects, leave a brief comment above the current code mentioning that rationale so future cleanup doesn't remove it.src/utils/performanceShim.ts (2)
44-66: ⚡ Quick win
measure()returnsvoidbut the spec (and TS types) requirePerformanceMeasure.The cast
measure as typeof performance.measure(line 130) hides this — any caller that reads the return value will silently getundefined. Nativeperformance.measure(name, ...)has returned aPerformanceMeasuresince 2019.Either return a minimal entry object (mirroring how
mark()already does) or, if you're confident no consumer reads it, drop the cast and accept that this shim is intentionally narrower than the spec.♻️ Return a minimal PerformanceMeasure-shaped object
function measure( name: string, startMarkOrOptions?: string | MeasureOptions, endMark?: string, -): void { +): PerformanceMeasure { let startTime: number let duration: number // ... existing logic ... measures.set(name, { name, startTime, duration }) + return { + name, + entryType: 'measure', + startTime, + duration, + detail: null, + toJSON: () => ({ name, entryType: 'measure', startTime, duration }), + } as PerformanceMeasure }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/utils/performanceShim.ts` around lines 44 - 66, The shimbed measure function currently returns void which breaks callers expecting a PerformanceMeasure; update the measure function to return a minimal PerformanceMeasure-shaped object (mirror the mark() behavior) and change its signature from void to PerformanceMeasure (or the appropriate TS type), ensure the measures Map stores that object (include name, entryType: 'measure', startTime, duration) and remove or stop casting `measure` to `typeof performance.measure` so callers receive the proper value; reference the existing measure function and the cast `measure as typeof performance.measure` when locating the changes.
32-42: ⚖️ Poor tradeoffBehavioral divergence:
mark/measureoverwrite same-name entries; native preserves history.
marks.set(name, …)andmeasures.set(name, …)use aMapkeyed by name, so the second call tomark('x')discards the first. The native API stores them in a list andgetEntriesByName('x', 'mark')returns all of them in order. Anything that uses repeated marks for timeline traces (React Compiler/Profiler, OTel timing export, custom devtools) will silently lose data after this shim is installed.If keeping memory bounded is the goal, consider a small ring buffer per-name (or capped array) instead of a single-slot map; a single
setsemantics is a stricter break than the file's intent suggests.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/utils/performanceShim.ts` around lines 32 - 42, The current mark/measure implementation overwrites same-name entries because marks and measures are stored as single values in the maps; change this to store an array (or capped/ring-buffer) per name so repeated calls append entries and preserve insertion order; update the mark function to push a new timestamp into marks.get(name) array (creating it if missing) and return a PerformanceMark-like object with that timestamp, update measure to compute start/end by looking up the appropriate entries in the marks arrays (and store measures as arrays in measures map), and adjust getEntriesByName/getEntries to iterate these per-name arrays in order so consumers like mark, measure, getEntriesByName('x','mark') receive all historical entries rather than only the last one.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/dev.ts`:
- Around line 17-22: The current defines object hardcodes 'process.env.NODE_ENV'
to 'production' which disables dev-only branches; change this so the production
value is applied only when a new opt-in env var (e.g.
CLAUDE_CODE_FORCE_NODE_ENV) is set: keep the defines and getMacroDefines() usage
but set 'process.env.NODE_ENV' to
JSON.stringify(process.env.CLAUDE_CODE_FORCE_NODE_ENV || process.env.NODE_ENV ||
'development') (or equivalent) so developers default to dev mode while allowing
opt-in production mode for the React memory optimization when
CLAUDE_CODE_FORCE_NODE_ENV=production is provided; update any related comments
to reflect the opt-in behavior and reference the defines symbol and
getMacroDefines().
In `@src/screens/REPL.tsx`:
- Line 4940: Remove the unnecessary cast in the selector: change the useAppState
call that assigns _pipeIpcState to call getPipeIpc with the selector argument
directly (useAppState(s => getPipeIpc(s))) instead of casting s to any; update
the line referencing _pipeIpcState in REPL.tsx to remove "as any" so it matches
other usages like useMasterMonitor and useSlaveNotifications and relies on
getPipeIpc’s accepted any-typed parameter.
In `@src/services/api/gemini/index.ts`:
- Line 9: Replace the deep-relative import of the Tools type in
src/services/api/gemini/index.ts with the project path-alias form: change the
import that references '../../../Tool.js' to use the 'src/...' alias (import {
type Tools } from 'src/...') so the file imports Tools via the src path alias
instead of a '../../../' relative path; keep the imported symbol name (Tools)
unchanged.
In `@src/utils/fileHistory.ts`:
- Around line 54-56: The comment above MAX_SNAPSHOTS is misleading because
snapshots are throttled, not disabled; update the comment to accurately state
that file checkpointing remains enabled but capped to prevent unbounded growth
and refer to the gating via fileHistoryEnabled(). Locate the MAX_SNAPSHOTS
constant and replace the "Disabled" wording with a note like "Throttled: file
checkpointing remains enabled but capped at MAX_SNAPSHOTS (see
fileHistoryEnabled() gating) and re-enable full backups only after switching to
incremental diffs," ensuring the comment mentions the reason (heap snapshot
growth) and the intended future change.
In `@src/utils/performanceShim.ts`:
- Around line 142-160: The code uses unsafe `as any` casts in the performance
shim; replace them with safer double-assertions or proper typings: cast
`original` to the correct Performance-like interface using `as unknown as {
onresourcetimingbufferfull?: EventListener | null; toJSON: () => any; [k:
string]: any }` (or extend the Performance interface) so the getter
`onresourcetimingbufferfull` and the `toJSON()` call use typed access instead of
`(original as any)`, change the setter parameter `_v: any` to a typed parameter
(e.g. `_v: EventListener | null`) or `_v: unknown` then cast only if needed, and
replace `(globalThis as any).__performanceShimInstalled` with `(globalThis as
unknown as { __performanceShimInstalled?: boolean }).__performanceShimInstalled`
(or add an ambient declaration), updating references in `get
onresourcetimingbufferfull`, `set onresourcetimingbufferfull`, `toJSON`, and
`installPerformanceShim` accordingly.
- Around line 81-106: Add the missing no-argument overload and other missing
members to the shim so it fully matches typeof performance: implement
performance.getEntries() to return the union of getEntriesByType('mark') and
getEntriesByType('measure') (reuse getEntriesByType/getEntriesByName logic), and
add stubbed/pass-through implementations for markResourceTiming,
setResourceTimingBufferSize (already stub-typed but ensure the function exists),
eventCounts, and the EventTarget-like methods
addEventListener/removeEventListener/dispatchEvent on the shim object; ensure
their signatures match the standard Performance/EventTarget surface so the final
"as typeof performance" cast is accurate and consumers calling
performance.getEntries() or the other APIs won't throw.
---
Outside diff comments:
In `@src/utils/toolPool.ts`:
- Around line 52-59: Update the JSDoc for mergeAndFilterTools to match the
renamed parameter: change the `@param` entry from "mode" to "_mode" (or rename the
function parameter to "mode" if you prefer consistency) so the docstring and the
function signature align; ensure the description still references
ToolPermissionContext['mode'] and that the `@param` name matches the actual
parameter (_mode) used in the mergeAndFilterTools function.
---
Nitpick comments:
In `@src/components/PromptInput/Notifications.tsx`:
- Around line 42-50: Remove the obsolete auto-updater API from the Notifications
component: delete the autoUpdaterResult: AutoUpdaterResult | null,
isAutoUpdating: boolean, onAutoUpdaterResult: (result: AutoUpdaterResult) =>
void, and onChangeIsUpdating: (isUpdating: boolean) => void fields from the
Props type and remove those same props from the Notifications component
parameter list (and any underscore-prefixed variants). Also remove any remaining
references to AutoUpdaterResult type and any internal use of those props
(handlers or flags) inside Notifications.tsx, and update all parent callsites to
stop passing these props. Ensure imports for AutoUpdaterResult are removed if no
longer used.
In `@src/components/Spinner.tsx`:
- Around line 245-247: Props currently declares apiMetricsRef but the
implementation comments and local variable _ttftText indicate apiMetricsRef was
removed and TTFT support is disabled; pick one: either remove apiMetricsRef from
the Props type (and any related tests/consumers) and update the comment to
remove TTFT gating wording, or re-thread the prop by restoring usage in the
Spinner component (use the apiMetricsRef to compute/set _ttftText and any metric
updates) and update the comment to reflect active TTFT wiring; specifically edit
the Props interface to remove or keep apiMetricsRef, and update Spinner (the
_ttftText initialization and surrounding comment) to match that choice so the
component API and implementation are consistent.
In `@src/hooks/useSSHSession.ts`:
- Line 24: The import for SSHSessionManager in useSSHSession.ts uses a relative
path; update the import to use the project's src path alias (e.g., import type {
SSHSessionManager } from 'src/ssh/SSHSessionManager') so it matches repo
conventions and other imports; locate the import statement referencing
SSHSessionManager in the useSSHSession.ts file and replace the relative path
with the src/* alias.
In `@src/query.ts`:
- Around line 71-74: The binding _jobClassifier is unused but still causes
require('./jobs/classifier.js') to execute at module-eval, pulling that module
into the bundle; either remove the entire ternary and the _jobClassifier
declaration if you don't need the classifier, or make the load lazy/conditional
at use-time (e.g., call require('./jobs/classifier.js') inside the function that
needs it) and keep feature('TEMPLATES') check there; if you intentionally rely
on module-load side effects, leave a brief comment above the current code
mentioning that rationale so future cleanup doesn't remove it.
In `@src/utils/betas.ts`:
- Line 26: Update the import in src/utils/betas.ts to use the repository path
alias instead of a relative path: replace the current relative import of
isEnvTruthy with the aliased module import (e.g., import { isEnvTruthy } from
'src/utils/envUtils.js') so the symbol isEnvTruthy is imported via the src/*
path alias.
In `@src/utils/performanceShim.ts`:
- Around line 44-66: The shimbed measure function currently returns void which
breaks callers expecting a PerformanceMeasure; update the measure function to
return a minimal PerformanceMeasure-shaped object (mirror the mark() behavior)
and change its signature from void to PerformanceMeasure (or the appropriate TS
type), ensure the measures Map stores that object (include name, entryType:
'measure', startTime, duration) and remove or stop casting `measure` to `typeof
performance.measure` so callers receive the proper value; reference the existing
measure function and the cast `measure as typeof performance.measure` when
locating the changes.
- Around line 32-42: The current mark/measure implementation overwrites
same-name entries because marks and measures are stored as single values in the
maps; change this to store an array (or capped/ring-buffer) per name so repeated
calls append entries and preserve insertion order; update the mark function to
push a new timestamp into marks.get(name) array (creating it if missing) and
return a PerformanceMark-like object with that timestamp, update measure to
compute start/end by looking up the appropriate entries in the marks arrays (and
store measures as arrays in measures map), and adjust
getEntriesByName/getEntries to iterate these per-name arrays in order so
consumers like mark, measure, getEntriesByName('x','mark') receive all
historical entries rather than only the last one.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e2d88263-3684-4765-8dee-7a5019fa5477
📒 Files selected for processing (142)
build.tsscripts/dev.tssrc/QueryEngine.tssrc/assistant/gate.tssrc/bridge/bridgeMain.tssrc/bridge/remoteBridgeCore.tssrc/bridge/replBridge.tssrc/buddy/CompanionCard.tsxsrc/cli/handlers/mcp.tsxsrc/cli/print.tssrc/commands/assistant/assistant.tsxsrc/commands/config/config.tsxsrc/commands/diff/diff.tsxsrc/commands/doctor/doctor.tsxsrc/commands/help/help.tsxsrc/commands/hooks/hooks.tsxsrc/commands/install-github-app/ApiKeyStep.tsxsrc/commands/install-github-app/CheckExistingSecretStep.tsxsrc/commands/install-github-app/CheckGitHubStep.tsxsrc/commands/install-github-app/ChooseRepoStep.tsxsrc/commands/install-github-app/CreatingStep.tsxsrc/commands/install-github-app/ErrorStep.tsxsrc/commands/install-github-app/ExistingWorkflowStep.tsxsrc/commands/install-github-app/InstallAppStep.tsxsrc/commands/install-github-app/WarningsStep.tsxsrc/commands/login/login.tsxsrc/commands/permissions/permissions.tsxsrc/commands/provider.tssrc/commands/remoteControlServer/remoteControlServer.tsxsrc/commands/review/ultrareviewCommand.tsxsrc/commands/skill-learning/skill-learning.tssrc/commands/stats/stats.tsxsrc/commands/ultraplan.tsxsrc/commands/usage/usage.tsxsrc/components/BuiltinStatusLine.tsxsrc/components/ConsoleOAuthFlow.tsxsrc/components/FileEditToolUpdatedMessage.tsxsrc/components/LogoV2/CondensedLogo.tsxsrc/components/LogoV2/LogoV2.tsxsrc/components/LogoV2/feedConfigs.tsxsrc/components/Onboarding.tsxsrc/components/PromptInput/Notifications.tsxsrc/components/PromptInput/PromptInput.tsxsrc/components/PromptInput/PromptInputFooter.tsxsrc/components/PromptInput/PromptInputFooterSuggestions.tsxsrc/components/PromptInput/SandboxPromptFooterHint.tsxsrc/components/SandboxViolationExpandedView.tsxsrc/components/Settings/Config.tsxsrc/components/Spinner.tsxsrc/components/agents/new-agent-creation/CreateAgentWizard.tsxsrc/components/agents/new-agent-creation/wizard-steps/ColorStep.tsxsrc/components/agents/new-agent-creation/wizard-steps/ConfirmStep.tsxsrc/components/agents/new-agent-creation/wizard-steps/ConfirmStepWrapper.tsxsrc/components/agents/new-agent-creation/wizard-steps/DescriptionStep.tsxsrc/components/agents/new-agent-creation/wizard-steps/GenerateStep.tsxsrc/components/agents/new-agent-creation/wizard-steps/LocationStep.tsxsrc/components/agents/new-agent-creation/wizard-steps/MemoryStep.tsxsrc/components/agents/new-agent-creation/wizard-steps/MethodStep.tsxsrc/components/agents/new-agent-creation/wizard-steps/ModelStep.tsxsrc/components/agents/new-agent-creation/wizard-steps/PromptStep.tsxsrc/components/agents/new-agent-creation/wizard-steps/ToolsStep.tsxsrc/components/agents/new-agent-creation/wizard-steps/TypeStep.tsxsrc/components/messages/SnipBoundaryMessage.tssrc/components/messages/UserCrossSessionMessage.tssrc/components/messages/UserForkBoilerplateMessage.tssrc/components/messages/UserGitHubWebhookMessage.tssrc/components/permissions/FilePermissionDialog/permissionOptions.tsxsrc/components/permissions/shellPermissionHelpers.tsxsrc/components/tasks/ShellProgress.tsxsrc/components/tasks/WorkflowDetailDialog.tsxsrc/components/teams/TeamsDialog.tsxsrc/components/wizard/WizardDialogLayout.tsxsrc/components/wizard/WizardNavigationFooter.tsxsrc/components/wizard/WizardProvider.tsxsrc/context/promptOverlayContext.tsxsrc/daemon/main.tssrc/entrypoints/cli.tsxsrc/hooks/notifs/useCanSwitchToExistingSubscription.tsxsrc/hooks/notifs/useIDEStatusIndicator.tsxsrc/hooks/notifs/useMcpConnectivityStatus.tsxsrc/hooks/notifs/usePluginAutoupdateNotification.tsxsrc/hooks/notifs/usePluginInstallationStatus.tsxsrc/hooks/notifs/useRateLimitWarningNotification.tsxsrc/hooks/useArrowKeyHistory.tsxsrc/hooks/useChromeExtensionNotification.tsxsrc/hooks/useMergedTools.tssrc/hooks/useOfficialMarketplaceNotification.tsxsrc/hooks/useSSHSession.tssrc/hooks/useTypeahead.tsxsrc/interactiveHelpers.tsxsrc/main.tsxsrc/query.tssrc/screens/REPL.tsxsrc/services/acp/permissions.tssrc/services/api/claude.tssrc/services/api/gemini/index.tssrc/services/api/openai/client.tssrc/services/api/openai/index.tssrc/services/compact/cachedMicrocompact.tssrc/services/compact/snipCompact.tssrc/services/doubaoSTT.tssrc/services/extractMemories/extractMemories.tssrc/services/langfuse/client.tssrc/services/langfuse/index.tssrc/services/langfuse/sanitize.tssrc/services/mcp/channelNotification.tssrc/services/mcp/client.tssrc/services/mcpServerApproval.tsxsrc/services/remoteManagedSettings/securityCheck.tsxsrc/services/skillLearning/observationStore.tssrc/services/skillLearning/toolEventObserver.tssrc/services/skillSearch/localSearch.tssrc/services/skillSearch/prefetch.tssrc/services/tools/toolHooks.tssrc/types/hooks.tssrc/types/message.tssrc/types/permissions.tssrc/utils/attachments.tssrc/utils/autonomyStatus.tssrc/utils/betas.tssrc/utils/claudemd.tssrc/utils/computerUse/executorCrossPlatform.tssrc/utils/computerUse/gates.tssrc/utils/computerUse/win32/inputIndicator.tssrc/utils/computerUse/win32/windowMessage.tssrc/utils/fileHistory.tssrc/utils/lanBeacon.tssrc/utils/messages.tssrc/utils/model/modelOptions.tssrc/utils/performanceShim.tssrc/utils/permissions/PermissionMode.tssrc/utils/permissions/bypassPermissionsKillswitch.tssrc/utils/permissions/getNextPermissionMode.tssrc/utils/permissions/permissionSetup.tssrc/utils/pipeRegistry.tssrc/utils/promptEditor.tssrc/utils/queryHelpers.tssrc/utils/sentry.tssrc/utils/settings/types.tssrc/utils/teleport.tsxsrc/utils/toolPool.tsvite.config.ts
💤 Files with no reviewable changes (73)
- src/commands/login/login.tsx
- src/commands/install-github-app/InstallAppStep.tsx
- src/commands/install-github-app/CreatingStep.tsx
- src/commands/hooks/hooks.tsx
- src/hooks/notifs/useCanSwitchToExistingSubscription.tsx
- src/hooks/useOfficialMarketplaceNotification.tsx
- src/services/mcpServerApproval.tsx
- src/utils/queryHelpers.ts
- src/commands/help/help.tsx
- src/hooks/notifs/usePluginInstallationStatus.tsx
- src/utils/permissions/getNextPermissionMode.ts
- src/components/tasks/ShellProgress.tsx
- src/commands/install-github-app/CheckGitHubStep.tsx
- src/commands/install-github-app/ExistingWorkflowStep.tsx
- src/commands/install-github-app/WarningsStep.tsx
- src/commands/doctor/doctor.tsx
- src/commands/install-github-app/ErrorStep.tsx
- src/services/remoteManagedSettings/securityCheck.tsx
- src/services/doubaoSTT.ts
- src/commands/stats/stats.tsx
- src/hooks/notifs/useMcpConnectivityStatus.tsx
- src/commands/config/config.tsx
- src/daemon/main.ts
- src/assistant/gate.ts
- src/types/hooks.ts
- src/hooks/notifs/useRateLimitWarningNotification.tsx
- src/services/extractMemories/extractMemories.ts
- src/components/messages/SnipBoundaryMessage.ts
- src/cli/handlers/mcp.tsx
- src/commands/review/ultrareviewCommand.tsx
- src/buddy/CompanionCard.tsx
- src/components/PromptInput/PromptInputFooterSuggestions.tsx
- src/components/messages/UserGitHubWebhookMessage.ts
- src/hooks/useChromeExtensionNotification.tsx
- src/utils/pipeRegistry.ts
- src/utils/teleport.tsx
- src/utils/computerUse/win32/inputIndicator.ts
- src/hooks/notifs/usePluginAutoupdateNotification.tsx
- src/services/api/openai/client.ts
- src/commands/usage/usage.tsx
- src/hooks/useTypeahead.tsx
- src/bridge/bridgeMain.ts
- src/components/LogoV2/CondensedLogo.tsx
- src/bridge/replBridge.ts
- src/hooks/useMergedTools.ts
- src/components/messages/UserCrossSessionMessage.ts
- src/types/permissions.ts
- src/components/messages/UserForkBoilerplateMessage.ts
- src/utils/computerUse/gates.ts
- src/services/api/openai/index.ts
- src/services/skillLearning/observationStore.ts
- src/utils/permissions/PermissionMode.ts
- src/components/Settings/Config.tsx
- src/commands/diff/diff.tsx
- src/commands/permissions/permissions.tsx
- src/components/LogoV2/LogoV2.tsx
- src/services/mcp/channelNotification.ts
- src/components/PromptInput/SandboxPromptFooterHint.tsx
- src/utils/permissions/bypassPermissionsKillswitch.ts
- src/utils/autonomyStatus.ts
- src/services/mcp/client.ts
- src/components/LogoV2/feedConfigs.tsx
- src/components/SandboxViolationExpandedView.tsx
- src/services/api/claude.ts
- src/types/message.ts
- src/commands/ultraplan.tsx
- src/services/skillSearch/localSearch.ts
- src/bridge/remoteBridgeCore.ts
- src/utils/claudemd.ts
- src/utils/computerUse/win32/windowMessage.ts
- src/components/BuiltinStatusLine.tsx
- src/commands/skill-learning/skill-learning.ts
- src/utils/model/modelOptions.ts
| 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'), | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify how many runtime branches depend on NODE_ENV development.
rg -n --type=ts --type=tsx -C2 "process\.env\.NODE_ENV.*development|NODE_ENV as string.*development"
# Confirm the dev launcher currently forces production.
sed -n '14,24p' scripts/dev.tsRepository: claude-code-best/claude-code
Length of output: 519
🏁 Script executed:
# Search for NODE_ENV development checks (fixing rg file type filter)
rg -n "NODE_ENV.*development|development.*NODE_ENV" --type ts -A2 -B2
# Check the specific files mentioned in the review
echo "=== desktopDeepLink.ts ==="
rg -n "NODE_ENV" src/utils/desktopDeepLink.ts -C3
echo "=== doctorDiagnostic.ts ==="
rg -n "NODE_ENV" src/utils/doctorDiagnostic.ts -C3Repository: claude-code-best/claude-code
Length of output: 6645
🏁 Script executed:
# Check build/dev script context
echo "=== scripts directory ==="
ls -la scripts/
echo "=== Check build script NODE_ENV handling ==="
rg -n "NODE_ENV" scripts/ --type ts
echo "=== Check if there's a separate build launcher ==="
rg -n "NODE_ENV.*production" scripts/ --type ts -C3
echo "=== Check React-related config for production mode comment context ==="
rg -n "debugStack|6,889" . --type ts --type tsxRepository: claude-code-best/claude-code
Length of output: 1791
🏁 Script executed:
# Read dev.ts in full to understand the production mode context
cat -n scripts/dev.ts
echo "=== dev-debug.ts ==="
cat -n scripts/dev-debug.ts
echo "=== Check package.json for script invocations ==="
rg -n "dev\.ts|dev-debug" . -t json --type toml -C2Repository: claude-code-best/claude-code
Length of output: 2872
Hardcoded production NODE_ENV in dev launcher breaks dev-only diagnostics and workflows.
Lines 17–22 force all process.env.NODE_ENV checks to 'production' at compile time. This disables 15+ dev-only branches across the codebase (doctorDiagnostic.ts, desktopDeepLink.ts, DevBar.tsx, warningHandler.ts, AutoUpdater components, and others), breaking developer diagnostic features and install-type detection. While the React memory optimization comment is valid, it should not disable the entire dev experience.
Make the production mode opt-in via environment variable while preserving the React optimization for developers who need it.
🔧 Suggested fix
+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),
}Developers who need the React optimization can opt in: CLAUDE_CODE_FORCE_NODE_ENV=production bun run dev
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 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'), | |
| } | |
| const forcedNodeEnv = process.env.CLAUDE_CODE_FORCE_NODE_ENV ?? process.env.NODE_ENV ?? 'development'; | |
| const defines = { | |
| ...getMacroDefines(), | |
| 'process.env.NODE_ENV': JSON.stringify(forcedNodeEnv), | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/dev.ts` around lines 17 - 22, The current defines object hardcodes
'process.env.NODE_ENV' to 'production' which disables dev-only branches; change
this so the production value is applied only when a new opt-in env var (e.g.
CLAUDE_CODE_FORCE_NODE_ENV) is set: keep the defines and getMacroDefines() usage
but set 'process.env.NODE_ENV' to
JSON.stringify(process.env.CLAUDE_CODE_FORCE_NODE_ENV || process.env.NODE_ENV ||
'development') (or equivalent) so developers default to dev mode while allowing
opt-in production mode for the React memory optimization when
CLAUDE_CODE_FORCE_NODE_ENV=production is provided; update any related comments
to reflect the opt-in behavior and reference the defines symbol and
getMacroDefines().
| useMasterMonitor(); | ||
| useSlaveNotifications(); | ||
| const pipeIpcState = useAppState(s => getPipeIpc(s as any)); | ||
| const _pipeIpcState = useAppState(s => getPipeIpc(s as any)); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify no prohibited `as any` assertions remain in TS/TSX production files.
# Expected: zero matches in src/** after applying the fix.
rg -nP --type=ts --type=tsx '\bas\s+any\b' srcRepository: claude-code-best/claude-code
Length of output: 100
🏁 Script executed:
#!/bin/bash
# Search for `as any` patterns in TypeScript/TSX files
# Using fd to find files, then rg to search within them
fd '\.(ts|tsx)$' src --exec rg -n 'as\s+any' {} +Repository: claude-code-best/claude-code
Length of output: 100714
🏁 Script executed:
cat -n src/screens/REPL.tsx | sed -n '4935,4945p'Repository: claude-code-best/claude-code
Length of output: 564
🏁 Script executed:
# Find the useAppState hook definition
rg -n "export.*useAppState|function useAppState|const useAppState" --type=ts --type=tsx -A 3 srcRepository: claude-code-best/claude-code
Length of output: 100
🏁 Script executed:
# Find getPipeIpc function definition
rg -n "export.*getPipeIpc|function getPipeIpc|const getPipeIpc" --type=ts --type=tsx -A 3 srcRepository: claude-code-best/claude-code
Length of output: 100
🏁 Script executed:
# Look at the imports and context around line 4940 in REPL.tsx
head -n 4945 src/screens/REPL.tsx | tail -n 20Repository: claude-code-best/claude-code
Length of output: 694
🏁 Script executed:
# Find useAppState definition
rg -n "useAppState" src --max-count=5 | head -20Repository: claude-code-best/claude-code
Length of output: 1935
🏁 Script executed:
# Find getPipeIpc function definition
rg -n "getPipeIpc" src --max-count=10 | head -30Repository: claude-code-best/claude-code
Length of output: 2467
🏁 Script executed:
# Look at imports at the top of REPL.tsx around getPipeIpc
head -n 100 src/screens/REPL.tsx | grep -E "import|getPipeIpc"Repository: claude-code-best/claude-code
Length of output: 2131
🏁 Script executed:
sed -n '715,730p' src/utils/pipeTransport.tsRepository: claude-code-best/claude-code
Length of output: 415
🏁 Script executed:
rg -n "useAppState.*getPipeIpc" srcRepository: claude-code-best/claude-code
Length of output: 432
🏁 Script executed:
# Check how useAppState is typed
sed -n '100,120p' src/state/AppState.tsxRepository: claude-code-best/claude-code
Length of output: 775
Remove the unnecessary as any cast from the AppState selector.
Line 4940 uses s as any, but this cast is redundant. The getPipeIpc function is explicitly designed to accept state: any, as shown in its definition at src/utils/pipeTransport.ts:721. Other usages of this selector throughout the codebase (e.g., in useMasterMonitor.ts and useSlaveNotifications.ts) call getPipeIpc(s) without any cast. Simply remove the as any cast to match the pattern:
Suggested fix
- const _pipeIpcState = useAppState(s => getPipeIpc(s as any));
+ const _pipeIpcState = useAppState(s => getPipeIpc(s));🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/screens/REPL.tsx` at line 4940, Remove the unnecessary cast in the
selector: change the useAppState call that assigns _pipeIpcState to call
getPipeIpc with the selector argument directly (useAppState(s => getPipeIpc(s)))
instead of casting s to any; update the line referencing _pipeIpcState in
REPL.tsx to remove "as any" so it matches other usages like useMasterMonitor and
useSlaveNotifications and relies on getPipeIpc’s accepted any-typed parameter.
| SystemAPIErrorMessage, | ||
| } from '../../../types/message.js' | ||
| import { getEmptyToolPermissionContext, type Tools } from '../../../Tool.js' | ||
| import { type Tools } from '../../../Tool.js' |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Use path alias import instead of deep relative path
Line 9 still uses a ../../../ import, which violates the TS import-path guideline. Please switch to the src/* alias form.
Suggested change
-import { type Tools } from '../../../Tool.js'
+import type { Tools } from 'src/Tool.js'As per coding guidelines: "Use src/* path alias in imports; do not use relative paths like ../../../".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { type Tools } from '../../../Tool.js' | |
| import type { Tools } from 'src/Tool.js' |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/services/api/gemini/index.ts` at line 9, Replace the deep-relative import
of the Tools type in src/services/api/gemini/index.ts with the project
path-alias form: change the import that references '../../../Tool.js' to use the
'src/...' alias (import { type Tools } from 'src/...') so the file imports Tools
via the src path alias instead of a '../../../' relative path; keep the imported
symbol name (Tools) unchanged.
| // Disabled: file checkpointing causes unbounded memory growth (100 snapshots × full file backups). | ||
| // See heap snapshot analysis — re-enable only after switching to incremental diffs. | ||
| const MAX_SNAPSHOTS = 20 |
There was a problem hiding this comment.
Misleading comment: feature is not disabled, just throttled.
The comment says "Disabled" but MAX_SNAPSHOTS = 20 keeps file checkpointing enabled with a lower cap. Other call sites still gate via fileHistoryEnabled(). The comment will confuse future readers about whether snapshots are still being taken.
📝 Suggested wording
-// Disabled: file checkpointing causes unbounded memory growth (100 snapshots × full file backups).
-// See heap snapshot analysis — re-enable only after switching to incremental diffs.
+// Reduced from 100 to mitigate unbounded memory growth (full file backups × N snapshots).
+// See heap snapshot analysis — only raise this cap after switching to incremental diffs.
const MAX_SNAPSHOTS = 20📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Disabled: file checkpointing causes unbounded memory growth (100 snapshots × full file backups). | |
| // See heap snapshot analysis — re-enable only after switching to incremental diffs. | |
| const MAX_SNAPSHOTS = 20 | |
| // Reduced from 100 to mitigate unbounded memory growth (full file backups × N snapshots). | |
| // See heap snapshot analysis — only raise this cap after switching to incremental diffs. | |
| const MAX_SNAPSHOTS = 20 |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/utils/fileHistory.ts` around lines 54 - 56, The comment above
MAX_SNAPSHOTS is misleading because snapshots are throttled, not disabled;
update the comment to accurately state that file checkpointing remains enabled
but capped to prevent unbounded growth and refer to the gating via
fileHistoryEnabled(). Locate the MAX_SNAPSHOTS constant and replace the
"Disabled" wording with a note like "Throttled: file checkpointing remains
enabled but capped at MAX_SNAPSHOTS (see fileHistoryEnabled() gating) and
re-enable full backups only after switching to incremental diffs," ensuring the
comment mentions the reason (heap snapshot growth) and the intended future
change.
| function getEntriesByType(type: string): PerformanceEntryLike[] { | ||
| if (type === 'mark') { | ||
| return [...marks.entries()].map(([name, startTime]) => ({ | ||
| name, | ||
| entryType: 'mark', | ||
| startTime, | ||
| duration: 0, | ||
| })) | ||
| } | ||
| if (type === 'measure') { | ||
| return [...measures.values()].map(m => ({ | ||
| name: m.name, | ||
| entryType: 'measure', | ||
| startTime: m.startTime, | ||
| duration: m.duration, | ||
| })) | ||
| } | ||
| return [] | ||
| } | ||
|
|
||
| function getEntriesByName(name: string, type?: string): PerformanceEntryLike[] { | ||
| const entries = getEntriesByType(type ?? 'mark').concat( | ||
| type === undefined ? getEntriesByType('measure') : [], | ||
| ) | ||
| return entries.filter(e => e.name === name) | ||
| } |
There was a problem hiding this comment.
Missing performance.getEntries() (no-arg variant) — as typeof performance cast hides the gap.
The shim implements getEntriesByType and getEntriesByName but not the no-argument getEntries() overload, even though the final cast at line 151 (as typeof performance) advertises it. Any consumer that calls performance.getEntries() will hit a TypeError: performance.getEntries is not a function after the shim is installed. Bun, OTel exporters, and various dev/observability tooling do call this.
The same gap exists for markResourceTiming, setResourceTimingBufferSize (you stub-typed the latter but not the former), eventCounts, and the EventTarget surface (addEventListener/removeEventListener/dispatchEvent). If the shim is meant to replace globalThis.performance wholesale, missing these creates a foot-gun once any new dependency starts using them.
🛡️ Add a no-arg getEntries() at minimum
+function getEntries(): PerformanceEntryLike[] {
+ return [...getEntriesByType('mark'), ...getEntriesByType('measure')]
+}
+
const shim = {
now,
mark,
measure: measure as typeof performance.measure,
+ getEntries: getEntries as typeof performance.getEntries,
getEntriesByType: getEntriesByType as typeof performance.getEntriesByType,#!/bin/bash
# Find callers that would break under the shim.
rg -nP --type=ts -C2 '\bperformance\.(getEntries|markResourceTiming|addEventListener|eventCounts)\b'
rg -nP --type=ts -C2 'globalThis\.performance\.(getEntries|markResourceTiming|addEventListener|eventCounts)\b'🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/utils/performanceShim.ts` around lines 81 - 106, Add the missing
no-argument overload and other missing members to the shim so it fully matches
typeof performance: implement performance.getEntries() to return the union of
getEntriesByType('mark') and getEntriesByType('measure') (reuse
getEntriesByType/getEntriesByName logic), and add stubbed/pass-through
implementations for markResourceTiming, setResourceTimingBufferSize (already
stub-typed but ensure the function exists), eventCounts, and the
EventTarget-like methods addEventListener/removeEventListener/dispatchEvent on
the shim object; ensure their signatures match the standard
Performance/EventTarget surface so the final "as typeof performance" cast is
accurate and consumers calling performance.getEntries() or the other APIs won't
throw.
| get onresourcetimingbufferfull() { | ||
| return (original as any).onresourcetimingbufferfull | ||
| }, | ||
| set onresourcetimingbufferfull(_v: any) { | ||
| // no-op — prevent accumulation | ||
| }, | ||
| toJSON() { | ||
| return original.toJSON() | ||
| }, | ||
| } as typeof performance | ||
|
|
||
| /** | ||
| * Install the shim onto globalThis.performance. Safe to call multiple times. | ||
| * Must run before React and OTel import to prevent them from capturing the | ||
| * native Performance reference. | ||
| */ | ||
| export function installPerformanceShim(): void { | ||
| if ((globalThis as any).__performanceShimInstalled) return | ||
| ;(globalThis as any).__performanceShimInstalled = true |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
as any violates the project's TypeScript guideline.
Four as any / : any usages remain in production code: line 143 ((original as any).onresourcetimingbufferfull), line 145 (_v: any), and lines 159–160 ((globalThis as any).__performanceShimInstalled). Per the coding guideline, prefer as unknown as SpecificType or extend an interface.
♻️ Replace with safer assertions
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
},
@@
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
}As per coding guidelines, "Prohibit as any type assertions in production code; ... Use as unknown as SpecificType double assertion or interface supplementation when type mismatches occur".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| get onresourcetimingbufferfull() { | |
| return (original as any).onresourcetimingbufferfull | |
| }, | |
| set onresourcetimingbufferfull(_v: any) { | |
| // no-op — prevent accumulation | |
| }, | |
| toJSON() { | |
| return original.toJSON() | |
| }, | |
| } as typeof performance | |
| /** | |
| * Install the shim onto globalThis.performance. Safe to call multiple times. | |
| * Must run before React and OTel import to prevent them from capturing the | |
| * native Performance reference. | |
| */ | |
| export function installPerformanceShim(): void { | |
| if ((globalThis as any).__performanceShimInstalled) return | |
| ;(globalThis as any).__performanceShimInstalled = true | |
| get onresourcetimingbufferfull() { | |
| return (original as Performance & { onresourcetimingbufferfull?: unknown }) | |
| .onresourcetimingbufferfull | |
| }, | |
| set onresourcetimingbufferfull(_v: unknown) { | |
| // no-op — prevent accumulation | |
| }, | |
| toJSON() { | |
| return original.toJSON() | |
| }, | |
| } as typeof performance | |
| /** | |
| * Install the shim onto globalThis.performance. Safe to call multiple times. | |
| * Must run before React and OTel import to prevent them from capturing the | |
| * native Performance reference. | |
| */ | |
| export function installPerformanceShim(): void { | |
| const g = globalThis as typeof globalThis & { __performanceShimInstalled?: boolean } | |
| if (g.__performanceShimInstalled) return | |
| g.__performanceShimInstalled = true |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/utils/performanceShim.ts` around lines 142 - 160, The code uses unsafe
`as any` casts in the performance shim; replace them with safer
double-assertions or proper typings: cast `original` to the correct
Performance-like interface using `as unknown as { onresourcetimingbufferfull?:
EventListener | null; toJSON: () => any; [k: string]: any }` (or extend the
Performance interface) so the getter `onresourcetimingbufferfull` and the
`toJSON()` call use typed access instead of `(original as any)`, change the
setter parameter `_v: any` to a typed parameter (e.g. `_v: EventListener |
null`) or `_v: unknown` then cast only if needed, and replace `(globalThis as
any).__performanceShimInstalled` with `(globalThis as unknown as {
__performanceShimInstalled?: boolean }).__performanceShimInstalled` (or add an
ambient declaration), updating references in `get onresourcetimingbufferfull`,
`set onresourcetimingbufferfull`, `toJSON`, and `installPerformanceShim`
accordingly.
Need help on this PR? Tag
@codesmithwith what you need.Summary by CodeRabbit
Bug Fixes
Chores