diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..827aff2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM python:3.11-slim AS base + +COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv + +WORKDIR /app + +COPY pyproject.toml uv.lock ./ +RUN uv sync --frozen --no-dev + +COPY src/ src/ + +EXPOSE 8000 + +CMD ["uv", "run", "start"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..8e1a7b9 --- /dev/null +++ b/README.md @@ -0,0 +1,79 @@ +# OpusAgent + +Servizio self-hosted per l'interazione programmatica con i modelli Anthropic +tramite Claude Code SDK, sfruttando un abbonamento Claude Pro/Max esistente. + +## Architettura + +Due container Docker: +- **fastapi-service** — API REST, autenticazione, coda richieste, rate limiting +- **claude-worker** — Processamento richieste via Claude Code SDK + +## Setup + +### Prerequisiti + +- Docker e Docker Compose +- Un abbonamento Claude Pro/Max attivo + +### Prima installazione + +1. Copia e configura l'environment: + ```bash + cp .env.example .env + # Edita .env: imposta API_KEY e le altre variabili + ``` + +2. Autentica Claude Code nel worker: + ```bash + docker compose run --rm claude-worker npx claude login + ``` + +3. Avvia il sistema: + ```bash + docker compose up -d + ``` + +4. Verifica: + ```bash + curl -H "X-Api-Key: TUA_KEY" http://localhost:8000/api/health + ``` + +## Sviluppo locale + +```bash +uv sync --all-groups +cp .env.example .env +# Edita .env +uv run dev +``` + +## Test + +```bash +uv run pytest -v +``` + +## API + +Documentazione completa: `http://localhost:8000/doc` + +### Esempio d'uso + +```bash +# Crea un argomento +curl -X POST http://localhost:8000/api/topics \ + -H "X-Api-Key: TUA_KEY" \ + -H "Content-Type: application/json" \ + -d '{"name": "coding", "system_prompt": "Sei un esperto sviluppatore."}' + +# Invia una richiesta +curl -X POST http://localhost:8000/api/requests \ + -H "X-Api-Key: TUA_KEY" \ + -H "Content-Type: application/json" \ + -d '{"prompt": "Come implemento JWT in FastAPI?", "topic_id": "ID_TOPIC"}' + +# Controlla il risultato +curl http://localhost:8000/api/requests/ID_RICHIESTA \ + -H "X-Api-Key: TUA_KEY" +``` diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e3f952e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,46 @@ +services: + fastapi-service: + build: + context: . + dockerfile: Dockerfile + ports: + - "${API_PORT:-8000}:8000" + env_file: .env + volumes: + - opus-data:/data + depends_on: + claude-worker: + condition: service_healthy + restart: unless-stopped + healthcheck: + test: + [ + "CMD", + "python", + "-c", + "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health')", + ] + interval: 10s + timeout: 5s + retries: 3 + + claude-worker: + build: + context: ./worker + dockerfile: Dockerfile + expose: + - "3001" + env_file: .env + volumes: + - opus-data:/data + - claude-auth:/home/node/.claude + restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "http://localhost:3001/health"] + interval: 10s + timeout: 5s + retries: 3 + +volumes: + opus-data: + claude-auth: