restore: recover deleted documentation, CI/CD, and infrastructure files
Restored from origin/main (b4663fb): - .github/ workflows and issue templates - .gitignore (proper exclusions) - .opencode/agent/web_developer.md - AGENTS.md, BUILD.md, PROGRESS.md - dev-docs/ (9 architecture/implementation docs) - docs/screenshots/ (4 UI screenshots) - images/ (CodeNomad icons) - package-lock.json (dependency lockfile) - tasks/ (25+ project task files) Also restored original source files that were modified: - packages/ui/src/App.tsx - packages/ui/src/lib/logger.ts - packages/ui/src/stores/instances.ts - packages/server/src/server/routes/workspaces.ts - packages/server/src/workspaces/manager.ts - packages/server/src/workspaces/runtime.ts - packages/server/package.json Kept new additions: - Install-*.bat/.sh (enhanced installers) - Launch-*.bat/.sh (new launchers) - README.md (SEO optimized with GLM 4.7)
This commit is contained in:
180
dev-docs/INDEX.md
Normal file
180
dev-docs/INDEX.md
Normal file
@@ -0,0 +1,180 @@
|
||||
# Documentation Index
|
||||
|
||||
Quick reference to all documentation files.
|
||||
|
||||
## Main Documents
|
||||
|
||||
### [README.md](../README.md)
|
||||
|
||||
Project overview, installation, and getting started guide.
|
||||
|
||||
### [SUMMARY.md](SUMMARY.md)
|
||||
|
||||
Executive summary of the entire project - **start here!**
|
||||
|
||||
### [MVP-PRINCIPLES.md](MVP-PRINCIPLES.md)
|
||||
|
||||
**MVP development philosophy** - Focus on functionality, NOT performance ⚡
|
||||
|
||||
---
|
||||
|
||||
## Specification Documents
|
||||
|
||||
### [architecture.md](architecture.md)
|
||||
|
||||
**Complete system architecture**
|
||||
|
||||
- Component layers and responsibilities
|
||||
- State management structure
|
||||
- Data flow diagrams
|
||||
- Technology stack
|
||||
- Security and performance considerations
|
||||
|
||||
**Read this to understand:** How the app is structured
|
||||
|
||||
### [user-interface.md](user-interface.md)
|
||||
|
||||
**Complete UI/UX specifications**
|
||||
|
||||
- Every screen and component layout
|
||||
- Visual design specifications
|
||||
- Interaction patterns
|
||||
- Accessibility requirements
|
||||
- Color schemes and typography
|
||||
|
||||
**Read this to understand:** What the app looks like and how users interact
|
||||
|
||||
### [technical-implementation.md](technical-implementation.md)
|
||||
|
||||
**Implementation details**
|
||||
|
||||
- File structure
|
||||
- TypeScript interfaces
|
||||
- Process management logic
|
||||
- SDK integration patterns
|
||||
- IPC communication
|
||||
- Error handling strategies
|
||||
|
||||
**Read this to understand:** How to actually build it
|
||||
|
||||
### [build-roadmap.md](build-roadmap.md)
|
||||
|
||||
**Development plan**
|
||||
|
||||
- 8 phases of development
|
||||
- Task dependencies
|
||||
- Timeline estimates
|
||||
- Success criteria
|
||||
- Risk mitigation
|
||||
|
||||
**Read this to understand:** The development journey from start to finish
|
||||
|
||||
---
|
||||
|
||||
## Task Documents
|
||||
|
||||
### [tasks/README.md](../tasks/README.md)
|
||||
|
||||
**Task management guide**
|
||||
|
||||
- Task workflow
|
||||
- Naming conventions
|
||||
- How to work on tasks
|
||||
- Progress tracking
|
||||
|
||||
### Task Files (in tasks/todo/)
|
||||
|
||||
- **001-project-setup.md** - Electron + SolidJS boilerplate
|
||||
- **002-empty-state-ui.md** - Initial UI with folder selection
|
||||
- **003-process-manager.md** - OpenCode server spawning
|
||||
- **004-sdk-integration.md** - API client integration
|
||||
- **005-session-picker-modal.md** - Session selection UI
|
||||
|
||||
More tasks will be added as we progress through phases.
|
||||
|
||||
---
|
||||
|
||||
## Reading Order
|
||||
|
||||
### For First-Time Readers:
|
||||
|
||||
1. [SUMMARY.md](SUMMARY.md) - Get the big picture
|
||||
2. [architecture.md](architecture.md) - Understand the structure
|
||||
3. [user-interface.md](user-interface.md) - See what you're building
|
||||
4. [build-roadmap.md](build-roadmap.md) - Understand the plan
|
||||
5. [tasks/README.md](../tasks/README.md) - Learn the workflow
|
||||
|
||||
### For Implementers:
|
||||
|
||||
1. [tasks/README.md](../tasks/README.md) - Understand task workflow
|
||||
2. [technical-implementation.md](technical-implementation.md) - Implementation patterns
|
||||
3. [tasks/todo/001-\*.md](../tasks/todo/) - Start with first task
|
||||
4. Refer to architecture.md and user-interface.md as needed
|
||||
|
||||
### For Designers:
|
||||
|
||||
1. [user-interface.md](user-interface.md) - Complete UI specs
|
||||
2. [architecture.md](architecture.md) - Component structure
|
||||
3. [SUMMARY.md](SUMMARY.md) - Feature overview
|
||||
|
||||
### For Project Managers:
|
||||
|
||||
1. [SUMMARY.md](SUMMARY.md) - Executive overview
|
||||
2. [build-roadmap.md](build-roadmap.md) - Timeline and phases
|
||||
3. [tasks/README.md](../tasks/README.md) - Task tracking
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Common Questions
|
||||
|
||||
**Q: Where do I start?**
|
||||
A: Read [SUMMARY.md](SUMMARY.md), then start [Task 001](../tasks/todo/001-project-setup.md)
|
||||
|
||||
**Q: How long will this take?**
|
||||
A: See [build-roadmap.md](build-roadmap.md) - MVP in 3-7 weeks depending on commitment
|
||||
|
||||
**Q: What does the UI look like?**
|
||||
A: See [user-interface.md](user-interface.md) for complete specifications
|
||||
|
||||
**Q: How does it work internally?**
|
||||
A: See [architecture.md](architecture.md) for system design
|
||||
|
||||
**Q: How do I build feature X?**
|
||||
A: See [technical-implementation.md](technical-implementation.md) for patterns
|
||||
|
||||
**Q: What's the development plan?**
|
||||
A: See [build-roadmap.md](build-roadmap.md) for phases
|
||||
|
||||
---
|
||||
|
||||
## Document Status
|
||||
|
||||
| Document | Status | Last Updated |
|
||||
| --------------------------- | ----------- | ------------ |
|
||||
| README.md | ✅ Complete | 2024-10-22 |
|
||||
| SUMMARY.md | ✅ Complete | 2024-10-22 |
|
||||
| architecture.md | ✅ Complete | 2024-10-22 |
|
||||
| user-interface.md | ✅ Complete | 2024-10-22 |
|
||||
| technical-implementation.md | ✅ Complete | 2024-10-22 |
|
||||
| build-roadmap.md | ✅ Complete | 2024-10-22 |
|
||||
| tasks/README.md | ✅ Complete | 2024-10-22 |
|
||||
| Task 001-005 | ✅ Complete | 2024-10-22 |
|
||||
|
||||
**Project phase:** Post-MVP (Phases 1-3 complete; Phase 4 work underway).
|
||||
|
||||
---
|
||||
|
||||
## Contributing to Documentation
|
||||
|
||||
When updating documentation:
|
||||
|
||||
1. Update the relevant file
|
||||
2. Update "Last Updated" in this index
|
||||
3. Update SUMMARY.md if adding major changes
|
||||
4. Keep consistent formatting and style
|
||||
|
||||
---
|
||||
|
||||
_This index will be updated as more documentation is added._
|
||||
326
dev-docs/MVP-PRINCIPLES.md
Normal file
326
dev-docs/MVP-PRINCIPLES.md
Normal file
@@ -0,0 +1,326 @@
|
||||
# MVP Development Principles
|
||||
|
||||
## Core Philosophy
|
||||
|
||||
**Focus on functionality, NOT performance.**
|
||||
|
||||
The MVP (Minimum Viable Product) is about proving the concept and getting feedback. Performance optimization comes later, after we validate the product with real users.
|
||||
|
||||
---
|
||||
|
||||
## What We Care About in MVP
|
||||
|
||||
### ✅ DO Focus On:
|
||||
|
||||
1. **Functionality**
|
||||
- Does it work?
|
||||
- Can users complete their tasks?
|
||||
- Are all core features present?
|
||||
|
||||
2. **Correctness**
|
||||
- Does it produce correct results?
|
||||
- Does error handling work?
|
||||
- Is data persisted properly?
|
||||
|
||||
3. **User Experience**
|
||||
- Is the UI intuitive?
|
||||
- Are loading states clear?
|
||||
- Are error messages helpful?
|
||||
|
||||
4. **Stability**
|
||||
- Does it crash?
|
||||
- Can users recover from errors?
|
||||
- Does it lose data?
|
||||
|
||||
5. **Code Quality**
|
||||
- Is code readable?
|
||||
- Are types correct?
|
||||
- Is it maintainable?
|
||||
|
||||
### ❌ DON'T Focus On:
|
||||
|
||||
1. **Performance Optimization**
|
||||
- Virtual scrolling
|
||||
- Message batching
|
||||
- Lazy loading
|
||||
- Memory optimization
|
||||
- Render optimization
|
||||
|
||||
2. **Scalability**
|
||||
- Handling 1000+ messages
|
||||
- Multiple instances with 100+ sessions
|
||||
- Large file attachments
|
||||
- Massive search indexes
|
||||
|
||||
3. **Advanced Features**
|
||||
- Plugins
|
||||
- Advanced search
|
||||
- Custom themes
|
||||
- Workspace management
|
||||
|
||||
---
|
||||
|
||||
## Specific MVP Guidelines
|
||||
|
||||
### Messages & Rendering
|
||||
|
||||
**Simple approach:**
|
||||
|
||||
```typescript
|
||||
// Just render everything - no virtual scrolling
|
||||
<For each={messages()}>
|
||||
{(message) => <MessageItem message={message} />}
|
||||
</For>
|
||||
```
|
||||
|
||||
**Don't worry about:**
|
||||
|
||||
- Sessions with 500+ messages
|
||||
- Re-render performance
|
||||
- Memory usage
|
||||
- Scroll performance
|
||||
|
||||
**When to optimize:**
|
||||
|
||||
- Post-MVP (Phase 8)
|
||||
- Only if users report issues
|
||||
- Based on real-world usage data
|
||||
|
||||
### State Management
|
||||
|
||||
**Simple approach:**
|
||||
|
||||
- Use SolidJS signals directly
|
||||
- No batching
|
||||
- No debouncing
|
||||
- No caching layers
|
||||
|
||||
**Don't worry about:**
|
||||
|
||||
- Update frequency
|
||||
- Number of reactive dependencies
|
||||
- State structure optimization
|
||||
|
||||
### Process Management
|
||||
|
||||
**Simple approach:**
|
||||
|
||||
- Spawn servers as needed
|
||||
- Kill on close
|
||||
- Basic error handling
|
||||
|
||||
**Don't worry about:**
|
||||
|
||||
- Resource limits (max processes)
|
||||
- CPU/memory monitoring
|
||||
- Restart optimization
|
||||
- Process pooling
|
||||
|
||||
### API Communication
|
||||
|
||||
**Simple approach:**
|
||||
|
||||
- Direct SDK calls
|
||||
- Basic error handling
|
||||
- Simple retry (if at all)
|
||||
|
||||
**Don't worry about:**
|
||||
|
||||
- Request batching
|
||||
- Response caching
|
||||
- Optimistic updates
|
||||
- Request deduplication
|
||||
|
||||
---
|
||||
|
||||
## Decision Framework
|
||||
|
||||
When implementing any feature, ask:
|
||||
|
||||
### Is this optimization needed for MVP?
|
||||
|
||||
**NO if:**
|
||||
|
||||
- It only helps with large datasets
|
||||
- It only helps with many instances
|
||||
- It's about speed, not correctness
|
||||
- Users won't notice the difference
|
||||
- It adds significant complexity
|
||||
|
||||
**YES if:**
|
||||
|
||||
- Users can't complete basic tasks without it
|
||||
- App is completely unusable without it
|
||||
- It prevents data loss
|
||||
- It's a security requirement
|
||||
|
||||
### Examples
|
||||
|
||||
**Virtual Scrolling:** ❌ NO for MVP
|
||||
|
||||
- MVP users won't have 1000+ message sessions
|
||||
- Simple list rendering works fine for <100 messages
|
||||
- Add in Phase 8 if needed
|
||||
|
||||
**Error Handling:** ✅ YES for MVP
|
||||
|
||||
- Users need clear feedback when things fail
|
||||
- Prevents frustration and data loss
|
||||
- Core to usability
|
||||
|
||||
**Message Batching:** ❌ NO for MVP
|
||||
|
||||
- SolidJS handles updates efficiently
|
||||
- Only matters at very high frequency
|
||||
- Add later if users report lag
|
||||
|
||||
**Session Persistence:** ✅ YES for MVP
|
||||
|
||||
- Users expect sessions to persist
|
||||
- Losing work is unacceptable
|
||||
- Core functionality
|
||||
|
||||
---
|
||||
|
||||
## Testing Approach
|
||||
|
||||
### MVP Testing Focus
|
||||
|
||||
**Test for:**
|
||||
|
||||
- ✅ Correctness (does it work?)
|
||||
- ✅ Error handling (does it fail gracefully?)
|
||||
- ✅ Data integrity (is data saved?)
|
||||
- ✅ User flows (can users complete tasks?)
|
||||
|
||||
**Don't test for:**
|
||||
|
||||
- ❌ Performance benchmarks
|
||||
- ❌ Load testing
|
||||
- ❌ Stress testing
|
||||
- ❌ Scalability limits
|
||||
|
||||
### Acceptable Performance
|
||||
|
||||
For MVP, these are **acceptable:**
|
||||
|
||||
- 100 messages render in 1 second
|
||||
- UI slightly laggy during heavy streaming
|
||||
- Memory usage grows with message count
|
||||
- Multiple instances slow down app
|
||||
|
||||
These become **unacceptable** only if:
|
||||
|
||||
- Users complain
|
||||
- App becomes unusable
|
||||
- Basic tasks can't be completed
|
||||
|
||||
---
|
||||
|
||||
## When to Optimize
|
||||
|
||||
### Post-MVP Triggers
|
||||
|
||||
Add optimization when:
|
||||
|
||||
1. **User Feedback**
|
||||
- Multiple users report slowness
|
||||
- Users abandon due to performance
|
||||
- Performance prevents usage
|
||||
|
||||
2. **Measurable Issues**
|
||||
- App freezes for >2 seconds
|
||||
- Memory usage causes crashes
|
||||
- UI becomes unresponsive
|
||||
|
||||
3. **Phase 8 Reached**
|
||||
- MVP complete and validated
|
||||
- User base established
|
||||
- Performance becomes focus
|
||||
|
||||
### How to Optimize
|
||||
|
||||
When the time comes:
|
||||
|
||||
1. **Measure First**
|
||||
- Profile actual bottlenecks
|
||||
- Use real user data
|
||||
- Identify specific problems
|
||||
|
||||
2. **Target Fixes**
|
||||
- Fix the specific bottleneck
|
||||
- Don't over-engineer
|
||||
- Measure improvement
|
||||
|
||||
3. **Iterate**
|
||||
- Optimize one thing at a time
|
||||
- Verify with users
|
||||
- Stop when "fast enough"
|
||||
|
||||
---
|
||||
|
||||
## Communication with Users
|
||||
|
||||
### During Alpha/Beta
|
||||
|
||||
**Be honest about performance:**
|
||||
|
||||
- "This is an MVP - expect some slowness with large sessions"
|
||||
- "We're focused on functionality first"
|
||||
- "Performance optimization is planned for v1.x"
|
||||
|
||||
**Set expectations:**
|
||||
|
||||
- Works best with <200 messages per session
|
||||
- Multiple instances may slow things down
|
||||
- We'll optimize based on your feedback
|
||||
|
||||
### Collecting Feedback
|
||||
|
||||
**Ask about:**
|
||||
|
||||
- ✅ What features are missing?
|
||||
- ✅ What's confusing?
|
||||
- ✅ What doesn't work?
|
||||
- ✅ Is it too slow to use?
|
||||
|
||||
**Don't ask about:**
|
||||
|
||||
- ❌ How many milliseconds for X?
|
||||
- ❌ Memory usage specifics
|
||||
- ❌ Benchmark comparisons
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
### The MVP Mantra
|
||||
|
||||
> **Make it work, then make it better, then make it fast.**
|
||||
|
||||
For CodeNomad MVP:
|
||||
|
||||
- **Phase 1-7:** Make it work, make it better
|
||||
- **Phase 8+:** Make it fast
|
||||
|
||||
### Remember
|
||||
|
||||
- Premature optimization is the root of all evil
|
||||
- Real users provide better optimization guidance than assumptions
|
||||
- Functionality > Performance for MVP
|
||||
- You can't optimize what users don't use
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
**When in doubt, ask:**
|
||||
|
||||
1. Is this feature essential for users to do their job? → Build it
|
||||
2. Is this optimization essential for the feature to work? → Build it
|
||||
3. Is this just making it faster/more efficient? → Defer to Phase 8
|
||||
|
||||
**MVP = Minimum _Viable_ Product**
|
||||
|
||||
- Viable = works and is useful
|
||||
- Viable ≠ optimized and fast
|
||||
348
dev-docs/SUMMARY.md
Normal file
348
dev-docs/SUMMARY.md
Normal file
@@ -0,0 +1,348 @@
|
||||
# CodeNomad - Project Summary
|
||||
|
||||
## Current Status
|
||||
|
||||
We have completed the MVP milestones (Phases 1-3) and are now operating in post-MVP mode. Future work prioritizes multi-instance support, advanced input polish, and system integrations outlined in later phases.
|
||||
|
||||
## What We've Created
|
||||
|
||||
A comprehensive specification and task breakdown for building the CodeNomad desktop application.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
packages/opencode-client/
|
||||
├── docs/ # Comprehensive documentation
|
||||
│ ├── architecture.md # System architecture & design
|
||||
│ ├── user-interface.md # UI/UX specifications
|
||||
│ ├── technical-implementation.md # Technical details & patterns
|
||||
│ ├── build-roadmap.md # Phased development plan
|
||||
│ └── SUMMARY.md # This file
|
||||
├── tasks/
|
||||
│ ├── README.md # Task management guide
|
||||
│ ├── todo/ # Tasks to implement
|
||||
│ │ ├── 001-project-setup.md
|
||||
│ │ ├── 002-empty-state-ui.md
|
||||
│ │ ├── 003-process-manager.md
|
||||
│ │ ├── 004-sdk-integration.md
|
||||
│ │ └── 005-session-picker-modal.md
|
||||
│ └── done/ # Completed tasks (empty)
|
||||
└── README.md # Project overview
|
||||
|
||||
```
|
||||
|
||||
## Documentation Overview
|
||||
|
||||
### 1. Architecture (architecture.md)
|
||||
|
||||
**What it covers:**
|
||||
|
||||
- High-level system design
|
||||
- Component layers (Main process, Renderer, Communication)
|
||||
- State management approach
|
||||
- Tab hierarchy (Instance tabs → Session tabs)
|
||||
- Data flow for key operations
|
||||
- Technology stack decisions
|
||||
- Security considerations
|
||||
|
||||
**Key sections:**
|
||||
|
||||
- Component architecture diagram
|
||||
- Instance/Session state structures
|
||||
- Communication patterns (HTTP, SSE)
|
||||
- Error handling strategies
|
||||
- Performance considerations
|
||||
|
||||
### 2. User Interface (user-interface.md)
|
||||
|
||||
**What it covers:**
|
||||
|
||||
- Complete UI layout specifications
|
||||
- Visual design for every component
|
||||
- Interaction patterns
|
||||
- Keyboard shortcuts
|
||||
- Accessibility requirements
|
||||
- Empty states and error states
|
||||
- Modal designs
|
||||
|
||||
**Key sections:**
|
||||
|
||||
- Detailed layout wireframes (ASCII art)
|
||||
- Component-by-component specifications
|
||||
- Message rendering formats
|
||||
- Control bar designs
|
||||
- Modal/overlay specifications
|
||||
- Color schemes and typography
|
||||
|
||||
### 3. Technical Implementation (technical-implementation.md)
|
||||
|
||||
**What it covers:**
|
||||
|
||||
- Technology stack details
|
||||
- Project file structure
|
||||
- State management patterns
|
||||
- Process management implementation
|
||||
- SDK integration approach
|
||||
- SSE event handling
|
||||
- IPC communication
|
||||
- Error handling strategies
|
||||
- Performance optimizations
|
||||
|
||||
**Key sections:**
|
||||
|
||||
- Complete project structure
|
||||
- TypeScript interfaces
|
||||
- Process spawning logic
|
||||
- SDK client management
|
||||
- Message rendering implementation
|
||||
- Build and packaging config
|
||||
|
||||
### 4. Build Roadmap (build-roadmap.md)
|
||||
|
||||
**What it covers:**
|
||||
|
||||
- 8 development phases
|
||||
- Task dependencies
|
||||
- Timeline estimates
|
||||
- Success criteria per phase
|
||||
- Risk mitigation
|
||||
- Release strategy
|
||||
|
||||
**Phases:**
|
||||
|
||||
1. **Foundation** (Week 1) - Project setup, process management
|
||||
2. **Core Chat** (Week 2) - Message display, SSE streaming
|
||||
3. **Essential Features** (Week 3) - Markdown, agents, errors
|
||||
4. **Multi-Instance** (Week 4) - Multiple projects support
|
||||
5. **Advanced Input** (Week 5) - Commands, file attachments
|
||||
6. **Polish** (Week 6) - UX refinements, settings
|
||||
7. **System Integration** (Week 7) - Native features
|
||||
8. **Advanced** (Week 8+) - Performance, plugins
|
||||
|
||||
## Task Breakdown
|
||||
|
||||
### Current Tasks (Phase 1)
|
||||
|
||||
**001 - Project Setup** (2-3 hours)
|
||||
|
||||
- Set up Electron + SolidJS + Vite
|
||||
- Configure TypeScript, TailwindCSS
|
||||
- Create basic project structure
|
||||
- Verify build pipeline works
|
||||
|
||||
**002 - Empty State UI** (2-3 hours)
|
||||
|
||||
- Create empty state component
|
||||
- Implement folder selection dialog
|
||||
- Add keyboard shortcuts
|
||||
- Style and test responsiveness
|
||||
|
||||
**003 - Process Manager** (4-5 hours)
|
||||
|
||||
- Spawn OpenCode server processes
|
||||
- Parse stdout for port extraction
|
||||
- Kill processes on command
|
||||
- Handle errors and timeouts
|
||||
- Auto-cleanup on app quit
|
||||
|
||||
**004 - SDK Integration** (3-4 hours)
|
||||
|
||||
- Create SDK client per instance
|
||||
- Fetch sessions, agents, models
|
||||
- Implement session CRUD operations
|
||||
- Add error handling and retries
|
||||
|
||||
**005 - Session Picker Modal** (3-4 hours)
|
||||
|
||||
- Build modal with session list
|
||||
- Agent selector for new sessions
|
||||
- Keyboard navigation
|
||||
- Loading and error states
|
||||
|
||||
**Total Phase 1 time: ~15-20 hours (2-3 weeks part-time)**
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
### 1. Two-Level Tabs
|
||||
|
||||
- **Level 1**: Instance tabs (one per project folder)
|
||||
- **Level 2**: Session tabs (multiple per instance)
|
||||
- Allows working on multiple projects with multiple conversations each
|
||||
|
||||
### 2. Process Management in Main Process
|
||||
|
||||
- Electron main process spawns servers
|
||||
- Parses stdout to get port
|
||||
- IPC sends port to renderer
|
||||
- Ensures clean shutdown on app quit
|
||||
|
||||
### 3. One SDK Client Per Instance
|
||||
|
||||
- Each instance has its own HTTP client
|
||||
- Connects to different port (different server)
|
||||
- Isolated state prevents cross-contamination
|
||||
|
||||
### 4. SolidJS for Reactivity
|
||||
|
||||
- Fine-grained reactivity for SSE updates
|
||||
- No re-render cascades
|
||||
- Better performance for real-time updates
|
||||
- Smaller bundle size than React
|
||||
|
||||
### 5. No Virtual Scrolling or Performance Optimization in MVP
|
||||
|
||||
- Start with simple list rendering
|
||||
- Don't optimize for large sessions initially
|
||||
- Focus on functionality, not performance
|
||||
- Add optimizations in post-MVP phases if needed
|
||||
- Reduces initial complexity and speeds up development
|
||||
|
||||
### 6. Messages and Tool Calls Inline
|
||||
|
||||
- All activity shows in main message stream
|
||||
- Tool calls expandable/collapsible
|
||||
- File changes visible inline
|
||||
- Single timeline view
|
||||
|
||||
## Implementation Guidelines
|
||||
|
||||
### For Each Task:
|
||||
|
||||
1. Read task file completely
|
||||
2. Review related documentation
|
||||
3. Follow steps in order
|
||||
4. Check off acceptance criteria
|
||||
5. Test thoroughly
|
||||
6. Move to done/ when complete
|
||||
|
||||
### Code Standards:
|
||||
|
||||
- TypeScript for everything
|
||||
- No `any` types
|
||||
- Descriptive variable names
|
||||
- Comments for complex logic
|
||||
- Error handling on all async operations
|
||||
- Loading states for all network calls
|
||||
|
||||
### Testing Approach:
|
||||
|
||||
- Manual testing at each step
|
||||
- Test on minimum window size (800x600)
|
||||
- Test error cases
|
||||
- Test edge cases (long text, special chars)
|
||||
- Keyboard navigation verification
|
||||
|
||||
## Next Steps
|
||||
|
||||
### To Start Building:
|
||||
|
||||
1. **Read all documentation**
|
||||
- Understand architecture
|
||||
- Review UI specifications
|
||||
- Study technical approach
|
||||
|
||||
2. **Start with Task 001**
|
||||
- Set up project structure
|
||||
- Install dependencies
|
||||
- Verify build works
|
||||
|
||||
3. **Follow sequential order**
|
||||
- Each task builds on previous
|
||||
- Don't skip ahead
|
||||
- Dependencies matter
|
||||
|
||||
4. **Track progress**
|
||||
- Update task checkboxes
|
||||
- Move completed tasks to done/
|
||||
- Update roadmap as you go
|
||||
|
||||
### When You Hit Issues:
|
||||
|
||||
1. Review task prerequisites
|
||||
2. Check documentation for clarification
|
||||
3. Look at related specs
|
||||
4. Ask questions on unclear requirements
|
||||
5. Document blockers and solutions
|
||||
|
||||
## Success Metrics
|
||||
|
||||
### MVP (After Task 015)
|
||||
|
||||
- Can select folder → spawn server → chat
|
||||
- Messages stream in real-time
|
||||
- Can switch agents and models
|
||||
- Tool executions visible
|
||||
- Basic error handling works
|
||||
- **Performance is NOT a concern** - focus on functionality
|
||||
|
||||
### Beta (After Task 030)
|
||||
|
||||
- Multi-instance support
|
||||
- Advanced input (files, commands)
|
||||
- Polished UX
|
||||
- Settings and preferences
|
||||
- Native menus
|
||||
|
||||
### v1.0 (After Task 035)
|
||||
|
||||
- System tray integration
|
||||
- Auto-updates
|
||||
- Crash reporting
|
||||
- Production-ready stability
|
||||
|
||||
## Useful References
|
||||
|
||||
### Within This Project:
|
||||
|
||||
- `README.md` - Project overview and getting started
|
||||
- `docs/architecture.md` - System design
|
||||
- `docs/user-interface.md` - UI specifications
|
||||
- `docs/technical-implementation.md` - Implementation details
|
||||
- `tasks/README.md` - Task workflow guide
|
||||
|
||||
### External:
|
||||
|
||||
- OpenCode server API: https://opencode.ai/docs/server/
|
||||
- Electron docs: https://electronjs.org/docs
|
||||
- SolidJS docs: https://solidjs.com
|
||||
- Kobalte UI: https://kobalte.dev
|
||||
|
||||
## Questions to Resolve
|
||||
|
||||
Before starting implementation, clarify:
|
||||
|
||||
1. Exact OpenCode CLI syntax for spawning server
|
||||
2. Expected stdout format for port extraction
|
||||
3. SDK package location and version
|
||||
4. Any platform-specific gotchas
|
||||
5. Icon and branding assets location
|
||||
|
||||
## Estimated Timeline
|
||||
|
||||
**Conservative estimate (part-time, ~15 hours/week):**
|
||||
|
||||
- Phase 1 (MVP Foundation): 2-3 weeks
|
||||
- Phase 2 (Core Chat): 2 weeks
|
||||
- Phase 3 (Essential): 2 weeks
|
||||
- **MVP Complete: 6-7 weeks**
|
||||
|
||||
**Aggressive estimate (full-time, ~40 hours/week):**
|
||||
|
||||
- Phase 1: 1 week
|
||||
- Phase 2: 1 week
|
||||
- Phase 3: 1 week
|
||||
- **MVP Complete: 3 weeks**
|
||||
|
||||
Add 2-4 weeks for testing, bug fixes, and polish before alpha release.
|
||||
|
||||
## This is a Living Document
|
||||
|
||||
As you build:
|
||||
|
||||
- Update estimates based on actual time
|
||||
- Add new tasks as needed
|
||||
- Refine specifications
|
||||
- Document learnings
|
||||
- Track blockers and solutions
|
||||
|
||||
Good luck! 🚀
|
||||
228
dev-docs/TOOL_CALL_IMPLEMENTATION.md
Normal file
228
dev-docs/TOOL_CALL_IMPLEMENTATION.md
Normal file
@@ -0,0 +1,228 @@
|
||||
# Tool Call Rendering Implementation
|
||||
|
||||
This document describes how tool calls are rendered in the CodeNomad, following the patterns established in the TUI.
|
||||
|
||||
## Overview
|
||||
|
||||
Each tool type has specialized rendering logic that displays the most relevant information for that tool. This matches the TUI's approach of providing context-specific displays rather than generic input/output dumps.
|
||||
|
||||
## Tool-Specific Rendering
|
||||
|
||||
### 1. **read** - File Reading
|
||||
|
||||
- **Title**: `Read {filename}`
|
||||
- **Body**: Preview of file content (first 6 lines) from `metadata.preview`
|
||||
- **Use case**: Shows what file content the assistant is reading
|
||||
|
||||
### 2. **edit** - File Editing
|
||||
|
||||
- **Title**: `Edit {filename}`
|
||||
- **Body**: Diff/patch showing changes from `metadata.diff`
|
||||
- **Special**: Shows diagnostics if available in metadata
|
||||
- **Use case**: Shows what changes are being made to files
|
||||
|
||||
### 3. **write** - File Writing
|
||||
|
||||
- **Title**: `Write {filename}`
|
||||
- **Body**: File content being written (first 10 lines)
|
||||
- **Special**: Shows diagnostics if available in metadata
|
||||
- **Use case**: Shows new file content being created
|
||||
|
||||
### 4. **bash** - Shell Commands
|
||||
|
||||
- **Title**: `Shell {description}` (or command if no description)
|
||||
- **Body**: Console-style display with `$ command` and output
|
||||
|
||||
```
|
||||
$ npm install vitest
|
||||
added 50 packages...
|
||||
```
|
||||
|
||||
- **Output from**: `metadata.output`
|
||||
- **Use case**: Shows command execution and results
|
||||
|
||||
### 5. **webfetch** - Web Fetching
|
||||
|
||||
- **Title**: `Fetch {url}`
|
||||
- **Body**: Fetched content (first 10 lines)
|
||||
- **Use case**: Shows web content being retrieved
|
||||
|
||||
### 6. **todowrite** - Task Planning
|
||||
|
||||
- **Title**: Dynamic based on todo phase:
|
||||
- All pending: "Creating plan"
|
||||
- All completed: "Completing plan"
|
||||
- Mixed: "Updating plan"
|
||||
- **Body**: Formatted todo list:
|
||||
- `- [x] Completed task`
|
||||
- `- [ ] Pending task`
|
||||
- `- [ ] ~~Cancelled task~~`
|
||||
- `- [ ] In progress task` (highlighted)
|
||||
- **Use case**: Shows the AI's task planning
|
||||
|
||||
### 7. **task** - Delegated Tasks
|
||||
|
||||
- **Title**: `Task[subagent_type] {description}`
|
||||
- **Body**: List of delegated tool calls with icons:
|
||||
|
||||
```
|
||||
⚡ bash: npm install
|
||||
📖 read package.json
|
||||
✏️ edit src/app.ts
|
||||
```
|
||||
|
||||
- **Special**: In TUI, includes navigation hints for session tree
|
||||
- **Use case**: Shows what the delegated agent is doing
|
||||
|
||||
### 8. **todoread** - Plan Reading
|
||||
|
||||
- **Special**: Hidden in TUI, returns empty string
|
||||
- **Use case**: Internal tool, not displayed to user
|
||||
|
||||
### 9. **glob** - File Pattern Matching
|
||||
|
||||
- **Title**: `Glob {pattern}`
|
||||
- **Use case**: Shows file search patterns
|
||||
|
||||
### 10. **grep** - Content Search
|
||||
|
||||
- **Title**: `Grep "{pattern}"`
|
||||
- **Use case**: Shows what content is being searched
|
||||
|
||||
### 11. **list** - Directory Listing
|
||||
|
||||
- **Title**: `List`
|
||||
- **Use case**: Shows directory operations
|
||||
|
||||
### 12. **patch** - Patching Files
|
||||
|
||||
- **Title**: `Patch`
|
||||
- **Use case**: Shows patch operations
|
||||
|
||||
### 13. **invalid** - Invalid Tool Calls
|
||||
|
||||
- **Title**: Name of the actual tool attempted
|
||||
- **Use case**: Shows validation errors
|
||||
|
||||
### 14. **Default** - Unknown Tools
|
||||
|
||||
- **Title**: Capitalized tool name
|
||||
- **Body**: Output truncated to 10 lines
|
||||
- **Use case**: Fallback for any new or custom tools
|
||||
|
||||
## Status States
|
||||
|
||||
### Pending
|
||||
|
||||
- **Icon**: ⏸ (pause symbol)
|
||||
- **Title**: Action text (e.g., "Writing command...", "Preparing edit...")
|
||||
- **Border**: Accent color
|
||||
- **Animation**: Shimmer effect on title
|
||||
- **Expandable**: Shows "Waiting for permission..." message
|
||||
|
||||
### Running
|
||||
|
||||
- **Icon**: ⏳ (hourglass)
|
||||
- **Title**: Same as completed state
|
||||
- **Border**: Warning color (yellow/orange)
|
||||
- **Animation**: Pulse on status icon
|
||||
|
||||
### Completed
|
||||
|
||||
- **Icon**: ✓ (checkmark)
|
||||
- **Title**: Tool-specific title with arguments
|
||||
- **Border**: Success color (green)
|
||||
- **Body**: Tool-specific rendered content
|
||||
|
||||
### Error
|
||||
|
||||
- **Icon**: ✗ (X mark)
|
||||
- **Title**: Same format but in error color
|
||||
- **Border**: Error color (red)
|
||||
- **Body**: Error message in highlighted box
|
||||
|
||||
## Title Rendering Logic
|
||||
|
||||
The title follows this pattern:
|
||||
|
||||
1. **Pending state**: Show action text
|
||||
|
||||
```
|
||||
"Writing command..."
|
||||
"Preparing edit..."
|
||||
"Delegating..."
|
||||
```
|
||||
|
||||
2. **Completed/Running/Error**: Show specific info
|
||||
|
||||
```
|
||||
"Shell npm install"
|
||||
"Edit src/app.ts"
|
||||
"Read package.json"
|
||||
"Task[general] Search for files"
|
||||
```
|
||||
|
||||
3. **Special cases**:
|
||||
- `todowrite`: Shows plan phase
|
||||
- `todoread`: Just "Plan"
|
||||
- `bash`: Uses description if available, otherwise shows command
|
||||
|
||||
## Metadata Usage
|
||||
|
||||
Tool calls use `metadata` for rich content:
|
||||
|
||||
- **read**: `metadata.preview` - file preview content
|
||||
- **edit**: `metadata.diff` - patch/diff text
|
||||
- **bash**: `metadata.output` - command output
|
||||
- **todowrite**: `metadata.todos[]` - todo items with status
|
||||
- **task**: `metadata.summary[]` - delegated tool calls
|
||||
- **edit/write**: `metadata.diagnostics` - LSP diagnostics
|
||||
|
||||
## Design Principles
|
||||
|
||||
1. **Context-specific**: Each tool shows the most relevant information
|
||||
2. **Progressive disclosure**: Collapsed by default, expand for details
|
||||
3. **Visual hierarchy**: Icons, colors, and borders indicate status
|
||||
4. **Truncation**: Long content is truncated (6-10 lines) to prevent overwhelming
|
||||
5. **Consistency**: All tools follow same header/body/error structure
|
||||
|
||||
## Component Structure
|
||||
|
||||
```tsx
|
||||
<div class="tool-call tool-call-status-{status}">
|
||||
<button class="tool-call-header" onClick={toggle}>
|
||||
<span class="tool-call-icon">▶/▼</span>
|
||||
<span class="tool-call-emoji">{icon}</span>
|
||||
<span class="tool-call-summary">{title}</span>
|
||||
<span class="tool-call-status">{statusIcon}</span>
|
||||
</button>
|
||||
|
||||
{expanded && (
|
||||
<div class="tool-call-details">
|
||||
{/* Tool-specific body content */}
|
||||
{error && <div class="tool-call-error-content">{error}</div>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
```
|
||||
|
||||
## CSS Classes
|
||||
|
||||
- `.tool-call` - Base container
|
||||
- `.tool-call-status-{pending|running|completed|error}` - Status-specific styling
|
||||
- `.tool-call-header` - Clickable header with expand/collapse
|
||||
- `.tool-call-emoji` - Tool type icon
|
||||
- `.tool-call-summary` - Tool title/description
|
||||
- `.tool-call-details` - Expanded content area
|
||||
- `.tool-call-content` - Code/output content (monospace)
|
||||
- `.tool-call-todos` - Todo list container
|
||||
- `.tool-call-task-summary` - Delegated task list
|
||||
- `.tool-call-error-content` - Error message display
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **Syntax highlighting**: Use Shiki for code blocks in bash, read, write
|
||||
2. **Diff rendering**: Better diff visualization for edit tool
|
||||
3. **Copy buttons**: Quick copy for code/output
|
||||
4. **File links**: Click filename to open in editor
|
||||
5. **Diagnostics display**: Show LSP errors/warnings inline
|
||||
312
dev-docs/architecture.md
Normal file
312
dev-docs/architecture.md
Normal file
@@ -0,0 +1,312 @@
|
||||
# CodeNomad Architecture
|
||||
|
||||
## Overview
|
||||
|
||||
CodeNomad is a cross-platform desktop application built with Electron that provides a multi-instance, multi-session interface for interacting with OpenCode servers. Each instance manages its own OpenCode server process and can handle multiple concurrent sessions.
|
||||
|
||||
## High-Level Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Electron Main Process │
|
||||
│ - Window management │
|
||||
│ - Process spawning (opencode serve) │
|
||||
│ - IPC bridge to renderer │
|
||||
│ - File system operations │
|
||||
└────────────────┬────────────────────────────────────────┘
|
||||
│ IPC
|
||||
┌────────────────┴────────────────────────────────────────┐
|
||||
│ Electron Renderer Process │
|
||||
│ ┌──────────────────────────────────────────────────┐ │
|
||||
│ │ SolidJS Application │ │
|
||||
│ │ ┌────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Instance Manager │ │ │
|
||||
│ │ │ - Spawns/kills OpenCode servers │ │ │
|
||||
│ │ │ - Manages SDK clients per instance │ │ │
|
||||
│ │ │ - Handles port allocation │ │ │
|
||||
│ │ └────────────────────────────────────────────┘ │ │
|
||||
│ │ ┌────────────────────────────────────────────┐ │ │
|
||||
│ │ │ State Management (SolidJS Stores) │ │ │
|
||||
│ │ │ - instances[] │ │ │
|
||||
│ │ │ - sessions[] per instance │ │ │
|
||||
│ │ │ - normalized message store per session │ │ │
|
||||
│ │ └────────────────────────────────────────────┘ │ │
|
||||
│ │ ┌────────────────────────────────────────────┐ │ │
|
||||
│ │ │ UI Components │ │ │
|
||||
│ │ │ - InstanceTabs │ │ │
|
||||
│ │ │ - SessionTabs │ │ │
|
||||
│ │ │ - MessageSection │ │ │
|
||||
│ │ │ - PromptInput │ │ │
|
||||
│ │ └────────────────────────────────────────────┘ │ │
|
||||
│ └──────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
│ HTTP/SSE
|
||||
┌────────────────┴────────────────────────────────────────┐
|
||||
│ Multiple OpenCode Server Processes │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Instance 1 │ │ Instance 2 │ │ Instance 3 │ │
|
||||
│ │ Port: 4096 │ │ Port: 4097 │ │ Port: 4098 │ │
|
||||
│ │ ~/project-a │ │ ~/project-a │ │ ~/api │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Component Layers
|
||||
|
||||
### 1. Main Process Layer (Electron)
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- Create and manage application window
|
||||
- Spawn OpenCode server processes as child processes
|
||||
- Parse server stdout to extract port information
|
||||
- Handle process lifecycle (start, stop, restart)
|
||||
- Provide IPC handlers for renderer requests
|
||||
- Manage native OS integrations (file dialogs, menus)
|
||||
|
||||
**Key Modules:**
|
||||
|
||||
- `main.ts` - Application entry point
|
||||
- `process-manager.ts` - OpenCode server process spawning
|
||||
- `ipc-handlers.ts` - IPC communication handlers
|
||||
- `menu.ts` - Native application menu
|
||||
|
||||
### 2. Renderer Process Layer (SolidJS)
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- Render UI components
|
||||
- Manage application state
|
||||
- Handle user interactions
|
||||
- Communicate with OpenCode servers via HTTP/SSE
|
||||
- Real-time message streaming
|
||||
|
||||
**Key Modules:**
|
||||
|
||||
- `App.tsx` - Root component
|
||||
- `stores/` - State management
|
||||
- `components/` - UI components
|
||||
- `contexts/` - SolidJS context providers
|
||||
- `lib/` - Utilities and helpers
|
||||
|
||||
### 3. Communication Layer
|
||||
|
||||
**HTTP API Communication:**
|
||||
|
||||
- SDK client per instance
|
||||
- RESTful API calls for session/config/file operations
|
||||
- Error handling and retries
|
||||
|
||||
**SSE (Server-Sent Events):**
|
||||
|
||||
- One EventSource per instance
|
||||
- Real-time message updates
|
||||
- Event type routing
|
||||
- Reconnection logic
|
||||
|
||||
**CLI Proxy Paths:**
|
||||
|
||||
- The CLI server terminates all HTTP/SSE traffic and forwards it to the correct OpenCode instance.
|
||||
- Each `WorkspaceDescriptor` exposes `proxyPath` (e.g., `/workspaces/<id>/instance`), which acts as the base URL for both REST and SSE calls.
|
||||
- The renderer never touches the random per-instance port directly; it only talks to `window.location.origin + proxyPath` so a single CLI port can front every session.
|
||||
|
||||
## Data Flow
|
||||
|
||||
### Instance Creation Flow
|
||||
|
||||
1. User selects folder via Electron file dialog
|
||||
2. Main process receives folder path via IPC
|
||||
3. Main process spawns `opencode serve --port 0`
|
||||
4. Main process parses stdout for port number
|
||||
5. Main process sends port + PID back to renderer
|
||||
6. Renderer creates SDK client for that port
|
||||
7. Renderer fetches initial session list
|
||||
8. Renderer displays session picker
|
||||
|
||||
### Message Streaming Flow
|
||||
|
||||
1. User submits prompt in active session
|
||||
2. Renderer POSTs to `/session/:id/message`
|
||||
3. SSE connection receives `MessageUpdated` events
|
||||
4. Events are routed to correct instance → session
|
||||
5. Message state updates trigger UI re-render
|
||||
6. Messages display with auto-scroll
|
||||
|
||||
### Child Session Creation Flow
|
||||
|
||||
1. OpenCode server creates child session
|
||||
2. SSE emits `SessionUpdated` event with `parentId`
|
||||
3. Renderer adds session to instance's session list
|
||||
4. New session tab appears automatically
|
||||
5. Optional: Auto-switch to new tab
|
||||
|
||||
## State Management
|
||||
|
||||
### Instance State
|
||||
|
||||
```
|
||||
instances: Map<instanceId, {
|
||||
id: string
|
||||
folder: string
|
||||
port: number
|
||||
pid: number
|
||||
proxyPath: string // `/workspaces/:id/instance`
|
||||
status: 'starting' | 'ready' | 'error' | 'stopped'
|
||||
client: OpenCodeClient
|
||||
eventSource: EventSource
|
||||
sessions: Map<sessionId, Session>
|
||||
activeSessionId: string | null
|
||||
logs: string[]
|
||||
}>
|
||||
```
|
||||
|
||||
### Session State
|
||||
|
||||
```
|
||||
Session: {
|
||||
id: string
|
||||
title: string
|
||||
parentId: string | null
|
||||
messages: Message[]
|
||||
agent: string
|
||||
model: { providerId: string, modelId: string }
|
||||
status: 'idle' | 'streaming' | 'error'
|
||||
}
|
||||
```
|
||||
|
||||
### Message State
|
||||
|
||||
```
|
||||
Message: {
|
||||
id: string
|
||||
sessionId: string
|
||||
type: 'user' | 'assistant'
|
||||
parts: Part[]
|
||||
timestamp: number
|
||||
status: 'sending' | 'sent' | 'streaming' | 'complete' | 'error'
|
||||
}
|
||||
```
|
||||
|
||||
## Tab Hierarchy
|
||||
|
||||
### Level 1: Instance Tabs
|
||||
|
||||
Each tab represents one OpenCode server instance:
|
||||
|
||||
- Label: Folder name (with counter if duplicate)
|
||||
- Icon: Folder icon
|
||||
- Close button: Stops server and closes tab
|
||||
- "+" button: Opens folder picker for new instance
|
||||
|
||||
### Level 2: Session Tabs
|
||||
|
||||
Each instance has multiple session tabs:
|
||||
|
||||
- Main session tab (always present)
|
||||
- Child session tabs (auto-created)
|
||||
- Logs tab (shows server output)
|
||||
- "+" button: Creates new session
|
||||
|
||||
### Tab Behavior
|
||||
|
||||
**Instance Tab Switching:**
|
||||
|
||||
- Preserves session tabs
|
||||
- Switches active SDK client
|
||||
- Updates SSE event routing
|
||||
|
||||
**Session Tab Switching:**
|
||||
|
||||
- Loads messages for that session
|
||||
- Updates agent/model controls
|
||||
- Preserves scroll position
|
||||
|
||||
## Technology Stack
|
||||
|
||||
### Core
|
||||
|
||||
- **Electron** - Desktop wrapper
|
||||
- **SolidJS** - Reactive UI framework
|
||||
- **TypeScript** - Type safety
|
||||
- **Vite** - Build tool
|
||||
|
||||
### UI
|
||||
|
||||
- **TailwindCSS** - Styling
|
||||
- **Kobalte** - Accessible UI primitives
|
||||
- **Shiki** - Code syntax highlighting
|
||||
- **Marked** - Markdown parsing
|
||||
|
||||
### Communication
|
||||
|
||||
- **OpenCode SDK** - API client
|
||||
- **EventSource** - SSE streaming
|
||||
- **Node Child Process** - Process spawning
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Process Errors
|
||||
|
||||
- Server fails to start → Show error in instance tab
|
||||
- Server crashes → Attempt auto-restart once
|
||||
- Port already in use → Find next available port
|
||||
|
||||
### Network Errors
|
||||
|
||||
- API call fails → Show inline error, allow retry
|
||||
- SSE disconnects → Auto-reconnect with backoff
|
||||
- Timeout → Show timeout error, allow manual retry
|
||||
|
||||
### User Errors
|
||||
|
||||
- Invalid folder selection → Show error dialog
|
||||
- Permission denied → Show actionable error message
|
||||
- Out of memory → Graceful degradation message
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
**Note: Performance optimization is NOT a focus for MVP. These are future considerations.**
|
||||
|
||||
### Message Rendering (Post-MVP)
|
||||
|
||||
- Start with simple list rendering - no virtual scrolling
|
||||
- No message limits initially
|
||||
- Only optimize if users report issues
|
||||
- Virtual scrolling can be added in Phase 8 if needed
|
||||
|
||||
### State Updates
|
||||
|
||||
- SolidJS fine-grained reactivity handles most cases
|
||||
- No special optimizations needed for MVP
|
||||
- Batching/debouncing can be added later if needed
|
||||
|
||||
### Memory Management (Post-MVP)
|
||||
|
||||
- No memory management in MVP
|
||||
- Let browser/OS handle it
|
||||
- Add limits only if problems arise in testing
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- No remote code execution
|
||||
- Server spawned with user permissions
|
||||
- No eval() or dangerous innerHTML
|
||||
- Sanitize markdown rendering
|
||||
- Validate all IPC messages
|
||||
- HTTPS only for external requests
|
||||
|
||||
## Extensibility Points
|
||||
|
||||
### Plugin System (Future)
|
||||
|
||||
- Custom slash commands
|
||||
- Custom message renderers
|
||||
- Theme extensions
|
||||
- Keybinding customization
|
||||
|
||||
### Configuration (Future)
|
||||
|
||||
- Per-instance settings
|
||||
- Global preferences
|
||||
- Workspace-specific configs
|
||||
- Import/export settings
|
||||
391
dev-docs/build-roadmap.md
Normal file
391
dev-docs/build-roadmap.md
Normal file
@@ -0,0 +1,391 @@
|
||||
# CodeNomad Build Roadmap
|
||||
|
||||
## Overview
|
||||
|
||||
This document outlines the phased approach to building the CodeNomad desktop application. Each phase builds incrementally on the previous, with clear deliverables and milestones.
|
||||
|
||||
**Status:** MVP (Phases 1-3) is complete. Focus now shifts to post-MVP phases starting with multi-instance support and advanced input refinements.
|
||||
|
||||
## MVP Scope (Phases 1-3)
|
||||
|
||||
The minimum viable product includes:
|
||||
|
||||
- Single instance management
|
||||
- Session selection and creation
|
||||
- Message display (streaming)
|
||||
- Basic prompt input (text only)
|
||||
- Agent/model selection
|
||||
- Process lifecycle management
|
||||
|
||||
**Target: 3-4 weeks for MVP**
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Foundation (Week 1)
|
||||
|
||||
**Goal:** Running Electron app that can spawn OpenCode servers
|
||||
|
||||
### Tasks
|
||||
|
||||
1. ✅ **001-project-setup** - Electron + SolidJS + Vite boilerplate
|
||||
2. ✅ **002-empty-state-ui** - Empty state UI with folder selection
|
||||
3. ✅ **003-process-manager** - Spawn and manage OpenCode server processes
|
||||
4. ✅ **004-sdk-integration** - Connect to server via SDK
|
||||
5. ✅ **005-session-picker-modal** - Select/create session modal
|
||||
|
||||
### Deliverables
|
||||
|
||||
- App launches successfully
|
||||
- Can select folder
|
||||
- Server spawns automatically
|
||||
- Session picker appears
|
||||
- Can create/select session
|
||||
|
||||
### Success Criteria
|
||||
|
||||
- User can launch app → select folder → see session picker
|
||||
- Server process runs in background
|
||||
- Sessions fetch from API successfully
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Core Chat Interface (Week 2)
|
||||
|
||||
**Goal:** Display messages and send basic prompts
|
||||
|
||||
### Tasks
|
||||
|
||||
6. **006-instance-session-tabs** - Two-level tab navigation
|
||||
7. **007-message-display** - Render user and assistant messages
|
||||
8. **008-sse-integration** - Real-time message streaming
|
||||
9. **009-prompt-input-basic** - Text input with send functionality
|
||||
10. **010-tool-call-rendering** - Display tool executions inline
|
||||
|
||||
### Deliverables
|
||||
|
||||
- Tab navigation works
|
||||
- Messages display correctly
|
||||
- Real-time updates via SSE
|
||||
- Can send text messages
|
||||
- Tool calls show status
|
||||
|
||||
### Success Criteria
|
||||
|
||||
- User can type message → see response stream in real-time
|
||||
- Tool executions visible and expandable
|
||||
- Multiple sessions can be open simultaneously
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Essential Features (Week 3)
|
||||
|
||||
**Goal:** Feature parity with basic TUI functionality
|
||||
|
||||
### Tasks
|
||||
|
||||
11. **011-agent-model-selectors** - Dropdown for agent/model switching
|
||||
12. **012-markdown-rendering** - Proper markdown with code highlighting
|
||||
13. **013-logs-tab** - View server logs
|
||||
14. **014-error-handling** - Comprehensive error states and recovery
|
||||
15. **015-keyboard-shortcuts** - Essential keyboard navigation
|
||||
|
||||
### Deliverables
|
||||
|
||||
- Can switch agents and models
|
||||
- Markdown renders beautifully
|
||||
- Code blocks have syntax highlighting
|
||||
- Server logs accessible
|
||||
- Errors handled gracefully
|
||||
- Cmd/Ctrl+N, K, L shortcuts work
|
||||
|
||||
### Success Criteria
|
||||
|
||||
- User experience matches TUI quality
|
||||
- All error cases handled
|
||||
- Keyboard-first navigation option available
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Multi-Instance Support (Week 4)
|
||||
|
||||
**Goal:** Work on multiple projects simultaneously
|
||||
|
||||
### Tasks
|
||||
|
||||
16. **016-instance-tabs** - Instance-level tab management
|
||||
17. **017-instance-state-persistence** - Remember instances across restarts
|
||||
18. **018-child-session-handling** - Auto-create tabs for child sessions
|
||||
19. **019-instance-lifecycle** - Stop, restart, reconnect instances
|
||||
20. **020-multiple-sdk-clients** - One SDK client per instance
|
||||
|
||||
### Deliverables
|
||||
|
||||
- Multiple instance tabs
|
||||
- Persists across app restarts
|
||||
- Child sessions appear as new tabs
|
||||
- Can stop individual instances
|
||||
- All instances work independently
|
||||
|
||||
### Success Criteria
|
||||
|
||||
- User can work on 3+ projects simultaneously
|
||||
- App remembers state on restart
|
||||
- No interference between instances
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Advanced Input (Week 5)
|
||||
|
||||
**Goal:** Full input capabilities matching TUI
|
||||
|
||||
### Tasks
|
||||
|
||||
21. **021-slash-commands** - Command palette with autocomplete
|
||||
22. **022-file-attachments** - @ mention file picker
|
||||
23. **023-drag-drop-files** - Drag files onto input
|
||||
24. **024-attachment-chips** - Display and manage attachments
|
||||
25. **025-input-history** - Up/down arrow message history
|
||||
|
||||
### Deliverables
|
||||
|
||||
- `/command` autocomplete works
|
||||
- `@file` picker searches files
|
||||
- Drag & drop attaches files
|
||||
- Attachment chips removable
|
||||
- Previous messages accessible
|
||||
|
||||
### Success Criteria
|
||||
|
||||
- Input feature parity with TUI
|
||||
- File context easy to add
|
||||
- Command discovery intuitive
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Polish & UX (Week 6)
|
||||
|
||||
**Goal:** Production-ready user experience
|
||||
|
||||
### Tasks
|
||||
|
||||
26. **026-message-actions** - Copy, edit, regenerate messages
|
||||
27. **027-search-in-session** - Find text in conversation
|
||||
28. **028-session-management** - Rename, share, export sessions
|
||||
29. **029-settings-ui** - Preferences and configuration
|
||||
30. **030-native-menus** - Platform-native menu bar
|
||||
|
||||
### Deliverables
|
||||
|
||||
- Message context menus
|
||||
- Search within conversation
|
||||
- Session CRUD operations
|
||||
- Settings dialog
|
||||
- Native File/Edit/View menus
|
||||
|
||||
### Success Criteria
|
||||
|
||||
- Feels polished and professional
|
||||
- All common actions accessible
|
||||
- Settings discoverable
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: System Integration (Week 7)
|
||||
|
||||
**Goal:** Native desktop app features
|
||||
|
||||
### Tasks
|
||||
|
||||
31. **031-system-tray** - Background running with tray icon
|
||||
32. **032-notifications** - Desktop notifications for events
|
||||
33. **033-auto-updater** - In-app update mechanism
|
||||
34. **034-crash-reporting** - Error reporting and recovery
|
||||
35. **035-performance-profiling** - Optimize rendering and memory
|
||||
|
||||
### Deliverables
|
||||
|
||||
- Runs in background
|
||||
- Notifications for session activity
|
||||
- Auto-updates on launch
|
||||
- Crash logs captured
|
||||
- Smooth performance with large sessions
|
||||
|
||||
### Success Criteria
|
||||
|
||||
- App feels native to platform
|
||||
- Updates seamlessly
|
||||
- Crashes don't lose data
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: Advanced Features (Week 8+)
|
||||
|
||||
**Goal:** Beyond MVP, power user features
|
||||
|
||||
### Tasks
|
||||
|
||||
36. **036-virtual-scrolling** - Handle 1000+ message sessions
|
||||
37. **037-message-search-advanced** - Full-text search across sessions
|
||||
38. **038-workspace-management** - Save/load workspace configurations
|
||||
39. **039-theme-customization** - Custom themes and UI tweaks
|
||||
40. **040-plugin-system** - Extension API for custom tools
|
||||
|
||||
### Deliverables
|
||||
|
||||
- Virtual scrolling for performance
|
||||
- Cross-session search
|
||||
- Workspace persistence
|
||||
- Theme editor
|
||||
- Plugin loader
|
||||
|
||||
### Success Criteria
|
||||
|
||||
- Handles massive sessions (5000+ messages)
|
||||
- Can search entire project history
|
||||
- Fully customizable
|
||||
|
||||
---
|
||||
|
||||
## Parallel Tracks
|
||||
|
||||
Some tasks can be worked on independently:
|
||||
|
||||
### Design Track
|
||||
|
||||
- Visual design refinements
|
||||
- Icon creation
|
||||
- Brand assets
|
||||
- Marketing materials
|
||||
|
||||
### Documentation Track
|
||||
|
||||
- User guide
|
||||
- Keyboard shortcuts reference
|
||||
- Troubleshooting docs
|
||||
- Video tutorials
|
||||
|
||||
### Infrastructure Track
|
||||
|
||||
- CI/CD pipeline
|
||||
- Automated testing
|
||||
- Release automation
|
||||
- Analytics integration
|
||||
|
||||
---
|
||||
|
||||
## Release Strategy
|
||||
|
||||
### Alpha (After Phase 3)
|
||||
|
||||
- Internal testing only
|
||||
- Frequent bugs expected
|
||||
- Rapid iteration
|
||||
|
||||
### Beta (After Phase 6)
|
||||
|
||||
- Public beta program
|
||||
- Feature complete
|
||||
- Bug fixes and polish
|
||||
|
||||
### v1.0 (After Phase 7)
|
||||
|
||||
- Public release
|
||||
- Stable and reliable
|
||||
- Production-ready
|
||||
|
||||
### v1.x (Phase 8+)
|
||||
|
||||
- Regular feature updates
|
||||
- Community-driven priorities
|
||||
- Plugin ecosystem
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
### MVP Success
|
||||
|
||||
- 10 internal users daily
|
||||
- Can complete full coding session
|
||||
- <5 critical bugs
|
||||
|
||||
### Beta Success
|
||||
|
||||
- 100+ external users
|
||||
- NPS >50
|
||||
- <10 bugs per week
|
||||
|
||||
### v1.0 Success
|
||||
|
||||
- 1000+ users
|
||||
- <1% crash rate
|
||||
- Feature requests > bug reports
|
||||
|
||||
---
|
||||
|
||||
## Risk Mitigation
|
||||
|
||||
### Technical Risks
|
||||
|
||||
- **Process management complexity**
|
||||
- Mitigation: Extensive testing, graceful degradation
|
||||
- **SSE connection stability**
|
||||
- Mitigation: Robust reconnection logic, offline mode
|
||||
- **Performance with large sessions**
|
||||
- Mitigation: NOT a concern for MVP - defer to Phase 8
|
||||
- Accept slower performance initially, optimize later based on user feedback
|
||||
|
||||
### Product Risks
|
||||
|
||||
- **Feature creep**
|
||||
- Mitigation: Strict MVP scope, user feedback prioritization
|
||||
- **Over-optimization too early**
|
||||
- Mitigation: Focus on functionality first, optimize in Phase 8
|
||||
- Avoid premature performance optimization
|
||||
- **Platform inconsistencies**
|
||||
- Mitigation: Test on all platforms regularly
|
||||
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
|
||||
### External
|
||||
|
||||
- OpenCode CLI availability
|
||||
- OpenCode SDK stability
|
||||
- Electron framework updates
|
||||
|
||||
### Internal
|
||||
|
||||
- Design assets
|
||||
- Documentation
|
||||
- Testing resources
|
||||
|
||||
---
|
||||
|
||||
## Milestone Checklist
|
||||
|
||||
### Pre-Alpha
|
||||
|
||||
- [ ] All Phase 1 tasks complete
|
||||
- [ ] Can create instance and session
|
||||
- [ ] Internal demo successful
|
||||
|
||||
### Alpha
|
||||
|
||||
- [ ] All Phase 2-3 tasks complete
|
||||
- [ ] MVP feature complete
|
||||
- [ ] 5+ internal users testing
|
||||
|
||||
### Beta
|
||||
|
||||
- [ ] All Phase 4-6 tasks complete
|
||||
- [ ] Multi-instance stable
|
||||
- [ ] 50+ external testers
|
||||
|
||||
### v1.0
|
||||
|
||||
- [ ] All Phase 7 tasks complete
|
||||
- [ ] Documentation complete
|
||||
- [ ] <5 known bugs
|
||||
- [ ] Ready for public release
|
||||
82
dev-docs/solidjs-llms.txt
Normal file
82
dev-docs/solidjs-llms.txt
Normal file
@@ -0,0 +1,82 @@
|
||||
# SolidJS Documentation
|
||||
|
||||
> Solid is a modern JavaScript framework for building user interfaces with fine-grained reactivity. It compiles JSX to real DOM elements and updates only what changes, delivering exceptional performance without a virtual DOM. Solid provides reactive primitives like signals, effects, and stores for predictable state management.
|
||||
|
||||
SolidJS is a declarative JavaScript framework that prioritizes performance and developer experience. Unlike frameworks that re-run components on every update, Solid components run once during initialization and set up a reactive system that precisely updates the DOM when dependencies change.
|
||||
|
||||
Key principles:
|
||||
- Fine-grained reactivity: Updates only the specific DOM nodes that depend on changed data
|
||||
- Compile-time optimization: JSX transforms into efficient DOM operations
|
||||
- Unidirectional data flow: Props are read-only, promoting predictable state management
|
||||
- Component lifecycle: Components run once, with reactive primitives handling updates
|
||||
|
||||
**Use your web fetch tool on any of the following links to understand the relevant concept**.
|
||||
|
||||
## Quick Start
|
||||
|
||||
- [Overview](https://docs.solidjs.com/): Framework introduction and key advantages
|
||||
- [Quick Start](https://docs.solidjs.com/quick-start): Installation and project setup with create-solid
|
||||
- [Interactive Tutorial](https://www.solidjs.com/tutorial/introduction_basics): Learn Solid basics through guided examples
|
||||
- [Playground](https://playground.solidjs.com/): Experiment with Solid directly in your browser
|
||||
|
||||
## Core Concepts
|
||||
|
||||
- [Intro to Reactivity](https://docs.solidjs.com/concepts/intro-to-reactivity): Signals, subscribers, and reactive principles
|
||||
- [Understanding JSX](https://docs.solidjs.com/concepts/understanding-jsx): How Solid uses JSX and key differences from HTML
|
||||
- [Components Basics](https://docs.solidjs.com/concepts/components/basics): Component trees, lifecycles, and composition patterns
|
||||
- [Signals](https://docs.solidjs.com/concepts/signals): Core reactive primitive for state management with getters/setters
|
||||
- [Effects](https://docs.solidjs.com/concepts/effects): Side effects, dependency tracking, and lifecycle functions
|
||||
- [Stores](https://docs.solidjs.com/concepts/stores): Complex state management with proxy-based reactivity
|
||||
- [Context](https://docs.solidjs.com/concepts/context): Cross-component state sharing without prop drilling
|
||||
|
||||
## Component APIs
|
||||
|
||||
- [Props](https://docs.solidjs.com/concepts/components/props): Passing data and handlers to child components
|
||||
- [Event Handlers](https://docs.solidjs.com/concepts/components/event-handlers): Managing user interactions
|
||||
- [Class and Style](https://docs.solidjs.com/concepts/components/class-style): Dynamic styling approaches
|
||||
- [Refs](https://docs.solidjs.com/concepts/refs): Accessing DOM elements directly
|
||||
|
||||
## Control Flow
|
||||
|
||||
- [Conditional Rendering](https://docs.solidjs.com/concepts/control-flow/conditional-rendering): Show, Switch, and Match components
|
||||
- [List Rendering](https://docs.solidjs.com/concepts/control-flow/list-rendering): For, Index, and keyed iteration
|
||||
- [Dynamic](https://docs.solidjs.com/concepts/control-flow/dynamic): Dynamic component switching
|
||||
- [Portal](https://docs.solidjs.com/concepts/control-flow/portal): Rendering outside component hierarchy
|
||||
- [Error Boundary](https://docs.solidjs.com/concepts/control-flow/error-boundary): Graceful error handling
|
||||
|
||||
## Derived Values
|
||||
|
||||
- [Derived Signals](https://docs.solidjs.com/concepts/derived-values/derived-signals): Computed values from signals
|
||||
- [Memos](https://docs.solidjs.com/concepts/derived-values/memos): Cached computed values for performance
|
||||
|
||||
## State Management
|
||||
|
||||
- [Basic State Management](https://docs.solidjs.com/guides/state-management): One-way data flow and lifting state
|
||||
- [Complex State Management](https://docs.solidjs.com/guides/complex-state-management): Stores for scalable applications
|
||||
- [Fetching Data](https://docs.solidjs.com/guides/fetching-data): Async data with createResource
|
||||
|
||||
## Routing
|
||||
|
||||
- [Routing & Navigation](https://docs.solidjs.com/guides/routing-and-navigation): @solidjs/router setup and usage
|
||||
- [Dynamic Routes](https://docs.solidjs.com/guides/routing-and-navigation#dynamic-routes): Route parameters and validation
|
||||
- [Nested Routes](https://docs.solidjs.com/guides/routing-and-navigation#nested-routes): Hierarchical route structures
|
||||
- [Preload Functions](https://docs.solidjs.com/guides/routing-and-navigation#preload-functions): Parallel data fetching
|
||||
|
||||
## Advanced Topics
|
||||
|
||||
- [Fine-Grained Reactivity](https://docs.solidjs.com/advanced-concepts/fine-grained-reactivity): Deep dive into reactive system
|
||||
- [TypeScript](https://docs.solidjs.com/configuration/typescript): Type safety and configuration
|
||||
|
||||
## Ecosystem
|
||||
|
||||
- [Solid Router](https://docs.solidjs.com/solid-router/): File-system routing and data APIs
|
||||
- [SolidStart](https://docs.solidjs.com/solid-start/): Full-stack meta-framework
|
||||
- [Solid Meta](https://docs.solidjs.com/solid-meta/): Document head management
|
||||
- [Templates](https://github.com/solidjs/templates): Starter templates for different setups
|
||||
|
||||
## Optional
|
||||
|
||||
- [Ecosystem Libraries](https://www.solidjs.com/ecosystem): Community packages and tools
|
||||
- [API Reference](https://docs.solidjs.com/reference/): Complete API documentation
|
||||
- [Testing](https://docs.solidjs.com/guides/testing): Testing strategies and utilities
|
||||
- [Deployment](https://docs.solidjs.com/guides/deploying-your-app): Build and deployment options
|
||||
642
dev-docs/technical-implementation.md
Normal file
642
dev-docs/technical-implementation.md
Normal file
@@ -0,0 +1,642 @@
|
||||
# Technical Implementation Details
|
||||
|
||||
## Technology Stack
|
||||
|
||||
### Core Technologies
|
||||
|
||||
- **Electron** v28+ - Desktop application wrapper
|
||||
- **SolidJS** v1.8+ - Reactive UI framework
|
||||
- **TypeScript** v5.3+ - Type-safe development
|
||||
- **Vite** v5+ - Fast build tool and dev server
|
||||
|
||||
### UI & Styling
|
||||
|
||||
- **TailwindCSS** v4+ - Utility-first styling
|
||||
- **Kobalte** - Accessible UI primitives for SolidJS
|
||||
- **Shiki** - Syntax highlighting for code blocks
|
||||
- **Marked** - Markdown parsing
|
||||
- **Lucide** - Icon library
|
||||
|
||||
### Communication
|
||||
|
||||
- **OpenCode SDK** (@opencode-ai/sdk) - API client
|
||||
- **EventSource API** - Server-sent events
|
||||
- **Node Child Process** - Process management
|
||||
|
||||
### Development Tools
|
||||
|
||||
- **electron-vite** - Electron + Vite integration
|
||||
- **electron-builder** - Application packaging
|
||||
- **ESLint** - Code linting
|
||||
- **Prettier** - Code formatting
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
packages/opencode-client/
|
||||
├── electron/
|
||||
│ ├── main/
|
||||
│ │ ├── main.ts # Electron main entry
|
||||
│ │ ├── window.ts # Window management
|
||||
│ │ ├── process-manager.ts # OpenCode server spawning
|
||||
│ │ ├── ipc.ts # IPC handlers
|
||||
│ │ └── menu.ts # Application menu
|
||||
│ ├── preload/
|
||||
│ │ └── index.ts # Preload script (IPC bridge)
|
||||
│ └── resources/
|
||||
│ └── icon.png # Application icon
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ ├── instance-tabs.tsx # Level 1 tabs
|
||||
│ │ ├── session-tabs.tsx # Level 2 tabs
|
||||
│ │ ├── message-stream-v2.tsx # Messages display (normalized store)
|
||||
│ │ ├── message-item.tsx # Single message
|
||||
│ │ ├── tool-call.tsx # Tool execution display
|
||||
│ │ ├── prompt-input.tsx # Input with attachments
|
||||
│ │ ├── agent-selector.tsx # Agent dropdown
|
||||
│ │ ├── model-selector.tsx # Model dropdown
|
||||
│ │ ├── session-picker.tsx # Startup modal
|
||||
│ │ ├── logs-view.tsx # Server logs
|
||||
│ │ └── empty-state.tsx # No instances view
|
||||
│ ├── stores/
|
||||
│ │ ├── instances.ts # Instance state
|
||||
│ │ ├── sessions.ts # Session state per instance
|
||||
│ │ └── ui.ts # UI state (active tabs, etc)
|
||||
│ ├── lib/
|
||||
│ │ ├── sdk-manager.ts # SDK client management
|
||||
│ │ ├── sse-manager.ts # SSE connection handling
|
||||
│ │ ├── port-finder.ts # Find available ports
|
||||
│ │ └── markdown.ts # Markdown rendering utils
|
||||
│ ├── hooks/
|
||||
│ │ ├── use-instance.ts # Instance operations
|
||||
│ │ ├── use-session.ts # Session operations
|
||||
│ │ └── use-messages.ts # Message operations
|
||||
│ ├── types/
|
||||
│ │ ├── instance.ts # Instance types
|
||||
│ │ ├── session.ts # Session types
|
||||
│ │ └── message.ts # Message types
|
||||
│ ├── App.tsx # Root component
|
||||
│ ├── main.tsx # Renderer entry
|
||||
│ └── index.css # Global styles
|
||||
├── docs/ # Documentation
|
||||
├── tasks/ # Task tracking
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
├── electron.vite.config.ts
|
||||
├── tailwind.config.js
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## State Management
|
||||
|
||||
### Instance Store
|
||||
|
||||
```typescript
|
||||
interface InstanceState {
|
||||
instances: Map<string, Instance>
|
||||
activeInstanceId: string | null
|
||||
|
||||
// Actions
|
||||
createInstance(folder: string): Promise<void>
|
||||
removeInstance(id: string): Promise<void>
|
||||
setActiveInstance(id: string): void
|
||||
}
|
||||
|
||||
interface Instance {
|
||||
id: string // UUID
|
||||
folder: string // Absolute path
|
||||
port: number // Server port
|
||||
pid: number // Process ID
|
||||
status: InstanceStatus
|
||||
client: OpenCodeClient // SDK client
|
||||
eventSource: EventSource | null // SSE connection
|
||||
sessions: Map<string, Session>
|
||||
activeSessionId: string | null
|
||||
logs: LogEntry[]
|
||||
}
|
||||
|
||||
type InstanceStatus =
|
||||
| "starting" // Server spawning
|
||||
| "ready" // Server connected
|
||||
| "error" // Failed to start
|
||||
| "stopped" // Server killed
|
||||
|
||||
interface LogEntry {
|
||||
timestamp: number
|
||||
level: "info" | "error" | "warn"
|
||||
message: string
|
||||
}
|
||||
```
|
||||
|
||||
### Session Store
|
||||
|
||||
```typescript
|
||||
interface SessionState {
|
||||
// Per instance
|
||||
getSessions(instanceId: string): Session[]
|
||||
getActiveSession(instanceId: string): Session | null
|
||||
|
||||
// Actions
|
||||
createSession(instanceId: string, agent: string): Promise<Session>
|
||||
deleteSession(instanceId: string, sessionId: string): Promise<void>
|
||||
setActiveSession(instanceId: string, sessionId: string): void
|
||||
updateSession(instanceId: string, sessionId: string, updates: Partial<Session>): void
|
||||
}
|
||||
|
||||
interface Session {
|
||||
id: string
|
||||
instanceId: string
|
||||
title: string
|
||||
parentId: string | null
|
||||
agent: string
|
||||
model: {
|
||||
providerId: string
|
||||
modelId: string
|
||||
}
|
||||
version: string
|
||||
time: { created: number; updated: number }
|
||||
revert?: {
|
||||
messageID?: string
|
||||
partID?: string
|
||||
snapshot?: string
|
||||
diff?: string
|
||||
}
|
||||
}
|
||||
|
||||
// Message content lives in the normalized message-v2 store
|
||||
// keyed by instanceId/sessionId/messageId
|
||||
|
||||
type SessionStatus =
|
||||
| "idle" // No activity
|
||||
| "streaming" // Assistant responding
|
||||
| "error" // Error occurred
|
||||
|
||||
```
|
||||
|
||||
### UI Store
|
||||
|
||||
```typescript
|
||||
interface UIState {
|
||||
// Tab state
|
||||
instanceTabOrder: string[]
|
||||
sessionTabOrder: Map<string, string[]> // instanceId -> sessionIds
|
||||
|
||||
// Modal state
|
||||
showSessionPicker: string | null // instanceId or null
|
||||
showSettings: boolean
|
||||
|
||||
// Actions
|
||||
reorderInstanceTabs(newOrder: string[]): void
|
||||
reorderSessionTabs(instanceId: string, newOrder: string[]): void
|
||||
openSessionPicker(instanceId: string): void
|
||||
closeSessionPicker(): void
|
||||
}
|
||||
```
|
||||
|
||||
## Process Management
|
||||
|
||||
### Server Spawning
|
||||
|
||||
**Strategy:** Spawn with port 0 (random), parse stdout for actual port
|
||||
|
||||
```typescript
|
||||
interface ProcessManager {
|
||||
spawn(folder: string): Promise<ProcessInfo>
|
||||
kill(pid: number): Promise<void>
|
||||
restart(pid: number, folder: string): Promise<ProcessInfo>
|
||||
}
|
||||
|
||||
interface ProcessInfo {
|
||||
pid: number
|
||||
port: number
|
||||
stdout: Readable
|
||||
stderr: Readable
|
||||
}
|
||||
|
||||
// Implementation approach:
|
||||
// 1. Check if opencode binary exists
|
||||
// 2. Spawn: spawn('opencode', ['serve', '--port', '0'], { cwd: folder })
|
||||
// 3. Listen to stdout
|
||||
// 4. Parse line matching: "Server listening on port 4096"
|
||||
// 5. Resolve promise with port
|
||||
// 6. Timeout after 10 seconds
|
||||
```
|
||||
|
||||
### Port Parsing
|
||||
|
||||
```typescript
|
||||
// Expected output from opencode serve:
|
||||
// > Starting OpenCode server...
|
||||
// > Server listening on port 4096
|
||||
// > API available at http://localhost:4096
|
||||
|
||||
function parsePort(output: string): number | null {
|
||||
const match = output.match(/port (\d+)/)
|
||||
return match ? parseInt(match[1], 10) : null
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
**Server fails to start:**
|
||||
|
||||
- Parse stderr for error message
|
||||
- Display in instance tab with retry button
|
||||
- Common errors: Port in use, permission denied, binary not found
|
||||
|
||||
**Server crashes after start:**
|
||||
|
||||
- Detect via process 'exit' event
|
||||
- Attempt auto-restart once
|
||||
- If restart fails, show error state
|
||||
- Preserve session data for manual restart
|
||||
|
||||
## Communication Layer
|
||||
|
||||
### SDK Client Management
|
||||
|
||||
```typescript
|
||||
interface SDKManager {
|
||||
createClient(port: number): OpenCodeClient
|
||||
destroyClient(port: number): void
|
||||
getClient(port: number): OpenCodeClient | null
|
||||
}
|
||||
|
||||
// One client per instance
|
||||
// Client lifecycle tied to instance lifecycle
|
||||
```
|
||||
|
||||
### SSE Event Handling
|
||||
|
||||
```typescript
|
||||
interface SSEManager {
|
||||
connect(instanceId: string, port: number): void
|
||||
disconnect(instanceId: string): void
|
||||
|
||||
// Event routing
|
||||
onMessageUpdate(handler: (instanceId: string, event: MessageUpdateEvent) => void): void
|
||||
onSessionUpdate(handler: (instanceId: string, event: SessionUpdateEvent) => void): void
|
||||
onError(handler: (instanceId: string, error: Error) => void): void
|
||||
}
|
||||
|
||||
// Event flow:
|
||||
// 1. EventSource connects to /event endpoint
|
||||
// 2. Events arrive as JSON
|
||||
// 3. Route to correct instance store
|
||||
// 4. Update reactive state
|
||||
// 5. UI auto-updates via signals
|
||||
```
|
||||
|
||||
### Reconnection Logic
|
||||
|
||||
```typescript
|
||||
// SSE disconnects:
|
||||
// - Network issue
|
||||
// - Server restart
|
||||
// - Tab sleep (browser optimization)
|
||||
|
||||
class SSEConnection {
|
||||
private reconnectAttempts = 0
|
||||
private maxReconnectAttempts = 5
|
||||
private reconnectDelay = 1000 // Start with 1s
|
||||
|
||||
reconnect() {
|
||||
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
||||
this.emitError(new Error("Max reconnection attempts reached"))
|
||||
return
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.connect()
|
||||
this.reconnectAttempts++
|
||||
this.reconnectDelay *= 2 // Exponential backoff
|
||||
}, this.reconnectDelay)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Message Rendering
|
||||
|
||||
### Markdown Processing
|
||||
|
||||
```typescript
|
||||
// Use Marked + Shiki for syntax highlighting
|
||||
import { marked } from "marked"
|
||||
import { markedHighlight } from "marked-highlight"
|
||||
import { getHighlighter } from "shiki"
|
||||
|
||||
const highlighter = await getHighlighter({
|
||||
themes: ["github-dark", "github-light"],
|
||||
langs: ["typescript", "javascript", "python", "bash", "json"],
|
||||
})
|
||||
|
||||
marked.use(
|
||||
markedHighlight({
|
||||
highlight(code, lang) {
|
||||
return highlighter.codeToHtml(code, {
|
||||
lang,
|
||||
theme: isDark ? "github-dark" : "github-light",
|
||||
})
|
||||
},
|
||||
}),
|
||||
)
|
||||
```
|
||||
|
||||
### Tool Call Rendering
|
||||
|
||||
```typescript
|
||||
interface ToolCallComponent {
|
||||
tool: string // "bash", "edit", "read"
|
||||
input: any // Tool-specific input
|
||||
output?: any // Tool-specific output
|
||||
status: "pending" | "running" | "success" | "error"
|
||||
expanded: boolean // Collapse state
|
||||
}
|
||||
|
||||
// Render logic:
|
||||
// - Default: Collapsed, show summary
|
||||
// - Click: Toggle expanded state
|
||||
// - Running: Show spinner
|
||||
// - Complete: Show checkmark
|
||||
// - Error: Show error icon + message
|
||||
```
|
||||
|
||||
### Streaming Updates
|
||||
|
||||
```typescript
|
||||
// Messages stream in via SSE
|
||||
// Update strategy: Replace existing message parts
|
||||
|
||||
function handleMessagePartUpdate(event: MessagePartEvent) {
|
||||
const session = getSession(event.sessionId)
|
||||
const message = session.messages.find((m) => m.id === event.messageId)
|
||||
|
||||
if (!message) {
|
||||
// New message
|
||||
session.messages.push(createMessage(event))
|
||||
} else {
|
||||
// Update existing
|
||||
const partIndex = message.parts.findIndex((p) => p.id === event.partId)
|
||||
if (partIndex === -1) {
|
||||
message.parts.push(event.part)
|
||||
} else {
|
||||
message.parts[partIndex] = event.part
|
||||
}
|
||||
}
|
||||
|
||||
// SolidJS reactivity triggers re-render
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
**MVP Approach: Don't optimize prematurely**
|
||||
|
||||
### Message Rendering (MVP)
|
||||
|
||||
**Simple approach - no optimization:**
|
||||
|
||||
```typescript
|
||||
// Render all messages - no virtual scrolling, no limits
|
||||
<For each={messages()}>
|
||||
{(message) => <MessageItem message={message} />}
|
||||
</For>
|
||||
|
||||
// SolidJS will handle reactivity efficiently
|
||||
// Only optimize if users report issues
|
||||
```
|
||||
|
||||
### State Update Batching
|
||||
|
||||
**Not needed for MVP:**
|
||||
|
||||
- SolidJS reactivity is efficient enough
|
||||
- SSE updates will just trigger normal re-renders
|
||||
- Add batching only if performance issues arise
|
||||
|
||||
### Memory Management
|
||||
|
||||
**Not needed for MVP:**
|
||||
|
||||
- No message limits
|
||||
- No pruning
|
||||
- No lazy loading
|
||||
- Let users create as many messages as they want
|
||||
- Optimize later if problems occur
|
||||
|
||||
**When to add optimizations (post-MVP):**
|
||||
|
||||
- Users report slowness with large sessions
|
||||
- Measurable performance degradation
|
||||
- Memory usage becomes problematic
|
||||
- See Phase 8 tasks for virtual scrolling and optimization
|
||||
|
||||
## IPC Communication
|
||||
|
||||
### Main Process → Renderer
|
||||
|
||||
```typescript
|
||||
// Events sent from main to renderer
|
||||
type MainToRenderer = {
|
||||
"instance:started": { id: string; port: number; pid: number }
|
||||
"instance:error": { id: string; error: string }
|
||||
"instance:stopped": { id: string }
|
||||
"instance:log": { id: string; entry: LogEntry }
|
||||
}
|
||||
```
|
||||
|
||||
### Renderer → Main Process
|
||||
|
||||
```typescript
|
||||
// Commands sent from renderer to main
|
||||
type RendererToMain = {
|
||||
"folder:select": () => Promise<string | null>
|
||||
"instance:create": (folder: string) => Promise<{ port: number; pid: number }>
|
||||
"instance:stop": (pid: number) => Promise<void>
|
||||
"app:quit": () => void
|
||||
}
|
||||
```
|
||||
|
||||
### Preload Script (Bridge)
|
||||
|
||||
```typescript
|
||||
// Expose safe IPC methods to renderer
|
||||
contextBridge.exposeInMainWorld("electronAPI", {
|
||||
selectFolder: () => ipcRenderer.invoke("folder:select"),
|
||||
createInstance: (folder: string) => ipcRenderer.invoke("instance:create", folder),
|
||||
stopInstance: (pid: number) => ipcRenderer.invoke("instance:stop", pid),
|
||||
onInstanceStarted: (callback) => ipcRenderer.on("instance:started", callback),
|
||||
onInstanceError: (callback) => ipcRenderer.on("instance:error", callback),
|
||||
})
|
||||
```
|
||||
|
||||
## Error Handling Strategy
|
||||
|
||||
### Network Errors
|
||||
|
||||
```typescript
|
||||
// HTTP request fails
|
||||
try {
|
||||
const response = await client.session.list()
|
||||
} catch (error) {
|
||||
if (error.code === "ECONNREFUSED") {
|
||||
// Server not responding
|
||||
showError("Cannot connect to server. Is it running?")
|
||||
} else if (error.code === "ETIMEDOUT") {
|
||||
// Request timeout
|
||||
showError("Request timed out. Retry?", { retry: true })
|
||||
} else {
|
||||
// Unknown error
|
||||
showError(error.message)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### SSE Errors
|
||||
|
||||
```typescript
|
||||
eventSource.onerror = (error) => {
|
||||
// Connection lost
|
||||
if (eventSource.readyState === EventSource.CLOSED) {
|
||||
// Attempt reconnect
|
||||
reconnectSSE()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### User Input Errors
|
||||
|
||||
```typescript
|
||||
// Validate before sending
|
||||
function validatePrompt(text: string): string | null {
|
||||
if (!text.trim()) {
|
||||
return "Message cannot be empty"
|
||||
}
|
||||
if (text.length > 10000) {
|
||||
return "Message too long (max 10000 characters)"
|
||||
}
|
||||
return null
|
||||
}
|
||||
```
|
||||
|
||||
## Security Measures
|
||||
|
||||
### IPC Security
|
||||
|
||||
- Use `contextIsolation: true`
|
||||
- Whitelist allowed IPC channels
|
||||
- Validate all data from renderer
|
||||
- No `nodeIntegration` in renderer
|
||||
|
||||
### Process Security
|
||||
|
||||
- Spawn OpenCode with user permissions only
|
||||
- No shell execution of user input
|
||||
- Sanitize file paths
|
||||
|
||||
### Content Security
|
||||
|
||||
- Sanitize markdown before rendering
|
||||
- Use DOMPurify for HTML sanitization
|
||||
- No `dangerouslySetInnerHTML` without sanitization
|
||||
- CSP headers in renderer
|
||||
|
||||
## Testing Strategy (Future)
|
||||
|
||||
### Unit Tests
|
||||
|
||||
- State management logic
|
||||
- Utility functions
|
||||
- Message parsing
|
||||
|
||||
### Integration Tests
|
||||
|
||||
- Process spawning
|
||||
- SDK client operations
|
||||
- SSE event handling
|
||||
|
||||
### E2E Tests
|
||||
|
||||
- Complete user flows
|
||||
- Multi-instance scenarios
|
||||
- Error recovery
|
||||
|
||||
## Build & Packaging
|
||||
|
||||
### Development
|
||||
|
||||
```bash
|
||||
npm run dev # Start Electron + Vite dev server
|
||||
npm run dev:main # Main process only
|
||||
npm run dev:renderer # Renderer only
|
||||
```
|
||||
|
||||
### Production
|
||||
|
||||
```bash
|
||||
npm run build # Build all
|
||||
npm run build:main # Build main process
|
||||
npm run build:renderer # Build renderer
|
||||
npm run package # Create distributable
|
||||
```
|
||||
|
||||
### Distribution
|
||||
|
||||
- macOS: DMG + auto-update
|
||||
- Windows: NSIS installer + auto-update
|
||||
- Linux: AppImage + deb/rpm
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### electron.vite.config.ts
|
||||
|
||||
```typescript
|
||||
import { defineConfig } from "electron-vite"
|
||||
import solid from "vite-plugin-solid"
|
||||
|
||||
export default defineConfig({
|
||||
main: {
|
||||
build: {
|
||||
rollupOptions: {
|
||||
external: ["electron"],
|
||||
},
|
||||
},
|
||||
},
|
||||
preload: {
|
||||
build: {
|
||||
rollupOptions: {
|
||||
external: ["electron"],
|
||||
},
|
||||
},
|
||||
},
|
||||
renderer: {
|
||||
plugins: [solid()],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": "/src",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### tsconfig.json
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2020", "DOM"],
|
||||
"jsx": "preserve",
|
||||
"jsxImportSource": "solid-js",
|
||||
"moduleResolution": "bundler",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
493
dev-docs/user-interface.md
Normal file
493
dev-docs/user-interface.md
Normal file
@@ -0,0 +1,493 @@
|
||||
# User Interface Specification
|
||||
|
||||
## Overview
|
||||
|
||||
The CodeNomad interface consists of a two-level tabbed layout with instance tabs at the top and session tabs below. Each session displays a message stream and prompt input.
|
||||
|
||||
## Layout Structure
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ File Edit View Window Help ● ○ ◐ │ ← Native menu bar
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ [~/project-a] [~/project-a (2)] [~/api-service] [+] │ ← Instance tabs (Level 1)
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ [Main] [Fix login] [Write tests] [Logs] [+] │ ← Session tabs (Level 2)
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ Messages Area │ │
|
||||
│ │ │ │
|
||||
│ │ User: How do I set up testing? │ │
|
||||
│ │ │ │
|
||||
│ │ Assistant: To set up testing, you'll need to... │ │
|
||||
│ │ → bash: npm install vitest ✓ │ │
|
||||
│ │ Output: added 50 packages │ │
|
||||
│ │ │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ Agent: Build ▼ Model: Claude 3.5 Sonnet ▼ │ ← Controls
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ [@file.ts] [@api.ts] [×] │ ← Attachments
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ Type your message or /command... │ │ ← Prompt input
|
||||
│ │ │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ [▶] │ ← Send button
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Components Specification
|
||||
|
||||
### 1. Instance Tabs (Level 1)
|
||||
|
||||
**Visual Design:**
|
||||
|
||||
- Horizontal tabs at top of window
|
||||
- Each tab shows folder name
|
||||
- Icon: Folder icon (🗂️)
|
||||
- Close button (×) on hover
|
||||
- Active tab: Highlighted with accent color
|
||||
- Inactive tabs: Muted background
|
||||
|
||||
**Tab Label Format:**
|
||||
|
||||
- Single instance: `~/project-name`
|
||||
- Multiple instances of same folder: `~/project-name (2)`, `~/project-name (3)`
|
||||
- Max width: 200px with ellipsis for long paths
|
||||
- Tooltip shows full path on hover
|
||||
|
||||
**Actions:**
|
||||
|
||||
- Click: Switch to that instance
|
||||
- Close (×): Stop server and close instance (with confirmation)
|
||||
- Drag: Reorder tabs (future)
|
||||
|
||||
**New Instance Button (+):**
|
||||
|
||||
- Always visible at right end
|
||||
- Click: Opens folder picker dialog
|
||||
- Keyboard: Cmd/Ctrl+N
|
||||
|
||||
**States:**
|
||||
|
||||
- Starting: Loading spinner + "Starting..."
|
||||
- Ready: Normal appearance
|
||||
- Error: Red indicator + error icon
|
||||
- Stopped: Grayed out (should not be visible, tab closes)
|
||||
|
||||
### 2. Session Tabs (Level 2)
|
||||
|
||||
**Visual Design:**
|
||||
|
||||
- Horizontal tabs below instance tabs
|
||||
- Smaller than instance tabs
|
||||
- Each tab shows session title or "Untitled"
|
||||
- Active tab: Underline or bold
|
||||
- Parent-child relationship: No visual distinction (all siblings)
|
||||
|
||||
**Tab Types:**
|
||||
|
||||
**Session Tab:**
|
||||
|
||||
- Label: Session title (editable on double-click)
|
||||
- Icon: Chat bubble (💬) or none
|
||||
- Close button (×) on hover
|
||||
- Max width: 150px with ellipsis
|
||||
|
||||
**Logs Tab:**
|
||||
|
||||
- Label: "Logs"
|
||||
- Icon: Terminal (⚡)
|
||||
- Always present per instance
|
||||
- Non-closable
|
||||
- Shows server stdout/stderr
|
||||
|
||||
**Actions:**
|
||||
|
||||
- Click: Switch to that session
|
||||
- Double-click label: Rename session
|
||||
- Close (×): Delete session (with confirmation if has messages)
|
||||
- Right-click: Context menu (Share, Export, Delete)
|
||||
|
||||
**New Session Button (+):**
|
||||
|
||||
- Click: Creates new session with default agent
|
||||
- Keyboard: Cmd/Ctrl+T
|
||||
|
||||
### 3. Messages Area
|
||||
|
||||
**Container:**
|
||||
|
||||
- Scrollable viewport
|
||||
- Auto-scroll to bottom when new messages arrive
|
||||
- Manual scroll up: Disable auto-scroll
|
||||
- "Scroll to bottom" button appears when scrolled up
|
||||
|
||||
**Message Layout:**
|
||||
|
||||
**User Message:**
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ You 10:32 AM │
|
||||
│ How do I set up testing? │
|
||||
│ │
|
||||
│ [@src/app.ts] [@package.json] │ ← Attachments if any
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Assistant Message:**
|
||||
|
||||
````
|
||||
┌──────────────────────────────────────────┐
|
||||
│ Assistant • Build 10:32 AM │
|
||||
│ To set up testing, you'll need to │
|
||||
│ install Vitest and configure it. │
|
||||
│ │
|
||||
│ ▶ bash: npm install vitest ✓ │ ← Tool call (collapsed)
|
||||
│ │
|
||||
│ ▶ edit src/vitest.config.ts ✓ │
|
||||
│ │
|
||||
│ Here's the configuration I added: │
|
||||
│ ```typescript │
|
||||
│ export default { │
|
||||
│ test: { globals: true } │
|
||||
│ } │
|
||||
│ ``` │
|
||||
└──────────────────────────────────────────┘
|
||||
````
|
||||
|
||||
**Tool Call (Collapsed):**
|
||||
|
||||
```
|
||||
▶ bash: npm install vitest ✓
|
||||
^ ^ ^
|
||||
| | |
|
||||
Icon Tool name + summary Status
|
||||
```
|
||||
|
||||
**Tool Call (Expanded):**
|
||||
|
||||
```
|
||||
▼ bash: npm install vitest ✓
|
||||
|
||||
Input:
|
||||
{
|
||||
"command": "npm install vitest"
|
||||
}
|
||||
|
||||
Output:
|
||||
added 50 packages, and audited 51 packages in 2s
|
||||
found 0 vulnerabilities
|
||||
```
|
||||
|
||||
**Status Icons:**
|
||||
|
||||
- ⏳ Pending (spinner)
|
||||
- ✓ Success (green checkmark)
|
||||
- ✗ Error (red X)
|
||||
- ⚠ Warning (yellow triangle)
|
||||
|
||||
**File Change Display:**
|
||||
|
||||
```
|
||||
▶ edit src/vitest.config.ts ✓
|
||||
Modified: src/vitest.config.ts
|
||||
+12 lines, -3 lines
|
||||
```
|
||||
|
||||
Click to expand: Show diff inline
|
||||
|
||||
### 4. Controls Bar
|
||||
|
||||
**Agent Selector:**
|
||||
|
||||
- Dropdown button showing current agent
|
||||
- Click: Opens dropdown with agent list
|
||||
- Shows: Agent name + description
|
||||
- Grouped by category (if applicable)
|
||||
|
||||
**Model Selector:**
|
||||
|
||||
- Dropdown button showing current model
|
||||
- Click: Opens dropdown with model list
|
||||
- Shows: Provider icon + Model name
|
||||
- Grouped by provider
|
||||
- Displays: Context window, capabilities icons
|
||||
|
||||
**Layout:**
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────┐
|
||||
│ Agent: Build ▼ Model: Claude 3.5 ▼ │
|
||||
└────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5. Prompt Input
|
||||
|
||||
**Input Field:**
|
||||
|
||||
- Multi-line textarea
|
||||
- Auto-expanding (max 10 lines)
|
||||
- Placeholder: "Type your message or /command..."
|
||||
- Supports keyboard shortcuts
|
||||
|
||||
**Features:**
|
||||
|
||||
**Slash Commands:**
|
||||
|
||||
- Type `/` → Autocomplete dropdown appears
|
||||
- Shows: Command name + description
|
||||
- Filter as you type
|
||||
- Enter to execute
|
||||
|
||||
**File Mentions:**
|
||||
|
||||
- Type `@` → File picker appears
|
||||
- Search files by name
|
||||
- Shows: File icon + path
|
||||
- Enter to attach
|
||||
|
||||
**Attachments:**
|
||||
|
||||
- Display as chips above input
|
||||
- Format: [@filename] [×]
|
||||
- Click × to remove
|
||||
- Drag & drop files onto input area
|
||||
|
||||
**Send Button:**
|
||||
|
||||
- Icon: Arrow (▶) or paper plane
|
||||
- Click: Submit message
|
||||
- Keyboard: Enter (without Shift)
|
||||
- Disabled when: Empty input or server busy
|
||||
|
||||
**Keyboard Shortcuts:**
|
||||
|
||||
- Enter: New line
|
||||
- Cmd+Enter (macOS) / Ctrl+Enter (Windows/Linux): Send message
|
||||
- Cmd/Ctrl+K: Clear input
|
||||
- Cmd/Ctrl+V: Paste (handles files)
|
||||
- Cmd/Ctrl+L: Focus input
|
||||
- Up/Down: Navigate message history (when input empty)
|
||||
|
||||
## Overlays & Modals
|
||||
|
||||
### Session Picker (Startup)
|
||||
|
||||
Appears when instance starts:
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────┐
|
||||
│ OpenCode • ~/project-a │
|
||||
├────────────────────────────────────────┤
|
||||
│ Resume a session: │
|
||||
│ │
|
||||
│ > Fix login bug 2h ago │
|
||||
│ Add dark mode 5h ago │
|
||||
│ Refactor API Yesterday │
|
||||
│ │
|
||||
│ ────────────── or ────────────── │
|
||||
│ │
|
||||
│ Start new session: │
|
||||
│ Agent: [Build ▼] [Start] │
|
||||
│ │
|
||||
│ [Cancel] │
|
||||
└────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Actions:**
|
||||
|
||||
- Click session: Resume that session
|
||||
- Click "Start": Create new session with selected agent
|
||||
- Click "Cancel": Close instance
|
||||
- Keyboard: Arrow keys to navigate, Enter to select
|
||||
|
||||
### Confirmation Dialogs
|
||||
|
||||
**Close Instance:**
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────┐
|
||||
│ Stop OpenCode instance? │
|
||||
├────────────────────────────────────────┤
|
||||
│ This will stop the server for: │
|
||||
│ ~/project-a │
|
||||
│ │
|
||||
│ Active sessions will be lost. │
|
||||
│ │
|
||||
│ [Cancel] [Stop Instance] │
|
||||
└────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Delete Session:**
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────┐
|
||||
│ Delete session? │
|
||||
├────────────────────────────────────────┤
|
||||
│ This will permanently delete: │
|
||||
│ "Fix login bug" │
|
||||
│ │
|
||||
│ This cannot be undone. │
|
||||
│ │
|
||||
│ [Cancel] [Delete] │
|
||||
└────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Empty States
|
||||
|
||||
### No Instances
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ │
|
||||
│ [Folder Icon] │
|
||||
│ │
|
||||
│ Start Coding with AI │
|
||||
│ │
|
||||
│ Select a folder to start coding with AI │
|
||||
│ │
|
||||
│ [Select Folder] │
|
||||
│ │
|
||||
│ Keyboard shortcut: Cmd/Ctrl+N │
|
||||
│ │
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### No Messages (New Session)
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ │
|
||||
│ Start a conversation │
|
||||
│ │
|
||||
│ Type a message below or try: │
|
||||
│ • /init-project │
|
||||
│ • Ask about your codebase │
|
||||
│ • Attach files with @ │
|
||||
│ │
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Logs Tab (No Logs Yet)
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ Waiting for server output... │
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Visual Styling
|
||||
|
||||
### Color Scheme
|
||||
|
||||
**Light Mode:**
|
||||
|
||||
- Background: #FFFFFF
|
||||
- Secondary background: #F5F5F5
|
||||
- Border: #E0E0E0
|
||||
- Text: #1A1A1A
|
||||
- Muted text: #666666
|
||||
- Accent: #0066FF
|
||||
|
||||
**Dark Mode:**
|
||||
|
||||
- Background: #1A1A1A
|
||||
- Secondary background: #2A2A2A
|
||||
- Border: #3A3A3A
|
||||
- Text: #E0E0E0
|
||||
- Muted text: #999999
|
||||
- Accent: #0080FF
|
||||
|
||||
### Typography
|
||||
|
||||
- **Main text**: 14px, system font
|
||||
- **Headers**: 16px, medium weight
|
||||
- **Labels**: 12px, regular weight
|
||||
- **Code**: Monospace font (Consolas, Monaco, Courier)
|
||||
- **Line height**: 1.5
|
||||
|
||||
### Spacing
|
||||
|
||||
- **Padding**: 8px, 12px, 16px, 24px (consistent scale)
|
||||
- **Margins**: Same as padding
|
||||
- **Tab height**: 40px
|
||||
- **Input height**: 80px (auto-expanding)
|
||||
- **Message spacing**: 16px between messages
|
||||
|
||||
### Icons
|
||||
|
||||
- Use consistent icon set (Lucide, Heroicons, or similar)
|
||||
- Size: 16px for inline, 20px for buttons
|
||||
- Stroke width: 2px
|
||||
|
||||
## Responsive Behavior
|
||||
|
||||
### Minimum Window Size
|
||||
|
||||
- Width: 800px
|
||||
- Height: 600px
|
||||
|
||||
### Behavior When Small
|
||||
|
||||
- Instance tabs: Scroll horizontally
|
||||
- Session tabs: Scroll horizontally
|
||||
- Messages: Always visible, scroll vertically
|
||||
- Input: Fixed at bottom
|
||||
|
||||
## Accessibility
|
||||
|
||||
- All interactive elements keyboard-navigable
|
||||
- ARIA labels for screen readers
|
||||
- Focus indicators visible
|
||||
- Color contrast WCAG AA compliant
|
||||
- Tab trap in modals
|
||||
- Escape key closes overlays
|
||||
|
||||
## Animation & Transitions
|
||||
|
||||
- Tab switching: Instant (no animation)
|
||||
- Message appearance: Fade in (100ms)
|
||||
- Tool expand/collapse: Slide (200ms)
|
||||
- Dropdown menus: Fade + slide (150ms)
|
||||
- Loading states: Spinner or skeleton
|
||||
|
||||
## Context Menus
|
||||
|
||||
### Session Tab Right-Click
|
||||
|
||||
- Rename
|
||||
- Duplicate
|
||||
- Share
|
||||
- Export
|
||||
- Delete
|
||||
- Close Other Tabs
|
||||
|
||||
### Message Right-Click
|
||||
|
||||
- Copy message
|
||||
- Copy code block
|
||||
- Edit & regenerate
|
||||
- Delete message
|
||||
- Quote in reply
|
||||
|
||||
## Status Indicators
|
||||
|
||||
### Instance Tab
|
||||
|
||||
- Green dot: Server running
|
||||
- Yellow dot: Server starting
|
||||
- Red dot: Server error
|
||||
- No dot: Server stopped
|
||||
|
||||
### Session Tab
|
||||
|
||||
- Blue pulse: Assistant responding
|
||||
- No indicator: Idle
|
||||
|
||||
### Connection Status
|
||||
|
||||
- Bottom right corner: "Connected" or "Reconnecting..."
|
||||
Reference in New Issue
Block a user