Streaming tool UI fix (ChatView.tsx):
- Add toolUsesRef/toolResultsRef to reliably track tool data across closures
- Serialize tool_use/tool_result into JSON content-blocks array when building
assistant message after stream ends, matching backend storage format
- MessageItem.parseToolBlocks() now renders tool UI from history messages
- Clean up refs in finally block and timeout auto-retry path
File tree UX (FileTree.tsx, file-tree.tsx):
- Remove folder path header from right panel, merge search + refresh into one row
- Remove file icon spacer (size-5) so file icons align flush with search box
- Change folder icon color from blue to muted-foreground
Chat list panel (ChatListPanel.tsx):
- Folder header: expanded uses FolderOpenIcon, collapsed uses Folder01Icon
- Add tooltip showing full working directory path on folder hover
- Double-click folder header opens in system file manager
Title bar folder name (chat/[id]/page.tsx):
- Add tooltip with full path on project name hover
- Click opens folder in Finder/Explorer via Electron IPC or API fallback
Open folder support:
- electron/main.ts: add shell:open-path IPC handler via shell.openPath
- electron/preload.ts: expose electronAPI.shell.openPath to renderer
- api/files/open/route.ts: fallback API route using open/explorer/xdg-open
Unify icon library — migrate app-level components from Lucide to Hugeicons:
- file-tree.tsx: folder, file, chevron, plus icons
- tool-actions-group.tsx: chevron expand icon
- MessageItem.tsx: copy, check, expand/collapse icons
- MessageInput.tsx: stop button (SquareIcon → StopIcon)
- FileCard.tsx: file icon
- ImageLightbox.tsx: left/right navigation arrows
- InstallWizard.tsx: status icons (check, x, minus, loader, circle, copy, download)
- Keep Lucide in ui/ and ai-elements/ base layers (shadcn standard)
Core fixes:
- Add settingSources to SDK options so CodePilot loads user/project settings
like the CLI (fixes WebFetch timeouts, tool permission issues)
- Delete CLAUDECODE env var to prevent nested session detection when
CodePilot runs alongside Claude Code CLI (fixes 'exited with code 1')
- Remove manual MCP config reading (SDK handles it via settingSources)
- Remove hardcoded timeout env vars (SDK loads from user settings)
UX improvements:
- Remember last selected model across sessions (localStorage)
- Same-project new chat skips directory picker
- File tree auto-refreshes on project switch and after each tool completes
- Left sidebar projects default collapsed (only most recent expanded)
- Right-side file tree defaults collapsed
- Fix file tree icon alignment (spacer size-4 → size-5)
- Dynamic model list from /api/providers/models endpoint
- Provider change dispatches event to refresh model selector
- Improved error messages with provider name and troubleshooting hints
- Fix context button file type matching for extension patterns
- Default tool timeout 120s → 300s
The chat route and claude-client both fell back to process.cwd() when
working_directory was empty, causing Claude to operate in the server's
directory instead of the user's project. Since session creation now
requires a valid working_directory, these fallbacks are unnecessary
and misleading. Fall back to os.homedir() as a safer last resort.
Also update CLAUDE.md: require explicit user confirmation before
publishing releases (no auto push+tag).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Backend: POST /api/chat/sessions now validates working_directory
exists (400 MISSING_DIRECTORY / INVALID_DIRECTORY)
- db.ts: remove process.cwd() fallback in createSession
- ChatListPanel: validate last-working-directory before use,
open FolderPicker when invalid; add SSR guard for localStorage
- NewChatPage: block sending without a project directory selected
Bump version to 0.10.5.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Upload route now passes persisted filePath to claude-client, which
reuses it instead of writing the file again.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add configurable tool timeout with auto-retry: when a tool exceeds the
timeout threshold, abort and send a follow-up message asking Claude to
try a different approach
- Add "+" button on file tree items to attach files directly to chat
input via new /api/files/raw endpoint and custom event bridge
- Add force stop button in streaming status bar when tool runs >90s,
with warning indicators at 60s
- Improve doc preview markdown rendering (padding, list indentation)
- Bump version to 0.10.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously uploaded files were only held in memory (optimistic message)
and lost when navigating away. Now:
- API route saves all uploaded files to .codepilot-uploads/ on disk
- File metadata (with filePath, not base64) is embedded in message content
- New /api/uploads endpoint serves persisted files
- FileAttachmentDisplay handles both base64 (in-memory) and filePath (DB)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Support image (JPEG/PNG/GIF/WebP, max 5MB) and document uploads
- Images sent as multimodal content blocks to Claude SDK
- Documents saved to temp dir for Claude's Read tool
- Emerald capsule badges in input for attached files
- Drag-and-drop, paste, and file picker support via PromptInput
- Chat display: image thumbnails with lightbox, file cards
- Lightbox uses Radix Dialog with prev/next navigation
- File metadata embedded in message content as HTML comments
- Compatible with existing slash command badge system
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Slash commands:
- Fix skills not appearing (removed non-existent `enabled` filter)
- Add badge/capsule UI for prompt-type commands (/compact, /review, etc.)
- SDK-native commands sent directly; CLI-only commands expanded to prompts
- /clear now resets SDK session and clears database messages
- /cost shows actual aggregated token usage statistics
- Keyboard: Backspace/Escape to remove badge, arrow keys auto-scroll popover
- Add /memory command for editing CLAUDE.md
Multi-provider management:
- CRUD API for API providers with SQLite storage
- ProviderManager UI with quick presets (GLM, Kimi, MiniMax, etc.)
- Dynamic model labels based on active provider
- Environment variable injection with conflict resolution
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The collectStreamResponse() function only collected text events,
discarding tool_use and tool_result events. When a conversation was
resumed, all tool call context was lost — the user only saw the
text portions of Claude's responses.
Changes:
- Collect tool_use and tool_result SSE events as MessageContentBlock
entries alongside text blocks
- Flush accumulated text into a text block before each tool_use to
preserve the interleaved ordering (text → tool_use → tool_result →
text → ...)
- Store messages with tool calls as JSON arrays of MessageContentBlock,
using the existing type definitions in types/index.ts
- Text-only messages remain as plain strings for backward compatibility
with existing message rendering (parseMessageContent handles both)
- Add 10 unit tests covering parsing, serialization, round-tripping,
edge cases, and backward compatibility (all passing)
This enables future improvements like:
- Rendering tool call history in resumed conversations
- Showing which files were read/written in previous turns
- Exporting full conversation logs with tool context
Return full error stack traces from the sessions API and display
the actual server error in the frontend, instead of a generic
"Failed to create session" message.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full-featured desktop application built with Next.js + Electron:
- Streaming chat with Claude Code via Agent SDK
- Session management with SQLite persistence
- Project file tree and file preview
- MCP server and custom skills management
- Permission controls with Code/Plan/Ask modes
- Dark/light theme, token tracking
- macOS DMG packaging with electron-builder
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>