-
Notifications
You must be signed in to change notification settings - Fork 451
perf: Optimize message sync loop and add LRU cache eviction #148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
nilskroe
wants to merge
90
commits into
21st-dev:main
from
nilskroe:fix/chat-performance-memory-leaks
Closed
perf: Optimize message sync loop and add LRU cache eviction #148
nilskroe
wants to merge
90
commits into
21st-dev:main
from
nilskroe:fix/chat-performance-memory-leaks
+28
−0
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Open source release of 1Code - Best UI for Claude Code with Local and Remote agent execution. Apache License 2.0
## What's New in v0.0.11 ### Changes - Renamed app from Agents to 1Code - Fixed appId to dev.21st.agents for auto-update compatibility - Prevent todo list flickering and improve streaming UX - Handle stale lock files from crashed instances - Show Open PR button when no uncommitted changes - Improved auto-update UX
## What's New in v0.0.12
### Features
- Drafts section in sidebar with preview and delete functionality
- Interrupted state for tools - shows "{toolName} interrupted" when stopping agent with ESC
- Tooltip with full file path when hovering over truncated filenames
- "See what's new" banner after app updates with link to changelog
### Improvements & Fixes
- Fixed sub-chat renaming not persisting to database
- Fixed editor focus after drag & drop image insertion
- Pending questions now bound to specific sub-chat (no longer appear in wrong chat)
- Fixed duplicate text in todo tool when status is in_progress
- Renamed "Premium support" button to "Feedback"
- Performance optimizations for pending questions
## What's New in v0.0.16 ### Improvements & Fixes - Fixed authentication redirect URL for packaged app - Fixed sidebar workspace timestamps updating on message send - Exclude session/plan files from changed files status bar - Reduced stop button icon size in send button
Adds ability to clone repos directly from GitHub by entering a URL or owner/repo format.
Repos are stored in userData/repos/{owner}/{repo}.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Stores cloned repos alongside worktrees for consistency. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Shows "Clone from GitHub" button alongside "Select folder" during first-time setup. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## What's New in v0.0.18 ### Improvements & Fixes - Fixed sidebar flickering when switching between chats
## What's New ### Features - Added Cmd+Enter shortcut for "Implement plan" button - Improved archive popover: auto-unarchive on selection, input clears on revisit ### Fixes - Fixed sidebar flickering when switching between chats
## What's New ### Features - Added Cmd+Enter shortcut for "Implement plan" button - Improved archive popover: auto-unarchive on selection, input clears on revisit
## What's New ### Fixes - Fixed z-index layering for sticky user message bubble - Removed MCP servers indicator from header
Prevent message submission during IME composition (Chinese/Japanese/Korean input). Users can now use Enter to confirm IME candidate selection without triggering message send. Added isComposing check to both AgentsMentionsEditor and PromptInputTextarea components. Changes: - agents-mentions-editor.tsx: Add !e.nativeEvent.isComposing check - prompt-input.tsx: Add !e.nativeEvent.isComposing check
## What's New ### Fixes - Fixed scroll behavior: users can now scroll up freely during streaming - Fixed input lag by deferring trigger detection to next frame
Add animated GIF demos for key features: - Worktree isolation and background agent execution - Cursor-like UI with diff previews and git client - Plan mode with clarifying questions and structured plans Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix IME composition issue with Enter key
Add animated GIF demos for key features: - Worktree isolation and background agent execution - Cursor-like UI with diff previews and git client - Plan mode with clarifying questions and structured plans Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move GIF assets to root assets/ directory and update paths in README. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## What's New ### Fixes - Fixed scroll behavior: users can now scroll up freely during streaming - Fixed input lag by deferring trigger detection to next frame - Fixed tool display state during streaming
## What's New ### Features - Added scroll-to-bottom button with Cmd+↓ hotkey - Archive now kills terminal processes and deletes worktree ### Fixes - Fixed excessive re-renders in sidebar during scroll - Restored copy and play buttons for AI messages - ESC now skips AskQuestion instead of stopping stream - Show full command in collapsed tool view - Fixed tool display state during streaming
Update download URL to include binary name
fix: Add author email in package.json for .deb package generation
Add clone from GitHub feature
## What's New ### Features - **Kanban Board View** — New Kanban board view for managing workspaces - **Voice Input** — Voice dictation with OpenAI Whisper API - **Extensible Mention Providers** — Add custom mention providers for @ mentions - **Custom Hotkeys in Context Menus** — Your keyboard shortcuts now show in context menus ### Improvements & Fixes - **Kanban UI** — Smaller, centered columns for better layout - **Plan Indicator** — Removed PlanIcon from plan update status indicator - **Kanban Settings** — Hide Kanban hotkey in settings when feature is disabled
…v#93) When typing a command prefix, suggestions now appear sorted by name length (shortest first). This makes the closest match appear first. Example: typing "ape" now shows "/apex" before "/apex-analyze". Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…1st-dev#102) Co-authored-by: Jeremy Holstein <jjjrmy@gmail.com>
- Add right-click context menu for terminal with copy/paste support - If text is selected: copies to clipboard and shows toast notification - If no selection: pastes from clipboard - Fix Ctrl+V paste by intercepting the key to prevent xterm showing ^v and letting Electron's menu paste role handle it via paste event - Works on both Windows and macOS Co-authored-by: Claude <noreply@anthropic.com>
…t-dev#100) Prevent SQLite migration crash on startup. `0005_marvelous_master_chief.sql` may run `ALTER TABLE sub_chats DROP COLUMN ...` on DBs where these columns never existed, causing `SQLITE_ERROR: no such column` and aborting migrations. Remove the unsafe DROP COLUMN statements (keep index creation). Related: 15ee551 (PR 21st-dev#87) - https://github.com/paul-bouzian/1code/blob/15ee55107f3eefbf012fb9754484f987b9fbf399/drizzle/0005_marvelous_master_chief.sql#L1-L4 - https://github.com/paul-bouzian/1code/blob/15ee55107f3eefbf012fb9754484f987b9fbf399/drizzle/meta/_journal.json#L40-L46
…1st-dev#80) * feat: add platform provider abstraction for cross-platform support Introduce a platform provider pattern to centralize all platform-specific logic (Windows, macOS, Linux) in one place. This fixes Windows shell command execution issues and improves maintainability. Changes: - Add platform provider interface and implementations for Windows, macOS, Linux - Refactor cli.ts to use platform provider for CLI installation - Refactor terminal/env.ts to use platform provider for shell detection - Refactor claude/env.ts to use platform provider for environment building - Refactor claude-token.ts to use platform provider for PATH extension - Fix path separator issues (use path.basename instead of split('/')) The platform provider handles: - Shell configuration and detection - PATH building with common tool locations - Environment variable setup - CLI installation/uninstallation - Locale detection Co-Authored-By: Claude <noreply@anthropic.com> * fix: address PR review feedback Based on PR 21st-dev#80 review by @serafimcloud: 1. Windows PATH limitation (Critical): - Remove `setx PATH` which has 1024 char limit and can truncate PATH - CLI install dir is already in buildExtendedPath() for app usage - Return pathHint for users who want terminal access 2. Variable shadowing (Critical): - Rename `path` to `filePath` in chats.ts to avoid shadowing the imported `path` module 3. Electron coupling (Medium): - Remove unused `app` import from windows.ts - Remove unused `exec`, `promisify`, `lstatSync` imports 4. execCommand consistency (Low): - Add documentation explaining execCommand is for simple commands - Complex shell commands (osascript, pipes) may use exec directly Co-Authored-By: Claude <noreply@anthropic.com> * fix(windows): install CLI to ~/.local/bin instead of %LOCALAPPDATA% - Install to ~/.local/bin which is already in buildExtendedPath() - Avoids needing to modify system PATH or prompt user - App can find CLI automatically via extended PATH - Users with ~/.local/bin in their PATH can use it from terminal too Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
## What's New ### Features - **Multi-Account Support** — Switch between multiple Anthropic accounts - **Remote Sandbox Chats** — Full support for remote sandbox chats - **Default Agent Mode** — Set default agent mode preference with per-chat mode isolation — thanks @serafimcloud! (21st-dev#102) - **Batch Discard** — Multi-select files for batch discard in changes view - **Terminal Copy/Paste** — Improved terminal copy/paste support on Windows — thanks @ChrisPei! (21st-dev#91) ### Improvements & Fixes - **Command Autocomplete** — Sort by name length for better UX — thanks @paul-bouzian! (21st-dev#93) - **SQLite Migration Fix** — Prevent crash on sub_chats drop column — thanks @a3my! (21st-dev#100) - **Cross-Platform Support** — Add platform provider abstraction — thanks @ChrisPei! (21st-dev#80) - **Theme Selector** — Add scroll and max-height to dropdown - **Kanban View** — Various fixes and improvements
## What's New ### Improvements & Fixes - **Chat Stability** — Improved chat remounting and migration idempotency - **Selected Text Indicator** — Show "Using selected text" bubble for pasted text attachments - **UI Polish** — Updated spinner icons and selectors to match desktop style
## What's New ### Improvements & Fixes - **MCP Cache Fix** — Fixed MCP caching issues - **Tool UI Polish** — Improved expand button spacing in bash/edit tools - **Onboarding Cleanup** — Removed welcome dialog and streamlined sidebar
## What's New ### Bug Fixes - **Startup Crash Fix** — Fixed "Cannot find module async-mutex" error that prevented app from launching
## What's New ### Features - **Copy Plan** — Copy plan content to clipboard - **Raw Plan View** — View raw markdown of implementation plans ### Improvements & Fixes - **New Subchat Button** — Fixed blocked state for add subchat button - **Message Store** — Include meta in message store state - **Community PRs** — Merged community contributions (21st-dev#117, 21st-dev#118)
FIX: Reply Sends To Wrong Sub-Chat In Multi-Chat Workspace
## What's New ### Features - **Automations & Inbox** — New automations and inbox pages (beta — enable in Settings → Beta) - **Open in Editor** — Open worktree workspaces directly in your code editor ### Improvements & Fixes - **Expired Questions UX** — Keep expired AskUserQuestion visible and send answers as messages — thanks @jjjrmy! (21st-dev#121) - **Default Model Fix** — Fixed chat UI disabled state when creating new chat with wrong default model
## What's New ### Features - **Open Automations in Browser** — Automations now open in browser with external link icon ### Improvements & Fixes - **Send Now Fix** — Fixed queued messages being lost when clicking "Send Now" during streaming — thanks @jjjrmy! (21st-dev#126) - **Symlinks in Skills** — Fixed symlink handling in skills - **Compact Commands** — Improved compact command display - **Plan Text Fix** — Fixed build plan text rendering
…t-dev#141) The "viewed" file tracking (GitHub-style eye icon) was showing inconsistent state across different UI panels during a session. agent-diff-view checked content hashes to detect changes, but changes-view and changes-widget only checked the boolean flag, causing files to appear as "viewed" even after their content changed. Two fixes: 1. agent-diff-view now proactively invalidates stale viewed entries in the shared atom when it detects content hash mismatches, so all consumers see the correct state 2. changes-widget now uses the exact diff key from ParsedDiffFile instead of guessing possible key formats from the file path Co-authored-by: Claude <noreply@anthropic.com>
…ng new one (21st-dev#135) The "Add Account" button was calling `disconnect()` which deleted the currently active account before opening the onboarding flow. This caused new accounts to overwrite previous ones instead of storing both. Now the Add button simply opens the onboarding dialog without disconnecting, allowing users to add multiple accounts that are properly stored. Fixes ENG-587 Co-authored-by: Claude <claude@anthropic.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…ab (21st-dev#140) The pendingPrMessage, pendingReviewMessage, and pendingConflictMessage atoms are global and shared across all ChatViewInner instances. When multiple sub-chat tabs are mounted, any non-streaming inactive tab could consume the pending message before the active tab, sending the PR creation prompt to the wrong Claude session. This made Create PR appear broken since the user wouldn't see the message in their active tab. Add isActive guard to all three pending message effects so only the currently active tab consumes and sends pending messages. Co-authored-by: Claude <noreply@anthropic.com>
The applyRollbackStash function was returning true (success) when a checkpoint wasn't found, which caused the rollbackToMessage mutation to proceed with truncating messages even though the git state wasn't reverted. This led to message history being out of sync with git state. Changed the return type to a discriminated union that explicitly indicates whether a checkpoint was found and applied, allowing the caller to handle the case properly. Now rollback will fail with a clear error message when the checkpoint doesn't exist. Co-authored-by: Claude <assistant@claude.ai> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Skills and agents from project-level .claude/ folders were not showing up in the settings tab or @ mention dropdown because the frontend was not passing the project path (cwd) to the backend tRPC queries. Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Read AGENTS.md from project root and pass its content to the Claude SDK via systemPrompt append, and include it in Ollama offline context. This allows users who maintain AGENTS.md files in their projects to have those instructions automatically loaded into chat sessions. Co-authored-by: Claude <noreply@anthropic.com>
## What's New ### Features - **File Viewer Sidebar** — Monaco Editor-powered file viewer with theme support, custom context menu, and find widget - **Cmd+P File Search** — Quick file search dialog with recently opened files - **Terminal Display Modes** — Switch between sidebar and bottom panel terminal layout - **AGENTS.md Support** — Project-level instructions via AGENTS.md files - **Task Tools in Sidebar** — Show task tools in details sidebar todo widget ### Improvements & Fixes - **Reply to Wrong Sub-Chat Fix** — Fixed pending messages being sent to inactive sub-chat tab — thanks @jjjrmy! (21st-dev#127) - **Project-Level Skills Discovery** — Pass project path to skills and agents queries — thanks @amal-irgashev! (21st-dev#132) - **Relative Paths in Tools** — Show relative paths instead of absolute in tool UI - **Attachments Layout** — Render all attachment blocks in a single row above message bubble - **Any File Attachments** — Allow attaching any file type in chat - **Cmd+J Terminal Toggle** — Toggle terminal with keyboard shortcut - **Rollback Fix** — Handle checkpoint not found gracefully - **Multi-Account Fix** — Stop deleting active account when adding new one - **File Icons** — Added icons for .gitignore, .npmrc, .prettierrc, and .txt files - **Sub Agent Labels** — Renamed Task tool display labels to Sub agent
## What's New ### Features - **Full-Page Settings Redesign** — Settings converted from modal dialog to a full-page two-panel layout with grouped sections, custom icons, and dedicated tabs for MCP, Skills, and Agents - **MCP Servers Sidebar Widget** — New MCP servers widget in the details sidebar with server icons, tool listing, and mention integration (click a tool to @-mention it in chat) - **MCP Button in Input** — Quick access to MCP servers directly from the chat input area - **Terminal Display Mode Switcher** — Switch terminal between sidebar and bottom panel layouts - **Task Tools in Details Sidebar** — Todo widget now shows task tools for better visibility ### Improvements & Fixes - Auto-save model overrides on blur with border separators in Models tab - Project icon caching and fix for spurious auto-save triggers - Settings back button aligned with tab buttons - Widget settings drag and click behavior improved - Cmd+J toggle terminal with resize tooltip and click-to-close - Relative file path display in agent tools using projectPath - Direct PR creation restored (ENG-592) - Dependency updates ## Downloads - [Apple Silicon (arm64)](https://cdn.21st.dev/releases/desktop/1Code-0.0.53-arm64.dmg) - [Intel (x64)](https://cdn.21st.dev/releases/desktop/1Code-0.0.53.dmg)
This addresses critical performance issues for long chat sessions: 1. O(1) sync during streaming (was O(n)): - During streaming, only the last message changes - Now only checks the last message instead of all messages - Full sync only happens when IDs change or on first sync 2. O(1) LRU cache eviction for subchats: - Uses Map's insertion order for O(1) LRU operations - Tracks most recent subChat to skip redundant updates during streaming - Automatically evicts oldest subchat caches when threshold exceeded (10 max) - Prevents unbounded memory growth in long-running sessions 3. O(1) textPartCache cleanup: - Tracks cache keys per message for instant cleanup - No more O(n) iteration through all keys when removing a message 4. Better cache cleanup in clearSubChatCaches(): - Clears textPartCache entries using tracked keys - Clears messageStructureCache entries Performance impact: - Streaming sync: O(n) -> O(1) where n = message count - LRU operations: O(n) -> O(1) - Cache cleanup: O(total keys) -> O(keys for message) - Memory: Bounded by MAX_CACHED_SUBCHATS (10) instead of unbounded
9dff50f to
ec4ca66
Compare
1. Deep clone nested objects in message sync
- Previously only shallow cloned `input` field
- Now also clones `output`, `result`, and `error` to ensure Jotai
detects all changes and components re-render properly
2. Eliminate duplicate token calculation
- active-chat.tsx had O(n) useMemo that iterated all messages
- Now uses centralized messageTokenDataAtom from message-store
- Atom uses caching to achieve O(1) lookups during streaming
- Added totalCostUsd to the centralized atom for full parity
1. Add abort() method to agentChatStore - Calls chat.stop() to abort any active stream - Sets manuallyAborted flag to prevent completion sounds - Handles errors gracefully (chat may already be stopped) 2. Update delete() to call abort() first - Ensures stream is stopped before removing references - Prevents orphaned tRPC subscriptions 3. LRU cache eviction now aborts streams - When oldest sub-chat is evicted, abort its stream first - Prevents background streams from continuing after cache cleared - Saves CPU, memory, and network bandwidth
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
This PR addresses critical performance issues for long chat sessions:
Performance Optimizations
output,result, anderrorfields in message sync, ensuring Jotai detects all changes.Stream Lifecycle Fixes
agentChatStore.delete()now callsabort()first to ensure streams are stopped before removing references, preventing orphaned tRPC subscriptions.Performance Impact
Test Plan