***Project Code and Documentation***

<workbench-ui/app.py>
```
from fasthtml.common import *
import time
import sys
import os
import asyncio
sys.path.append(os.path.abspath('../multi-engineer-V2'))
from starlette.responses import HTMLResponse

# Add HighlightJS for syntax highlighting
hdrs = (HighlightJS(langs=['python', 'javascript', 'html', 'css']),)

app, rt = fast_app(pico=False, hdrs=hdrs)

def is_code_file(filename):
    code_extensions = ['.py', '.js', '.html', '.css', '.java', '.cpp', '.c', '.go', '.rs', '.ts']
    return any(filename.endswith(ext) for ext in code_extensions)

@rt("/")
def get():
    return Titled("Workbench",
        Link(rel="stylesheet", href="/static/style.css"),
        Script(src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/prism.min.js"),
        Link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/themes/prism-tomorrow.min.css"),
        Script(src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"),
        Link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/default.min.css"),
        Script("hljs.highlightAll();"),
        Script(src="/static/script.js"),
        Div(
            Button("Open Project", id="open-project-btn"),
            Div(
                Input(type="checkbox", id="dark-mode-toggle", name="dark-mode-toggle"),
                Label("Light Mode", for_="dark-mode-toggle"),
                cls="mode-toggle"
            ),
            cls="top-nav"
        ),
        Grid(
            Div(
                H2("File Browser"),
                Div(id="file-browser", cls="file-browser"),
                H2("Conversation History"),
                Div(id="conversation-history", cls="scrollable"),
                H2("Code Output"),
                Div(
                    Pre(Code(id="code-output", cls="language-python")),
                    Button("Copy Code", id="copy-code-btn"),
                    cls="code-container"
                ),
                cls="left-column"
            ),
            Div(
                H2("Prompt Management"),
                Select(
                    Option("Default Model", value="default"),
                    Option("Code Specialist", value="code"),
                    Option("Explanation Expert", value="explanation"),
                    id="model-preset"
                ),
                Form(
                    Label("Enter your prompt:", for_="prompt-input"),
                    Textarea(id="prompt-input", name="prompt", placeholder="Enter your prompt here..."),
                    Div(id="char-counter", cls="char-counter"),
                    Div(
                        Button("Preview", id="preview-prompt-btn", type="button"),
                        Button("Submit", type="submit"),
                        Button("Streaming", id="streaming-btn", type="button"),
                        cls="button-group"
                    ),
                    id="prompt-form", hx_post="/submit", hx_target="#conversation-history", hx_swap="beforeend"
                ),
                cls="right-column"
            ),
            cls="main-grid"
        )
    )

@rt("/browse", methods=["POST"])
def browse_files(path: str = "."):
    try:
        abs_path = os.path.abspath(path)
        parent_path = os.path.dirname(abs_path)
        items = os.listdir(abs_path)
        
        directories = [item for item in items if os.path.isdir(os.path.join(abs_path, item))]
        code_files = [item for item in items if os.path.isfile(os.path.join(abs_path, item)) and is_code_file(item)]
        
        file_list = Ul(
            Li(A("📂 ..", href=f"javascript:browseDirectory('{parent_path.replace(os.sep, '/')}')", cls="file-browser-link parent-dir")),
            *[Li(A(f"📁 {directory}", href=f"javascript:browseDirectory('{os.path.join(path, directory).replace(os.sep, '/')}')", cls="file-browser-link directory")
               ) for directory in directories],
            *[Li(A(f"📄 {file}", href=f"javascript:viewFile('{os.path.join(path, file).replace(os.sep, '/')}')", cls="file-browser-link file")
               ) for file in code_files],
            cls="file-list"
        )
        
        return Div(
            P(f"Current path: {abs_path}", cls="current-path"),
            file_list,
            id="file-browser"
        )
    except Exception as e:
        return Div(f"Error browsing files: {str(e)}", id="file-browser", cls="error-message")

@rt("/submit", methods=["POST"])
def post(prompt: str):
    timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
    user_message = Div(f"[{timestamp}] User: {prompt}", cls="user-message")
    # Simulate a delay for response generation
    time.sleep(1)
    response = f"Received prompt: {prompt}"
    system_message = Div(f"[{timestamp}] System: {response}", cls="system-message")
    return user_message + system_message

@rt("/preview", methods=["POST"])
def preview(prompt: str):
    # Simple tokenization
    tokens = prompt.split()
    preview_info = f"Tokenized preview:\n{' | '.join(tokens)}\nToken count: {len(tokens)}"
    return Div(Pre(Code(preview_info, cls="language-plaintext")), cls="preview-info")

@rt("/stream")
async def stream(prompt: str):
    async def event_stream():
        timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
        yield f"data: {Div(f'[{timestamp}] User: {prompt}', cls='user-message')}\n\n"
        for i in range(5):  # Simulate streaming response
            await asyncio.sleep(1)
            yield f"data: {Div(f'Streaming response part {i+1}', cls='system-message')}\n\n"
    return EventStream(event_stream())

@rt("/view_file", methods=["POST"])
def view_file(file_path: str):
    try:
        with open(file_path, 'r') as file:
            content = file.read()
        # Remove the first line if it contains the filename
        lines = content.splitlines()
        if lines and lines[0].strip() == os.path.basename(file_path):
            content = '\n'.join(lines[1:])
        language = detect_language(file_path)
        html_content = f"<pre><code class='language-{language}'>{content}</code></pre>"
        return HTMLResponse(content=html_content)
    except Exception as e:
        return HTMLResponse(content=f"<div class='error-message'>Error reading file: {str(e)}</div>")

def detect_language(file_path):
    extension = os.path.splitext(file_path)[1].lower()
    language_map = {
        '.py': 'python',
        '.js': 'javascript',
        '.html': 'html',
        '.css': 'css',
        '.java': 'java',
        '.cpp': 'cpp',
        '.c': 'c',
        '.go': 'go',
        '.rs': 'rust',
        '.ts': 'typescript'
    }
    return language_map.get(extension, 'plaintext')

if __name__ == "__main__":
    serve()
```
<workbench-ui/static/script.js>
```
document.addEventListener('DOMContentLoaded', function() {
    const modeToggle = document.getElementById('dark-mode-toggle');
    const body = document.body;
    const promptInput = document.getElementById('prompt-input');
    const charCounter = document.getElementById('char-counter');
    const copyCodeBtn = document.getElementById('copy-code-btn');
    const openProjectBtn = document.getElementById('open-project-btn');
    const streamingBtn = document.getElementById('streaming-btn');
    const previewPromptBtn = document.getElementById('preview-prompt-btn');
    
    // Light/Dark mode toggle
    if (localStorage.getItem('lightMode') === 'enabled') {
        body.classList.add('light-mode');
        modeToggle.checked = true;
    }

    modeToggle.addEventListener('change', function() {
        if (this.checked) {
            body.classList.add('light-mode');
            localStorage.setItem('lightMode', 'enabled');
        } else {
            body.classList.remove('light-mode');
            localStorage.setItem('lightMode', 'disabled');
        }
    });

    // Character counter
    promptInput.addEventListener('input', function() {
        charCounter.textContent = `${this.value.length} / 500`;
    });

    // Copy code button
    copyCodeBtn.addEventListener('click', function() {
        const codeOutput = document.getElementById('code-output');
        const textArea = document.createElement('textarea');
        textArea.value = codeOutput.textContent;
        document.body.appendChild(textArea);
        textArea.select();
        try {
            document.execCommand('copy');
            copyCodeBtn.textContent = 'Copied!';
        } catch (err) {
            console.error('Failed to copy: ', err);
            copyCodeBtn.textContent = 'Copy failed';
        }
        document.body.removeChild(textArea);
        setTimeout(() => {
            copyCodeBtn.textContent = 'Copy Code';
        }, 2000);
    });

    // Open Project button
    openProjectBtn.addEventListener('click', function() {
        const path = prompt("Enter the path to your project:", currentPath);
        if (path) {
            browseDirectory(path);
        }
    });

    // Streaming button
    streamingBtn.addEventListener('click', function() {
        const prompt = promptInput.value;
        const eventSource = new EventSource(`/stream?prompt=${encodeURIComponent(prompt)}`);
        eventSource.onmessage = function(event) {
            document.getElementById('conversation-history').innerHTML += event.data;
        };
        eventSource.onerror = function() {
            eventSource.close();
        };
    });

    // Preview button
    previewPromptBtn.addEventListener('click', function() {
        const prompt = promptInput.value;
        fetch('/preview', {
            method: 'POST',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            body: `prompt=${encodeURIComponent(prompt)}`
        })
        .then(response => response.text())
        .then(html => {
            document.getElementById('code-output').innerHTML = html;
            Prism.highlightAll();
        });
    });

    // Clear the form after submission
    document.body.addEventListener('htmx:afterOnLoad', function(event) {
        if (event.detail.elt.id === 'prompt-form') {
            event.detail.elt.reset();
            charCounter.textContent = '0 / 500';
        }
    });

    // Initial file browse on page load
    browseDirectory('.');
});

function browseDirectory(path) {
    fetch('/browse', {
        method: 'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        body: `path=${encodeURIComponent(path)}`
    })
    .then(response => response.text())
    .then(html => {
        document.getElementById('file-browser').innerHTML = html;
    });
}

function viewFile(filePath) {
    fetch('/view_file', {
        method: 'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        body: `file_path=${encodeURIComponent(filePath)}`
    })
    .then(response => response.text())
    .then(html => {
        document.getElementById('code-output').innerHTML = html;
        Prism.highlightAll(); // Re-apply syntax highlighting
    });
}
```
workbench-ui/static/style.css
```
:root {
    --bg-color: #1e1e1e;
    --text-color: #d4d4d4;
    --primary-color: #0078d4;
    --secondary-bg: #252526;
    --border-color: #3c3c3c;
    --directory-color: #ffd700;
    --file-color: #90ee90;
    --parent-dir-color: #ff9900;
}

body {
    background-color: var(--bg-color);
    color: var(--text-color);
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    margin: 0;
    padding: 20px;
    transition: background-color 0.3s, color 0.3s;
}

body.light-mode {
    --bg-color: #ffffff;
    --text-color: #000000;
    --secondary-bg: #f0f0f0;
    --border-color: #cccccc;
    --directory-color: #8b4513;
    --file-color: #2e8b57;
    --parent-dir-color: #ff6600;
}

.top-nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px;
    background-color: var(--secondary-bg);
    margin-bottom: 20px;
}

.mode-toggle {
    display: flex;
    align-items: center;
}

.mode-toggle input {
    margin-right: 5px;
}

.main-grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 20px;
}

.left-column, .right-column {
    background-color: var(--secondary-bg);
    padding: 20px;
    border-radius: 5px;
}

.file-browser-container, .conversation-container, .code-container {
    margin-bottom: 20px;
}

.file-browser {
    max-height: 200px;
    overflow-y: auto;
    margin-bottom: 20px;
    border: 1px solid var(--border-color);
    border-radius: 5px;
    padding: 10px;
}

#file-browser .file-list {
    list-style-type: none;
    padding: 0;
}

#file-browser .file-list li {
    margin-bottom: 5px;
}

#file-browser .file-list a.file-browser-link {
    color: var(--text-color) !important;
    text-decoration: none;
    display: block;
    padding: 5px;
    border-radius: 3px;
    transition: background-color 0.2s, color 0.2s;
}

#file-browser .file-list a.file-browser-link:hover {
    background-color: var(--primary-color);
    color: white !important;
}

#file-browser .file-list a.file-browser-link.parent-dir {
    color: var(--parent-dir-color) !important;
    font-weight: bold;
}

#file-browser .file-list a.file-browser-link.directory {
    color: var(--directory-color) !important;
}

#file-browser .file-list a.file-browser-link.file {
    color: var(--file-color) !important;
}

.scrollable {
    max-height: 300px;
    overflow-y: auto;
}

#prompt-form {
    display: flex;
    flex-direction: column;
}

#prompt-input {
    margin-bottom: 10px;
    background-color: var(--bg-color);
    color: var(--text-color);
    border: 1px solid var(--border-color);
    padding: 10px;
    border-radius: 5px;
    resize: vertical;
    min-height: 100px;
}

.button-group {
    display: flex;
    justify-content: space-between;
}

button {
    background-color: var(--primary-color);
    color: white;
    border: none;
    padding: 10px;
    cursor: pointer;
    border-radius: 5px;
    transition: background-color 0.3s;
}

button:hover {
    background-color: #005a9e;
}

.user-message, .system-message {
    margin-bottom: 10px;
    padding: 10px;
    border-radius: 5px;
}

.user-message {
    background-color: var(--primary-color);
    color: white;
}

.system-message {
    background-color: var(--secondary-bg);
}

#model-preset {
    width: 100%;
    margin-bottom: 10px;
    padding: 5px;
    background-color: var(--bg-color);
    color: var(--text-color);
    border: 1px solid var(--border-color);
    border-radius: 5px;
}

.char-counter {
    text-align: right;
    font-size: 0.8em;
    margin-bottom: 5px;
}

.current-path {
    margin-bottom: 10px;
    font-weight: bold;
}

.preview-info {
    background-color: var(--secondary-bg);
    padding: 10px;
    border-radius: 5px;
    margin-top: 10px;
}

.file-content {
    background-color: var(--secondary-bg);
    padding: 10px;
    border-radius: 5px;
    margin-top: 10px;
}

.file-content h3 {
    margin-top: 0;
    margin-bottom: 10px;
}

.error-message {
    color: #ff6b6b;
    background-color: #2f2f2f;
    padding: 10px;
    border-radius: 5px;
    margin-top: 10px;
}
```
<sep>
High-Level Project Overview:
High-Level Project Overview
This project aims to create a dynamic and user-friendly web-based interface (Workbench) for your AI-powered coding assistant, currently implemented as a CLI tool. The web UI will leverage the FastHTML library to provide an intuitive and responsive experience.
Core Goals:
1. Seamless CLI Integration: Adapt the existing CLI tool's functionality for web use, allowing users to interact with the assistant through a browser-based interface.
2. Enhanced User Experience: Improve upon the CLI experience by providing real-time updates, streaming responses, interactive UI elements, and enhanced visualizations.
3. Advanced Features: Implement features like project management, variable embedding, and any other capabilities specific to your CLI tool.
Technical Approach:
* The web UI will be built using FastHTML, a Python-centric library for creating server-rendered hypermedia applications.
* FastHTML's FT components will be used for declarative HTML generation, allowing for a clean and efficient development process.
* HTMX will be used to enhance interactivity, enabling dynamic content updates without requiring extensive custom JavaScript.
* WebSockets will be implemented to provide real-time feedback and streaming responses from the CLI tool.
* Existing CLI functions will be modularized and adapted for use in FastHTML routes, creating a seamless integration between the backend and the UI.
Target Audience:
The Workbench UI is designed for developers who want to leverage the power of your AI coding assistant in a more intuitive and user-friendly environment.
Expected Benefits:
* Improved user experience and productivity through a dynamic and interactive interface.
* Enhanced accessibility to the AI coding assistant through a web-based platform.
* Increased efficiency in code generation, editing, and collaboration.
This project will transform your existing CLI tool into a more powerful and versatile web-based application, empowering developers to take their coding to the next level.

