Compare commits

..

4 Commits

Author SHA1 Message Date
1eacc3cd8e fix(paperclip): force Traefik to use ai_net network for routing
Some checks failed
Build Hermes agent / build (pull_request) Has been cancelled
Build ollama (gfx906) / build (pull_request) Has been cancelled
2026-05-18 22:13:59 -04:00
bce403232a Revert custom Dockerfile - not needed, adapter installs on persistent volume
Some checks failed
Build Hermes agent / build (pull_request) Has been cancelled
Build ollama (gfx906) / build (pull_request) Has been cancelled
The Hermes adapter can be installed once via Paperclip's adapter
management API and persists on the Docker volume across restarts.
No custom Dockerfile or build step required.
2026-05-18 18:38:17 -04:00
37bf43c3ea feat: add custom Dockerfile with Hermes adapter baked in
Some checks failed
Build Hermes agent / build (pull_request) Has been cancelled
Build ollama (gfx906) / build (pull_request) Has been cancelled
Creates ai/paperclip/ with:
- Dockerfile: extends upstream paperclip image, pre-installs
  hermes-paperclip-adapter@0.3.0 npm package as seed data
- docker-entrypoint.sh: seeds the adapter plugin on first boot
  if the persistent volume is empty, then runs original startup

This ensures the Hermes adapter is available on first boot without
requiring network access — no npm install needed at runtime. The
adapter persists on the Docker volume across restarts.
2026-05-18 18:37:31 -04:00
563ccc5632 feat: add Paperclip agent orchestrator to AI compose stack
Some checks failed
Build Hermes agent / build (pull_request) Has been cancelled
Build ollama (gfx906) / build (pull_request) Has been cancelled
Paperclip (ghcr.io/paperclipai/paperclip:v2026.517.0) is an open-source
agent management dashboard. Adds paperclip-db (PostgreSQL 17) and
paperclip services with Traefik reverse proxy on
paperclip.lazyworkhorse.net.

Requires .env: PAPERCLIP_DB_PASSWORD, PAPERCLIP_AUTH_SECRET.
2026-05-18 18:17:15 -04:00
6 changed files with 6 additions and 344 deletions

View File

@@ -44,7 +44,7 @@ services:
- API_SERVER_HOST=0.0.0.0
- API_SERVER_KEY=hermes_local_key
- GATEWAY_ALLOW_ALL_USERS=true
- OPENROUTER_API_KEY=${OPEN...KEY}
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
# ROCm for GPU-accelerated faster-whisper STT
- HSA_OVERRIDE_GFX_VERSION=9.0.6
- HCC_AMDGPU_TARGET=gfx906
@@ -54,10 +54,6 @@ services:
- TZ=America/Montreal
volumes:
- /mnt/HoardingCow_docker_data/Hermes/data:/opt/data
# Syncthing-shared org files — read-only view of user's agenda
- /mnt/HoardingCow_docker_data/Syncthing/telos-ro:/opt/data/telos-ro:ro
# Syncthing-shared inbox — write tasks here, they sync to user's laptop
- /mnt/HoardingCow_docker_data/Syncthing/telos-rw:/opt/data/telos-rw:rw
devices:
- /dev/kfd:/dev/kfd
- /dev/dri:/dev/dri
@@ -67,35 +63,6 @@ services:
networks:
- ai_backend
syncthing:
image: syncthing/syncthing:latest
container_name: syncthing
hostname: syncthing
restart: always
ports:
- "8384:8384"
- "22000:22000"
- "21027:21027/udp"
environment:
- TZ=America/Montreal
volumes:
- /mnt/HoardingCow_docker_data/Syncthing/config:/var/syncthing/config
- /mnt/HoardingCow_docker_data/Syncthing/telos-ro:/telos-ro
- /mnt/HoardingCow_docker_data/Syncthing/telos-rw:/telos-rw
networks:
- ai_backend
- ai_net
labels:
- "traefik.enable=true"
- "traefik.http.routers.syncthing-http.rule=Host(`syncthing.lazyworkhorse.net`)"
- "traefik.http.routers.syncthing-http.entrypoints=web"
- "traefik.http.routers.syncthing-http.middlewares=redirect-to-https"
- "traefik.http.routers.syncthing-https.rule=Host(`syncthing.lazyworkhorse.net`)"
- "traefik.http.routers.syncthing-https.entrypoints=websecure"
- "traefik.http.routers.syncthing-https.tls=true"
- "traefik.http.routers.syncthing-https.tls.certresolver=njalla"
- "traefik.http.services.syncthing.loadbalancer.server.port=8384"
ollama:
build:
context: ./ollama
@@ -157,8 +124,8 @@ services:
- HOST=0.0.0.0
- PORT=3100
- SERVE_UI=true
- DATABASE_URL=postgres://paperclip:***@paperclip-db:5432/paperclip
- BETTER_AUTH_SECRET=${PAPE...CRET must be set}
- DATABASE_URL=postgres://paperclip:${PAPERCLIP_DB_PASSWORD}@paperclip-db:5432/paperclip
- BETTER_AUTH_SECRET=${PAPERCLIP_AUTH_SECRET:?PAPERCLIP_AUTH_SECRET must be set}
- PAPERCLIP_PUBLIC_URL=https://paperclip.lazyworkhorse.net
- PAPERCLIP_DEPLOYMENT_MODE=authenticated
- PAPERCLIP_DEPLOYMENT_EXPOSURE=private
@@ -185,94 +152,6 @@ services:
- "traefik.http.services.paperclip.loadbalancer.server.port=3100"
# ---------------------------------------------------------------------------
# Honcho — Memory infrastructure for stateful AI agents
# Self-hosted memory server with pgvector for embedding storage.
# Defaults to Ollama for embeddings; configure LLM provider for full deriver
# and summarization support.
#
# API port: 8000
# Web: https://honcho.lazyworkhorse.net
# Docs: https://github.com/plastic-labs/honcho
# ---------------------------------------------------------------------------
honcho-db:
image: pgvector/pgvector:pg17-trixie
container_name: honcho-db
restart: unless-stopped
environment:
POSTGRES_DB: honcho
POSTGRES_USER: honcho
POSTGRES_PASSWORD: ${HONCHO_DB_PASSWORD:?HONCHO_DB_PASSWORD must be set}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U honcho -d honcho"]
interval: 5s
timeout: 5s
retries: 10
volumes:
- /mnt/HoardingCow_docker_data/Honcho/pgdata:/var/lib/postgresql/data
- ./honcho/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- ai_backend
honcho:
build:
context: ./honcho
dockerfile: Dockerfile
container_name: honcho
restart: unless-stopped
ports:
- "127.0.0.1:8000:8000"
depends_on:
honcho-db:
condition: service_healthy
environment:
DB_CONNECTION_URI: postgresql+psycopg://honcho:${HONCHO_DB_PASSWORD:?HONCHO_DB_PASSWORD must be set}@honcho-db:5432/honcho
LOG_LEVEL: INFO
LLM_OPENAI_API_KEY: ${LLM_OPENAI_API_KEY:-ollama}
volumes:
- /mnt/HoardingCow_docker_data/Honcho/config.toml:/app/config.toml
networks:
- ai_backend
- ai_net
labels:
- "traefik.enable=true"
- "traefik.docker.network=ai_net"
- "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"
- "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.services.honcho.loadbalancer.server.port=8000"
holographic-memory:
build:
context: ./holographic-memory
image: holographic-memory:latest
container_name: holographic-memory
restart: unless-stopped
ports:
- "127.0.0.1:8100:8100"
environment:
- HOLOGRAPHIC_DB_PATH=/data/holographic/memory_store.db
- HOLOGRAPHIC_PORT=8100
- HOLOGRAPHIC_DEFAULT_TRUST=0.5
volumes:
- /mnt/HoardingCow_docker_data/HolographicMemory:/data/holographic
networks:
- ai_backend
healthcheck:
test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8100/health')"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
networks:
ai_net:
external: true
@@ -424,8 +303,8 @@ networks:
# - /home/gortium/infra:/data/workspace/infra
# environment:
# - TZ=America/Toronto
# - OPENCLAW_GATEWAY_TOKEN=${OPEN...KEN}
# - OPENROUTER_API_KEY=${OPEN...KEY}
# - OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
# - OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
# # Point to the sidecar browser
# - BROWSER_CDP_URL=http://openclaw-browser:9222
# - BROWSER_EVALUATE_ENABLED=true
@@ -470,7 +349,7 @@ networks:
# - PGID=1000
# - PUBLIC_KEY_FILE=/config/ssh/authorized_keys
# - SUDO_ACCESS=false
# - PASSWORD_ACCESS=***
# - PASSWORD_ACCESS=false
# volumes:
# - /mnt/HoardingCow_docker_data/openclaw/ssh-config:/config
# - /home/gortium/infra:/data/workspace/infra:ro

View File

@@ -79,26 +79,6 @@ PYEOF
COPY --chmod=0755 himalaya-ro.sh /usr/local/bin/himalaya-ro
# ---------- Install 7-Zip (7zz) for CHM extraction ----------
RUN /opt/hermes/.venv/bin/python3 /dev/stdin << 'PYEOF'
import urllib.request, tarfile, os, shutil, subprocess
url = 'https://github.com/ip7z/7zip/releases/download/26.01/7z2601-linux-x64.tar.xz'
xz = '/tmp/7z2601-linux-x64.tar.xz'
urllib.request.urlretrieve(url, xz)
os.makedirs('/tmp/7z', exist_ok=True)
with tarfile.open(xz, 'r:xz') as t:
t.extractall('/tmp/7z')
shutil.move('/tmp/7z/7zz', '/usr/local/bin/7zz')
os.chmod('/usr/local/bin/7zz', 0o755)
shutil.rmtree('/tmp/7z', ignore_errors=True)
os.remove(xz)
# Verify
result = subprocess.run(['/usr/local/bin/7zz'], capture_output=True, text=True)
assert result.returncode == 0, f'7zz verify failed: {result.stderr}'
print('7-Zip 26.01 installed successfully')
PYEOF
# ---------- Runtime ----------
USER hermes
ENV HERMES_HOME=/opt/data

View File

@@ -1,72 +0,0 @@
# Honcho — Memory infrastructure for stateful AI agents
# Builds the Honcho FastAPI server from the official GitHub repository.
#
# Usage:
# docker compose build honcho
# docker compose up honcho
#
# Reference: https://github.com/plastic-labs/honcho
# ---------------------------------------------------------------------------
# Stage 1 — clone source & install dependencies
# ---------------------------------------------------------------------------
FROM python:3.13-slim-bookworm AS builder
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
COPY --from=ghcr.io/astral-sh/uv:0.9.24 /uv /bin/uv
WORKDIR /src
RUN git clone --depth 1 --branch main https://github.com/plastic-labs/honcho.git .
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
# Install project dependencies (frozen from lockfile, no dev)
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-project --no-group dev
# ---------------------------------------------------------------------------
# Stage 2 — runtime image
# ---------------------------------------------------------------------------
FROM python:3.13-slim-bookworm AS runtime
COPY --from=ghcr.io/astral-sh/uv:0.9.24 /uv /bin/uv
RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV PATH="/app/.venv/bin:$PATH"
ENV HOME=/app
ENV UV_CACHE_DIR=/tmp/uv-cache
# Copy the dependency layer from the builder
COPY --from=builder /src/uv.lock /src/pyproject.toml /app/
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-group dev
# Copy application source and config
COPY --from=builder /src/src/ /app/src/
COPY --from=builder /src/migrations/ /app/migrations/
COPY --from=builder /src/scripts/ /app/scripts/
COPY --from=builder /src/docker/ /app/docker/
COPY --from=builder /src/alembic.ini /app/alembic.ini
# Create non-root user
RUN addgroup --system app && \
adduser --system --ingroup app app && \
mkdir -p /tmp/uv-cache && \
chown -R app:app /app /tmp/uv-cache
USER app
EXPOSE 8000
# The entrypoint.sh script runs database migrations then starts the FastAPI server
ENTRYPOINT ["sh", "docker/entrypoint.sh"]

