feat: update configuration and enhance Docker support with new Makefile commands

This commit is contained in:
2026-06-12 20:00:35 +08:00
parent 144f994d58
commit 1e206eed8b
5 changed files with 58 additions and 11 deletions
+6
View File
@@ -1,3 +1,9 @@
# OpenAI-compatible API configuration # OpenAI-compatible API configuration
LLM_BASE_URL=http://localhost:11434/v1 LLM_BASE_URL=http://localhost:11434/v1
LLM_MODEL=llama LLM_MODEL=llama
# API key for the LLM provider (leave empty for local servers like Ollama)
LLM_API_KEY=
# Logfire observability (set your token to enable)
LOGFIRE_TOKEN=
+24 -1
View File
@@ -1,5 +1,11 @@
.PHONY: install run dev clean setup \ .PHONY: install run dev clean setup \
frontend-install frontend-dev frontend-build frontend-install frontend-dev frontend-build \
compose-up compose-down compose-build compose-logs compose-rebuild
# ── Container runtime detection (Docker / Podman) ─────────────────────────
# Uses Docker if available, otherwise falls back to Podman.
DOCKER := $(shell command -v docker 2>/dev/null || command -v podman 2>/dev/null)
DOCKER_COMPOSE := $(shell command -v docker-compose 2>/dev/null || (command -v docker 2>/dev/null && echo "docker compose") || (command -v podman 2>/dev/null && echo "podman compose"))
# ── Backend Setup ────────────────────────────────────────────────────────── # ── Backend Setup ──────────────────────────────────────────────────────────
@@ -32,6 +38,23 @@ frontend-dev: ## Start the Vite dev server
frontend-build: ## Build frontend for production frontend-build: ## Build frontend for production
cd frontend && bun run build cd frontend && bun run build
# ── Containers (Docker / Podman) ───────────────────────────────────────────
compose-up: ## Start all containers in detached mode
$(DOCKER_COMPOSE) up -d
compose-down: ## Stop and remove containers
$(DOCKER_COMPOSE) down
compose-build: ## Build (or rebuild) all container images
$(DOCKER_COMPOSE) build
compose-rebuild: ## Rebuild images & restart containers
$(DOCKER_COMPOSE) up -d --build
compose-logs: ## Follow container logs
$(DOCKER_COMPOSE) logs -f
# ── Utilities ────────────────────────────────────────────────────────────── # ── Utilities ──────────────────────────────────────────────────────────────
clean: ## Remove caches and build artifacts clean: ## Remove caches and build artifacts
+16 -8
View File
@@ -32,6 +32,7 @@ class AgentService:
def __init__(self, settings: Settings) -> None: def __init__(self, settings: Settings) -> None:
self._settings = settings self._settings = settings
self._agent: Agent | None = None self._agent: Agent | None = None
self._model: OpenAIResponsesModel | None = None
# ── Lifecycle ────────────────────────────────────────────────────────── # ── Lifecycle ──────────────────────────────────────────────────────────
@@ -40,16 +41,23 @@ class AgentService:
if self._agent is not None: if self._agent is not None:
return return
logfire.configure() if self._settings.logfire_token:
logfire.instrument_pydantic_ai() try:
logfire.configure(token=self._settings.logfire_token)
logfire.instrument_pydantic_ai()
except Exception:
pass # Logfire is optional — don't crash if it fails
model = OpenAIResponsesModel( self._model = OpenAIResponsesModel(
self._settings.llm_model, self._settings.llm_model,
provider=OpenAIProvider(base_url=self._settings.llm_base_url), provider=OpenAIProvider(
base_url=self._settings.llm_base_url,
api_key=self._settings.llm_api_key or "no-key-required",
),
) )
self._agent = Agent( self._agent = Agent(
model, self._model,
capabilities=self._build_capabilities(), capabilities=self._build_capabilities(),
) )
@@ -69,8 +77,7 @@ class AgentService:
# ── Internal helpers ─────────────────────────────────────────────────── # ── Internal helpers ───────────────────────────────────────────────────
@staticmethod def _build_capabilities(self) -> list:
def _build_capabilities() -> list:
"""Assemble the full list of agent capabilities.""" """Assemble the full list of agent capabilities."""
return [ return [
CodeMode(), CodeMode(),
@@ -89,7 +96,8 @@ class AgentService:
description="Deep research on a topic", description="Deep research on a topic",
instructions="You are a thorough research assistant.", instructions="You are a thorough research assistant.",
), ),
] ],
default_model=self._model,
), ),
TodoCapability(enable_subtasks=True), TodoCapability(enable_subtasks=True),
CostTracking(budget_usd=5.0), CostTracking(budget_usd=5.0),
+2
View File
@@ -22,6 +22,8 @@ class Settings(BaseSettings):
llm_base_url: str = "http://localhost:11434/v1" llm_base_url: str = "http://localhost:11434/v1"
llm_model: str = "llama" llm_model: str = "llama"
llm_api_key: str = ""
logfire_token: str = ""
# ── Factories ────────────────────────────────────────────────────────── # ── Factories ──────────────────────────────────────────────────────────
+10 -2
View File
@@ -5,14 +5,22 @@ server {
root /usr/share/nginx/html; root /usr/share/nginx/html;
index index.html; index index.html;
# Podman/Docker DNS — forces runtime resolution so nginx picks up
# container IP changes after restarts.
resolver 10.89.6.1 valid=10s;
# ── API proxy ───────────────────────────────────────────────── # ── API proxy ─────────────────────────────────────────────────
# Use a variable so nginx resolves DNS at runtime, not at startup.
set $backend_upstream http://backend:8000;
location /api/ { location /api/ {
proxy_pass http://backend:8000; proxy_pass $backend_upstream;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 120s; proxy_connect_timeout 30s;
proxy_read_timeout 200s;
proxy_send_timeout 200s;
} }
# ── Static files ────────────────────────────────────────────── # ── Static files ──────────────────────────────────────────────