Skip to content

chore: cherry-pick 8 upstream PRs for review#1

Merged
bourgois merged 12 commits into
mainfrom
cherry-picks/upstream-features
May 30, 2026
Merged

chore: cherry-pick 8 upstream PRs for review#1
bourgois merged 12 commits into
mainfrom
cherry-picks/upstream-features

Conversation

@bourgois
Copy link
Copy Markdown
Owner

Cherry-picks 8 open upstream PRs (siteboon/claudecodeui) for review before merging into the fork.

PRs included

# Title
#737 fix(claude-sync): skip subagent JSONL files to prevent main session corruption
#770 fix(websocket): add 30s server-side heartbeat to prevent proxy idle disconnects
#757 fix(vite): proxy /plugin-ws WebSocket requests to the backend in dev
#788 fix(chat): re-anchor initial scroll across lazy content reflow
#802 feat: add Codex permission env fallback
#810 fix: prevent system context from rendering as user messages
#811 feat: add scroll navigation for chat messages
#753 feat: add file upload button with progress bar and improve terminal session limits

Conflict resolutions

kamioj and others added 12 commits May 30, 2026 16:19
…orruption

Subagent transcripts under `~/.claude/projects/.../<project>/subagents/`
share their parent's sessionId. Indexing them as standalone sessions
overwrites the parent's row in the sessions DB, which breaks session
resume and history listing.

Skip them in both the bulk `synchronize()` scan and the watcher-driven
`synchronizeFile()` entry point. Path check covers Windows backslash and
POSIX slash so the same guard works regardless of how findFilesRecursively
emits the path.
…isconnects

The WebSocket gateway never sent ping frames, so any reverse proxy with
an idle timeout (Cloudflare Tunnel ~100s, AWS ALB 60s, nginx 60s, etc.)
would silently tear down /shell, /ws and /plugin-ws/* connections after
the idle window. The UI reconnects automatically but users see a
"Connecting to shell" toast every 1–3 minutes during normal use and any
in-flight PTY/chat traffic can race the reconnect.

Schedule a 30s ws.ping() per connection at the gateway level, cleared on
close/error. ping/pong counts as protocol activity for all proxies that
implement WebSocket correctly, so this single change covers every
deployment topology without per-proxy tuning.

Fixes siteboon#769
Plugin WebSocket connections (e.g. the official Terminal plugin) hang
in `npm run dev` because Vite proxies /api, /ws, and /shell but not
/plugin-ws/*. Production is unaffected because the same Express server
serves both the frontend and the WS gateway.
The previous initial-scroll behavior fired one scrollToBottom() at
+200ms after the session load and cleared the pending flag. When
markdown, syntax highlighting, or images finished rendering after
that window, scrollHeight grew but nothing re-anchored the viewport.
The chat tab appeared "scrolled way up" with the latest assistant
message off-screen until the user manually scrolled or sent a new
message.

This replaces the setTimeout with a requestAnimationFrame loop that
re-scrolls every frame while scrollHeight is still growing, capped
at ~1s (60 frames) or 3 consecutive stable frames. The loop cancels
cleanly on session change via the existing pendingInitialScrollRef
flag, and the cleanup function cancels any in-flight rAF on unmount.

No behavior change for sessions whose content layout is already stable
at the first frame.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SDK emits synthetic user messages (subagent prompts, context resumption,
internal bookkeeping) with message.role === 'user' during streaming, which
were incorrectly rendered as user chat bubbles. After streaming completes,
refreshFromServer replaces these with clean history, so the bug only
manifests during the streaming phase.

Changes:
- Add isHumanOrigin gate using SDK fields (isSynthetic, origin.kind) and
  permissionMode marker to filter non-user text parts
- Detect and skip context resumption summary messages
- Filter image data URIs from rendering as user messages
- Add subagent prompt echo filtering via normalized whitespace comparison
- Move refreshFromServer after session ID remap in complete handler
- Fix pendingUserMessage visibility with hasUserMessage check
- Improve scroll-based message loading with loadMoreMessages callback
- Add projectPath resolution for session recovery from terminal
- Sync session custom names to Claude CLI history on startup
- Prevent empty project_path overwrite in session upsert
- Expand ANSI stripping to handle OSC and control sequences

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Remove debug console.log statements before merge
- Remove unused 'os' import in sessions.service.ts
- Allow surrounding whitespace in taskNotifRegex
- Check for echoed pending message specifically, not any user message

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add a scroll navigation bar with dots and quick-jump buttons to navigate
between user messages in long chat sessions.

Changes:
- Add ScrollNavigation component with dot indicators for each user message
- Previous/Next buttons for sequential navigation
- First/Last buttons for quick jump to start/end
- Load all button when messages are paginated
- Integration with ChatMessagesPane and ChatInterface
- Improve message loading with explicit loadMoreMessages callback
- Fix pendingUserMessage visibility with hasUserMessage check
- Add i18n strings for scroll navigation in all languages

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Trim content before task-notification regex matching
- Remove hardcoded Chinese fallback text

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ession limits

- Add upload button to file tree header with file picker dialog
- Replace fetch-based upload with XMLHttpRequest for real-time progress tracking
- Add progress bar UI in file tree during uploads
- Increase file upload size limit from 50MB to 200MB
- Extend PTY session timeout from 30min to 4 hours
- Increase terminal buffer limit from 5000 to 100000 entries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Reduce global body-parser limit from 200MB to 10MB (uploads use multer)
- Replace O(n) Array.shift() with batch slice() for PTY buffer management
- Reduce PTY buffer cap from 100K to 20K and session timeout from 240min to 60min
- Add batched reconnect replay with setImmediate back-pressure
- Add isUploadingRef guard to prevent concurrent upload race conditions
@bourgois
Copy link
Copy Markdown
Owner Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

Reviewed:

  • Subagent JSONL skip logic across synchronize() and synchronizeFile() — functionally equivalent on POSIX
  • isSubagentPromptEcho startsWith branch — low collision risk in practice given Task prompt lengths
  • isHumanOrigin guard coverage in normalizeMessage() — missing from the textParts fallback path but synthetic messages reaching that path are uncommon
  • [DEBUG] console.log statements in the file upload handler — present but user-triggered, not automatic
  • JSON body limit reduction 50MB→10MB — upload paths correctly bypass via multipart; no regression
  • paginableMessages pagination refactor — tool_result attachment via toolResultMap runs before filtering, so tool_use cards render correctly
  • All normalizeMessage() callers updated or using providers that don't require subagentPrompts

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@bourgois bourgois merged commit ffcbfaa into main May 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants