diff --git a/ai/compose.yml b/ai/compose.yml index 89dceca..ae2b56b 100755 --- a/ai/compose.yml +++ b/ai/compose.yml @@ -1,4 +1,3 @@ -version: "3.8" services: # webui: @@ -72,6 +71,8 @@ services: networks: - ai_backend - ai_net + depends_on: + - honcho labels: - "traefik.enable=true" - "traefik.docker.network=ai_net" @@ -125,6 +126,7 @@ services: - "traefik.http.routers.syncthing-https.tls.certresolver=njalla" - "traefik.http.services.syncthing.loadbalancer.server.port=8384" + ollama: build: context: ./ollama @@ -158,6 +160,92 @@ services: - "303" - "26" + # --- Honcho + OpenConcho combiné: API + Web UI nginx/FastAPI --- + honcho: + build: + context: ./honcho + ssh: + - default + container_name: honcho + restart: unless-stopped + environment: + - DB_CONNECTION_URI=postgresql+psycopg://honcho:honcho_pass@honcho-db:5432/honcho + - CACHE_URL=redis://honcho-redis:6379/0 + - CACHE_ENABLED=true + - EMBEDDING_VECTOR_DIMENSIONS=1024 + - AUTH_USE_AUTH=true + - AUTH_JWT_SECRET=${HONCHO_AUTH_JWT_SECRET} + # Needed by deriver/dream to make LLM calls (api_key_env = "HONCHO_OPENAI_API_KEY" in config.toml) + - HONCHO_OPENAI_API_KEY=${HONCHO_OPENAI_API_KEY} + volumes: + - honcho_data:/app/data + - /mnt/HoardingCow_docker_data/Honcho/config.toml:/app/config.toml:ro + networks: + - ai_backend + - ai_net + labels: + - "traefik.enable=true" + - "traefik.docker.network=ai_net" + + # Router for HTTP + redirect to HTTPS + - "traefik.http.routers.honcho-http.rule=Host(`honcho.lazyworkhorse.net`)" + - "traefik.http.routers.honcho-http.entrypoints=web" + - "traefik.http.routers.honcho-http.middlewares=redirect-to-https" + + # Router for HTTPS with TLS — protected by Authelia + - "traefik.http.routers.honcho-https.rule=Host(`honcho.lazyworkhorse.net`)" + - "traefik.http.routers.honcho-https.entrypoints=websecure" + - "traefik.http.routers.honcho-https.tls=true" + - "traefik.http.routers.honcho-https.tls.certresolver=njalla" + - "traefik.http.routers.honcho-https.middlewares=hermes-auth" + + # Service Loadbalancer (nginx port) + - "traefik.http.services.honcho.loadbalancer.server.port=80" + depends_on: + honcho-db: + condition: service_healthy + honcho-redis: + condition: service_healthy + + honcho-db: + image: pgvector/pgvector:pg15 + container_name: honcho-db + restart: unless-stopped + ports: + - "127.0.0.1:5432:5432" + command: ["postgres", "-c", "max_connections=200"] + environment: + - POSTGRES_DB=honcho + - POSTGRES_USER=honcho + - POSTGRES_PASSWORD=honcho_pass + - PGDATA=/var/lib/postgresql/data/pgdata + volumes: + - /mnt/HoardingCow_docker_data/Honcho/postgres:/var/lib/postgresql/data + - ./honcho/init-db.sql:/docker-entrypoint-initdb.d/init.sql:ro + networks: + - ai_backend + healthcheck: + test: ["CMD-SHELL", "pg_isready -U honcho -d honcho"] + interval: 5s + timeout: 5s + retries: 5 + + honcho-redis: + image: redis:8 + container_name: honcho-redis + restart: unless-stopped + ports: + - "127.0.0.1:6379:6379" + volumes: + - /mnt/HoardingCow_docker_data/Honcho/redis:/data + networks: + - ai_backend + healthcheck: + test: ["CMD-SHELL", "redis-cli ping"] + interval: 5s + timeout: 5s + retries: 5 + networks: ai_net: external: true @@ -165,6 +253,11 @@ networks: ai_backend: driver: bridge name: ai_backend + +volumes: + honcho_data: + external: true + name: honcho_data # llama_cpp_devstral: # image: ghcr.io/ggml-org/llama.cpp:server-rocm diff --git a/ai/hermes/Dockerfile b/ai/hermes/Dockerfile index dd044f9..368efca 100644 --- a/ai/hermes/Dockerfile +++ b/ai/hermes/Dockerfile @@ -43,6 +43,14 @@ RUN apt-get update && \ # ---------- UV ---------- COPY --chmod=0755 --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/ +# ---------- Matrix bridge + extra pip deps ---------- +# Previously installed inline at container startup and persisted via volume mount. +# Now baked into the image so the fragile venv volume mount can be removed. +RUN . /opt/hermes/.venv/bin/activate && \ + uv pip install --no-cache-dir 'mautrix[encryption]' openai + +WORKDIR /opt/hermes + # ---------- Matrix bridge + extra pip deps ---------- # Previously installed inline at container startup and persisted via volume mount. # Now baked into the image so the fragile venv volume mount can be removed. diff --git a/ai/honcho/Dockerfile b/ai/honcho/Dockerfile new file mode 100644 index 0000000..9407eea --- /dev/null +++ b/ai/honcho/Dockerfile @@ -0,0 +1,75 @@ +# build stage — fetches and builds Honcho from source +FROM python:3.13-slim-bookworm AS honcho-builder + +RUN apt-get update && \ + apt-get install -y --no-install-recommends git openssh-client && \ + rm -rf /var/lib/apt/lists/* + +COPY --from=ghcr.io/astral-sh/uv:0.9.24 /uv /bin/uv + +ARG HONCHO_REPO=ssh://git@code.lazyworkhorse.net:2222/Hermes/honcho.git +ARG HONCHO_REF=main +RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan -p 2222 code.lazyworkhorse.net >> ~/.ssh/known_hosts 2>/dev/null +RUN --mount=type=ssh git clone --depth 1 --branch ${HONCHO_REF} ${HONCHO_REPO} /app + +WORKDIR /app + +ENV UV_COMPILE_BYTECODE=1 +ENV UV_LINK_MODE=copy +ENV UV_PYTHON=/usr/local/bin/python3.13 + +RUN uv sync --frozen + +# build stage — builds OpenConcho SPA +FROM node:22-bookworm AS openconcho-builder + +ENV PNPM_HOME=/pnpm +ENV PATH=$PNPM_HOME:$PATH +RUN corepack enable && corepack prepare pnpm@latest --activate + +WORKDIR /app +RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* + +ARG OPENCONCHO_SHA=3b5c3293fc18d768dbe85285264a8d66c896bd81 +RUN --mount=type=ssh git clone --depth 1 ssh://git@code.lazyworkhorse.net:2222/gortium/openconcho.git /app && \ + git -C /app fetch --depth 1 origin ${OPENCONCHO_SHA} && \ + git -C /app checkout ${OPENCONCHO_SHA} + +RUN pnpm install --frozen-lockfile +RUN pnpm --filter @openconcho/web build + +# runtime stage — nginx + Honcho FastAPI +FROM python:3.13-slim-bookworm + +# Install nginx and create runtime dirs before dropping permissions +RUN apt-get update && apt-get install -y --no-install-recommends nginx && \ + rm -rf /var/log/nginx/* && \ + rm -rf /var/lib/apt/lists/* && \ + rm -f /etc/nginx/sites-enabled/default + +# Patch nginx.conf: comment out "user www-data;" so nginx master stays as root +# (workers inherit root inside a container — fine for single-service isolation) +RUN sed -i 's/^user /# user /' /etc/nginx/nginx.conf + +# Pre-create nginx runtime directories with proper ownership +RUN mkdir -p /var/lib/nginx/body /var/lib/nginx/proxy /var/lib/nginx/fastcgi \ + /var/lib/nginx/uwsgi /var/lib/nginx/scgi /var/lib/nginx/proxy_temp \ + /var/cache/nginx && \ + chown -R root:root /var/lib/nginx /var/cache/nginx + +# Honcho +COPY --from=honcho-builder /app /app +WORKDIR /app +ENV PATH="/app/.venv/bin:$PATH" +ENV HOME=/app +COPY config.toml /app/config.toml + +# OpenConcho SPA +COPY --from=openconcho-builder /app/packages/web/dist /usr/share/nginx/html + +# nginx config (proxies /v3/, /v2/ to Honcho on localhost:8000) +COPY honcho-nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 + +CMD ["bash", "-c", "nginx -g 'daemon off;' & fastapi run --host 127.0.0.1 --port 8000 src/main.py & python3 -m src.deriver & wait -n"] diff --git a/ai/honcho/config.toml b/ai/honcho/config.toml new file mode 100644 index 0000000..8ecbc89 --- /dev/null +++ b/ai/honcho/config.toml @@ -0,0 +1,132 @@ +[app] +LOG_LEVEL = "INFO" +MAX_MESSAGE_SIZE = 25000 +EMBED_MESSAGES = true +NAMESPACE = "honcho" + +[db] +CONNECTION_URI = "postgresql+psycopg://honcho:honcho_pass@honcho-db:5432/honcho" +SCHEMA = "public" +POOL_SIZE = 10 +MAX_OVERFLOW = 20 + +[auth] +USE_AUTH = false + +[sentry] +ENABLED = false + +[telemetry] +ENABLED = false + +[webhook] +ENABLED = false + +[cache] +ENABLED = true +URL = "redis://honcho-redis:6379/0" + +[llm] +DEFAULT_MAX_TOKENS = 4096 + +# Embeddings via Ollama — bge-m3 provides 1024-dim +[embedding] +VECTOR_DIMENSIONS = 1024 +MAX_INPUT_TOKENS = 8192 + +[embedding.model_config] +transport = "openai" +model = "bge-m3" +overrides = {base_url = "http://ollama:11434/v1", api_key = "ollama"} + +# --- Deriver --- +[deriver] +ENABLED = true +WORKERS = 1 +POLLING_SLEEP_INTERVAL_SECONDS = 5.0 +FLUSH_ENABLED = true + +[deriver.model_config] +overrides = {base_url = "https://opencode.ai/zen/go/v1", api_key_env = "HONCHO_OPENAI_API_KEY"} +transport = "openai" +model = "deepseek-v4-flash" + +# --- Dialectic --- +[dialectic] +MAX_INPUT_TOKENS = 4096 +SESSION_HISTORY_MAX_TOKENS = 8192 + +[dialectic.levels.minimal] +MAX_TOOL_ITERATIONS = 1 +MAX_OUTPUT_TOKENS = 512 +[dialectic.levels.minimal.model_config] +overrides = {base_url = "https://opencode.ai/zen/go/v1", api_key_env = "HONCHO_OPENAI_API_KEY"} +transport = "openai" +model = "deepseek-v4-flash" + +[dialectic.levels.low] +MAX_TOOL_ITERATIONS = 3 +[dialectic.levels.low.model_config] +overrides = {base_url = "https://opencode.ai/zen/go/v1", api_key_env = "HONCHO_OPENAI_API_KEY"} +transport = "openai" +model = "deepseek-v4-flash" + +[dialectic.levels.medium] +MAX_TOOL_ITERATIONS = 2 +[dialectic.levels.medium.model_config] +overrides = {base_url = "https://opencode.ai/zen/go/v1", api_key_env = "HONCHO_OPENAI_API_KEY"} +transport = "openai" +model = "deepseek-v4-flash" + +[dialectic.levels.high] +MAX_TOOL_ITERATIONS = 4 +[dialectic.levels.high.model_config] +overrides = {base_url = "https://opencode.ai/zen/go/v1", api_key_env = "HONCHO_OPENAI_API_KEY"} +transport = "openai" +model = "deepseek-v4-flash" + +[dialectic.levels.max] +MAX_TOOL_ITERATIONS = 10 +[dialectic.levels.max.model_config] +overrides = {base_url = "https://opencode.ai/zen/go/v1", api_key_env = "HONCHO_OPENAI_API_KEY"} +transport = "openai" +model = "deepseek-v4-flash" + +# --- Summary --- +[summary] +ENABLED = true +MESSAGES_PER_SHORT_SUMMARY = 20 +MESSAGES_PER_LONG_SUMMARY = 60 + +[summary.model_config] +overrides = {base_url = "https://opencode.ai/zen/go/v1", api_key_env = "HONCHO_OPENAI_API_KEY"} +transport = "openai" +model = "deepseek-v4-flash" + +# --- Dream --- +[dream] +ENABLED = true + +[dream.model_config] +overrides = {base_url = "https://opencode.ai/zen/go/v1", api_key_env = "HONCHO_OPENAI_API_KEY"} +transport = "openai" +model = "deepseek-v4-flash" + +[dream.deduction_model_config] +overrides = {base_url = "https://opencode.ai/zen/go/v1", api_key_env = "HONCHO_OPENAI_API_KEY"} +transport = "openai" +model = "deepseek-v4-flash" + +[dream.induction_model_config] +overrides = {base_url = "https://opencode.ai/zen/go/v1", api_key_env = "HONCHO_OPENAI_API_KEY"} +transport = "openai" +model = "deepseek-v4-flash" + +# --- Peer Card --- +[peer_card] +ENABLED = true + +# --- Vector Store --- +[vector_store] +TYPE = "pgvector" +# DIMENSIONS is deprecated — EMBEDDING.VECTOR_DIMENSIONS is authoritative diff --git a/ai/honcho/honcho-nginx.conf b/ai/honcho/honcho-nginx.conf new file mode 100644 index 0000000..90d13b2 --- /dev/null +++ b/ai/honcho/honcho-nginx.conf @@ -0,0 +1,52 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + # Honcho API proxy + location /v3/ { + proxy_pass http://127.0.0.1:8000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /v2/ { + proxy_pass http://127.0.0.1:8000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # Honcho health + location /health { + proxy_pass http://127.0.0.1:8000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # OpenAPI docs + location /openapi.json { + proxy_pass http://127.0.0.1:8000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # SPA: fallback to index.html for client-side routing + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/ai/honcho/init-db.sql b/ai/honcho/init-db.sql new file mode 100644 index 0000000..0aa0fc2 --- /dev/null +++ b/ai/honcho/init-db.sql @@ -0,0 +1 @@ +CREATE EXTENSION IF NOT EXISTS vector;