Add templates and MCP server modules
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled

This commit is contained in:
2026-01-29 13:25:00 +00:00
parent 32fc493a90
commit 3178ac8dde

View File

@@ -0,0 +1,346 @@
"""Template engine using Jinja2 for rendering."""
from pathlib import Path
from typing import Any
from jinja2 import BaseLoader, Environment, FileSystemLoader, TemplateSyntaxError, UndefinedError
class TemplateEngine:
"""Jinja2-based template engine for rendering context output."""
BUILTIN_TEMPLATES = {
"minimal": """# Project Context
## Overview
{{ project.name }}
{{ project.description }}
## Tech Stack
{% for lang, details in analysis.languages.items() %}
- {{ lang }}: {{ details.file_count }} files
{% endfor %}
## Key Files
{% for file, desc in structure.key_files.items() %}
- {{ file }}: {{ desc }}
{% endfor %}
""",
"standard": """# Project Context
## Overview
- **Project**: {{ project.name }}
- **Description**: {{ project.description }}
- **Primary Language**: {{ analysis.primary_language }}
- **Generated**: {{ timestamp }}
## Tech Stack
### Languages
{% for lang, details in analysis.languages.items() %}
- **{{ lang }}**: {{ details.file_count }} files
{% endfor %}
### Frameworks
{% if analysis.frameworks %}
{% for fw in analysis.frameworks %}
- {{ fw.name }} (confidence: {{ (fw.confidence * 100)|round(1) }}%)
{% endfor %}
{% else %}
- No frameworks detected
{% endif %}
### Build Tools
{% if analysis.build_tools %}
{% for tool in analysis.build_tools %}
- {{ tool.name }} (confidence: {{ (tool.confidence * 100)|round(1) }}%)
{% endfor %}
{% else %}
- No build tools detected
{% endif %}
## Project Structure
### Key Files
{% for file, desc in structure.key_files.items() %}
- `{{ file }}`: {{ desc }}
{% endfor %}
### Directory Tree
```
{% for dir, contents in structure.file_tree.directories.items() %}
{{ dir }}
{% for subdir, subcontents in contents.directories.items() %}
{{ subdir }}
{% endfor %}
{% endfor %}
```
## Coding Conventions
### Naming Style
- **Functions**: {{ conventions.naming.functions.dominant }}
- **Classes**: {{ conventions.naming.classes.dominant }}
- **Variables**: {{ conventions.naming.variables.dominant }}
- **Files**: {{ conventions.naming.files.pattern }}
### Code Style
- **Indentation**: {{ conventions.style.indentation.style }} ({{ conventions.style.indentation.width }} spaces)
- **Quote Style**: {{ conventions.style.quote_style.style }}
- **Line Endings**: {{ conventions.style.line_endings.style }}
### Documentation
- **Style**: {{ conventions.documentation.style }}
- **Coverage**: {{ (conventions.documentation.documentation_coverage.ratio * 100)|round(1) }}%
## Setup Instructions
{% if setup.install_commands %}
### Installation
{% for cmd in setup.install_commands %}
```
{{ cmd }}
```
{% endfor %}
{% endif %}
{% if setup.run_commands %}
### Running
{% for cmd in setup.run_commands %}
```
{{ cmd }}
```
{% endfor %}
{% endif %}
{% if setup.test_commands %}
### Testing
{% for cmd in setup.test_commands %}
```
{{ cmd }}
```
{% endfor %}
{% endif %}
{% if setup.environment_variables %}
### Environment Variables
{% for var in setup.environment_variables %}
- `{{ var }}`
{% endfor %}
{% endif %}
""",
"comprehensive": """# Project Context - Comprehensive Analysis
## Metadata
- **Project Name**: {{ project.name }}
- **Description**: {{ project.description }}
- **Primary Language**: {{ analysis.primary_language }}
- **Total Files**: {{ structure.total_files }}
- **Total Directories**: {{ structure.total_dirs }}
- **Generated**: {{ timestamp }}
---
## 1. Technology Stack
### 1.1 Languages Detected
| Language | Files | Extensions |
|----------|-------|------------|
{% for lang, details in analysis.languages.items() %}
| {{ lang }} | {{ details.file_count }} | {{ details.extensions|join(', ') }} |
{% endfor %}
### 1.2 Frameworks & Libraries
{% if analysis.frameworks %}
| Framework | Confidence | Indicators |
|-----------|------------|------------|
{% for fw in analysis.frameworks %}
| {{ fw.name }} | {{ (fw.confidence * 100)|round(1) }}% | {{ fw.indicators_found }} |
{% endfor %}
{% else %}
No frameworks detected.
{% endif %}
### 1.3 Build Tools
{% if analysis.build_tools %}
| Tool | Confidence |
|------|------------|
{% for tool in analysis.build_tools %}
| {{ tool.name }} | {{ (tool.confidence * 100)|round(1) }}% |
{% endfor %}
{% else %}
No build tools detected.
{% endif %}
### 1.4 Full Stack
{% if analysis.full_stack %}
- **Frontend**: {{ analysis.full_stack.frontend or 'Not detected' }}
- **Backend**: {{ analysis.full_stack.backend or 'Not detected' }}
{% else %}
No clear full stack detected.
{% endif %}
---
## 2. Project Structure
### 2.1 Key Files
| File | Description |
|------|-------------|
{% for file, desc in structure.key_files.items() %}
| `{{ file }}` | {{ desc }} |
{% endfor %}
### 2.2 File Statistics
- **Total Files**: {{ structure.total_files }}
- **Total Directories**: {{ structure.total_dirs }}
### 2.3 Directory Tree
```
{{ project.path }}
{% for dir, contents in structure.file_tree.directories.items() %}
├── {{ dir }}
{% for subdir, subcontents in contents.directories.items() %}
│ ├── {{ subdir }}
{% endfor %}
{% endfor %}
```
---
## 3. Coding Conventions
### 3.1 Naming Conventions
| Type | Dominant Style | Examples |
|------|----------------|----------|
| Functions | {{ conventions.naming.functions.dominant }} | {{ conventions.naming.functions.examples[:3]|join(', ') }} |
| Classes | {{ conventions.naming.classes.dominant }} | {{ conventions.naming.classes.examples[:3]|join(', ') }} |
| Variables | {{ conventions.naming.variables.dominant }} | {{ conventions.naming.variables.examples[:3]|join(', ') }} |
| Constants | {{ conventions.naming.constants.dominant }} | {{ conventions.naming.constants.examples[:3]|join(', ') }} |
| Files | {{ conventions.naming.files.pattern }} | {{ conventions.naming.files.examples[:3]|join(', ') }} |
### 3.2 Code Style
| Aspect | Value |
|--------|-------|
| Indentation | {{ conventions.style.indentation.style }} ({{ conventions.style.indentation.width }} spaces) |
| Quote Style | {{ conventions.style.quote_style.style }} |
| Line Endings | {{ conventions.style.line_endings.style }} |
| Max Line Length | {{ conventions.style.max_line_length.max }} characters |
| Trailing Newline | {{ 'Yes' if conventions.style.trailing_newline.has_trailing_newline else 'No' }} |
### 3.3 Documentation
| Aspect | Value |
|--------|-------|
| Docstring Style | {{ conventions.documentation.style }} |
| Coverage | {{ (conventions.documentation.documentation_coverage.ratio * 100)|round(1) }}% |
| Comment Style | {{ conventions.documentation.comment_style.dominant }} |
---
## 4. Setup Instructions
### 4.1 Installation
{% for cmd in setup.install_commands %}
```bash
{{ cmd }}
```
{% endfor %}
### 4.2 Build
{% for cmd in setup.build_commands %}
```bash
{{ cmd }}
```
{% endfor %}
### 4.3 Running
{% for cmd in setup.run_commands %}
```bash
{{ cmd }}
```
{% endfor %}
### 4.4 Testing
{% for cmd in setup.test_commands %}
```bash
{{ cmd }}
```
{% endfor %}
### 4.5 Environment Variables
{% for var in setup.environment_variables %}
- `{{ var }}`
{% endfor %}
### 4.6 Notes
{% for note in setup.notes %}
- {{ note }}
{% endfor %}
---
## 5. AI Assistant Tips
When working with this codebase:
1. **Naming**: The project uses {{ conventions.naming.dominant_style }} naming conventions.
2. **Documentation**: Docstrings follow {{ conventions.documentation.style }} style.
3. **Setup**: Run `{{ setup.install_commands[0] if setup.install_commands else 'appropriate install command' }}` to get started.
4. **Language**: Primary language is {{ analysis.primary_language }}.
---
*Generated by Project Context Generator*
""",
}
def __init__(self, template_path: Path | None = None):
self.template_path = template_path
self.env = self._create_environment()
def _create_environment(self) -> Environment:
"""Create Jinja2 environment."""
if self.template_path and self.template_path.exists():
loader: BaseLoader = FileSystemLoader(str(self.template_path))
else:
loader = DummyLoader(self.BUILTIN_TEMPLATES)
return Environment(
loader=loader,
trim_blocks=True,
lstrip_blocks=True,
)
def render(
self, template_name: str, context: dict[str, Any]
) -> str:
"""Render a template with the given context."""
try:
template = self.env.get_template(template_name)
return template.render(**context)
except (TemplateSyntaxError, UndefinedError) as e:
raise ValueError(f"Template error: {e}")
def get_available_templates(self) -> list[str]:
"""Get list of available templates."""
return list(self.BUILTIN_TEMPLATES.keys())
def list_templates(self) -> list[str]:
"""List all available template names."""
return self.get_available_templates()
class DummyLoader(BaseLoader):
"""Dummy loader for builtin templates."""
def __init__(self, templates: dict[str, str]):
self.templates = templates
def get_source(self, environment: Environment, template: str) -> tuple[str, str, None]:
if template in self.templates:
return self.templates[template], template, None
raise FileNotFoundError(f"Template {template} not found")
def list_templates(self) -> list[str]:
return list(self.templates.keys())