Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/worktrees/elastic-lichterman
Submodule elastic-lichterman added at 77af75
1 change: 1 addition & 0 deletions .claude/worktrees/suspicious-raman
Submodule suspicious-raman added at 77af75
2 changes: 1 addition & 1 deletion .github/workflows/version.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ name: Auto Version

on:
push:
branches: [main]
branches: [main, dev]

jobs:
version:
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
.env
*.key
.venv/
__pycache__/
*.pyc
data/backups/
git.json
.claude/worktrees/
Empty file addedAgents/Shared/__init__.py
Empty file.
Empty file addedAgents/__init__.py
Empty file.
52 changes: 46 additions & 6 deletions Agents/orchestrator.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -507,18 +507,58 @@ def route_after_orchestrator(state: dict) -> str:

def human_gate_node(state: dict) -> dict:
"""
Human gate — attend la validation humaine via Discord.
Pour l'instant : simule un 'approve' automatique pour les tests.
TODO: integrer discord_tools.request_human_approval()
Human gate — attend la validation humaine via le canal configure (Discord, Email, etc.).
Envoie une demande d'approbation et attend la reponse (timeout 30 min).
"""
logger.info("🚦 Human gate — simulation approve (a integrer Discord)")
from agents.shared.human_gate import request_approval_sync

phase = state.get("project_phase", "inconnue")
team_id = state.get("_team_id", "default")
channel_id = state.get("_discord_channel_id", "")

# Construire le resume a partir de la derniere decision
summary = f"Validation requise — phase « {phase} »"
details = ""
decisions = state.get("decision_history", [])
if decisions:
last = decisions[-1]
reasoning = last.get("reasoning", "")
if reasoning:
details = reasoning

logger.info(f"🚦 Human gate — demande approbation (team={team_id}, phase={phase})")

result = request_approval_sync(
agent_name="Orchestrateur",
summary=summary,
details=details,
channel_id=channel_id,
team_id=team_id,
)

approved = result.get("approved", False)
reviewer = result.get("reviewer", "unknown")
response_text = result.get("response", "")
timed_out = result.get("timed_out", False)

feedback = list(state.get("human_feedback_log", []))
feedback.append({
"timestamp": datetime.now(timezone.utc).isoformat(),
"response": "approve",
"source": "auto-test",
"response": "approve" if approved else "reject",
"reviewer": reviewer,
"comment": response_text,
"timed_out": timed_out,
"source": "human_gate",
})
state["human_feedback_log"] = feedback

if timed_out:
logger.warning("🚦 Human gate — timeout, aucune reponse")
elif approved:
logger.info(f"🚦 Human gate — approuve par {reviewer}")
else:
logger.info(f"🚦 Human gate — rejete par {reviewer} : {response_text}")

return state


Expand Down
12 changes: 7 additions & 5 deletions CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -543,10 +543,12 @@ GOOGLE_CLIENT_SECRET=... # Secret Google OAuth (si google_oauth.enabled)

| Script | Rôle |
|---|---|
| `00-configure-lxc.sh` | Config LXC Proxmox |
| `01-proxmox-create-vm.sh` | Création VM |
| `02-install-langgraph.sh` | Docker + infra + code agents + configs équipe |
| `start.sh / restart.sh / build.sh` | Gestion des containers |
| `00-create-lxc.sh` | Création LXC Proxmox + installation complète |
| `00-prepare-existing-lxc4Docker.sh` | Prépare un LXC existant pour Docker |
| `01-install-docker.sh` | Docker Engine + Compose + Caddy reverse proxy |
| `02-install-langgraph.sh` | Infra + code agents + configs équipe (paramètre branche) |
| `03-install-rag.sh` | Couche RAG (pgvector + Voyage AI) |
| `start.sh / stop.sh / restart.sh / build.sh / update.sh` | Gestion des containers + mise à jour |

Le script 02 télécharge tout depuis GitHub : Dockerfiles, code agents (`Agents/Shared/*.py`, `Agents/*.py`), configs globales, et structure d'équipe. Les prompts sont gérés via git pull depuis le dashboard admin.