View File

@@ -1 +0,0 @@
CREATE EXTENSION IF NOT EXISTS vector;

View File

@@ -1,93 +0,0 @@
# Honcho Configuration
# Pre-configured for self-hosted deployment with Ollama embeddings.
# Mount this file at /app/config.toml in the Honcho container.
#
# Environment variables override these values at runtime
# (e.g. DB_CONNECTION_URI, DERIVER_*).
[app]
LOG_LEVEL = "INFO"
NAMESPACE = "honcho"
SESSION_OBSERVERS_LIMIT = 10
GET_CONTEXT_MAX_TOKENS = 16384
EMBED_MESSAGES = true
[db]
# Connection URI is set via environment variable DB_CONNECTION_URI
SCHEMA = "public"
POOL_SIZE = 10
MAX_OVERFLOW = 20
POOL_TIMEOUT = 30
POOL_RECYCLE = 300
POOL_PRE_PING = true
POOL_USE_LIFO = true
SQL_DEBUG = false
[auth]
USE_AUTH = false
[llm]
DEFAULT_MAX_TOKENS = 4096
[embedding]
VECTOR_DIMENSIONS = 768
MAX_INPUT_TOKENS = 8192
MAX_TOKENS_PER_REQUEST = 2048
[embedding.model_config]
transport = "openai"
model = "nomic-embed-text:latest"
[embedding.model_config.overrides]
base_url = "http://ollama:11434/v1"
# Ollama does not require an API key; env var must be set to non-empty string
api_key_env = "LLM_OPENAI_API_KEY"
[deriver]
ENABLED = false
WORKERS = 1
POLLING_SLEEP_INTERVAL_SECONDS = 1.0
STALE_SESSION_TIMEOUT_MINUTES = 5
DEDUPLICATE = true
LOG_OBSERVATIONS = false
[deriver.model_config]
transport = "openai"
model = "qwen3.6:27b-q4_K_M"
[deriver.model_config.overrides]
base_url = "http://ollama:11434/v1"
api_key_env = "LLM_OPENAI_API_KEY"
[summary]
ENABLED = false
[summary.model_config]
transport = "openai"
model = "qwen3.6:27b-q4_K_M"
[summary.model_config.overrides]
base_url = "http://ollama:11434/v1"
api_key_env = "LLM_OPENAI_API_KEY"
[dream]
ENABLED = false
[dialectic]
MAX_OUTPUT_TOKENS = 4096
MAX_INPUT_TOKENS = 16384
[cache]
ENABLED = false
[vector_store]
TYPE = "pgvector"
[metrics]
ENABLED = false
[telemetry]
ENABLED = false
[sentry]
ENABLED = false

View File

@@ -1,31 +0,0 @@
# Honcho Environment Variables
# Copy this file to your .env (at the compose root or docker-compose working directory)
# and fill in the secrets.
#
# cp env/.env.example.honcho .env
#
# Then reference it from compose.yml:
# env_file:
# - path: .env
# required: true
# ---------------------------------------------------------------------------
# Database
# ---------------------------------------------------------------------------
# PostgreSQL connection string for Honcho.
# The password must match HONCHO_DB_PASSWORD below.
HONCHO_DB_PASSWORD=change_me_to_a_strong_random_password
# ---------------------------------------------------------------------------
# LLM Provider
# ---------------------------------------------------------------------------
# Ollama does not require a real API key, but the env var must be set to a
# non-empty string for the OpenAI-compatible client to connect.
LLM_OPENAI_API_KEY=ollama
# ---------------------------------------------------------------------------
# Honcho Server
# ---------------------------------------------------------------------------
# Honcho will pick up DB_CONNECTION_URI from the compose environment.
# You can override additional settings here if needed.
# LOG_LEVEL=INFO