Introduces home automation endpoints for the Tatlock Housekeeper agent: - Device discovery and control (turn_on, turn_off, toggle, set_brightness) - Scene activation and script execution - Automation management (enable/disable) - State history queries and area discovery Includes Home Assistant REST client and configuration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
199 lines
7.0 KiB
Python
199 lines
7.0 KiB
Python
"""
|
|
Main FastAPI application for Core Code API
|
|
"""
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
from contextlib import asynccontextmanager
|
|
|
|
from src.config import get_settings
|
|
from src.logging_config import setup_logging, get_logger
|
|
from src.models.ollama_client import get_ollama_client, close_ollama_client
|
|
from src.controllers.infrastructure_controller import infrastructure_controller
|
|
from src.controllers.tools_controller import tools_controller
|
|
from src.controllers.health_controller import health_controller
|
|
from src.controllers.static_controller import static_controller
|
|
from src.controllers.ai_controller import router as ai_router
|
|
from src.controllers.housekeeping_controller import housekeeping_controller
|
|
from src.security import initialize_oidc
|
|
|
|
# Initialize settings
|
|
settings = get_settings()
|
|
|
|
# Setup logging
|
|
setup_logging(settings.log_level)
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
"""
|
|
Application lifespan manager for startup/shutdown events
|
|
|
|
Args:
|
|
app: FastAPI application instance
|
|
"""
|
|
# Startup
|
|
logger.info("=" * 60)
|
|
logger.info(f"Starting {settings.app_name} v{settings.app_version}")
|
|
logger.info(f"Debug mode: {settings.debug}")
|
|
logger.info(f"Log level: {settings.log_level}")
|
|
logger.info(f"Ollama URL: {settings.ollama_base_url}")
|
|
logger.info("=" * 60)
|
|
|
|
# Check Ollama connectivity
|
|
ollama_client = get_ollama_client()
|
|
ollama_healthy = await ollama_client.health_check()
|
|
if ollama_healthy:
|
|
logger.info("✓ Ollama connection successful")
|
|
else:
|
|
logger.warning("✗ Ollama connection failed - AI features may not work")
|
|
|
|
# Initialize security (OIDC authentication)
|
|
initialize_oidc(settings)
|
|
|
|
yield
|
|
|
|
# Shutdown
|
|
logger.info("Shutting down application")
|
|
await close_ollama_client()
|
|
|
|
|
|
# Create FastAPI application
|
|
app = FastAPI(
|
|
title=settings.app_name,
|
|
version=settings.app_version,
|
|
description="""
|
|
Core Code API provides OpenAPI-compatible functions and AI orchestration for Open WebUI.
|
|
|
|
## Features
|
|
|
|
### OpenAI-Compatible API (v1)
|
|
- `/v1/chat/completions` - Chat completions with streaming support
|
|
- `/v1/models` - List available models
|
|
Compatible with OpenAI client libraries and Open WebUI.
|
|
|
|
### Conversation Memory (Phase 2)
|
|
- `/v1/conversations/{id}` - Get conversation history
|
|
- `/v1/conversations/{id}/search` - Semantic search within conversation
|
|
- `/v1/conversations/search` - Search across all conversations
|
|
- `/v1/conversations/{id}/stats` - Get conversation statistics
|
|
- `/v1/conversations/{id}/consolidate` - Manual consolidation
|
|
- `DELETE /v1/conversations/{id}` - Delete conversation
|
|
|
|
Multi-tier memory system:
|
|
- **Tier 1**: Fast in-memory buffer (last 10 turns)
|
|
- **Tier 2/3**: Unified Qdrant storage (persistent + semantic search)
|
|
|
|
### Infrastructure Management
|
|
**Read Endpoints:**
|
|
- `GET /infrastructure/health` - Check Portainer & NPM connectivity
|
|
- `GET /infrastructure/services` - List all deployed services
|
|
- `GET /infrastructure/services/{name}` - Get service details
|
|
- `GET /infrastructure/ports` - List allocated ports
|
|
- `GET /infrastructure/domains` - List configured domains
|
|
|
|
**Write Endpoints (Admin Only):**
|
|
- `POST /infrastructure/services` - Deploy new service from compose YAML
|
|
- `PUT /infrastructure/services/{name}` - Update existing service
|
|
- `DELETE /infrastructure/services/{name}` - Remove service and stack
|
|
- `POST /infrastructure/proxy` - Create proxy host with optional SSL
|
|
|
|
Automates infrastructure operations via Portainer and Nginx Proxy Manager APIs.
|
|
|
|
### Home Automation (Housekeeping)
|
|
**Read Endpoints:**
|
|
- `GET /housekeeping/health` - Check Home Assistant connectivity
|
|
- `GET /housekeeping/devices` - List devices (filter by domain, area)
|
|
- `GET /housekeeping/devices/{entity_id}` - Get device details
|
|
- `GET /housekeeping/areas` - List areas/rooms
|
|
- `GET /housekeeping/scenes` - List scenes
|
|
- `GET /housekeeping/scripts` - List scripts
|
|
- `GET /housekeeping/automations` - List automations
|
|
- `GET /housekeeping/history` - Get state history
|
|
|
|
**Write Endpoints (Admin Only):**
|
|
- `POST /housekeeping/devices/{entity_id}/control` - Control device
|
|
- `POST /housekeeping/scenes/{scene_id}/activate` - Activate scene
|
|
- `POST /housekeeping/scripts/{script_id}/run` - Run script
|
|
- `POST /housekeeping/automations/{automation_id}/toggle` - Enable/disable automation
|
|
|
|
Abstracts Home Assistant for the Tatlock Housekeeper agent and other consumers.
|
|
|
|
### Web Scraper
|
|
Intelligent web scraping with main content extraction.
|
|
Perfect for extracting articles, documentation, and blog posts for LLM consumption.
|
|
|
|
## Authentication
|
|
|
|
When OIDC authentication is enabled (oidc_enabled=true in config):
|
|
- Infrastructure write endpoints require authentication
|
|
- Use OAuth2/OIDC bearer token from Authentik
|
|
- Admin group membership required for infrastructure operations
|
|
|
|
## Integration
|
|
|
|
This API is designed to integrate with:
|
|
- **Open WebUI**: Direct OpenAI API compatibility
|
|
- **Open WebUI Functions**: Import via OpenAPI spec
|
|
- **Open WebUI Pipelines**: Use as data source
|
|
- **LangChain**: Compatible with standard HTTP tools
|
|
|
|
## Documentation
|
|
|
|
- **OpenAPI Spec**: `/openapi.json`
|
|
- **Swagger UI**: `/docs`
|
|
- **ReDoc**: `/redoc`
|
|
""",
|
|
docs_url="/docs",
|
|
redoc_url="/redoc",
|
|
openapi_url="/openapi.json",
|
|
lifespan=lifespan,
|
|
debug=settings.debug,
|
|
swagger_ui_init_oauth={
|
|
"clientId": settings.oidc_audience,
|
|
"usePkceWithAuthorizationCodeGrant": True,
|
|
} if settings.oidc_enabled else None
|
|
)
|
|
|
|
# Add CORS middleware
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.cors_origins,
|
|
allow_credentials=settings.cors_credentials,
|
|
allow_methods=settings.cors_methods,
|
|
allow_headers=settings.cors_headers,
|
|
)
|
|
|
|
|
|
# Include controller routers
|
|
app.include_router(health_controller.router) # / and /health
|
|
app.include_router(tools_controller.router) # /tools/*
|
|
app.include_router(infrastructure_controller.router) # /infrastructure/*
|
|
app.include_router(housekeeping_controller.router) # /housekeeping/*
|
|
app.include_router(static_controller.router) # /static/*
|
|
app.include_router(ai_router) # /ai/*
|
|
|
|
|
|
# Global exception handler
|
|
@app.exception_handler(Exception)
|
|
async def global_exception_handler(request, exc):
|
|
"""
|
|
Catch-all exception handler for unhandled errors
|
|
|
|
Args:
|
|
request: The request that caused the exception
|
|
exc: The exception instance
|
|
|
|
Returns:
|
|
JSON error response
|
|
"""
|
|
logger.error(f"Unhandled exception: {str(exc)}", exc_info=True)
|
|
return JSONResponse(
|
|
status_code=500,
|
|
content={
|
|
"detail": "Internal server error",
|
|
"type": type(exc).__name__
|
|
}
|
|
)
|