Initial commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# Edison Developer Documentation
|
||||
|
||||
Welcome to the Edison developer documentation! This guide will help you understand Edison's architecture, code organization, and how to extend its functionality.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Architecture Overview](architecture.md)
|
||||
2. [Code Structure](code-structure.md)
|
||||
3. [API Integration](api-integration.md)
|
||||
4. [Contributing Guidelines](contributing.md)
|
||||
5. [Development Environment Setup](development-setup.md)
|
||||
|
||||
## Getting Started with Development
|
||||
|
||||
Edison is a Python application that translates natural language into shell commands using OpenAI's APIs. It's designed to be modular and extensible, making it easy to add new features.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
User([User]) -->|Query| CLI[CLI Module]
|
||||
CLI -->|Process| Core[Core Module]
|
||||
Core -->|API Request| OpenAI[OpenAI API]
|
||||
OpenAI -->|Response| Core
|
||||
Core -->|Command| Shell[Shell]
|
||||
Core -->|Feedback| CLI
|
||||
CLI -->|Display| User
|
||||
|
||||
subgraph Edison Application
|
||||
CLI
|
||||
Core
|
||||
end
|
||||
|
||||
style User fill:#f9d5e5,stroke:#333,stroke-width:2px
|
||||
style Edison Application fill:#d3f6db,stroke:#333,stroke-width:4px
|
||||
style OpenAI fill:#d3f6f5,stroke:#333,stroke-width:2px
|
||||
style Shell fill:#eeeeee,stroke:#333,stroke-width:2px
|
||||
```
|
||||
|
||||
## Quick Start for Developers
|
||||
|
||||
1. **Clone the repository**:
|
||||
```bash
|
||||
git clone https://github.com/user/command-assistant
|
||||
cd command-assistant
|
||||
```
|
||||
|
||||
2. **Create a development environment**:
|
||||
```bash
|
||||
python -m venv venv
|
||||
source venv/bin/activate # On Windows: venv\Scripts\activate
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
3. **Run Edison in development mode**:
|
||||
```bash
|
||||
python -m edison your query here
|
||||
```
|
||||
|
||||
## Key Developer Resources
|
||||
|
||||
| Resource | Description |
|
||||
|----------|-------------|
|
||||
| [Architecture Overview](architecture.md) | High-level design and component interaction |
|
||||
| [Code Structure](code-structure.md) | Detailed breakdown of the codebase |
|
||||
| [API Integration](api-integration.md) | How Edison interacts with the OpenAI API |
|
||||
| [Contributing Guidelines](contributing.md) | How to contribute to the project |
|
||||
|
||||
## Development Philosophy
|
||||
|
||||
Edison follows these design principles:
|
||||
|
||||
1. **Modularity**: Components should be loosely coupled and focused on a single responsibility
|
||||
2. **Simplicity**: Keep the codebase simple and maintainable
|
||||
3. **User-centric**: Features should address real user needs
|
||||
4. **Safety**: Prioritize user safety when generating and executing commands
|
||||
|
||||
## Component Overview
|
||||
|
||||
Edison is organized into several main components:
|
||||
|
||||
- **CLI**: Command-line interface and user interaction
|
||||
- **Core**: Business logic, API integration, and command processing
|
||||
- **Config**: Configuration management
|
||||
- **UI**: User interface components
|
||||
- **Utils**: Utility functions and helpers
|
||||
@@ -0,0 +1,312 @@
|
||||
# API Integration
|
||||
|
||||
This document explains how Edison integrates with the OpenAI API to translate natural language into shell commands.
|
||||
|
||||
## Overview
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[User Query] --> B[Prompt Construction]
|
||||
B --> C[API Request]
|
||||
C --> D[Response Processing]
|
||||
D --> E[Command Extraction]
|
||||
E --> F[Command Validation]
|
||||
F --> G[Command Execution]
|
||||
|
||||
style A fill:#f9d5e5,stroke:#333,stroke-width:2px
|
||||
style B fill:#eeeeee,stroke:#333,stroke-width:2px
|
||||
style C fill:#d3f6db,stroke:#333,stroke-width:2px
|
||||
style D fill:#d3f6f5,stroke:#333,stroke-width:2px
|
||||
style E fill:#d5f6d5,stroke:#333,stroke-width:2px
|
||||
style F fill:#f6f6d5,stroke:#333,stroke-width:2px
|
||||
style G fill:#f5d5f5,stroke:#333,stroke-width:2px
|
||||
```
|
||||
|
||||
## API Client Module
|
||||
|
||||
The `api_client.py` module is responsible for all OpenAI API interactions:
|
||||
|
||||
```python
|
||||
def get_api_key(config):
|
||||
"""Get the OpenAI API key from various sources."""
|
||||
# Find API key from environment, file, or config
|
||||
|
||||
def create_client(config):
|
||||
"""Create and initialize an OpenAI client."""
|
||||
# Initialize client with API key
|
||||
|
||||
def call_api(client, config, query):
|
||||
"""Call the OpenAI API with the given query."""
|
||||
# Send request to API and extract response
|
||||
|
||||
def generate_command(client, config, query, max_retries=3):
|
||||
"""Generate a command using the OpenAI API with retry logic."""
|
||||
# Call API with retries for rate limits
|
||||
```
|
||||
|
||||
## API Key Management
|
||||
|
||||
Edison supports multiple methods for supplying the OpenAI API key, processed in this order:
|
||||
|
||||
1. **Environment Variable**: `OPENAI_API_KEY`
|
||||
2. **API Key File**: `~/.openai.apikey`
|
||||
3. **Configuration File**: `openai_api_key` in `edison.yaml`
|
||||
|
||||
This implementation is in `get_api_key()`:
|
||||
|
||||
```python
|
||||
def get_api_key(config):
|
||||
"""Get the OpenAI API key from various sources."""
|
||||
dotenv.load_dotenv()
|
||||
|
||||
# Method 1: Environment variable
|
||||
api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
# Method 2: File in home directory
|
||||
if not api_key:
|
||||
home_path = os.path.expanduser("~")
|
||||
api_key_path = os.path.join(home_path, ".openai.apikey")
|
||||
if os.path.exists(api_key_path):
|
||||
with open(api_key_path, 'r') as f:
|
||||
api_key = f.read().strip()
|
||||
|
||||
# Method 3: Configuration file
|
||||
if not api_key:
|
||||
api_key = config.get("openai_api_key")
|
||||
|
||||
if not api_key:
|
||||
raise ValueError("No OpenAI API key found")
|
||||
|
||||
return api_key
|
||||
```
|
||||
|
||||
## Prompt Construction
|
||||
|
||||
Edison uses a template-based approach to construct effective prompts:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant PromptManager
|
||||
participant Template
|
||||
participant APIClient
|
||||
participant OpenAI
|
||||
|
||||
User->>APIClient: Query: "list all files"
|
||||
APIClient->>PromptManager: get_full_prompt(query, shell)
|
||||
PromptManager->>Template: Load template
|
||||
Template-->>PromptManager: Template content
|
||||
PromptManager->>PromptManager: Format template with query
|
||||
PromptManager-->>APIClient: Formatted prompt
|
||||
APIClient->>OpenAI: Send API request
|
||||
OpenAI-->>APIClient: Command response
|
||||
```
|
||||
|
||||
The `prompt_manager.py` module handles this:
|
||||
|
||||
```python
|
||||
def load_prompt_template(shell="bash"):
|
||||
"""Load the prompt template with shell-specific considerations."""
|
||||
# Load and return the appropriate template
|
||||
|
||||
def get_full_prompt(query, shell="bash"):
|
||||
"""Get the full prompt for the given query and shell."""
|
||||
# Format prompt with query and shell
|
||||
```
|
||||
|
||||
### Prompt Template
|
||||
|
||||
Edison uses a prompt template (`edison.prompt`) to structure requests to the AI model. The template:
|
||||
|
||||
1. Provides context about the desired output format
|
||||
2. Includes examples of good responses
|
||||
3. Specifies the shell environment
|
||||
4. Encourages safe commands
|
||||
5. Includes the user's query
|
||||
|
||||
## API Request
|
||||
|
||||
Edison uses the OpenAI Python client library for API requests:
|
||||
|
||||
```python
|
||||
def call_api(client, config, query):
|
||||
"""Call the OpenAI API with the given query."""
|
||||
prompt = prompt_manager.get_full_prompt(query, config.get("shell", "bash"))
|
||||
system_prompt = prompt.split('\n')[0] if '\n' in prompt else prompt
|
||||
|
||||
response = client.chat.completions.create(
|
||||
model=config.get("model", "gpt-3.5-turbo"),
|
||||
messages=[
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": prompt}
|
||||
],
|
||||
temperature=config.get("temperature", 0),
|
||||
max_tokens=config.get("max_tokens", 500),
|
||||
)
|
||||
|
||||
return response.choices[0].message.content.strip()
|
||||
```
|
||||
|
||||
### Streaming API Integration
|
||||
|
||||
Edison also supports streaming command generation, which provides a more responsive user experience:
|
||||
|
||||
```python
|
||||
def call_api_streaming(client, config, query, callback):
|
||||
"""Call the OpenAI API with streaming enabled.
|
||||
|
||||
Args:
|
||||
client: The OpenAI client
|
||||
config: The configuration dictionary
|
||||
query: The user query
|
||||
callback: Function to call with each token
|
||||
"""
|
||||
prompt = prompt_manager.get_full_prompt(query, config.get("shell", "bash"))
|
||||
system_prompt = prompt.split('\n')[0] if '\n' in prompt else prompt
|
||||
|
||||
response = client.chat.completions.create(
|
||||
model=config.get("model", "gpt-3.5-turbo"),
|
||||
messages=[
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": prompt}
|
||||
],
|
||||
temperature=config.get("temperature", 0),
|
||||
max_tokens=config.get("max_tokens", 500),
|
||||
stream=True # Enable streaming
|
||||
)
|
||||
|
||||
# Collect the full response while calling the callback for each chunk
|
||||
full_response = ""
|
||||
|
||||
for chunk in response:
|
||||
if chunk.choices and chunk.choices[0].delta.content:
|
||||
content = chunk.choices[0].delta.content
|
||||
full_response += content
|
||||
callback(content) # Call the callback with each chunk
|
||||
|
||||
return full_response.strip()
|
||||
```
|
||||
|
||||
This streaming functionality is integrated with the UI through a callback function that updates the display in real-time as tokens are received.
|
||||
|
||||
### Request Parameters
|
||||
|
||||
The API request includes these key parameters:
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| model | The OpenAI model to use | gpt-3.5-turbo |
|
||||
| temperature | Randomness of completions (0-1) | 0 |
|
||||
| max_tokens | Maximum tokens in response | 500 |
|
||||
|
||||
## Error Handling and Retries
|
||||
|
||||
The `generate_command()` function implements retry logic to handle rate limiting:
|
||||
|
||||
```python
|
||||
def generate_command(client, config, query, max_retries=3):
|
||||
"""Generate a command using the OpenAI API with retry logic."""
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
return call_api(client, config, query)
|
||||
except Exception as e:
|
||||
if "rate limit" in str(e).lower() and attempt < max_retries - 1:
|
||||
wait_time = 2 ** attempt # Exponential backoff
|
||||
logger.warning(f"Rate limited. Retrying in {wait_time} seconds...")
|
||||
time.sleep(wait_time)
|
||||
else:
|
||||
logger.error(f"Error after {attempt+1} attempts: {str(e)}")
|
||||
raise
|
||||
```
|
||||
|
||||
Key features:
|
||||
- Exponential backoff for rate limits
|
||||
- Maximum retry attempts
|
||||
- Detailed error logging
|
||||
|
||||
## Command Processing and Validation
|
||||
|
||||
After receiving the API response, Edison:
|
||||
|
||||
1. Extracts the command from the response
|
||||
2. Validates the command for safety
|
||||
3. Checks for markdown or other formatting issues
|
||||
4. Prepares the command for execution
|
||||
|
||||
## Extending the API Integration
|
||||
|
||||
To support additional AI providers or models:
|
||||
|
||||
1. **Create a new client factory function**:
|
||||
```python
|
||||
def create_anthropic_client(config):
|
||||
# Initialize Anthropic client
|
||||
```
|
||||
|
||||
2. **Add a model selection mechanism**:
|
||||
```python
|
||||
def get_client_for_model(config):
|
||||
model = config.get("model", "gpt-3.5-turbo")
|
||||
if model.startswith("claude"):
|
||||
return create_anthropic_client(config)
|
||||
else:
|
||||
return create_client(config)
|
||||
```
|
||||
|
||||
3. **Implement provider-specific API call function**:
|
||||
```python
|
||||
def call_anthropic_api(client, config, query):
|
||||
# Format request for Anthropic API
|
||||
```
|
||||
|
||||
4. **Update the command generation logic**:
|
||||
```python
|
||||
def generate_command(client, config, query, max_retries=3):
|
||||
model = config.get("model", "gpt-3.5-turbo")
|
||||
if model.startswith("claude"):
|
||||
return call_anthropic_api(client, config, query)
|
||||
else:
|
||||
return call_api(client, config, query)
|
||||
```
|
||||
|
||||
## API Response Examples
|
||||
|
||||
### Successful Response
|
||||
|
||||
```json
|
||||
{
|
||||
"choices": [
|
||||
{
|
||||
"message": {
|
||||
"content": "ls -la",
|
||||
"role": "assistant"
|
||||
},
|
||||
"index": 0,
|
||||
"finish_reason": "stop"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Error Response
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"message": "Rate limit exceeded",
|
||||
"type": "rate_limit_error",
|
||||
"param": null,
|
||||
"code": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
To optimize API usage and performance:
|
||||
|
||||
1. **Use Efficient Models**: Default to `gpt-3.5-turbo` for lower latency
|
||||
2. **Limit Token Usage**: Keep max_tokens reasonable (default 500)
|
||||
3. **Request Caching**: Consider implementing caching for common queries
|
||||
4. **Concurrent Requests**: For batch processing, consider async requests
|
||||
5. **Prompt Optimization**: Keep prompt templates concise but effective
|
||||
@@ -0,0 +1,177 @@
|
||||
# Architecture Overview
|
||||
|
||||
This document provides a comprehensive overview of Edison's architecture, components, and their interactions.
|
||||
|
||||
## System Architecture
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph User Interaction
|
||||
CLI[CLI Module]
|
||||
Interactive[Interactive Mode]
|
||||
Console[Console UI]
|
||||
end
|
||||
|
||||
subgraph Core Components
|
||||
APIClient[API Client]
|
||||
PromptManager[Prompt Manager]
|
||||
CommandExecutor[Command Executor]
|
||||
end
|
||||
|
||||
subgraph Configuration
|
||||
ConfigManager[Config Manager]
|
||||
Validation[Validation]
|
||||
end
|
||||
|
||||
subgraph Utilities
|
||||
Logging[Logging Utils]
|
||||
OSUtils[OS Utils]
|
||||
end
|
||||
|
||||
CLI --> APIClient
|
||||
CLI --> CommandExecutor
|
||||
CLI --> Console
|
||||
CLI --> Interactive
|
||||
Interactive --> APIClient
|
||||
Interactive --> CommandExecutor
|
||||
|
||||
APIClient --> PromptManager
|
||||
APIClient --> ConfigManager
|
||||
CommandExecutor --> Validation
|
||||
CommandExecutor --> OSUtils
|
||||
|
||||
ConfigManager --> Logging
|
||||
|
||||
style User Interaction fill:#f9d5e5,stroke:#333,stroke-width:2px
|
||||
style Core Components fill:#d3f6db,stroke:#333,stroke-width:2px
|
||||
style Configuration fill:#d3f6f5,stroke:#333,stroke-width:2px
|
||||
style Utilities fill:#eeeeee,stroke:#333,stroke-width:2px
|
||||
```
|
||||
|
||||
## Component Breakdown
|
||||
|
||||
### User Interaction Layer
|
||||
|
||||
The user interaction layer handles all user-facing functionality:
|
||||
|
||||
1. **CLI Module** (`edison/cli.py`):
|
||||
- Entry point for the application
|
||||
- Parses command-line arguments
|
||||
- Initializes logging and configuration
|
||||
- Coordinates between components
|
||||
|
||||
2. **Interactive Mode** (`edison/ui/interactive.py`):
|
||||
- Provides a dedicated shell for continuous interaction
|
||||
- Manages command history and user input
|
||||
- Handles special commands and actions
|
||||
|
||||
3. **Console UI** (`edison/ui/console.py`):
|
||||
- Formats and displays text output
|
||||
- Presents commands and prompt options
|
||||
- Manages colored output with termcolor
|
||||
|
||||
### Core Components
|
||||
|
||||
The core components handle the main business logic:
|
||||
|
||||
1. **API Client** (`edison/core/api_client.py`):
|
||||
- Manages communication with the OpenAI API
|
||||
- Handles API key management and retry logic
|
||||
- Processes responses from the API
|
||||
|
||||
2. **Prompt Manager** (`edison/core/prompt_manager.py`):
|
||||
- Constructs effective prompts for the AI model
|
||||
- Formats user queries for optimal command generation
|
||||
- Adapts prompts based on shell and OS
|
||||
|
||||
3. **Command Executor** (`edison/core/command_executor.py`):
|
||||
- Safely executes generated commands
|
||||
- Handles command output and errors
|
||||
- Adapts execution for different shells and platforms
|
||||
|
||||
### Configuration Layer
|
||||
|
||||
The configuration layer manages settings and validation:
|
||||
|
||||
1. **Config Manager** (`edison/config/config_manager.py`):
|
||||
- Loads and validates configuration from edison.yaml
|
||||
- Provides default settings
|
||||
- Handles environment variables for API keys
|
||||
|
||||
2. **Validation** (`edison/utils/validation.py`):
|
||||
- Validates commands for safety
|
||||
- Detects potentially dangerous operations
|
||||
- Checks for invalid syntax or formatting
|
||||
|
||||
### Utilities
|
||||
|
||||
Utility modules provide support functions:
|
||||
|
||||
1. **Logging Utils** (`edison/utils/logging_utils.py`):
|
||||
- Configures logging for the application
|
||||
- Manages log files and levels
|
||||
- Provides logger access
|
||||
|
||||
2. **OS Utils** (`edison/utils/os_utils.py`):
|
||||
- Provides OS-specific functionality
|
||||
- Detects platform and shell information
|
||||
- Manages environment variables
|
||||
|
||||
## Data Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant CLI
|
||||
participant Config
|
||||
participant APIClient
|
||||
participant CommandExecutor
|
||||
participant Shell
|
||||
|
||||
User->>CLI: Input query
|
||||
CLI->>Config: Load configuration
|
||||
CLI->>APIClient: Send query
|
||||
APIClient->>APIClient: Format prompt
|
||||
APIClient->>OpenAI: API request
|
||||
OpenAI-->>APIClient: Command response
|
||||
APIClient-->>CLI: Return command
|
||||
CLI->>User: Display command
|
||||
User->>CLI: Confirm execution
|
||||
CLI->>CommandExecutor: Execute command
|
||||
CommandExecutor->>Shell: Run in shell
|
||||
Shell-->>CommandExecutor: Command output
|
||||
CommandExecutor-->>CLI: Execution result
|
||||
CLI->>User: Display output
|
||||
```
|
||||
|
||||
1. User inputs a natural language query
|
||||
2. CLI loads configuration and processes arguments
|
||||
3. Query is sent to the API client
|
||||
4. API client formats the prompt and sends it to OpenAI
|
||||
5. Response is received and processed
|
||||
6. Command is displayed to the user
|
||||
7. User confirms, modifies, or cancels execution
|
||||
8. If confirmed, command is sent to the command executor
|
||||
9. Command executor runs the command in the appropriate shell
|
||||
10. Output is returned to the CLI and displayed to the user
|
||||
|
||||
## Extension Points
|
||||
|
||||
Edison is designed to be extensible in several ways:
|
||||
|
||||
1. **New UI Components**: Add new UI modes by extending the UI components
|
||||
2. **Alternative AI Providers**: The API client can be extended to support other AI providers
|
||||
3. **Custom Prompt Templates**: The prompt manager can be enhanced with specialized prompts
|
||||
4. **Additional Command Validation**: Add custom validation rules in the validation module
|
||||
5. **Platform-Specific Features**: Extend OS utils for additional platform support
|
||||
|
||||
## Technologies Used
|
||||
|
||||
Edison is built using:
|
||||
|
||||
- **Python**: Core programming language
|
||||
- **OpenAI API**: For natural language processing and command generation
|
||||
- **prompt_toolkit**: For interactive shell functionality
|
||||
- **termcolor**: For colored terminal output
|
||||
- **pyyaml**: For configuration file parsing
|
||||
- **pyperclip**: For clipboard integration
|
||||
@@ -0,0 +1,324 @@
|
||||
# Code Structure
|
||||
|
||||
This document provides a detailed overview of Edison's code organization and file structure.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
edison/
|
||||
├── __init__.py # Package initialization
|
||||
├── __main__.py # Entry point for module execution
|
||||
├── cli.py # Command-line interface
|
||||
├── edison.prompt # Prompt template for command generation
|
||||
├── edison.yaml # Default configuration file
|
||||
├── config/ # Configuration management
|
||||
│ ├── __init__.py
|
||||
│ └── config_manager.py
|
||||
├── core/ # Core business logic
|
||||
│ ├── __init__.py
|
||||
│ ├── api_client.py # OpenAI API integration
|
||||
│ ├── command_executor.py # Command execution
|
||||
│ └── prompt_manager.py # Prompt handling
|
||||
├── logs/ # Log files directory
|
||||
├── ui/ # User interface components
|
||||
│ ├── __init__.py
|
||||
│ ├── console.py # Console output formatting
|
||||
│ └── interactive.py # Interactive shell mode
|
||||
└── utils/ # Utility functions
|
||||
├── __init__.py
|
||||
├── logging_utils.py # Logging configuration
|
||||
├── os_utils.py # OS-specific utilities
|
||||
└── validation.py # Command validation
|
||||
```
|
||||
|
||||
## Key Files and Their Functions
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
cli <|-- config_manager
|
||||
cli <|-- api_client
|
||||
cli <|-- console
|
||||
cli <|-- interactive
|
||||
api_client <|-- prompt_manager
|
||||
interactive <|-- api_client
|
||||
interactive <|-- command_executor
|
||||
|
||||
class cli {
|
||||
+main()
|
||||
+parse_arguments()
|
||||
}
|
||||
|
||||
class config_manager {
|
||||
+load_config()
|
||||
+print_config()
|
||||
}
|
||||
|
||||
class api_client {
|
||||
+create_client()
|
||||
+generate_command()
|
||||
+call_api()
|
||||
+get_api_key()
|
||||
}
|
||||
|
||||
class prompt_manager {
|
||||
+get_full_prompt()
|
||||
+load_prompt_template()
|
||||
}
|
||||
|
||||
class command_executor {
|
||||
+execute_command()
|
||||
}
|
||||
|
||||
class console {
|
||||
+print_command()
|
||||
+prompt_user_input()
|
||||
+handle_command_execution()
|
||||
+handle_user_input()
|
||||
}
|
||||
|
||||
class interactive {
|
||||
+interactive_mode()
|
||||
+get_command_explanation()
|
||||
+show_help()
|
||||
}
|
||||
|
||||
class logging_utils {
|
||||
+setup_logging()
|
||||
+get_logger()
|
||||
}
|
||||
|
||||
class os_utils {
|
||||
+get_default_shell()
|
||||
+missing_posix_display()
|
||||
}
|
||||
|
||||
class validation {
|
||||
+check_for_issue()
|
||||
+check_for_markdown()
|
||||
+is_dangerous_command()
|
||||
}
|
||||
```
|
||||
|
||||
### Core Modules
|
||||
|
||||
#### cli.py
|
||||
|
||||
The main entry point and command-line interface for Edison:
|
||||
- Parses command-line arguments
|
||||
- Initializes logging
|
||||
- Loads configuration
|
||||
- Handles user interaction flow
|
||||
- Manages error handling
|
||||
|
||||
```python
|
||||
def main():
|
||||
"""Main entry point for the application."""
|
||||
# Parse arguments, set up logging, load config, etc.
|
||||
|
||||
def parse_arguments():
|
||||
"""Parse command line arguments."""
|
||||
# Define and parse command-line arguments
|
||||
```
|
||||
|
||||
#### config/config_manager.py
|
||||
|
||||
Handles configuration loading and management:
|
||||
- Loads settings from edison.yaml
|
||||
- Provides default values
|
||||
- Validates configuration
|
||||
|
||||
```python
|
||||
def load_config():
|
||||
"""Load configuration from the YAML file."""
|
||||
# Find and load the configuration file
|
||||
|
||||
def print_config(config):
|
||||
"""Print the current configuration."""
|
||||
# Display configuration settings
|
||||
```
|
||||
|
||||
#### core/api_client.py
|
||||
|
||||
Manages interaction with the OpenAI API:
|
||||
- Creates and initializes the API client
|
||||
- Handles API key management
|
||||
- Formats queries and processes responses
|
||||
- Implements retry logic
|
||||
- Supports both streaming and non-streaming command generation
|
||||
|
||||
```python
|
||||
def create_client(config):
|
||||
"""Create and initialize an OpenAI client."""
|
||||
# Initialize API client with key
|
||||
|
||||
def generate_command(client, config, query, max_retries=3):
|
||||
"""Generate a command using the OpenAI API with retry logic."""
|
||||
# Send query to API and handle response
|
||||
|
||||
def generate_command_streaming(client, config, query, callback):
|
||||
"""Generate a command using the OpenAI API with streaming output.
|
||||
|
||||
Args:
|
||||
client: The OpenAI client
|
||||
config: The configuration dictionary
|
||||
query: The user query
|
||||
callback: Function to call with each token
|
||||
"""
|
||||
# Stream response tokens and call the callback for each one
|
||||
```
|
||||
|
||||
#### core/command_executor.py
|
||||
|
||||
Executes shell commands:
|
||||
- Runs commands in the appropriate shell
|
||||
- Handles command output and errors
|
||||
- Implements safety checks
|
||||
|
||||
```python
|
||||
def execute_command(shell, command):
|
||||
"""Execute a shell command."""
|
||||
# Run command and handle result
|
||||
```
|
||||
|
||||
#### core/prompt_manager.py
|
||||
|
||||
Manages prompt templates and formatting:
|
||||
- Loads prompt templates
|
||||
- Formats user queries for optimal results
|
||||
- Adapts prompts based on shell and OS
|
||||
|
||||
```python
|
||||
def get_full_prompt(query, shell="bash"):
|
||||
"""Get the full prompt for the given query and shell."""
|
||||
# Format prompt with query and shell info
|
||||
```
|
||||
|
||||
### UI Modules
|
||||
|
||||
#### ui/console.py
|
||||
|
||||
Handles console output and user interaction:
|
||||
- Formats and displays text
|
||||
- Presents command options
|
||||
- Handles user input
|
||||
- Supports direct command modification
|
||||
- Controls display of generating prefix
|
||||
|
||||
```python
|
||||
def print_command(command, show_generating_prefix=True):
|
||||
"""Print a command to the console."""
|
||||
# Display command with formatting, optionally showing the generating prefix
|
||||
|
||||
def handle_command_execution(client, config, command, explain=False):
|
||||
"""Handle the execution of a command."""
|
||||
# Manage command execution flow
|
||||
|
||||
def handle_direct_modification(command):
|
||||
"""Handle direct modification of a command.
|
||||
|
||||
Args:
|
||||
command: The command to modify
|
||||
|
||||
Returns:
|
||||
The modified command
|
||||
"""
|
||||
# Present interactive editor for direct command modification
|
||||
```
|
||||
|
||||
#### ui/interactive.py
|
||||
|
||||
Provides an interactive shell mode:
|
||||
- Manages continuous interaction
|
||||
- Handles command history
|
||||
- Processes special commands
|
||||
|
||||
```python
|
||||
def interactive_mode(client, config):
|
||||
"""Start an interactive shell."""
|
||||
# Run interactive loop
|
||||
|
||||
def get_command_explanation(client, command):
|
||||
"""Get an explanation for a command."""
|
||||
# Generate explanation
|
||||
```
|
||||
|
||||
### Utility Modules
|
||||
|
||||
#### utils/logging_utils.py
|
||||
|
||||
Configures and manages logging:
|
||||
- Sets up log files and formats
|
||||
- Controls log levels
|
||||
- Provides access to loggers
|
||||
|
||||
```python
|
||||
def setup_logging(verbose=False):
|
||||
"""Configure logging for the application."""
|
||||
# Set up logging with appropriate levels
|
||||
```
|
||||
|
||||
#### utils/os_utils.py
|
||||
|
||||
Provides OS-specific functionality:
|
||||
- Detects platform information
|
||||
- Manages environment-specific behavior
|
||||
- Determines default shell
|
||||
|
||||
```python
|
||||
def get_default_shell():
|
||||
"""Get the default shell for the current OS."""
|
||||
# Determine system shell
|
||||
```
|
||||
|
||||
#### utils/validation.py
|
||||
|
||||
Validates and checks commands:
|
||||
- Detects potentially dangerous commands
|
||||
- Checks for markdown formatting
|
||||
- Identifies command issues
|
||||
|
||||
```python
|
||||
def is_dangerous_command(command):
|
||||
"""Check if a command is potentially dangerous."""
|
||||
# Analyze command for dangerous patterns
|
||||
```
|
||||
|
||||
## Static Files
|
||||
|
||||
- **edison.prompt**: Template for generating prompts sent to the OpenAI API
|
||||
- **edison.yaml**: Default configuration file with settings
|
||||
|
||||
## Dependencies and Imports
|
||||
|
||||
The project uses these key dependencies:
|
||||
|
||||
1. **Core Python Libraries**:
|
||||
- `argparse`: For command-line argument parsing
|
||||
- `logging`: For log management
|
||||
- `subprocess`: For command execution
|
||||
- `os`, `sys`: For system interaction
|
||||
|
||||
2. **External Libraries**:
|
||||
- `openai`: For API interaction
|
||||
- `termcolor`: For colored terminal output
|
||||
- `python-dotenv`: For environment variable loading
|
||||
- `pyyaml`: For configuration parsing
|
||||
- `pyperclip`: For clipboard operations
|
||||
- `prompt_toolkit`: For interactive shell functionality
|
||||
- `colorama`: For cross-platform color support
|
||||
|
||||
## Code Style and Conventions
|
||||
|
||||
Edison follows these coding conventions:
|
||||
|
||||
1. **PEP 8**: Standard Python style guide
|
||||
2. **Docstrings**: All functions and classes have docstrings in the Google style
|
||||
3. **Error Handling**: Comprehensive try/except blocks with detailed logging
|
||||
4. **Modularity**: Functions and classes have single responsibilities
|
||||
5. **Type Hints**: Not currently used but planned for future versions
|
||||
|
||||
## Special Considerations
|
||||
|
||||
1. **Cross-Platform Support**: Code includes handling for different operating systems
|
||||
2. **API Key Security**: Multiple secure methods for handling API keys
|
||||
3. **Command Safety**: Validation to prevent dangerous command execution
|
||||
@@ -0,0 +1,208 @@
|
||||
# Contributing Guidelines
|
||||
|
||||
Thank you for your interest in contributing to Edison! This guide will help you get started with contributing to the project.
|
||||
|
||||
## Development Workflow
|
||||
|
||||
```mermaid
|
||||
gitGraph
|
||||
commit id: "Initial setup"
|
||||
branch feature/my-feature
|
||||
checkout feature/my-feature
|
||||
commit id: "Implement feature"
|
||||
commit id: "Add tests"
|
||||
commit id: "Fix bugs"
|
||||
checkout main
|
||||
merge feature/my-feature
|
||||
commit id: "Release v1.0.1"
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Setting Up Your Development Environment
|
||||
|
||||
1. **Fork the repository**:
|
||||
- Visit the GitHub repository and click the "Fork" button
|
||||
|
||||
2. **Clone your fork**:
|
||||
```bash
|
||||
git clone https://github.com/YOUR_USERNAME/command-assistant.git
|
||||
cd command-assistant
|
||||
```
|
||||
|
||||
3. **Set up a virtual environment**:
|
||||
```bash
|
||||
python -m venv venv
|
||||
source venv/bin/activate # On Windows: venv\Scripts\activate
|
||||
```
|
||||
|
||||
4. **Install in development mode**:
|
||||
```bash
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
5. **Install development dependencies**:
|
||||
```bash
|
||||
pip install pylint pytest
|
||||
```
|
||||
|
||||
### Development Process
|
||||
|
||||
1. **Create a branch**:
|
||||
```bash
|
||||
git checkout -b feature/my-feature-name
|
||||
```
|
||||
|
||||
2. **Make your changes**:
|
||||
- Write code
|
||||
- Add tests
|
||||
- Update documentation
|
||||
|
||||
3. **Run tests and linting**:
|
||||
```bash
|
||||
# Run tests (future addition)
|
||||
pytest
|
||||
|
||||
# Run linting
|
||||
pylint edison
|
||||
```
|
||||
|
||||
4. **Commit your changes**:
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Descriptive commit message"
|
||||
```
|
||||
|
||||
5. **Push to your fork**:
|
||||
```bash
|
||||
git push origin feature/my-feature-name
|
||||
```
|
||||
|
||||
6. **Submit a pull request**:
|
||||
- Go to your fork on GitHub
|
||||
- Click "New Pull Request"
|
||||
- Select your branch and submit
|
||||
|
||||
## Code Style and Guidelines
|
||||
|
||||
### Python Style Guide
|
||||
|
||||
Edison follows [PEP 8](https://www.python.org/dev/peps/pep-0008/) with some additional guidelines:
|
||||
|
||||
- Use 4 spaces for indentation
|
||||
- Maximum line length of 100 characters
|
||||
- Use meaningful variable and function names
|
||||
- Write docstrings for all classes and functions
|
||||
|
||||
### Docstring Format
|
||||
|
||||
We use Google-style docstrings:
|
||||
|
||||
```python
|
||||
def example_function(param1, param2):
|
||||
"""
|
||||
Brief description of the function.
|
||||
|
||||
Args:
|
||||
param1: Description of param1
|
||||
param2: Description of param2
|
||||
|
||||
Returns:
|
||||
Description of return value
|
||||
|
||||
Raises:
|
||||
ExceptionType: When and why this exception is raised
|
||||
"""
|
||||
pass
|
||||
```
|
||||
|
||||
### Code Organization
|
||||
|
||||
- Keep functions focused on a single responsibility
|
||||
- Group related functionality in modules
|
||||
- Use appropriate error handling
|
||||
- Add useful log messages
|
||||
|
||||
## Adding New Features
|
||||
|
||||
When adding new features:
|
||||
|
||||
1. **Start by discussing**: Open an issue to discuss your proposed feature
|
||||
2. **Design the interface**: How will users interact with your feature?
|
||||
3. **Plan the implementation**: Sketch out the implementation before coding
|
||||
4. **Write tests**: Add tests to verify your feature works correctly
|
||||
5. **Document the feature**: Update or add documentation explaining the feature
|
||||
6. **Submit for review**: Submit a pull request for review
|
||||
|
||||
## Release Process
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Feature Development] --> B[Testing]
|
||||
B --> C[Code Review]
|
||||
C --> D{Approved?}
|
||||
D -->|No| B
|
||||
D -->|Yes| E[Merge to Main]
|
||||
E --> F[Version Bump]
|
||||
F --> G[Release]
|
||||
|
||||
style A fill:#f9d5e5,stroke:#333,stroke-width:2px
|
||||
style B fill:#eeeeee,stroke:#333,stroke-width:2px
|
||||
style C fill:#d3f6db,stroke:#333,stroke-width:2px
|
||||
style D fill:#d3f6f5,stroke:#333,stroke-width:2px
|
||||
style E fill:#f5d5f5,stroke:#333,stroke-width:2px
|
||||
style F fill:#f5d5d5,stroke:#333,stroke-width:2px
|
||||
style G fill:#d5d5f5,stroke:#333,stroke-width:2px
|
||||
```
|
||||
|
||||
Edison follows semantic versioning (MAJOR.MINOR.PATCH):
|
||||
|
||||
- **MAJOR**: Incompatible API changes
|
||||
- **MINOR**: Backwards-compatible new features
|
||||
- **PATCH**: Backwards-compatible bug fixes
|
||||
|
||||
## Future Development Areas
|
||||
|
||||
We're looking for contributions in these areas:
|
||||
|
||||
1. **Testing Framework**: Adding a comprehensive test suite
|
||||
2. **Documentation**: Expanding and improving documentation
|
||||
3. **Supported Shells**: Adding support for additional shells
|
||||
4. **Platform Support**: Enhancing cross-platform compatibility
|
||||
5. **Model Support**: Adding support for alternative AI models
|
||||
6. **Command Validation**: Improving safety checks
|
||||
7. **Interactive Features**: Enhancing the interactive shell
|
||||
8. **Performance Optimization**: Improving response times
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Security Considerations
|
||||
|
||||
- Never commit API keys or sensitive information
|
||||
- Validate user input thoroughly
|
||||
- Use safe subprocess execution methods
|
||||
- Be careful with permissions and file operations
|
||||
|
||||
### Performance
|
||||
|
||||
- Minimize API calls where possible
|
||||
- Use efficient algorithms and data structures
|
||||
- Avoid unnecessary file I/O
|
||||
- Profile code to identify bottlenecks
|
||||
|
||||
### User Experience
|
||||
|
||||
- Provide clear feedback to users
|
||||
- Use consistent command-line interfaces
|
||||
- Add helpful error messages
|
||||
- Consider accessibility in your design
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you need help with contributing:
|
||||
|
||||
- Open an issue on GitHub
|
||||
- Check existing documentation
|
||||
- Reach out to maintainers
|
||||
|
||||
Thank you for contributing to Edison!
|
||||
@@ -0,0 +1,247 @@
|
||||
# Development Environment Setup
|
||||
|
||||
This guide explains how to set up your development environment for Edison.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before beginning development on Edison, ensure you have:
|
||||
|
||||
- **Python 3.6+**: Required for core development
|
||||
- **Git**: For version control
|
||||
- **OpenAI API Key**: For testing API integration
|
||||
- **pip**: For package management
|
||||
|
||||
## Setting Up Your Development Environment
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Clone Repository] --> B[Set Up Virtual Environment]
|
||||
B --> C[Install Dependencies]
|
||||
C --> D[Configure API Key]
|
||||
D --> E[Run Tests]
|
||||
E --> F[Start Development]
|
||||
|
||||
style A fill:#f9d5e5,stroke:#333,stroke-width:2px
|
||||
style B fill:#eeeeee,stroke:#333,stroke-width:2px
|
||||
style C fill:#d3f6db,stroke:#333,stroke-width:2px
|
||||
style D fill:#d3f6f5,stroke:#333,stroke-width:2px
|
||||
style E fill:#f5d5f5,stroke:#333,stroke-width:2px
|
||||
style F fill:#f5f5d5,stroke:#333,stroke-width:2px
|
||||
```
|
||||
|
||||
### Step 1: Clone the Repository
|
||||
|
||||
```bash
|
||||
# If you're a contributor, fork the repository first, then:
|
||||
git clone https://github.com/YOUR_USERNAME/command-assistant.git
|
||||
|
||||
# If you're a maintainer:
|
||||
git clone https://github.com/user/command-assistant.git
|
||||
|
||||
# Navigate to the directory
|
||||
cd command-assistant
|
||||
```
|
||||
|
||||
### Step 2: Create a Virtual Environment
|
||||
|
||||
```bash
|
||||
# Create virtual environment
|
||||
python -m venv venv
|
||||
|
||||
# Activate virtual environment
|
||||
# On macOS/Linux:
|
||||
source venv/bin/activate
|
||||
|
||||
# On Windows:
|
||||
venv\Scripts\activate
|
||||
```
|
||||
|
||||
### Step 3: Install in Development Mode
|
||||
|
||||
```bash
|
||||
# Install Edison in development mode
|
||||
pip install -e .
|
||||
|
||||
# Install development dependencies
|
||||
pip install pylint pytest
|
||||
```
|
||||
|
||||
### Step 4: Configure OpenAI API Key
|
||||
|
||||
For development, it's best to use environment variables:
|
||||
|
||||
```bash
|
||||
# On macOS/Linux:
|
||||
export OPENAI_API_KEY="your-api-key-here"
|
||||
|
||||
# On Windows:
|
||||
set OPENAI_API_KEY=your-api-key-here
|
||||
```
|
||||
|
||||
Or create a `.env` file in the project root:
|
||||
|
||||
```
|
||||
OPENAI_API_KEY="your-api-key-here"
|
||||
```
|
||||
|
||||
## Directory Structure Setup
|
||||
|
||||
The development environment should match this structure:
|
||||
|
||||
```
|
||||
command-assistant/ # Root directory
|
||||
├── docs/ # Documentation
|
||||
├── edison/ # Main package
|
||||
├── tests/ # Test directory (future addition)
|
||||
├── venv/ # Virtual environment (generated)
|
||||
├── .gitignore # Git ignore file
|
||||
├── LICENSE # License file
|
||||
├── README.md # Project readme
|
||||
├── install_edison.sh # Installation script for Linux/macOS
|
||||
├── install_edison.bat # Installation script for Windows
|
||||
├── requirements.txt # Package dependencies
|
||||
└── setup.py # Package setup file
|
||||
```
|
||||
|
||||
## Running Edison in Development Mode
|
||||
|
||||
```bash
|
||||
# Run Edison from the command line
|
||||
edison your query here
|
||||
|
||||
# Run Edison as a module
|
||||
python -m edison your query here
|
||||
|
||||
# Run with verbose logging
|
||||
edison -v your query here
|
||||
```
|
||||
|
||||
## Development Tools
|
||||
|
||||
### Code Linting
|
||||
|
||||
Edison uses `pylint` for code linting:
|
||||
|
||||
```bash
|
||||
# Lint the entire package
|
||||
pylint edison
|
||||
|
||||
# Lint a specific file
|
||||
pylint edison/cli.py
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
In the future, Edison will use `pytest` for testing:
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pytest
|
||||
|
||||
# Run specific tests
|
||||
pytest tests/test_api_client.py
|
||||
|
||||
# Run with coverage
|
||||
pytest --cov=edison
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
### Logging
|
||||
|
||||
Enable verbose logging for debugging:
|
||||
|
||||
```bash
|
||||
edison -v your query here
|
||||
```
|
||||
|
||||
Logs are stored in `edison/logs/edison.log`.
|
||||
|
||||
### Using a Debugger
|
||||
|
||||
For detailed debugging, you can use Python's built-in debugger or an IDE:
|
||||
|
||||
```python
|
||||
import pdb; pdb.set_trace() # Add this line where you want to break
|
||||
|
||||
# Or with Python 3.7+
|
||||
breakpoint()
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Feature
|
||||
Feature --> Development
|
||||
Development --> Testing
|
||||
Testing --> Refinement
|
||||
Refinement --> Testing: Issues found
|
||||
Testing --> PullRequest: Tests pass
|
||||
PullRequest --> Review
|
||||
Review --> Refinement: Changes requested
|
||||
Review --> Merge: Approved
|
||||
Merge --> [*]
|
||||
```
|
||||
|
||||
1. **Pick a Feature/Issue**: Select something to work on
|
||||
2. **Create a Branch**: Make a new branch for your work
|
||||
3. **Development**: Write code, docstrings, and comments
|
||||
4. **Testing**: Test your changes thoroughly
|
||||
5. **Pull Request**: Submit your changes for review
|
||||
6. **Review**: Address any feedback
|
||||
7. **Merge**: Changes are merged into main branch
|
||||
|
||||
## IDE Setup
|
||||
|
||||
### VS Code
|
||||
|
||||
Recommended settings for `settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"python.linting.pylintEnabled": true,
|
||||
"python.linting.enabled": true,
|
||||
"python.formatting.provider": "black",
|
||||
"python.formatting.blackArgs": ["--line-length", "100"],
|
||||
"editor.formatOnSave": true,
|
||||
"python.testing.pytestEnabled": true,
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.nosetestsEnabled": false,
|
||||
"python.testing.pytestArgs": ["tests"]
|
||||
}
|
||||
```
|
||||
|
||||
### PyCharm
|
||||
|
||||
Recommended settings:
|
||||
- Enable pylint integration
|
||||
- Set code style to PEP 8
|
||||
- Configure pytest as the test runner
|
||||
|
||||
## Pre-Commit Hooks (Future Addition)
|
||||
|
||||
In the future, we'll add pre-commit hooks for:
|
||||
- Code formatting with `black`
|
||||
- Import sorting with `isort`
|
||||
- Linting with `pylint`
|
||||
- Type checking with `mypy`
|
||||
|
||||
## Troubleshooting Development Issues
|
||||
|
||||
### Common Issues and Solutions
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| `ModuleNotFoundError` | Ensure your virtual environment is activated and package is installed with `pip install -e .` |
|
||||
| Import errors | Check your PYTHONPATH and package structure |
|
||||
| API errors | Verify your API key is set correctly |
|
||||
| Permission denied | Check file permissions, especially for executable scripts |
|
||||
|
||||
### Getting Help
|
||||
|
||||
If you encounter issues during development:
|
||||
- Check the documentation
|
||||
- Search for similar issues on GitHub
|
||||
- Ask for help in your pull request
|
||||
- Open a new issue describing your problem
|
||||
Reference in New Issue
Block a user