<sep>
FastHTML Cheat Sheet (Updated):
1. Use FastHTML components (e.g., Div, Button, Input) instead of string literals for HTML elements.
2. Properly nest components to ensure correct rendering.
3. Use cls for CSS classes, not class. (class is a reserved keyword in Python)
4. For HTML's class attribute, you can also use klass if cls doesn't work in certain contexts.
5. For event handlers, use FastHTML's built-in attributes like hx_post, hx_target, etc.
6. When in doubt, break complex UI elements into smaller, manageable components.
7. Always test rendered output to ensure proper structure and functionality.
8. Use the children parameter for nested elements rather than string interpolation.
9. Leverage FastHTML's integration with HTMX for dynamic content updates.
10. Use fast_app() to initialize your application with sensible defaults.
11. Utilize Titled() for pages that need both a meta title and an H1 element.
12. For forms, use the fill_form() function to populate form fields with data.
13. Implement WebSockets using the ws_hdr=True parameter in fast_app().
14. Use EventStream for server-sent events (SSE) to implement real-time updates.
15. Leverage Beforeware for tasks like authentication that need to run before route handlers.
16. Use fastlite for simple database operations with SQLite.
17. Use NotStr() when you need to include raw HTML content without escaping.
18. Leverage HTMLResponse from Starlette for fine-grained control over HTTP responses.
19. Remember that FastHTML automatically escapes string content for security; use NotStr() judiciously.
20. When working with file paths, use os.path.join() and replace backslashes with forward slashes for JavaScript compatibility.
21. Utilize the Grid component for creating responsive layouts easily.
22. Remember to call Prism.highlightAll() after dynamically inserting code content for syntax highlighting.
23. Use the hx_swap attribute to control how HTMX updates the DOM (e.g., "innerHTML", "outerHTML", "beforeend").
24. Leverage FastHTML's automatic form handling capabilities, but be prepared to implement custom logic when needed.
25. When using WebSockets, remember to set ws_hdr=True in fast_app() initialization.
26. Use async/await syntax in route handlers for non-blocking operations, especially for file I/O or external API calls.
Additional comments based on our experience:
* FastHTML's integration with HTMX provides a powerful way to create dynamic interfaces with minimal JavaScript.
* The framework's Python-centric approach allows for rapid development, but requires careful attention to component nesting and attribute naming.
* While FastHTML simplifies many aspects of web development, complex UI interactions may still require custom JavaScript.
* The ability to mix Python logic directly within the UI components is powerful but should be used judiciously to maintain clean separation of concerns.
* FastHTML's error messages can sometimes be cryptic; thorough testing and gradual component building can help isolate issues.
* The framework's flexibility in accepting both string literals and component objects can lead to confusion; consistently using component objects can help maintain code clarity.

<sep>
```
FastHTML Reference Tags (Comprehensive List):
* "A Minimal Application"
* "CSS Files and Inline Styles"
* "Defining new ft components"
* "Forms"
* "HTTP Methods"
* "Code highlighting"
* "Websockets application"
* "Strings and conversion order"
* "Sessions"
* "Authentication and authorization"
* "Testing views in notebooks"
* "Surreal"
* "Other Static Media File Locations"
* "Server-Sent Events (SSE)"
```

<sep>
FastHTML Documentation:
```
# Comprehensive Guide to FastHTML for Implementing Workbench UI

## Quick Start
1. FastHTML: Python library for server-rendered hypermedia applications
2. Key components: FT (FastTags), HTMX, WebSockets, SSE
3. Basic structure: `from fasthtml.common import *; app, rt = fast_app()`
4. Routing: Use `@rt("/path")` decorator
5. HTML generation: Use FT components (e.g., `Div`, `P`, `Input`)
6. CLI integration: Adapt CLI functions for web use
7. State management: Utilize FastHTML sessions
8. Real-time updates: Implement WebSockets and SSE

## Table of Contents
1. Overview of FastHTML
2. Getting Started with FastHTML
3. Routing and View Functions
4. FT Components and HTML Rendering
5. Best Practices for Using FT Components
6. Custom Components and Reusability
7. Forms and Data Handling
8. Handling HTTP Methods
9. State Management and Sessions
10. Adapting CLI Functions for Web Use
11. Integrating with Your CLI Tool
12. Enhanced UI Element Adaptation
13. Project-Specific Considerations
14. WebSockets Integration
15. Server-Sent Events (SSE)
16. Syntax Highlighting and Markdown Rendering
17. Error Handling and User Notifications (Toasts)
18. Authentication and Authorization
19. Testing and Debugging
20. Additional Utilities: Surreal and HTMX
21. Best Practices and Tips
22. Conclusion

## 1. Overview of FastHTML

FastHTML is a powerful Python library that combines **Starlette**, **Uvicorn**, **HTMX**, and **Fastcore's FT** ("FastTags") to create sophisticated server-rendered hypermedia applications. It's designed to streamline the development of dynamic web interfaces with a Python-centric approach.

**Key Features:**
- **Declarative HTML generation** using Python functions and classes
- **Decorator-based routing** with enhanced functionality
- **Seamless integration** with CSS frameworks and JavaScript libraries
- **Support for asynchronous operations** and real-time communication
- **Comprehensive utilities** for forms, state management, WebSockets, and Server-Sent Events (SSE)

**Why FastHTML for Workbench UI:**
FastHTML's architecture aligns perfectly with our goal of creating a dynamic, responsive interface for our AI-powered coding assistant. Its Python-centric approach allows for seamless integration with our existing CLI tool, while its support for real-time updates via WebSockets and SSE enables us to create a truly interactive experience.

## 2. Getting Started with FastHTML

### Installation
```bash
pip install python-fasthtml
```

### A Minimal Application
```python
from fasthtml.common import *

app, rt = fast_app()

@rt("/")
def get():
    return Titled("Workbench", P("AI-powered coding assistant"))

serve()
```

**Explanation:**
- `from fasthtml.common import *`: Imports a curated set of FastHTML functions and objects.
- `app, rt = fast_app()`: Initializes the FastHTML application with sensible defaults.
- `@rt("/")`: Defines a route for the root URL (/).
- `def get():`: Handles HTTP GET requests for the defined route.
- `return Titled(...)`: Returns an HTML structure with a meta <title> and an <h1> element.
- `serve()`: Runs the application using Uvicorn.

**Common Pitfall:** Forgetting to call `serve()` at the end of your script will result in the application not running.

## 3. Routing and View Functions

### Defining Routes
Use the `@rt` decorator to define routes. The route path can include dynamic segments.

```python
@rt("/profile/{email}")
def get(email: str):
    # Handle the request using the 'email' parameter
    return Titled(f"Profile: {email}", P(f"Viewing profile for {email}"))
```

### Handling Different HTTP Methods
FastHTML maps function names to HTTP methods:

```python
@rt("/resource")
def get():
    # Handle GET requests
    return Titled("Resource", P("Viewing resource"))

@rt("/resource")
def post():
    # Handle POST requests
    return Titled("Resource Created", P("Resource has been created"))
```

**Best Practice:** Use type hints for route parameters to enable automatic type conversion and validation.

## 4. FT Components and HTML Rendering

### Understanding FT Components
FT Components are Python functions or classes that generate HTML elements. They allow you to build UIs declaratively in Python, avoiding string concatenation.

```python
def hero(title, statement):
    return Div(
        H1(title),
        P(statement),
        cls="hero"
    )

# Usage
Main(
    hero("Welcome to Workbench", "Your AI-powered coding assistant")
)
```

### Rendering and Nesting Components
Properly nest components to ensure correct HTML structure. Use the `children` parameter for nested elements rather than string interpolation.

```python
Div(
    P("This is a paragraph inside a div."),
    Span("This is a span inside the same div."),
    cls="container"
)
```

### Important Attributes
- Use `cls` for CSS classes (since `class` is a reserved keyword in Python).
- Alternatively, use `klass` if `cls` doesn't fit the context.

**Common Pitfall:** Using `class` instead of `cls` will result in a Python syntax error.

## 5. Best Practices for Using FT Components

1. **Avoid String Literals for HTML Elements:**
   Use FT components instead of string literals for better structure and readability.

   ```python
   # Good
   Div(P("Hello, World!"), cls="greeting")
   
   # Avoid
   "<div class='greeting'><p>Hello, World!</p></div>"
   ```

2. **Proper Nesting:**
   Ensure components are properly nested to reflect the desired HTML hierarchy.

3. **Attribute Naming:**
   Use `cls` for CSS classes; `class` is reserved in Python.

4. **Event Handlers:**
   Use FastHTML's built-in attributes like `hx_post`, `hx_target`, etc., for event handling.

   ```python
   Button("Submit", hx_post="/submit", hx_target="#result")
   ```

5. **Breaking Down Complexity:**
   Break complex UI elements into smaller, manageable components or functions.

6. **Consistent Use of Components:**
   Consistently use component objects rather than mixing with string literals to maintain code clarity.

7. **Testing Rendered Output:**
   Regularly test the rendered HTML output to ensure correctness.

8. **Leverage HTMX Integration:**
   Use FastHTML's integration with HTMX for dynamic content updates.

9. **Utilize children Parameter:**
   For nested elements, pass them as arguments rather than using string interpolation.

10. **Initialize with fast_app():**
    Use `fast_app()` to initialize your application with sensible defaults.

**Best Practice:** Create reusable components for common UI elements in your Workbench interface, such as code editors, file browsers, and conversation displays.

## 6. Custom Components and Reusability

### Using Functions for Components
Define reusable UI elements as functions that return FT components.

```python
def code_block(language, content):
    return Div(
        Pre(Code(content, cls=f"language-{language}")),
        cls="code-block"
    )

# Usage
Main(
    code_block("python", "print('Hello, Workbench!')")
)
```

### Using Dataclasses
For more complex components, define them as dataclasses with an `__ft__` method.

```python
from dataclasses import dataclass

@dataclass
class ConversationMessage:
    sender: str
    content: str
    timestamp: str

    def __ft__(self):
        return Div(
            P(f"{self.sender} ({self.timestamp}):"),
            P(self.content),
            cls=f"message {self.sender.lower()}-message"
        )

# Usage
conversation = Div(
    ConversationMessage("User", "How do I implement a binary search?", "14:30"),
    ConversationMessage("Assistant", "Here's an example implementation...", "14:31"),
    cls="conversation-history"
)
```

**Best Practice:** Create custom components for recurring elements in your Workbench UI, such as file tree nodes, code suggestion blocks, or conversation bubbles.

## 7. Forms and Data Handling

### Defining Data Classes for Validation
Use dataclasses to represent the data structure and for validation.

```python
from dataclasses import dataclass

@dataclass
class CodePrompt:
    language: str
    prompt: str
    context: str = ""
```

### Creating Forms with FT Components
Build forms using FT components, ensuring each input corresponds to a field in your dataclass.

```python
code_prompt_form = Form(method="post", action="/generate")(
    Fieldset(
        Label("Language", Select(name="language")(
            Option("Python"),
            Option("JavaScript"),
            Option("Rust")
        )),
        Label("Prompt", Textarea(name="prompt")),
        Label("Context", Textarea(name="context")),
    ),
    Button("Generate Code", type="submit")
)
```

### Populating Forms with Data
Use `fill_form()` to populate form fields with existing data.

```python
existing_prompt = CodePrompt(language="Python", prompt="Implement quicksort")
filled_form = fill_form(code_prompt_form, existing_prompt)
```

### Handling Form Submission
Define view functions that receive form data and validate it using the dataclass.

```python
@rt("/generate")
def post(prompt: CodePrompt):
    # Process the code generation request
    generated_code = generate_code(prompt)
    return Titled("Generated Code", code_block(prompt.language, generated_code))
```

**Common Pitfall:** Forgetting to handle form validation can lead to unexpected behavior or security vulnerabilities. Always validate and sanitize user input.

## 8. Handling HTTP Methods

FastHTML allows you to handle different HTTP methods by naming your view functions accordingly. This is particularly useful for RESTful API design and CRUD operations in your Workbench UI.

```python
@rt("/code/{id}")
def get(id: int):
    # Retrieve code snippet
    code = get_code_snippet(id)
    return Titled(f"Code Snippet {id}", code_block(code.language, code.content))

@rt("/code")
def post(snippet: CodeSnippet):
    # Create new code snippet
    new_id = save_code_snippet(snippet)
    return RedirectResponse(f"/code/{new_id}", status_code=303)

@rt("/code/{id}")
def put(id: int, snippet: CodeSnippet):
    # Update existing code snippet
    update_code_snippet(id, snippet)
    return RedirectResponse(f"/code/{id}", status_code=303)

@rt("/code/{id}")
def delete(id: int):
    # Delete code snippet
    delete_code_snippet(id)
    return RedirectResponse("/code", status_code=303)
```

**Best Practice:** Use appropriate HTTP methods for different operations to maintain RESTful principles in your API design.

## 9. State Management and Sessions

FastHTML sessions are Python dictionaries stored per user session. They're crucial for maintaining state across requests in your Workbench UI.

### Accessing Sessions

```python
@rt("/workspace")
def get(session):
    session['last_visited'] = time.time()
    current_project = session.get('current_project', 'No project selected')
    return Titled("Workspace", P(f"Current project: {current_project}"))
```

### Tips for Effective Session Management:
1. Include `session` in your view function's parameters to use sessions.
2. Use sessions to store user-specific data like conversation history, current model, and file context.
3. Implement session cleanup mechanisms to prevent memory leaks.
4. Be cautious about storing large amounts of data in sessions.

**Example: Managing Conversation History**

```python
@rt("/chat")
def post(user_input: str, session):
    history = session.get('conversation_history', [])
    history.append(("User", user_input))
    
    # Generate response using your CLI tool
    response = generate_response(user_input, history)
    
    history.append(("Assistant", response))
    session['conversation_history'] = history[-10:]  # Keep last 10 messages
    
    return Div(*[P(f"{sender}: {message}") for sender, message in history])
```

**Common Pitfall:** Overusing sessions for data that should be stored in a database can lead to performance issues and data inconsistencies.

## 10. Adapting CLI Functions for Web Use

This section is crucial for integrating your existing CLI tool with the Workbench UI. We'll break down the main CLI functions into smaller, web-friendly components.

### Modularization of CLI Functions

Create a new file, `cli_integration.py`, to house the adapted CLI functions:

```python
# cli_integration.py
import asyncio
from your_cli_tool import generate_code, switch_model, manage_context

async def web_generate_code(prompt, language, context):
    # Adapt your CLI's generate_code function for web use
    return await asyncio.to_thread(generate_code, prompt, language, context)

async def web_switch_model(new_model):
    # Adapt your CLI's model switching function
    return await asyncio.to_thread(switch_model, new_model)

async def web_manage_context(action, file_paths):
    # Adapt your CLI's context management function
    return await asyncio.to_thread(manage_context, action, file_paths)
