- IChatSession/IChatTurn interfaces: add optional numCtx field
- Mongoose schemas: add numCtx field to ChatSession and ChatTurn
- API controller: validate numCtx (>=16384, multiple of 8192)
- ChatSessionService: persist numCtx on session, pass through to turn
- SessionPanel: add range slider for Context Window (hidden for OpenAI)
- Drone buildDroneModelConfig: prefer turn.numCtx over model defaults
Complete Phase 1 of subprocess management in gadget-drone:
- SubProcessService with graceful shutdown (SIGINT→SIGKILL), halt, getLog
- SubprocessTool with create/list/kill/killAll/halt/log commands
- Registered in agent toolbox for build/test/ship/develop modes
- Fixed missing {{process_management_block}} replacement in chat-session.ts
- 34 unit tests across service and tool
- Comprehensive documentation in docs/subprocess.md
Documents:
- Complete session history and what was accomplished
- ACE → CodeMirror migration rationale and steps
- Flex layout height constraint fix pattern
- Key technical learnings (CJS/ESM interop, flex layouts)
- Remaining steps organized by priority (high/medium/low)
- Continuation prompt template for next session
- MVP success criteria (all ✅ complete)
This serves as the handoff document for the next developer
or AI agent continuing work on User Mode.
Documents the complete ACE → CodeMirror migration, including:
- Root cause analysis of react-ace CJS/ESM incompatibility with Vite
- Migration steps and rationale for @uiw/react-codemirror
- Flex layout height constraint fix and the underlying pattern
- Key technical learnings about CJS/ESM interop and flex layouts
- Remaining steps and continuation prompt for next session
This serves as the authoritative reference for why we use CodeMirror
and how to properly constrain third-party components in flex layouts.
The editor was overflowing its container because @uiw/react-codemirror
renders a wrapper div that doesn't inherit flex constraints by default.
Fixed by adding CSS rules that:
1. Set overflow:hidden on .cm-editor-container
2. Target the wrapper div (> div) with flex:1, min-height:0, overflow:hidden
3. Set .cm-editor and .cm-scroller to overflow appropriately
This ensures the flex height constraint propagates through every level
of the CodeMirror DOM tree, and only .cm-scroller scrolls.
Layout chain:
.cm-editor-container (flex-1, min-h-0)
└─ wrapper div (flex:1, min-h-0, overflow:hidden)
└─ .cm-editor (flex:1, min-h-0, overflow:hidden)
└─ .cm-scroller (min-h-0, overflow:auto) ← only this scrolls
react-ace v14 is CommonJS-only with no ESM entry point, making it
fundamentally incompatible with Vite's ESM-first dev server. Every
CJS interop workaround failed. Switched to @uiw/react-codemirror v4.25
which ships proper dual ESM+CJS and works with Vite out of the box.
Changes:
- Remove ace-builds and react-ace dependencies
- Add @uiw/react-codemirror + 16 @codemirror/lang-* packages
- Add @uiw/codemirror-theme-tomorrow-night-blue (closest to ACE's 'tomorrow')
- Add @replit/codemirror-lang-csharp for C# support
- Rewrite EditorPanel.tsx: delete 108 lines of ACE boilerplate
(?url imports, setModuleUrl, CJS interop hack), replace with
~30 lines of clean CodeMirror language extension setup
- Delete vite.d.ts (only needed for ACE ?url import types)
- Remove optimizeDeps.include from vite.config.ts (not needed for CM)
- Add CodeMirror flex layout CSS to index.css
Supported languages: JavaScript/JSX, TypeScript/TSX, Python, JSON,
HTML, CSS, Less, YAML, Markdown, SQL, Java, Go, Rust, C/C++, C#,
PHP, XML. Unsupported types fall back to plain text.
Verified: tsc clean, vite build passes, heartbeat worker intact.
react-ace v14 ships CommonJS only ('main': 'lib/index.js'). Vite's dev
server pre-bundling wraps CJS modules as namespace objects where the
default export is nested under .default. This caused 'Element type is
invalid: got object' because import Ace from 'react-ace' resolved to
the module namespace instead of the React component.
Fix: import * as ReactAceModule and extract default with fallback:
const Ace = ReactAceModule.default || ReactAceModule
Same treatment for ace-builds import. Production build (Rolldown) was
unaffected due to different CJS interop handling.
- Added react-ace and ace-builds to optimizeDeps.include
- This forces Vite to properly bundle the CommonJS react-ace module
- Resolves 'Element type is invalid' error when opening files
The react-ace package uses CommonJS exports, and Vite needs to
pre-bundle it to properly handle the default export in ESM context.
- Fixed Ace import (default import, not named)
- Moved EditorPanel from FilesPanel to ChatSessionView
- Editor now replaces chat view when file is selected (per UI design guide)
- FILES panel now contains only the file tree
- Added editorFilePath state to track open file
- File selection in tree opens editor in content area
- Close button returns to chat view
This matches the UI design guide specification where the File Editor
replaces the Chat View in the content area when a file is selected.
Root Cause: CSS flex items default to min-height: auto, which prevents
flex-1 elements from shrinking below their content size. This caused
the FilesPanel to grow beyond its allocated space when the file tree
had many entries, pushing content off-screen.
Changes:
- FilesPanel.tsx: Added min-h-0 to root div to override min-height: auto
This allows flex-1 to actually constrain height and enable scrolling
- FileTree.tsx: Removed redundant overflow-auto and h-full from root div
The parent (FilesPanel flex-1 overflow-auto) already handles scrolling.
Nested scroll containers create height resolution issues.
The sidebar layout is now a clean single-scroll-container hierarchy:
Sidebar (flex flex-col, no overflow)
↳ SESSION (shrink-0, natural height)
↳ PROJECT (shrink-0, natural height)
↳ FilesPanel (flex-1 min-h-0) — constrained to available space
↳ Header (natural height)
↳ Scroll area (flex-1 overflow-auto) — THE scroll container
↳ FileTree (p-2 only) — no overflow, no h-full
↳ Footer (natural height)
- SESSION and PROJECT panels now have shrink-0 to prevent them from
growing unbounded and pushing FILES panel off-screen
- FILES panel with flex-1 now properly fills remaining vertical space
- File tree scrolls in-place while SESSION/PROJECT stay fixed
- FileTree had flex-1 inside an overflow container which didn't work
- Changed to h-full to properly fill the parent container height
- Scrolling now works correctly in the file tree area
- The sidebar container had overflow-y-auto which caused the entire sidebar
to scroll when FILES panel content grew
- FILES panel already has proper flex-1 and internal overflow-auto handling
- Now only the file tree scrolls in place while SESSION and PROJECT panels
remain fixed as expected
- Fixes UX issue where entire sidebar would scroll vertically
- Add flex-1 to FilesPanel root div
- Sidebar is flex flex-col, FILES panel now grows to fill space
- SESSION and PROJECT panels remain natural height
- FILES panel expands into all remaining vertical space
This eliminates the gap below the FILES panel footer by making
the panel itself grow rather than just making the tree bigger.
- Remove max-h-80 constraint from FileTree
- FileTree uses flex-1 to expand and fill available space
- Panel now properly fills sidebar from top to bottom
- File tree scrolls internally when content overflows
The FILES panel header, file tree, and footer now form a proper
flex column that fills all remaining vertical space in the sidebar.
- Change FilesPanel overflow-hidden to overflow-auto for scrolling
- Add max-h-80 to FileTree to limit height while allowing scroll
- Add select-none to FileTreeNode to prevent text selection
- Cursor-pointer already present for clickable indication
Now the file tree scrolls independently within the FILES panel,
and text cannot be selected during rapid clicking.
CRITICAL FIX: Remove recursion from listDirectoryForTree function.
The backend was recursively fetching ALL subdirectories and returning
them as a flat list, which completely broke the lazy-loading model.
Changes:
- Remove recursive call in listDirectoryForTree
- Backend now returns ONLY immediate children
- Frontend handles lazy loading by requesting children on expand
- This matches the intended architecture where frontend controls tree
This fixes the issue where directory contents were duplicated and
the tree structure was corrupted when expanding/collapsing.
- Add debug logging to track project directory resolution
- Improve path traversal security check with proper separator handling
- Log entry count and first 10 entries for debugging
- Fix project root validation to prevent listing workspace root
The issue was that the tree was listing from the workspace root
(containing gadget-code/, gadget-drone/, packages/) instead of the
specific project directory. Added logging to help diagnose.
- Replace recursive buildTree with buildVisibleNodes approach
- Build flat list of visible nodes based on expanded state
- Use processNode helper to traverse tree structure correctly
- Each node appears exactly once in the rendered output
- Eliminates duplication when expanding directories
- Change buildTree from .map() to for-loop to properly render children
- Append expanded directory children to nodes array immediately
- Fix TypeScript error by using ReactElement instead of JSX.Element
- Children now render correctly when directories are expanded
- Create comprehensive plan document for agent instructions text area
- Define requirements, acceptance criteria, and technical implementation
- Include UI/UX mockups and testing strategy
- Plan discovered during FILES panel implementation
- Addresses need for project-specific acceptance criteria