[pull] main from xintaofei:main#147
Merged
Merged
Conversation
The rich-diff viewer passed keepCurrentOriginalModel/keepCurrentModifiedModel while feeding plain strings, so the two anonymous Monaco models it creates per mount were never disposed — every diff open or switch leaked both. Dropping the flags lets the library dispose them on unmount; the commit, unstash, and push dialogs reuse the same viewer and are covered too.
@monaco-editor/react keeps a model alive for every path it has shown: switching paths only setModel()s away and unmount disposes just the attached one, so each file opened during a session left its model (full text, tokenization, undo stack) in the registry after its tab closed. The workspace panel now records the model URIs it created and disposes the ones whose tab is gone whenever tab membership changes — guarded by isAttachedToEditor() and scoped strictly to its own URIs, so models owned by others (diff editors' anonymous pairs) are never touched. The keep-set derivation lives in collectLiveModelPaths with unit tests.
…wrapper Untiled, nothing in the conversation tile wrapper can scroll, yet its always-initialized OverlayScrollbars instance answered every streaming DOM mutation with a forced-reflow scrollWidth read — the largest single JS cost in performance traces. The new TileScrollContainer keeps the host/contents DOM constant across tile flips (so toggling tile mode never remounts the conversation subtree or tears down a live response) and only creates the OverlayScrollbars decoration while tiling is on, destroying it when tiling turns off.
…ssage cards Radix Collapsible measures its content on every open-on-mount (disable animation, getBoundingClientRect, restore), which turned a history conversation full of expanded cards into a forced-layout storm inside a single React commit — while nothing ever consumed the measured CSS variables. The message-path cards (tool, reasoning, tool groups, goal, agent capsule, agent prompt) now use ui/instant-collapsible: same component API, data/aria attributes, and unmount-when-closed contract, with close animations still playing via a lightweight exit presence that never reads layout. Non-message collapsibles (file tree, commit card, settings) keep the Radix version.
Multi-sub-turn assistant replies were re-merged into fresh group/parts/sourceTurns objects on every streaming batch, defeating the memo of every merged card in the viewport. mergeConsecutiveAssistantTurns now reuses the merged item while the run's membership (member group references and item keys) is unchanged; runs containing the streaming turn still rebuild each batch by design. The showStats/isRoleTransition/ previousUserIndex pass resets each flag before recomputing so a cached item cannot carry stale values across renders.
Every 16ms live-message batch replaces the session object, so the per-session timeline memo missed and rebuilt all four phases plus the dedup pass on each batch — the one per-frame cost that grew with conversation length. The persisted/local/background/optimistic prefix is now cached on the detail object with a field-by-field deps check (including the conversation id, so a migration re-homing the same detail object cannot leak another conversation's keys), and only the small streaming tail is rebuilt per batch: a tail with no key collisions appends via a fast path, and collisions fall back to the full role-aware dedup with unchanged keep-first (user) / keep-last (assistant) semantics.
Agents that advertise `image: false` with `embedded_context: true` (e.g. Grok) accept images only as embedded resources, so a pasted image took the generic file path and rendered as an inline file badge instead of a top thumbnail like image-capable agents. Route pasted/dropped/picked images to the thumbnail strip whenever the agent supports images or embedded context, and encode each per capability at send time — a native image block when supported, otherwise an embedded resource blob — leaving the sent payload unchanged per agent. Image-mime embedded resources restore as thumbnails on queue re-edit.
Grok carries a user image as an embedded resource (image mime + blob), but every user-message display path recognized only native image blocks: the sent bubble dropped the image, and a reopened session showed an empty attachment bubble instead of the picture. Normalize an image-mime embedded resource to an image at each boundary — the optimistic draft, the broadcast/snapshot fold (user_blocks_from_prompt), and the Grok transcript parser, which also merges the prose and image chunks of one prompt into a single user turn. Existing image rendering is reused and the wire format is unchanged.
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
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )