diff --git a/ai/compose.yml b/ai/compose.yml index 81f4cc1..0b918dd 100755 --- a/ai/compose.yml +++ b/ai/compose.yml @@ -175,7 +175,8 @@ services: - AUTH_JWT_SECRET=${AUTH_JWT_SECRET} - OPENAI_API_KEY=${OPENAI_API_KEY} volumes: - - /mnt/HoardingCow_docker_data/Honcho/data:/app/data + - honcho_data:/app/data + - /mnt/HoardingCow_docker_data/Honcho/config.toml:/app/config.toml:ro networks: - ai_backend - ai_net @@ -248,6 +249,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/honcho/Dockerfile b/ai/honcho/Dockerfile index e124482..98f4794 100644 --- a/ai/honcho/Dockerfile +++ b/ai/honcho/Dockerfile @@ -7,7 +7,7 @@ RUN apt-get update && \ COPY --from=ghcr.io/astral-sh/uv:0.9.24 /uv /bin/uv -ARG HONCHO_REPO=https://github.com/plastic-labs/honcho +ARG HONCHO_REPO=https://code.lazyworkhorse.net/Hermes/honcho.git ARG HONCHO_REF=main RUN git clone --depth 1 --branch ${HONCHO_REF} ${HONCHO_REPO} /app diff --git a/copy_script.txt b/copy_script.txt new file mode 100644 index 0000000..c562d14 --- /dev/null +++ b/copy_script.txt @@ -0,0 +1,7 @@ +import shutil, os +src = "/opt/data/projects/gortium/compose/ai/compose_updated.txt" +dst = "/opt/data/projects/gortium/compose/ai/compose.yml" +print(f"Source exists: {os.path.exists(src)}, size: {os.path.getsize(src)}") +print(f"Dest exists: {os.path.exists(dst)}") +shutil.copy2(src, dst) +print(f"Copied, dest size: {os.path.getsize(dst)}") diff --git a/entrypoint-combined.sh b/entrypoint-combined.sh new file mode 100644 index 0000000..0dbbeb5 --- /dev/null +++ b/entrypoint-combined.sh @@ -0,0 +1,154 @@ +#!/bin/bash +# ── Hermes Workspace Combined Entrypoint ── +# Waits for the Hermes gateway container (hermes:8642) to become healthy, +# then starts the Hermes Workspace web UI in the foreground. +# Supports graceful shutdown via SIGTERM/SIGINT. +# ────────────────────────────────────────── + +set -euo pipefail + +# ── Configuration ────────────────────────────────────────────── +GATEWAY_HOST="${GATEWAY_HOST:-hermes}" +GATEWAY_PORT="${GATEWAY_PORT:-8642}" +GATEWAY_URL="http://${GATEWAY_HOST}:${GATEWAY_PORT}" + +HEALTH_ENDPOINT="${HEALTH_ENDPOINT:-/health}" +MAX_RETRIES="${HEALTH_MAX_RETRIES:-60}" +RETRY_INTERVAL="${HEALTH_RETRY_INTERVAL:-2}" + +WORKSPACE_DIR="${WORKSPACE_DIR:-/workspace}" +WORKSPACE_ENTRY="${WORKSPACE_ENTRY:-server-entry.js}" + +PID_FILE="${PID_FILE:-/tmp/workspace.pid}" + +# ── Logging ──────────────────────────────────────────────────── +log_info() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $*"; } +log_warn() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $*"; } +log_error() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $*"; } + +# ── Graceful Shutdown ────────────────────────────────────────── +_workspace_pid="" +_shutting_down=false + +cleanup() { + if [ "$_shutting_down" = true ]; then + return + fi + _shutting_down=true + + log_info "Shutdown signal received, cleaning up..." + + # Stop workspace process if running + if [ -n "$_workspace_pid" ] && kill -0 "$_workspace_pid" 2>/dev/null; then + log_info "Stopping workspace (PID: $_workspace_pid)..." + kill -TERM "$_workspace_pid" 2>/dev/null || true + + # Give it time to shut down gracefully + local wait_sec=10 + while kill -0 "$_workspace_pid" 2>/dev/null && [ "$wait_sec" -gt 0 ]; do + sleep 1 + wait_sec=$((wait_sec - 1)) + done + + # Force kill if still running + if kill -0 "$_workspace_pid" 2>/dev/null; then + log_warn "Workspace did not shut down gracefully, force killing..." + kill -KILL "$_workspace_pid" 2>/dev/null || true + fi + fi + + # Clean up PID file + [ -f "$PID_FILE" ] && rm -f "$PID_FILE" + + log_info "Shutdown complete." + exit 0 +} + +# Trap termination signals for graceful shutdown +trap cleanup SIGTERM SIGINT + +# ── Gateway Health Check ─────────────────────────────────────── +wait_for_gateway() { + local url="${GATEWAY_URL}${HEALTH_ENDPOINT}" + local retries="$MAX_RETRIES" + local interval="$RETRY_INTERVAL" + local attempt=0 + + log_info "Waiting for Hermes gateway at ${GATEWAY_URL}..." + log_info "Max retries: ${retries}, interval: ${interval}s" + + while [ "$attempt" -lt "$retries" ]; do + attempt=$((attempt + 1)) + + if curl -fsS "${url}" >/dev/null 2>&1; then + log_info "Gateway is healthy after ${attempt} attempt(s) (${GATEWAY_URL})" + return 0 + fi + + if [ "$attempt" -lt "$retries" ]; then + log_info "Gateway not ready yet (attempt ${attempt}/${retries}), retrying in ${interval}s..." + sleep "$interval" + fi + done + + log_error "Gateway did not become healthy after ${retries} attempts (${retries * interval}s)" + return 1 +} + +# ── Workspace Startup ────────────────────────────────────────── +start_workspace() { + local entry="${WORKSPACE_DIR}/${WORKSPACE_ENTRY}" + + if [ ! -d "$WORKSPACE_DIR" ]; then + log_error "Workspace directory not found: ${WORKSPACE_DIR}" + return 1 + fi + + if [ ! -f "$entry" ]; then + log_error "Workspace entry point not found: ${entry}" + return 1 + fi + + log_info "Starting Hermes Workspace web UI..." + log_info " Directory: ${WORKSPACE_DIR}" + log_info " Entry: ${entry}" + + cd "$WORKSPACE_DIR" + + # Start workspace in background so we can trap signals + exec node --max-old-space-size=2048 "${entry}" & + _workspace_pid=$! + echo "$_workspace_pid" > "$PID_FILE" + + log_info "Workspace started (PID: ${_workspace_pid})" + + # Wait for workspace process + wait "$_workspace_pid" + local exit_code=$? + + log_info "Workspace exited with code ${exit_code}" + return "$exit_code" +} + +# ── Main ─────────────────────────────────────────────────────── +main() { + log_info "=== Hermes Workspace Combined Entrypoint ===" + log_info "Gateway: ${GATEWAY_URL}" + log_info "Workspace: ${WORKSPACE_DIR}/${WORKSPACE_ENTRY}" + log_info "PID file: ${PID_FILE}" + + # Wait for gateway to be healthy + if ! wait_for_gateway; then + log_warn "Proceeding without confirmed gateway health..." + fi + + # Start the workspace + start_workspace + local exit_code=$? + + log_info "Entrypoint exiting with code ${exit_code}" + return "$exit_code" +} + +# Run main; exit with its return code +main "$@" diff --git a/replace_compose.py b/replace_compose.py new file mode 100644 index 0000000..4ecd7f3 --- /dev/null +++ b/replace_compose.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +"""Copy the updated txt file over the original yml file.""" +import shutil +import os + +src = "/opt/data/projects/gortium/compose/ai/compose_updated.txt" +dst = "/opt/data/projects/gortium/compose/ai/compose.yml" + +# Check src exists +print(f"Source exists: {os.path.exists(src)}") +print(f"Source size: {os.path.getsize(src)} bytes") +print(f"Destination exists: {os.path.exists(dst)}") + +# Copy +shutil.copy2(src, dst) +print(f"Copied {src} -> {dst}") +print(f"Destination size: {os.path.getsize(dst)} bytes")