Expand All@@ -567,7 +569,7 @@ Le script 02 télécharge tout depuis GitHub : Dockerfiles, code agents (`Agents
### Infrastructure
1. Infrastructure LXC + Docker (5 containers opérationnels)
2. Volumes mappés sur l'hôte
3. Langfuse dans docker-compose (port 3000)
3. OpenLIT observabilité dans docker-compose (port 3000)
4. Scripts utilitaires + script d'installation unifié (02)

### Agents & Orchestration
Expand Down
1 change: 1 addition & 0 deletions Dockerfile.hitl
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,4 +5,5 @@ RUN pip install --no-cache-dir -r requirements.txt
COPY hitl/server.py .
COPY hitl/static/ ./static/
COPY config/Teams/ ./config/Teams/
EXPOSE 8090
CMD ["python", "server.py"]
47 changes: 44 additions & 3 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,7 +50,7 @@ Trois scripts sequentiels. Chaque script se telecharge et s'execute en une comma
bash -c "$(wget -qLO - https://raw.githubusercontent.com/Configurations/LandGraph/refs/heads/main/scripts/Infra/00-create-lxc.sh)"

# Option B — Configurer un LXC existant pour Docker
bash -c "$(wget -qLO - https://raw.githubusercontent.com/Configurations/LandGraph/refs/heads/main/scripts/Infra/00-configure-lxc.sh)" _ <CTID>
bash -c "$(wget -qLO - https://raw.githubusercontent.com/Configurations/LandGraph/refs/heads/main/scripts/Infra/00-prepare-existing-lxc4Docker.sh)" _ <CTID>
```

| Parametre | Valeur par defaut |
Expand All@@ -68,14 +68,29 @@ bash -c "$(wget -qLO - https://raw.githubusercontent.com/Configurations/LandGrap
bash -c "$(wget -qLO - https://raw.githubusercontent.com/Configurations/LandGraph/refs/heads/main/scripts/Infra/01-install-docker.sh)"
```

Installe Docker Engine + Compose, configure les logs, active UFW (ports 8123, 8080, 3000 en reseau local). **Se reconnecter apres execution** (groupe docker).
Installe Docker Engine + Compose, configure les logs, active UFW (ports 8123, 8080, 3000 en reseau local), et installe **Caddy** comme reverse proxy HTTP (port 80). **Se reconnecter apres execution** (groupe docker).

Caddy est configure pour router les sous-domaines vers les services locaux (SSL gere par Cloudflare Tunnel en front) :

| Domaine | Service |
|---------|---------|
| `admin.langgraph.yoops.org` | Dashboard Admin (:8080) |
| `hitl.langgraph.yoops.org` | HITL Console (:8090) |
| `api.langgraph.yoops.org` | API Gateway (:8123) |
| `openlit.langgraph.yoops.org` | OpenLIT (:3000) |

La config Caddy est dans `/etc/caddy/Caddyfile`. Pour ajouter un domaine, dupliquer un bloc et relancer `systemctl reload caddy`.

### Etape 2 — Installer LangGraph

**Ou** : SSH sur la VM/LXC, apres reconnexion.

```bash
# Depuis main (defaut)
bash -c "$(wget -qLO - https://raw.githubusercontent.com/Configurations/LandGraph/refs/heads/main/scripts/Infra/02-install-langgraph.sh)"

# Depuis une branche specifique (dev, uat, main)
bash -c "$(wget -qLO - https://raw.githubusercontent.com/Configurations/LandGraph/refs/heads/dev/scripts/Infra/02-install-langgraph.sh)" _ dev
```

Ce script deploie le socle complet :
Expand DownExpand Up@@ -237,7 +252,7 @@ langgraph-project/
├── docker-compose.yml
├── Dockerfile / Dockerfile.discord / Dockerfile.mail / Dockerfile.admin / Dockerfile.hitl
├── .env ← Secrets uniquement
├── start.sh / stop.sh / restart.sh / build.sh
├── start.sh / stop.sh / restart.sh / build.sh / update.sh
└── requirements.txt
```

Expand DownExpand Up@@ -378,6 +393,7 @@ http://<IP-VM>:8080

| Service | Port | Acces |
|---------|------|-------|
| Caddy (reverse proxy) | 80 | Public (via Cloudflare Tunnel) |
| LangGraph API | 8123 | Reseau local |
| Admin Dashboard | 8080 | Reseau local |
| HITL Console | 8090 | Reseau local |
Expand All@@ -387,13 +403,38 @@ http://<IP-VM>:8080
| PostgreSQL | 5432 | localhost uniquement |
| Redis | 6379 | localhost uniquement |

## Branches

Le projet suit une strategie a trois branches :

| Branche | Role | Stabilite |
|---------|------|-----------|
| `main` | Production — deploiement stable | Haute |
| `uat` | Pre-production — tests d'acceptation | Moyenne |
| `dev` | Developpement — nouvelles features | Basse |

Flux : `dev` → `uat` → `main`. Les scripts d'installation et de mise a jour acceptent la branche en parametre.

## Mise a jour

Le script `update.sh` telecharge et execute le script d'installation depuis GitHub. Il accepte une branche en parametre :

```bash
./update.sh # Mise a jour depuis main (defaut)
./update.sh dev # Mise a jour depuis la branche dev
./update.sh uat # Mise a jour depuis la branche uat
```

Branches acceptees : `dev`, `uat`, `main`. Le script verifie la version avant de telecharger — si la version locale est identique, rien n'est fait.

## Scripts utilitaires

```bash
./start.sh # Demarre tous les containers
./stop.sh # Arrete tous les containers
./restart.sh # Arrete + demarre
./build.sh # Rebuild les images + demarre
./update.sh [branche] # Mise a jour depuis GitHub (dev|uat|main, defaut: main)
```

## HITL Console (port 8090)
Expand Down
2 changes: 1 addition & 1 deletion build.sh
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
#!/bin/bash
PROJECT_DIR="/${HOME}/langgraph-project"
PROJECT_DIR="${HOME}/langgraph-project"
cd "${PROJECT_DIR}"

docker compose stop
Expand Down
17 changes: 0 additions & 17 deletions docker-compose-mail.yml

This file was deleted.

1 change: 0 additions & 1 deletion docker-compose.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -80,7 +80,6 @@ services:
volumes:
- ./agents:/app/agents
- ./config:/app/config
- ./config/Teams:/app/config/Teams
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
Expand Down
41 changes: 38 additions & 3 deletions env.example
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@


# ── LLM ──────────────────────────────────────
ANTHROPIC_API_KEY=sk-ant-api03-VOTRE-CLE-ICI# OPENAI_API_KEY=sk-VOTRE-CLE-OPENAI
ANTHROPIC_API_KEY=sk-ant-api03-VOTRE-CLE-ICI
# OPENAI_API_KEY=sk-VOTRE-CLE-OPENAI
# AZURE_OPENAI_API_KEY=VOTRE-CLE-AZURE
# GOOGLE_API_KEY=VOTRE-CLE-GOOGLE
# MISTRAL_API_KEY=VOTRE-CLE-MISTRAL
Expand DownExpand Up@@ -36,6 +37,11 @@ DATABASE_URI=postgres://langgraph:CHANGEZ-MOI-EN-PROD@langgraph-postgres:5432/la
REDIS_URI=redis://:CHANGEZ-MOI-AUSSI@langgraph-redis:6379/0


# ── Canal par defaut ─────────────────────────
# discord | email
DEFAULT_CHANNEL=discord


# ── Discord ──────────────────────────────────
DISCORD_BOT_TOKEN=VOTRE-TOKEN-BOT
DISCORD_CHANNEL_COMMANDS=ID-CHANNEL-COMMANDES
Expand All@@ -44,5 +50,34 @@ DISCORD_CHANNEL_ALERTS=ID-CHANNEL-ALERTS
DISCORD_CHANNEL_REVIEW=ID-CHANNEL-REVIEW
DISCORD_GUILD_ID=ID-SERVEUR

WEB_ADMIN_USERNAME=root
WEB_ADMIN_PASSWORD=root

# ── Email (si DEFAULT_CHANNEL=email) ─────────
# SMTP_HOST=smtp.gmail.com
# SMTP_PORT=587
# SMTP_USER=votre-email@gmail.com
# SMTP_PASSWORD=xxxx-xxxx-xxxx-xxxx
# IMAP_HOST=imap.gmail.com
# IMAP_PASSWORD=xxxx-xxxx-xxxx-xxxx


# ── Admin Dashboard ──────────────────────────
WEB_ADMIN_USERNAME=admin
WEB_ADMIN_PASSWORD=CHANGEZ-MOI-EN-PROD


# ── MCP Server (optionnel) ───────────────────
# MCP_SECRET=CHANGEZ-MOI-SECRET-MCP


# ── HITL Console ─────────────────────────────
HITL_JWT_SECRET=CHANGEZ-MOI-SECRET-JWT
HITL_ADMIN_EMAIL=admin@company.com
HITL_ADMIN_PASSWORD=CHANGEZ-MOI-EN-PROD
# HITL_PUBLIC_URL=https://hitl.company.com
# GOOGLE_CLIENT_SECRET=VOTRE-SECRET-GOOGLE-OAUTH


# ── OpenLIT (optionnel) ──────────────────────
# OPENLIT_DB_PASSWORD=CHANGEZ-MOI
# OPENLIT_DB_USER=default
# OPENLIT_DB_NAME=default
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
timeout = 30
pythonpath = ["."]
addopts = "--tb=short -q --cov=Agents --cov-report=term-missing"
5 changes: 5 additions & 0 deletions requirements-test.txt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
pytest>=8.0
pytest-asyncio>=0.23
pytest-mock>=3.12
pytest-cov>=5.0
freezegun>=1.3
2 changes: 1 addition & 1 deletion restart.sh
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
#!/bin/bash
PROJECT_DIR="${HOME}/langgraph-project"
cd "/${PROJECT_DIR}"
cd "${PROJECT_DIR}"
docker compose down
docker compose up -d
echo ""
Expand Down
2 changes: 0 additions & 2 deletions scripts/Infra/00-create-lxc.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,7 +44,6 @@ SSH_KEY_DIR="/root/.ssh/lxc-keys"
DOCKER_SCRIPT_URL="https://raw.githubusercontent.com/Configurations/LandGraph/refs/heads/main/scripts/Infra/01-install-docker.sh"
LANGGRAPH_SCRIPT_URL="https://raw.githubusercontent.com/Configurations/LandGraph/refs/heads/main/scripts/Infra/02-install-langgraph.sh"
RAG_SCRIPT_URL="https://raw.githubusercontent.com/Configurations/LandGraph/refs/heads/main/scripts/Infra/03-install-rag.sh"
WEB_SCRIPT_URL="https://raw.githubusercontent.com/Configurations/LandGraph/refs/heads/main/scripts/Infra/04-install-admin.sh"

if [ -z "${CTID}" ]; then
echo "Usage: $0 <CTID>"
Expand DownExpand Up@@ -371,7 +370,6 @@ echo ""
pct exec "${CTID}" -- bash -c "$(wget -qLO - "${DOCKER_SCRIPT_URL}" 2>/dev/null || echo 'echo ERREUR : impossible de telecharger ${DOCKER_SCRIPT_URL}')"
pct exec "${CTID}" -- bash -c "$(wget -qLO - "${LANGGRAPH_SCRIPT_URL}" 2>/dev/null || echo 'echo ERREUR : impossible de telecharger ${LANGGRAPH_SCRIPT_URL}')"
pct exec "${CTID}" -- bash -c "$(wget -qLO - "${RAG_SCRIPT_URL}" 2>/dev/null || echo 'echo ERREUR : impossible de telecharger ${RAG_SCRIPT_URL}')"
pct exec "${CTID}" -- bash -c "$(wget -qLO - "${WEB_SCRIPT_URL}" 2>/dev/null || echo 'echo ERREUR : impossible de telecharger ${WEB_SCRIPT_URL}')"

# ── Recuperer l'IP finale ────────────────────────────────────────────────────
CT_IP=$(pct exec "${CTID}" -- bash -c "ip -4 addr show eth0 2>/dev/null | grep inet | awk '{print \$2}' | cut -d/ -f1 | head -1")
Expand Down
Loading
Loading