Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New feature branch #83

Closed
wants to merge 9 commits into from
211 changes: 211 additions & 0 deletions PROJECT_PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
# Project Plan: Bolt.new Any LLM

## Project Overview
A web-based development environment that integrates LLM capabilities with code editing, chat interface, and terminal functionality. The application provides a seamless experience for developers to interact with AI while working on their code.

## Architecture

### Frontend Stack
- React + TypeScript
- Remix for routing and server-side rendering
- SCSS for styling
- CodeMirror for code editing
- Web Container API for terminal emulation

### Core Components

1. Chat System (`app/components/chat/`)
- Base chat interface
- Message handling (user/assistant)
- Code block rendering
- Markdown support
- Image upload capabilities
- Artifact handling

2. Code Editor (`app/components/editor/`)
- CodeMirror integration
- Syntax highlighting
- Multiple language support
- Binary content handling

3. Workbench (`app/components/workbench/`)
- File tree navigation
- Editor panel
- Preview functionality
- Terminal integration
- Port management

4. Terminal (`app/components/workbench/terminal/`)
- Command execution
- Custom theming
- Shell integration

### State Management
- Store-based architecture (`app/lib/stores/`)
- Chat state
- Editor state
- File system state
- Preview management
- Settings
- Terminal state
- Theme management
- Workbench state

### Data Persistence
- Local storage based persistence
- Chat history management
- File system state preservation
- User preferences storage

### Runtime Features
- Message parsing system
- Action running capabilities
- Prompt enhancement
- Web container integration

## Key Features

1. AI Integration
- Real-time chat interface
- Code-aware responses
- Context-aware suggestions
- File system integration

2. Development Environment
- Multi-file editing
- Live preview
- Terminal access
- File system operations

3. User Experience
- Theme switching
- Responsive design
- Keyboard shortcuts
- Drag-and-drop support

4. File Management
- File tree navigation
- File creation/editing
- Binary file handling
- Breadcrumb navigation

## Implementation Priorities

1. Core Infrastructure
- Basic application setup
- Routing system
- State management
- Theme support

2. Editor Integration
- CodeMirror setup
- Language support
- File handling

3. Chat System
- Message handling
- AI integration
- Code block support
- Markdown rendering

4. Terminal & Preview
- Terminal emulation
- Preview functionality
- Port management

5. User Experience
- Responsive design
- Keyboard shortcuts
- Performance optimization

## Technical Considerations

### Performance
- Efficient state management
- Lazy loading of components
- Optimized file handling
- Memory management for terminal sessions

### Security
- Secure file system operations
- Safe terminal command execution
- Input sanitization
- Secure AI interactions

### Accessibility
- Keyboard navigation
- Screen reader support
- ARIA attributes
- Color contrast compliance

### Browser Compatibility
- Modern browser support
- Progressive enhancement
- Fallback behaviors
- Mobile device support

## Development Workflow

1. Version Control
- Git-based workflow
- Feature branching
- Pull request reviews
- Semantic versioning

2. Code Quality
- TypeScript for type safety
- ESLint for code linting
- Prettier for code formatting
- Unit testing with Jest

3. Documentation
- Code documentation
- API documentation
- User guides
- Contributing guidelines

## Future Enhancements

1. Collaboration Features
- Real-time collaboration
- Shared terminals
- Chat history sharing
- Project sharing

2. Advanced AI Features
- Multiple model support
- Custom model integration
- Enhanced context awareness
- Code generation improvements

3. Development Tools
- Debugging capabilities
- Performance profiling
- Error tracking
- Analytics integration

4. Extensibility
- Plugin system
- Custom themes
- API integrations
- Custom commands

## Maintenance & Support

1. Monitoring
- Error tracking
- Performance monitoring
- Usage analytics
- User feedback collection

2. Updates
- Regular dependency updates
- Security patches
- Feature enhancements
- Bug fixes

3. Support
- Documentation maintenance
- Issue tracking
- Community engagement
- User support channels
15 changes: 15 additions & 0 deletions app/components/chat/BaseChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import { classNames } from '~/utils/classNames';
import { MODEL_LIST, DEFAULT_PROVIDER } from '~/utils/constants';
import { Messages } from './Messages.client';
import { SendButton } from './SendButton.client';
import { LastSavedIndicator } from './LastSavedIndicator.client';
import { useState } from 'react';
import { ImageUpload } from './ImageUpload';

import styles from './BaseChat.module.scss';

Expand Down Expand Up @@ -83,6 +85,8 @@ interface BaseChatProps {
sendMessage?: (event: React.UIEvent, messageInput?: string) => void;
handleInputChange?: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
enhancePrompt?: () => void;
imageFile?: File | null;
onImageUpload?: (file: File) => void;
}

