diff --git a/README.md b/README.md index 06356ec77..03a38967c 100644 --- a/README.md +++ b/README.md @@ -18,27 +18,91 @@ ![Discord Shield](https://discord.com/api/guilds/1138070673756004464/widget.png?style=shield) -## Sidecar +## Overview + +Sidecar is the AI brains of Aide, providing intelligent code assistance through: +- Code completion and suggestions +- Repository analysis and symbol mapping +- Git integration and version control +- Real-time code intelligence + +## Architecture + +Sidecar consists of several key components: + +### Core Components +- `tool_box.rs` - Collection of language-specific tools and utilities +- `symbol/` - Smart symbol management from file to function level +- `llm_prompts/` - LLM integration and prompt management +- `repomap/` - Repository mapping using PageRank on code symbols + +### Additional Components +- `webserver/` - API endpoints and WebSocket communication +- `chunking/` - Code analysis and segmentation +- `git/` - Version control integration +- `agentic/` - AI agent implementation + +## Features + +1. **Code Intelligence** + - Smart code completion + - Symbol analysis and navigation + - Context-aware suggestions + - Multi-language support + +2. **Repository Analysis** + - Code structure mapping + - Dependency tracking + - Symbol relationship analysis + - Intelligent code navigation + +3. **AI Integration** + - Multiple LLM provider support + - Customizable prompts + - Context-aware responses + - Efficient token management + +## Quick Start + +1. **Prerequisites** + ```bash + # Ensure Rust 1.73 + rustup default 1.73 + + # Clone repository + git clone https://github.com/codestoryai/sidecar.git + cd sidecar + ``` + +2. **Build and Run** + ```bash + # Build the binary + cargo build --bin webserver + + # Run Sidecar + ./target/debug/webserver + ``` + +3. **Configuration** + - Copy `.env.example` to `.env` + - Set required API keys + - Configure model preferences + +## Integration with Aide Editor -Sidecar is the AI brains of Aide the editor. To accomplish the work of creating the prompts, talking to LLM and everything else in between Sidecar is responsible for making sure it all works together. - -Broadly speaking these are the following important bits in Sidecar: -- `tool_box.rs` - The collection of all and any tools AI might need is present here, all the language specific smartness is handled by `tool_box.rs` -- `symbol/` - The symbol folder contains the code which allows each individual symbol to be smart and independent. This can work on any granularity level, all the way from a file to a single function or function inside a class (its very versatile) -- `llm_prompts/` - This is a relic of the past (and somewhat in use still) for creating prompts especially for the inline completion bits. The inline completions bits are not maintained any longer but if you want to take a stab at working on it, please reach out to us on Discord, we are happy to support you. -- `repomap` - This creates a repository map using page rank on the code symbols. Most of the code here is a port of the python implementation done on Aider (do check it out if you are in the market for a CLI tool for code-generation) - -## Getting Started -1. Ensure you are using Rust 1.73 -2. Build the binary: `cargo build --bin webserver` -3. Run the binary: `./target/debug/webserver` -4. Profit! - -## Bonus on how to get your Aide editor to talk to Sidecar: 1. Run the Aide production build or build from source using [this](https://github.com/codestoryai/ide) 2. Run the sidecar binary -3. Since you have a sidecar binary already running, the editor will prefer to use this over starting its own process. -4. Congratulations! You are now running sidecar for Aide locally with your own built binary. +3. Since you have a sidecar binary already running, the editor will prefer to use this over starting its own process +4. Your Aide editor is now using your local Sidecar instance! + +## Documentation + +- [Standalone Sidecar Guide](standalone-sidecar.md) - Build standalone version +- [Settings Guide](sidecar-settings.md) - Configure models and preferences +- [API Documentation](api-documentation.md) - REST and WebSocket APIs +- [Development Guide](development-guide.md) - Development workflow +- [Testing Guide](testing-guide.md) - Testing practices +- [Deployment Guide](deployment-guide.md) - Deployment options ## Contributing @@ -68,4 +132,4 @@ This project has adopted the [Contributor Covenant Code of Conduct](CODE_OF_COND ## License Copyright (c) 2024 CodeStory AI. All rights reserved. -Licensed under the [GNU Affero General Public License v3.0](LICENSE.md). +Licensed under the [GNU Affero General Public License v3.0](LICENSE.md). \ No newline at end of file diff --git a/api-documentation.md b/api-documentation.md new file mode 100644 index 000000000..ab04786e6 --- /dev/null +++ b/api-documentation.md @@ -0,0 +1,156 @@ +# Sidecar API Documentation + +This guide documents the REST and WebSocket APIs exposed by the Sidecar backend. + +## Base URL + +- Development: `http://localhost:3001` +- Production: Configure as needed + +## Authentication + +All API endpoints require authentication via Bearer token: +```http +Authorization: Bearer +``` + +## REST Endpoints + +### Code Completion + +`POST /completion` + +Request code completions based on current context. + +**Request:** +```json +{ + "code": "function hello() {", + "cursor": { "line": 0, "character": 16 }, + "language": "typescript", + "context": { + "filePath": "src/hello.ts", + "projectRoot": "/path/to/project" + } +} +``` + +**Response:** +```json +{ + "completions": [ + { + "text": "console.log('Hello');", + "score": 0.95 + } + ] +} +``` + +### Settings Management + +`GET /settings` + +Retrieve current settings. + +**Response:** +```json +{ + "activeModel": "gpt-4", + "models": [...], + "editorPreferences": {...} +} +``` + +`POST /settings` + +Update settings configuration. + +**Request:** +```json +{ + "activeModel": "claude-2", + "editorPreferences": { + "theme": "dark" + } +} +``` + +### Repository Analysis + +`POST /analyze` + +Analyze repository structure and dependencies. + +**Request:** +```json +{ + "path": "/path/to/repo", + "excludePatterns": ["node_modules", "dist"] +} +``` + +## WebSocket API + +Connect to `ws://localhost:3001/ws` + +### Message Types + +1. **Code Intelligence:** +```json +{ + "type": "codeIntel", + "action": "completion", + "payload": { + "code": "...", + "cursor": {...} + } +} +``` + +2. **File Changes:** +```json +{ + "type": "fileChange", + "action": "edit", + "payload": { + "path": "src/main.ts", + "changes": [...] + } +} +``` + +### Error Responses + +All errors follow this format: +```json +{ + "error": { + "code": "INVALID_REQUEST", + "message": "Invalid completion request format" + } +} +``` + +## Rate Limiting + +- 60 requests per minute for completion endpoints +- 120 requests per minute for other endpoints +- WebSocket messages: 10 per second + +## Best Practices + +1. **Error Handling** + - Always check response status codes + - Implement exponential backoff for retries + - Handle WebSocket reconnection gracefully + +2. **Performance** + - Batch related requests when possible + - Cache completion results locally + - Reuse WebSocket connections + +3. **Security** + - Never send sensitive data in URLs + - Validate all input on client-side + - Use HTTPS in production \ No newline at end of file diff --git a/architecture.md b/architecture.md new file mode 100644 index 000000000..d2688a9cd --- /dev/null +++ b/architecture.md @@ -0,0 +1,238 @@ +# Sidecar Architecture Guide + +This document provides a detailed overview of Sidecar's architecture and how its components work together. + +## High-Level Architecture + +``` +┌─────────────────┐ ┌──────────────┐ ┌───────────────┐ +│ IDE Extension │◄────┤ WebServer │◄────┤ AI Pipeline │ +└─────────────────┘ └──────────────┘ └───────────────┘ + │ ▲ + ▼ │ + ┌──────────────┐ ┌───────────────┐ + │ Repository │────►│ Code Analysis │ + │ Manager │ │ Engine │ + └──────────────┘ └───────────────┘ +``` + +## Core Components + +### 1. WebServer (`src/webserver/`) +- HTTP/WebSocket server using Axum +- Handles API requests and real-time communication +- Manages authentication and session state +- Routes requests to appropriate handlers + +### 2. AI Pipeline (`src/agentic/`) +- Processes code analysis requests +- Manages LLM interactions +- Handles prompt generation and response parsing +- Implements retry and fallback logic + +### 3. Repository Manager (`src/repo/`) +- Git integration and version control +- File system operations +- Cache management +- Change tracking + +### 4. Code Analysis Engine +- Symbol extraction and mapping +- Dependency analysis +- Code chunking and parsing +- Language-specific processing + +## Data Flow + +1. **Request Processing:** +```mermaid +sequenceDiagram + IDE->>WebServer: Request (HTTP/WS) + WebServer->>Auth: Validate + WebServer->>Router: Route + Router->>Handler: Process + Handler->>Response: Generate + Response->>IDE: Send +``` + +2. **Code Analysis:** +```mermaid +sequenceDiagram + Handler->>Repo: Get Files + Repo->>Chunker: Process + Chunker->>Symbols: Extract + Symbols->>Analysis: Analyze + Analysis->>Handler: Results +``` + +## Key Subsystems + +### 1. Symbol Management (`src/symbol/`) +```rust +pub struct Symbol { + name: String, + kind: SymbolKind, + location: Location, + children: Vec, +} + +impl Symbol { + pub fn analyze(&self) -> Analysis { + // Symbol-specific analysis + } +} +``` + +### 2. LLM Integration (`src/llm/`) +```rust +pub trait LLMProvider { + async fn complete(&self, prompt: &str) -> Result; + async fn embed(&self, text: &str) -> Result>; +} +``` + +### 3. Repository Mapping (`src/repomap/`) +```rust +pub struct RepoMap { + nodes: Vec, + edges: Vec, + page_rank: HashMap, +} +``` + +## State Management + +### 1. Application State +```rust +pub struct AppState { + config: Config, + llm_client: Arc, + repo_manager: Arc, +} +``` + +### 2. Session State +```rust +pub struct Session { + id: String, + context: Context, + history: Vec, +} +``` + +## Performance Optimizations + +### 1. Caching System +- In-memory cache for frequent operations +- Disk cache for larger datasets +- Cache invalidation strategies + +### 2. Parallel Processing +- Async request handling +- Parallel file processing +- Concurrent LLM requests + +## Security Architecture + +### 1. Authentication +- Token-based authentication +- Role-based access control +- Session management + +### 2. Data Security +- API key encryption +- Secure WebSocket connections +- Input sanitization + +## Error Handling + +### 1. Error Types +```rust +#[derive(Error, Debug)] +pub enum SidecarError { + #[error("IO error: {0}")] + IO(#[from] std::io::Error), + + #[error("LLM error: {0}")] + LLM(String), + + #[error("Analysis error: {0}")] + Analysis(String), +} +``` + +### 2. Recovery Strategies +- Graceful degradation +- Automatic retries +- Fallback mechanisms + +## Configuration System + +### 1. Environment Configuration +```toml +[server] +host = "0.0.0.0" +port = 3001 + +[llm] +provider = "openai" +model = "gpt-4" + +[analysis] +chunk_size = 1000 +cache_ttl = 3600 +``` + +### 2. Runtime Configuration +- Dynamic model switching +- Feature flags +- Performance tuning + +## Extension Points + +### 1. Language Support +- Language parser interface +- Custom analysis rules +- Language-specific optimizations + +### 2. LLM Providers +- Provider interface +- Custom prompt templates +- Response processors + +## Monitoring and Telemetry + +### 1. Metrics +- Request latency +- Token usage +- Cache hit rates +- Error rates + +### 2. Logging +- Structured logging +- Performance tracing +- Error tracking + +## Development Guidelines + +### 1. Code Organization +- Feature-based directory structure +- Clear separation of concerns +- Consistent naming conventions + +### 2. Testing Strategy +- Unit tests per component +- Integration tests for workflows +- Performance benchmarks + +## Future Architecture + +### 1. Planned Improvements +- Distributed processing +- Enhanced caching +- Real-time collaboration + +### 2. Scalability Plans +- Horizontal scaling +- Load balancing +- Database sharding \ No newline at end of file diff --git a/deployment-guide.md b/deployment-guide.md new file mode 100644 index 000000000..195f59737 --- /dev/null +++ b/deployment-guide.md @@ -0,0 +1,248 @@ +# Sidecar Deployment Guide + +This guide explains how to deploy Sidecar in various environments. + +## Deployment Options + +### 1. Docker Deployment + +```dockerfile +# Dockerfile +FROM rust:1.73 as builder +WORKDIR /app +COPY . . +RUN cargo build --release + +FROM node:18 as frontend-builder +WORKDIR /app +COPY frontend . +RUN npm install && npm run build + +FROM debian:bullseye-slim +COPY --from=builder /app/target/release/sidecar /usr/local/bin/ +COPY --from=frontend-builder /app/dist /usr/share/sidecar/frontend +EXPOSE 3001 +CMD ["sidecar"] +``` + +Deploy with Docker Compose: +```yaml +# docker-compose.yml +version: '3.8' +services: + sidecar: + build: . + ports: + - "3001:3001" + environment: + - OPENAI_API_KEY=${OPENAI_API_KEY} + - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} + volumes: + - ./data:/data +``` + +### 2. Kubernetes Deployment + +```yaml +# kubernetes/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sidecar +spec: + replicas: 3 + selector: + matchLabels: + app: sidecar + template: + metadata: + labels: + app: sidecar + spec: + containers: + - name: sidecar + image: sidecar:latest + ports: + - containerPort: 3001 + env: + - name: OPENAI_API_KEY + valueFrom: + secretKeyRef: + name: llm-secrets + key: openai-key +``` + +### 3. Bare Metal Deployment + +1. **System Requirements:** + - 4+ CPU cores + - 8GB+ RAM + - 20GB+ storage + - Linux/Unix OS + +2. **Installation:** +```bash +# Install dependencies +apt-get update && apt-get install -y \ + build-essential \ + pkg-config \ + libssl-dev + +# Build and install +cargo install --path . + +# Setup systemd service +cat > /etc/systemd/system/sidecar.service << EOF +[Unit] +Description=Sidecar AI Code Assistant +After=network.target + +[Service] +Type=simple +User=sidecar +Environment=RUST_LOG=info +ExecStart=/usr/local/bin/sidecar +Restart=always + +[Install] +WantedBy=multi-user.target +EOF + +systemctl enable --now sidecar +``` + +## Configuration + +### 1. Environment Variables + +```bash +# .env +RUST_LOG=info +SIDECAR_PORT=3001 +OPENAI_API_KEY=sk-... +ANTHROPIC_API_KEY=sk-... +``` + +### 2. SSL/TLS Setup + +```nginx +# nginx configuration +server { + listen 443 ssl; + server_name sidecar.example.com; + + ssl_certificate /etc/letsencrypt/live/sidecar.example.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/sidecar.example.com/privkey.pem; + + location / { + proxy_pass http://localhost:3001; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + } +} +``` + +## Monitoring + +### 1. Health Checks + +```bash +# Check service health +curl http://localhost:3001/health + +# Monitor logs +journalctl -u sidecar -f +``` + +### 2. Metrics + +```yaml +# prometheus.yml +scrape_configs: + - job_name: 'sidecar' + static_configs: + - targets: ['localhost:3001'] +``` + +## Scaling + +### 1. Horizontal Scaling + +- Use load balancer +- Configure session affinity +- Scale based on CPU/memory usage + +### 2. Vertical Scaling + +- Increase resources +- Optimize memory usage +- Configure cache size + +## Backup and Recovery + +1. **Data Backup:** +```bash +# Backup script +#!/bin/bash +DATE=$(date +%Y%m%d) +tar -czf backup-$DATE.tar.gz /data/sidecar +aws s3 cp backup-$DATE.tar.gz s3://backups/ +``` + +2. **Recovery:** +```bash +# Recovery script +#!/bin/bash +aws s3 cp s3://backups/backup-latest.tar.gz . +tar -xzf backup-latest.tar.gz -C /data/sidecar +systemctl restart sidecar +``` + +## Security + +1. **Firewall Rules:** +```bash +# Allow only necessary ports +ufw allow 443/tcp +ufw allow 3001/tcp +``` + +2. **API Authentication:** +```nginx +# Add authentication header +proxy_set_header Authorization "Bearer ${API_KEY}"; +``` + +## Troubleshooting + +1. **Common Issues:** + - Check logs: `journalctl -u sidecar` + - Verify permissions + - Check API keys + - Monitor resource usage + +2. **Performance Issues:** + - Profile CPU/memory + - Check network latency + - Monitor LLM response times + +## Maintenance + +1. **Updates:** +```bash +# Update script +#!/bin/bash +git pull +cargo build --release +systemctl restart sidecar +``` + +2. **Cleanup:** +```bash +# Cleanup old logs +find /var/log/sidecar -mtime +30 -delete + +# Cleanup temp files +find /tmp/sidecar -mtime +1 -delete +``` \ No newline at end of file diff --git a/development-guide.md b/development-guide.md new file mode 100644 index 000000000..9d80f1b34 --- /dev/null +++ b/development-guide.md @@ -0,0 +1,271 @@ +# Sidecar Development Guide + +This guide helps developers understand Sidecar's architecture and contribute effectively. + +## Project Structure + +``` +sidecar/ +├── src/ +│ ├── agentic/ # AI agent implementation +│ ├── chunking/ # Code chunking and analysis +│ ├── git/ # Git integration +│ ├── llm/ # LLM client implementations +│ ├── repomap/ # Repository mapping +│ └── webserver/ # API endpoints +├── llm_client/ # LLM API clients +├── llm_prompts/ # Prompt templates +└── logging/ # Logging infrastructure +``` + +## Development Setup + +1. **Prerequisites:** + - Rust 1.73+ + - Node.js 18+ + - Git + - VSCode with recommended extensions + +2. **Environment Setup:** + ```bash + # Clone repository + git clone https://github.com/yourusername/sidecar.git + cd sidecar + + # Install Rust dependencies + cargo build + + # Install frontend dependencies + cd frontend + npm install + ``` + +3. **Configuration:** + - Copy `.env.example` to `.env` + - Set required API keys and configurations + +## Docker Development Environment + +1. **Docker Setup:** + ```dockerfile + # Development Dockerfile + FROM rust:1.73 as rust-builder + WORKDIR /app + RUN apt-get update && apt-get install -y \ + nodejs \ + npm \ + git + + # Install development tools + RUN rustup component add rustfmt clippy + RUN cargo install cargo-watch + + # Copy project files + COPY . . + + # Install dependencies + RUN cargo build + RUN cd frontend && npm install + + # Development command + CMD ["cargo", "watch", "-x", "run"] + ``` + +2. **Docker Compose Setup:** + ```yaml + # docker-compose.dev.yml + version: '3.8' + services: + sidecar: + build: + context: . + dockerfile: Dockerfile.dev + ports: + - "3001:3001" + volumes: + - .:/app + - cargo-cache:/usr/local/cargo/registry + - target-cache:/app/target + environment: + - RUST_LOG=debug + - OPENAI_API_KEY=${OPENAI_API_KEY} + command: cargo watch -x run + + frontend: + image: node:18 + working_dir: /app/frontend + volumes: + - .:/app + - node-modules:/app/frontend/node_modules + ports: + - "3000:3000" + command: npm run dev + + volumes: + cargo-cache: + target-cache: + node-modules: + ``` + +3. **Development Workflow:** + ```bash + # Start development environment + docker-compose -f docker-compose.dev.yml up -d + + # View logs + docker-compose -f docker-compose.dev.yml logs -f + + # Run tests in container + docker-compose -f docker-compose.dev.yml exec sidecar cargo test + + # Access container shell + docker-compose -f docker-compose.dev.yml exec sidecar bash + ``` + +4. **Benefits:** + - Consistent development environment + - Hot-reloading for both backend and frontend + - Isolated dependencies + - Easy cleanup and reset + - Volume caching for faster builds + +5. **Performance Tips:** + - Use volume caching for cargo and node_modules + - Enable BuildKit for faster builds + - Use multi-stage builds for production + - Configure resource limits appropriately + +## Core Components + +### 1. AI Agent System +- Located in `src/agentic/` +- Handles code analysis and generation +- Uses LLM for intelligent operations + +### 2. Repository Analysis +- Located in `src/repomap/` +- Maps code structure and relationships +- Tracks symbol definitions and usage + +### 3. LLM Integration +- Located in `llm_client/` +- Supports multiple LLM providers +- Handles token management and rate limiting + +### 4. Code Chunking +- Located in `src/chunking/` +- Breaks code into manageable segments +- Language-specific parsing and analysis + +## Development Workflow + +1. **Creating Features:** + - Branch naming: `feature/description` + - Follow Rust/TypeScript best practices + - Add tests for new functionality + +2. **Testing:** + ```bash + # Run Rust tests + cargo test + + # Run specific test + cargo test test_name + + # Run frontend tests + npm test + ``` + +3. **Code Style:** + - Run formatters: + ```bash + cargo fmt + cargo clippy + ``` + - Follow project conventions + +4. **Documentation:** + - Update API docs for endpoint changes + - Add inline documentation + - Update README for major changes + +## Debugging + +1. **Backend:** + ```rust + // Add debug logging + log::debug!("Processing request: {:?}", request); + ``` + +2. **Frontend:** + - Use Chrome DevTools + - React Developer Tools + - Network tab for API calls + +## Common Tasks + +1. **Adding LLM Provider:** + - Implement provider trait in `llm_client/` + - Add configuration in settings + - Update provider factory + +2. **New Language Support:** + - Add parser in `chunking/` + - Implement language-specific analysis + - Update language configuration + +3. **API Endpoints:** + - Add route in `webserver/` + - Implement handler + - Update API documentation + +## Performance Considerations + +1. **Code Analysis:** + - Use incremental processing + - Implement caching where possible + - Profile heavy operations + +2. **Memory Usage:** + - Monitor heap allocations + - Use appropriate data structures + - Implement cleanup for unused resources + +## Error Handling + +1. **Backend:** + ```rust + use thiserror::Error; + + #[derive(Error, Debug)] + pub enum SidecarError { + #[error("Invalid request: {0}")] + InvalidRequest(String), + #[error("LLM error: {0}")] + LLMError(String), + } + ``` + +2. **Frontend:** + - Implement error boundaries + - Add user-friendly error messages + - Log errors for debugging + +## Contributing + +1. **Pull Requests:** + - Reference issue numbers + - Include test coverage + - Update documentation + - Add changelog entry + +2. **Code Review:** + - Review guidelines in CONTRIBUTING.md + - Use PR templates + - Address all comments + +## Resources + +- [Architecture Documentation](./architecture.md) +- [API Documentation](./api-documentation.md) +- [Testing Guide](./testing-guide.md) \ No newline at end of file diff --git a/frontend-building.md b/frontend-building.md new file mode 100644 index 000000000..9818b5643 --- /dev/null +++ b/frontend-building.md @@ -0,0 +1,405 @@ +# Building the Standalone Sidecar Frontend + +This guide provides a complete implementation for building the standalone Sidecar frontend using Next.js and CodeMirror. + +## Project Structure + +``` +standalone-sidecar/ +├── frontend/ +│ ├── components/ +│ │ ├── Editor/ +│ │ ├── Settings/ +│ │ └── Git/ +│ ├── lib/ +│ │ ├── api/ +│ │ ├── git/ +│ │ └── websocket/ +│ ├── pages/ +│ └── styles/ +└── backend/ + └── src/ + ├── main.rs + └── handlers/ +``` + +## Getting Started + +1. Create the Next.js project: +```bash +npx create-next-app@latest frontend --typescript --tailwind +cd frontend +``` + +2. Install dependencies: +```bash +npm install @uiw/react-codemirror @codemirror/lang-javascript @codemirror/theme-one-dark +npm install @codemirror/language @codemirror/state @codemirror/view @codemirror/commands +npm install @codemirror/autocomplete @codemirror/lint @codemirror/search @codemirror/language-data +npm install isomorphic-git @monaco-editor/react zustand axios react-query +``` + +## Core Components Implementation + +### 1. Editor Component + +```typescript +// components/Editor/Editor.tsx +import { useEffect, useState } from 'react'; +import CodeMirror from '@uiw/react-codemirror'; +import { javascript } from '@codemirror/lang-javascript'; +import { oneDark } from '@codemirror/theme-one-dark'; +import { useSettings } from '@/lib/store/settings'; +import { useWebSocket } from '@/lib/hooks/useWebSocket'; + +export function Editor() { + const { settings } = useSettings(); + const ws = useWebSocket(); + const [value, setValue] = useState(''); + const [suggestions, setSuggestions] = useState([]); + + const handleChange = async (val: string) => { + setValue(val); + ws.send({ + type: 'completion_request', + payload: { + code: val, + cursor: getCursorPosition(), + language: 'typescript' + } + }); + }; + + return ( +
+ + {suggestions.length > 0 && ( +
+ {suggestions.map((suggestion, i) => ( +
+ {suggestion.text} +
+ ))} +
+ )} +
+ ); +} +``` + +### 2. Settings Panel + +```typescript +// components/Settings/SettingsPanel.tsx +import { useSettings } from '@/lib/store/settings'; + +export function SettingsPanel() { + const { settings, updateSettings } = useSettings(); + + return ( +
+

Settings

+ +
+

Model Selection

+ +
+ +
+

Editor Preferences

+
+
+ + +
+
+ + updateSettings({ + editorPreferences: { ...settings.editorPreferences, fontSize: parseInt(e.target.value) } + })} + className="w-full p-2 bg-gray-700 rounded" + /> +
+
+
+
+ ); +} +``` + +### 3. Git Integration + +```typescript +// components/Git/GitPanel.tsx +import { useGit } from '@/lib/hooks/useGit'; + +export function GitPanel() { + const { status, addFiles, commit } = useGit(); + + const handleCommit = async (message: string) => { + await commit(message); + }; + + return ( +
+

Git Operations

+ +
+

Status

+
+          {JSON.stringify(status, null, 2)}
+        
+
+ +
+

Commit Changes

+ { + if (e.key === 'Enter') { + handleCommit(e.currentTarget.value); + } + }} + /> +
+
+ ); +} +``` + +## State Management + +```typescript +// lib/store/settings.ts +import create from 'zustand'; + +interface Settings { + activeModel: string; + models: Array<{ + name: string; + provider: string; + contextLength: number; + }>; + editorPreferences: { + theme: string; + fontSize: number; + tabSize: number; + }; +} + +export const useSettings = create<{ + settings: Settings; + updateSettings: (settings: Partial) => void; +}>((set) => ({ + settings: { + activeModel: 'gpt-4', + models: [ + { + name: 'gpt-4', + provider: 'openai', + contextLength: 8192 + }, + { + name: 'claude-2', + provider: 'anthropic', + contextLength: 100000 + } + ], + editorPreferences: { + theme: 'dark', + fontSize: 14, + tabSize: 2 + } + }, + updateSettings: (newSettings) => + set((state) => ({ + settings: { ...state.settings, ...newSettings } + })) +})); +``` + +## API Integration + +```typescript +// lib/api/sidecar.ts +import axios from 'axios'; + +const api = axios.create({ + baseURL: 'http://localhost:3001' +}); + +export const sidecarApi = { + getCompletions: async (code: string, cursor: number) => { + const response = await api.post('/completion', { + code, + cursor, + language: 'typescript' + }); + return response.data; + }, + + updateSettings: async (settings: any) => { + const response = await api.post('/settings', settings); + return response.data; + }, + + getStatus: async () => { + const response = await api.get('/status'); + return response.data; + } +}; +``` + +## WebSocket Communication + +```typescript +// lib/websocket/connection.ts +export class WebSocketConnection { + private ws: WebSocket; + private messageHandlers: Map; + + constructor() { + this.ws = new WebSocket('ws://localhost:3001/ws'); + this.messageHandlers = new Map(); + this.setupHandlers(); + } + + private setupHandlers() { + this.ws.onmessage = (event) => { + const data = JSON.parse(event.data); + const handler = this.messageHandlers.get(data.type); + if (handler) { + handler(data.payload); + } + }; + } + + public send(message: any) { + this.ws.send(JSON.stringify(message)); + } + + public onMessage(type: string, handler: Function) { + this.messageHandlers.set(type, handler); + } +} +``` + +## Main Application Layout + +```typescript +// pages/index.tsx +import { Editor } from '@/components/Editor/Editor'; +import { SettingsPanel } from '@/components/Settings/SettingsPanel'; +import { GitPanel } from '@/components/Git/GitPanel'; + +export default function Home() { + return ( +
+
+ +
+
+ + +
+
+ ); +} +``` + +## Running the Application + +1. Start the Sidecar backend: +```bash +cd backend +cargo run --bin webserver +``` + +2. Start the frontend development server: +```bash +cd frontend +npm run dev +``` + +The application will be available at `http://localhost:3000`. + +## Security Considerations + +1. Implement proper authentication +2. Secure WebSocket connections +3. Validate all user inputs +4. Sanitize code before execution +5. Implement rate limiting + +## Performance Optimization + +1. Implement caching for: + - Code analysis results + - Git operations + - LLM completions +2. Use WebSocket for real-time updates +3. Optimize large file handling +4. Implement proper error boundaries + +## Testing + +1. Unit tests for components +2. Integration tests for API +3. End-to-end testing +4. Performance testing + +## Deployment + +1. Build the frontend: +```bash +npm run build +``` + +2. Build the backend: +```bash +cargo build --release +``` + +3. Deploy using Docker: +```bash +docker-compose up -d +``` + +## Future Improvements + +1. Collaborative editing +2. Multiple file support +3. Advanced git operations +4. Custom theme support +5. Plugin system \ No newline at end of file diff --git a/git-tool.md b/git-tool.md new file mode 100644 index 000000000..cf47f2b44 --- /dev/null +++ b/git-tool.md @@ -0,0 +1,80 @@ +# Git Tool for Sidecar Agent + +This document describes the git tool that enables the agent to perform git operations like adding files and making commits. + +## Tool: git_operation + +The git_operation tool allows the agent to perform git operations on the repository. + +### Parameters + +- operation: (required) The git operation to perform. Valid values: + - "add": Stage files for commit + - "commit": Create a commit with staged changes + - "status": Get repository status + +- paths: (required for "add") Array of file paths to stage +- message: (required for "commit") Commit message that follows conventional commits format +- author_name: (optional) Author name for commit +- author_email: (optional) Author email for commit + +### Usage Examples + +1. Adding files: +```xml + +add + +["src/main.rs", "docs/README.md"] + + +``` + +2. Creating a commit: +```xml + +commit +feat: add new authentication system +Sidecar Agent +agent@sidecar.ai + +``` + +3. Checking status: +```xml + +status + +``` + +### Response Format + +The tool returns a JSON response with: +- success: Boolean indicating operation success +- message: Description of what was done +- error: Error message if operation failed + +Example response: +```json +{ + "success": true, + "message": "Successfully committed 2 files", + "error": null +} +``` + +### Implementation Notes + +1. The tool uses libgit2 for git operations +2. Handles relative and absolute paths +3. Validates commit message format +4. Provides detailed error messages +5. Supports atomic operations + +### Best Practices + +1. Always check repository status before operations +2. Use conventional commits format for messages +3. Group related files in single commits +4. Provide meaningful commit messages +5. Handle errors gracefully \ No newline at end of file diff --git a/git_tool.rs b/git_tool.rs new file mode 100644 index 000000000..cb19d816c --- /dev/null +++ b/git_tool.rs @@ -0,0 +1,177 @@ +use git2::{Repository, Signature}; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +#[derive(Debug, Deserialize)] +pub enum GitOperation { + Add, + Commit, + Status, +} + +#[derive(Debug, Deserialize)] +pub struct GitRequest { + operation: GitOperation, + paths: Option>, + message: Option, + author_name: Option, + author_email: Option, +} + +#[derive(Debug, Serialize)] +pub struct GitResponse { + success: bool, + message: String, + error: Option, +} + +#[derive(Error, Debug)] +pub enum GitToolError { + #[error("Git error: {0}")] + Git(#[from] git2::Error), + #[error("Invalid operation: {0}")] + InvalidOperation(String), + #[error("Missing required field: {0}")] + MissingField(String), +} + +pub struct GitTool { + repo: Repository, +} + +impl GitTool { + pub fn new(repo_path: &str) -> Result { + let repo = Repository::open(repo_path)?; + Ok(Self { repo }) + } + + pub fn execute(&self, request: GitRequest) -> Result { + match request.operation { + GitOperation::Add => self.add_files(request.paths), + GitOperation::Commit => self.create_commit(request), + GitOperation::Status => self.get_status(), + } + } + + fn add_files(&self, paths: Option>) -> Result { + let paths = paths.ok_or_else(|| GitToolError::MissingField("paths".to_string()))?; + + let mut index = self.repo.index()?; + for path in paths { + index.add_path(std::path::Path::new(&path))?; + } + index.write()?; + + Ok(GitResponse { + success: true, + message: format!("Added {} files to staging", paths.len()), + error: None, + }) + } + + fn create_commit(&self, request: GitRequest) -> Result { + let message = request.message + .ok_or_else(|| GitToolError::MissingField("message".to_string()))?; + + let signature = Signature::now( + &request.author_name.unwrap_or_else(|| "Sidecar Agent".to_string()), + &request.author_email.unwrap_or_else(|| "agent@sidecar.ai".to_string()), + )?; + + let mut index = self.repo.index()?; + let tree_id = index.write_tree()?; + let tree = self.repo.find_tree(tree_id)?; + + let parent = if let Ok(head) = self.repo.head() { + Some(head.peel_to_commit()?) + } else { + None + }; + + let parents = parent.as_ref().map(|c| vec![c]).unwrap_or_default(); + + self.repo.commit( + Some("HEAD"), + &signature, + &signature, + &message, + &tree, + parents.as_slice(), + )?; + + Ok(GitResponse { + success: true, + message: "Successfully created commit".to_string(), + error: None, + }) + } + + fn get_status(&self) -> Result { + let statuses = self.repo.statuses(None)?; + + let mut staged = 0; + let mut modified = 0; + let mut untracked = 0; + + for entry in statuses.iter() { + match entry.status() { + s if s.is_index_new() || s.is_index_modified() => staged += 1, + s if s.is_wt_modified() => modified += 1, + s if s.is_wt_new() => untracked += 1, + _ => (), + } + } + + Ok(GitResponse { + success: true, + message: format!( + "Status: {} staged, {} modified, {} untracked", + staged, modified, untracked + ), + error: None, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use tempfile::TempDir; + use std::fs::File; + use std::io::Write; + + #[test] + fn test_git_operations() -> Result<(), GitToolError> { + let temp_dir = TempDir::new().unwrap(); + let repo = Repository::init(temp_dir.path()).unwrap(); + + let git_tool = GitTool::new(temp_dir.path().to_str().unwrap())?; + + // Create test file + let test_file = temp_dir.path().join("test.txt"); + let mut file = File::create(&test_file).unwrap(); + writeln!(file, "test content").unwrap(); + + // Test add + let add_result = git_tool.execute(GitRequest { + operation: GitOperation::Add, + paths: Some(vec!["test.txt".to_string()]), + message: None, + author_name: None, + author_email: None, + })?; + assert!(add_result.success); + + // Test commit + let commit_result = git_tool.execute(GitRequest { + operation: GitOperation::Commit, + paths: None, + message: Some("test: add test file".to_string()), + author_name: Some("Test".to_string()), + author_email: Some("test@example.com".to_string()), + })?; + assert!(commit_result.success); + + Ok(()) + } +} \ No newline at end of file diff --git a/git_tool_integration.md b/git_tool_integration.md new file mode 100644 index 000000000..6ea882f3d --- /dev/null +++ b/git_tool_integration.md @@ -0,0 +1,123 @@ +# Git Tool Integration Guide + +This guide explains how to integrate the git tool into the Sidecar agent's tool system. + +## Integration Steps + +1. Add the git tool to the agent's tool registry: + +```rust +// src/tools/mod.rs +mod git_tool; +use git_tool::GitTool; + +pub struct ToolRegistry { + git_tool: GitTool, + // other tools... +} + +impl ToolRegistry { + pub fn new(repo_path: &str) -> Result { + Ok(Self { + git_tool: GitTool::new(repo_path)?, + // other tools... + }) + } +} +``` + +2. Add tool XML schema: + +```rust +// src/tools/schema.rs +#[derive(Deserialize)] +pub struct GitToolInput { + operation: String, + paths: Option>, + message: Option, + author_name: Option, + author_email: Option, +} +``` + +3. Implement tool handler: + +```rust +// src/tools/handlers.rs +pub async fn handle_git_operation(input: GitToolInput) -> Result { + let request = GitRequest { + operation: match input.operation.as_str() { + "add" => GitOperation::Add, + "commit" => GitOperation::Commit, + "status" => GitOperation::Status, + _ => return Err(Error::InvalidOperation), + }, + paths: input.paths, + message: input.message, + author_name: input.author_name, + author_email: input.author_email, + }; + + let response = TOOL_REGISTRY.git_tool.execute(request)?; + Ok(serde_json::to_string(&response)?) +} +``` + +## Usage in Agent Prompts + +The git tool can be used in agent prompts like this: + +1. Adding files: +```xml + +add + +["src/new_feature.rs", "tests/new_feature_test.rs"] + + +``` + +2. Creating commits: +```xml + +commit +feat: implement new authentication system + +``` + +## Error Handling + +The tool provides detailed error messages that should be handled appropriately: + +```rust +match git_tool.execute(request) { + Ok(response) => { + // Handle successful response + }, + Err(GitToolError::MissingField(field)) => { + // Handle missing required fields + }, + Err(GitToolError::Git(err)) => { + // Handle git operation errors + }, + Err(GitToolError::InvalidOperation(op)) => { + // Handle invalid operation errors + } +} +``` + +## Best Practices + +1. Always validate input parameters before executing git operations +2. Use conventional commits format for commit messages +3. Group related file changes into single commits +4. Handle errors gracefully and provide clear error messages +5. Clean up resources after operations complete + +## Security Considerations + +1. Validate file paths to prevent path traversal +2. Sanitize commit messages and author information +3. Implement proper access controls +4. Log all git operations for audit purposes +5. Handle sensitive data in repositories carefully \ No newline at end of file diff --git a/sidecar-settings.md b/sidecar-settings.md new file mode 100644 index 000000000..ae022412a --- /dev/null +++ b/sidecar-settings.md @@ -0,0 +1,284 @@ +# Sidecar Settings and Model Configuration + +This guide explains how to implement model switching and settings configuration in the standalone Sidecar frontend. + +## Settings Architecture + +The settings system consists of: +- Settings UI components +- State management for settings +- Backend API endpoints for configuration +- Persistent storage + +## Implementation + +1. Create settings types: +```typescript +// types/settings.ts +interface ModelConfig { + name: string; + provider: 'openai' | 'anthropic' | 'local'; + contextLength: number; + temperature: number; +} + +interface SidecarSettings { + activeModel: string; + models: ModelConfig[]; + customPrompts: Record; + editorPreferences: { + theme: string; + fontSize: number; + tabSize: number; + }; +} +``` + +2. Implement settings store: +```typescript +// store/settings.ts +import create from 'zustand'; + +export const useSettings = create<{ + settings: SidecarSettings; + updateSettings: (settings: Partial) => void; +}>((set) => ({ + settings: { + activeModel: 'gpt-4', + models: [ + { + name: 'gpt-4', + provider: 'openai', + contextLength: 8192, + temperature: 0.7 + }, + { + name: 'claude-2', + provider: 'anthropic', + contextLength: 100000, + temperature: 0.7 + } + ], + customPrompts: {}, + editorPreferences: { + theme: 'dark', + fontSize: 14, + tabSize: 2 + } + }, + updateSettings: (newSettings) => + set((state) => ({ + settings: { ...state.settings, ...newSettings } + })) +})); +``` + +3. Create settings UI: +```typescript +// components/SettingsPanel.tsx +export function SettingsPanel() { + const { settings, updateSettings } = useSettings(); + + return ( +
+
+

