diff --git a/.clinerules b/.clinerules new file mode 100644 index 0000000..9f47cdc --- /dev/null +++ b/.clinerules @@ -0,0 +1,35 @@ +# abc/.clinerules + +- Always read these files to understand the project and the layout: + + - `README.md` + - always run this at the beginning of a project to understand the Git repo layout: `make tree` + - read files referenced in the above as appropriate for the task at hand + +- When working on a GitHub issue, follow standard best practices with a branch name like: + `issue-NN-{fix,feature}-description-$(date _%Y%m%d) + +- Use the `git` and `gh` CLIs where it makes sense. + +- When an update is complete, the software version can be updated in these five files: + + - `abc_provider_anthropic/pyproject.toml` + - `pyproject.toml` + - `abc_cli/abc_generate.py` + - `README.md` + - `../getabc.sh/app/components/OpenSource.tsx` + +- Uninstall + + ```bash + abc_setup --uninstall --no-prompt && + pipx uninstall abc-cli + ``` + +- Install for development (editable mode) + + ```bash + pipx install -e . && + pipx inject abc-cli -e ./abc_provider_anthropic && + abc_setup --no-prompt + ``` diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a28290b --- /dev/null +++ b/.gitignore @@ -0,0 +1,47 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual Environment +venv/ +env/ +ENV/ +.env/ +.venv/ + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Project specific +work/ +*.log +.coverage +htmlcov/ +.pytest_cache/ +.tox/ diff --git a/INSTALL.md b/INSTALL.md index 8e0f3c3..3dd2a5f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -7,7 +7,18 @@ This guide provides instructions for installing abc on your system using pipx. - Linux or macOS - Python 3.8 or higher - bash 4.4+, zsh 5.0+, or tcsh 6.0+ -- An API key for the Claude AI model from Anthropic +- An API key for your chosen LLM provider (default: Anthropic) + +## LLM Providers + +abc uses a plugin system for LLM providers. The default installation includes: + +- Anthropic LLM provider (Claude) + +Additional providers can be installed using: +```bash +pipx inject abc-cli abc-provider-NAME +``` ## Easy Installation @@ -80,15 +91,17 @@ This guide provides instructions for installing abc on your system using pipx. ```bash pipx install git+https://github.com/alestic/abc.git + pipx inject abc-cli abc-provider-anthropic@git+https://github.com/alestic/abc.git#subdirectory=abc_provider_anthropic abc_setup ``` - Alternative: + Alternative (for development): ```bash git clone https://github.com/alestic/abc.git cd abc - pipx install . + pipx install -e . + pipx inject abc-cli -e ./abc_provider_anthropic abc_setup ``` diff --git a/abc_cli/__init__.py b/abc_cli/__init__.py index e69de29..818993b 100644 --- a/abc_cli/__init__.py +++ b/abc_cli/__init__.py @@ -0,0 +1,4 @@ +"""abc-cli - AI Bash Command Generator.""" +from .llm_provider import LLMProvider + +__all__ = ['LLMProvider'] diff --git a/abc_cli/abc_generate.py b/abc_cli/abc_generate.py index dfb1746..cf68146 100755 --- a/abc_cli/abc_generate.py +++ b/abc_cli/abc_generate.py @@ -21,10 +21,13 @@ from typing import Dict import re import distro +from importlib import metadata -from .providers import LLMProvider -from .providers.anthropic import AnthropicProvider -from .providers.prompts import get_system_prompt +from . import LLMProvider +from .prompts import get_system_prompt + +# Entry point group for LLM providers +PROVIDER_ENTRY_POINT = 'abc.llm_providers' VERSION: str = "# 2024.12.15" PROGRAM_NAME: str = "abc" @@ -92,7 +95,23 @@ def get_provider(config: Dict[str, str]) -> LLMProvider: Currently defaults to Anthropic provider for backward compatibility. Will be enhanced to support provider selection in the future. """ - return AnthropicProvider(config) + # For now, hardcode to anthropic for backward compatibility + provider_name = 'anthropic' + + try: + # Find the provider entry point + eps = metadata.entry_points().select(group=PROVIDER_ENTRY_POINT) + provider_ep = next(ep for ep in eps if ep.name == provider_name) + + # Load the provider class + provider_class = provider_ep.load() + return provider_class(config) + + except (StopIteration, metadata.PackageNotFoundError): + raise ValueError( + f"Provider '{provider_name}' not found. " + f"Please install abc-provider-{provider_name} package." + ) def process_generated_command(command: str) -> str: """Process the generated command based on its danger level.""" diff --git a/abc_cli/providers/__init__.py b/abc_cli/llm_provider.py similarity index 95% rename from abc_cli/providers/__init__.py rename to abc_cli/llm_provider.py index 29ad469..266172d 100644 --- a/abc_cli/providers/__init__.py +++ b/abc_cli/llm_provider.py @@ -1,4 +1,4 @@ -"""Provider interface for abc LLM integrations.""" +"""Core interface definition for abc LLM providers.""" # NOTE! The `abc`/`ABC` module is part of the Python standard library and should not be confused with the `abc` command and `abc-cli` package. diff --git a/abc_cli/providers/prompts.py b/abc_cli/prompts.py similarity index 100% rename from abc_cli/providers/prompts.py rename to abc_cli/prompts.py diff --git a/abc_provider_anthropic/README.md b/abc_provider_anthropic/README.md new file mode 100644 index 0000000..800764a --- /dev/null +++ b/abc_provider_anthropic/README.md @@ -0,0 +1,23 @@ +# abc-provider-anthropic + +Anthropic LLM provider for [abc-cli](https://github.com/alestic/abc). + +## Configuration + +In your `~/.abc.conf`: + +```ini +[default] +api_key = {ANTHROPIC_API_KEY} + +# Optional settings: +model = claude-3-5-sonnet-20241022 +temperature = 0.0 +max_tokens = 1000 +``` + +Get your Anthropic API key from the [Anthropic Console](https://console.anthropic.com/settings/keys). + +## License + +Apache 2.0 - See [LICENSE](../LICENSE) diff --git a/abc_provider_anthropic/abc_provider_anthropic/__init__.py b/abc_provider_anthropic/abc_provider_anthropic/__init__.py new file mode 100644 index 0000000..943d114 --- /dev/null +++ b/abc_provider_anthropic/abc_provider_anthropic/__init__.py @@ -0,0 +1,5 @@ +"""Anthropic LLM provider package.""" + +from .llm_provider import AnthropicProvider + +__all__ = ['AnthropicProvider'] diff --git a/abc_cli/providers/anthropic.py b/abc_provider_anthropic/abc_provider_anthropic/llm_provider.py similarity index 93% rename from abc_cli/providers/anthropic.py rename to abc_provider_anthropic/abc_provider_anthropic/llm_provider.py index b8a304e..5eff919 100644 --- a/abc_cli/providers/anthropic.py +++ b/abc_provider_anthropic/abc_provider_anthropic/llm_provider.py @@ -3,7 +3,7 @@ import anthropic from typing import Dict, Any -from . import LLMProvider +from abc_cli import LLMProvider DEFAULT_MODEL = 'claude-3-5-sonnet-20241022' DEFAULT_TEMPERATURE = 0.0 @@ -62,17 +62,17 @@ def get_config_schema(self) -> Dict: "model": { "type": "string", "description": "Claude model to use", - "default": "claude-3-5-sonnet-20241022" + "default": DEFAULT_MODEL }, "temperature": { "type": "string", "description": "Sampling temperature", - "default": "0.0" + "default": DEFAULT_TEMPERATURE }, "max_tokens": { "type": "string", "description": "Maximum tokens in response", - "default": "1000" + "default": DEFAULT_MAX_TOKENS } }, "required": ["api_key"] diff --git a/abc_provider_anthropic/pyproject.toml b/abc_provider_anthropic/pyproject.toml new file mode 100644 index 0000000..2076f65 --- /dev/null +++ b/abc_provider_anthropic/pyproject.toml @@ -0,0 +1,21 @@ +[project] +name = "abc-provider-anthropic" +version = "2024.12.15" +description = "Anthropic LLM provider for abc-cli" +readme = "README.md" +requires-python = ">=3.8" +license = "Apache-2.0" +authors = [ + { name = "Claude 3.5 Sonnet", email = "" }, + { name = "Eric Hammond", email = "" } +] +dependencies = [ + "anthropic==0.40.0" +] + +[project.entry-points."abc.llm_providers"] +anthropic = "abc_provider_anthropic:AnthropicProvider" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" diff --git a/install_from_github.sh b/install_from_github.sh index c4a6f15..cb01eb9 100755 --- a/install_from_github.sh +++ b/install_from_github.sh @@ -170,6 +170,8 @@ main() { log "abc is already installed, attempting upgrade..." if [[ "$(prompt_user "About to upgrade abc via pipx. Continue?" "y")" = "yes" ]]; then pipx upgrade abc-cli || error "Failed to upgrade abc" + log "Upgrading Anthropic provider..." + pipx inject abc-cli abc-provider-anthropic@git+https://github.com/alestic/abc.git#subdirectory=abc_provider_anthropic $FORCE_OPTION || error "Failed to upgrade Anthropic provider" else log "Upgrade cancelled by user" exit 0 @@ -178,6 +180,8 @@ main() { log "Installing abc from GitHub..." if [[ "$(prompt_user "About to install abc via pipx. Continue?" "y")" = "yes" ]]; then pipx install git+https://github.com/alestic/abc.git $FORCE_OPTION || error "Failed to install abc via pipx" + log "Installing Anthropic provider..." + pipx inject abc-cli abc-provider-anthropic@git+https://github.com/alestic/abc.git#subdirectory=abc_provider_anthropic $FORCE_OPTION || error "Failed to install Anthropic provider" else log "Installation cancelled by user" exit 0 diff --git a/pyproject.toml b/pyproject.toml index 704bee8..47d1395 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,6 @@ authors = [ { name = "Eric Hammond", email = "" } ] dependencies = [ - "anthropic==0.40.0", "readchar==4.1.0", "distro==1.8.0", "prompt_toolkit==3.0.47" @@ -35,3 +34,6 @@ packages = ["abc_cli"] "abc_cli/abc.sh" = "abc_cli/abc.sh" "abc_cli/abc.tcsh" = "abc_cli/abc.tcsh" "abc_cli/abc.conf.template" = "abc_cli/abc.conf.template" + +[tool.hatch.metadata] +allow-direct-references = true