- SEMANTIC_SUMMARY_REPLACE_SESSIONS supports * (all sessions, present and future), mirroring INTENT_PLAN_PROJECT_ALLOWLIST; empty allowlist still replaces nothing (fail-closed defense in depth unchanged) - declare SEMANTIC_SUMMARY_REPLACE(_SESSIONS) in dev/test/main compose app env (stale Wave2 "REPLACE unwired" comment fixed); extend A-4 declaration test; .env.example key docs updated - sysadmin feature catalog: SESSIONS description + REPLACE reason note * Prepares dev degraded-flags enable (task degraded-flags-enable-2026-09-26-r4): user-authorized all-session replace, plan tier confirm, shadow summary, PI change-report narrative; env ops and runtime verification follow.
222 lines
9.3 KiB
YAML
222 lines
9.3 KiB
YAML
# =============================================================================
|
||
# 主分支/生产环境编排 (Main Branch Production Environment)
|
||
# 特性:
|
||
# 1. 独占系统业务库 (5435:5432) 与专属高稳定性数据卷
|
||
# 2. 独占生产对话记录、工作区及审计日志目录 (./data/main)
|
||
# 3. 共享连接知识库服务 (shuimu-kb-shared:5432)
|
||
# =============================================================================
|
||
name: agent-main
|
||
|
||
services:
|
||
system-db:
|
||
image: pgvector/pgvector:pg16
|
||
container_name: shuimu-system-pg-main
|
||
command: ["postgres", "-c", "shared_buffers=512MB", "-c", "max_connections=300"]
|
||
environment:
|
||
POSTGRES_USER: ${SYSTEM_DB_USER:-app}
|
||
POSTGRES_PASSWORD: ${SYSTEM_DB_PASSWORD:?SYSTEM_DB_PASSWORD is required for main/production}
|
||
POSTGRES_DB: ${SYSTEM_DB_NAME:-agent_system_main}
|
||
ports:
|
||
- "127.0.0.1:${SYSTEM_DB_PUBLISH_PORT:-5435}:5432"
|
||
volumes:
|
||
- main-system-pgdata:/var/lib/postgresql/data
|
||
# T20-I4: 三环境统一仅初始化扩展;表结构一律走 app goose 迁移(空卷顺序: 扩展→迁移)
|
||
- ./deploy/postgres/extensions_init.sql:/docker-entrypoint-initdb.d/01-extensions.sql:ro
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "pg_isready -U ${SYSTEM_DB_USER:-app} -d ${SYSTEM_DB_NAME:-agent_system_main}"]
|
||
interval: 5s
|
||
timeout: 5s
|
||
retries: 20
|
||
restart: always
|
||
networks:
|
||
- main-net
|
||
|
||
pi-agent:
|
||
image: ${PI_AGENT_IMAGE:-shuimu-pi-agent:main}
|
||
build:
|
||
context: .
|
||
dockerfile: deploy/pi-agent/Dockerfile
|
||
container_name: shuimu-pi-agent-main
|
||
environment:
|
||
PORT: 18867
|
||
DATA_DIR: /app/data/workspaces
|
||
MINIMAX_ENDPOINT_URL: ${MINIMAX_ENDPOINT_URL:-https://api.minimaxi.com/v1}
|
||
MINIMAX_API_KEY: ${MINIMAX_API_KEY:-}
|
||
# Unified model across environments (was MiniMax-M3 release pin).
|
||
MINIMAX_MODEL_ID: ${MINIMAX_MODEL_ID:-MiniMax-M2.7-highspeed}
|
||
MINIMAX_API_TYPE: ${MINIMAX_API_TYPE:-openai-compatible}
|
||
MINIMAX_PROVIDER: minimax
|
||
TAVILY_API_KEYS: ${TAVILY_API_KEYS:-}
|
||
RUNNER_AUTH_TOKEN: ${RUNNER_AUTH_TOKEN:?RUNNER_AUTH_TOKEN is required for main/production}
|
||
ports:
|
||
- "127.0.0.1:${PI_AGENT_RUNNER_PORT:-18867}:18867"
|
||
volumes:
|
||
- ./data/main/workspaces:/app/data/workspaces
|
||
- ./data/main/agent_sessions:/root/.pi/agent/sessions
|
||
tmpfs:
|
||
- /tmp
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "curl -f http://127.0.0.1:18867/health || exit 1"]
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 5
|
||
restart: always
|
||
networks:
|
||
- main-net
|
||
|
||
app:
|
||
# T20-I1: 资源上限(防 OOM 连坐;app 限额独立于 runner)
|
||
mem_limit: 3g
|
||
mem_reservation: 1536m
|
||
cpus: 3.0
|
||
image: ${APP_IMAGE:-shuimu-agent-app:main}
|
||
build:
|
||
context: .
|
||
dockerfile: deploy/app/Dockerfile
|
||
args:
|
||
GOPROXY: ${GO_PROXY:-https://proxy.golang.org,direct}
|
||
container_name: shuimu-agent-app-main
|
||
depends_on:
|
||
system-db:
|
||
condition: service_healthy
|
||
events:
|
||
condition: service_healthy
|
||
# T20-B7:drain 窗口对齐 SHUTDOWN_DRAIN_TIMEOUT(默认 min(AGENT_TIMEOUT,35m)+30s)
|
||
stop_grace_period: ${SHUTDOWN_DRAIN_GRACE:-35m30s}
|
||
environment:
|
||
ENV: main
|
||
SEED_DEMO_USERS: "false"
|
||
HTTP_ADDR: ":${HTTP_PORT:-8000}"
|
||
HTTP_PORT: "${HTTP_PORT:-8000}"
|
||
HTTP_HOST: "0.0.0.0"
|
||
AGENT_BACKEND: ${AGENT_BACKEND:-pi-agent}
|
||
AGENT_TIMEOUT: ${AGENT_TIMEOUT:-30m}
|
||
MAX_CONCURRENT_AGENTS: ${MAX_CONCURRENT_AGENTS:-8}
|
||
DATA_DIR: /app/data
|
||
# 独占生产业务与对话库
|
||
APP_DB_DSN: postgres://${SYSTEM_DB_USER:-app}:${SYSTEM_DB_PASSWORD:?SYSTEM_DB_PASSWORD is required for main/production}@system-db:5432/${SYSTEM_DB_NAME:-agent_system_main}?sslmode=disable
|
||
# 共享知识库
|
||
POSTGRES_SHARED_KB_DSN: postgres://${KB_DB_USER:-regkb}:${KB_DB_PASSWORD:?KB_DB_PASSWORD is required for main/production}@shuimu-kb-shared:5432/${KB_DB_NAME:-regulations}?sslmode=disable
|
||
PI_AGENT_RUNNER_URL: http://pi-agent:18867
|
||
PI_AGENT_RUNNER_AUTH_TOKEN: ${RUNNER_AUTH_TOKEN:?RUNNER_AUTH_TOKEN is required for main/production}
|
||
PI_AGENT_PROVIDER: ${PI_AGENT_PROVIDER:-minimax}
|
||
PI_AGENT_MODEL: ${PI_AGENT_MODEL:-${MINIMAX_MODEL_ID:-MiniMax-M2.7-highspeed}}
|
||
RUNNER_AUTH_TOKEN: ${RUNNER_AUTH_TOKEN:?RUNNER_AUTH_TOKEN is required for main/production}
|
||
KB_DB_PASSWORD: ${KB_DB_PASSWORD:?KB_DB_PASSWORD is required for main/production}
|
||
ADMIN_USERNAME: ${ADMIN_USERNAME:-admin}
|
||
ADMIN_PASSWORD: ${ADMIN_PASSWORD:?ADMIN_PASSWORD is required for main/production}
|
||
AUTH_REGISTRATION_ENABLED: ${AUTH_REGISTRATION_ENABLED:-false}
|
||
AUTH_REQUIRE_APPROVAL: ${AUTH_REQUIRE_APPROVAL:-false}
|
||
EMBEDDING_ENDPOINT_URL: ${EMBEDDING_ENDPOINT_URL:-}
|
||
EMBEDDING_MODEL: ${EMBEDDING_MODEL:-bge-m3}
|
||
EMBEDDING_API_KEY: ${EMBEDDING_API_KEY:-}
|
||
RERANKER_ENDPOINT_URL: ${RERANKER_ENDPOINT_URL:-}
|
||
RERANKER_MODEL: ${RERANKER_MODEL:-bge-reranker-v2-m3-free}
|
||
RERANKER_API_KEY: ${RERANKER_API_KEY:-}
|
||
MINERU_ENDPOINT_URL: ${MINERU_ENDPOINT_URL:-https://mineru.net}
|
||
MINERU_API_KEY: ${MINERU_API_KEY:-}
|
||
MINERU_MODEL_VERSION: ${MINERU_MODEL_VERSION:-vlm}
|
||
MINERU_LANGUAGE: ${MINERU_LANGUAGE:-ch}
|
||
MINERU_TIMEOUT: ${MINERU_TIMEOUT:-90s}
|
||
MATERIAL_FULLTEXT_MAX_BYTES: ${MATERIAL_FULLTEXT_MAX_BYTES:-61440}
|
||
MATERIAL_RAG_TOP_K: ${MATERIAL_RAG_TOP_K:-8}
|
||
CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS:-}
|
||
ALLOW_IN_MEMORY: "false"
|
||
VAULT_STATE_ROOT: /app/vault
|
||
VAULT_STORAGE_IDENTITY: ${VAULT_STORAGE_IDENTITY:-main-vault}
|
||
VAULT_MASTER_KEY: ${VAULT_MASTER_KEY:-}
|
||
FAV_DEGRADED_READ: "false"
|
||
CACHE_ENABLED: ${CACHE_ENABLED:-true}
|
||
INTENT_V2_SHADOW: ${INTENT_V2_SHADOW:-false}
|
||
JEV_DECIDE_MODE: ${JEV_DECIDE_MODE:-off}
|
||
JEV_BASE_URL: ${JEV_BASE_URL:-}
|
||
JEV_API_KEY: ${JEV_API_KEY:-}
|
||
INTENT_V2_DECISION: ${INTENT_V2_DECISION:-false}
|
||
INTENT_V2_DECISION_TIER: ${INTENT_V2_DECISION_TIER:-none}
|
||
WORKFLOW_INTENTS_ENABLED: ${WORKFLOW_INTENTS_ENABLED:-true}
|
||
MULTI_INTENT_ENABLED: ${MULTI_INTENT_ENABLED:-true}
|
||
MULTI_INTENT_PLAN_TIER: ${MULTI_INTENT_PLAN_TIER:-legacy}
|
||
INTENT_PLAN_PROJECT_ALLOWLIST: ${INTENT_PLAN_PROJECT_ALLOWLIST:-}
|
||
MULTI_INTENT_U9_SEGMENT: ${MULTI_INTENT_U9_SEGMENT:-false}
|
||
MULTI_INTENT_U10_MUTATE: ${MULTI_INTENT_U10_MUTATE:-false}
|
||
MULTI_INTENT_U11_DOCGOV: ${MULTI_INTENT_U11_DOCGOV:-false}
|
||
MULTI_INTENT_U12_RUN_CONTROL: ${MULTI_INTENT_U12_RUN_CONTROL:-false}
|
||
WORKFLOW_SCOPE_MODE: ${WORKFLOW_SCOPE_MODE:-strict}
|
||
SEMANTIC_SUMMARY_SHADOW: ${SEMANTIC_SUMMARY_SHADOW:-false}
|
||
SEMANTIC_SUMMARY_REPLACE: ${SEMANTIC_SUMMARY_REPLACE:-false}
|
||
SEMANTIC_SUMMARY_REPLACE_SESSIONS: ${SEMANTIC_SUMMARY_REPLACE_SESSIONS:-}
|
||
PI_CHANGE_REPORT_NARRATIVE: ${PI_CHANGE_REPORT_NARRATIVE:-false}
|
||
FAV_PUBLISHER_ENABLED: "false"
|
||
ports:
|
||
- "${APP_PUBLISH_HOST:-0.0.0.0}:${HTTP_PORT:-8000}:${HTTP_PORT:-8000}"
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:${HTTP_PORT:-8000}/api/v1/ready"]
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 6
|
||
start_period: 20s
|
||
volumes:
|
||
# 独占生产对话记录与环境数据
|
||
- ./data/main:/app/data
|
||
- ./data/vault/main:/app/vault
|
||
- main-aux-sqlite-data:/var/lib/feishu
|
||
- ./.regulations:/app/.regulations:ro
|
||
restart: always
|
||
networks:
|
||
- main-net
|
||
- shared-net
|
||
|
||
events:
|
||
# T20-I1: 资源上限(防 OOM 连坐;events 限额独立于 runner)
|
||
mem_limit: 1g
|
||
mem_reservation: 512m
|
||
cpus: 1.0
|
||
image: ${EVENTS_IMAGE:-shuimu-agent-events:main}
|
||
build:
|
||
context: .
|
||
dockerfile: deploy/app/Dockerfile
|
||
args:
|
||
GOPROXY: ${GO_PROXY:-https://proxy.golang.org,direct}
|
||
container_name: shuimu-agent-events-main
|
||
entrypoint: ["/app/events"]
|
||
command: ["-env", "/dev/null"]
|
||
depends_on:
|
||
system-db:
|
||
condition: service_healthy
|
||
environment:
|
||
ENV: main
|
||
HTTP_HOST: "0.0.0.0"
|
||
HTTP_PORT: "${EVENTS_HTTP_PORT:-8090}"
|
||
EVENTS_HTTP_PORT: "${EVENTS_HTTP_PORT:-8090}"
|
||
DATA_DIR: /app/data
|
||
ALLOW_IN_MEMORY: "false"
|
||
# validateProductionSecrets(ENV=main) 需要口令;events 本身只连系统库,KB DSN 仅满足启动校验
|
||
APP_DB_DSN: postgres://${SYSTEM_DB_USER:-app}:${SYSTEM_DB_PASSWORD:?SYSTEM_DB_PASSWORD is required for main/production}@system-db:5432/${SYSTEM_DB_NAME:-agent_system_main}?sslmode=disable
|
||
POSTGRES_SHARED_KB_DSN: postgres://${KB_DB_USER:-regkb}:${KB_DB_PASSWORD:?KB_DB_PASSWORD is required for main/production}@shuimu-kb-shared:5432/${KB_DB_NAME:-regulations}?sslmode=disable
|
||
ADMIN_PASSWORD: ${ADMIN_PASSWORD:?ADMIN_PASSWORD is required for main/production}
|
||
ports:
|
||
- "127.0.0.1:${EVENTS_HTTP_PORT:-8090}:${EVENTS_HTTP_PORT:-8090}"
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:${EVENTS_HTTP_PORT:-8090}/health"]
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 6
|
||
start_period: 15s
|
||
restart: always
|
||
networks:
|
||
- main-net
|
||
|
||
networks:
|
||
main-net:
|
||
name: chat-agent-main-net
|
||
driver: bridge
|
||
shared-net:
|
||
name: chat-agent-shared-net
|
||
external: true
|
||
|
||
volumes:
|
||
main-system-pgdata:
|
||
name: agent-main-system-pgdata
|
||
main-aux-sqlite-data:
|
||
name: agent-main-aux-sqlite-data
|