- Updated .env.example to include Asterisk templates path. - Modified docker-compose.yml to mount the templates directory. - Enhanced backend Dockerfile to copy templates into the container. - Introduced Asterisk diagnostics functionality in asterisk_profiles.py, allowing for baseline checks and diagnostics reporting. - Integrated Asterisk diagnostics into the device diagnostics workflow in graph.py. - Added formatting for Asterisk baseline drift reports in diagnostic_format.py. - Updated SKILL.md to document new config baseline drift feature for Asterisk. This commit enhances the system's capabilities for managing Asterisk configurations and diagnostics, improving overall troubleshooting processes.
125 lines
4.7 KiB
Python
125 lines
4.7 KiB
Python
"""Application configuration, loaded from environment variables."""
|
|
from __future__ import annotations
|
|
|
|
from functools import lru_cache
|
|
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
model_config = SettingsConfigDict(env_file=".env", extra="ignore", case_sensitive=False)
|
|
|
|
# Core security
|
|
secret_key: str = "dev-insecure-secret-change-me"
|
|
credential_encryption_key: str = ""
|
|
access_token_expire_minutes: int = 60 * 12
|
|
algorithm: str = "HS256"
|
|
|
|
first_admin_email: str = "admin@agentic.local"
|
|
first_admin_password: str = "changeme"
|
|
|
|
# Database / cache
|
|
database_url: str = "postgresql+asyncpg://agentic:agentic@postgres:5432/agentic_os"
|
|
redis_url: str = "redis://redis:6379/0"
|
|
|
|
# CORS: comma-separated allowed browser origins (no wildcard with credentials).
|
|
cors_allow_origins: str = "http://localhost:3000"
|
|
|
|
# LLM routing
|
|
litellm_base_url: str = "http://litellm:4000"
|
|
litellm_master_key: str = "sk-litellm-master-change-me"
|
|
ollama_base_url: str = "http://host.docker.internal:11434"
|
|
local_triage_model: str = "qwen2.5:7b-instruct"
|
|
cloud_reasoning_model: str = "openrouter/deepseek/deepseek-chat"
|
|
|
|
# Tiered LLM routing (local → gemini → deepseek → openrouter)
|
|
llm_local_model: str = "qwen2.5:7b-instruct"
|
|
llm_economy_gemini: str = "gemini-2.5-flash"
|
|
llm_economy_deepseek: str = "deepseek-chat"
|
|
llm_economy_openrouter: str = "deepseek/deepseek-chat"
|
|
llm_premium_gemini: str = "gemini-2.5-pro"
|
|
llm_premium_deepseek: str = "deepseek-reasoner"
|
|
llm_premium_openrouter: str = "anthropic/claude-3.5-sonnet"
|
|
llm_auto_escalate: bool = True
|
|
llm_max_tier: str = "premium"
|
|
llm_cloud_provider_order: str = "gemini,deepseek,openrouter"
|
|
|
|
# Cloud API keys
|
|
gemini_api_key: str = ""
|
|
openrouter_api_key: str = ""
|
|
openrouter_provisioning_key: str = ""
|
|
deepseek_api_key: str = ""
|
|
|
|
# Balance polling
|
|
balance_poll_interval_seconds: int = 900
|
|
min_balance_usd: float = 1.0
|
|
|
|
# Gitea / MCP repos
|
|
gitea_base_url: str = "http://10.77.30.250:3000"
|
|
gitea_username: str = "nearxos"
|
|
gitea_token: str = ""
|
|
mcp_repos: str = "ssh-generic-mcp,fortigate-mcp,fortiswitch-mcp,pfsense-mcp,proxmox-mcp,asterisk-mcp"
|
|
|
|
# Obsidian
|
|
obsidian_vault_repo: str = "homelab-vault"
|
|
obsidian_tasks_folder: str = "agentic-os-tasks"
|
|
obsidian_auto_push: bool = True
|
|
|
|
# Project memory MCP
|
|
memory_mcp_url: str = "http://10.77.30.184:8787/mcp"
|
|
memory_mcp_token: str = ""
|
|
memory_task_project_id: str = "agentic-os-task"
|
|
memory_search_projects: str = "agentic-os-task,agentic-os,global"
|
|
obsidian_search_paths: str = "agentic-os-tasks,Meta/Agent-Memory"
|
|
|
|
# Troubleshooting decision rules (YAML, editable via Admin → Rules)
|
|
troubleshooting_rules_path: str = "/app/rules/troubleshooting.yaml"
|
|
|
|
# Agent skills (procedural guides in skills/*/SKILL.md)
|
|
skills_path: str = "/app/skills"
|
|
skills_max_matched: int = 2
|
|
skills_max_body_chars: int = 8000
|
|
|
|
# Asterisk golden config templates (templates/asterisk/<profile>/manifest.yaml)
|
|
asterisk_templates_path: str = "/app/templates/asterisk"
|
|
|
|
# Runtime paths (inside container)
|
|
runtime_dir: str = "/runtime"
|
|
|
|
# MCP self-development: agent patches MCP source on tool failure / missing capability
|
|
mcp_development_enabled: bool = True
|
|
mcp_dev_require_approval: bool = True # when true, apply/reload waits for human approval
|
|
mcp_dev_auto_push: bool = False # when false, patch applies + reload; git push needs approval
|
|
mcp_dev_model_tier: str = "premium"
|
|
|
|
# Worker: max tasks executed in parallel (MCP sessions are shared — use 1 for same-vessel safety)
|
|
worker_max_concurrent_tasks: int = 1
|
|
|
|
@property
|
|
def cors_origin_list(self) -> list[str]:
|
|
return [o.strip() for o in self.cors_allow_origins.split(",") if o.strip()]
|
|
|
|
@property
|
|
def mcp_repo_list(self) -> list[str]:
|
|
return [r.strip() for r in self.mcp_repos.split(",") if r.strip()]
|
|
|
|
def gitea_clone_url(self, repo: str) -> str:
|
|
"""Authenticated clone URL for a Gitea repo (preserves http/https from base URL)."""
|
|
base = self.gitea_base_url.rstrip("/")
|
|
if self.gitea_token:
|
|
from urllib.parse import urlparse
|
|
|
|
parsed = urlparse(base if "://" in base else f"http://{base}")
|
|
scheme = parsed.scheme or "http"
|
|
host = parsed.netloc or parsed.path
|
|
return f"{scheme}://{self.gitea_username}:{self.gitea_token}@{host}/{self.gitea_username}/{repo}.git"
|
|
return f"{base}/{self.gitea_username}/{repo}.git"
|
|
|
|
|
|
@lru_cache
|
|
def get_settings() -> Settings:
|
|
return Settings()
|
|
|
|
|
|
settings = get_settings()
|