```

### Integrating with FastHTML Routes

Now, use these adapted functions in your FastHTML routes:

```python
# app.py
from fasthtml.common import *
from cli_integration import web_generate_code, web_switch_model, web_manage_context

app, rt = fast_app()

@rt("/generate")
async def post(prompt: str, language: str, context: str, session):
    code = await web_generate_code(prompt, language, context)
    session['last_generated_code'] = code
    return Div(code_block(language, code))

@rt("/switch_model")
async def post(new_model: str, session):
    result = await web_switch_model(new_model)
    session['current_model'] = new_model
    return P(f"Switched to model: {new_model}")

@rt("/update_context")
async def post(action: str, file_paths: list[str], session):
    context = await web_manage_context(action, file_paths)
    session['current_context'] = context
    return P("Context updated successfully")
```

**Best Practice:** Use asyncio to prevent blocking operations from your CLI tool from freezing the web interface.

## 11. Integrating with Your CLI Tool

### Web-Friendly Responses and Rich Output Conversion

Your CLI tool likely uses rich console output. We need to convert this to web-friendly HTML.

```python
from rich.console import Console
from rich.markdown import Markdown

def rich_to_html(rich_content):
    console = Console(record=True, width=100)
    console.print(rich_content)
    html = console.export_html()
    return NotStr(html)  # Use NotStr to prevent escaping

@rt("/rich_output")
async def get(session):
    cli_output = await generate_cli_output()  # Your CLI function
    markdown = Markdown(cli_output)
    return Div(rich_to_html(markdown), cls="cli-output")
