systemd+skills+mattermost

This commit is contained in:
Yanis Mahboub
2026-03-27 19:05:47 +01:00
parent a4e4bb21e3
commit 282fbdb9a0
9 changed files with 306 additions and 1 deletions

View File

@@ -0,0 +1,59 @@
"""
Mattermost Notification Tool for DeerFlow.
Posts notifications to Mattermost via incoming webhook.
Set MATTERMOST_WEBHOOK_URL in .env
"""
import json
import logging
import os
from langchain.tools import tool
logger = logging.getLogger(__name__)
MATTERMOST_WEBHOOK_URL = os.environ.get("MATTERMOST_WEBHOOK_URL", "")
@tool("notify_team", parse_docstring=True)
def notify_team_tool(
message: str,
channel: str = "",
username: str = "DeerFlow Agent",
) -> str:
"""Send a notification to the WEVAL team via Mattermost. Use this after completing research, enrichment, or any task that the team should know about.
Args:
message: The message to send. Supports Markdown formatting.
channel: Optional channel override (e.g. #general, #alerts). Leave empty for default.
username: Display name for the bot. Default is DeerFlow Agent.
"""
if not MATTERMOST_WEBHOOK_URL:
return json.dumps({"error": "MATTERMOST_WEBHOOK_URL not configured in .env"})
try:
import urllib.request
payload = {
"text": message,
"username": username,
"icon_url": "https://weval-consulting.com/assets/logo-weval-png-DChrMGao.png",
}
if channel:
payload["channel"] = channel
data = json.dumps(payload).encode()
req = urllib.request.Request(
MATTERMOST_WEBHOOK_URL,
data=data,
headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(req, timeout=10) as resp:
result = resp.read().decode()
return json.dumps({"status": "sent", "response": result})
except Exception as e:
logger.error(f"Mattermost notification failed: {e}")
return json.dumps({"error": str(e)})

View File

@@ -0,0 +1,94 @@
"""
Web Search Tool - Search the web using SearXNG (replaces DDG which has DNS issues).
SearXNG runs on localhost:8080.
"""
import json
import logging
import os
from langchain.tools import tool
from deerflow.config import get_app_config
logger = logging.getLogger(__name__)
SEARXNG_URL = os.environ.get("SEARXNG_URL", "http://127.0.0.1:8080")
def _search_text(
query: str,
max_results: int = 5,
language: str = "auto",
safesearch: int = 1,
) -> list[dict]:
"""
Execute text search using SearXNG.
"""
try:
import urllib.request
import urllib.parse
params = urllib.parse.urlencode({
"q": query,
"format": "json",
"categories": "general",
"language": language,
"safesearch": safesearch,
})
url = f"{SEARXNG_URL}/search?{params}"
req = urllib.request.Request(url)
req.add_header("Accept", "application/json")
with urllib.request.urlopen(req, timeout=15) as resp:
data = json.loads(resp.read().decode())
results = data.get("results", [])[:max_results]
return results
except Exception as e:
logger.error(f"Failed to search web via SearXNG: {e}")
return []
@tool("web_search", parse_docstring=True)
def web_search_tool(
query: str,
max_results: int = 5,
) -> str:
"""Search the web for information. Use this tool to find current information, news, articles, and facts from the internet.
Args:
query: Search keywords describing what you want to find. Be specific for better results.
max_results: Maximum number of results to return. Default is 5.
"""
config = get_app_config().get_tool_config("web_search")
if config is not None and "max_results" in config.model_extra:
max_results = config.model_extra.get("max_results", max_results)
results = _search_text(
query=query,
max_results=max_results,
)
if not results:
return json.dumps({"error": "No results found", "query": query}, ensure_ascii=False)
normalized_results = [
{
"title": r.get("title", ""),
"url": r.get("url", r.get("href", r.get("link", ""))),
"content": r.get("content", r.get("body", r.get("snippet", ""))),
}
for r in results
]
output = {
"query": query,
"total_results": len(normalized_results),
"results": normalized_results,
}
return json.dumps(output, indent=2, ensure_ascii=False)

View File

@@ -24,7 +24,7 @@ http {
}
upstream frontend {
server 127.0.0.1:3000;
server 127.0.0.1:3002;
}
server {

View File

@@ -0,0 +1,44 @@
---
name: weval-crm-enrichment
description: Enrich company and contact data for WEVAL Consulting CRM pipeline via Twenty CRM API. Use when asked about CRM stats, companies, deals, contacts, or pipeline data.
---
# WEVAL CRM Enrichment Skill
## Purpose
Enrich company and contact data for WEVAL Consulting CRM pipeline.
## Available APIs
- CRM Stats: `GET https://weval-consulting.com/api/crm-api.php?action=stats`
- Companies: `GET https://weval-consulting.com/api/crm-api.php?action=companies`
- Deals: `GET https://weval-consulting.com/api/crm-api.php?action=deals`
- Contacts: `GET https://weval-consulting.com/api/crm-api.php?action=contacts`
- Enrich Domain: `POST https://weval-consulting.com/api/crm-api.php?action=enrich` body: `{"domain":"example.com","company_id":1}`
- Add Contact: `POST https://weval-consulting.com/api/crm-api.php?action=contacts` body: `{"first_name":"","last_name":"","email":"","company_id":1}`
## Bash Tools Available
```bash
# theHarvester - find emails/subdomains for a domain
theHarvester -d example.com -b google,bing,duckduckgo -l 50
# emailfinder - find email patterns
emailfinder -d example.com
# Direct DB query
PGPASSWORD=admin123 psql -U admin -h 127.0.0.1 -d weval_crm -c "SELECT * FROM crm.companies;"
# LinkedIn data via SearXNG
curl -s "http://127.0.0.1:8080/search?q=site:linkedin.com+COMPANY+NAME+morocco&format=json"
```
## Workflow
1. Fetch current companies from CRM API via web_fetch
2. For each company domain, use bash to run theHarvester
3. Parse discovered emails and create contacts via API
4. Research LinkedIn/web via web_search for decision-maker names
5. Generate enrichment report with new contacts found
## Context
WEVAL Consulting - sovereign AI consulting firm in Casablanca, Morocco.
Key clients: Cosumar, Carrefour Maroc, Vistex, Huawei Cloud, Confluent Digital, Groupe Ethica.
Focus: ERP/SAP, Cloud, Supply Chain, Life Sciences/Pharma, Cybersecurity.

View File

@@ -0,0 +1,46 @@
---
name: weval-ethica-research
description: Query Ethica database for real-time campaign KPIs, HCP analytics, send tracking, and campaign performance across Morocco, Tunisia, and Algeria. Use when asked about Ethica campaigns, HCP counts, open rates, or pharma outreach metrics.
---
# WEVAL Ethica Campaign KPIs & HCP Analytics Skill
## Purpose
Query Ethica database for real-time campaign KPIs and HCP analytics.
## Database Access
- Server: S95 (95.216.167.89), SSH port 49222
- DB: adx_system, schema: ethica (22 tables)
- Credentials: admin/admin123
- Access: ssh -p 49222 root@95.216.167.89 "PGPASSWORD=admin123 psql -U admin -h 127.0.0.1 -d adx_system -c SQL"
## Key Tables
- campaigns: id, name, status, target_specialites, target_pays, sent/open/click/bounce counts
- send_log: campaign_id, hcp_id, email, sent_at, status
- tracking_opens: campaign_id, hcp_id, opened_at
- tracking_clicks: campaign_id, hcp_id, clicked_at, url
- medecins_validated: 123K HCPs (nom, prenom, specialite, email, telephone, ville, pays)
- consent_log: GDPR consent tracking
- senders: sender domains and warmup status
## Current State (27 mars 2026)
- Campaigns: 1 (Lancement Ethica Pharma Mars 2026), status=paused, 0 sent
- HCPs: 123,032 validated (MA, TN, DZ)
- Sends: 0 (not yet launched)
- Tracking: 2 opens, 2 clicks (test)
## KPI Queries
### Campaign Overview
SELECT id, name, status, target_pays, sent_count, open_count, click_count, bounce_count FROM ethica.campaigns ORDER BY created_at DESC;
### HCP Stats by Specialty
SELECT specialite, pays, COUNT(*) as total, COUNT(email) AS with_email FROM ethica.medecins_validated GROUP BY specialite, pays ORDER BY total DESC LIMIT 20;
## Workflow
1. Identify campaign by name or ID
2. Query overview for totals
3. Calculate rates only when sent_count > 0
4. Compare to pharma benchmarks: open 18-25 pct, click 2-5 pct
5. NEVER fabricate data - report exactly what DB returns
6. Flag empty data (0 sends = pre-launch)

View File

@@ -0,0 +1,29 @@
---
name: weval-infra-monitor
description: Use this skill to monitor WEVAL infrastructure status, check server health, verify services are running, and diagnose issues across S204, S95, and S151 servers.
---
# WEVAL Infrastructure Monitor Skill
## Servers
- **S204** (weval-consulting.com): nginx, PHP 8.5, PostgreSQL 13, 14 Docker containers, Ollama
- **S95** (95.216.167.89): Apache, PMTA v5.0r3, Node.js WEVADS v2, PostgreSQL
- **S151** (151.80.235.110): OVH, tracking relay, Ollama granite4, OpenClaw, DeerFlow sandbox
## Health Endpoints
- Chat API: `https://weval-consulting.com/api/weval-ia`
- Fast API: `https://weval-consulting.com/api/weval-ia-fast.php`
- Ethica: `https://ethica.wevup.app/ethica-app-v3.html`
- CRM: `https://weval-consulting.com/api/crm-api.php?action=stats`
- DeerFlow: `http://localhost:2024/ok`
- Ollama S204: `http://localhost:11435/api/ps`
- Ollama S151: `http://151.80.235.110:11434/api/ps`
## Chat Monitor
- 30 systems dashboard: `https://weval-consulting.com/test-report/wevia-chat-monitor.html`
## Key Metrics to Check
- PHP workers: `pgrep -c php-fpm8.5`
- Disk: `df -h /`
- Memory: `free -m`
- Docker: `docker ps --format '{{.Names}} {{.Status}}'`

View File

@@ -0,0 +1,33 @@
---
name: weval-proposal-generator
description: Generate professional commercial proposals (devis) for WEVAL Consulting deals. Use when asked to create a proposal, quote, or commercial offer.
---
# WEVAL Proposal Generator Skill
## Purpose
Generate professional commercial proposals (devis) for WEVAL Consulting deals.
## Available APIs
- Get Deals: `GET https://weval-consulting.com/api/crm-api.php?action=deals`
- Generate Proposal: `POST https://weval-consulting.com/api/crm-api.php?action=proposal_generate` body: `{"deal_id":1}`
- PDF Generation: `POST https://weval-consulting.com/api/weval-ia-pdf.php` body: `{"message":"...","title":"..."}`
## Template Structure
1. Executive Summary (client name, project scope, WEVAL value proposition)
2. Understanding of Needs (client challenges, market context)
3. Proposed Solution (methodology, deliverables, WEVAL expertise)
4. Project Timeline (phases, milestones, Gantt-style)
5. Pricing Table (modules, unit prices, total)
6. Terms & Conditions (payment terms, SLA, confidentiality)
7. WEVAL References (similar projects delivered)
## Pricing Guidelines
- Consulting day rate: 5,000-8,000 MAD / 500-800 EUR
- ERP/SAP projects: 200,000-2,000,000 MAD
- Digital transformation: 100,000-500,000 MAD
- Pharma/Life Sciences: 50,000-200,000 MAD per brand
## Context
WEVAL Consulting — 200+ projects, 8 countries, 97% satisfaction rate.
Partners: SAP, Vistex, Huawei Cloud.