Model Selection

+ +
+ +
+

Custom Prompts

+ {/* Prompt editor interface */} +
+ +
+

Editor Preferences

+ {/* Editor settings controls */} +
+
+ ); +} +``` + +4. Add backend endpoints: +```rust +// src/settings.rs +#[derive(Serialize, Deserialize)] +struct Settings { + active_model: String, + models: Vec, + custom_prompts: HashMap, + editor_preferences: EditorPreferences, +} + +#[post("/settings")] +async fn update_settings(Json(settings): Json) -> impl IntoResponse { + // Update settings in persistent storage + store_settings(&settings).await?; + + // Reconfigure model clients if needed + reconfigure_model_clients(&settings.active_model).await?; + + Json(settings) +} +``` + +## Persistent Storage + +1. Store settings in local storage: +```typescript +// lib/storage.ts +export function saveSettings(settings: SidecarSettings) { + localStorage.setItem('sidecar-settings', JSON.stringify(settings)); +} + +export function loadSettings(): SidecarSettings { + const saved = localStorage.getItem('sidecar-settings'); + return saved ? JSON.parse(saved) : defaultSettings; +} +``` + +2. Backend storage: +```rust +// src/storage.rs +pub async fn store_settings(settings: &Settings) -> Result<()> { + let path = config_dir().join("settings.json"); + let json = serde_json::to_string_pretty(settings)?; + fs::write(path, json).await?; + Ok(()) +} +``` + +## Model Integration + +1. Model client factory: +```typescript +// lib/models.ts +class ModelClientFactory { + createClient(config: ModelConfig) { + switch (config.provider) { + case 'openai': + return new OpenAIClient(config); + case 'anthropic': + return new AnthropicClient(config); + case 'local': + return new LocalModelClient(config); + } + } +} +``` + +2. Model switching: +```typescript +// lib/completion.ts +export async function getCompletion(prompt: string) { + const { settings } = useSettings.getState(); + const model = settings.models.find(m => m.name === settings.activeModel); + const client = new ModelClientFactory().createClient(model); + return client.complete(prompt); +} +``` + +## Custom Prompts + +1. Prompt template system: +```typescript +// lib/prompts.ts +export class PromptTemplate { + constructor(private template: string) {} + + format(params: Record): string { + return this.template.replace(/\${(\w+)}/g, (_, key) => params[key]); + } +} +``` + +2. Prompt management: +```typescript +// components/PromptEditor.tsx +export function PromptEditor() { + const { settings, updateSettings } = useSettings(); + + const addPrompt = (name: string, template: string) => { + updateSettings({ + customPrompts: { + ...settings.customPrompts, + [name]: template + } + }); + }; + + return ( +
+ {/* Prompt editing interface */} +
+ ); +} +``` + +## Security Considerations + +1. Validate settings before applying: +- Check model configurations +- Sanitize custom prompts +- Validate API keys + +2. Encrypt sensitive data: +- API keys +- Custom prompts with sensitive content +- User preferences + +## Usage Example + +```typescript +// pages/index.tsx +export default function Editor() { + const { settings } = useSettings(); + + const handleCompletion = async () => { + const completion = await getCompletion(prompt); + // Handle completion result + }; + + return ( +
+ + +
+ ); +} +``` + +## Best Practices + +1. **Settings Validation** + - Validate all settings changes + - Provide clear feedback for invalid settings + - Implement settings migration for updates + +2. **Performance** + - Cache model configurations + - Lazy load settings UI + - Debounce settings updates + +3. **User Experience** + - Provide default configurations + - Include preset prompts + - Show model capabilities and limitations + +4. **Error Handling** + - Graceful fallbacks for unavailable models + - Clear error messages + - Automatic recovery strategies \ No newline at end of file diff --git a/standalone-frontend/docker-compose.dev.yml b/standalone-frontend/docker-compose.dev.yml new file mode 100644 index 000000000..a6343b052 --- /dev/null +++ b/standalone-frontend/docker-compose.dev.yml @@ -0,0 +1,34 @@ +version: '3.8' +services: + frontend: + build: + context: ./frontend + dockerfile: Dockerfile.dev + ports: + - "3000:3000" + environment: + - NEXT_PUBLIC_BACKEND_URL=http://backend:3001 + - NEXT_PUBLIC_WS_URL=ws://backend:3001/ws + volumes: + - ./frontend:/app + - /app/node_modules + - /app/.next + depends_on: + - backend + + backend: + build: + context: ../ + dockerfile: sidecar/Dockerfile + ports: + - "3001:3001" + environment: + - RUST_LOG=debug + - RUST_BACKTRACE=1 + volumes: + - ./data:/data + - ../:/app + command: cargo watch -x run + +volumes: + data: \ No newline at end of file diff --git a/standalone-frontend/docker-compose.yml b/standalone-frontend/docker-compose.yml new file mode 100644 index 000000000..e42403b85 --- /dev/null +++ b/standalone-frontend/docker-compose.yml @@ -0,0 +1,27 @@ +version: '3.8' +services: + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + ports: + - "3000:3000" + environment: + - NEXT_PUBLIC_BACKEND_URL=http://backend:3001 + - NEXT_PUBLIC_WS_URL=ws://backend:3001/ws + depends_on: + - backend + + backend: + build: + context: ../ + dockerfile: sidecar/Dockerfile + ports: + - "3001:3001" + environment: + - RUST_LOG=info + volumes: + - ./data:/data + +volumes: + data: \ No newline at end of file diff --git a/standalone-frontend/frontend/Dockerfile b/standalone-frontend/frontend/Dockerfile new file mode 100644 index 000000000..16d04eca9 --- /dev/null +++ b/standalone-frontend/frontend/Dockerfile @@ -0,0 +1,29 @@ +# Build stage +FROM node:18-alpine AS builder +WORKDIR /app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build + +# Production stage +FROM node:18-alpine AS runner +WORKDIR /app + +ENV NODE_ENV production + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +ENV PORT 3000 +ENV HOSTNAME "0.0.0.0" + +CMD ["node", "server.js"] \ No newline at end of file diff --git a/standalone-frontend/frontend/Dockerfile.dev b/standalone-frontend/frontend/Dockerfile.dev new file mode 100644 index 000000000..c262b0b9a --- /dev/null +++ b/standalone-frontend/frontend/Dockerfile.dev @@ -0,0 +1,16 @@ +FROM node:18-alpine + +WORKDIR /app + +# Install dependencies +COPY package*.json ./ +RUN npm install + +# Copy source code +COPY . . + +# Expose development port +EXPOSE 3000 + +# Start development server with hot reloading +CMD ["npm", "run", "dev"] \ No newline at end of file diff --git a/standalone-frontend/frontend/README.md b/standalone-frontend/frontend/README.md new file mode 100644 index 000000000..6bd60fe2e --- /dev/null +++ b/standalone-frontend/frontend/README.md @@ -0,0 +1,77 @@ +# Sidecar Standalone Frontend + +A standalone frontend implementation for Sidecar using Next.js and CodeMirror. + +## Features + +- Code editing with CodeMirror +- AI-powered code completions +- Git integration +- Model switching and configuration +- Real-time updates via WebSocket +- Dark mode support + +## Prerequisites + +- Node.js 18+ +- npm or yarn +- Sidecar backend running on port 3001 + +## Setup + +1. Install dependencies: +```bash +npm install +``` + +2. Create a `.env.local` file: +``` +NEXT_PUBLIC_BACKEND_URL=http://localhost:3001 +NEXT_PUBLIC_WS_URL=ws://localhost:3001/ws +``` + +3. Start the development server: +```bash +npm run dev +``` + +## Project Structure + +``` +frontend/ +├── components/ # React components +│ ├── Editor/ # Code editor components +│ ├── Settings/ # Settings panel +│ └── Git/ # Git integration +├── lib/ # Shared utilities +│ ├── hooks/ # Custom React hooks +│ ├── api/ # API integration +│ ├── git/ # Git operations +│ ├── store/ # State management +│ └── websocket/ # WebSocket connection +├── pages/ # Next.js pages +└── styles/ # Global styles +``` + +## Development + +- Run tests: `npm test` +- Build: `npm run build` +- Lint: `npm run lint` + +## Production + +Build and start the production server: + +```bash +npm run build +npm start +``` + +## Contributing + +1. Fork the repository +2. Create a feature branch +3. Commit your changes +4. Push to the branch +5. Create a Pull Request \ No newline at end of file diff --git a/standalone-frontend/frontend/components/Editor/Editor.tsx b/standalone-frontend/frontend/components/Editor/Editor.tsx new file mode 100644 index 000000000..e32c9400a --- /dev/null +++ b/standalone-frontend/frontend/components/Editor/Editor.tsx @@ -0,0 +1,62 @@ +import { useEffect, useState } from 'react'; +import CodeMirror from '@uiw/react-codemirror'; +import { javascript } from '@codemirror/lang-javascript'; +import { oneDark } from '@codemirror/theme-one-dark'; +import { useSettings } from '../../lib/store/settings'; +import { useWebSocket } from '../../lib/hooks/useWebSocket'; + +export function Editor() { + const { settings } = useSettings(); + const ws = useWebSocket(); + const [value, setValue] = useState(''); + const [suggestions, setSuggestions] = useState([]); + + useEffect(() => { + ws.onMessage('completion_response', (payload) => { + setSuggestions(payload.suggestions); + }); + }, [ws]); + + const handleChange = async (val: string) => { + setValue(val); + ws.send({ + type: 'completion_request', + payload: { + code: val, + cursor: getCursorPosition(), + language: 'typescript' + } + }); + }; + + const getCursorPosition = () => { + // Get cursor position from CodeMirror + return 0; // Placeholder + }; + + return ( +
+ + {suggestions.length > 0 && ( +
+ {suggestions.map((suggestion, i) => ( +
setValue(suggestion.text)} + > + {suggestion.text} +
+ ))} +
+ )} +
+ ); +} \ No newline at end of file diff --git a/standalone-frontend/frontend/components/Git/GitPanel.tsx b/standalone-frontend/frontend/components/Git/GitPanel.tsx new file mode 100644 index 000000000..281996a2f --- /dev/null +++ b/standalone-frontend/frontend/components/Git/GitPanel.tsx @@ -0,0 +1,114 @@ +import { useState, useEffect } from 'react'; +import { useGit } from '../../lib/hooks/useGit'; + +export function GitPanel() { + const { status, loading, error, fetchStatus, addFiles, commit } = useGit(); + const [commitMessage, setCommitMessage] = useState(''); + + useEffect(() => { + fetchStatus(); + // Poll for status updates + const interval = setInterval(fetchStatus, 5000); + return () => clearInterval(interval); + }, [fetchStatus]); + + const handleCommit = async () => { + if (!commitMessage) return; + await commit(commitMessage); + setCommitMessage(''); + }; + + const handleAddFiles = async (files: string[]) => { + await addFiles(files); + }; + + return ( +
+

Git Operations

+ + {error && ( +
+ {error} +
+ )} + +
+

Repository Status

+ {loading ? ( +
Loading...
+ ) : ( +
+ {status.staged.length > 0 && ( +
+

Staged Files:

+
    + {status.staged.map(file => ( +
  • {file}
  • + ))} +
+
+ )} + + {status.modified.length > 0 && ( +
+

Modified Files:

+
    + {status.modified.map(file => ( +
  • handleAddFiles([file])} + > + {file} +
  • + ))} +
+
+ )} + + {status.untracked.length > 0 && ( +
+

Untracked Files:

+
    + {status.untracked.map(file => ( +
  • handleAddFiles([file])} + > + {file} +
  • + ))} +
+
+ )} +
+ )} +
+ +
+

Create Commit

+
+