## LLM 공급자 어댑터 (B)
- sister-agent/src/llm/ 에 LlmAdapter 인터페이스 신설. 어댑터 5종:
openclaw (기존), openai, anthropic, ollama, mock
- 선택은 LLM_PROVIDER 환경변수로. 기본값 mock.
- 모델명은 LLM_MODEL_{MANAGER,PRINCIPAL,LEAD,JUNIOR} 로 외부화.
OpenClaw 내부 네이밍이 기본값이지만 env 로 얼마든지 갈아끼움.
- openai 어댑터는 OPENAI_BASE_URL 로 OpenRouter / Azure / 로컬 llama.cpp
서버까지 커버.
## In-process 단일 프로세스 모드 (C)
- sister-agent/src/core.ts 로 executeInvocation 을 library-export
- rails 에 InProcessTransport 추가. 동적 import 로 sister-agent core 를
로드해 같은 Node 프로세스에서 함수 호출로 실행.
- DirectRailsClient 로 HTTP 루프백 없이 DB 에 직접 쓰기 — 단일
프로세스에서도 observability 동일.
- RailsConfig 에 transport: "in-process" 추가.
- buildTransports 가 RAILS_TRANSPORT 와 per-stage override 를 지원하도록
확장. 레거시 RAILS_TRANSPORT_MODE + RAILS_AGENT_*_HOST 도 그대로 호환.
## Git push 외부화 + allowlist env 화
- spawn.ts 의 ENABLE_GIT_PUSH 를 "GITEA_TOKEN 있으면 auto on" 으로 변경.
기존 Dev 토폴로지는 sister LXC 들에 이미 토큰이 있어서 행동 변화 없음.
- rails.service.ts 의 파일 프록시 allowlist 를 GIT_RAW_ALLOWED_HOSTS
env 로 외부화. 기본값은 기존 Gitea 호스트 유지.
## Docker / 배포
- Dockerfile 추가. 단일 이미지로 rails + sister-agent 둘 다 빌드.
- docker-compose.yml (기본): mariadb + rails 한 컨테이너 = in-process.
docker compose up 한 줄로 로컬 E2E 가능.
- docker-compose.full.yml: rails + 4 개 독립 sister 컨테이너 = 분산.
## 설정 샘플 + 문서
- .env.example 완전 재작성: 필수/LLM/토폴로지/Gitea/Discord 5 섹션
- rails.config.local.yaml: in-process 샘플
- rails.config.distributed.yaml: http 분산 샘플
- docs/LOCAL-SETUP.md: 30분 퀵스타트 (Docker + 네이티브 두 경로)
- README 에 "5분 퀵스타트" + 토폴로지 표 + LLM 공급자 목록 추가
## 테스트
- tests/transport-build.test.ts (6 테스트): 기본값 / in-process /
per-stage override / http 엔드포인트 누락 / env 기반 wiring / 레거시
env 호환
- 전체 테스트 105 → 111 통과
142 lines
4.0 KiB
YAML
142 lines
4.0 KiB
YAML
# ────────────────────────────────────────────────────────────────
|
|
# docker-compose.full.yml — production-style distributed topology
|
|
#
|
|
# Brings up:
|
|
# - mariadb
|
|
# - rails (orchestrator only)
|
|
# - sister-harang (plan)
|
|
# - sister-narang (implement)
|
|
# - sister-darang (review)
|
|
# - sister-erang (deploy)
|
|
#
|
|
# All 6 services share the same image but each sister container runs the
|
|
# sister-agent HTTP daemon instead of the rails orchestrator, and rails
|
|
# is configured to talk to them over HTTP.
|
|
#
|
|
# Usage:
|
|
# cp .env.example .env
|
|
# docker compose -f docker-compose.full.yml up --build
|
|
# ────────────────────────────────────────────────────────────────
|
|
|
|
x-sister-env: &sister-env
|
|
NODE_ENV: production
|
|
RAILS_API_URL: http://rails:18800
|
|
SISTER_WORKSPACE_DIR: /app/rails-projects
|
|
LLM_PROVIDER: ${LLM_PROVIDER:-mock}
|
|
LLM_MODEL_MANAGER: ${LLM_MODEL_MANAGER:-}
|
|
LLM_MODEL_PRINCIPAL: ${LLM_MODEL_PRINCIPAL:-}
|
|
LLM_MODEL_LEAD: ${LLM_MODEL_LEAD:-}
|
|
LLM_MODEL_JUNIOR: ${LLM_MODEL_JUNIOR:-}
|
|
LLM_MODEL_FALLBACK: ${LLM_MODEL_FALLBACK:-}
|
|
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
|
|
OPENAI_BASE_URL: ${OPENAI_BASE_URL:-}
|
|
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
|
|
ANTHROPIC_BASE_URL: ${ANTHROPIC_BASE_URL:-}
|
|
OLLAMA_BASE_URL: ${OLLAMA_BASE_URL:-}
|
|
GITEA_BASE_URL: ${GITEA_BASE_URL:-}
|
|
GITEA_ORG: ${GITEA_ORG:-}
|
|
GITEA_TOKEN: ${GITEA_TOKEN:-}
|
|
|
|
x-sister-service: &sister-service
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
restart: unless-stopped
|
|
depends_on:
|
|
mariadb:
|
|
condition: service_healthy
|
|
command:
|
|
["node", "sister-agent/dist/server.js"]
|
|
networks:
|
|
- rails-net
|
|
|
|
services:
|
|
mariadb:
|
|
image: mariadb:10.11
|
|
restart: unless-stopped
|
|
environment:
|
|
MARIADB_ROOT_PASSWORD: rootpw
|
|
MARIADB_DATABASE: hanarang_rails
|
|
MARIADB_USER: rails
|
|
MARIADB_PASSWORD: rails
|
|
healthcheck:
|
|
test:
|
|
- "CMD"
|
|
- "healthcheck.sh"
|
|
- "--connect"
|
|
- "--innodb_initialized"
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 20
|
|
volumes:
|
|
- rails-db:/var/lib/mysql
|
|
networks:
|
|
- rails-net
|
|
|
|
rails:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
restart: unless-stopped
|
|
depends_on:
|
|
mariadb:
|
|
condition: service_healthy
|
|
sister-harang: { condition: service_started }
|
|
sister-narang: { condition: service_started }
|
|
sister-darang: { condition: service_started }
|
|
sister-erang: { condition: service_started }
|
|
environment:
|
|
DATABASE_URL: mysql://rails:rails@mariadb:3306/hanarang_rails
|
|
RAILS_PORT: "18800"
|
|
RAILS_LOG_LEVEL: info
|
|
NODE_ENV: production
|
|
RAILS_TRANSPORT: http
|
|
RAILS_API_URL: http://rails:18800
|
|
SISTER_ENDPOINT_PLAN: http://sister-harang:18801
|
|
SISTER_ENDPOINT_IMPLEMENT: http://sister-narang:18801
|
|
SISTER_ENDPOINT_REVIEW: http://sister-darang:18801
|
|
SISTER_ENDPOINT_DEPLOY: http://sister-erang:18801
|
|
SISTER_NAME_PLAN: harang
|
|
SISTER_NAME_IMPLEMENT: narang
|
|
SISTER_NAME_REVIEW: darang
|
|
SISTER_NAME_DEPLOY: erang
|
|
ports:
|
|
- "18800:18800"
|
|
networks:
|
|
- rails-net
|
|
|
|
sister-harang:
|
|
<<: *sister-service
|
|
environment:
|
|
<<: *sister-env
|
|
SISTER_AGENT_NAME: harang
|
|
SISTER_AGENT_PORT: "18801"
|
|
|
|
sister-narang:
|
|
<<: *sister-service
|
|
environment:
|
|
<<: *sister-env
|
|
SISTER_AGENT_NAME: narang
|
|
SISTER_AGENT_PORT: "18801"
|
|
|
|
sister-darang:
|
|
<<: *sister-service
|
|
environment:
|
|
<<: *sister-env
|
|
SISTER_AGENT_NAME: darang
|
|
SISTER_AGENT_PORT: "18801"
|
|
|
|
sister-erang:
|
|
<<: *sister-service
|
|
environment:
|
|
<<: *sister-env
|
|
SISTER_AGENT_NAME: erang
|
|
SISTER_AGENT_PORT: "18801"
|
|
|
|
volumes:
|
|
rails-db:
|
|
|
|
networks:
|
|
rails-net:
|
|
driver: bridge
|