Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
1 line
138 KiB
JSON
1 line
138 KiB
JSON
{"repo": "brain-researcher/brain-researcher-public", "files": {"docker-compose.yml": {"3305b62aef6852ddf0b33fde658e0048a4af65da": {"t": 1785745240.1459904, "n": 7100, "h": "cf767818424f97b4", "c": "name: brain-researcher\n\nservices:\n init-local-dirs:\n image: alpine:3.20\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-init-local-dirs\n command:\n - sh\n - -c\n - >\n mkdir -p /data/agent_outputs/sessions /data/br-kg/db /data/br-kg/logs /logs\n && chown -R 1000:1000 /data/agent_outputs /data/br-kg /logs\n volumes:\n - ./data:/data\n - ./logs:/logs\n restart: \"no\"\n\n neo4j:\n image: neo4j:5.20\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-neo4j\n ports:\n - \"${BIND_ADDRESS:-127.0.0.1}:${BR_NEO4J_BOLT_PORT:-7687}:7687\"\n - \"${BIND_ADDRESS:-127.0.0.1}:${BR_NEO4J_HTTP_PORT:-7474}:7474\"\n environment:\n - NEO4J_AUTH=neo4j/${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_USERNAME=neo4j\n - NEO4J_PASSWORD=${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_server_memory_pagecache_size=512M\n - NEO4J_server_memory_heap_initial__size=512M\n - NEO4J_server_memory_heap_max__size=1G\n volumes:\n - ./data/neo4j:/data\n - ./backups/neo4j:/data/backups\n restart: unless-stopped\n healthcheck:\n test: [\"CMD\", \"cypher-shell\", \"-a\", \"bolt://localhost:7687\", \"RETURN 1\"]\n interval: 20s\n timeout: 5s\n start_period: 20s\n retries: 6\n\n # BR-KG API Service\n br-kg:\n build:\n context: .\n target: br-kg\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-br-kg\n depends_on:\n init-local-dirs:\n condition: service_completed_successfully\n neo4j:\n condition: service_healthy\n ports:\n - \"${BIND_ADDRESS:-127.0.0.1}:${BR_KG_PORT:-5000}:5000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./src:/app/src\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - PORT=5000\n - FLASK_APP=brain_researcher.services.br_kg.api.graph_api:app\n - NEO4J_URI=bolt://neo4j:7687\n - NEO4J_USER=neo4j\n - NEO4J_PASSWORD=${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_PRELOAD_CACHE=0\n command: [ \"python\", \"-m\", \"brain_researcher.services.br_kg.app\" ]\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Agent Service\n agent:\n image: brain_researcher-agent\n build:\n context: .\n target: agent\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-agent\n depends_on:\n init-local-dirs:\n condition: service_completed_successfully\n br-kg:\n condition: service_healthy\n redis:\n condition: service_healthy\n ports:\n - \"${BIND_ADDRESS:-127.0.0.1}:${AGENT_PORT:-8000}:8000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./src:/app/src:ro\n - ./configs:/app/configs:ro\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - BR_KG_URL=http://br-kg:5000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - THREAD_STORE_REDIS_URL=redis://redis:6379/0\n - REDIS_URL=redis://redis:6379/1\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - DISABLE_AUTH_FOR_DEV=0\n - ORCHESTRATOR_UPLOAD_DIR=/tmp/brain_researcher_uploads/chat\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - GEMINI_API_KEY=${GEMINI_API_KEY:-}\n - BR_ALLOW_RUN_ID_OVERRIDE=1\n - DEFAULT_LLM_MODEL=${DEFAULT_LLM_MODEL:-gemini-2.0-flash}\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Orchestrator worker (no longer UI gateway; optional)\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-orchestrator\n profiles: [ \"worker\" ] # start with `docker compose --profile worker up`\n depends_on:\n agent:\n condition: service_healthy\n br-kg:\n condition: service_healthy\n redis:\n condition: service_healthy\n ports:\n - \"${BIND_ADDRESS:-127.0.0.1}:${ORCHESTRATOR_PORT:-3001}:3001\"\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n # Foundation model optional; provide if service is running\n # - NICLIP_URL=http://niclip:8001\n - REDIS_URL=redis://redis:6379\n - BR_MCP_TOKEN_PEPPER=${BR_MCP_TOKEN_PEPPER:-}\n - BR_MCP_TOKEN_PEPPER_VERSION=${BR_MCP_TOKEN_PEPPER_VERSION:-v1}\n - BR_MCP_TOKEN_REDIS_PREFIX=${BR_MCP_TOKEN_REDIS_PREFIX:-mcp_token}\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n restart: unless-stopped\n\n # Web UI (Next.js) - talks directly to Agent & BR-KG\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-web-ui\n depends_on:\n agent:\n condition: service_healthy\n br-kg:\n condition: service_healthy\n ports:\n - \"${BIND_ADDRESS:-127.0.0.1}:${WEB_UI_PORT:-3000}:3000\"\n volumes:\n - ./configs:/app/configs:ro\n environment:\n - NODE_ENV=production\n - BR_AGENT_URL=http://agent:8000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - NEXT_PUBLIC_AGENT_URL=http://agent:8000\n - NEXT_PUBLIC_BR_KG_URL=http://br-kg:5000\n - BR_KG_URL=http://br-kg:5000\n - NEXT_PUBLIC_API_URL=http://agent:8000 # legacy alias\n - NEXT_PUBLIC_ORCHESTRATOR_URL=http://localhost:3001\n - NEXT_PUBLIC_APP_NAME=Brain Researcher Web\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - NEXTAUTH_SECRET=${NEXTAUTH_SECRET:?set NEXTAUTH_SECRET}\n - ENABLE_DEV_CREDENTIALS=${ENABLE_DEV_CREDENTIALS:-0}\n - DEV_CREDENTIALS_EMAIL=${DEV_CREDENTIALS_EMAIL:-}\n - DEV_CREDENTIALS_PASSWORD=${DEV_CREDENTIALS_PASSWORD:-}\n - AGENT_HOST=agent\n - BR_KG_HOST=br-kg\n - AGENT_BASE_URL=http://agent:8000\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD-SHELL\", \"IP=$$(hostname -i || echo 127.0.0.1); IP=$$IP node -e \\\"const ip=process.env.IP||'127.0.0.1'; require('http').get('http://'+ip+':3000/',(r)=>{process.exit(r.statusCode>=200 && r.statusCode<400 ? 0 : 1);}).on('error',()=>process.exit(1));\\\"\" ]\n interval: 30s\n timeout: 10s\n retries: 5\n\n # Redis for Agent State Management (optional)\n redis:\n image: redis:7-alpine\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-redis\n volumes:\n - redis_data:/data\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"redis-cli\", \"ping\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\nvolumes:\n redis_data:\n\n # Network configuration (optional, for isolation)\nnetworks:\n default:\n name: ${COMPOSE_PROJECT_NAME:-brain-researcher}\n"}, "62482fe171a5072e49a5a743bd26b776d42b64b0": {"t": 1785749118.9431996, "n": 7100, "h": "cf767818424f97b4", "c": "name: brain-researcher\n\nservices:\n init-local-dirs:\n image: alpine:3.20\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-init-local-dirs\n command:\n - sh\n - -c\n - >\n mkdir -p /data/agent_outputs/sessions /data/br-kg/db /data/br-kg/logs /logs\n && chown -R 1000:1000 /data/agent_outputs /data/br-kg /logs\n volumes:\n - ./data:/data\n - ./logs:/logs\n restart: \"no\"\n\n neo4j:\n image: neo4j:5.20\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-neo4j\n ports:\n - \"${BIND_ADDRESS:-127.0.0.1}:${BR_NEO4J_BOLT_PORT:-7687}:7687\"\n - \"${BIND_ADDRESS:-127.0.0.1}:${BR_NEO4J_HTTP_PORT:-7474}:7474\"\n environment:\n - NEO4J_AUTH=neo4j/${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_USERNAME=neo4j\n - NEO4J_PASSWORD=${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_server_memory_pagecache_size=512M\n - NEO4J_server_memory_heap_initial__size=512M\n - NEO4J_server_memory_heap_max__size=1G\n volumes:\n - ./data/neo4j:/data\n - ./backups/neo4j:/data/backups\n restart: unless-stopped\n healthcheck:\n test: [\"CMD\", \"cypher-shell\", \"-a\", \"bolt://localhost:7687\", \"RETURN 1\"]\n interval: 20s\n timeout: 5s\n start_period: 20s\n retries: 6\n\n # BR-KG API Service\n br-kg:\n build:\n context: .\n target: br-kg\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-br-kg\n depends_on:\n init-local-dirs:\n condition: service_completed_successfully\n neo4j:\n condition: service_healthy\n ports:\n - \"${BIND_ADDRESS:-127.0.0.1}:${BR_KG_PORT:-5000}:5000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./src:/app/src\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - PORT=5000\n - FLASK_APP=brain_researcher.services.br_kg.api.graph_api:app\n - NEO4J_URI=bolt://neo4j:7687\n - NEO4J_USER=neo4j\n - NEO4J_PASSWORD=${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_PRELOAD_CACHE=0\n command: [ \"python\", \"-m\", \"brain_researcher.services.br_kg.app\" ]\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Agent Service\n agent:\n image: brain_researcher-agent\n build:\n context: .\n target: agent\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-agent\n depends_on:\n init-local-dirs:\n condition: service_completed_successfully\n br-kg:\n condition: service_healthy\n redis:\n condition: service_healthy\n ports:\n - \"${BIND_ADDRESS:-127.0.0.1}:${AGENT_PORT:-8000}:8000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./src:/app/src:ro\n - ./configs:/app/configs:ro\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - BR_KG_URL=http://br-kg:5000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - THREAD_STORE_REDIS_URL=redis://redis:6379/0\n - REDIS_URL=redis://redis:6379/1\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - DISABLE_AUTH_FOR_DEV=0\n - ORCHESTRATOR_UPLOAD_DIR=/tmp/brain_researcher_uploads/chat\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - GEMINI_API_KEY=${GEMINI_API_KEY:-}\n - BR_ALLOW_RUN_ID_OVERRIDE=1\n - DEFAULT_LLM_MODEL=${DEFAULT_LLM_MODEL:-gemini-2.0-flash}\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Orchestrator worker (no longer UI gateway; optional)\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-orchestrator\n profiles: [ \"worker\" ] # start with `docker compose --profile worker up`\n depends_on:\n agent:\n condition: service_healthy\n br-kg:\n condition: service_healthy\n redis:\n condition: service_healthy\n ports:\n - \"${BIND_ADDRESS:-127.0.0.1}:${ORCHESTRATOR_PORT:-3001}:3001\"\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n # Foundation model optional; provide if service is running\n # - NICLIP_URL=http://niclip:8001\n - REDIS_URL=redis://redis:6379\n - BR_MCP_TOKEN_PEPPER=${BR_MCP_TOKEN_PEPPER:-}\n - BR_MCP_TOKEN_PEPPER_VERSION=${BR_MCP_TOKEN_PEPPER_VERSION:-v1}\n - BR_MCP_TOKEN_REDIS_PREFIX=${BR_MCP_TOKEN_REDIS_PREFIX:-mcp_token}\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n restart: unless-stopped\n\n # Web UI (Next.js) - talks directly to Agent & BR-KG\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-web-ui\n depends_on:\n agent:\n condition: service_healthy\n br-kg:\n condition: service_healthy\n ports:\n - \"${BIND_ADDRESS:-127.0.0.1}:${WEB_UI_PORT:-3000}:3000\"\n volumes:\n - ./configs:/app/configs:ro\n environment:\n - NODE_ENV=production\n - BR_AGENT_URL=http://agent:8000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - NEXT_PUBLIC_AGENT_URL=http://agent:8000\n - NEXT_PUBLIC_BR_KG_URL=http://br-kg:5000\n - BR_KG_URL=http://br-kg:5000\n - NEXT_PUBLIC_API_URL=http://agent:8000 # legacy alias\n - NEXT_PUBLIC_ORCHESTRATOR_URL=http://localhost:3001\n - NEXT_PUBLIC_APP_NAME=Brain Researcher Web\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - NEXTAUTH_SECRET=${NEXTAUTH_SECRET:?set NEXTAUTH_SECRET}\n - ENABLE_DEV_CREDENTIALS=${ENABLE_DEV_CREDENTIALS:-0}\n - DEV_CREDENTIALS_EMAIL=${DEV_CREDENTIALS_EMAIL:-}\n - DEV_CREDENTIALS_PASSWORD=${DEV_CREDENTIALS_PASSWORD:-}\n - AGENT_HOST=agent\n - BR_KG_HOST=br-kg\n - AGENT_BASE_URL=http://agent:8000\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD-SHELL\", \"IP=$$(hostname -i || echo 127.0.0.1); IP=$$IP node -e \\\"const ip=process.env.IP||'127.0.0.1'; require('http').get('http://'+ip+':3000/',(r)=>{process.exit(r.statusCode>=200 && r.statusCode<400 ? 0 : 1);}).on('error',()=>process.exit(1));\\\"\" ]\n interval: 30s\n timeout: 10s\n retries: 5\n\n # Redis for Agent State Management (optional)\n redis:\n image: redis:7-alpine\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-redis\n volumes:\n - redis_data:/data\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"redis-cli\", \"ping\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\nvolumes:\n redis_data:\n\n # Network configuration (optional, for isolation)\nnetworks:\n default:\n name: ${COMPOSE_PROJECT_NAME:-brain-researcher}\n"}, "4e30a299d8efec82c88f1ea59e143b330ea8ced7": {"t": 1785749120.011334, "n": 6845, "h": "4c40d05e7f674c28", "c": "name: brain-researcher\n\nservices:\n init-local-dirs:\n image: alpine:3.20\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-init-local-dirs\n command:\n - sh\n - -c\n - >\n mkdir -p /data/agent_outputs/sessions /data/br-kg/db /data/br-kg/logs /logs\n && chown -R 1000:1000 /data/agent_outputs /data/br-kg /logs\n volumes:\n - ./data:/data\n - ./logs:/logs\n restart: \"no\"\n\n neo4j:\n image: neo4j:5.20\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-neo4j\n ports:\n - \"${BR_NEO4J_BOLT_PORT:-7687}:7687\"\n - \"${BR_NEO4J_HTTP_PORT:-7474}:7474\"\n environment:\n - NEO4J_AUTH=neo4j/${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_server_memory_pagecache_size=512M\n - NEO4J_server_memory_heap_initial__size=512M\n - NEO4J_server_memory_heap_max__size=1G\n volumes:\n - ./data/neo4j:/data\n - ./backups/neo4j:/data/backups\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD-SHELL\", \"cypher-shell -a bolt://localhost:7687 -u neo4j -p ${NEO4J_PASSWORD:?set NEO4J_PASSWORD} 'RETURN 1'\" ]\n interval: 20s\n timeout: 5s\n start_period: 20s\n retries: 6\n\n # BR-KG API Service\n br-kg:\n build:\n context: .\n target: br-kg\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-br-kg\n depends_on:\n init-local-dirs:\n condition: service_completed_successfully\n neo4j:\n condition: service_healthy\n ports:\n - \"${BR_KG_PORT:-5000}:5000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./src:/app/src\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - PORT=5000\n - FLASK_APP=brain_researcher.services.br_kg.api.graph_api:app\n - NEO4J_URI=bolt://neo4j:7687\n - NEO4J_USER=neo4j\n - NEO4J_PASSWORD=${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_PRELOAD_CACHE=0\n command: [ \"python\", \"-m\", \"brain_researcher.services.br_kg.app\" ]\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Agent Service\n agent:\n image: brain_researcher-agent\n build:\n context: .\n target: agent\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-agent\n depends_on:\n init-local-dirs:\n condition: service_completed_successfully\n br-kg:\n condition: service_healthy\n redis:\n condition: service_healthy\n ports:\n - \"${AGENT_PORT:-8000}:8000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./src:/app/src:ro\n - ./configs:/app/configs:ro\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - BR_KG_URL=http://br-kg:5000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - THREAD_STORE_REDIS_URL=redis://redis:6379/0\n - REDIS_URL=redis://redis:6379/1\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - DISABLE_AUTH_FOR_DEV=0\n - ORCHESTRATOR_UPLOAD_DIR=/tmp/brain_researcher_uploads/chat\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - GEMINI_API_KEY=${GEMINI_API_KEY:-}\n - BR_ALLOW_RUN_ID_OVERRIDE=1\n - DEFAULT_LLM_MODEL=${DEFAULT_LLM_MODEL:-gemini-2.0-flash}\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Orchestrator worker (no longer UI gateway; optional)\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-orchestrator\n profiles: [ \"worker\" ] # start with `docker compose --profile worker up`\n depends_on:\n agent:\n condition: service_healthy\n br-kg:\n condition: service_healthy\n redis:\n condition: service_healthy\n ports:\n - \"${ORCHESTRATOR_PORT:-3001}:3001\"\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n # Foundation model optional; provide if service is running\n # - NICLIP_URL=http://niclip:8001\n - REDIS_URL=redis://redis:6379\n - BR_MCP_TOKEN_PEPPER=${BR_MCP_TOKEN_PEPPER:-}\n - BR_MCP_TOKEN_PEPPER_VERSION=${BR_MCP_TOKEN_PEPPER_VERSION:-v1}\n - BR_MCP_TOKEN_REDIS_PREFIX=${BR_MCP_TOKEN_REDIS_PREFIX:-mcp_token}\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n restart: unless-stopped\n\n # Web UI (Next.js) - talks directly to Agent & BR-KG\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-web-ui\n depends_on:\n agent:\n condition: service_healthy\n br-kg:\n condition: service_healthy\n ports:\n - \"${WEB_UI_PORT:-3000}:3000\"\n volumes:\n - ./configs:/app/configs:ro\n environment:\n - NODE_ENV=production\n - BR_AGENT_URL=http://agent:8000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - NEXT_PUBLIC_AGENT_URL=http://agent:8000\n - NEXT_PUBLIC_BR_KG_URL=http://br-kg:5000\n - BR_KG_URL=http://br-kg:5000\n - NEXT_PUBLIC_API_URL=http://agent:8000 # legacy alias\n - NEXT_PUBLIC_ORCHESTRATOR_URL=http://localhost:3001\n - NEXT_PUBLIC_APP_NAME=Brain Researcher Web\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - NEXTAUTH_SECRET=${NEXTAUTH_SECRET:?set NEXTAUTH_SECRET}\n - ENABLE_DEV_CREDENTIALS=1\n - DEV_CREDENTIALS_EMAIL=demo@example.com\n - DEV_CREDENTIALS_PASSWORD=DemoPass123!\n - AGENT_HOST=agent\n - BR_KG_HOST=br-kg\n - AGENT_BASE_URL=http://agent:8000\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD-SHELL\", \"IP=$$(hostname -i || echo 127.0.0.1); IP=$$IP node -e \\\"const ip=process.env.IP||'127.0.0.1'; require('http').get('http://'+ip+':3000/',(r)=>{process.exit(r.statusCode>=200 && r.statusCode<400 ? 0 : 1);}).on('error',()=>process.exit(1));\\\"\" ]\n interval: 30s\n timeout: 10s\n retries: 5\n\n # Redis for Agent State Management (optional)\n redis:\n image: redis:7-alpine\n container_name: ${COMPOSE_PROJECT_NAME:-brain-researcher}-redis\n volumes:\n - redis_data:/data\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"redis-cli\", \"ping\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\nvolumes:\n redis_data:\n\n # Network configuration (optional, for isolation)\nnetworks:\n default:\n name: ${COMPOSE_PROJECT_NAME:-brain-researcher}\n"}, "cdfb137a88bda31bd8d2959c0c2037ce9fbcf115": {"t": 1785749121.3150082, "n": 6451, "h": "04707685372dadf6", "c": "services:\n init-local-dirs:\n image: alpine:3.20\n container_name: brain-researcher-init-local-dirs\n command:\n - sh\n - -c\n - >\n mkdir -p /data/agent_outputs/sessions /data/br-kg/db /data/br-kg/logs /logs\n && chown -R 1000:1000 /data/agent_outputs /data/br-kg /logs\n volumes:\n - ./data:/data\n - ./logs:/logs\n restart: \"no\"\n\n neo4j:\n image: neo4j:5.20\n container_name: brain-researcher-neo4j\n ports:\n - \"${BR_NEO4J_BOLT_PORT:-7687}:7687\"\n - \"${BR_NEO4J_HTTP_PORT:-7474}:7474\"\n environment:\n - NEO4J_AUTH=neo4j/${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_server_memory_pagecache_size=512M\n - NEO4J_server_memory_heap_initial__size=512M\n - NEO4J_server_memory_heap_max__size=1G\n volumes:\n - ./data/neo4j:/data\n - ./backups/neo4j:/data/backups\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD-SHELL\", \"cypher-shell -a bolt://localhost:7687 -u neo4j -p ${NEO4J_PASSWORD:?set NEO4J_PASSWORD} 'RETURN 1'\" ]\n interval: 20s\n timeout: 5s\n start_period: 20s\n retries: 6\n\n # BR-KG API Service\n br-kg:\n build:\n context: .\n target: br-kg\n container_name: brain-researcher-br-kg\n depends_on:\n init-local-dirs:\n condition: service_completed_successfully\n neo4j:\n condition: service_started\n ports:\n - \"${BR_KG_PORT:-5000}:5000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./src:/app/src\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - PORT=5000\n - FLASK_APP=brain_researcher.services.br_kg.api.graph_api:app\n - NEO4J_URI=bolt://neo4j:7687\n - NEO4J_USER=neo4j\n - NEO4J_PASSWORD=${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_PRELOAD_CACHE=0\n command: [ \"python\", \"-m\", \"brain_researcher.services.br_kg.app\" ]\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Agent Service\n agent:\n image: brain_researcher-agent\n build:\n context: .\n target: agent\n container_name: brain-researcher-agent\n depends_on:\n init-local-dirs:\n condition: service_completed_successfully\n br-kg:\n condition: service_started\n redis:\n condition: service_started\n ports:\n - \"${AGENT_PORT:-8000}:8000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./src:/app/src:ro\n - ./configs:/app/configs:ro\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - BR_KG_URL=http://br-kg:5000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - THREAD_STORE_REDIS_URL=redis://redis:6379/0\n - REDIS_URL=redis://redis:6379/1\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - DISABLE_AUTH_FOR_DEV=0\n - ORCHESTRATOR_UPLOAD_DIR=/tmp/brain_researcher_uploads/chat\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - GEMINI_API_KEY=${GEMINI_API_KEY:-}\n - BR_ALLOW_RUN_ID_OVERRIDE=1\n - DEFAULT_LLM_MODEL=${DEFAULT_LLM_MODEL:-gemini-2.0-flash}\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Orchestrator worker (no longer UI gateway; optional)\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n container_name: brain-researcher-orchestrator\n profiles: [ \"worker\" ] # start with `docker compose --profile worker up`\n depends_on:\n - agent\n - br-kg\n - redis\n ports:\n - \"${ORCHESTRATOR_PORT:-3001}:3001\"\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n # Foundation model optional; provide if service is running\n # - NICLIP_URL=http://niclip:8001\n - REDIS_URL=redis://redis:6379\n - BR_MCP_TOKEN_PEPPER=${BR_MCP_TOKEN_PEPPER:-}\n - BR_MCP_TOKEN_PEPPER_VERSION=${BR_MCP_TOKEN_PEPPER_VERSION:-v1}\n - BR_MCP_TOKEN_REDIS_PREFIX=${BR_MCP_TOKEN_REDIS_PREFIX:-mcp_token}\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n restart: unless-stopped\n\n # Web UI (Next.js) - talks directly to Agent & BR-KG\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n container_name: brain-researcher-web-ui\n depends_on:\n - agent\n - br-kg\n ports:\n - \"${WEB_UI_PORT:-3000}:3000\"\n volumes:\n - ./configs:/app/configs:ro\n environment:\n - NODE_ENV=production\n - BR_AGENT_URL=http://agent:8000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - NEXT_PUBLIC_AGENT_URL=http://agent:8000\n - NEXT_PUBLIC_BR_KG_URL=http://br-kg:5000\n - BR_KG_URL=http://br-kg:5000\n - NEXT_PUBLIC_API_URL=http://agent:8000 # legacy alias\n - NEXT_PUBLIC_ORCHESTRATOR_URL=http://localhost:3001\n - NEXT_PUBLIC_APP_NAME=Brain Researcher Web\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - NEXTAUTH_SECRET=${NEXTAUTH_SECRET:?set NEXTAUTH_SECRET}\n - ENABLE_DEV_CREDENTIALS=1\n - DEV_CREDENTIALS_EMAIL=demo@example.com\n - DEV_CREDENTIALS_PASSWORD=DemoPass123!\n - AGENT_HOST=agent\n - BR_KG_HOST=br-kg\n - AGENT_BASE_URL=http://agent:8000\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD-SHELL\", \"IP=$$(hostname -i || echo 127.0.0.1); IP=$$IP node -e \\\"const ip=process.env.IP||'127.0.0.1'; require('http').get('http://'+ip+':3000/',(r)=>{process.exit(r.statusCode>=200 && r.statusCode<400 ? 0 : 1);}).on('error',()=>process.exit(1));\\\"\" ]\n interval: 30s\n timeout: 10s\n retries: 5\n\n # Redis for Agent State Management (optional)\n redis:\n image: redis:7-alpine\n container_name: brain-researcher-redis\n volumes:\n - redis_data:/data\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"redis-cli\", \"ping\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\nvolumes:\n redis_data:\n\n # Network configuration (optional, for isolation)\nnetworks:\n default:\n name: brain-researcher\n"}, "db7adf346fb299057b64957a37fb04137753a70e": {"t": 1785749122.8876274, "n": 5650, "h": "b13c700e1140b68d", "c": "version: '3.8'\n\nservices:\n neo4j:\n image: neo4j:5.20\n container_name: brain-researcher-neo4j\n ports:\n - \"7687:7687\"\n - \"7474:7474\"\n environment:\n - NEO4J_AUTH=neo4j/${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_server_memory_pagecache_size=512M\n - NEO4J_server_memory_heap_initial__size=512M\n - NEO4J_server_memory_heap_max__size=1G\n volumes:\n - ./data/neo4j:/data\n - ./backups/neo4j:/data/backups\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD-SHELL\", \"cypher-shell -a bolt://localhost:7687 -u neo4j -p ${NEO4J_PASSWORD:?set NEO4J_PASSWORD} 'RETURN 1'\" ]\n interval: 20s\n timeout: 5s\n start_period: 20s\n retries: 6\n\n # BR-KG API Service\n br-kg:\n build:\n context: .\n target: br-kg\n container_name: brain-researcher-br-kg\n depends_on:\n - neo4j\n ports:\n - \"5000:5000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./src:/app/src\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - PORT=5000\n - FLASK_APP=brain_researcher.services.br_kg.api.graph_api:app\n - NEO4J_URI=bolt://neo4j:7687\n - NEO4J_USER=neo4j\n - NEO4J_PASSWORD=${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_PRELOAD_CACHE=0\n command: [ \"python\", \"-m\", \"brain_researcher.services.br_kg.app\" ]\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Agent Service\n agent:\n image: brain_researcher-agent\n build:\n context: .\n target: agent\n container_name: brain-researcher-agent\n depends_on:\n - br-kg\n ports:\n - \"${AGENT_PORT:-8000}:8000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./src:/app/src:ro\n - ./configs:/app/configs:ro\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - BR_KG_URL=http://br-kg:5000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - THREAD_STORE_REDIS_URL=redis://redis:6379/0\n - REDIS_URL=redis://redis:6379/1\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - DISABLE_AUTH_FOR_DEV=0\n - ORCHESTRATOR_UPLOAD_DIR=/tmp/brain_researcher_uploads/chat\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - GEMINI_API_KEY=${GEMINI_API_KEY:-}\n - BR_ALLOW_RUN_ID_OVERRIDE=1\n - DEFAULT_LLM_MODEL=${DEFAULT_LLM_MODEL:-gemini-2.0-flash}\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Orchestrator worker (no longer UI gateway; optional)\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n container_name: brain-researcher-orchestrator\n profiles: [ \"worker\" ] # start with `docker compose --profile worker up`\n depends_on:\n - agent\n - br-kg\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n # Foundation model optional; provide if service is running\n # - NICLIP_URL=http://niclip:8001\n - REDIS_URL=redis://redis:6379\n - BR_MCP_TOKEN_PEPPER=${BR_MCP_TOKEN_PEPPER:-}\n - BR_MCP_TOKEN_PEPPER_VERSION=${BR_MCP_TOKEN_PEPPER_VERSION:-v1}\n - BR_MCP_TOKEN_REDIS_PREFIX=${BR_MCP_TOKEN_REDIS_PREFIX:-mcp_token}\n restart: unless-stopped\n\n # Web UI (Next.js) - talks directly to Agent & BR-KG\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n container_name: brain-researcher-web-ui\n depends_on:\n - agent\n - br-kg\n ports:\n - \"${WEB_UI_PORT:-3000}:3000\"\n volumes:\n - ./configs:/app/configs:ro\n environment:\n - NODE_ENV=production\n - BR_AGENT_URL=http://agent:8000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - NEXT_PUBLIC_AGENT_URL=http://agent:8000\n - NEXT_PUBLIC_BR_KG_URL=http://br-kg:5000\n - BR_KG_URL=http://br-kg:5000\n - NEXT_PUBLIC_API_URL=http://agent:8000 # legacy alias\n - NEXT_PUBLIC_ORCHESTRATOR_URL=http://localhost:3001\n - NEXT_PUBLIC_APP_NAME=Brain Researcher Web\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - NEXTAUTH_SECRET=${NEXTAUTH_SECRET:?set NEXTAUTH_SECRET}\n - ENABLE_DEV_CREDENTIALS=1\n - DEV_CREDENTIALS_EMAIL=demo@example.com\n - DEV_CREDENTIALS_PASSWORD=DemoPass123!\n - AGENT_HOST=agent\n - BR_KG_HOST=br-kg\n - AGENT_BASE_URL=http://agent:8000\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD-SHELL\", \"IP=$$(hostname -i || echo 127.0.0.1); IP=$$IP node -e \\\"const ip=process.env.IP||'127.0.0.1'; require('http').get('http://'+ip+':3000/',(r)=>{process.exit(r.statusCode>=200 && r.statusCode<400 ? 0 : 1);}).on('error',()=>process.exit(1));\\\"\" ]\n interval: 30s\n timeout: 10s\n retries: 5\n\n # Redis for Agent State Management (optional)\n redis:\n image: redis:7-alpine\n container_name: brain-researcher-redis\n volumes:\n - redis_data:/data\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"redis-cli\", \"ping\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\nvolumes:\n redis_data:\n\n # Network configuration (optional, for isolation)\nnetworks:\n default:\n name: brain-researcher\n"}, "ba5c18fca5405755729e6b0bcb7c737c827f6ed2": {"t": 1785749124.0033236, "n": 5713, "h": "164b93101aa0b67c", "c": "version: '3.8'\n\nservices:\n neo4j:\n image: neo4j:5.20\n container_name: brain-researcher-neo4j\n ports:\n - \"7687:7687\"\n - \"7474:7474\"\n environment:\n - NEO4J_AUTH=neo4j/${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_server_memory_pagecache_size=512M\n - NEO4J_server_memory_heap_initial__size=512M\n - NEO4J_server_memory_heap_max__size=1G\n volumes:\n - ./data/neo4j:/data\n - ./backups/neo4j:/data/backups\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD-SHELL\", \"cypher-shell -a bolt://localhost:7687 -u neo4j -p ${NEO4J_PASSWORD:?set NEO4J_PASSWORD} 'RETURN 1'\" ]\n interval: 20s\n timeout: 5s\n start_period: 20s\n retries: 6\n\n # BR-KG API Service\n br-kg:\n build:\n context: .\n target: br-kg\n container_name: brain-researcher-br-kg\n depends_on:\n - neo4j\n ports:\n - \"5000:5000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./src:/app/src\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - PORT=5000\n - FLASK_APP=brain_researcher.services.br_kg.api.graph_api:app\n - NEO4J_URI=bolt://neo4j:7687\n - NEO4J_USER=neo4j\n - NEO4J_PASSWORD=${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_PRELOAD_CACHE=0\n command: [ \"python\", \"-m\", \"brain_researcher.services.br_kg.app\" ]\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Agent Service\n agent:\n image: brain_researcher-agent\n build:\n context: .\n target: agent\n container_name: brain-researcher-agent\n depends_on:\n - br-kg\n ports:\n - \"${AGENT_PORT:-8000}:8000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./src:/app/src:ro\n - ./configs:/app/configs:ro\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - BR_KG_URL=http://br-kg:5000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - THREAD_STORE_REDIS_URL=redis://redis:6379/0\n - REDIS_URL=redis://redis:6379/1\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - DISABLE_AUTH_FOR_DEV=0\n - ORCHESTRATOR_UPLOAD_DIR=/tmp/brain_researcher_uploads/chat\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - GEMINI_API_KEY=${GEMINI_API_KEY:-}\n - BR_ALLOW_RUN_ID_OVERRIDE=1\n - DEFAULT_LLM_MODEL=${DEFAULT_LLM_MODEL:-gemini-2.0-flash}\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Orchestrator worker (no longer UI gateway; optional)\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n container_name: brain-researcher-orchestrator\n profiles: [ \"worker\" ] # start with `docker compose --profile worker up`\n depends_on:\n - agent\n - br-kg\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n # Foundation model optional; provide if service is running\n # - NICLIP_URL=http://niclip:8001\n - REDIS_URL=redis://redis:6379\n - BR_MCP_TOKEN_PEPPER=${BR_MCP_TOKEN_PEPPER:-}\n - BR_MCP_TOKEN_PEPPER_VERSION=${BR_MCP_TOKEN_PEPPER_VERSION:-v1}\n - BR_MCP_TOKEN_REDIS_PREFIX=${BR_MCP_TOKEN_REDIS_PREFIX:-mcp_token}\n restart: unless-stopped\n\n # Web UI (Next.js) - talks directly to Agent & BR-KG\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n container_name: brain-researcher-web-ui\n depends_on:\n - agent\n - br-kg\n ports:\n - \"${WEB_UI_PORT:-3000}:3000\"\n volumes:\n - ./configs:/app/configs:ro\n environment:\n - NODE_ENV=production\n - BR_AGENT_URL=http://agent:8000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - NEXT_PUBLIC_AGENT_URL=http://agent:8000\n - NEXT_PUBLIC_BR_KG_URL=http://br-kg:5000\n - NEXT_PUBLIC_BR_KG_API=http://br-kg:5000 # legacy alias\n - BR_KG_URL=http://br-kg:5000\n - NEXT_PUBLIC_API_URL=http://agent:8000 # legacy alias\n - NEXT_PUBLIC_ORCHESTRATOR_URL=http://localhost:3001\n - NEXT_PUBLIC_APP_NAME=Brain Researcher Web\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - NEXTAUTH_SECRET=${NEXTAUTH_SECRET:?set NEXTAUTH_SECRET}\n - ENABLE_DEV_CREDENTIALS=1\n - DEV_CREDENTIALS_EMAIL=demo@example.com\n - DEV_CREDENTIALS_PASSWORD=DemoPass123!\n - AGENT_HOST=agent\n - BR_KG_HOST=br-kg\n - AGENT_BASE_URL=http://agent:8000\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD-SHELL\", \"IP=$$(hostname -i || echo 127.0.0.1); IP=$$IP node -e \\\"const ip=process.env.IP||'127.0.0.1'; require('http').get('http://'+ip+':3000/',(r)=>{process.exit(r.statusCode>=200 && r.statusCode<400 ? 0 : 1);}).on('error',()=>process.exit(1));\\\"\" ]\n interval: 30s\n timeout: 10s\n retries: 5\n\n # Redis for Agent State Management (optional)\n redis:\n image: redis:7-alpine\n container_name: brain-researcher-redis\n volumes:\n - redis_data:/data\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"redis-cli\", \"ping\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\nvolumes:\n redis_data:\n\n # Network configuration (optional, for isolation)\nnetworks:\n default:\n name: brain-researcher\n"}, "9e86e308c3adfb5e13bc513f9ac69307cd1cd5a4": {"t": 1785749125.095673, "n": 5607, "h": "089b82d13f460e56", "c": "version: '3.8'\n\nservices:\n neo4j:\n image: neo4j:5.20\n ports:\n - \"${BR_NEO4J_BOLT_PORT:-7687}:7687\"\n - \"${BR_NEO4J_HTTP_PORT:-7474}:7474\"\n environment:\n - NEO4J_AUTH=neo4j/${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_server_memory_pagecache_size=512M\n - NEO4J_server_memory_heap_initial__size=512M\n - NEO4J_server_memory_heap_max__size=1G\n volumes:\n - ./data/neo4j:/data\n - ./backups/neo4j:/data/backups\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD-SHELL\", \"cypher-shell -a bolt://localhost:7687 -u neo4j -p ${NEO4J_PASSWORD:?set NEO4J_PASSWORD} 'RETURN 1'\" ]\n interval: 20s\n timeout: 5s\n start_period: 20s\n retries: 6\n\n # BR-KG API Service\n neurokg:\n build:\n context: .\n target: neurokg\n depends_on:\n - neo4j\n ports:\n - \"${BR_NEUROKG_PORT:-5000}:5000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./packages/brain-researcher/src:/app/src\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - PORT=5000\n - FLASK_APP=brain_researcher.services.neurokg.api.graph_api:app\n - NEO4J_URI=bolt://neo4j:7687\n - NEO4J_USER=neo4j\n - NEO4J_PASSWORD=${NEO4J_PASSWORD:?set NEO4J_PASSWORD}\n - NEO4J_PRELOAD_CACHE=0\n command: [ \"python\", \"-m\", \"brain_researcher.services.neurokg.app\" ]\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Agent Service\n agent:\n image: brain_researcher-agent\n build:\n context: .\n target: agent\n depends_on:\n - neurokg\n ports:\n - \"${AGENT_PORT:-8000}:8000\"\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n - ./packages/brain-researcher/src:/app/src:ro\n - ./configs:/app/configs:ro\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - NEUROKG_API_URL=http://neurokg:5000\n - NEUROKG_URL=http://neurokg:5000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - THREAD_STORE_REDIS_URL=redis://redis:6379/0\n - REDIS_URL=redis://redis:6379/1\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - DISABLE_AUTH_FOR_DEV=0\n - ORCHESTRATOR_UPLOAD_DIR=/tmp/brain_researcher_uploads/chat\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - GEMINI_API_KEY=${GEMINI_API_KEY:-}\n - BR_ALLOW_RUN_ID_OVERRIDE=1\n - DEFAULT_LLM_MODEL=${DEFAULT_LLM_MODEL:-gemini-2.0-flash}\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Orchestrator worker (no longer UI gateway; optional)\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n profiles: [ \"worker\" ] # start with `docker compose --profile worker up`\n depends_on:\n - agent\n - neurokg\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - NEUROKG_URL=http://neurokg:5000\n # Foundation model optional; provide if service is running\n # - NICLIP_URL=http://niclip:8001\n - REDIS_URL=redis://redis:6379\n - BR_MCP_TOKEN_PEPPER=${BR_MCP_TOKEN_PEPPER:-}\n - BR_MCP_TOKEN_PEPPER_VERSION=${BR_MCP_TOKEN_PEPPER_VERSION:-v1}\n - BR_MCP_TOKEN_REDIS_PREFIX=${BR_MCP_TOKEN_REDIS_PREFIX:-mcp_token}\n restart: unless-stopped\n\n # Web UI (Next.js) - talks directly to Agent & BR-KG\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n depends_on:\n - agent\n - neurokg\n ports:\n - \"${WEB_UI_PORT:-3000}:3000\"\n volumes:\n - ./configs:/app/configs:ro\n environment:\n - NODE_ENV=production\n - BR_AGENT_URL=http://agent:8000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - NEXT_PUBLIC_AGENT_URL=http://agent:8000\n - NEXT_PUBLIC_NEUROKG_URL=http://neurokg:5000\n - NEXT_PUBLIC_NEUROKG_API=http://neurokg:5000 # legacy alias\n - NEUROKG_URL=http://neurokg:5000\n - NEXT_PUBLIC_API_URL=http://agent:8000 # legacy alias\n - NEXT_PUBLIC_ORCHESTRATOR_URL=http://localhost:3001\n - NEXT_PUBLIC_APP_NAME=Brain Researcher Web\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n - NEXTAUTH_SECRET=${NEXTAUTH_SECRET:?set NEXTAUTH_SECRET}\n - ENABLE_DEV_CREDENTIALS=1\n - DEV_CREDENTIALS_EMAIL=demo@example.com\n - DEV_CREDENTIALS_PASSWORD=DemoPass123!\n - AGENT_HOST=agent\n - NEUROKG_HOST=neurokg\n - AGENT_BASE_URL=http://agent:8000\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD-SHELL\", \"IP=$$(hostname -i || echo 127.0.0.1); IP=$$IP node -e \\\"const ip=process.env.IP||'127.0.0.1'; require('http').get('http://'+ip+':3000/',(r)=>{process.exit(r.statusCode>=200 && r.statusCode<400 ? 0 : 1);}).on('error',()=>process.exit(1));\\\"\" ]\n interval: 30s\n timeout: 10s\n retries: 5\n\n # Redis for Agent State Management (optional)\n redis:\n image: redis:7-alpine\n volumes:\n - redis_data:/data\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"redis-cli\", \"ping\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n\nvolumes:\n redis_data:\n\n # Network configuration (optional, for isolation)\nnetworks:\n default:\n name: brain-researcher\n"}}, "infrastructure/docker/compose/docker-compose.override.prod.yml": {"3305b62aef6852ddf0b33fde658e0048a4af65da": {"t": 1785745245.3787968, "n": 8017, "h": "07bca4b5a0a51191", "c": "services:\n # Nginx Reverse Proxy & Load Balancer\n nginx:\n image: nginx:1.25-alpine\n container_name: brain-researcher-nginx\n depends_on:\n - agent\n - web-ui\n ports:\n - \"80:80\"\n - \"443:443\"\n volumes:\n - ./infrastructure/nginx/brain-researcher-compose.conf:/etc/nginx/conf.d/default.conf:ro\n - ./ssl:/etc/nginx/ssl:ro\n - nginx_logs:/var/log/nginx\n environment:\n - NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx/conf.d\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"nginx\", \"-t\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n networks:\n - brain-researcher-network\n\n # Agent Service (LangGraph-based)\n agent:\n build:\n context: .\n target: agent\n container_name: brain-researcher-agent\n depends_on:\n - br-kg\n - redis\n ports:\n - \"8000:8000\"\n volumes:\n - ./data:/app/data\n - ./logs/agent:/app/logs\n - ./src/brain_researcher/services/agent/.env:/app/.env:ro\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - REDIS_URL=redis://redis:6379/2\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - BR_QUEUE_BACKEND=sqlite\n - BR_QUEUE_DB=/app/data/orchestrator/jobs.sqlite\n - LOG_LEVEL=INFO\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 4G\n cpus: '2.0'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 90s\n networks:\n - brain-researcher-network\n\n # BR-KG Service\n br-kg:\n build:\n context: .\n target: br-kg\n container_name: brain-researcher-br-kg\n ports:\n - \"5000:5000\"\n volumes:\n - ./data/br-kg:/app/data/br-kg\n - ./logs/br-kg:/app/logs\n - br_kg_db:/app/data/br-kg/db\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - FLASK_ENV=production\n - LOG_LEVEL=INFO\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 3G\n cpus: '1.5'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n networks:\n - brain-researcher-network\n\n # Orchestrator Service\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n container_name: brain-researcher-orchestrator\n depends_on:\n - agent\n - br-kg\n - redis\n ports:\n - \"3001:3001\"\n volumes:\n - ./data:/app/data\n - ./logs/orchestrator:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n - REDIS_URL=redis://redis:6379/0\n - BR_QUEUE_BACKEND=sqlite\n - BR_QUEUE_DB=/app/data/orchestrator/jobs.sqlite\n - ORCHESTRATOR_UPLOAD_DIR=/app/data/uploads/chat\n - LOG_LEVEL=INFO\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 2G\n cpus: '1.0'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:3001/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 30s\n networks:\n - brain-researcher-network\n\n # Web UI (Next.js)\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n container_name: brain-researcher-web-ui\n depends_on:\n - orchestrator\n ports:\n - \"3000:3000\"\n environment:\n - NODE_ENV=production\n - AGENT_BASE_URL=http://agent:8000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - NEXT_PUBLIC_API_URL=${PUBLIC_API_URL:-http://localhost:3001}\n - NEXT_PUBLIC_ORCHESTRATOR_URL=${PUBLIC_ORCHESTRATOR_URL:-http://localhost:3001}\n - NEXT_PUBLIC_AGENT_URL=${PUBLIC_AGENT_URL:-http://localhost:8000}\n - NEXT_PUBLIC_BR_KG_URL=${PUBLIC_BR_KG_URL:-http://localhost:5000}\n - NEXT_PUBLIC_APP_NAME=Brain Researcher\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n - NEXT_TELEMETRY_DISABLED=1\n - ENABLE_DEV_CREDENTIALS=0\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 1G\n cpus: '0.5'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:3000/api/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n networks:\n - brain-researcher-network\n\n # Redis for state management, caching, and pub/sub\n redis:\n image: redis:7-alpine\n container_name: brain-researcher-redis\n command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru\n volumes:\n - redis_data:/data\n - ./configs/runtime/redis.conf:/usr/local/etc/redis/redis.conf:ro\n environment:\n - REDIS_PASSWORD=${REDIS_PASSWORD:-}\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 1G\n cpus: '0.5'\n healthcheck:\n test: [ \"CMD\", \"redis-cli\", \"ping\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n networks:\n - brain-researcher-network\n\n # PostgreSQL for persistent data (optional, for production)\n postgres:\n image: postgres:15-alpine\n container_name: brain-researcher-postgres\n ports:\n - \"5432:5432\"\n volumes:\n - postgres_data:/var/lib/postgresql/data\n - ./infrastructure/database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro\n environment:\n - POSTGRES_DB=brain_researcher\n - POSTGRES_USER=brain_researcher\n - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}\n - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --locale=C\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 2G\n cpus: '1.0'\n healthcheck:\n test: [ \"CMD-SHELL\", \"pg_isready -U brain_researcher -d brain_researcher\" ]\n interval: 30s\n timeout: 10s\n retries: 5\n networks:\n - brain-researcher-network\n\n # Monitoring with Prometheus (optional)\n prometheus:\n image: prom/prometheus:latest\n container_name: brain-researcher-prometheus\n ports:\n - \"9090:9090\"\n volumes:\n - ./configs/runtime/prometheus.yml:/etc/prometheus/prometheus.yml:ro\n - prometheus_data:/prometheus\n command:\n - '--config.file=/etc/prometheus/prometheus.yml'\n - '--storage.tsdb.path=/prometheus'\n - '--web.console.libraries=/etc/prometheus/console_libraries'\n - '--web.console.templates=/etc/prometheus/consoles'\n - '--storage.tsdb.retention.time=30d'\n - '--web.enable-lifecycle'\n restart: unless-stopped\n networks:\n - brain-researcher-network\n\n # Grafana for dashboards (optional)\n grafana:\n image: grafana/grafana:latest\n container_name: brain-researcher-grafana\n ports:\n - \"3100:3000\"\n volumes:\n - grafana_data:/var/lib/grafana\n - ./infrastructure/monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards:ro\n - ./infrastructure/monitoring/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources:ro\n environment:\n - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:?set GRAFANA_PASSWORD}\n - GF_USERS_ALLOW_SIGN_UP=false\n - GF_INSTALL_PLUGINS=grafana-piechart-panel\n restart: unless-stopped\n networks:\n - brain-researcher-network\n\nvolumes:\n redis_data:\n driver: local\n postgres_data:\n driver: local\n br_kg_db:\n driver: local\n prometheus_data:\n driver: local\n grafana_data:\n driver: local\n nginx_logs:\n driver: local\n\nnetworks:\n brain-researcher-network:\n driver: bridge\n name: brain-researcher-network\n ipam:\n config:\n - subnet: 172.20.0.0/16\n"}, "62482fe171a5072e49a5a743bd26b776d42b64b0": {"t": 1785749119.005172, "n": 8017, "h": "07bca4b5a0a51191", "c": "services:\n # Nginx Reverse Proxy & Load Balancer\n nginx:\n image: nginx:1.25-alpine\n container_name: brain-researcher-nginx\n depends_on:\n - agent\n - web-ui\n ports:\n - \"80:80\"\n - \"443:443\"\n volumes:\n - ./infrastructure/nginx/brain-researcher-compose.conf:/etc/nginx/conf.d/default.conf:ro\n - ./ssl:/etc/nginx/ssl:ro\n - nginx_logs:/var/log/nginx\n environment:\n - NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx/conf.d\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"nginx\", \"-t\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n networks:\n - brain-researcher-network\n\n # Agent Service (LangGraph-based)\n agent:\n build:\n context: .\n target: agent\n container_name: brain-researcher-agent\n depends_on:\n - br-kg\n - redis\n ports:\n - \"8000:8000\"\n volumes:\n - ./data:/app/data\n - ./logs/agent:/app/logs\n - ./src/brain_researcher/services/agent/.env:/app/.env:ro\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - REDIS_URL=redis://redis:6379/2\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - BR_QUEUE_BACKEND=sqlite\n - BR_QUEUE_DB=/app/data/orchestrator/jobs.sqlite\n - LOG_LEVEL=INFO\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 4G\n cpus: '2.0'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 90s\n networks:\n - brain-researcher-network\n\n # BR-KG Service\n br-kg:\n build:\n context: .\n target: br-kg\n container_name: brain-researcher-br-kg\n ports:\n - \"5000:5000\"\n volumes:\n - ./data/br-kg:/app/data/br-kg\n - ./logs/br-kg:/app/logs\n - br_kg_db:/app/data/br-kg/db\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - FLASK_ENV=production\n - LOG_LEVEL=INFO\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 3G\n cpus: '1.5'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n networks:\n - brain-researcher-network\n\n # Orchestrator Service\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n container_name: brain-researcher-orchestrator\n depends_on:\n - agent\n - br-kg\n - redis\n ports:\n - \"3001:3001\"\n volumes:\n - ./data:/app/data\n - ./logs/orchestrator:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n - REDIS_URL=redis://redis:6379/0\n - BR_QUEUE_BACKEND=sqlite\n - BR_QUEUE_DB=/app/data/orchestrator/jobs.sqlite\n - ORCHESTRATOR_UPLOAD_DIR=/app/data/uploads/chat\n - LOG_LEVEL=INFO\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 2G\n cpus: '1.0'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:3001/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 30s\n networks:\n - brain-researcher-network\n\n # Web UI (Next.js)\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n container_name: brain-researcher-web-ui\n depends_on:\n - orchestrator\n ports:\n - \"3000:3000\"\n environment:\n - NODE_ENV=production\n - AGENT_BASE_URL=http://agent:8000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - NEXT_PUBLIC_API_URL=${PUBLIC_API_URL:-http://localhost:3001}\n - NEXT_PUBLIC_ORCHESTRATOR_URL=${PUBLIC_ORCHESTRATOR_URL:-http://localhost:3001}\n - NEXT_PUBLIC_AGENT_URL=${PUBLIC_AGENT_URL:-http://localhost:8000}\n - NEXT_PUBLIC_BR_KG_URL=${PUBLIC_BR_KG_URL:-http://localhost:5000}\n - NEXT_PUBLIC_APP_NAME=Brain Researcher\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n - NEXT_TELEMETRY_DISABLED=1\n - ENABLE_DEV_CREDENTIALS=0\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 1G\n cpus: '0.5'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:3000/api/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n networks:\n - brain-researcher-network\n\n # Redis for state management, caching, and pub/sub\n redis:\n image: redis:7-alpine\n container_name: brain-researcher-redis\n command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru\n volumes:\n - redis_data:/data\n - ./configs/runtime/redis.conf:/usr/local/etc/redis/redis.conf:ro\n environment:\n - REDIS_PASSWORD=${REDIS_PASSWORD:-}\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 1G\n cpus: '0.5'\n healthcheck:\n test: [ \"CMD\", \"redis-cli\", \"ping\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n networks:\n - brain-researcher-network\n\n # PostgreSQL for persistent data (optional, for production)\n postgres:\n image: postgres:15-alpine\n container_name: brain-researcher-postgres\n ports:\n - \"5432:5432\"\n volumes:\n - postgres_data:/var/lib/postgresql/data\n - ./infrastructure/database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro\n environment:\n - POSTGRES_DB=brain_researcher\n - POSTGRES_USER=brain_researcher\n - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}\n - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --locale=C\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 2G\n cpus: '1.0'\n healthcheck:\n test: [ \"CMD-SHELL\", \"pg_isready -U brain_researcher -d brain_researcher\" ]\n interval: 30s\n timeout: 10s\n retries: 5\n networks:\n - brain-researcher-network\n\n # Monitoring with Prometheus (optional)\n prometheus:\n image: prom/prometheus:latest\n container_name: brain-researcher-prometheus\n ports:\n - \"9090:9090\"\n volumes:\n - ./configs/runtime/prometheus.yml:/etc/prometheus/prometheus.yml:ro\n - prometheus_data:/prometheus\n command:\n - '--config.file=/etc/prometheus/prometheus.yml'\n - '--storage.tsdb.path=/prometheus'\n - '--web.console.libraries=/etc/prometheus/console_libraries'\n - '--web.console.templates=/etc/prometheus/consoles'\n - '--storage.tsdb.retention.time=30d'\n - '--web.enable-lifecycle'\n restart: unless-stopped\n networks:\n - brain-researcher-network\n\n # Grafana for dashboards (optional)\n grafana:\n image: grafana/grafana:latest\n container_name: brain-researcher-grafana\n ports:\n - \"3100:3000\"\n volumes:\n - grafana_data:/var/lib/grafana\n - ./infrastructure/monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards:ro\n - ./infrastructure/monitoring/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources:ro\n environment:\n - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:?set GRAFANA_PASSWORD}\n - GF_USERS_ALLOW_SIGN_UP=false\n - GF_INSTALL_PLUGINS=grafana-piechart-panel\n restart: unless-stopped\n networks:\n - brain-researcher-network\n\nvolumes:\n redis_data:\n driver: local\n postgres_data:\n driver: local\n br_kg_db:\n driver: local\n prometheus_data:\n driver: local\n grafana_data:\n driver: local\n nginx_logs:\n driver: local\n\nnetworks:\n brain-researcher-network:\n driver: bridge\n name: brain-researcher-network\n ipam:\n config:\n - subnet: 172.20.0.0/16\n"}, "ba5c18fca5405755729e6b0bcb7c737c827f6ed2": {"t": 1785749120.7378938, "n": 8002, "h": "2cb3f5e3f3c6a84d", "c": "services:\n # Nginx Reverse Proxy & Load Balancer\n nginx:\n image: nginx:1.25-alpine\n container_name: brain-researcher-nginx\n depends_on:\n - agent\n - web-ui\n ports:\n - \"80:80\"\n - \"443:443\"\n volumes:\n - ./infrastructure/nginx/brain-researcher-compose.conf:/etc/nginx/conf.d/default.conf:ro\n - ./ssl:/etc/nginx/ssl:ro\n - nginx_logs:/var/log/nginx\n environment:\n - NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx/conf.d\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"nginx\", \"-t\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n networks:\n - brain-researcher-network\n\n # Agent Service (LangGraph-based)\n agent:\n build:\n context: .\n target: agent\n container_name: brain-researcher-agent\n depends_on:\n - br-kg\n - redis\n ports:\n - \"8000:8000\"\n volumes:\n - ./data:/app/data\n - ./logs/agent:/app/logs\n - ./src/brain_researcher/services/agent/.env:/app/.env:ro\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - REDIS_URL=redis://redis:6379/2\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - BR_QUEUE_BACKEND=sqlite\n - BR_QUEUE_DB=/app/data/orchestrator/jobs.sqlite\n - LOG_LEVEL=INFO\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 4G\n cpus: '2.0'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 90s\n networks:\n - brain-researcher-network\n\n # BR-KG Service\n br-kg:\n build:\n context: .\n target: br-kg\n container_name: brain-researcher-br-kg\n ports:\n - \"5000:5000\"\n volumes:\n - ./data/br-kg:/app/data/br-kg\n - ./logs/br-kg:/app/logs\n - br_kg_db:/app/data/br-kg/db\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - FLASK_ENV=production\n - LOG_LEVEL=INFO\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 3G\n cpus: '1.5'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n networks:\n - brain-researcher-network\n\n # Orchestrator Service\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n container_name: brain-researcher-orchestrator\n depends_on:\n - agent\n - br-kg\n - redis\n ports:\n - \"3001:3001\"\n volumes:\n - ./data:/app/data\n - ./logs/orchestrator:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n - REDIS_URL=redis://redis:6379/0\n - BR_QUEUE_BACKEND=sqlite\n - BR_QUEUE_DB=/app/data/orchestrator/jobs.sqlite\n - ORCHESTRATOR_UPLOAD_DIR=/app/data/uploads/chat\n - LOG_LEVEL=INFO\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 2G\n cpus: '1.0'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:3001/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 30s\n networks:\n - brain-researcher-network\n\n # Web UI (Next.js)\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n container_name: brain-researcher-web-ui\n depends_on:\n - orchestrator\n ports:\n - \"3000:3000\"\n environment:\n - NODE_ENV=production\n - AGENT_BASE_URL=http://agent:8000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - NEXT_PUBLIC_API_URL=${PUBLIC_API_URL:-http://localhost:3001}\n - NEXT_PUBLIC_ORCHESTRATOR_URL=${PUBLIC_ORCHESTRATOR_URL:-http://localhost:3001}\n - NEXT_PUBLIC_AGENT_URL=${PUBLIC_AGENT_URL:-http://localhost:8000}\n - NEXT_PUBLIC_BR_KG_URL=${PUBLIC_BR_KG_URL:-http://localhost:5000}\n - NEXT_PUBLIC_APP_NAME=Brain Researcher\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n - NEXT_TELEMETRY_DISABLED=1\n - ENABLE_DEV_CREDENTIALS=0\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 1G\n cpus: '0.5'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:3000/api/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n networks:\n - brain-researcher-network\n\n # Redis for state management, caching, and pub/sub\n redis:\n image: redis:7-alpine\n container_name: brain-researcher-redis\n command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru\n volumes:\n - redis_data:/data\n - ./configs/runtime/redis.conf:/usr/local/etc/redis/redis.conf:ro\n environment:\n - REDIS_PASSWORD=${REDIS_PASSWORD:-}\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 1G\n cpus: '0.5'\n healthcheck:\n test: [ \"CMD\", \"redis-cli\", \"ping\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n networks:\n - brain-researcher-network\n\n # PostgreSQL for persistent data (optional, for production)\n postgres:\n image: postgres:15-alpine\n container_name: brain-researcher-postgres\n ports:\n - \"5432:5432\"\n volumes:\n - postgres_data:/var/lib/postgresql/data\n - ./infrastructure/database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro\n environment:\n - POSTGRES_DB=brain_researcher\n - POSTGRES_USER=brain_researcher\n - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-brain_researcher_pass}\n - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --locale=C\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 2G\n cpus: '1.0'\n healthcheck:\n test: [ \"CMD-SHELL\", \"pg_isready -U brain_researcher -d brain_researcher\" ]\n interval: 30s\n timeout: 10s\n retries: 5\n networks:\n - brain-researcher-network\n\n # Monitoring with Prometheus (optional)\n prometheus:\n image: prom/prometheus:latest\n container_name: brain-researcher-prometheus\n ports:\n - \"9090:9090\"\n volumes:\n - ./configs/runtime/prometheus.yml:/etc/prometheus/prometheus.yml:ro\n - prometheus_data:/prometheus\n command:\n - '--config.file=/etc/prometheus/prometheus.yml'\n - '--storage.tsdb.path=/prometheus'\n - '--web.console.libraries=/etc/prometheus/console_libraries'\n - '--web.console.templates=/etc/prometheus/consoles'\n - '--storage.tsdb.retention.time=30d'\n - '--web.enable-lifecycle'\n restart: unless-stopped\n networks:\n - brain-researcher-network\n\n # Grafana for dashboards (optional)\n grafana:\n image: grafana/grafana:latest\n container_name: brain-researcher-grafana\n ports:\n - \"3100:3000\"\n volumes:\n - grafana_data:/var/lib/grafana\n - ./infrastructure/monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards:ro\n - ./infrastructure/monitoring/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources:ro\n environment:\n - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin}\n - GF_USERS_ALLOW_SIGN_UP=false\n - GF_INSTALL_PLUGINS=grafana-piechart-panel\n restart: unless-stopped\n networks:\n - brain-researcher-network\n\nvolumes:\n redis_data:\n driver: local\n postgres_data:\n driver: local\n br_kg_db:\n driver: local\n prometheus_data:\n driver: local\n grafana_data:\n driver: local\n nginx_logs:\n driver: local\n\nnetworks:\n brain-researcher-network:\n driver: bridge\n name: brain-researcher-network\n ipam:\n config:\n - subnet: 172.20.0.0/16\n"}, "9e86e308c3adfb5e13bc513f9ac69307cd1cd5a4": {"t": 1785749122.8900948, "n": 8036, "h": "22cbad5b751a48d9", "c": "services:\n # Nginx Reverse Proxy & Load Balancer\n nginx:\n image: nginx:1.25-alpine\n container_name: brain-researcher-nginx\n depends_on:\n - agent\n - web-ui\n ports:\n - \"80:80\"\n - \"443:443\"\n volumes:\n - ./infrastructure/nginx/brain-researcher-compose.conf:/etc/nginx/conf.d/default.conf:ro\n - ./ssl:/etc/nginx/ssl:ro\n - nginx_logs:/var/log/nginx\n environment:\n - NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx/conf.d\n restart: unless-stopped\n healthcheck:\n test: [ \"CMD\", \"nginx\", \"-t\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n networks:\n - brain-researcher-network\n\n # Agent Service (LangGraph-based)\n agent:\n build:\n context: .\n target: agent\n container_name: brain-researcher-agent\n depends_on:\n - neurokg\n - redis\n ports:\n - \"8000:8000\"\n volumes:\n - ./data:/app/data\n - ./logs/agent:/app/logs\n - ./src/brain_researcher/services/agent/.env:/app/.env:ro\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - NEUROKG_API_URL=http://neurokg:5000\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - REDIS_URL=redis://redis:6379/2\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - BR_QUEUE_BACKEND=sqlite\n - BR_QUEUE_DB=/app/data/orchestrator/jobs.sqlite\n - LOG_LEVEL=INFO\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 4G\n cpus: '2.0'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 90s\n networks:\n - brain-researcher-network\n\n # BR-KG Service\n neurokg:\n build:\n context: .\n target: neurokg\n container_name: brain-researcher-neurokg\n ports:\n - \"5000:5000\"\n volumes:\n - ./data/neurokg:/app/data/neurokg\n - ./logs/neurokg:/app/logs\n - neurokg_db:/app/data/neurokg/db\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - FLASK_ENV=production\n - LOG_LEVEL=INFO\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 3G\n cpus: '1.5'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n networks:\n - brain-researcher-network\n\n # Orchestrator Service\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n container_name: brain-researcher-orchestrator\n depends_on:\n - agent\n - neurokg\n - redis\n ports:\n - \"3001:3001\"\n volumes:\n - ./data:/app/data\n - ./logs/orchestrator:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - NEUROKG_URL=http://neurokg:5000\n - REDIS_URL=redis://redis:6379/0\n - BR_QUEUE_BACKEND=sqlite\n - BR_QUEUE_DB=/app/data/orchestrator/jobs.sqlite\n - ORCHESTRATOR_UPLOAD_DIR=/app/data/uploads/chat\n - LOG_LEVEL=INFO\n - JWT_SECRET_KEY=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 2G\n cpus: '1.0'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:3001/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 30s\n networks:\n - brain-researcher-network\n\n # Web UI (Next.js)\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n container_name: brain-researcher-web-ui\n depends_on:\n - orchestrator\n ports:\n - \"3000:3000\"\n environment:\n - NODE_ENV=production\n - AGENT_BASE_URL=http://agent:8000\n - BR_ORCHESTRATOR_URL=http://orchestrator:3001\n - NEXT_PUBLIC_API_URL=${PUBLIC_API_URL:-http://localhost:3001}\n - NEXT_PUBLIC_ORCHESTRATOR_URL=${PUBLIC_ORCHESTRATOR_URL:-http://localhost:3001}\n - NEXT_PUBLIC_AGENT_URL=${PUBLIC_AGENT_URL:-http://localhost:8000}\n - NEXT_PUBLIC_NEUROKG_URL=${PUBLIC_NEUROKG_URL:-http://localhost:5000}\n - NEXT_PUBLIC_APP_NAME=Brain Researcher\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n - NEXT_TELEMETRY_DISABLED=1\n - ENABLE_DEV_CREDENTIALS=0\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 1G\n cpus: '0.5'\n healthcheck:\n test: [ \"CMD\", \"curl\", \"-f\", \"http://localhost:3000/api/health\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n networks:\n - brain-researcher-network\n\n # Redis for state management, caching, and pub/sub\n redis:\n image: redis:7-alpine\n container_name: brain-researcher-redis\n command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru\n volumes:\n - redis_data:/data\n - ./configs/runtime/redis.conf:/usr/local/etc/redis/redis.conf:ro\n environment:\n - REDIS_PASSWORD=${REDIS_PASSWORD:-}\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 1G\n cpus: '0.5'\n healthcheck:\n test: [ \"CMD\", \"redis-cli\", \"ping\" ]\n interval: 30s\n timeout: 10s\n retries: 3\n networks:\n - brain-researcher-network\n\n # PostgreSQL for persistent data (optional, for production)\n postgres:\n image: postgres:15-alpine\n container_name: brain-researcher-postgres\n ports:\n - \"5432:5432\"\n volumes:\n - postgres_data:/var/lib/postgresql/data\n - ./infrastructure/database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro\n environment:\n - POSTGRES_DB=brain_researcher\n - POSTGRES_USER=brain_researcher\n - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-brain_researcher_pass}\n - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --locale=C\n restart: unless-stopped\n deploy:\n resources:\n limits:\n memory: 2G\n cpus: '1.0'\n healthcheck:\n test: [ \"CMD-SHELL\", \"pg_isready -U brain_researcher -d brain_researcher\" ]\n interval: 30s\n timeout: 10s\n retries: 5\n networks:\n - brain-researcher-network\n\n # Monitoring with Prometheus (optional)\n prometheus:\n image: prom/prometheus:latest\n container_name: brain-researcher-prometheus\n ports:\n - \"9090:9090\"\n volumes:\n - ./configs/runtime/prometheus.yml:/etc/prometheus/prometheus.yml:ro\n - prometheus_data:/prometheus\n command:\n - '--config.file=/etc/prometheus/prometheus.yml'\n - '--storage.tsdb.path=/prometheus'\n - '--web.console.libraries=/etc/prometheus/console_libraries'\n - '--web.console.templates=/etc/prometheus/consoles'\n - '--storage.tsdb.retention.time=30d'\n - '--web.enable-lifecycle'\n restart: unless-stopped\n networks:\n - brain-researcher-network\n\n # Grafana for dashboards (optional)\n grafana:\n image: grafana/grafana:latest\n container_name: brain-researcher-grafana\n ports:\n - \"3100:3000\"\n volumes:\n - grafana_data:/var/lib/grafana\n - ./infrastructure/monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards:ro\n - ./infrastructure/monitoring/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources:ro\n environment:\n - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin}\n - GF_USERS_ALLOW_SIGN_UP=false\n - GF_INSTALL_PLUGINS=grafana-piechart-panel\n restart: unless-stopped\n networks:\n - brain-researcher-network\n\nvolumes:\n redis_data:\n driver: local\n postgres_data:\n driver: local\n neurokg_db:\n driver: local\n prometheus_data:\n driver: local\n grafana_data:\n driver: local\n nginx_logs:\n driver: local\n\nnetworks:\n brain-researcher-network:\n driver: bridge\n name: brain-researcher-network\n ipam:\n config:\n - subnet: 172.20.0.0/16\n"}}, "infrastructure/docker/compose/docker-compose.override.swarm.yml": {"3305b62aef6852ddf0b33fde658e0048a4af65da": {"t": 1785746978.0096252, "n": 11131, "h": "65b74498923b7334", "c": "services:\n # Load Balancer (HAProxy)\n haproxy:\n image: haproxy:2.8-alpine\n ports:\n - \"80:80\"\n - \"443:443\"\n - \"8080:8080\" # HAProxy stats\n volumes:\n - ./infrastructure/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro\n - ./infrastructure/haproxy/ssl:/etc/ssl/certs:ro\n networks:\n - frontend\n - backend\n deploy:\n replicas: 2\n placement:\n constraints:\n - node.role == manager\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n update_config:\n parallelism: 1\n delay: 10s\n failure_action: rollback\n rollback_config:\n parallelism: 1\n delay: 10s\n\n # BR-KG API Service - Replicated\n br-kg:\n build:\n context: .\n target: br-kg\n networks:\n - backend\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n deploy:\n replicas: 4\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == api\n resources:\n limits:\n cpus: '1.0'\n memory: 1G\n reservations:\n cpus: '0.5'\n memory: 512M\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n update_config:\n parallelism: 2\n delay: 10s\n failure_action: rollback\n monitor: 60s\n rollback_config:\n parallelism: 2\n delay: 10s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\"]\n interval: 30s\n timeout: 15s\n retries: 3\n start_period: 60s\n\n # Agent Service - Multiple Replicas\n agent:\n build:\n context: .\n target: agent\n networks:\n - backend\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - REDIS_URL=redis://redis:6379\n deploy:\n replicas: 3\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == compute\n resources:\n limits:\n cpus: '2.0'\n memory: 2G\n reservations:\n cpus: '1.0'\n memory: 1G\n restart_policy:\n condition: on-failure\n delay: 15s\n max_attempts: 3\n update_config:\n parallelism: 1\n delay: 30s\n failure_action: rollback\n monitor: 120s\n rollback_config:\n parallelism: 1\n delay: 30s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\"]\n interval: 45s\n timeout: 15s\n retries: 3\n start_period: 120s\n\n # Orchestrator API Gateway - Highly Available\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n networks:\n - backend\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n - NICLIP_URL=http://niclip:8001\n - REDIS_URL=redis://redis:6379\n - \"DATABASE_URL=${DATABASE_URL:?set DATABASE_URL}\"\n deploy:\n replicas: 5\n placement:\n max_replicas_per_node: 3\n constraints:\n - node.labels.tier == orchestrator\n resources:\n limits:\n cpus: '1.5'\n memory: 1.5G\n reservations:\n cpus: '0.75'\n memory: 750M\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n update_config:\n parallelism: 2\n delay: 15s\n failure_action: rollback\n monitor: 90s\n rollback_config:\n parallelism: 2\n delay: 15s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:3001/health\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n\n # Web UI - Multiple Frontend Instances\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n networks:\n - backend\n environment:\n - NODE_ENV=production\n - NEXT_PUBLIC_API_URL=http://orchestrator:3001\n - NEXT_PUBLIC_APP_NAME=Brain Researcher Web\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n deploy:\n replicas: 4\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == web\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n update_config:\n parallelism: 2\n delay: 10s\n failure_action: rollback\n monitor: 60s\n rollback_config:\n parallelism: 2\n delay: 10s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:3000\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n\n # Redis Cluster for State Management\n redis-master:\n image: redis:7-alpine\n networks:\n - backend\n volumes:\n - redis_master_data:/data\n command: redis-server --appendonly yes --replica-read-only no\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 30s\n timeout: 5s\n retries: 3\n\n redis-replica:\n image: redis:7-alpine\n networks:\n - backend\n volumes:\n - redis_replica_data:/data\n command: redis-server --appendonly yes --replicaof redis-master 6379\n deploy:\n replicas: 2\n placement:\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.25'\n memory: 256M\n reservations:\n cpus: '0.125'\n memory: 128M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n depends_on:\n - redis-master\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 30s\n timeout: 5s\n retries: 3\n\n # PostgreSQL with Connection Pooling\n postgres:\n image: postgres:15-alpine\n networks:\n - backend\n volumes:\n - postgres_data:/var/lib/postgresql/data\n - ./infrastructure/database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro\n environment:\n - POSTGRES_DB=brain_researcher\n - POSTGRES_USER=postgres\n - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}\n - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == storage\n - node.role == manager\n resources:\n limits:\n cpus: '2.0'\n memory: 2G\n reservations:\n cpus: '1.0'\n memory: 1G\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U postgres -d brain_researcher\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # PgBouncer Connection Pool\n pgbouncer:\n image: pgbouncer/pgbouncer:1.19.1\n networks:\n - backend\n volumes:\n - ./infrastructure/database/pgbouncer.ini:/etc/pgbouncer/pgbouncer.ini:ro\n - ${PGBOUNCER_AUTH_FILE:?set PGBOUNCER_AUTH_FILE}:/etc/pgbouncer/userlist.txt:ro\n environment:\n - DATABASES_HOST=postgres\n - DATABASES_PORT=5432\n - DATABASES_USER=postgres\n - DATABASES_PASSWORD=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}\n - DATABASES_DBNAME=brain_researcher\n - POOL_MODE=transaction\n - MAX_CLIENT_CONN=1000\n - DEFAULT_POOL_SIZE=50\n deploy:\n replicas: 2\n placement:\n max_replicas_per_node: 1\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.5'\n memory: 256M\n reservations:\n cpus: '0.25'\n memory: 128M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n depends_on:\n - postgres\n healthcheck:\n test: [\"CMD-SHELL\", \"psql -h localhost -p 6432 -U postgres -d brain_researcher -c 'SELECT 1;' || exit 1\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Prometheus Monitoring\n prometheus:\n image: prom/prometheus:v2.44.0\n networks:\n - backend\n volumes:\n - ./infrastructure/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro\n - prometheus_data:/prometheus\n command:\n - '--config.file=/etc/prometheus/prometheus.yml'\n - '--storage.tsdb.path=/prometheus'\n - '--web.console.libraries=/usr/share/prometheus/console_libraries'\n - '--web.console.templates=/usr/share/prometheus/consoles'\n - '--storage.tsdb.retention.time=15d'\n - '--web.enable-lifecycle'\n - '--web.enable-admin-api'\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == monitoring\n resources:\n limits:\n cpus: '1.0'\n memory: 1G\n reservations:\n cpus: '0.5'\n memory: 512M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n\n # Grafana Dashboard\n grafana:\n image: grafana/grafana:9.5.2\n networks:\n - backend\n volumes:\n - grafana_data:/var/lib/grafana\n - ./infrastructure/monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro\n - ./infrastructure/monitoring/grafana/provisioning:/etc/grafana/provisioning:ro\n environment:\n - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:?set GRAFANA_ADMIN_PASSWORD}\n - GF_USERS_ALLOW_SIGN_UP=false\n - GF_SERVER_ROOT_URL=http://localhost:3000/grafana\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == monitoring\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n\nnetworks:\n frontend:\n driver: overlay\n external: false\n backend:\n driver: overlay\n external: false\n\nvolumes:\n redis_master_data:\n redis_replica_data:\n postgres_data:\n prometheus_data:\n grafana_data:\n\n# Global configuration\nconfigs:\n haproxy_config:\n file: ./infrastructure/haproxy/haproxy.cfg\n pgbouncer_config:\n file: ./infrastructure/database/pgbouncer.ini\n\nsecrets:\n postgres_password:\n external: true\n openai_api_key:\n external: true\n anthropic_api_key:\n external: true\n"}, "62482fe171a5072e49a5a743bd26b776d42b64b0": {"t": 1785749118.800877, "n": 11131, "h": "65b74498923b7334", "c": "services:\n # Load Balancer (HAProxy)\n haproxy:\n image: haproxy:2.8-alpine\n ports:\n - \"80:80\"\n - \"443:443\"\n - \"8080:8080\" # HAProxy stats\n volumes:\n - ./infrastructure/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro\n - ./infrastructure/haproxy/ssl:/etc/ssl/certs:ro\n networks:\n - frontend\n - backend\n deploy:\n replicas: 2\n placement:\n constraints:\n - node.role == manager\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n update_config:\n parallelism: 1\n delay: 10s\n failure_action: rollback\n rollback_config:\n parallelism: 1\n delay: 10s\n\n # BR-KG API Service - Replicated\n br-kg:\n build:\n context: .\n target: br-kg\n networks:\n - backend\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n deploy:\n replicas: 4\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == api\n resources:\n limits:\n cpus: '1.0'\n memory: 1G\n reservations:\n cpus: '0.5'\n memory: 512M\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n update_config:\n parallelism: 2\n delay: 10s\n failure_action: rollback\n monitor: 60s\n rollback_config:\n parallelism: 2\n delay: 10s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\"]\n interval: 30s\n timeout: 15s\n retries: 3\n start_period: 60s\n\n # Agent Service - Multiple Replicas\n agent:\n build:\n context: .\n target: agent\n networks:\n - backend\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - REDIS_URL=redis://redis:6379\n deploy:\n replicas: 3\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == compute\n resources:\n limits:\n cpus: '2.0'\n memory: 2G\n reservations:\n cpus: '1.0'\n memory: 1G\n restart_policy:\n condition: on-failure\n delay: 15s\n max_attempts: 3\n update_config:\n parallelism: 1\n delay: 30s\n failure_action: rollback\n monitor: 120s\n rollback_config:\n parallelism: 1\n delay: 30s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\"]\n interval: 45s\n timeout: 15s\n retries: 3\n start_period: 120s\n\n # Orchestrator API Gateway - Highly Available\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n networks:\n - backend\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n - NICLIP_URL=http://niclip:8001\n - REDIS_URL=redis://redis:6379\n - \"DATABASE_URL=${DATABASE_URL:?set DATABASE_URL}\"\n deploy:\n replicas: 5\n placement:\n max_replicas_per_node: 3\n constraints:\n - node.labels.tier == orchestrator\n resources:\n limits:\n cpus: '1.5'\n memory: 1.5G\n reservations:\n cpus: '0.75'\n memory: 750M\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n update_config:\n parallelism: 2\n delay: 15s\n failure_action: rollback\n monitor: 90s\n rollback_config:\n parallelism: 2\n delay: 15s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:3001/health\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n\n # Web UI - Multiple Frontend Instances\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n networks:\n - backend\n environment:\n - NODE_ENV=production\n - NEXT_PUBLIC_API_URL=http://orchestrator:3001\n - NEXT_PUBLIC_APP_NAME=Brain Researcher Web\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n deploy:\n replicas: 4\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == web\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n update_config:\n parallelism: 2\n delay: 10s\n failure_action: rollback\n monitor: 60s\n rollback_config:\n parallelism: 2\n delay: 10s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:3000\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n\n # Redis Cluster for State Management\n redis-master:\n image: redis:7-alpine\n networks:\n - backend\n volumes:\n - redis_master_data:/data\n command: redis-server --appendonly yes --replica-read-only no\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 30s\n timeout: 5s\n retries: 3\n\n redis-replica:\n image: redis:7-alpine\n networks:\n - backend\n volumes:\n - redis_replica_data:/data\n command: redis-server --appendonly yes --replicaof redis-master 6379\n deploy:\n replicas: 2\n placement:\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.25'\n memory: 256M\n reservations:\n cpus: '0.125'\n memory: 128M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n depends_on:\n - redis-master\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 30s\n timeout: 5s\n retries: 3\n\n # PostgreSQL with Connection Pooling\n postgres:\n image: postgres:15-alpine\n networks:\n - backend\n volumes:\n - postgres_data:/var/lib/postgresql/data\n - ./infrastructure/database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro\n environment:\n - POSTGRES_DB=brain_researcher\n - POSTGRES_USER=postgres\n - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}\n - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == storage\n - node.role == manager\n resources:\n limits:\n cpus: '2.0'\n memory: 2G\n reservations:\n cpus: '1.0'\n memory: 1G\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U postgres -d brain_researcher\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # PgBouncer Connection Pool\n pgbouncer:\n image: pgbouncer/pgbouncer:1.19.1\n networks:\n - backend\n volumes:\n - ./infrastructure/database/pgbouncer.ini:/etc/pgbouncer/pgbouncer.ini:ro\n - ${PGBOUNCER_AUTH_FILE:?set PGBOUNCER_AUTH_FILE}:/etc/pgbouncer/userlist.txt:ro\n environment:\n - DATABASES_HOST=postgres\n - DATABASES_PORT=5432\n - DATABASES_USER=postgres\n - DATABASES_PASSWORD=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}\n - DATABASES_DBNAME=brain_researcher\n - POOL_MODE=transaction\n - MAX_CLIENT_CONN=1000\n - DEFAULT_POOL_SIZE=50\n deploy:\n replicas: 2\n placement:\n max_replicas_per_node: 1\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.5'\n memory: 256M\n reservations:\n cpus: '0.25'\n memory: 128M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n depends_on:\n - postgres\n healthcheck:\n test: [\"CMD-SHELL\", \"psql -h localhost -p 6432 -U postgres -d brain_researcher -c 'SELECT 1;' || exit 1\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Prometheus Monitoring\n prometheus:\n image: prom/prometheus:v2.44.0\n networks:\n - backend\n volumes:\n - ./infrastructure/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro\n - prometheus_data:/prometheus\n command:\n - '--config.file=/etc/prometheus/prometheus.yml'\n - '--storage.tsdb.path=/prometheus'\n - '--web.console.libraries=/usr/share/prometheus/console_libraries'\n - '--web.console.templates=/usr/share/prometheus/consoles'\n - '--storage.tsdb.retention.time=15d'\n - '--web.enable-lifecycle'\n - '--web.enable-admin-api'\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == monitoring\n resources:\n limits:\n cpus: '1.0'\n memory: 1G\n reservations:\n cpus: '0.5'\n memory: 512M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n\n # Grafana Dashboard\n grafana:\n image: grafana/grafana:9.5.2\n networks:\n - backend\n volumes:\n - grafana_data:/var/lib/grafana\n - ./infrastructure/monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro\n - ./infrastructure/monitoring/grafana/provisioning:/etc/grafana/provisioning:ro\n environment:\n - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:?set GRAFANA_ADMIN_PASSWORD}\n - GF_USERS_ALLOW_SIGN_UP=false\n - GF_SERVER_ROOT_URL=http://localhost:3000/grafana\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == monitoring\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n\nnetworks:\n frontend:\n driver: overlay\n external: false\n backend:\n driver: overlay\n external: false\n\nvolumes:\n redis_master_data:\n redis_replica_data:\n postgres_data:\n prometheus_data:\n grafana_data:\n\n# Global configuration\nconfigs:\n haproxy_config:\n file: ./infrastructure/haproxy/haproxy.cfg\n pgbouncer_config:\n file: ./infrastructure/database/pgbouncer.ini\n\nsecrets:\n postgres_password:\n external: true\n openai_api_key:\n external: true\n anthropic_api_key:\n external: true\n"}, "b4b9ad6154ca54646a4f49d98f6b119e8916e321": {"t": 1785749120.0953639, "n": 11122, "h": "638ac5f12f82d8eb", "c": "services:\n # Load Balancer (HAProxy)\n haproxy:\n image: haproxy:2.8-alpine\n ports:\n - \"80:80\"\n - \"443:443\"\n - \"8080:8080\" # HAProxy stats\n volumes:\n - ./infrastructure/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro\n - ./infrastructure/haproxy/ssl:/etc/ssl/certs:ro\n networks:\n - frontend\n - backend\n deploy:\n replicas: 2\n placement:\n constraints:\n - node.role == manager\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n update_config:\n parallelism: 1\n delay: 10s\n failure_action: rollback\n rollback_config:\n parallelism: 1\n delay: 10s\n\n # BR-KG API Service - Replicated\n br-kg:\n build:\n context: .\n target: br-kg\n networks:\n - backend\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n deploy:\n replicas: 4\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == api\n resources:\n limits:\n cpus: '1.0'\n memory: 1G\n reservations:\n cpus: '0.5'\n memory: 512M\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n update_config:\n parallelism: 2\n delay: 10s\n failure_action: rollback\n monitor: 60s\n rollback_config:\n parallelism: 2\n delay: 10s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\"]\n interval: 30s\n timeout: 15s\n retries: 3\n start_period: 60s\n\n # Agent Service - Multiple Replicas\n agent:\n build:\n context: .\n target: agent\n networks:\n - backend\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - REDIS_URL=redis://redis:6379\n deploy:\n replicas: 3\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == compute\n resources:\n limits:\n cpus: '2.0'\n memory: 2G\n reservations:\n cpus: '1.0'\n memory: 1G\n restart_policy:\n condition: on-failure\n delay: 15s\n max_attempts: 3\n update_config:\n parallelism: 1\n delay: 30s\n failure_action: rollback\n monitor: 120s\n rollback_config:\n parallelism: 1\n delay: 30s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\"]\n interval: 45s\n timeout: 15s\n retries: 3\n start_period: 120s\n\n # Orchestrator API Gateway - Highly Available\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n networks:\n - backend\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n - NICLIP_URL=http://niclip:8001\n - REDIS_URL=redis://redis:6379\n - DATABASE_URL=postgresql://postgres:password@postgres:5432/brain_researcher\n deploy:\n replicas: 5\n placement:\n max_replicas_per_node: 3\n constraints:\n - node.labels.tier == orchestrator\n resources:\n limits:\n cpus: '1.5'\n memory: 1.5G\n reservations:\n cpus: '0.75'\n memory: 750M\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n update_config:\n parallelism: 2\n delay: 15s\n failure_action: rollback\n monitor: 90s\n rollback_config:\n parallelism: 2\n delay: 15s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:3001/health\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n\n # Web UI - Multiple Frontend Instances\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n networks:\n - backend\n environment:\n - NODE_ENV=production\n - NEXT_PUBLIC_API_URL=http://orchestrator:3001\n - NEXT_PUBLIC_APP_NAME=Brain Researcher Web\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n deploy:\n replicas: 4\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == web\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n update_config:\n parallelism: 2\n delay: 10s\n failure_action: rollback\n monitor: 60s\n rollback_config:\n parallelism: 2\n delay: 10s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:3000\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n\n # Redis Cluster for State Management\n redis-master:\n image: redis:7-alpine\n networks:\n - backend\n volumes:\n - redis_master_data:/data\n command: redis-server --appendonly yes --replica-read-only no\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 30s\n timeout: 5s\n retries: 3\n\n redis-replica:\n image: redis:7-alpine\n networks:\n - backend\n volumes:\n - redis_replica_data:/data\n command: redis-server --appendonly yes --replicaof redis-master 6379\n deploy:\n replicas: 2\n placement:\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.25'\n memory: 256M\n reservations:\n cpus: '0.125'\n memory: 128M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n depends_on:\n - redis-master\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 30s\n timeout: 5s\n retries: 3\n\n # PostgreSQL with Connection Pooling\n postgres:\n image: postgres:15-alpine\n networks:\n - backend\n volumes:\n - postgres_data:/var/lib/postgresql/data\n - ./infrastructure/database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro\n environment:\n - POSTGRES_DB=brain_researcher\n - POSTGRES_USER=postgres\n - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-password}\n - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == storage\n - node.role == manager\n resources:\n limits:\n cpus: '2.0'\n memory: 2G\n reservations:\n cpus: '1.0'\n memory: 1G\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U postgres -d brain_researcher\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # PgBouncer Connection Pool\n pgbouncer:\n image: pgbouncer/pgbouncer:1.19.1\n networks:\n - backend\n volumes:\n - ./infrastructure/database/pgbouncer.ini:/etc/pgbouncer/pgbouncer.ini:ro\n - ./infrastructure/database/userlist.txt:/etc/pgbouncer/userlist.txt:ro\n environment:\n - DATABASES_HOST=postgres\n - DATABASES_PORT=5432\n - DATABASES_USER=postgres\n - DATABASES_PASSWORD=${POSTGRES_PASSWORD:-password}\n - DATABASES_DBNAME=brain_researcher\n - POOL_MODE=transaction\n - MAX_CLIENT_CONN=1000\n - DEFAULT_POOL_SIZE=50\n deploy:\n replicas: 2\n placement:\n max_replicas_per_node: 1\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.5'\n memory: 256M\n reservations:\n cpus: '0.25'\n memory: 128M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n depends_on:\n - postgres\n healthcheck:\n test: [\"CMD-SHELL\", \"psql -h localhost -p 6432 -U postgres -d brain_researcher -c 'SELECT 1;' || exit 1\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Prometheus Monitoring\n prometheus:\n image: prom/prometheus:v2.44.0\n networks:\n - backend\n volumes:\n - ./infrastructure/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro\n - prometheus_data:/prometheus\n command:\n - '--config.file=/etc/prometheus/prometheus.yml'\n - '--storage.tsdb.path=/prometheus'\n - '--web.console.libraries=/usr/share/prometheus/console_libraries'\n - '--web.console.templates=/usr/share/prometheus/consoles'\n - '--storage.tsdb.retention.time=15d'\n - '--web.enable-lifecycle'\n - '--web.enable-admin-api'\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == monitoring\n resources:\n limits:\n cpus: '1.0'\n memory: 1G\n reservations:\n cpus: '0.5'\n memory: 512M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n\n # Grafana Dashboard\n grafana:\n image: grafana/grafana:9.5.2\n networks:\n - backend\n volumes:\n - grafana_data:/var/lib/grafana\n - ./infrastructure/monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro\n - ./infrastructure/monitoring/grafana/provisioning:/etc/grafana/provisioning:ro\n environment:\n - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:?set GRAFANA_ADMIN_PASSWORD}\n - GF_USERS_ALLOW_SIGN_UP=false\n - GF_SERVER_ROOT_URL=http://localhost:3000/grafana\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == monitoring\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n\nnetworks:\n frontend:\n driver: overlay\n external: false\n backend:\n driver: overlay\n external: false\n\nvolumes:\n redis_master_data:\n redis_replica_data:\n postgres_data:\n prometheus_data:\n grafana_data:\n\n# Global configuration\nconfigs:\n haproxy_config:\n file: ./infrastructure/haproxy/haproxy.cfg\n pgbouncer_config:\n file: ./infrastructure/database/pgbouncer.ini\n\nsecrets:\n postgres_password:\n external: true\n openai_api_key:\n external: true\n anthropic_api_key:\n external: true\n"}, "ba5c18fca5405755729e6b0bcb7c737c827f6ed2": {"t": 1785749122.3464375, "n": 11104, "h": "8a1543fd8bf1616b", "c": "services:\n # Load Balancer (HAProxy)\n haproxy:\n image: haproxy:2.8-alpine\n ports:\n - \"80:80\"\n - \"443:443\"\n - \"8080:8080\" # HAProxy stats\n volumes:\n - ./infrastructure/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro\n - ./infrastructure/haproxy/ssl:/etc/ssl/certs:ro\n networks:\n - frontend\n - backend\n deploy:\n replicas: 2\n placement:\n constraints:\n - node.role == manager\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n update_config:\n parallelism: 1\n delay: 10s\n failure_action: rollback\n rollback_config:\n parallelism: 1\n delay: 10s\n\n # BR-KG API Service - Replicated\n br-kg:\n build:\n context: .\n target: br-kg\n networks:\n - backend\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n deploy:\n replicas: 4\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == api\n resources:\n limits:\n cpus: '1.0'\n memory: 1G\n reservations:\n cpus: '0.5'\n memory: 512M\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n update_config:\n parallelism: 2\n delay: 10s\n failure_action: rollback\n monitor: 60s\n rollback_config:\n parallelism: 2\n delay: 10s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\"]\n interval: 30s\n timeout: 15s\n retries: 3\n start_period: 60s\n\n # Agent Service - Multiple Replicas\n agent:\n build:\n context: .\n target: agent\n networks:\n - backend\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - BR_KG_API_URL=http://br-kg:5000\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - REDIS_URL=redis://redis:6379\n deploy:\n replicas: 3\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == compute\n resources:\n limits:\n cpus: '2.0'\n memory: 2G\n reservations:\n cpus: '1.0'\n memory: 1G\n restart_policy:\n condition: on-failure\n delay: 15s\n max_attempts: 3\n update_config:\n parallelism: 1\n delay: 30s\n failure_action: rollback\n monitor: 120s\n rollback_config:\n parallelism: 1\n delay: 30s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\"]\n interval: 45s\n timeout: 15s\n retries: 3\n start_period: 120s\n\n # Orchestrator API Gateway - Highly Available\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n networks:\n - backend\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - BR_KG_URL=http://br-kg:5000\n - NICLIP_URL=http://niclip:8001\n - REDIS_URL=redis://redis:6379\n - DATABASE_URL=postgresql://postgres:password@postgres:5432/brain_researcher\n deploy:\n replicas: 5\n placement:\n max_replicas_per_node: 3\n constraints:\n - node.labels.tier == orchestrator\n resources:\n limits:\n cpus: '1.5'\n memory: 1.5G\n reservations:\n cpus: '0.75'\n memory: 750M\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n update_config:\n parallelism: 2\n delay: 15s\n failure_action: rollback\n monitor: 90s\n rollback_config:\n parallelism: 2\n delay: 15s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:3001/health\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n\n # Web UI - Multiple Frontend Instances\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n networks:\n - backend\n environment:\n - NODE_ENV=production\n - NEXT_PUBLIC_API_URL=http://orchestrator:3001\n - NEXT_PUBLIC_APP_NAME=Brain Researcher Web\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n deploy:\n replicas: 4\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == web\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n update_config:\n parallelism: 2\n delay: 10s\n failure_action: rollback\n monitor: 60s\n rollback_config:\n parallelism: 2\n delay: 10s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:3000\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n\n # Redis Cluster for State Management\n redis-master:\n image: redis:7-alpine\n networks:\n - backend\n volumes:\n - redis_master_data:/data\n command: redis-server --appendonly yes --replica-read-only no\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 30s\n timeout: 5s\n retries: 3\n\n redis-replica:\n image: redis:7-alpine\n networks:\n - backend\n volumes:\n - redis_replica_data:/data\n command: redis-server --appendonly yes --replicaof redis-master 6379\n deploy:\n replicas: 2\n placement:\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.25'\n memory: 256M\n reservations:\n cpus: '0.125'\n memory: 128M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n depends_on:\n - redis-master\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 30s\n timeout: 5s\n retries: 3\n\n # PostgreSQL with Connection Pooling\n postgres:\n image: postgres:15-alpine\n networks:\n - backend\n volumes:\n - postgres_data:/var/lib/postgresql/data\n - ./infrastructure/database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro\n environment:\n - POSTGRES_DB=brain_researcher\n - POSTGRES_USER=postgres\n - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-password}\n - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == storage\n - node.role == manager\n resources:\n limits:\n cpus: '2.0'\n memory: 2G\n reservations:\n cpus: '1.0'\n memory: 1G\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U postgres -d brain_researcher\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # PgBouncer Connection Pool\n pgbouncer:\n image: pgbouncer/pgbouncer:1.19.1\n networks:\n - backend\n volumes:\n - ./infrastructure/database/pgbouncer.ini:/etc/pgbouncer/pgbouncer.ini:ro\n - ./infrastructure/database/userlist.txt:/etc/pgbouncer/userlist.txt:ro\n environment:\n - DATABASES_HOST=postgres\n - DATABASES_PORT=5432\n - DATABASES_USER=postgres\n - DATABASES_PASSWORD=${POSTGRES_PASSWORD:-password}\n - DATABASES_DBNAME=brain_researcher\n - POOL_MODE=transaction\n - MAX_CLIENT_CONN=1000\n - DEFAULT_POOL_SIZE=50\n deploy:\n replicas: 2\n placement:\n max_replicas_per_node: 1\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.5'\n memory: 256M\n reservations:\n cpus: '0.25'\n memory: 128M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n depends_on:\n - postgres\n healthcheck:\n test: [\"CMD-SHELL\", \"psql -h localhost -p 6432 -U postgres -d brain_researcher -c 'SELECT 1;' || exit 1\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Prometheus Monitoring\n prometheus:\n image: prom/prometheus:v2.44.0\n networks:\n - backend\n volumes:\n - ./infrastructure/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro\n - prometheus_data:/prometheus\n command:\n - '--config.file=/etc/prometheus/prometheus.yml'\n - '--storage.tsdb.path=/prometheus'\n - '--web.console.libraries=/usr/share/prometheus/console_libraries'\n - '--web.console.templates=/usr/share/prometheus/consoles'\n - '--storage.tsdb.retention.time=15d'\n - '--web.enable-lifecycle'\n - '--web.enable-admin-api'\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == monitoring\n resources:\n limits:\n cpus: '1.0'\n memory: 1G\n reservations:\n cpus: '0.5'\n memory: 512M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n\n # Grafana Dashboard\n grafana:\n image: grafana/grafana:9.5.2\n networks:\n - backend\n volumes:\n - grafana_data:/var/lib/grafana\n - ./infrastructure/monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro\n - ./infrastructure/monitoring/grafana/provisioning:/etc/grafana/provisioning:ro\n environment:\n - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:-admin123}\n - GF_USERS_ALLOW_SIGN_UP=false\n - GF_SERVER_ROOT_URL=http://localhost:3000/grafana\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == monitoring\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n\nnetworks:\n frontend:\n driver: overlay\n external: false\n backend:\n driver: overlay\n external: false\n\nvolumes:\n redis_master_data:\n redis_replica_data:\n postgres_data:\n prometheus_data:\n grafana_data:\n\n# Global configuration\nconfigs:\n haproxy_config:\n file: ./infrastructure/haproxy/haproxy.cfg\n pgbouncer_config:\n file: ./infrastructure/database/pgbouncer.ini\n\nsecrets:\n postgres_password:\n external: true\n openai_api_key:\n external: true\n anthropic_api_key:\n external: true\n"}, "9e86e308c3adfb5e13bc513f9ac69307cd1cd5a4": {"t": 1785749123.5038757, "n": 11116, "h": "46925a1c7758e45d", "c": "services:\n # Load Balancer (HAProxy)\n haproxy:\n image: haproxy:2.8-alpine\n ports:\n - \"80:80\"\n - \"443:443\"\n - \"8080:8080\" # HAProxy stats\n volumes:\n - ./infrastructure/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro\n - ./infrastructure/haproxy/ssl:/etc/ssl/certs:ro\n networks:\n - frontend\n - backend\n deploy:\n replicas: 2\n placement:\n constraints:\n - node.role == manager\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n update_config:\n parallelism: 1\n delay: 10s\n failure_action: rollback\n rollback_config:\n parallelism: 1\n delay: 10s\n\n # BR-KG API Service - Replicated\n neurokg:\n build:\n context: .\n target: neurokg\n networks:\n - backend\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n deploy:\n replicas: 4\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == api\n resources:\n limits:\n cpus: '1.0'\n memory: 1G\n reservations:\n cpus: '0.5'\n memory: 512M\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n update_config:\n parallelism: 2\n delay: 10s\n failure_action: rollback\n monitor: 60s\n rollback_config:\n parallelism: 2\n delay: 10s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:5000/health\"]\n interval: 30s\n timeout: 15s\n retries: 3\n start_period: 60s\n\n # Agent Service - Multiple Replicas\n agent:\n build:\n context: .\n target: agent\n networks:\n - backend\n volumes:\n - ./data:/app/data\n - ./logs:/app/logs\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - NEUROKG_API_URL=http://neurokg:5000\n - OPENAI_API_KEY=${OPENAI_API_KEY:-}\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}\n - REDIS_URL=redis://redis:6379\n deploy:\n replicas: 3\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == compute\n resources:\n limits:\n cpus: '2.0'\n memory: 2G\n reservations:\n cpus: '1.0'\n memory: 1G\n restart_policy:\n condition: on-failure\n delay: 15s\n max_attempts: 3\n update_config:\n parallelism: 1\n delay: 30s\n failure_action: rollback\n monitor: 120s\n rollback_config:\n parallelism: 1\n delay: 30s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\"]\n interval: 45s\n timeout: 15s\n retries: 3\n start_period: 120s\n\n # Orchestrator API Gateway - Highly Available\n orchestrator:\n build:\n context: .\n dockerfile: infrastructure/docker/Dockerfile.orchestrator\n networks:\n - backend\n environment:\n - PYTHONPATH=/app/src\n - PYTHONUNBUFFERED=1\n - AGENT_URL=http://agent:8000\n - NEUROKG_URL=http://neurokg:5000\n - NICLIP_URL=http://niclip:8001\n - REDIS_URL=redis://redis:6379\n - DATABASE_URL=postgresql://postgres:password@postgres:5432/brain_researcher\n deploy:\n replicas: 5\n placement:\n max_replicas_per_node: 3\n constraints:\n - node.labels.tier == orchestrator\n resources:\n limits:\n cpus: '1.5'\n memory: 1.5G\n reservations:\n cpus: '0.75'\n memory: 750M\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n update_config:\n parallelism: 2\n delay: 15s\n failure_action: rollback\n monitor: 90s\n rollback_config:\n parallelism: 2\n delay: 15s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:3001/health\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n\n # Web UI - Multiple Frontend Instances\n web-ui:\n build:\n context: .\n dockerfile: apps/web-ui/Dockerfile\n networks:\n - backend\n environment:\n - NODE_ENV=production\n - NEXT_PUBLIC_API_URL=http://orchestrator:3001\n - NEXT_PUBLIC_APP_NAME=Brain Researcher Web\n - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL:-}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY:-}\n deploy:\n replicas: 4\n placement:\n max_replicas_per_node: 2\n constraints:\n - node.labels.tier == web\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n update_config:\n parallelism: 2\n delay: 10s\n failure_action: rollback\n monitor: 60s\n rollback_config:\n parallelism: 2\n delay: 10s\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:3000\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 60s\n\n # Redis Cluster for State Management\n redis-master:\n image: redis:7-alpine\n networks:\n - backend\n volumes:\n - redis_master_data:/data\n command: redis-server --appendonly yes --replica-read-only no\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 30s\n timeout: 5s\n retries: 3\n\n redis-replica:\n image: redis:7-alpine\n networks:\n - backend\n volumes:\n - redis_replica_data:/data\n command: redis-server --appendonly yes --replicaof redis-master 6379\n deploy:\n replicas: 2\n placement:\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.25'\n memory: 256M\n reservations:\n cpus: '0.125'\n memory: 128M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n depends_on:\n - redis-master\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 30s\n timeout: 5s\n retries: 3\n\n # PostgreSQL with Connection Pooling\n postgres:\n image: postgres:15-alpine\n networks:\n - backend\n volumes:\n - postgres_data:/var/lib/postgresql/data\n - ./infrastructure/database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro\n environment:\n - POSTGRES_DB=brain_researcher\n - POSTGRES_USER=postgres\n - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-password}\n - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == storage\n - node.role == manager\n resources:\n limits:\n cpus: '2.0'\n memory: 2G\n reservations:\n cpus: '1.0'\n memory: 1G\n restart_policy:\n condition: on-failure\n delay: 10s\n max_attempts: 5\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U postgres -d brain_researcher\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # PgBouncer Connection Pool\n pgbouncer:\n image: pgbouncer/pgbouncer:1.19.1\n networks:\n - backend\n volumes:\n - ./infrastructure/database/pgbouncer.ini:/etc/pgbouncer/pgbouncer.ini:ro\n - ./infrastructure/database/userlist.txt:/etc/pgbouncer/userlist.txt:ro\n environment:\n - DATABASES_HOST=postgres\n - DATABASES_PORT=5432\n - DATABASES_USER=postgres\n - DATABASES_PASSWORD=${POSTGRES_PASSWORD:-password}\n - DATABASES_DBNAME=brain_researcher\n - POOL_MODE=transaction\n - MAX_CLIENT_CONN=1000\n - DEFAULT_POOL_SIZE=50\n deploy:\n replicas: 2\n placement:\n max_replicas_per_node: 1\n constraints:\n - node.labels.tier == storage\n resources:\n limits:\n cpus: '0.5'\n memory: 256M\n reservations:\n cpus: '0.25'\n memory: 128M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n depends_on:\n - postgres\n healthcheck:\n test: [\"CMD-SHELL\", \"psql -h localhost -p 6432 -U postgres -d brain_researcher -c 'SELECT 1;' || exit 1\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n # Prometheus Monitoring\n prometheus:\n image: prom/prometheus:v2.44.0\n networks:\n - backend\n volumes:\n - ./infrastructure/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro\n - prometheus_data:/prometheus\n command:\n - '--config.file=/etc/prometheus/prometheus.yml'\n - '--storage.tsdb.path=/prometheus'\n - '--web.console.libraries=/usr/share/prometheus/console_libraries'\n - '--web.console.templates=/usr/share/prometheus/consoles'\n - '--storage.tsdb.retention.time=15d'\n - '--web.enable-lifecycle'\n - '--web.enable-admin-api'\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == monitoring\n resources:\n limits:\n cpus: '1.0'\n memory: 1G\n reservations:\n cpus: '0.5'\n memory: 512M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n\n # Grafana Dashboard\n grafana:\n image: grafana/grafana:9.5.2\n networks:\n - backend\n volumes:\n - grafana_data:/var/lib/grafana\n - ./infrastructure/monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro\n - ./infrastructure/monitoring/grafana/provisioning:/etc/grafana/provisioning:ro\n environment:\n - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:-admin123}\n - GF_USERS_ALLOW_SIGN_UP=false\n - GF_SERVER_ROOT_URL=http://localhost:3000/grafana\n deploy:\n replicas: 1\n placement:\n constraints:\n - node.labels.tier == monitoring\n resources:\n limits:\n cpus: '0.5'\n memory: 512M\n reservations:\n cpus: '0.25'\n memory: 256M\n restart_policy:\n condition: on-failure\n delay: 5s\n max_attempts: 3\n\nnetworks:\n frontend:\n driver: overlay\n external: false\n backend:\n driver: overlay\n external: false\n\nvolumes:\n redis_master_data:\n redis_replica_data:\n postgres_data:\n prometheus_data:\n grafana_data:\n\n# Global configuration\nconfigs:\n haproxy_config:\n file: ./infrastructure/haproxy/haproxy.cfg\n pgbouncer_config:\n file: ./infrastructure/database/pgbouncer.ini\n\nsecrets:\n postgres_password:\n external: true\n openai_api_key:\n external: true\n anthropic_api_key:\n external: true\n"}}, "src/brain_researcher/services/agent/.env.example": {"3305b62aef6852ddf0b33fde658e0048a4af65da": {"t": 1786068546.0429065, "n": 1275, "h": "c3b18e7b7a866b19", "c": "# Brain Researcher Agent Environment Configuration\n\n# BR-KG API Configuration\nBR_KG_API_URL=http://localhost:5010\n\n# LLM Configuration\n## DeepSeek (default)\n# API base is OpenAI-compatible; prefer setting BASE explicitly for new endpoints\nDEEPSEEK_API_KEY=your_deepseek_key\nDEEPSEEK_API_URL=https://api.deepseek.com/v1/chat/completions\n# If DeepSeek changes endpoints, set BASE to the root (e.g., https://api.deepseek.com)\nDEEPSEEK_API_BASE=https://api.deepseek.com\n# Explicit DeepSeek model (overrides default)\nDEEPSEEK_MODEL=deepseek-chat\n\n# Default model selection\nDEFAULT_LLM_MODEL=deepseek-chat\n\n# Alternative LLM Providers:\n# For Anthropic Claude:\n# ANTHROPIC_API_KEY=your_anthropic_api_key_here\n# DEFAULT_LLM_MODEL=claude-3-sonnet-20240229\n\n# For OpenAI:\n# OPENAI_API_KEY=your_openai_api_key_here\n# DEFAULT_LLM_MODEL=gpt-4o\n\n# For Google Gemini (optional — requires extra packages):\n# GOOGLE_API_KEY=your_gemini_api_key_here\n# DEFAULT_LLM_MODEL=gemini-1.5-pro # or gemini-1.5-flash for speed\n\n# Tool Configuration\nTOOL_TIMEOUT_SECONDS=300 # 5 minutes default timeout for tool execution\n\n# Agent Configuration\nUSE_TOOL_RETRIEVER=false # Set to true to enable LLM-based tool selection\nMAX_ITERATIONS=10 # Maximum number of agent iterations\n\n# Logging\nLOG_LEVEL=INFO\n"}}}} |