From c0ca166d43807fe014b25a5b4caa9b2d45e585f4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Feb 2026 18:08:57 +0000 Subject: [PATCH] fix: improve macOS deployment compatibility and Docker build hygiene - .gitignore: add missing macOS artifacts (.AppleDouble, .Spotlight-V100, etc.) - Makefile: fix `make ip` to detect network interfaces on both macOS and Linux (adds `ip` command fallback, guards macOS-only `ipconfig` behind uname check) - Makefile: add `make install-creative` target with Apple Silicon Metal guidance - Dockerfile: install deps from pyproject.toml instead of duplicating the list, eliminating drift between Dockerfile and pyproject.toml - docker-compose.yml: document data/ directory prerequisite for bind-mount volume https://claude.ai/code/session_01A81E5HMxZEPxzv2acNo35u --- .gitignore | 8 +++++++- Dockerfile | 31 ++++++++++++------------------- Makefile | 27 ++++++++++++++++++++++----- docker-compose.yml | 3 +++ 4 files changed, 44 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 529a9379..45c6e090 100644 --- a/.gitignore +++ b/.gitignore @@ -37,5 +37,11 @@ reports/ .vscode/ *.swp *.swo -.DS_Store .claude/ + +# macOS +.DS_Store +.AppleDouble +.LSOverride +.Spotlight-V100 +.Trashes diff --git a/Dockerfile b/Dockerfile index 7efebd2c..6ac6daa6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,29 +21,22 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ WORKDIR /app # ── Python deps (install before copying src for layer caching) ─────────────── +# Copy only pyproject.toml first so Docker can cache the dep-install layer. +# The editable install (-e) happens after src is copied below. COPY pyproject.toml . -# Install production deps only (no dev/test extras in the image) -RUN pip install --no-cache-dir \ - "fastapi>=0.115.0" \ - "uvicorn[standard]>=0.32.0" \ - "jinja2>=3.1.0" \ - "httpx>=0.27.0" \ - "python-multipart>=0.0.12" \ - "aiofiles>=24.0.0" \ - "typer>=0.12.0" \ - "rich>=13.0.0" \ - "pydantic-settings>=2.0.0" \ - "websockets>=12.0" \ - "agno[sqlite]>=1.4.0" \ - "ollama>=0.3.0" \ - "openai>=1.0.0" \ - "python-telegram-bot>=21.0" \ - "GitPython>=3.1.40" \ - "moviepy>=2.0.0" \ - "redis>=5.0.0" +# Create a minimal src layout so `pip install` can resolve the package metadata +# without copying the full source tree (preserves Docker layer caching). +RUN mkdir -p src/timmy src/timmy_serve src/self_tdd src/dashboard && \ + touch src/timmy/__init__.py src/timmy/cli.py \ + src/timmy_serve/__init__.py src/timmy_serve/cli.py \ + src/self_tdd/__init__.py src/self_tdd/watchdog.py \ + src/dashboard/__init__.py src/config.py + +RUN pip install --no-cache-dir -e ".[swarm,telegram]" # ── Application source ─────────────────────────────────────────────────────── +# Overwrite the stubs with real source code COPY src/ ./src/ COPY static/ ./static/ diff --git a/Makefile b/Makefile index 97d5a21b..498220e2 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: install install-bigbrain dev nuke test test-cov test-cov-html watch lint clean help \ +.PHONY: install install-bigbrain install-creative dev nuke test test-cov test-cov-html watch lint clean help \ up down logs \ docker-build docker-up docker-down docker-agent docker-logs docker-shell \ cloud-deploy cloud-up cloud-down cloud-logs cloud-status cloud-update @@ -25,6 +25,17 @@ install-bigbrain: $(VENV)/bin/activate echo "✓ AirLLM installed (PyTorch backend)"; \ fi +install-creative: $(VENV)/bin/activate + $(PIP) install --quiet -e ".[dev,creative]" + @if [ "$$(uname -s)" = "Darwin" ]; then \ + echo ""; \ + echo " Note: PyTorch on macOS uses CPU by default."; \ + echo " For Metal (GPU) acceleration, install the nightly build:"; \ + echo " pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cpu"; \ + echo ""; \ + fi + @echo "✓ Creative extras installed (diffusers, torch, ace-step)" + $(VENV)/bin/activate: python3 -m venv $(VENV) @@ -54,10 +65,15 @@ ip: @echo "" @echo " Open one of these on your phone: http://:8000" @echo "" - @ipconfig getifaddr en0 2>/dev/null | awk '{print " en0 (Wi-Fi): http://" $$1 ":8000"}' || true - @ipconfig getifaddr en1 2>/dev/null | awk '{print " en1 (Ethernet): http://" $$1 ":8000"}' || true - @ipconfig getifaddr en2 2>/dev/null | awk '{print " en2: http://" $$1 ":8000"}' || true - @ifconfig 2>/dev/null | awk '/inet / && !/127\.0\.0\.1/ && !/::1/{print " " $$2 " → http://" $$2 ":8000"}' | head -5 || true + @if [ "$$(uname -s)" = "Darwin" ]; then \ + ipconfig getifaddr en0 2>/dev/null | awk '{print " en0 (Wi-Fi): http://" $$1 ":8000"}' || true; \ + ipconfig getifaddr en1 2>/dev/null | awk '{print " en1 (Ethernet): http://" $$1 ":8000"}' || true; \ + ipconfig getifaddr en2 2>/dev/null | awk '{print " en2: http://" $$1 ":8000"}' || true; \ + fi + @# Generic fallback — works on both macOS and Linux + @ifconfig 2>/dev/null | awk '/inet / && !/127\.0\.0\.1/ && !/::1/{print " " $$2 " → http://" $$2 ":8000"}' | head -5 \ + || ip -4 addr show 2>/dev/null | awk '/inet / && !/127\.0\.0\.1/{split($$2,a,"/"); print " " a[1] " → http://" a[1] ":8000"}' | head -5 \ + || true @echo "" watch: @@ -202,6 +218,7 @@ help: @echo " ─────────────────────────────────────────────────" @echo " make install create venv + install dev deps" @echo " make install-bigbrain install with AirLLM (big-model backend)" + @echo " make install-creative install with creative extras (torch, diffusers)" @echo " make dev clean up + start dashboard (auto-fixes errno 48)" @echo " make nuke kill port 8000, stop containers, reset state" @echo " make ip print local IP addresses for phone testing" diff --git a/docker-compose.yml b/docker-compose.yml index 8c229a83..91180830 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -93,6 +93,9 @@ services: restart: unless-stopped # ── Shared volume ───────────────────────────────────────────────────────────── +# NOTE: the data/ directory must exist before running docker compose up. +# `make docker-up` and `make up` handle this automatically. +# If running docker compose directly, first run: mkdir -p data volumes: timmy-data: driver: local