services:
  router:
    build:
      context: ./services/router
      dockerfile: Dockerfile
    container_name: dagi-router-node2
    ports:
      - "127.0.0.1:9102:8000"
    environment:
      - NODE_ID=NODA2
      - DAGI_ROUTER_CONFIG=/app/router-config.yml
      - MEMORY_SERVICE_URL=http://memory-service:8000
      - NATS_URL=nats://dagi-nats:4222
      - QDRANT_HOST=qdrant-node2
      - QDRANT_PORT=6333
      - DATABASE_URL=postgresql://daarion:daarion_secret_node2@postgres-node2:5432/daarion_memory
      - NEO4J_BOLT_URL=bolt://neo4j-node2:7687
      - NEO4J_USER=neo4j
      - NEO4J_PASSWORD=daarion_node2_secret
      - CITY_SERVICE_URL=http://city-service:7001
      - PIECES_OS_URL=http://host.docker.internal:39300
      - NOTION_API_KEY=${NOTION_API_KEY:-}
      - XAI_API_KEY=${XAI_API_KEY}
      - GROK_API_KEY=${XAI_API_KEY}
      - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}
      # ── Fabric Layer (NCS + Node Worker, no Swapper dependency) ──────────
      - NODE_CAPABILITIES_URL=http://node-capabilities:8099/capabilities
      - ENABLE_GLOBAL_CAPS_NATS=true
      - OLLAMA_URL=http://host.docker.internal:11434
      - PREFER_NODE_WORKER=true
      # ── Persistence backends ──────────────────────────────────────────────
      - ALERT_BACKEND=postgres
      - ALERT_DATABASE_URL=${ALERT_DATABASE_URL:-${DATABASE_URL}}
      - RISK_HISTORY_BACKEND=auto
      - BACKLOG_BACKEND=auto
      - INCIDENT_BACKEND=auto
      - AUDIT_BACKEND=auto
      - CALENDAR_SERVICE_URL=http://calendar-service:8001
    volumes:
      - ./services/router/router-config.node2.yml:/app/router-config.yml:ro
      - ./tools:/app/tools:ro
      - ./config:/config:ro
      - ./logs:/app/logs
    extra_hosts:
      - "host.docker.internal:host-gateway"
      - "city-service:host-gateway"
      - "daarion-city-service:host-gateway"
    depends_on:
      - dagi-nats
      - node-capabilities
      - calendar-service
    networks:
      - dagi-network
      - dagi-memory-network
    restart: unless-stopped

  gateway:
    build:
      context: ./gateway-bot
      dockerfile: Dockerfile
    container_name: dagi-gateway-node2
    ports:
      - "0.0.0.0:9300:9300"
    environment:
      - ROUTER_URL=http://router:8000
      - DAARWIZZ_NAME=DAARWIZZ
      - DAARWIZZ_PROMPT_PATH=/app/gateway-bot/daarwizz_prompt.txt
      - MEMORY_SERVICE_URL=http://memory-service:8000
      - SOFIIA_NAME=SOFIIA
      - SOFIIA_PROMPT_PATH=/app/gateway-bot/sofiia_prompt.txt
      - SOFIIA_TELEGRAM_BOT_TOKEN=${SOFIIA_TELEGRAM_BOT_TOKEN}
    volumes:
      - ./gateway-bot:/app/gateway-bot:ro
      - ./logs:/app/logs
    depends_on:
      - router
    networks:
      - dagi-network
      - dagi-memory-network
    restart: unless-stopped

  aurora-service:
    build:
      context: ./services/aurora-service
      dockerfile: Dockerfile
    container_name: aurora-service-node2
    ports:
      - "127.0.0.1:9402:9401"
    environment:
      - AURORA_DATA_DIR=/data/aurora
      - AURORA_PUBLIC_BASE_URL=http://127.0.0.1:9402
      - AURORA_CORS_ORIGINS=*
      - AURORA_MODELS_DIR=/data/aurora/models
      - AURORA_FORCE_CPU=false
      - AURORA_PREFER_MPS=true
      - AURORA_ENABLE_VIDEOTOOLBOX=true
      - KLING_ACCESS_KEY=${KLING_ACCESS_KEY:-}
      - KLING_SECRET_KEY=${KLING_SECRET_KEY:-}
      - KLING_BASE_URL=${KLING_BASE_URL:-https://api.klingai.com}
      - KLING_TIMEOUT=${KLING_TIMEOUT:-60}
    volumes:
      - sofiia-data:/data
    networks:
      - dagi-network
    restart: unless-stopped

  radicale:
    image: tomsquest/docker-radicale:latest
    container_name: daarion-radicale-node2
    ports:
      - "127.0.0.1:5232:5232"
    environment:
      - RADICALE_HOST=0.0.0.0
      - RADICALE_PORT=5232
      - RADICALE_LOG_LEVEL=INFO
    volumes:
      - radicale-data:/data
      - radicale-config:/config
    networks:
      - dagi-network
    restart: unless-stopped

  calendar-service:
    build:
      context: ./services/calendar-service
      dockerfile: Dockerfile
    container_name: calendar-service-node2
    ports:
      - "127.0.0.1:8001:8001"
    environment:
      - DATABASE_URL=sqlite:////data/calendar.db
      - RADICALE_URL=http://radicale:5232
      - PYTHONUNBUFFERED=1
    depends_on:
      - radicale
    volumes:
      - sofiia-data:/data
    networks:
      - dagi-network
    restart: unless-stopped

  dagi-nats:
    image: nats:2.10-alpine
    container_name: dagi-nats-node2
    ports:
      - "4222:4222"
      - "8222:8222"
    command: -c /etc/nats/nats-server.conf
    volumes:
      - ./nats-server.conf:/etc/nats/nats-server.conf:ro
    networks:
      - dagi-network
    restart: unless-stopped
    
  swapper-service:
    build:
      context: ./services/swapper-service
      dockerfile: Dockerfile
    container_name: swapper-service-node2
    ports:
      - "127.0.0.1:8890:8890"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    environment:
      - OLLAMA_BASE_URL=http://host.docker.internal:11434
      - SWAPPER_CONFIG_PATH=/app/config/swapper_config_node2.yaml
      - SWAPPER_MODE=single-active
      - MODEL_SWAP_TIMEOUT=300
    volumes:
      - ./services/swapper-service/config:/app/config:ro
      - ./logs:/app/logs
    networks:
      - dagi-network
    restart: unless-stopped

  node-capabilities:
    build:
      context: ./services/node-capabilities
      dockerfile: Dockerfile
    container_name: node-capabilities-node2
    ports:
      - "127.0.0.1:8099:8099"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - ~/.ollama/models:/host_models/ollama:ro
      - ~/.cache/huggingface/hub:/host_models/hf_cache:ro
    environment:
      - NODE_ID=NODA2
      - OLLAMA_BASE_URL=http://host.docker.internal:11434
      - SWAPPER_URL=
      - LLAMA_SERVER_URL=http://host.docker.internal:11435
      - CACHE_TTL_SEC=15
      - ENABLE_NATS_CAPS=true
      - NATS_URL=nats://dagi-nats:4222
      - NODE_WORKER_URL=http://node-worker:8109
      - DISK_SCAN_PATHS=/host_models/ollama,/host_models/hf_cache
    depends_on:
      - swapper-service
      - dagi-nats
    networks:
      - dagi-network
    restart: unless-stopped

  node-worker:
    build:
      context: ./services/node-worker
      dockerfile: Dockerfile
    container_name: node-worker-node2
    ports:
      - "127.0.0.1:8109:8109"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    environment:
      - NODE_ID=noda2
      - NATS_URL=nats://dagi-nats:4222
      - OLLAMA_BASE_URL=http://host.docker.internal:11434
      - NODE_DEFAULT_LLM=qwen3:14b
      - NODE_DEFAULT_VISION=llava:13b
      - NODE_WORKER_MAX_CONCURRENCY=2
      - NCS_REPORT_URL=http://node-capabilities:8099
      # Capability providers: delegate STT/TTS to Memory Service (Phase 1)
      # Set to mlx_whisper/mlx_kokoro for Phase 2 MLX upgrade
      - STT_PROVIDER=memory_service
      - TTS_PROVIDER=memory_service
      - MEMORY_SERVICE_URL=http://memory-service:8000
      - OCR_PROVIDER=vision_prompted
      - IMAGE_PROVIDER=none
      # Voice HA: dedicated concurrency limits for voice.*.request subjects
      - VOICE_MAX_CONCURRENT_TTS=4
      - VOICE_MAX_CONCURRENT_LLM=2
      - VOICE_MAX_CONCURRENT_STT=2
    depends_on:
      - dagi-nats
    networks:
      - dagi-network
    restart: unless-stopped

  sofiia-console:
    build:
      context: ./services/sofiia-console
      dockerfile: Dockerfile
    container_name: sofiia-console
    ports:
      - "127.0.0.1:8002:8002"
    environment:
      - PORT=8002
      - ENV=${ENV:-prod}
      - NODE_ID=NODA2
      - ROUTER_URL=http://router:8000
      - CONFIG_DIR=/app/config
      - NODES_NODA2_ROUTER_URL=http://router:8000
      - NODES_NODA1_ROUTER_URL=http://144.76.224.179:9102
      - MEMORY_SERVICE_URL=http://memory-service:8000
      - OLLAMA_URL=${OLLAMA_URL:-http://host.docker.internal:11434}
      - NOTION_API_KEY=${NOTION_API_KEY:-}
      - OPENCODE_URL=${OPENCODE_URL:-}
      - AURORA_SERVICE_URL=http://aurora-service:9401
      # P1 SECURITY: SSH_PASSWORD removed — use key file instead
      # NODES_NODA1_SSH_PASSWORD is NO LONGER passed; sofiia-console reads from key file
      - NODES_NODA1_SSH_PRIVATE_KEY=/run/secrets/noda1_ssh_key
      - SUPERVISOR_API_KEY=${SUPERVISOR_API_KEY}
      - SOFIIA_CONSOLE_API_KEY=${SOFIIA_CONSOLE_API_KEY}
      - CORS_ORIGINS=${CORS_ORIGINS:-}
      # Voice HA feature flag (default: false = legacy direct path to memory-service)
      - VOICE_HA_ENABLED=${VOICE_HA_ENABLED:-false}
      - VOICE_HA_ROUTER_URL=${VOICE_HA_ROUTER_URL:-http://router:8000}
      # Projects / Documents / Sessions / Dialog Map (SQLite)
      - SOFIIA_DATA_DIR=/app/data
      - UPLOAD_MAX_IMAGE_MB=${UPLOAD_MAX_IMAGE_MB:-10}
      - UPLOAD_MAX_VIDEO_MB=${UPLOAD_MAX_VIDEO_MB:-200}
      - UPLOAD_MAX_DOC_MB=${UPLOAD_MAX_DOC_MB:-50}
      # Phase 2 feature flags (disabled by default)
      - USE_FABRIC_OCR=${USE_FABRIC_OCR:-false}
      - USE_EMBEDDINGS=${USE_EMBEDDINGS:-false}
      # Supervisor proxy (LangGraph workflows)
      - SUPERVISOR_URL=${SUPERVISOR_URL:-http://sofiia-supervisor:8080}
    volumes:
      - ./config:/app/config
      - ./secrets/noda1_id_ed25519:/run/secrets/noda1_ssh_key:ro
      - sofiia-data:/app/data
    depends_on:
      - router
    networks:
      - dagi-network
      - dagi-memory-network
    restart: unless-stopped

networks:
  dagi-network:
    driver: bridge
    name: dagi-network-node2
  dagi-memory-network:
    external: true
    name: dagi-memory-network-node2

volumes:
  sofiia-data:
    driver: local
  radicale-data:
    driver: local
  radicale-config:
    driver: local
