mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-04-25 11:18:22 +00:00
feat: unified serve.sh with gateway mode support (#1847)
This commit is contained in:
parent
117fa9b05d
commit
ca2fb95ee6
82
Makefile
82
Makefile
@ -1,6 +1,6 @@
|
|||||||
# DeerFlow - Unified Development Environment
|
# DeerFlow - Unified Development Environment
|
||||||
|
|
||||||
.PHONY: help config config-upgrade check install dev dev-daemon start stop up down clean docker-init docker-start docker-stop docker-logs docker-logs-frontend docker-logs-gateway
|
.PHONY: help config config-upgrade check install dev dev-pro dev-daemon dev-daemon-pro start start-pro start-daemon start-daemon-pro stop up up-pro down clean docker-init docker-start docker-start-pro docker-stop docker-logs docker-logs-frontend docker-logs-gateway
|
||||||
|
|
||||||
BASH ?= bash
|
BASH ?= bash
|
||||||
|
|
||||||
@ -20,18 +20,25 @@ help:
|
|||||||
@echo " make install - Install all dependencies (frontend + backend)"
|
@echo " make install - Install all dependencies (frontend + backend)"
|
||||||
@echo " make setup-sandbox - Pre-pull sandbox container image (recommended)"
|
@echo " make setup-sandbox - Pre-pull sandbox container image (recommended)"
|
||||||
@echo " make dev - Start all services in development mode (with hot-reloading)"
|
@echo " make dev - Start all services in development mode (with hot-reloading)"
|
||||||
@echo " make dev-daemon - Start all services in background (daemon mode)"
|
@echo " make dev-pro - Start in dev + Gateway mode (experimental, no LangGraph server)"
|
||||||
|
@echo " make dev-daemon - Start dev services in background (daemon mode)"
|
||||||
|
@echo " make dev-daemon-pro - Start dev daemon + Gateway mode (experimental)"
|
||||||
@echo " make start - Start all services in production mode (optimized, no hot-reloading)"
|
@echo " make start - Start all services in production mode (optimized, no hot-reloading)"
|
||||||
|
@echo " make start-pro - Start in prod + Gateway mode (experimental)"
|
||||||
|
@echo " make start-daemon - Start prod services in background (daemon mode)"
|
||||||
|
@echo " make start-daemon-pro - Start prod daemon + Gateway mode (experimental)"
|
||||||
@echo " make stop - Stop all running services"
|
@echo " make stop - Stop all running services"
|
||||||
@echo " make clean - Clean up processes and temporary files"
|
@echo " make clean - Clean up processes and temporary files"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Docker Production Commands:"
|
@echo "Docker Production Commands:"
|
||||||
@echo " make up - Build and start production Docker services (localhost:2026)"
|
@echo " make up - Build and start production Docker services (localhost:2026)"
|
||||||
|
@echo " make up-pro - Build and start production Docker in Gateway mode (experimental)"
|
||||||
@echo " make down - Stop and remove production Docker containers"
|
@echo " make down - Stop and remove production Docker containers"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Docker Development Commands:"
|
@echo "Docker Development Commands:"
|
||||||
@echo " make docker-init - Pull the sandbox image"
|
@echo " make docker-init - Pull the sandbox image"
|
||||||
@echo " make docker-start - Start Docker services (mode-aware from config.yaml, localhost:2026)"
|
@echo " make docker-start - Start Docker services (mode-aware from config.yaml, localhost:2026)"
|
||||||
|
@echo " make docker-start-pro - Start Docker in Gateway mode (experimental, no LangGraph container)"
|
||||||
@echo " make docker-stop - Stop Docker development services"
|
@echo " make docker-stop - Stop Docker development services"
|
||||||
@echo " make docker-logs - View Docker development logs"
|
@echo " make docker-logs - View Docker development logs"
|
||||||
@echo " make docker-logs-frontend - View Docker frontend logs"
|
@echo " make docker-logs-frontend - View Docker frontend logs"
|
||||||
@ -105,6 +112,15 @@ else
|
|||||||
@./scripts/serve.sh --dev
|
@./scripts/serve.sh --dev
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Start all services in dev + Gateway mode (experimental: agent runtime embedded in Gateway)
|
||||||
|
dev-pro:
|
||||||
|
@$(PYTHON) ./scripts/check.py
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
@call scripts\run-with-git-bash.cmd ./scripts/serve.sh --dev --gateway
|
||||||
|
else
|
||||||
|
@./scripts/serve.sh --dev --gateway
|
||||||
|
endif
|
||||||
|
|
||||||
# Start all services in production mode (with optimizations)
|
# Start all services in production mode (with optimizations)
|
||||||
start:
|
start:
|
||||||
@$(PYTHON) ./scripts/check.py
|
@$(PYTHON) ./scripts/check.py
|
||||||
@ -114,30 +130,54 @@ else
|
|||||||
@./scripts/serve.sh --prod
|
@./scripts/serve.sh --prod
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Start all services in prod + Gateway mode (experimental)
|
||||||
|
start-pro:
|
||||||
|
@$(PYTHON) ./scripts/check.py
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
@call scripts\run-with-git-bash.cmd ./scripts/serve.sh --prod --gateway
|
||||||
|
else
|
||||||
|
@./scripts/serve.sh --prod --gateway
|
||||||
|
endif
|
||||||
|
|
||||||
# Start all services in daemon mode (background)
|
# Start all services in daemon mode (background)
|
||||||
dev-daemon:
|
dev-daemon:
|
||||||
@$(PYTHON) ./scripts/check.py
|
@$(PYTHON) ./scripts/check.py
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
@call scripts\run-with-git-bash.cmd ./scripts/start-daemon.sh
|
@call scripts\run-with-git-bash.cmd ./scripts/serve.sh --dev --daemon
|
||||||
else
|
else
|
||||||
@./scripts/start-daemon.sh
|
@./scripts/serve.sh --dev --daemon
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Start daemon + Gateway mode (experimental)
|
||||||
|
dev-daemon-pro:
|
||||||
|
@$(PYTHON) ./scripts/check.py
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
@call scripts\run-with-git-bash.cmd ./scripts/serve.sh --dev --gateway --daemon
|
||||||
|
else
|
||||||
|
@./scripts/serve.sh --dev --gateway --daemon
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Start prod services in daemon mode (background)
|
||||||
|
start-daemon:
|
||||||
|
@$(PYTHON) ./scripts/check.py
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
@call scripts\run-with-git-bash.cmd ./scripts/serve.sh --prod --daemon
|
||||||
|
else
|
||||||
|
@./scripts/serve.sh --prod --daemon
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Start prod daemon + Gateway mode (experimental)
|
||||||
|
start-daemon-pro:
|
||||||
|
@$(PYTHON) ./scripts/check.py
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
@call scripts\run-with-git-bash.cmd ./scripts/serve.sh --prod --gateway --daemon
|
||||||
|
else
|
||||||
|
@./scripts/serve.sh --prod --gateway --daemon
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Stop all services
|
# Stop all services
|
||||||
stop:
|
stop:
|
||||||
@echo "Stopping all services..."
|
@./scripts/serve.sh --stop
|
||||||
@-pkill -f "langgraph dev" 2>/dev/null || true
|
|
||||||
@-pkill -f "uvicorn app.gateway.app:app" 2>/dev/null || true
|
|
||||||
@-pkill -f "next dev" 2>/dev/null || true
|
|
||||||
@-pkill -f "next start" 2>/dev/null || true
|
|
||||||
@-pkill -f "next-server" 2>/dev/null || true
|
|
||||||
@-pkill -f "next-server" 2>/dev/null || true
|
|
||||||
@-nginx -c $(PWD)/docker/nginx/nginx.local.conf -p $(PWD) -s quit 2>/dev/null || true
|
|
||||||
@sleep 1
|
|
||||||
@-pkill -9 nginx 2>/dev/null || true
|
|
||||||
@echo "Cleaning up sandbox containers..."
|
|
||||||
@-./scripts/cleanup-containers.sh deer-flow-sandbox 2>/dev/null || true
|
|
||||||
@echo "✓ All services stopped"
|
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
clean: stop
|
clean: stop
|
||||||
@ -159,6 +199,10 @@ docker-init:
|
|||||||
docker-start:
|
docker-start:
|
||||||
@./scripts/docker.sh start
|
@./scripts/docker.sh start
|
||||||
|
|
||||||
|
# Start Docker in Gateway mode (experimental)
|
||||||
|
docker-start-pro:
|
||||||
|
@./scripts/docker.sh start --gateway
|
||||||
|
|
||||||
# Stop Docker development environment
|
# Stop Docker development environment
|
||||||
docker-stop:
|
docker-stop:
|
||||||
@./scripts/docker.sh stop
|
@./scripts/docker.sh stop
|
||||||
@ -181,6 +225,10 @@ docker-logs-gateway:
|
|||||||
up:
|
up:
|
||||||
@./scripts/deploy.sh
|
@./scripts/deploy.sh
|
||||||
|
|
||||||
|
# Build and start production services in Gateway mode
|
||||||
|
up-pro:
|
||||||
|
@./scripts/deploy.sh --gateway
|
||||||
|
|
||||||
# Stop and remove production containers
|
# Stop and remove production containers
|
||||||
down:
|
down:
|
||||||
@./scripts/deploy.sh down
|
@./scripts/deploy.sh down
|
||||||
|
|||||||
54
README.md
54
README.md
@ -280,6 +280,60 @@ On Windows, run the local development flow from Git Bash. Native `cmd.exe` and P
|
|||||||
|
|
||||||
6. **Access**: http://localhost:2026
|
6. **Access**: http://localhost:2026
|
||||||
|
|
||||||
|
#### Startup Modes
|
||||||
|
|
||||||
|
DeerFlow supports multiple startup modes across two dimensions:
|
||||||
|
|
||||||
|
- **Dev / Prod** — dev enables hot-reload; prod uses pre-built frontend
|
||||||
|
- **Standard / Gateway** — standard uses a separate LangGraph server (4 processes); Gateway mode (experimental) embeds the agent runtime in the Gateway API (3 processes)
|
||||||
|
|
||||||
|
| | **Local Foreground** | **Local Daemon** | **Docker Dev** | **Docker Prod** |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| **Dev** | `./scripts/serve.sh --dev`<br/>`make dev` | `./scripts/serve.sh --dev --daemon`<br/>`make dev-daemon` | `./scripts/docker.sh start`<br/>`make docker-start` | — |
|
||||||
|
| **Dev + Gateway** | `./scripts/serve.sh --dev --gateway`<br/>`make dev-pro` | `./scripts/serve.sh --dev --gateway --daemon`<br/>`make dev-daemon-pro` | `./scripts/docker.sh start --gateway`<br/>`make docker-start-pro` | — |
|
||||||
|
| **Prod** | `./scripts/serve.sh --prod`<br/>`make start` | `./scripts/serve.sh --prod --daemon`<br/>`make start-daemon` | — | `./scripts/deploy.sh`<br/>`make up` |
|
||||||
|
| **Prod + Gateway** | `./scripts/serve.sh --prod --gateway`<br/>`make start-pro` | `./scripts/serve.sh --prod --gateway --daemon`<br/>`make start-daemon-pro` | — | `./scripts/deploy.sh --gateway`<br/>`make up-pro` |
|
||||||
|
|
||||||
|
| Action | Local | Docker Dev | Docker Prod |
|
||||||
|
|---|---|---|---|
|
||||||
|
| **Stop** | `./scripts/serve.sh --stop`<br/>`make stop` | `./scripts/docker.sh stop`<br/>`make docker-stop` | `./scripts/deploy.sh down`<br/>`make down` |
|
||||||
|
| **Restart** | `./scripts/serve.sh --restart [flags]` | `./scripts/docker.sh restart` | — |
|
||||||
|
|
||||||
|
> **Gateway mode** eliminates the LangGraph server process — the Gateway API handles agent execution directly via async tasks, managing its own concurrency.
|
||||||
|
|
||||||
|
#### Why Gateway Mode?
|
||||||
|
|
||||||
|
In standard mode, DeerFlow runs a dedicated [LangGraph Platform](https://langchain-ai.github.io/langgraph/) server alongside the Gateway API. This architecture works well but has trade-offs:
|
||||||
|
|
||||||
|
| | Standard Mode | Gateway Mode |
|
||||||
|
|---|---|---|
|
||||||
|
| **Architecture** | Gateway (REST API) + LangGraph (agent runtime) | Gateway embeds agent runtime |
|
||||||
|
| **Concurrency** | `--n-jobs-per-worker` per worker (requires license) | `--workers` × async tasks (no per-worker cap) |
|
||||||
|
| **Containers / Processes** | 4 (frontend, gateway, langgraph, nginx) | 3 (frontend, gateway, nginx) |
|
||||||
|
| **Resource usage** | Higher (two Python runtimes) | Lower (single Python runtime) |
|
||||||
|
| **LangGraph Platform license** | Required for production images | Not required |
|
||||||
|
| **Cold start** | Slower (two services to initialize) | Faster |
|
||||||
|
|
||||||
|
Both modes are functionally equivalent — the same agents, tools, and skills work in either mode.
|
||||||
|
|
||||||
|
#### Docker Production Deployment
|
||||||
|
|
||||||
|
`deploy.sh` supports building and starting separately. Images are mode-agnostic — runtime mode is selected at start time:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# One-step (build + start)
|
||||||
|
deploy.sh # standard mode (default)
|
||||||
|
deploy.sh --gateway # gateway mode
|
||||||
|
|
||||||
|
# Two-step (build once, start with any mode)
|
||||||
|
deploy.sh build # build all images
|
||||||
|
deploy.sh start # start in standard mode
|
||||||
|
deploy.sh start --gateway # start in gateway mode
|
||||||
|
|
||||||
|
# Stop
|
||||||
|
deploy.sh down
|
||||||
|
```
|
||||||
|
|
||||||
### Advanced
|
### Advanced
|
||||||
#### Sandbox Mode
|
#### Sandbox Mode
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,10 @@ DeerFlow is a LangGraph-based AI super agent system with a full-stack architectu
|
|||||||
- **Nginx** (port 2026): Unified reverse proxy entry point
|
- **Nginx** (port 2026): Unified reverse proxy entry point
|
||||||
- **Provisioner** (port 8002, optional in Docker dev): Started only when sandbox is configured for provisioner/Kubernetes mode
|
- **Provisioner** (port 8002, optional in Docker dev): Started only when sandbox is configured for provisioner/Kubernetes mode
|
||||||
|
|
||||||
|
**Runtime Modes**:
|
||||||
|
- **Standard mode** (`make dev`): LangGraph Server handles agent execution as a separate process. 4 processes total.
|
||||||
|
- **Gateway mode** (`make dev-pro`, experimental): Agent runtime embedded in Gateway via `RunManager` + `run_agent()` + `StreamBridge` (`packages/harness/deerflow/runtime/`). Service manages its own concurrency via async tasks. 3 processes total, no LangGraph Server.
|
||||||
|
|
||||||
**Project Structure**:
|
**Project Structure**:
|
||||||
```
|
```
|
||||||
deer-flow/
|
deer-flow/
|
||||||
@ -80,6 +84,8 @@ When making code changes, you MUST update the relevant documentation:
|
|||||||
make check # Check system requirements
|
make check # Check system requirements
|
||||||
make install # Install all dependencies (frontend + backend)
|
make install # Install all dependencies (frontend + backend)
|
||||||
make dev # Start all services (LangGraph + Gateway + Frontend + Nginx), with config.yaml preflight
|
make dev # Start all services (LangGraph + Gateway + Frontend + Nginx), with config.yaml preflight
|
||||||
|
make dev-pro # Gateway mode (experimental): skip LangGraph, agent runtime embedded in Gateway
|
||||||
|
make start-pro # Production + Gateway mode (experimental)
|
||||||
make stop # Stop all services
|
make stop # Stop all services
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -436,8 +442,25 @@ make dev
|
|||||||
|
|
||||||
This starts all services and makes the application available at `http://localhost:2026`.
|
This starts all services and makes the application available at `http://localhost:2026`.
|
||||||
|
|
||||||
|
**All startup modes:**
|
||||||
|
|
||||||
|
| | **Local Foreground** | **Local Daemon** | **Docker Dev** | **Docker Prod** |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| **Dev** | `./scripts/serve.sh --dev`<br/>`make dev` | `./scripts/serve.sh --dev --daemon`<br/>`make dev-daemon` | `./scripts/docker.sh start`<br/>`make docker-start` | — |
|
||||||
|
| **Dev + Gateway** | `./scripts/serve.sh --dev --gateway`<br/>`make dev-pro` | `./scripts/serve.sh --dev --gateway --daemon`<br/>`make dev-daemon-pro` | `./scripts/docker.sh start --gateway`<br/>`make docker-start-pro` | — |
|
||||||
|
| **Prod** | `./scripts/serve.sh --prod`<br/>`make start` | `./scripts/serve.sh --prod --daemon`<br/>`make start-daemon` | — | `./scripts/deploy.sh`<br/>`make up` |
|
||||||
|
| **Prod + Gateway** | `./scripts/serve.sh --prod --gateway`<br/>`make start-pro` | `./scripts/serve.sh --prod --gateway --daemon`<br/>`make start-daemon-pro` | — | `./scripts/deploy.sh --gateway`<br/>`make up-pro` |
|
||||||
|
|
||||||
|
| Action | Local | Docker Dev | Docker Prod |
|
||||||
|
|---|---|---|---|
|
||||||
|
| **Stop** | `./scripts/serve.sh --stop`<br/>`make stop` | `./scripts/docker.sh stop`<br/>`make docker-stop` | `./scripts/deploy.sh down`<br/>`make down` |
|
||||||
|
| **Restart** | `./scripts/serve.sh --restart [flags]` | `./scripts/docker.sh restart` | — |
|
||||||
|
|
||||||
|
Gateway mode embeds the agent runtime in Gateway, no LangGraph server.
|
||||||
|
|
||||||
**Nginx routing**:
|
**Nginx routing**:
|
||||||
- `/api/langgraph/*` → LangGraph Server (2024)
|
- Standard mode: `/api/langgraph/*` → LangGraph Server (2024)
|
||||||
|
- Gateway mode: `/api/langgraph/*` → Gateway embedded runtime (8001) (via envsubst)
|
||||||
- `/api/*` (other) → Gateway API (8001)
|
- `/api/*` (other) → Gateway API (8001)
|
||||||
- `/` (non-API) → Frontend (3000)
|
- `/` (non-API) → Frontend (3000)
|
||||||
|
|
||||||
|
|||||||
@ -19,8 +19,6 @@ services:
|
|||||||
# cluster via the K8s API.
|
# cluster via the K8s API.
|
||||||
# Backend accesses sandboxes directly via host.docker.internal:{NodePort}.
|
# Backend accesses sandboxes directly via host.docker.internal:{NodePort}.
|
||||||
provisioner:
|
provisioner:
|
||||||
profiles:
|
|
||||||
- provisioner
|
|
||||||
build:
|
build:
|
||||||
context: ./provisioner
|
context: ./provisioner
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
@ -59,20 +57,25 @@ services:
|
|||||||
|
|
||||||
# ── Reverse Proxy ──────────────────────────────────────────────────────
|
# ── Reverse Proxy ──────────────────────────────────────────────────────
|
||||||
# Routes API traffic to gateway/langgraph and (optionally) provisioner.
|
# Routes API traffic to gateway/langgraph and (optionally) provisioner.
|
||||||
# Select nginx config via NGINX_CONF:
|
# LANGGRAPH_UPSTREAM and LANGGRAPH_REWRITE control gateway vs standard
|
||||||
# - nginx.local.conf (default): no provisioner route (local/aio modes)
|
# routing (processed by envsubst at container start).
|
||||||
# - nginx.conf: includes provisioner route (provisioner mode)
|
|
||||||
nginx:
|
nginx:
|
||||||
image: nginx:alpine
|
image: nginx:alpine
|
||||||
container_name: deer-flow-nginx
|
container_name: deer-flow-nginx
|
||||||
ports:
|
ports:
|
||||||
- "2026:2026"
|
- "2026:2026"
|
||||||
volumes:
|
volumes:
|
||||||
- ./nginx/${NGINX_CONF:-nginx.conf}:/etc/nginx/nginx.conf:ro
|
- ./nginx/nginx.conf:/etc/nginx/nginx.conf.template:ro
|
||||||
|
environment:
|
||||||
|
- LANGGRAPH_UPSTREAM=${LANGGRAPH_UPSTREAM:-langgraph:2024}
|
||||||
|
- LANGGRAPH_REWRITE=${LANGGRAPH_REWRITE:-/}
|
||||||
|
command: >
|
||||||
|
sh -c "envsubst '$$LANGGRAPH_UPSTREAM $$LANGGRAPH_REWRITE'
|
||||||
|
< /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
|
||||||
|
&& nginx -g 'daemon off;'"
|
||||||
depends_on:
|
depends_on:
|
||||||
- frontend
|
- frontend
|
||||||
- gateway
|
- gateway
|
||||||
- langgraph
|
|
||||||
networks:
|
networks:
|
||||||
- deer-flow-dev
|
- deer-flow-dev
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
@ -29,11 +29,17 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "${PORT:-2026}:2026"
|
- "${PORT:-2026}:2026"
|
||||||
volumes:
|
volumes:
|
||||||
- ./nginx/${NGINX_CONF:-nginx.conf}:/etc/nginx/nginx.conf:ro
|
- ./nginx/nginx.conf:/etc/nginx/nginx.conf.template:ro
|
||||||
|
environment:
|
||||||
|
- LANGGRAPH_UPSTREAM=${LANGGRAPH_UPSTREAM:-langgraph:2024}
|
||||||
|
- LANGGRAPH_REWRITE=${LANGGRAPH_REWRITE:-/}
|
||||||
|
command: >
|
||||||
|
sh -c "envsubst '$$LANGGRAPH_UPSTREAM $$LANGGRAPH_REWRITE'
|
||||||
|
< /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
|
||||||
|
&& nginx -g 'daemon off;'"
|
||||||
depends_on:
|
depends_on:
|
||||||
- frontend
|
- frontend
|
||||||
- gateway
|
- gateway
|
||||||
- langgraph
|
|
||||||
networks:
|
networks:
|
||||||
- deer-flow
|
- deer-flow
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -68,7 +74,7 @@ services:
|
|||||||
UV_IMAGE: ${UV_IMAGE:-ghcr.io/astral-sh/uv:0.7.20}
|
UV_IMAGE: ${UV_IMAGE:-ghcr.io/astral-sh/uv:0.7.20}
|
||||||
UV_INDEX_URL: ${UV_INDEX_URL:-https://pypi.org/simple}
|
UV_INDEX_URL: ${UV_INDEX_URL:-https://pypi.org/simple}
|
||||||
container_name: deer-flow-gateway
|
container_name: deer-flow-gateway
|
||||||
command: sh -c "cd backend && PYTHONPATH=. uv run uvicorn app.gateway.app:app --host 0.0.0.0 --port 8001 --workers 2"
|
command: sh -c "cd backend && PYTHONPATH=. uv run uvicorn app.gateway.app:app --host 0.0.0.0 --port 8001 --workers ${GATEWAY_WORKERS:-4}"
|
||||||
volumes:
|
volumes:
|
||||||
- ${DEER_FLOW_CONFIG_PATH}:/app/backend/config.yaml:ro
|
- ${DEER_FLOW_CONFIG_PATH}:/app/backend/config.yaml:ro
|
||||||
- ${DEER_FLOW_EXTENSIONS_CONFIG_PATH}:/app/backend/extensions_config.json:ro
|
- ${DEER_FLOW_EXTENSIONS_CONFIG_PATH}:/app/backend/extensions_config.json:ro
|
||||||
@ -160,13 +166,12 @@ services:
|
|||||||
|
|
||||||
# ── Sandbox Provisioner (optional, Kubernetes mode) ────────────────────────
|
# ── Sandbox Provisioner (optional, Kubernetes mode) ────────────────────────
|
||||||
provisioner:
|
provisioner:
|
||||||
profiles:
|
|
||||||
- provisioner
|
|
||||||
build:
|
build:
|
||||||
context: ./provisioner
|
context: ./provisioner
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
args:
|
args:
|
||||||
APT_MIRROR: ${APT_MIRROR:-}
|
APT_MIRROR: ${APT_MIRROR:-}
|
||||||
|
PIP_INDEX_URL: ${PIP_INDEX_URL:-}
|
||||||
container_name: deer-flow-provisioner
|
container_name: deer-flow-provisioner
|
||||||
volumes:
|
volumes:
|
||||||
- ~/.kube/config:/root/.kube/config:ro
|
- ~/.kube/config:/root/.kube/config:ro
|
||||||
|
|||||||
@ -27,7 +27,7 @@ http {
|
|||||||
}
|
}
|
||||||
|
|
||||||
upstream langgraph {
|
upstream langgraph {
|
||||||
server langgraph:2024;
|
server ${LANGGRAPH_UPSTREAM};
|
||||||
}
|
}
|
||||||
|
|
||||||
upstream frontend {
|
upstream frontend {
|
||||||
@ -57,9 +57,11 @@ http {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# LangGraph API routes
|
# LangGraph API routes
|
||||||
# Rewrites /api/langgraph/* to /* before proxying
|
# In standard mode: /api/langgraph/* → langgraph:2024 (rewrite to /*)
|
||||||
|
# In gateway mode: /api/langgraph/* → gateway:8001 (rewrite to /api/*)
|
||||||
|
# Controlled by LANGGRAPH_UPSTREAM and LANGGRAPH_REWRITE env vars.
|
||||||
location /api/langgraph/ {
|
location /api/langgraph/ {
|
||||||
rewrite ^/api/langgraph/(.*) /$1 break;
|
rewrite ^/api/langgraph/(.*) ${LANGGRAPH_REWRITE}$1 break;
|
||||||
proxy_pass http://langgraph;
|
proxy_pass http://langgraph;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
|
|
||||||
@ -84,34 +86,6 @@ http {
|
|||||||
chunked_transfer_encoding on;
|
chunked_transfer_encoding on;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Experimental: Gateway-backed LangGraph-compatible API
|
|
||||||
# Frontend can opt-in via NEXT_PUBLIC_LANGGRAPH_BASE_URL=/api/langgraph-compat
|
|
||||||
location /api/langgraph-compat/ {
|
|
||||||
rewrite ^/api/langgraph-compat/(.*) /api/$1 break;
|
|
||||||
proxy_pass http://gateway;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
|
|
||||||
# Headers
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Connection '';
|
|
||||||
|
|
||||||
# SSE/Streaming support
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_cache off;
|
|
||||||
proxy_set_header X-Accel-Buffering no;
|
|
||||||
|
|
||||||
# Timeouts for long-running requests
|
|
||||||
proxy_connect_timeout 600s;
|
|
||||||
proxy_send_timeout 600s;
|
|
||||||
proxy_read_timeout 600s;
|
|
||||||
|
|
||||||
# Chunked transfer encoding
|
|
||||||
chunked_transfer_encoding on;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Custom API: Models endpoint
|
# Custom API: Models endpoint
|
||||||
location /api/models {
|
location /api/models {
|
||||||
proxy_pass http://gateway;
|
proxy_pass http://gateway;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
FROM python:3.12-slim-bookworm
|
FROM python:3.12-slim-bookworm
|
||||||
|
|
||||||
ARG APT_MIRROR
|
ARG APT_MIRROR
|
||||||
|
ARG PIP_INDEX_URL
|
||||||
|
|
||||||
# Optionally override apt mirror for restricted networks (e.g. APT_MIRROR=mirrors.aliyun.com)
|
# Optionally override apt mirror for restricted networks (e.g. APT_MIRROR=mirrors.aliyun.com)
|
||||||
RUN if [ -n "${APT_MIRROR}" ]; then \
|
RUN if [ -n "${APT_MIRROR}" ]; then \
|
||||||
@ -15,6 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
|
|
||||||
# Install Python dependencies
|
# Install Python dependencies
|
||||||
RUN pip install --no-cache-dir \
|
RUN pip install --no-cache-dir \
|
||||||
|
${PIP_INDEX_URL:+--index-url "$PIP_INDEX_URL"} \
|
||||||
fastapi \
|
fastapi \
|
||||||
"uvicorn[standard]" \
|
"uvicorn[standard]" \
|
||||||
kubernetes
|
kubernetes
|
||||||
|
|||||||
@ -1,16 +1,57 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# deploy.sh - Build and start (or stop) DeerFlow production services
|
# deploy.sh - Build, start, or stop DeerFlow production services
|
||||||
#
|
#
|
||||||
# Usage:
|
# Commands:
|
||||||
# deploy.sh [up] — build images and start containers (default)
|
# deploy.sh [--MODE] — build + start (default: --standard)
|
||||||
|
# deploy.sh build — build all images (mode-agnostic)
|
||||||
|
# deploy.sh start [--MODE] — start from pre-built images (default: --standard)
|
||||||
# deploy.sh down — stop and remove containers
|
# deploy.sh down — stop and remove containers
|
||||||
#
|
#
|
||||||
|
# Runtime modes:
|
||||||
|
# --standard (default) All services including LangGraph server.
|
||||||
|
# --gateway No LangGraph container; nginx routes /api/langgraph/*
|
||||||
|
# to the Gateway compat API instead.
|
||||||
|
#
|
||||||
|
# Sandbox mode (local / aio / provisioner) is auto-detected from config.yaml.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# deploy.sh # build + start in standard mode
|
||||||
|
# deploy.sh --gateway # build + start in gateway mode
|
||||||
|
# deploy.sh build # build all images
|
||||||
|
# deploy.sh start --gateway # start pre-built images in gateway mode
|
||||||
|
# deploy.sh down # stop and remove containers
|
||||||
|
#
|
||||||
# Must be run from the repo root directory.
|
# Must be run from the repo root directory.
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
CMD="${1:-up}"
|
RUNTIME_MODE="standard"
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
build|start|down)
|
||||||
|
CMD="$1"
|
||||||
|
if [ -n "${2:-}" ]; then
|
||||||
|
case "$2" in
|
||||||
|
--standard) RUNTIME_MODE="standard" ;;
|
||||||
|
--gateway) RUNTIME_MODE="gateway" ;;
|
||||||
|
*) echo "Unknown mode: $2"; echo "Usage: deploy.sh [build|start|down] [--standard|--gateway]"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--standard|--gateway)
|
||||||
|
CMD=""
|
||||||
|
RUNTIME_MODE="${1#--}"
|
||||||
|
;;
|
||||||
|
"")
|
||||||
|
CMD=""
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown argument: $1"
|
||||||
|
echo "Usage: deploy.sh [build|start|down] [--standard|--gateway]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
cd "$REPO_ROOT"
|
cd "$REPO_ROOT"
|
||||||
@ -150,6 +191,32 @@ if [ "$CMD" = "down" ]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ── build ────────────────────────────────────────────────────────────────────
|
||||||
|
# Build produces mode-agnostic images. No --gateway or sandbox detection needed.
|
||||||
|
|
||||||
|
if [ "$CMD" = "build" ]; then
|
||||||
|
echo "=========================================="
|
||||||
|
echo " DeerFlow — Building Images"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Docker socket is needed for compose to parse volume specs
|
||||||
|
if [ -z "$DEER_FLOW_DOCKER_SOCKET" ]; then
|
||||||
|
export DEER_FLOW_DOCKER_SOCKET="/var/run/docker.sock"
|
||||||
|
fi
|
||||||
|
|
||||||
|
"${COMPOSE_CMD[@]}" build
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo " ✓ Images built successfully"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo " Next: deploy.sh start [--gateway]"
|
||||||
|
echo ""
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
# ── Banner ────────────────────────────────────────────────────────────────────
|
# ── Banner ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
@ -157,19 +224,28 @@ echo " DeerFlow Production Deployment"
|
|||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# ── Step 1: Detect sandbox mode ──────────────────────────────────────────────
|
# ── Detect runtime configuration ────────────────────────────────────────────
|
||||||
|
# Only needed for start / up — determines which containers to launch.
|
||||||
|
|
||||||
sandbox_mode="$(detect_sandbox_mode)"
|
sandbox_mode="$(detect_sandbox_mode)"
|
||||||
echo -e "${BLUE}Sandbox mode: $sandbox_mode${NC}"
|
echo -e "${BLUE}Sandbox mode: $sandbox_mode${NC}"
|
||||||
|
|
||||||
if [ "$sandbox_mode" = "provisioner" ]; then
|
echo -e "${BLUE}Runtime mode: $RUNTIME_MODE${NC}"
|
||||||
services=""
|
|
||||||
extra_args="--profile provisioner"
|
|
||||||
else
|
|
||||||
services="frontend gateway langgraph nginx"
|
|
||||||
extra_args=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
case "$RUNTIME_MODE" in
|
||||||
|
gateway)
|
||||||
|
export LANGGRAPH_UPSTREAM=gateway:8001
|
||||||
|
export LANGGRAPH_REWRITE=/api/
|
||||||
|
services="frontend gateway nginx"
|
||||||
|
;;
|
||||||
|
standard)
|
||||||
|
services="frontend gateway langgraph nginx"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$sandbox_mode" = "provisioner" ]; then
|
||||||
|
services="$services provisioner"
|
||||||
|
fi
|
||||||
|
|
||||||
# ── DEER_FLOW_DOCKER_SOCKET ───────────────────────────────────────────────────
|
# ── DEER_FLOW_DOCKER_SOCKET ───────────────────────────────────────────────────
|
||||||
|
|
||||||
@ -189,22 +265,34 @@ fi
|
|||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# ── Step 2: Build and start ───────────────────────────────────────────────────
|
# ── Start / Up ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if [ "$CMD" = "start" ]; then
|
||||||
|
echo "Starting containers (no rebuild)..."
|
||||||
|
echo ""
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
"${COMPOSE_CMD[@]}" up -d --remove-orphans $services
|
||||||
|
else
|
||||||
|
# Default: build + start
|
||||||
echo "Building images and starting containers..."
|
echo "Building images and starting containers..."
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
"${COMPOSE_CMD[@]}" $extra_args up --build -d --remove-orphans $services
|
"${COMPOSE_CMD[@]}" up --build -d --remove-orphans $services
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo " DeerFlow is running!"
|
echo " DeerFlow is running! ($RUNTIME_MODE mode)"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo ""
|
echo ""
|
||||||
echo " 🌐 Application: http://localhost:${PORT:-2026}"
|
echo " 🌐 Application: http://localhost:${PORT:-2026}"
|
||||||
echo " 📡 API Gateway: http://localhost:${PORT:-2026}/api/*"
|
echo " 📡 API Gateway: http://localhost:${PORT:-2026}/api/*"
|
||||||
|
if [ "$RUNTIME_MODE" = "gateway" ]; then
|
||||||
|
echo " 🤖 Runtime: Gateway embedded"
|
||||||
|
echo " API: /api/langgraph/* → Gateway (compat)"
|
||||||
|
else
|
||||||
echo " 🤖 LangGraph: http://localhost:${PORT:-2026}/api/langgraph/*"
|
echo " 🤖 LangGraph: http://localhost:${PORT:-2026}/api/langgraph/*"
|
||||||
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
echo " Manage:"
|
echo " Manage:"
|
||||||
echo " make down — stop and remove containers"
|
echo " make down — stop and remove containers"
|
||||||
|
|||||||
@ -148,9 +148,18 @@ init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Start Docker development environment
|
# Start Docker development environment
|
||||||
|
# Usage: start [--gateway]
|
||||||
start() {
|
start() {
|
||||||
local sandbox_mode
|
local sandbox_mode
|
||||||
local services
|
local services
|
||||||
|
local gateway_mode=false
|
||||||
|
|
||||||
|
# Check for --gateway flag
|
||||||
|
for arg in "$@"; do
|
||||||
|
if [ "$arg" = "--gateway" ]; then
|
||||||
|
gateway_mode=true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo " Starting DeerFlow Docker Development"
|
echo " Starting DeerFlow Docker Development"
|
||||||
@ -159,12 +168,21 @@ start() {
|
|||||||
|
|
||||||
sandbox_mode="$(detect_sandbox_mode)"
|
sandbox_mode="$(detect_sandbox_mode)"
|
||||||
|
|
||||||
|
if $gateway_mode; then
|
||||||
|
services="frontend gateway nginx"
|
||||||
if [ "$sandbox_mode" = "provisioner" ]; then
|
if [ "$sandbox_mode" = "provisioner" ]; then
|
||||||
services="frontend gateway langgraph provisioner nginx"
|
services="frontend gateway provisioner nginx"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
services="frontend gateway langgraph nginx"
|
services="frontend gateway langgraph nginx"
|
||||||
|
if [ "$sandbox_mode" = "provisioner" ]; then
|
||||||
|
services="frontend gateway langgraph provisioner nginx"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if $gateway_mode; then
|
||||||
|
echo -e "${BLUE}Runtime: Gateway mode (experimental) — no LangGraph container${NC}"
|
||||||
|
fi
|
||||||
echo -e "${BLUE}Detected sandbox mode: $sandbox_mode${NC}"
|
echo -e "${BLUE}Detected sandbox mode: $sandbox_mode${NC}"
|
||||||
if [ "$sandbox_mode" = "provisioner" ]; then
|
if [ "$sandbox_mode" = "provisioner" ]; then
|
||||||
echo -e "${BLUE}Provisioner enabled (Kubernetes mode).${NC}"
|
echo -e "${BLUE}Provisioner enabled (Kubernetes mode).${NC}"
|
||||||
@ -213,6 +231,12 @@ start() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Set nginx routing for gateway mode (envsubst in nginx container)
|
||||||
|
if $gateway_mode; then
|
||||||
|
export LANGGRAPH_UPSTREAM=gateway:8001
|
||||||
|
export LANGGRAPH_REWRITE=/api/
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Building and starting containers..."
|
echo "Building and starting containers..."
|
||||||
cd "$DOCKER_DIR" && $COMPOSE_CMD up --build -d --remove-orphans $services
|
cd "$DOCKER_DIR" && $COMPOSE_CMD up --build -d --remove-orphans $services
|
||||||
echo ""
|
echo ""
|
||||||
@ -222,7 +246,12 @@ start() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo " 🌐 Application: http://localhost:2026"
|
echo " 🌐 Application: http://localhost:2026"
|
||||||
echo " 📡 API Gateway: http://localhost:2026/api/*"
|
echo " 📡 API Gateway: http://localhost:2026/api/*"
|
||||||
|
if $gateway_mode; then
|
||||||
|
echo " 🤖 Runtime: Gateway embedded"
|
||||||
|
echo " API: /api/langgraph/* → Gateway (compat)"
|
||||||
|
else
|
||||||
echo " 🤖 LangGraph: http://localhost:2026/api/langgraph/*"
|
echo " 🤖 LangGraph: http://localhost:2026/api/langgraph/*"
|
||||||
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
echo " 📋 View logs: make docker-logs"
|
echo " 📋 View logs: make docker-logs"
|
||||||
echo " 🛑 Stop: make docker-stop"
|
echo " 🛑 Stop: make docker-stop"
|
||||||
@ -302,6 +331,7 @@ help() {
|
|||||||
echo "Commands:"
|
echo "Commands:"
|
||||||
echo " init - Pull the sandbox image (speeds up first Pod startup)"
|
echo " init - Pull the sandbox image (speeds up first Pod startup)"
|
||||||
echo " start - Start Docker services (auto-detects sandbox mode from config.yaml)"
|
echo " start - Start Docker services (auto-detects sandbox mode from config.yaml)"
|
||||||
|
echo " start --gateway - Start without LangGraph container (Gateway mode, experimental)"
|
||||||
echo " restart - Restart all running Docker services"
|
echo " restart - Restart all running Docker services"
|
||||||
echo " logs [option] - View Docker development logs"
|
echo " logs [option] - View Docker development logs"
|
||||||
echo " --frontend View frontend logs only"
|
echo " --frontend View frontend logs only"
|
||||||
@ -320,7 +350,8 @@ main() {
|
|||||||
init
|
init
|
||||||
;;
|
;;
|
||||||
start)
|
start)
|
||||||
start
|
shift
|
||||||
|
start "$@"
|
||||||
;;
|
;;
|
||||||
restart)
|
restart)
|
||||||
restart
|
restart
|
||||||
|
|||||||
370
scripts/serve.sh
370
scripts/serve.sh
@ -1,15 +1,40 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# start.sh - Start all DeerFlow development services
|
# serve.sh — Unified DeerFlow service launcher
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./scripts/serve.sh [--dev|--prod] [--gateway] [--daemon] [--stop|--restart]
|
||||||
|
#
|
||||||
|
# Modes:
|
||||||
|
# --dev Development mode with hot-reload (default)
|
||||||
|
# --prod Production mode, pre-built frontend, no hot-reload
|
||||||
|
# --gateway Gateway mode (experimental): skip LangGraph server,
|
||||||
|
# agent runtime embedded in Gateway API
|
||||||
|
# --daemon Run all services in background (nohup), exit after startup
|
||||||
|
#
|
||||||
|
# Actions:
|
||||||
|
# --skip-install Skip dependency installation (faster restart)
|
||||||
|
# --stop Stop all running services and exit
|
||||||
|
# --restart Stop all services, then start with the given mode flags
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# ./scripts/serve.sh --dev # Standard dev (4 processes)
|
||||||
|
# ./scripts/serve.sh --dev --gateway # Gateway dev (3 processes)
|
||||||
|
# ./scripts/serve.sh --prod --gateway # Gateway prod (3 processes)
|
||||||
|
# ./scripts/serve.sh --dev --daemon # Standard dev, background
|
||||||
|
# ./scripts/serve.sh --dev --gateway --daemon # Gateway dev, background
|
||||||
|
# ./scripts/serve.sh --stop # Stop all services
|
||||||
|
# ./scripts/serve.sh --restart --dev --gateway # Restart in gateway mode
|
||||||
#
|
#
|
||||||
# Must be run from the repo root directory.
|
# Must be run from the repo root directory.
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
REPO_ROOT="$(builtin cd "$(dirname "${BASH_SOURCE[0]}")/.." >/dev/null 2>&1 && pwd -P)"
|
||||||
cd "$REPO_ROOT"
|
cd "$REPO_ROOT"
|
||||||
|
|
||||||
# ── Load environment variables from .env ──────────────────────────────────────
|
# ── Load .env ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
if [ -f "$REPO_ROOT/.env" ]; then
|
if [ -f "$REPO_ROOT/.env" ]; then
|
||||||
set -a
|
set -a
|
||||||
source "$REPO_ROOT/.env"
|
source "$REPO_ROOT/.env"
|
||||||
@ -19,14 +44,80 @@ fi
|
|||||||
# ── Argument parsing ─────────────────────────────────────────────────────────
|
# ── Argument parsing ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
DEV_MODE=true
|
DEV_MODE=true
|
||||||
|
GATEWAY_MODE=false
|
||||||
|
DAEMON_MODE=false
|
||||||
|
SKIP_INSTALL=false
|
||||||
|
ACTION="start" # start | stop | restart
|
||||||
|
|
||||||
for arg in "$@"; do
|
for arg in "$@"; do
|
||||||
case "$arg" in
|
case "$arg" in
|
||||||
--dev) DEV_MODE=true ;;
|
--dev) DEV_MODE=true ;;
|
||||||
--prod) DEV_MODE=false ;;
|
--prod) DEV_MODE=false ;;
|
||||||
*) echo "Unknown argument: $arg"; echo "Usage: $0 [--dev|--prod]"; exit 1 ;;
|
--gateway) GATEWAY_MODE=true ;;
|
||||||
|
--daemon) DAEMON_MODE=true ;;
|
||||||
|
--skip-install) SKIP_INSTALL=true ;;
|
||||||
|
--stop) ACTION="stop" ;;
|
||||||
|
--restart) ACTION="restart" ;;
|
||||||
|
*)
|
||||||
|
echo "Unknown argument: $arg"
|
||||||
|
echo "Usage: $0 [--dev|--prod] [--gateway] [--daemon] [--skip-install] [--stop|--restart]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# ── Stop helper ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
stop_all() {
|
||||||
|
echo "Stopping all services..."
|
||||||
|
pkill -f "langgraph dev" 2>/dev/null || true
|
||||||
|
pkill -f "uvicorn app.gateway.app:app" 2>/dev/null || true
|
||||||
|
pkill -f "next dev" 2>/dev/null || true
|
||||||
|
pkill -f "next start" 2>/dev/null || true
|
||||||
|
pkill -f "next-server" 2>/dev/null || true
|
||||||
|
nginx -c "$REPO_ROOT/docker/nginx/nginx.local.conf" -p "$REPO_ROOT" -s quit 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
pkill -9 nginx 2>/dev/null || true
|
||||||
|
./scripts/cleanup-containers.sh deer-flow-sandbox 2>/dev/null || true
|
||||||
|
echo "✓ All services stopped"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Action routing ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if [ "$ACTION" = "stop" ]; then
|
||||||
|
stop_all
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
ALREADY_STOPPED=false
|
||||||
|
if [ "$ACTION" = "restart" ]; then
|
||||||
|
stop_all
|
||||||
|
sleep 1
|
||||||
|
ALREADY_STOPPED=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Derive runtime flags ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if $GATEWAY_MODE; then
|
||||||
|
export SKIP_LANGGRAPH_SERVER=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Mode label for banner
|
||||||
|
if $DEV_MODE && $GATEWAY_MODE; then
|
||||||
|
MODE_LABEL="DEV + GATEWAY (experimental)"
|
||||||
|
elif $DEV_MODE; then
|
||||||
|
MODE_LABEL="DEV (hot-reload enabled)"
|
||||||
|
elif $GATEWAY_MODE; then
|
||||||
|
MODE_LABEL="PROD + GATEWAY (experimental)"
|
||||||
|
else
|
||||||
|
MODE_LABEL="PROD (optimized)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $DAEMON_MODE; then
|
||||||
|
MODE_LABEL="$MODE_LABEL [daemon]"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Frontend command
|
||||||
if $DEV_MODE; then
|
if $DEV_MODE; then
|
||||||
FRONTEND_CMD="pnpm run dev"
|
FRONTEND_CMD="pnpm run dev"
|
||||||
else
|
else
|
||||||
@ -35,46 +126,26 @@ else
|
|||||||
elif command -v python >/dev/null 2>&1; then
|
elif command -v python >/dev/null 2>&1; then
|
||||||
PYTHON_BIN="python"
|
PYTHON_BIN="python"
|
||||||
else
|
else
|
||||||
echo "Python is required to generate BETTER_AUTH_SECRET, but neither python3 nor python was found."
|
echo "Python is required to generate BETTER_AUTH_SECRET."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
FRONTEND_CMD="env BETTER_AUTH_SECRET=$($PYTHON_BIN -c 'import secrets; print(secrets.token_hex(16))') pnpm run preview"
|
FRONTEND_CMD="env BETTER_AUTH_SECRET=$($PYTHON_BIN -c 'import secrets; print(secrets.token_hex(16))') pnpm run preview"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Stop existing services ────────────────────────────────────────────────────
|
# Extra flags for uvicorn/langgraph
|
||||||
|
LANGGRAPH_EXTRA_FLAGS="--no-reload"
|
||||||
echo "Stopping existing services if any..."
|
if $DEV_MODE && ! $DAEMON_MODE; then
|
||||||
pkill -f "langgraph dev" 2>/dev/null || true
|
GATEWAY_EXTRA_FLAGS="--reload --reload-include='*.yaml' --reload-include='.env' --reload-exclude='*.pyc' --reload-exclude='__pycache__' --reload-exclude='sandbox/' --reload-exclude='.deer-flow/'"
|
||||||
pkill -f "uvicorn app.gateway.app:app" 2>/dev/null || true
|
|
||||||
pkill -f "next dev" 2>/dev/null || true
|
|
||||||
pkill -f "next-server" 2>/dev/null || true
|
|
||||||
nginx -c "$REPO_ROOT/docker/nginx/nginx.local.conf" -p "$REPO_ROOT" -s quit 2>/dev/null || true
|
|
||||||
sleep 1
|
|
||||||
pkill -9 nginx 2>/dev/null || true
|
|
||||||
killall -9 nginx 2>/dev/null || true
|
|
||||||
./scripts/cleanup-containers.sh deer-flow-sandbox 2>/dev/null || true
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# ── Banner ────────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=========================================="
|
|
||||||
echo " Starting DeerFlow Development Server"
|
|
||||||
echo "=========================================="
|
|
||||||
echo ""
|
|
||||||
if $DEV_MODE; then
|
|
||||||
echo " Mode: DEV (hot-reload enabled)"
|
|
||||||
echo " Tip: run \`make start\` in production mode"
|
|
||||||
else
|
else
|
||||||
echo " Mode: PROD (hot-reload disabled)"
|
GATEWAY_EXTRA_FLAGS=""
|
||||||
echo " Tip: run \`make dev\` to start in development mode"
|
fi
|
||||||
|
|
||||||
|
# ── Stop existing services (skip if restart already did it) ──────────────────
|
||||||
|
|
||||||
|
if ! $ALREADY_STOPPED; then
|
||||||
|
stop_all
|
||||||
|
sleep 1
|
||||||
fi
|
fi
|
||||||
echo ""
|
|
||||||
echo "Services starting up..."
|
|
||||||
echo " → Backend: LangGraph + Gateway"
|
|
||||||
echo " → Frontend: Next.js"
|
|
||||||
echo " → Nginx: Reverse Proxy"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# ── Config check ─────────────────────────────────────────────────────────────
|
# ── Config check ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@ -84,64 +155,108 @@ if ! { \
|
|||||||
[ -f config.yaml ]; \
|
[ -f config.yaml ]; \
|
||||||
}; then
|
}; then
|
||||||
echo "✗ No DeerFlow config file found."
|
echo "✗ No DeerFlow config file found."
|
||||||
echo " Checked these locations:"
|
echo " Run 'make config' to generate config.yaml."
|
||||||
echo " - $DEER_FLOW_CONFIG_PATH (when DEER_FLOW_CONFIG_PATH is set)"
|
|
||||||
echo " - backend/config.yaml"
|
|
||||||
echo " - ./config.yaml"
|
|
||||||
echo ""
|
|
||||||
echo " Run 'make config' from the repo root to generate ./config.yaml, then set required model API keys in .env or your config file."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Auto-upgrade config ──────────────────────────────────────────────────
|
|
||||||
|
|
||||||
"$REPO_ROOT/scripts/config-upgrade.sh"
|
"$REPO_ROOT/scripts/config-upgrade.sh"
|
||||||
|
|
||||||
# ── Cleanup trap ─────────────────────────────────────────────────────────────
|
# ── Install dependencies ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if ! $SKIP_INSTALL; then
|
||||||
|
echo "Syncing dependencies..."
|
||||||
|
(cd backend && uv sync --quiet) || { echo "✗ Backend dependency install failed"; exit 1; }
|
||||||
|
(cd frontend && pnpm install --silent) || { echo "✗ Frontend dependency install failed"; exit 1; }
|
||||||
|
echo "✓ Dependencies synced"
|
||||||
|
else
|
||||||
|
echo "⏩ Skipping dependency install (--skip-install)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Sync frontend .env.local ─────────────────────────────────────────────────
|
||||||
|
# Next.js .env.local takes precedence over process env vars.
|
||||||
|
# The script manages the NEXT_PUBLIC_LANGGRAPH_BASE_URL line to ensure
|
||||||
|
# the frontend routes match the active backend mode.
|
||||||
|
|
||||||
|
FRONTEND_ENV_LOCAL="$REPO_ROOT/frontend/.env.local"
|
||||||
|
ENV_KEY="NEXT_PUBLIC_LANGGRAPH_BASE_URL"
|
||||||
|
|
||||||
|
sync_frontend_env() {
|
||||||
|
if $GATEWAY_MODE; then
|
||||||
|
# Point frontend to Gateway's compat API
|
||||||
|
if [ -f "$FRONTEND_ENV_LOCAL" ] && grep -q "^${ENV_KEY}=" "$FRONTEND_ENV_LOCAL"; then
|
||||||
|
sed -i.bak "s|^${ENV_KEY}=.*|${ENV_KEY}=/api/langgraph-compat|" "$FRONTEND_ENV_LOCAL" && rm -f "${FRONTEND_ENV_LOCAL}.bak"
|
||||||
|
else
|
||||||
|
echo "${ENV_KEY}=/api/langgraph-compat" >> "$FRONTEND_ENV_LOCAL"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Remove override — frontend falls back to /api/langgraph (standard)
|
||||||
|
if [ -f "$FRONTEND_ENV_LOCAL" ] && grep -q "^${ENV_KEY}=" "$FRONTEND_ENV_LOCAL"; then
|
||||||
|
sed -i.bak "/^${ENV_KEY}=/d" "$FRONTEND_ENV_LOCAL" && rm -f "${FRONTEND_ENV_LOCAL}.bak"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_frontend_env
|
||||||
|
|
||||||
|
# ── Banner ───────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Starting DeerFlow"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo " Mode: $MODE_LABEL"
|
||||||
|
echo ""
|
||||||
|
echo " Services:"
|
||||||
|
if ! $GATEWAY_MODE; then
|
||||||
|
echo " LangGraph → localhost:2024 (agent runtime)"
|
||||||
|
fi
|
||||||
|
echo " Gateway → localhost:8001 (REST API$(if $GATEWAY_MODE; then echo " + agent runtime"; fi))"
|
||||||
|
echo " Frontend → localhost:3000 (Next.js)"
|
||||||
|
echo " Nginx → localhost:2026 (reverse proxy)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── Cleanup handler ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
trap - INT TERM
|
trap - INT TERM
|
||||||
echo ""
|
echo ""
|
||||||
echo "Shutting down services..."
|
stop_all
|
||||||
if [ "${SKIP_LANGGRAPH_SERVER:-0}" != "1" ]; then
|
|
||||||
pkill -f "langgraph dev" 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
pkill -f "uvicorn app.gateway.app:app" 2>/dev/null || true
|
|
||||||
pkill -f "next dev" 2>/dev/null || true
|
|
||||||
pkill -f "next start" 2>/dev/null || true
|
|
||||||
pkill -f "next-server" 2>/dev/null || true
|
|
||||||
# Kill nginx using the captured PID first (most reliable),
|
|
||||||
# then fall back to pkill/killall for any stray nginx workers.
|
|
||||||
if [ -n "${NGINX_PID:-}" ] && kill -0 "$NGINX_PID" 2>/dev/null; then
|
|
||||||
kill -TERM "$NGINX_PID" 2>/dev/null || true
|
|
||||||
sleep 1
|
|
||||||
kill -9 "$NGINX_PID" 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
pkill -9 nginx 2>/dev/null || true
|
|
||||||
killall -9 nginx 2>/dev/null || true
|
|
||||||
echo "Cleaning up sandbox containers..."
|
|
||||||
./scripts/cleanup-containers.sh deer-flow-sandbox 2>/dev/null || true
|
|
||||||
echo "✓ All services stopped"
|
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
trap cleanup INT TERM
|
trap cleanup INT TERM
|
||||||
|
|
||||||
# ── Start services ────────────────────────────────────────────────────────────
|
# ── Helper: start a service ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
# run_service NAME COMMAND PORT TIMEOUT
|
||||||
|
# In daemon mode, wraps with nohup. Waits for port to be ready.
|
||||||
|
run_service() {
|
||||||
|
local name="$1" cmd="$2" port="$3" timeout="$4"
|
||||||
|
|
||||||
|
echo "Starting $name..."
|
||||||
|
if $DAEMON_MODE; then
|
||||||
|
nohup sh -c "$cmd" > /dev/null 2>&1 &
|
||||||
|
else
|
||||||
|
sh -c "$cmd" &
|
||||||
|
fi
|
||||||
|
|
||||||
|
./scripts/wait-for-port.sh "$port" "$timeout" "$name" || {
|
||||||
|
local logfile="logs/$(echo "$name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-').log"
|
||||||
|
echo "✗ $name failed to start."
|
||||||
|
[ -f "$logfile" ] && tail -20 "$logfile"
|
||||||
|
cleanup
|
||||||
|
}
|
||||||
|
echo "✓ $name started on localhost:$port"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Start services ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
mkdir -p logs
|
mkdir -p logs
|
||||||
mkdir -p temp/client_body_temp temp/proxy_temp temp/fastcgi_temp temp/uwsgi_temp temp/scgi_temp
|
mkdir -p temp/client_body_temp temp/proxy_temp temp/fastcgi_temp temp/uwsgi_temp temp/scgi_temp
|
||||||
|
|
||||||
if $DEV_MODE; then
|
# 1. LangGraph (skip in gateway mode)
|
||||||
LANGGRAPH_EXTRA_FLAGS="--no-reload"
|
if ! $GATEWAY_MODE; then
|
||||||
GATEWAY_EXTRA_FLAGS="--reload --reload-include='*.yaml' --reload-include='.env' --reload-exclude='*.pyc' --reload-exclude='__pycache__' --reload-exclude='sandbox/' --reload-exclude='.deer-flow/'"
|
|
||||||
else
|
|
||||||
LANGGRAPH_EXTRA_FLAGS="--no-reload"
|
|
||||||
GATEWAY_EXTRA_FLAGS=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${SKIP_LANGGRAPH_SERVER:-0}" != "1" ]; then
|
|
||||||
echo "Starting LangGraph server..."
|
|
||||||
# Read log_level from config.yaml, fallback to env var, then to "info"
|
|
||||||
CONFIG_LOG_LEVEL=$(grep -m1 '^log_level:' config.yaml 2>/dev/null | awk '{print $2}' | tr -d ' ')
|
CONFIG_LOG_LEVEL=$(grep -m1 '^log_level:' config.yaml 2>/dev/null | awk '{print $2}' | tr -d ' ')
|
||||||
LANGGRAPH_LOG_LEVEL="${LANGGRAPH_LOG_LEVEL:-${CONFIG_LOG_LEVEL:-info}}"
|
LANGGRAPH_LOG_LEVEL="${LANGGRAPH_LOG_LEVEL:-${CONFIG_LOG_LEVEL:-info}}"
|
||||||
LANGGRAPH_JOBS_PER_WORKER="${LANGGRAPH_JOBS_PER_WORKER:-10}"
|
LANGGRAPH_JOBS_PER_WORKER="${LANGGRAPH_JOBS_PER_WORKER:-10}"
|
||||||
@ -150,85 +265,54 @@ if [ "${SKIP_LANGGRAPH_SERVER:-0}" != "1" ]; then
|
|||||||
if [ "$LANGGRAPH_ALLOW_BLOCKING" = "1" ]; then
|
if [ "$LANGGRAPH_ALLOW_BLOCKING" = "1" ]; then
|
||||||
LANGGRAPH_ALLOW_BLOCKING_FLAG="--allow-blocking"
|
LANGGRAPH_ALLOW_BLOCKING_FLAG="--allow-blocking"
|
||||||
fi
|
fi
|
||||||
(cd backend && NO_COLOR=1 uv run langgraph dev --no-browser $LANGGRAPH_ALLOW_BLOCKING_FLAG --n-jobs-per-worker "$LANGGRAPH_JOBS_PER_WORKER" --server-log-level $LANGGRAPH_LOG_LEVEL $LANGGRAPH_EXTRA_FLAGS > ../logs/langgraph.log 2>&1) &
|
run_service "LangGraph" \
|
||||||
./scripts/wait-for-port.sh 2024 60 "LangGraph" || {
|
"cd backend && NO_COLOR=1 uv run langgraph dev --no-browser $LANGGRAPH_ALLOW_BLOCKING_FLAG --n-jobs-per-worker $LANGGRAPH_JOBS_PER_WORKER --server-log-level $LANGGRAPH_LOG_LEVEL $LANGGRAPH_EXTRA_FLAGS > ../logs/langgraph.log 2>&1" \
|
||||||
echo " See logs/langgraph.log for details"
|
2024 60
|
||||||
tail -20 logs/langgraph.log
|
|
||||||
if grep -qE "config_version|outdated|Environment variable .* not found|KeyError|ValidationError|config\.yaml" logs/langgraph.log 2>/dev/null; then
|
|
||||||
echo ""
|
|
||||||
echo " Hint: This may be a configuration issue. Try running 'make config-upgrade' to update your config.yaml."
|
|
||||||
fi
|
|
||||||
cleanup
|
|
||||||
}
|
|
||||||
echo "✓ LangGraph server started on localhost:2024"
|
|
||||||
else
|
else
|
||||||
echo "⏩ Skipping LangGraph server (SKIP_LANGGRAPH_SERVER=1)"
|
echo "⏩ Skipping LangGraph (Gateway mode — runtime embedded in Gateway)"
|
||||||
echo " Use /api/langgraph-compat/* via Gateway instead"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Starting Gateway API..."
|
# 2. Gateway API
|
||||||
(cd backend && PYTHONPATH=. uv run uvicorn app.gateway.app:app --host 0.0.0.0 --port 8001 $GATEWAY_EXTRA_FLAGS > ../logs/gateway.log 2>&1) &
|
run_service "Gateway" \
|
||||||
./scripts/wait-for-port.sh 8001 30 "Gateway API" || {
|
"cd backend && PYTHONPATH=. uv run uvicorn app.gateway.app:app --host 0.0.0.0 --port 8001 $GATEWAY_EXTRA_FLAGS > ../logs/gateway.log 2>&1" \
|
||||||
echo "✗ Gateway API failed to start. Last log output:"
|
8001 30
|
||||||
tail -60 logs/gateway.log
|
|
||||||
echo ""
|
|
||||||
echo "Likely configuration errors:"
|
|
||||||
grep -E "Failed to load configuration|Environment variable .* not found|config\.yaml.*not found" logs/gateway.log | tail -5 || true
|
|
||||||
echo ""
|
|
||||||
echo " Hint: Try running 'make config-upgrade' to update your config.yaml with the latest fields."
|
|
||||||
cleanup
|
|
||||||
}
|
|
||||||
echo "✓ Gateway API started on localhost:8001"
|
|
||||||
|
|
||||||
echo "Starting Frontend..."
|
# 3. Frontend
|
||||||
(cd frontend && $FRONTEND_CMD > ../logs/frontend.log 2>&1) &
|
run_service "Frontend" \
|
||||||
./scripts/wait-for-port.sh 3000 120 "Frontend" || {
|
"cd frontend && $FRONTEND_CMD > ../logs/frontend.log 2>&1" \
|
||||||
echo " See logs/frontend.log for details"
|
3000 120
|
||||||
tail -20 logs/frontend.log
|
|
||||||
cleanup
|
|
||||||
}
|
|
||||||
echo "✓ Frontend started on localhost:3000"
|
|
||||||
|
|
||||||
echo "Starting Nginx reverse proxy..."
|
# 4. Nginx
|
||||||
nginx -g 'daemon off;' -c "$REPO_ROOT/docker/nginx/nginx.local.conf" -p "$REPO_ROOT" > logs/nginx.log 2>&1 &
|
run_service "Nginx" \
|
||||||
NGINX_PID=$!
|
"nginx -g 'daemon off;' -c '$REPO_ROOT/docker/nginx/nginx.local.conf' -p '$REPO_ROOT' > logs/nginx.log 2>&1" \
|
||||||
./scripts/wait-for-port.sh 2026 10 "Nginx" || {
|
2026 10
|
||||||
echo " See logs/nginx.log for details"
|
|
||||||
tail -10 logs/nginx.log
|
|
||||||
cleanup
|
|
||||||
}
|
|
||||||
echo "✓ Nginx started on localhost:2026"
|
|
||||||
|
|
||||||
# ── Ready ─────────────────────────────────────────────────────────────────────
|
# ── Ready ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
if $DEV_MODE; then
|
echo " ✓ DeerFlow is running! [$MODE_LABEL]"
|
||||||
echo " ✓ DeerFlow development server is running!"
|
|
||||||
else
|
|
||||||
echo " ✓ DeerFlow production server is running!"
|
|
||||||
fi
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo ""
|
echo ""
|
||||||
echo " 🌐 Application: http://localhost:2026"
|
echo " 🌐 http://localhost:2026"
|
||||||
echo " 📡 API Gateway: http://localhost:2026/api/*"
|
echo ""
|
||||||
if [ "${SKIP_LANGGRAPH_SERVER:-0}" = "1" ]; then
|
if $GATEWAY_MODE; then
|
||||||
echo " 🤖 LangGraph: skipped (SKIP_LANGGRAPH_SERVER=1)"
|
echo " Routing: Frontend → Nginx → Gateway (embedded runtime)"
|
||||||
|
echo " API: /api/langgraph-compat/* → Gateway agent runtime"
|
||||||
else
|
else
|
||||||
echo " 🤖 LangGraph: http://localhost:2026/api/langgraph/* (served by langgraph dev)"
|
echo " Routing: Frontend → Nginx → LangGraph + Gateway"
|
||||||
|
echo " API: /api/langgraph/* → LangGraph server (2024)"
|
||||||
fi
|
fi
|
||||||
echo " 🧪 LangGraph Compat (experimental): http://localhost:2026/api/langgraph-compat/* (served by Gateway)"
|
echo " /api/* → Gateway REST API (8001)"
|
||||||
if [ "${SKIP_LANGGRAPH_SERVER:-0}" = "1" ]; then
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " 💡 Set NEXT_PUBLIC_LANGGRAPH_BASE_URL=/api/langgraph-compat in frontend/.env.local"
|
echo " 📋 Logs: logs/{langgraph,gateway,frontend,nginx}.log"
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
echo " 📋 Logs:"
|
|
||||||
echo " - LangGraph: logs/langgraph.log"
|
|
||||||
echo " - Gateway: logs/gateway.log"
|
|
||||||
echo " - Frontend: logs/frontend.log"
|
|
||||||
echo " - Nginx: logs/nginx.log"
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
if $DAEMON_MODE; then
|
||||||
|
echo " 🛑 Stop: make stop"
|
||||||
|
# Detach — trap is no longer needed
|
||||||
|
trap - INT TERM
|
||||||
|
else
|
||||||
echo " Press Ctrl+C to stop all services"
|
echo " Press Ctrl+C to stop all services"
|
||||||
|
|
||||||
wait
|
wait
|
||||||
|
fi
|
||||||
|
|||||||
@ -1,146 +1,9 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# start-daemon.sh - Start all DeerFlow development services in daemon mode
|
# start-daemon.sh — Start DeerFlow in daemon (background) mode
|
||||||
#
|
#
|
||||||
# This script starts DeerFlow services in the background without keeping
|
# Thin wrapper around serve.sh --daemon.
|
||||||
# the terminal connection. Logs are written to separate files.
|
# Kept for backward compatibility.
|
||||||
#
|
|
||||||
# Must be run from the repo root directory.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
cd "$REPO_ROOT"
|
exec "$REPO_ROOT/scripts/serve.sh" --dev --daemon "$@"
|
||||||
|
|
||||||
# ── Stop existing services ────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
echo "Stopping existing services if any..."
|
|
||||||
pkill -f "langgraph dev" 2>/dev/null || true
|
|
||||||
pkill -f "uvicorn app.gateway.app:app" 2>/dev/null || true
|
|
||||||
pkill -f "next dev" 2>/dev/null || true
|
|
||||||
nginx -c "$REPO_ROOT/docker/nginx/nginx.local.conf" -p "$REPO_ROOT" -s quit 2>/dev/null || true
|
|
||||||
sleep 1
|
|
||||||
pkill -9 nginx 2>/dev/null || true
|
|
||||||
./scripts/cleanup-containers.sh deer-flow-sandbox 2>/dev/null || true
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# ── Banner ────────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=========================================="
|
|
||||||
echo " Starting DeerFlow in Daemon Mode"
|
|
||||||
echo "=========================================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# ── Config check ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
if ! { \
|
|
||||||
[ -n "$DEER_FLOW_CONFIG_PATH" ] && [ -f "$DEER_FLOW_CONFIG_PATH" ] || \
|
|
||||||
[ -f backend/config.yaml ] || \
|
|
||||||
[ -f config.yaml ]; \
|
|
||||||
}; then
|
|
||||||
echo "✗ No DeerFlow config file found."
|
|
||||||
echo " Checked these locations:"
|
|
||||||
echo " - $DEER_FLOW_CONFIG_PATH (when DEER_FLOW_CONFIG_PATH is set)"
|
|
||||||
echo " - backend/config.yaml"
|
|
||||||
echo " - ./config.yaml"
|
|
||||||
echo ""
|
|
||||||
echo " Run 'make config' from the repo root to generate ./config.yaml, then set required model API keys in .env or your config file."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ── Auto-upgrade config ──────────────────────────────────────────────────
|
|
||||||
|
|
||||||
"$REPO_ROOT/scripts/config-upgrade.sh"
|
|
||||||
|
|
||||||
# ── Cleanup on failure ───────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
cleanup_on_failure() {
|
|
||||||
echo "Failed to start services, cleaning up..."
|
|
||||||
pkill -f "langgraph dev" 2>/dev/null || true
|
|
||||||
pkill -f "uvicorn app.gateway.app:app" 2>/dev/null || true
|
|
||||||
pkill -f "next dev" 2>/dev/null || true
|
|
||||||
nginx -c "$REPO_ROOT/docker/nginx/nginx.local.conf" -p "$REPO_ROOT" -s quit 2>/dev/null || true
|
|
||||||
sleep 1
|
|
||||||
pkill -9 nginx 2>/dev/null || true
|
|
||||||
echo "✓ Cleanup complete"
|
|
||||||
}
|
|
||||||
|
|
||||||
trap cleanup_on_failure INT TERM
|
|
||||||
|
|
||||||
# ── Start services ────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
mkdir -p logs
|
|
||||||
mkdir -p temp/client_body_temp temp/proxy_temp temp/fastcgi_temp temp/uwsgi_temp temp/scgi_temp
|
|
||||||
|
|
||||||
echo "Starting LangGraph server..."
|
|
||||||
LANGGRAPH_JOBS_PER_WORKER="${LANGGRAPH_JOBS_PER_WORKER:-10}"
|
|
||||||
LANGGRAPH_ALLOW_BLOCKING="${LANGGRAPH_ALLOW_BLOCKING:-0}"
|
|
||||||
LANGGRAPH_ALLOW_BLOCKING_FLAG=""
|
|
||||||
if [ "$LANGGRAPH_ALLOW_BLOCKING" = "1" ]; then
|
|
||||||
LANGGRAPH_ALLOW_BLOCKING_FLAG="--allow-blocking"
|
|
||||||
fi
|
|
||||||
nohup sh -c "cd backend && NO_COLOR=1 uv run langgraph dev --no-browser ${LANGGRAPH_ALLOW_BLOCKING_FLAG} --no-reload --n-jobs-per-worker ${LANGGRAPH_JOBS_PER_WORKER} > ../logs/langgraph.log 2>&1" &
|
|
||||||
./scripts/wait-for-port.sh 2024 60 "LangGraph" || {
|
|
||||||
echo "✗ LangGraph failed to start. Last log output:"
|
|
||||||
tail -60 logs/langgraph.log
|
|
||||||
if grep -qE "config_version|outdated|Environment variable .* not found|KeyError|ValidationError|config\.yaml" logs/langgraph.log 2>/dev/null; then
|
|
||||||
echo ""
|
|
||||||
echo " Hint: This may be a configuration issue. Try running 'make config-upgrade' to update your config.yaml."
|
|
||||||
fi
|
|
||||||
cleanup_on_failure
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
echo "✓ LangGraph server started on localhost:2024"
|
|
||||||
|
|
||||||
echo "Starting Gateway API..."
|
|
||||||
nohup sh -c 'cd backend && PYTHONPATH=. uv run uvicorn app.gateway.app:app --host 0.0.0.0 --port 8001 > ../logs/gateway.log 2>&1' &
|
|
||||||
./scripts/wait-for-port.sh 8001 30 "Gateway API" || {
|
|
||||||
echo "✗ Gateway API failed to start. Last log output:"
|
|
||||||
tail -60 logs/gateway.log
|
|
||||||
echo ""
|
|
||||||
echo " Hint: Try running 'make config-upgrade' to update your config.yaml with the latest fields."
|
|
||||||
cleanup_on_failure
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
echo "✓ Gateway API started on localhost:8001"
|
|
||||||
|
|
||||||
echo "Starting Frontend..."
|
|
||||||
nohup sh -c 'cd frontend && pnpm run dev > ../logs/frontend.log 2>&1' &
|
|
||||||
./scripts/wait-for-port.sh 3000 120 "Frontend" || {
|
|
||||||
echo "✗ Frontend failed to start. Last log output:"
|
|
||||||
tail -60 logs/frontend.log
|
|
||||||
cleanup_on_failure
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
echo "✓ Frontend started on localhost:3000"
|
|
||||||
|
|
||||||
echo "Starting Nginx reverse proxy..."
|
|
||||||
nohup sh -c 'nginx -g "daemon off;" -c "$1/docker/nginx/nginx.local.conf" -p "$1" > logs/nginx.log 2>&1' _ "$REPO_ROOT" &
|
|
||||||
./scripts/wait-for-port.sh 2026 10 "Nginx" || {
|
|
||||||
echo "✗ Nginx failed to start. Last log output:"
|
|
||||||
tail -60 logs/nginx.log
|
|
||||||
cleanup_on_failure
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
echo "✓ Nginx started on localhost:2026"
|
|
||||||
|
|
||||||
# ── Ready ─────────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=========================================="
|
|
||||||
echo " DeerFlow is running in daemon mode!"
|
|
||||||
echo "=========================================="
|
|
||||||
echo ""
|
|
||||||
echo " 🌐 Application: http://localhost:2026"
|
|
||||||
echo " 📡 API Gateway: http://localhost:2026/api/*"
|
|
||||||
echo " 🤖 LangGraph: http://localhost:2026/api/langgraph/*"
|
|
||||||
echo ""
|
|
||||||
echo " 📋 Logs:"
|
|
||||||
echo " - LangGraph: logs/langgraph.log"
|
|
||||||
echo " - Gateway: logs/gateway.log"
|
|
||||||
echo " - Frontend: logs/frontend.log"
|
|
||||||
echo " - Nginx: logs/nginx.log"
|
|
||||||
echo ""
|
|
||||||
echo " 🛑 Stop daemon: make stop"
|
|
||||||
echo ""
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user