name: valuesee x-app-environment: &app-environment APP_ENV: production DATABASE_URL: postgresql://valuesee:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/valuesee REDIS_URL: redis://redis:6379/0 RABBITMQ_URL: amqp://valuesee:${RABBITMQ_PASSWORD:?set RABBITMQ_PASSWORD}@rabbitmq:5672/%2F S3_ENDPOINT_URL: http://minio:9000 S3_BUCKET: valuesee-uploads S3_ACCESS_KEY: ${MINIO_ROOT_USER:?set MINIO_ROOT_USER} S3_SECRET_KEY: ${MINIO_ROOT_PASSWORD:?set MINIO_ROOT_PASSWORD} VALUSee_JWT_SECRET: ${VALUSee_JWT_SECRET:?set VALUSee_JWT_SECRET} VALUSee_METRICS_TOKEN: ${VALUSee_METRICS_TOKEN:?set VALUSee_METRICS_TOKEN} VALUSee_MFA_ENCRYPTION_KEY: ${VALUSee_MFA_ENCRYPTION_KEY:?set VALUSee_MFA_ENCRYPTION_KEY} ALLOWED_HOSTS: ${ALLOWED_HOSTS:?set ALLOWED_HOSTS} ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:?set ALLOWED_ORIGINS} VALUSee_ADMIN_EMAILS: ${VALUSee_ADMIN_EMAILS:?set VALUSee_ADMIN_EMAILS} VALUSee_PUBLIC_BASE_URL: ${VALUSee_PUBLIC_BASE_URL:?set VALUSee_PUBLIC_BASE_URL} FORWARDED_ALLOW_IPS: ${FORWARDED_ALLOW_IPS:?set FORWARDED_ALLOW_IPS} VALUSee_MONITOR_INTERVAL_SECONDS: "60" OPENAI_API_KEY: ${OPENAI_API_KEY:-} OPENAI_BASE_URL: ${OPENAI_BASE_URL:-} OPENAI_WIRE_API: ${OPENAI_WIRE_API:-responses} DEV_AGENT_LLM_MODEL: ${DEV_AGENT_LLM_MODEL:-gpt-5.6-sol} VALUSee_VISION_MODEL: ${VALUSee_VISION_MODEL:-gpt-5.6-sol} VALUSee_VISION_MODELS: ${VALUSee_VISION_MODELS:-gpt-5.6-sol} OPENAI_VISION_FALLBACK_API_KEY: ${OPENAI_VISION_FALLBACK_API_KEY:-} OPENAI_VISION_FALLBACK_BASE_URL: ${OPENAI_VISION_FALLBACK_BASE_URL:-} OPENAI_VISION_FALLBACK_MODEL: ${OPENAI_VISION_FALLBACK_MODEL:-gpt-5.6-sol} OPENAI_VISION_FALLBACK_WIRE_API: ${OPENAI_VISION_FALLBACK_WIRE_API:-responses} DEV_AGENT_LLM_MODEL_PLANNER: ${DEV_AGENT_LLM_MODEL_PLANNER:-} DEV_AGENT_LLM_MODEL_REPORTER: ${DEV_AGENT_LLM_MODEL_REPORTER:-} DEV_AGENT_LLM_MODEL_SUPERVISOR: ${DEV_AGENT_LLM_MODEL_SUPERVISOR:-} DEV_AGENT_LLM_MODEL_PROJECT_ANALYZER: ${DEV_AGENT_LLM_MODEL_PROJECT_ANALYZER:-} DEV_AGENT_LLM_MODEL_CODE_REVIEWER: ${DEV_AGENT_LLM_MODEL_CODE_REVIEWER:-} DEV_AGENT_LLM_MODEL_FILE_REVIEWER: ${DEV_AGENT_LLM_MODEL_FILE_REVIEWER:-} DEV_AGENT_LLM_MODEL_TASK_QA: ${DEV_AGENT_LLM_MODEL_TASK_QA:-} DEV_AGENT_LLM_MODEL_LEARNING_COACH: ${DEV_AGENT_LLM_MODEL_LEARNING_COACH:-} DEV_AGENT_LLM_MODEL_MEMORY_EXTRACTOR: ${DEV_AGENT_LLM_MODEL_MEMORY_EXTRACTOR:-} DEV_AGENT_LLM_AGENT_MODELS: ${DEV_AGENT_LLM_AGENT_MODELS:-} DEV_AGENT_MEMORY_EXTRACTOR: ${DEV_AGENT_MEMORY_EXTRACTOR:-llm} DEV_AGENT_EMBEDDING_MODEL: ${DEV_AGENT_EMBEDDING_MODEL:-text-embedding-3-small} DEV_AGENT_EMBEDDING_DIM: ${DEV_AGENT_EMBEDDING_DIM:-1536} DEV_AGENT_LLM_PRICE_GPT_4O_MINI_INPUT_PER_1M: ${DEV_AGENT_LLM_PRICE_GPT_4O_MINI_INPUT_PER_1M:-} DEV_AGENT_LLM_PRICE_GPT_4O_MINI_OUTPUT_PER_1M: ${DEV_AGENT_LLM_PRICE_GPT_4O_MINI_OUTPUT_PER_1M:-} VALUSee_SMTP_HOST: ${VALUSee_SMTP_HOST:-} VALUSee_SMTP_PORT: ${VALUSee_SMTP_PORT:-465} VALUSee_SMTP_USERNAME: ${VALUSee_SMTP_USERNAME:-} VALUSee_SMTP_PASSWORD: ${VALUSee_SMTP_PASSWORD:-} VALUSee_SMTP_FROM: ${VALUSee_SMTP_FROM:-} VALUSee_SMTP_SSL: ${VALUSee_SMTP_SSL:-true} VALUSee_NOTIFICATION_WEBHOOK_URL: ${VALUSee_NOTIFICATION_WEBHOOK_URL:-} VALUSee_NOTIFICATION_WEBHOOK_SECRET: ${VALUSee_NOTIFICATION_WEBHOOK_SECRET:-} JD_APP_KEY: ${JD_APP_KEY:-} JD_APP_SECRET: ${JD_APP_SECRET:-} JD_UNION_PID: ${JD_UNION_PID:-} JD_ADAPTER_BASE_URL: ${JD_ADAPTER_BASE_URL:-} JD_ADAPTER_TOKEN: ${JD_ADAPTER_TOKEN:-} TAOBAO_APP_KEY: ${TAOBAO_APP_KEY:-} TAOBAO_APP_SECRET: ${TAOBAO_APP_SECRET:-} TAOBAO_ADAPTER_BASE_URL: ${TAOBAO_ADAPTER_BASE_URL:-} TAOBAO_ADAPTER_TOKEN: ${TAOBAO_ADAPTER_TOKEN:-} PDD_CLIENT_ID: ${PDD_CLIENT_ID:-} PDD_CLIENT_SECRET: ${PDD_CLIENT_SECRET:-} PDD_PID: ${PDD_PID:-} PDD_CUSTOM_PARAMETERS: ${PDD_CUSTOM_PARAMETERS:-} PDD_ADAPTER_BASE_URL: ${PDD_ADAPTER_BASE_URL:-} PDD_ADAPTER_TOKEN: ${PDD_ADAPTER_TOKEN:-} VALUSee_COMMERCE_PROVIDERS: ${VALUSee_COMMERCE_PROVIDERS:-[]} services: api: build: . restart: unless-stopped environment: *app-environment ports: - "${APP_PORT:-8000}:8000" depends_on: postgres: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy object-storage-init: condition: service_completed_successfully read_only: true tmpfs: - /tmp volumes: - application-data:/app/data security_opt: - no-new-privileges:true healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=3)"] interval: 15s timeout: 5s retries: 5 monitor-worker: build: . command: ["python", "-m", "app.shopping.worker"] restart: unless-stopped environment: *app-environment depends_on: postgres: condition: service_healthy rabbitmq: condition: service_healthy read_only: true tmpfs: - /tmp security_opt: - no-new-privileges:true healthcheck: test: ["CMD", "python", "-c", "import os,time,sys; p='/tmp/valuesee-worker-heartbeat'; sys.exit(0 if os.path.exists(p) and time.time()-os.path.getmtime(p)<180 else 1)"] interval: 30s timeout: 5s start_period: 90s retries: 3 postgres: image: pgvector/pgvector:pg17 restart: unless-stopped environment: POSTGRES_DB: valuesee POSTGRES_USER: valuesee POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD} volumes: - postgres-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U valuesee -d valuesee"] interval: 10s timeout: 5s retries: 10 redis: image: redis:7.4-alpine restart: unless-stopped command: ["redis-server", "--appendonly", "yes", "--maxmemory-policy", "allkeys-lru"] volumes: - redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 10 rabbitmq: image: rabbitmq:4.1-management-alpine restart: unless-stopped environment: RABBITMQ_DEFAULT_USER: valuesee RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:?set RABBITMQ_PASSWORD} volumes: - rabbitmq-data:/var/lib/rabbitmq healthcheck: test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"] interval: 10s timeout: 5s retries: 12 minio: image: minio/minio:RELEASE.2025-07-23T15-54-02Z command: server /data --console-address :9001 restart: unless-stopped environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:?set MINIO_ROOT_USER} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?set MINIO_ROOT_PASSWORD} volumes: - minio-data:/data healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 10s timeout: 5s retries: 10 object-storage-init: image: valuesee-api command: ["python", "-c", "from app.core.object_storage import ensure_bucket_exists; ensure_bucket_exists()"] restart: "no" environment: S3_ENDPOINT_URL: http://minio:9000 S3_BUCKET: valuesee-uploads S3_ACCESS_KEY: ${MINIO_ROOT_USER:?set MINIO_ROOT_USER} S3_SECRET_KEY: ${MINIO_ROOT_PASSWORD:?set MINIO_ROOT_PASSWORD} depends_on: minio: condition: service_healthy read_only: true tmpfs: - /tmp security_opt: - no-new-privileges:true volumes: postgres-data: redis-data: rabbitmq-data: minio-data: application-data: