Initial upload: Git Commit AI - privacy-first CLI for generating commit messages with local LLM
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-01-31 03:00:20 +00:00
parent 44b1479109
commit 1d3230f5f2

View File

@@ -0,0 +1,114 @@
"""Configuration management for Git Commit AI."""
import os
from pathlib import Path
from typing import Any, Optional
import yaml
class Config:
"""Configuration manager that loads from YAML and supports env overrides."""
def __init__(self, config_path: Optional[str] = None):
if config_path is None:
config_path = os.environ.get("CONFIG_PATH", str(Path(".git-commit-ai") / "config.yaml"))
self.config_path = Path(config_path)
self._config: dict[str, Any] = {}
self._load_config()
def _load_config(self) -> None:
if self.config_path.exists():
try:
with open(self.config_path, 'r') as f:
self._config = yaml.safe_load(f) or {}
except yaml.YAMLError as e:
print(f"Warning: Failed to parse config file: {e}")
self._config = {}
else:
self._config = {}
def get(self, key: str, default: Any = None) -> Any:
env_key = key.upper().replace(".", "_")
env_value = os.environ.get(env_key)
if env_value is not None:
return self._parse_env_value(env_value)
keys = key.split(".")
value = self._config
for k in keys:
if isinstance(value, dict):
value = value.get(k)
else:
return default
if value is None:
return default
return value
def _parse_env_value(self, value: str) -> Any:
if value.lower() in ("true", "false"):
return value.lower() == "true"
try:
return int(value)
except ValueError:
pass
try:
return float(value)
except ValueError:
pass
return value
@property
def ollama_model(self) -> str:
return self.get("ollama.model", "qwen2.5-coder:3b")
@property
def ollama_base_url(self) -> str:
return self.get("ollama.base_url", "http://localhost:11434")
@property
def ollama_timeout(self) -> int:
return self.get("ollama.timeout", 120)
@property
def max_message_length(self) -> int:
return self.get("commit.max_length", 80)
@property
def num_suggestions(self) -> int:
return self.get("commit.num_suggestions", 3)
@property
def conventional_by_default(self) -> bool:
return self.get("commit.conventional_by_default", False)
@property
def cache_enabled(self) -> bool:
return self.get("cache.enabled", True)
@property
def cache_directory(self) -> str:
return self.get("cache.directory", ".git-commit-ai/cache")
@property
def cache_ttl_hours(self) -> int:
return self.get("cache.ttl_hours", 24)
@property
def prompt_directory(self) -> str:
return self.get("prompts.directory", ".git-commit-ai/prompts")
@property
def show_diff(self) -> bool:
return self.get("output.show_diff", False)
@property
def interactive(self) -> bool:
return self.get("output.interactive", False)
def reload(self) -> None:
self._load_config()
def get_config(config_path: Optional[str] = None) -> Config:
return Config(config_path)