Add CLI commands and Gitea Actions workflow
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled

This commit is contained in:
2026-01-31 15:27:58 +00:00
parent f9a9bfa43f
commit 543058584e

View File

@@ -0,0 +1,201 @@
"""Explain command for Local Code Assistant."""
from pathlib import Path
from typing import Optional
import click
from rich.console import Console
from rich.markdown import Markdown
from rich.panel import Panel
from local_code_assistant.commands.base import BaseCommand
from local_code_assistant.prompts.templates import LanguageConfig, PromptTemplates
from local_code_assistant.services.ollama import OllamaService
console = Console()
class ExplainCommand(BaseCommand):
"""Command for explaining code."""
def __init__(self, ollama: OllamaService, config):
"""Initialize explain command.
Args:
ollama: Ollama service instance.
config: Configuration service instance.
"""
super().__init__(ollama, config)
self.supported_languages = LanguageConfig.get_supported_languages()
def run(
self,
code: str,
language: Optional[str] = None,
format_markdown: bool = False
) -> str:
"""Execute code explanation.
Args:
code: Code to explain.
language: Programming language (auto-detected if not provided).
format_markdown: Whether to format as markdown.
Returns:
Explanation text.
"""
if not self.ollama.check_connection():
raise click.ClickException(
"Cannot connect to Ollama. Make sure it's running."
)
if language is None:
language = self._detect_language(code)
if language not in self.supported_languages:
language = "text"
console.print("[dim]Analyzing code...[/dim]")
full_prompt = PromptTemplates.code_explanation(
language=language,
code=code
)
system_prompt = PromptTemplates.build_system_prompt(
"You are explaining code to a developer. Be clear and concise."
)
try:
explanation = self.ollama.generate(
prompt=full_prompt,
model=self._get_model(),
system=system_prompt,
temperature=self._get_temperature(0.3)
)
self._display_output(explanation, format_markdown)
return explanation
except Exception as e:
raise click.ClickException(f"Explanation failed: {str(e)}") from e
def run_file(
self,
file: Path,
format_markdown: bool = False
) -> str:
"""Explain code from a file.
Args:
file: Path to file.
format_markdown: Whether to format as markdown.
Returns:
Explanation text.
"""
if not file.exists():
raise click.ClickException(f"File not found: {file}")
code = file.read_text()
language = self._detect_language_from_file(file)
return self.run(code, language, format_markdown)
def _detect_language(self, code: str) -> str:
"""Detect programming language from code content.
Args:
code: Source code.
Returns:
Detected language.
"""
if "def " in code or "import " in code or "class " in code:
return "python"
elif "function " in code or "const " in code or "let " in code:
return "javascript"
elif "interface " in code or "type " in code or ": string" in code:
return "typescript"
elif "func " in code or "package " in code:
return "go"
elif "fn " in code or "let " in code or "struct " in code:
return "rust"
return "text"
def _detect_language_from_file(self, file: Path) -> str:
"""Detect language from file extension.
Args:
file: File path.
Returns:
Language name.
"""
suffix = file.suffix.lower()
language_map = {
".py": "python",
".js": "javascript",
".ts": "typescript",
".tsx": "typescript",
".go": "go",
".rs": "rust"
}
return language_map.get(suffix, "text")
def _display_output(self, explanation: str, as_markdown: bool):
"""Display explanation.
Args:
explanation: Explanation text.
as_markdown: Whether to render as markdown.
"""
if as_markdown:
console.print(Panel(Markdown(explanation), title="Explanation"))
else:
console.print(Panel(explanation, title="Explanation"))
@click.command()
@click.argument("file", type=click.Path(exists=True, path_type=Path))
@click.option(
"--language", "-l",
type=click.Choice(LanguageConfig.get_supported_languages()),
default=None,
help="Programming language (auto-detected if not specified)"
)
@click.option(
"--markdown/--no-markdown",
default=False,
help="Format output as markdown"
)
@click.pass_context
def explain_cmd(
ctx: click.Context,
file: Path,
language: Optional[str],
markdown: bool
):
"""Explain code from a file.
Example:
local-code-assistant explain script.py
local-code-assistant explain app.ts --markdown
\f
Args:
ctx: Click context.
file: Path to file to explain.
language: Programming language.
markdown: Format as markdown.
"""
config = ctx.obj["config"]
ollama_service = OllamaService(config)
ctx.obj["ollama_service"] = ollama_service
command = ExplainCommand(ollama_service, config)
command.run_file(file, markdown)