```

### Asynchronous Operations and Streaming Responses

Implement WebSockets for real-time updates, such as streaming code generation:

```python
@app.ws('/code_stream')
async def code_stream_ws(websocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        async for chunk in stream_code_generation(data):
            await websocket.send_text(chunk)
```

Client-side JavaScript:

```javascript
const ws = new WebSocket('ws://localhost:8000/code_stream');
ws.onmessage = function(event) {
    document.getElementById('code-output').innerHTML += event.data;
};
```

### Error Handling Specificity

Implement specific error handling for CLI interactions:

```python
@rt('/generate')
async def post(prompt: str, session):
    try:
        response = await web_generate_code(prompt, session.get('current_model'))
        return Div(code_block("python", response))
    except ConnectionError as ce:
        add_toast(session, f"Connection error: {ce}", "error")
        return RedirectResponse('/')
    except ValueError as ve:
        add_toast(session, f"Invalid input: {ve}", "warning")
        return RedirectResponse('/')
    except Exception as e:
        add_toast(session, f"An unexpected error occurred: {e}", "error")
        return RedirectResponse('/')
```

**Best Practice:** Provide clear, actionable error messages to users while logging detailed error information for debugging.

## 12. Enhanced UI Element Adaptation

### Transforming Console UI to Web UI

#### Example: Model Switching

Console Interaction:
```python
print("Available models:")
print("1. GPT-3")
print("2. GPT-4")
choice = input("Select a model: ")
```

Web UI Adaptation:
```python
def model_selection(models, current_model):
    return Form(
        Select(
            *[Option(model, value=model) for model in models],
            name="model",
            value=current_model,
            hx_post="/switch_model",
            hx_trigger="change"
        ),
        cls="model-selection"
    )

@rt('/')
def get(session):
    models = ["GPT-3", "GPT-4", "Custom Model"]
    current_model = session.get('current_model', 'GPT-3')
    return Titled(
        "Workbench",
        model_selection(models, current_model),
        # Other UI components
    )
```

#### Example: Code Extraction Feature

Creating an Interactive Button:
```python
def code_extraction_button(file_path):
    return Button(
        "Extract Code",
        hx_post="/extract_code",
        hx_trigger="click",
        hx_vals={"file_path": file_path}
    )

@rt('/file_browser')
def get():
    file_list = get_user_files()
    return Div(
        *[Div(
            Span(file_name),
            code_extraction_button(file_name)
        ) for file_name in file_list]
    )

@rt('/extract_code')
def post(file_path: str):
    code_content = extract_code(file_path)
    return Div(Pre(Code(code_content)))
```

**Best Practice:** When adapting CLI features to web UI, focus on creating intuitive, interactive elements that leverage the strengths of a web interface while maintaining the functionality of the original CLI tool.

## 13. Project-Specific Considerations

### Variable Embedding

Implement a system for embedding variables in prompts:

```python
def prompt_editor():
    return Form(
        Textarea(name="prompt", placeholder="Enter your prompt with variables like {variable_name}"),
        P("Variables: "),
        Input(name="variable_name", placeholder="Variable Name"),
        Input(name="variable_value", placeholder="Variable Value"),
        Button("Submit", type="submit")
    )

@rt('/create_prompt')
def get():
    return Titled("Create Prompt", prompt_editor())

@rt('/create_prompt')
def post(prompt: str, variable_name: str, variable_value: str, session):
    session['variables'] = session.get('variables', {})
    session['variables'][variable_name] = variable_value
    processed_prompt = prompt.format(**session['variables'])
    response = generate_code(processed_prompt, session['current_model'])
    return Div(code_block("python", response))
```

### Project Management System

Implement saving and loading of different projects:

```python
from dataclasses import dataclass
from typing import List, Dict, Any

@dataclass
class Project:
    name: str
    description: str
    files: List[str]
    settings: Dict[str, Any]

@rt('/save_project')
def post(project: Project, session):
    save_project_to_db(project)
    session['current_project'] = project.name
    return RedirectResponse('/projects')

@rt('/projects')
def get(session):
    projects = get_all_projects()
    return Titled("Projects",
        *[Div(
            H3(proj.name),
            P(proj.description),
            Button("Load", hx_post="/load_project", hx_vals={"project_id": proj.id})
        ) for proj in projects]
    )
```

**Best Practice:** Design your project management system to be scalable and efficient, considering factors like project size, number of files, and potential collaboration features.

## 14. WebSockets Integration

Implement WebSockets for real-time updates in your Workbench UI:

```python
@app.ws('/chat_stream')
async def chat_stream_ws(websocket):
    await websocket.accept()
    while True:
        user_input = await websocket.receive_text()
        async for response_chunk in stream_chat_response(user_input):
            await websocket.send_text(response_chunk)
```

Client-side JavaScript:
```javascript
const ws = new WebSocket('ws://localhost:8000/chat_stream');
ws.onmessage = function(event) {
    document.getElementById('chat-output').innerHTML += event.data;
};
```

**Best Practice:** Use WebSockets for bi-directional, real-time communication, such as live code updates or streaming chat responses.

## 15. Server-Sent Events (SSE)

Implement SSE for one-way server-to-client updates:

```python
@rt('/token_usage_stream')
async def get():
    async def token_usage_generator():
        while True:
            token_usage = get_current_token_usage()
            yield f"data: {token_usage}\n\n"
            await asyncio.sleep(1)
    return EventStream(token_usage_generator())
```

Client-side JavaScript:
```javascript
const eventSource = new EventSource('/token_usage_stream');
eventSource.onmessage = function(event) {
    document.getElementById('token-usage').textContent = event.data;
};
```

**Best Practice:** Use SSE for scenarios where you need frequent updates from the server but don't require two-way communication.

## 16. Syntax Highlighting and Markdown Rendering

Integrate syntax highlighting and markdown rendering for code display and documentation:

```python
hdrs = (
    HighlightJS(langs=['python', 'javascript', 'html', 'css']),
    MarkdownJS(),
)

app, rt = fast_app(hdrs=hdrs)

@rt('/display_code')
def get(code: str, language: str):
    return Titled("Code Display", 
        Div(Pre(Code(code, cls=f"language-{language}")))
    )

@rt('/display_markdown')
def get(markdown_content: str):
    return Titled("Documentation",
        Div(markdown_content, cls="markdown-body")
    )
```

**Best Practice:** Use syntax highlighting for all code displays to improve readability, and render documentation or comments as markdown for better formatting.

## 17. Error Handling and User Notifications (Toasts)

Implement a robust error handling system with user-friendly notifications:

```python
setup_toasts(app)

@rt('/perform_action')
def post(action: str, session):
    try:
        result = perform_action(action)
        add_toast(session, f"Action '{action}' completed successfully", "success")
        return result
    except ValueError as ve:
        add_toast(session, f"Invalid input: {ve}", "warning")
        return RedirectResponse('/')
    except Exception as e:
        add_toast(session, f"An error occurred: {e}", "error")
        log_error(e)  # Log detailed error for debugging
        return RedirectResponse('/')
```

**Best Practice:** Provide clear, actionable error messages to users while logging detailed error information for debugging purposes.

## 18. Authentication and Authorization

Implement user authentication and authorization using Beforeware:

```python
login_redirect = RedirectResponse('/login', status_code=303)

def authenticate(req, sess):
    if not sess.get('user'):
        return login_redirect

beforeware = Beforeware(
    authenticate,
    skip=['/login', '/register', '/static']
)

app, rt = fast_app(before=beforeware)

@rt('/login')
def post(username: str, password: str, session):
    if verify_credentials(username, password):
        session['user'] = username
        return RedirectResponse('/')
    else:
        return Titled("Login Failed", P("Invalid credentials"))
```

**Best Practice:** Implement proper authentication and authorization to secure your Workbench UI and protect sensitive information.

## 19. Testing and Debugging

### Testing Strategies with Starlette's TestClient

Use TestClient to simulate UI interactions and test CLI integration:

```python
from starlette.testclient import TestClient

client = TestClient(app)

def test_code_generation():
    response = client.post('/generate', json={
        'prompt': 'Write a Python function to calculate fibonacci numbers',
        'language': 'python'
    })
    assert response.status_code == 200
    assert "def fibonacci" in response.text
```

### Troubleshooting and Common Issues

1. Interpreting FastHTML Error Messages:
   - Issue: Cryptic errors due to incorrect component usage.
   - Solution: Ensure proper nesting of FT components and check for attribute names.

2. Debugging Asynchronous Operations:
   - Issue: Asynchronous functions not behaving as expected.
   - Solution: Use `asyncio.run()` for top-level async code, and ensure all async functions are properly awaited.

3. Handling Unexpected CLI Output:
   - Issue: CLI tool returns unexpected output causing the web UI to break.
   - Solution: Implement validation and sanitization of CLI outputs before rendering.

**Best Practice:** Implement comprehensive test coverage for both the FastHTML UI components and the CLI integration to catch issues early in the development process.

## 20. Additional Utilities: Surreal and HTMX

Leverage Surreal for enhanced JavaScript functionality and HTMX for dynamic content updates:

```python
from fasthtml.common import *
from fasthtml.surreal import Surreal

app, rt = fast_app(hdrs=[Surreal()])

@rt('/')
def get():
    return Titled("Dynamic UI",
        Button("Click me", 
               surreal="on click set #result.innerHTML to 'Button clicked!'"),
        Div(id="result")
    )
```

**Best Practice:** Use Surreal for simple client-side interactions and HTMX for more complex dynamic updates to reduce the need for custom JavaScript.

## 21. Best Practices and Tips

1. **Modular Design:** Break your Workbench UI into reusable components for easier maintenance and scalability.

2. **Consistent Naming:** Use clear, consistent naming conventions for routes, functions, and components.

3. **Error Handling:** Implement comprehensive error handling and provide user-friendly error messages.

4. **Performance Optimization:** Use asynchronous operations where appropriate to prevent blocking the event loop.

5. **Security:** Implement proper authentication, authorization, and input validation to secure your application.

6. **Testing:** Write unit tests for individual components and integration tests for the entire system.

7. **Documentation:** Maintain clear, up-to-date documentation for your codebase and API endpoints.

8. **Version Control:** Use Git for version control and follow best practices for branching and merging.

9. **Code Reviews:** Implement a code review process to maintain code quality and share knowledge among team members.

10. **Continuous Integration/Continuous Deployment (CI/CD):** Set up automated testing and deployment pipelines to streamline development and reduce errors.

## 22. Conclusion

This comprehensive guide provides a solid foundation for building the Workbench UI using FastHTML. By leveraging the power of FastHTML's components, routing system, and integration capabilities, you can create a robust, interactive web interface for your AI-powered coding assistant.

Key takeaways:
1. Utilize FT components for declarative UI construction.
2. Leverage FastHTML's routing system for clean, organized code.
3. Integrate your CLI tool seamlessly using adapted functions and WebSockets.
4. Implement real-time updates using WebSockets and SSE.
5. Prioritize user experience with clear error handling and intuitive UI design.

As you build your Workbench UI, remember to iterate on your design, continuously test your implementation, and refer back to this guide and the FastHTML documentation for deeper insights. With FastHTML, you have the tools to create a powerful, efficient, and user-friendly interface for your AI coding assistant.

Next steps:
1. Set up your project structure following FastHTML best practices.
2. Implement core UI components (file browser, code editor, conversation history).
3. Integrate your CLI tool, focusing on real-time interaction and error handling.
4. Develop advanced features like project management and variable embedding.
5. Conduct thorough testing and optimize performance.

By following this guide and leveraging FastHTML's capabilities, you're well-equipped to create an exceptional Workbench UI that enhances the power of your AI coding assistant.
```
CLI TOOL INTERFACE FOR CONTEXT
<multi-engineer-V2/main.py>
```
import logging
import asyncio
from rich.console import Console
from rich.panel import Panel
from rich.markdown import Markdown
from rich.prompt import Prompt
from app_state import get_app_state
from efc.efc_cache import get_file_context
from utils.token_usage import display_token_usage
from utils.code_utils import extract_and_save_code
from utils.conversation_utils import reset_conversation_context, view_conversation_context
from chat.chat import chat_with_model
from tools.tool_manager import initialize_tool_manager
from utils.utils import get_user_input
from setup_log import setup_environment


setup_environment()


async def main():
    console = Console()
    app_state = get_app_state()
    file_context = get_file_context()
    tool_manager = initialize_tool_manager()
    
    # Default to Llama model
    current_model = 'llama'

    console.print(Panel("Welcome to the Multi-Model AI Engineer Chat!", title="Welcome", style="bold green"))
    console.print("Type 'exit' to end the conversation.")
    console.print("Type 'switch model' to change the AI model.")
    console.print("Type 'raw' to toggle raw output mode.")
    console.print("Type 'extract <filename>' to extract and save code from the last response.")
    console.print("Type 'reset' to clear the entire Conversation Context.")
    console.print("Type 'view context' to display the current Conversation Context.")
    console.print("Type 'smart_edit <filename> \"<instruction>\"' to perform a smart edit on a file.")

    while True:
        try:
            user_input = await get_user_input("You: ")

            if user_input.lower() == 'exit':
                console.print(Panel("Thank you for chatting. Goodbye!", title="Goodbye", style="bold green"))
                break

            if user_input.lower() == 'switch model':
                models = ['llama', 'gpt', 'sonnet']
                new_model = Prompt.ask("Select a model", choices=models)
                if new_model != current_model:
                    current_model = new_model
                    console.print(f"Switched to {current_model.upper()} model.")
                continue

            if user_input.lower() == 'raw':
                app_state.raw_output_mode = not app_state.raw_output_mode
                mode_status = "enabled" if app_state.raw_output_mode else "disabled"
                console.print(Panel(f"Raw output mode {mode_status}.", title="Mode Change", style="bold yellow"))
                continue

            if user_input.lower().startswith('extract'):
                parts = user_input.split(maxsplit=1)
                file_name = parts[1] if len(parts) > 1 else "extracted_code.py"
                if app_state.conversation_history:
                    last_response = app_state.conversation_history[-1]["content"]
                    result = extract_and_save_code(last_response, file_name)
                    console.print(Panel(result, title="Code Extraction", style="green"))
                else:
                    console.print(Panel("No conversation history available.", title="Code Extraction", style="yellow"))
                continue

            if user_input.lower() == 'reset':
                result = reset_conversation_context()
                console.print(Panel(result, title="Conversation Context Reset", style="bold yellow"))
                continue

            if user_input.lower() == 'view context':
                context = view_conversation_context()
                console.print(Panel(context, title="Conversation Context", style="cyan"))
                continue

            if user_input.lower().startswith('smart_edit'):
                parts = user_input.split(maxsplit=2)
                if len(parts) == 3:
                    _, file_name, edit_instruction = parts
                    user_input = f"Perform a smart edit on the file {file_name} with the following instruction: {edit_instruction}"
                else:
                    console.print(Panel("Usage: smart_edit <filename> \"<edit instruction>\"", title="Smart Edit", style="yellow"))
                    continue

            assistant_response = await chat_with_model(user_input, tool_manager, current_model)

            if not app_state.raw_output_mode:
                console.print(Panel(Markdown(assistant_response), title=f"{current_model.upper()} Response", border_style="blue", expand=False))
            else:
                console.print(assistant_response)

            # Display file context summary
            try:
                context_summary = file_context.get_context_summary()
                console.print(Panel(context_summary, title="File Context", border_style="yellow"))
            except AttributeError as e:
                logging.error(f"Error getting context summary: {str(e)}")
                console.print(Panel("Unable to retrieve file context summary", title="File Context Error", border_style="red"))
            
            # Display token usage
            display_token_usage()

        except Exception as e:
            logging.exception("An unexpected error occurred in the main loop")
            console.print(f"[bold red]An unexpected error occurred: {str(e)}. Please try again.[/bold red]")

if __name__ == "__main__":
    asyncio.run(main())
```
<SEP>
Greetings, AI  ∞Ψ
ENGAGE. DEEP reflection on all the information and ***Project Code and Documentation*** provided thus far.

Please generate a detailed, step-by-step to-do list that outlines how to accomplish CLI Integration. Each step should be clear, actionable, and in logical order. Present the steps in a numbered list.
no matter the task always write a Todo list 

after the Todo list. Explain how to perform the tasks one by one. be verbose if needed.

when explaining how to perform the tasks use this format so it's easy to read:
((task name in bold markdown)
((task description in first person))
((task output verbose))