feat(service): add FastAPI agent service with 5 routers and Docker setup
- config.py: pydantic-settings with all env vars, privacy mode, per-agent overrides - app_state.py: global singletons (pool, master agent, registry, llm_router, sweep) - main.py: FastAPI lifespan startup — DB pool, LLM router, Odoo client, agents, master - routers/dispatch.py: POST /dispatch with rate limiting and webhook secret auth - routers/approval.py: GET /approval/pending, POST /approval/respond - routers/registry.py: GET/POST /registry/agents, POST /registry/backend overrides - routers/sweep.py: POST /sweep trigger, GET /sweep/status - routers/health.py: GET /health, GET /health/detailed (DB/Odoo/Ollama checks) - requirements.txt: pinned deps (fastapi, uvicorn, asyncpg, anthropic, alembic) - Dockerfile: python:3.11-slim, single uvicorn worker - docker-compose.yml: agent-service + postgres:15, bound to 192.168.2.47:8001 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
92
agent_service/config.py
Normal file
92
agent_service/config.py
Normal file
@@ -0,0 +1,92 @@
|
||||
from __future__ import annotations
|
||||
import os
|
||||
from functools import lru_cache
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
# Odoo
|
||||
odoo_url: str = 'http://localhost:8069'
|
||||
odoo_db: str = 'odoo'
|
||||
odoo_api_key: str = ''
|
||||
|
||||
# Ollama
|
||||
ollama_url: str = 'http://localhost:11434'
|
||||
ollama_model: str = 'llama3'
|
||||
ollama_timeout: int = 120
|
||||
|
||||
# Anthropic / Claude
|
||||
anthropic_api_key: str = ''
|
||||
claude_model: str = 'claude-sonnet-4-6'
|
||||
|
||||
# Privacy
|
||||
llm_privacy_mode: str = 'local' # local | hybrid | cloud
|
||||
|
||||
# Per-agent backend overrides (env: AGENT_BACKEND_FINANCE=claude)
|
||||
agent_backend_finance: str = ''
|
||||
agent_backend_accounting: str = ''
|
||||
agent_backend_crm: str = ''
|
||||
agent_backend_sales: str = ''
|
||||
agent_backend_project: str = ''
|
||||
agent_backend_elearning: str = ''
|
||||
agent_backend_expenses: str = ''
|
||||
agent_backend_employees: str = ''
|
||||
|
||||
# Service
|
||||
agent_service_port: int = 8001
|
||||
webhook_secret: str = ''
|
||||
allowed_callback_ip: str = ''
|
||||
|
||||
# Postgres
|
||||
postgres_host: str = 'localhost'
|
||||
postgres_port: int = 5432
|
||||
postgres_db: str = 'activeblue_ai'
|
||||
postgres_user: str = 'activeblue'
|
||||
postgres_password: str = ''
|
||||
postgres_min_connections: int = 2
|
||||
postgres_max_connections: int = 10
|
||||
|
||||
# Rate limiting
|
||||
dispatch_rate_limit_per_user: int = 30 # requests per minute
|
||||
directive_timeout_minutes: int = 10
|
||||
|
||||
# Logging
|
||||
log_level: str = 'INFO'
|
||||
log_format: str = 'json'
|
||||
loki_url: str = ''
|
||||
|
||||
class Config:
|
||||
env_file = '.env'
|
||||
env_file_encoding = 'utf-8'
|
||||
|
||||
@property
|
||||
def postgres_dsn(self) -> str:
|
||||
return (
|
||||
f'postgresql+asyncpg://{self.postgres_user}:{self.postgres_password}'
|
||||
f'@{self.postgres_host}:{self.postgres_port}/{self.postgres_db}'
|
||||
)
|
||||
|
||||
@property
|
||||
def postgres_asyncpg_dsn(self) -> str:
|
||||
return (
|
||||
f'asyncpg://{self.postgres_user}:{self.postgres_password}'
|
||||
f'@{self.postgres_host}:{self.postgres_port}/{self.postgres_db}'
|
||||
)
|
||||
|
||||
def agent_backend_override(self, agent_name: str) -> str:
|
||||
mapping = {
|
||||
'finance_agent': self.agent_backend_finance,
|
||||
'accounting_agent': self.agent_backend_accounting,
|
||||
'crm_agent': self.agent_backend_crm,
|
||||
'sales_agent': self.agent_backend_sales,
|
||||
'project_agent': self.agent_backend_project,
|
||||
'elearning_agent': self.agent_backend_elearning,
|
||||
'expenses_agent': self.agent_backend_expenses,
|
||||
'employees_agent': self.agent_backend_employees,
|
||||
}
|
||||
return mapping.get(agent_name, '')
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def get_settings() -> Settings:
|
||||
return Settings()
|
||||
Reference in New Issue
Block a user