export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
Expand All @@ -104,6 +108,8 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
handleInputChange,
enhancePrompt,
handleStop,
imageFile,
onImageUpload,
},
ref,
) => {
Expand Down Expand Up @@ -229,6 +235,10 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
</>
)}
</IconButton>
<ImageUpload onImageUpload={onImageUpload} />
<ClientOnly>
{() => <LastSavedIndicator />}
</ClientOnly>
</div>
{input.length > 3 ? (
<div className="text-xs text-bolt-elements-textTertiary">
Expand All @@ -237,6 +247,11 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
) : null}
</div>
</div>
{imageFile && (
<div className="px-4 pb-2 text-sm text-bolt-elements-textSecondary">
Image attached: {imageFile.name}
</div>
)}
<div className="bg-bolt-elements-background-depth-1 pb-6">{/* Ghost Element */}</div>
</div>
</div>
Expand Down
59 changes: 30 additions & 29 deletions app/components/chat/Chat.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { DEFAULT_MODEL } from '~/utils/constants';
import { cubicEasingFn } from '~/utils/easings';
import { createScopedLogger, renderLogger } from '~/utils/logger';
import { BaseChat } from './BaseChat';
import { ImageUpload } from './ImageUpload';

const toastAnimation = cssTransition({
enter: 'animated fadeInRight',
Expand All @@ -40,9 +41,6 @@ export function Chat() {
);
}}
icon={({ type }) => {
/**
* @todo Handle more types if we need them. This may require extra color palettes.
*/
switch (type) {
case 'success': {
return <div className="i-ph:check-bold text-bolt-elements-icon-success text-2xl" />;
Expand All @@ -51,7 +49,6 @@ export function Chat() {
return <div className="i-ph:warning-circle-bold text-bolt-elements-icon-error text-2xl" />;
}
}

return undefined;
}}
position="bottom-right"
Expand All @@ -74,6 +71,7 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp

const [chatStarted, setChatStarted] = useState(initialMessages.length > 0);
const [model, setModel] = useState(DEFAULT_MODEL);
const [imageFile, setImageFile] = useState<File | null>(null);

const { showChat } = useStore(chatStore);

Expand Down Expand Up @@ -153,17 +151,10 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
const sendMessage = async (_event: React.UIEvent, messageInput?: string) => {
const _input = messageInput || input;

if (_input.length === 0 || isLoading) {
if ((_input.length === 0 && !imageFile) || isLoading) {
return;
}

/**
* @note (delm) Usually saving files shouldn't take long but it may take longer if there
* many unsaved files. In that case we need to block user input and show an indicator
* of some kind so the user is aware that something is happening. But I consider the
* happy case to be no unsaved files and I would expect users to save their changes
* before they send another message.
*/
await workbenchStore.saveAllFiles();

const fileModifications = workbenchStore.getFileModifcations();
Expand All @@ -172,36 +163,44 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp

runAnimation();

let messageContent = `[Model: ${model}]\n\n`;

if (fileModifications !== undefined) {
const diff = fileModificationsToHTML(fileModifications);
messageContent += `${diff}\n\n`;
}

/**
* If we have file modifications we append a new user message manually since we have to prefix
* the user input with the file modifications and we don't want the new user input to appear
* in the prompt. Using `append` is almost the same as `handleSubmit` except that we have to
* manually reset the input and we'd have to manually pass in file attachments. However, those
* aren't relevant here.
*/
append({ role: 'user', content: `[Model: ${model}]\n\n${diff}\n\n${_input}` });

/**
* After sending a new message we reset all modifications since the model
* should now be aware of all the changes.
*/
workbenchStore.resetAllFileModifications();
messageContent += _input;

if (imageFile) {
const reader = new FileReader();
reader.onload = async (e) => {
const base64Image = e.target?.result as string;
messageContent += `\n\n[Attached Image: ${imageFile.name}]\n${base64Image}`;

append({ role: 'user', content: messageContent });
setImageFile(null);
};
reader.readAsDataURL(imageFile);
} else {
append({ role: 'user', content: `[Model: ${model}]\n\n${_input}` });
append({ role: 'user', content: messageContent });
}

setInput('');
if (fileModifications !== undefined) {
workbenchStore.resetAllFileModifications();
}

setInput('');
resetEnhancer();

textareaRef.current?.blur();
};

const [messageRef, scrollRef] = useSnapScroll();

const handleImageUpload = (file: File) => {
setImageFile(file);
};

return (
<BaseChat
ref={animationScope}
Expand Down Expand Up @@ -235,6 +234,8 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
scrollTextArea();
});
}}
imageFile={imageFile}
onImageUpload={handleImageUpload}
/>
);
});
Loading
Loading