feat: додано Node Registry, GreenFood, Monitoring та Utils

This commit is contained in:
Apple
2025-11-21 00:35:41 -08:00
parent 31f3602047
commit e018b9ab68
74 changed files with 13948 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
# GREENFOOD Crew
ERP-система з 13 AI-агентами для крафтових виробників продуктів харчування.
## Швидкий старт
```python
from services.greenfood.crew.greenfood_agents import GREENFOOD_AGENTS
from services.greenfood.crew.greenfood_crews import GREENFOOD_CREWS, GREENFOOD_TASK_CREATORS
# 1. Використання окремого агента
from services.greenfood.crew.greenfood_agents import greenfood_assistant
response = greenfood_assistant.execute_task(
"Допоможи онбордити нового комітента 'Еко Мед Карпати'"
)
# 2. Використання crew для складного сценарію
vendor_data = {
"name": "Еко Мед Карпати",
"products": ["Гірський мед", "Мед з липи"],
"contact": "eco@example.com",
}
tasks = GREENFOOD_TASK_CREATORS["onboard_vendor"](vendor_data)
crew = GREENFOOD_CREWS["onboard_vendor"]
crew.tasks = tasks
result = crew.kickoff()
```
## Структура
```
services/greenfood/
├── README.md # Цей файл
└── crew/
├── __init__.py
├── greenfood_prompts.py # 13 системних промтів
├── greenfood_agents.py # 13 агентів crewAI
└── greenfood_crews.py # 4 crews для бізнес-сценаріїв
```
## 13 агентів
1. **GREENFOOD Assistant** - Головний оркестратор
2. **Product & Catalog Agent** - Каталог товарів
3. **Batch & Quality Agent** - Партії та якість
4. **Vendor Success Agent** - Успіх комітентів
5. **Warehouse Agent** - Склад
6. **Logistics & Delivery Agent** - Доставка
7. **Seller Agent** - Продажі
8. **Customer Care Agent** - Підтримка
9. **Finance & Pricing Agent** - Фінанси
10. **SMM & Campaigns Agent** - Маркетинг
11. **SEO & Web Agent** - SEO
12. **Analytics & BI Agent** - Аналітика
13. **Compliance & Audit Agent** - Аудит
## 4 готових crews
- **onboard_vendor_crew** - Онбординг виробників
- **fulfill_order_crew** - Виконання замовлень
- **monthly_settlement_crew** - Місячні звіряння
- **marketing_campaign_crew** - Маркетингові кампанії
## Інтеграція з DAGI Router
GREENFOOD Assistant доданий у `router-config.yml`:
```yaml
agents:
greenfood:
description: "GREENFOOD Assistant - ERP orchestrator"
default_llm: local_qwen3_8b
```
Виклик через Router:
```python
from router_client import send_to_router
response = await send_to_router({
"mode": "chat",
"agent": "greenfood",
"message": "Покажи статистику по комітенту 'Еко Мед'",
})
```
## Документація
Детальна документація: [docs/greenfood/greenfood_agents.md](/docs/greenfood/greenfood_agents.md)
## Залежності
```bash
pip install crewai>=0.28.0
```
## Статус
✅ Готово до розробки:
- Системні промти (13 агентів)
- Агенти crewAI (13 агентів)
- Crews (4 сценарії)
- Інтеграція з Router
- Документація
🔜 Наступні кроки:
- Додати інструменти (tools) для агентів
- Реалізувати API для доменів (ProductCatalogAPI, WarehouseAPI, etc.)
- Протестувати crews
- UI/UX для різних ролей
## Автор
DAARION.city Platform Team
Дата створення: 2025-11-18

View File

View File

View File

@@ -0,0 +1,262 @@
"""
GREENFOOD Crew - Оголошення 13 агентів
Кожен агент має чітку роль, мету та інструкції з системного промпту.
"""
from crewai import Agent
from typing import List
from .greenfood_prompts import (
GREENFOOD_ASSISTANT_PROMPT,
PRODUCT_CATALOG_PROMPT,
BATCH_QUALITY_PROMPT,
VENDOR_SUCCESS_PROMPT,
WAREHOUSE_PROMPT,
LOGISTICS_PROMPT,
SELLER_PROMPT,
CUSTOMER_CARE_PROMPT,
FINANCE_PRICING_PROMPT,
SMM_CAMPAIGNS_PROMPT,
SEO_WEB_PROMPT,
ANALYTICS_BI_PROMPT,
COMPLIANCE_AUDIT_PROMPT,
)
# 1. GREENFOOD Assistant - головний оркестратор
greenfood_assistant = Agent(
name="GREENFOOD Assistant",
role="Фронтовий оркестратор ERP GREENFOOD",
goal="Розуміти роль користувача, виявляти намір і делегувати задачі доменним агентам.",
backstory="Єдина точка входу до екосистеми GREENFOOD для комітентів, складів, логістів, маркетологів, бухгалтерів і покупців. Координує роботу 12 спеціалізованих агентів.",
verbose=True,
memory=True,
allow_delegation=True, # Може делегувати завдання іншим агентам
tools=[], # TODO: Додати інструменти для доступу до API, БД, контексту користувача
llm_config={"temperature": 0.7}, # Баланс між креативністю та точністю
)
greenfood_assistant.backstory = GREENFOOD_ASSISTANT_PROMPT
# 2. Product & Catalog Agent - менеджер каталогу товарів
product_catalog_agent = Agent(
name="Product & Catalog Agent",
role="Менеджер каталогу товарів",
goal="Створювати та підтримувати чистий і структурований каталог товарів GREENFOOD без дублів.",
backstory="Відповідає за карточки товарів, атрибути, медіа, структуру каталогу. Працює з комітентами для забезпечення повноти та якості даних про продукцію.",
verbose=True,
memory=True,
allow_delegation=False,
tools=[], # TODO: ProductCatalogAPI, ImageUploadTool, DuplicateDetectorTool
llm_config={"temperature": 0.3}, # Точність важливіша за креативність
)
product_catalog_agent.backstory = PRODUCT_CATALOG_PROMPT
# 3. Batch & Quality Agent - менеджер партій та якості
batch_quality_agent = Agent(
name="Batch & Quality Agent",
role="Менеджер партій та якості",
goal="Вести партії товарів, контролювати якість та строки придатності на всіх етапах.",
backstory="Забезпечує трасованість кожної партії товару від виробника до покупця. Стежить за якістю, строками придатності та інцидентами.",
verbose=True,
memory=True,
allow_delegation=False,
tools=[], # TODO: BatchTrackingAPI, QualityCheckTool, ExpiryAlertTool
llm_config={"temperature": 0.2}, # Максимальна точність для критичних даних
)
batch_quality_agent.backstory = BATCH_QUALITY_PROMPT
# 4. Vendor Success Agent - менеджер успіху комітентів
vendor_success_agent = Agent(
name="Vendor Success Agent",
role="Менеджер успіху комітентів (виробників)",
goal="Забезпечити швидкий onboarding та зростання виробників разом із GREENFOOD.",
backstory="Проактивний партнер для комітентів. Веде чеклісти onboarding'у, виявляє слабкі місця та пропонує конкретні кроки для покращення.",
verbose=True,
memory=True,
allow_delegation=False,
tools=[], # TODO: VendorOnboardingAPI, ChecklistTool, RecommendationEngine
llm_config={"temperature": 0.6}, # Баланс між аналізом та рекомендаціями
)
vendor_success_agent.backstory = VENDOR_SUCCESS_PROMPT
# 5. Warehouse Agent - начальник складу
warehouse_agent = Agent(
name="Warehouse Agent",
role="Начальник складу",
goal="Завжди мати коректні й актуальні залишки товарів на всіх складах і хабах.",
backstory="Керує залишками, рухом товарів, структурою складів та зон. Працює в тісній зв'язці з партіями та логістикою.",
verbose=True,
memory=True,
allow_delegation=False,
tools=[], # TODO: WarehouseAPI, InventoryTool, StockMovementTool, ZoneManagementTool
llm_config={"temperature": 0.2}, # Точність критична для залишків
)
warehouse_agent.backstory = WAREHOUSE_PROMPT
# 6. Logistics & Delivery Agent - логіст і диспетчер
logistics_delivery_agent = Agent(
name="Logistics & Delivery Agent",
role="Логіст і диспетчер доставок",
goal="Організовувати доставку замовлень з мінімальними затримками та витратами.",
backstory="Керує маршрутами, статусами доставок, інтеграціями з перевізниками. Тримає зв'язок між складом та покупцем.",
verbose=True,
memory=True,
allow_delegation=False,
tools=[], # TODO: LogisticsAPI, DeliveryTrackerTool, CourierIntegrationTool
llm_config={"temperature": 0.3}, # Точність для маршрутів та статусів
)
logistics_delivery_agent.backstory = LOGISTICS_PROMPT
# 7. Seller (Sales) Agent - менеджер з продажу
seller_agent = Agent(
name="Seller Agent",
role="Менеджер з продажу",
goal="Допомагати покупцям і B2B-клієнтам оформляти замовлення й підбирати оптимальний набір товарів.",
backstory="Розуміє контекст клієнта (роздріб/опт, новий/постійний), формує кошик, пропонує альтернативи та допомагає з оформленням.",
verbose=True,
memory=True,
allow_delegation=False,
tools=[], # TODO: SalesAPI, BasketTool, RecommendationEngine, PricingTool
llm_config={"temperature": 0.5}, # Баланс між аналізом та пропозиціями
)
seller_agent.backstory = SELLER_PROMPT
# 8. Customer Care Agent - служба підтримки
customer_care_agent = Agent(
name="Customer Care Agent",
role="Служба підтримки покупців",
goal="Швидко й коректно відповідати на питання клієнтів і вирішувати проблеми.",
backstory="Першалінія підтримки. Ідентифікує клієнта, його замовлення, відповідає на питання, фіксує рекламації та пропонує наступні кроки.",
verbose=True,
memory=True,
allow_delegation=False,
tools=[], # TODO: SupportAPI, OrderLookupTool, ComplaintTool, TicketingTool
llm_config={"temperature": 0.5}, # Емпатія та точність
)
customer_care_agent.backstory = CUSTOMER_CARE_PROMPT
# 9. Finance & Pricing Agent - бухгалтер і фінансовий стратег
finance_pricing_agent = Agent(
name="Finance & Pricing Agent",
role="Бухгалтер і фінансовий стратег",
goal="Забезпечити прозорі взаєморозрахунки і здорову економіку платформи, хабів і комітентів.",
backstory="Веде баланси, моделі ціноутворення, комісії, взаєморозрахунки. Працює з токенами (DAAR/DAARION) та фіатом.",
verbose=True,
memory=True,
allow_delegation=False,
tools=[], # TODO: FinanceAPI, PricingEngine, BalanceTool, PayoutCalculator
llm_config={"temperature": 0.1}, # Максимальна точність для фінансів
)
finance_pricing_agent.backstory = FINANCE_PRICING_PROMPT
# 10. SMM & Campaigns Agent - маркетолог та контент-агент
smm_campaigns_agent = Agent(
name="SMM & Campaigns Agent",
role="Маркетолог та контент-агент",
goal="Допомагати просувати комітентів, їхні товари та хаби через цифрові канали.",
backstory="Створює контент для соцмереж, розсилок, банерів. Працює з реальними даними про товари, запаси та акції.",
verbose=True,
memory=True,
allow_delegation=False,
tools=[], # TODO: ContentGeneratorTool, CampaignAPI, SocialMediaTool, ImageGeneratorTool
llm_config={"temperature": 0.8}, # Креативність для маркетингу
)
smm_campaigns_agent.backstory = SMM_CAMPAIGNS_PROMPT
# 11. SEO & Web Experience Agent - SEO-оптимізатор
seo_web_agent = Agent(
name="SEO & Web Experience Agent",
role="SEO-оптимізатор та веб-архітектор",
goal="Зробити сторінки товарів, комітентів та хабів видимими в пошуку і зрозумілими для користувачів.",
backstory="Оптимізує заголовки, описи, сніпети, URL, метадані. Покращує структуру контенту для SEO та UX.",
verbose=True,
memory=True,
allow_delegation=False,
tools=[], # TODO: SEOAnalyzerTool, MetaGeneratorTool, ContentStructureTool
llm_config={"temperature": 0.6}, # Баланс між SEO та читабельністю
)
seo_web_agent.backstory = SEO_WEB_PROMPT
# 12. Analytics & BI Agent - аналітик даних
analytics_bi_agent = Agent(
name="Analytics & BI Agent",
role="Аналітик даних (Business Intelligence)",
goal="Перетворювати дані продажів, складів, маркетингу й фінансів на actionable insights.",
backstory="Формує зрозумілі звіти, виявляє тренди, сезонність, аномалії. Пропонує варіанти дій із вказанням ризиків.",
verbose=True,
memory=True,
allow_delegation=False,
tools=[], # TODO: AnalyticsAPI, ReportGeneratorTool, TrendAnalyzerTool, ForecastingTool
llm_config={"temperature": 0.4}, # Точність для аналізу даних
)
analytics_bi_agent.backstory = ANALYTICS_BI_PROMPT
# 13. Compliance & Audit Agent - внутрішній аудитор
compliance_audit_agent = Agent(
name="Compliance & Audit Agent",
role="Внутрішній аудитор",
goal="Стежити за тим, щоб дії в системі відповідали політикам, правилам безпеки та бізнес-логіці.",
backstory="Аналізує логи подій, виявляє ризикові операції, формує попередження та рекомендації для адміністраторів.",
verbose=True,
memory=True,
allow_delegation=False,
tools=[], # TODO: AuditLogTool, RiskDetectorTool, ComplianceCheckerTool
llm_config={"temperature": 0.2}, # Об'єктивність та точність
)
compliance_audit_agent.backstory = COMPLIANCE_AUDIT_PROMPT
# Експорт всіх агентів
GREENFOOD_AGENTS: List[Agent] = [
greenfood_assistant, # 1. Головний оркестратор
product_catalog_agent, # 2. Каталог товарів
batch_quality_agent, # 3. Партії та якість
vendor_success_agent, # 4. Успіх комітентів
warehouse_agent, # 5. Склад
logistics_delivery_agent, # 6. Логістика
seller_agent, # 7. Продажі
customer_care_agent, # 8. Підтримка
finance_pricing_agent, # 9. Фінанси
smm_campaigns_agent, # 10. Маркетинг
seo_web_agent, # 11. SEO
analytics_bi_agent, # 12. Аналітика
compliance_audit_agent, # 13. Аудит
]
# Експорт агентів по категоріях для зручності
CORE_AGENTS = [greenfood_assistant]
OPERATIONS_AGENTS = [
product_catalog_agent,
batch_quality_agent,
warehouse_agent,
logistics_delivery_agent,
]
SALES_SUPPORT_AGENTS = [
seller_agent,
customer_care_agent,
]
FINANCE_AGENTS = [finance_pricing_agent]
MARKETING_AGENTS = [
smm_campaigns_agent,
seo_web_agent,
]
ANALYTICS_GOVERNANCE_AGENTS = [
analytics_bi_agent,
compliance_audit_agent,
]
SUCCESS_AGENTS = [vendor_success_agent]

View File

@@ -0,0 +1,378 @@
"""
GREENFOOD Crew - Оркестрація команд для бізнес-сценаріїв
Визначає crews (команди агентів) для виконання комплексних завдань:
- onboard_vendor_crew: Онбординг нових комітентів
- fulfill_order_crew: Виконання замовлень
- monthly_settlement_crew: Місячні звіряння та розрахунки
"""
from crewai import Crew, Task, Process
from typing import Dict, Any, List
from .greenfood_agents import (
greenfood_assistant,
product_catalog_agent,
batch_quality_agent,
vendor_success_agent,
warehouse_agent,
logistics_delivery_agent,
seller_agent,
customer_care_agent,
finance_pricing_agent,
smm_campaigns_agent,
seo_web_agent,
analytics_bi_agent,
compliance_audit_agent,
GREENFOOD_AGENTS,
)
# ========================================
# 1. Onboard Vendor Crew
# ========================================
def create_onboard_vendor_tasks(vendor_data: Dict[str, Any]) -> List[Task]:
"""
Створює завдання для онбордингу нового комітента (виробника).
Args:
vendor_data: Дані про комітента (назва, контакти, товари, склади)
Returns:
List[Task]: Список завдань для виконання
"""
tasks = [
Task(
description=f"""
Привітай комітента "{vendor_data.get('name', 'Новий комітент')}" та поясни процес онбордингу.
Збери всю необхідну інформацію: реквізити, контактні дані, опис виробництва.
Делегуй наступні завдання відповідним агентам.
""",
agent=greenfood_assistant,
expected_output="Стислий план онбордингу з чеклістом для комітента",
),
Task(
description=f"""
Допоможи комітенту створити карточки товарів в каталозі.
Товари для додавання: {vendor_data.get('products', [])}
Перевір повноту інформації: назва, опис, категорія, атрибути, фото.
""",
agent=product_catalog_agent,
expected_output="Список створених ID товарів з їх ключовими даними",
),
Task(
description="""
Налаштуй структуру складу для комітента та створи початкові партії товарів.
Встанови правила контролю якості та термінів придатності.
""",
agent=warehouse_agent,
expected_output="Конфігурація складу та список створених партій",
),
Task(
description="""
Налаштуй базові моделі ціноутворення та взаєморозрахунків.
Обговори з комітентом комісії, умови оплати, модель співпраці.
""",
agent=finance_pricing_agent,
expected_output="Фінансові налаштування: моделі ціноутворення, комісії, умови",
),
Task(
description="""
Складі чекліст успішного запуску та запланюй наступні кроки.
Визнач метрики успіху та терміни першого revenue.
""",
agent=vendor_success_agent,
expected_output="Чекліст з термінами, метрики успіху, план підтримки",
),
]
return tasks
onboard_vendor_crew = Crew(
agents=[
greenfood_assistant,
vendor_success_agent,
product_catalog_agent,
warehouse_agent,
finance_pricing_agent,
],
tasks=[], # Будуть додані динамічно через create_onboard_vendor_tasks()
process=Process.sequential, # Послідовне виконання завдань
verbose=True,
memory=True,
)
# ========================================
# 2. Fulfill Order Crew
# ========================================
def create_fulfill_order_tasks(order_data: Dict[str, Any]) -> List[Task]:
"""
Створює завдання для виконання замовлення.
Args:
order_data: Дані про замовлення (товари, кількість, адреса доставки)
Returns:
List[Task]: Список завдань для виконання
"""
tasks = [
Task(
description=f"""
Прийми замовлення від клієнта: {order_data.get('customer_name', 'Клієнт')}.
Товари: {order_data.get('items', [])}
Адреса доставки: {order_data.get('delivery_address', 'Не вказано')}
Перевір повноту даних та делегуй далі.
""",
agent=greenfood_assistant,
expected_output="Підтвердження прийняття замовлення з номером",
),
Task(
description="""
Сформуй кошик, перевір наявність товарів, запропонуй альтернативи якщо потрібно.
Розрахуй суму замовлення з урахуванням знижок та умов клієнта.
""",
agent=seller_agent,
expected_output="Підтверджений кошик з розрахунком суми",
),
Task(
description="""
Перевір наявність товарів на складі, зарезервуй необхідну кількість.
Підготуй замовлення до відвантаження: picking list, packing list.
""",
agent=warehouse_agent,
expected_output="Резервація товарів, списки picking/packing",
),
Task(
description="""
Створи маршрут доставки, вибери оптимального перевізника.
Сформуй документи доставки, трек-номер для клієнта.
""",
agent=logistics_delivery_agent,
expected_output="Маршрут доставки, трек-номер, очікувана дата доставки",
),
Task(
description="""
Проведи фінансові операції: фіксація продажу, розрахунок комісій.
Запланюй виплату комітенту згідно умов договору.
""",
agent=finance_pricing_agent,
expected_output="Фінансові проводки, розрахунок виплат комітенту",
),
Task(
description="""
Відправ клієнту підтвердження замовлення з детальною інформацією.
Надай контакти для зв'язку та трек-номер для відстеження.
""",
agent=customer_care_agent,
expected_output="Повідомлення клієнту з детальною інформацією про замовлення",
),
]
return tasks
fulfill_order_crew = Crew(
agents=[
greenfood_assistant,
seller_agent,
warehouse_agent,
logistics_delivery_agent,
customer_care_agent,
finance_pricing_agent,
],
tasks=[], # Будуть додані динамічно через create_fulfill_order_tasks()
process=Process.sequential,
verbose=True,
memory=True,
)
# ========================================
# 3. Monthly Settlement Crew
# ========================================
def create_monthly_settlement_tasks(period_data: Dict[str, Any]) -> List[Task]:
"""
Створює завдання для місячного звіряння та розрахунків.
Args:
period_data: Період звіряння (місяць, рік, комітенти)
Returns:
List[Task]: Список завдань для виконання
"""
tasks = [
Task(
description=f"""
Ініціюй процес місячного звіряння за період: {period_data.get('period', 'Поточний місяць')}.
Зібери дані від усіх доменних агентів для формування звітів.
""",
agent=greenfood_assistant,
expected_output="План звіряння з переліком необхідних даних",
),
Task(
description="""
Зформуй аналітичні звіти:
- Обороти по комітентах, товарах, хабах
- Тренди продажів, популярні товари, аномалії
- Рекомендації для оптимізації
""",
agent=analytics_bi_agent,
expected_output="Аналітичні звіти з insights та рекомендаціями",
),
Task(
description="""
Розрахуй фінансові показники:
- Виручка, комісії, чисті виплати комітентам
- Операційні витрати, прибуток платформи
- Баланси всіх учасників (комітенти, хаби, платформа)
Сформуй акти звіряння для комітентів.
""",
agent=finance_pricing_agent,
expected_output="Фінансові звіти, акти звіряння, розрахунок виплат",
),
Task(
description="""
Перевір дані на аномалії та ризикові операції:
- Великі списання, нетипові повернення
- Зміни цін, коригування балансів
- Відхилення від нормальних операцій
Сформуй звіт для адміністрації.
""",
agent=compliance_audit_agent,
expected_output="Audit звіт з виявленими ризиками та рекомендаціями",
),
Task(
description="""
На основі звітів сформуй персоналізовані рекомендації для кожного комітента:
- Що покращити в каталозі, запасах, цінах
- Які товари просунути, які зняти з асортименту
- Плани на наступний місяць
""",
agent=vendor_success_agent,
expected_output="Персоналізовані рекомендації для комітентів",
),
]
return tasks
monthly_settlement_crew = Crew(
agents=[
greenfood_assistant,
finance_pricing_agent,
analytics_bi_agent,
compliance_audit_agent,
vendor_success_agent,
],
tasks=[], # Будуть додані динамічно через create_monthly_settlement_tasks()
process=Process.sequential,
verbose=True,
memory=True,
)
# ========================================
# 4. Marketing Campaign Crew (додатковий)
# ========================================
def create_marketing_campaign_tasks(campaign_data: Dict[str, Any]) -> List[Task]:
"""
Створює завдання для запуску маркетингової кампанії.
Args:
campaign_data: Дані про кампанію (мета, товари, канали, бюджет)
Returns:
List[Task]: Список завдань для виконання
"""
tasks = [
Task(
description=f"""
Прийми запит на маркетингову кампанію:
Мета: {campaign_data.get('goal', 'Підвищення продажів')}
Товари: {campaign_data.get('products', [])}
Канали: {campaign_data.get('channels', ['соцмережі', 'розсилки'])}
""",
agent=greenfood_assistant,
expected_output="План кампанії з цілями та метриками",
),
Task(
description="""
Перевір наявність товарів на складах для промо.
Переконайся, що можемо виконати підвищений попит.
""",
agent=warehouse_agent,
expected_output="Підтвердження наявності товарів та можливості виконати попит",
),
Task(
description="""
Створи контент для соцмереж, розсилок та банерів.
Використай реальні дані про товари, переваги, акції.
""",
agent=smm_campaigns_agent,
expected_output="Готовий контент для різних каналів",
),
Task(
description="""
Оптимізуй посадкові сторінки товарів для SEO.
Покращи заголовки, описи, метадані для органічного трафіку.
""",
agent=seo_web_agent,
expected_output="Оптимізовані сторінки з покращеними SEO-елементами",
),
Task(
description="""
Налаштуй спеціальне ціноутворення для кампанії:
знижки, промокоди, умови акції.
""",
agent=finance_pricing_agent,
expected_output="Налаштування цін та промокодів для кампанії",
),
Task(
description="""
Підготуй KPI для відстеження ефективності кампанії:
охоплення, конверсії, продажі, ROI.
""",
agent=analytics_bi_agent,
expected_output="Налаштування відстеження та KPI для кампанії",
),
]
return tasks
marketing_campaign_crew = Crew(
agents=[
greenfood_assistant,
warehouse_agent,
smm_campaigns_agent,
seo_web_agent,
finance_pricing_agent,
analytics_bi_agent,
],
tasks=[], # Будуть додані динамічно через create_marketing_campaign_tasks()
process=Process.sequential,
verbose=True,
memory=True,
)
# ========================================
# Експорт crews
# ========================================
GREENFOOD_CREWS = {
"onboard_vendor": onboard_vendor_crew,
"fulfill_order": fulfill_order_crew,
"monthly_settlement": monthly_settlement_crew,
"marketing_campaign": marketing_campaign_crew,
}
GREENFOOD_TASK_CREATORS = {
"onboard_vendor": create_onboard_vendor_tasks,
"fulfill_order": create_fulfill_order_tasks,
"monthly_settlement": create_monthly_settlement_tasks,
"marketing_campaign": create_marketing_campaign_tasks,
}

View File

@@ -0,0 +1,228 @@
"""
GREENFOOD Crew - Системні промти для 13 агентів
Ці промти визначають роль, поведінку та правила роботи кожного агента
в екосистемі GREENFOOD ERP.
"""
GREENFOOD_ASSISTANT_PROMPT = """
Ти — GREENFOOD Assistant, фронтовий оркестратор ERP-системи для крафтових виробників, хабів та покупців.
Твоя місія: зрозуміти, хто з тобою говорить (комітент, менеджер складу, логіст, бухгалтер, маркетолог, покупець), виявити намір і делегувати завдання спеціалізованим агентам GREENFOOD.
Правила роботи:
* Спочатку уточнюй роль і контекст: хто ти, який кабінет/склад/хаб, про який період або товар йдеться.
* Перетворюй запит на чітку дію: створити товар, завести партію, оформити замовлення, перевірити баланс, запустити кампанію, сформувати звіт.
* Не вигадуй дані. Якщо чогось немає в системі — чесно кажи і пропонуй створити або уточнити.
* Не дублюй логіку доменних агентів: вони роблять роботу, ти — координуєш і пояснюєш результат користувачу людською мовою.
Взаємодія:
* Використовуй Product & Catalog, Batch & Quality, Warehouse, Logistics, Seller, Customer Care, Finance & Pricing, SMM & Campaigns, SEO & Web, Analytics & BI, Compliance & Audit.
* На виході завжди давай коротке резюме: що зроблено, які наступні кроки і де це побачити в інтерфейсі.
"""
PRODUCT_CATALOG_PROMPT = """
Ти — Product & Catalog Agent GREENFOOD, відповідальний за повний і чистий каталог товарів.
Твоя місія: створювати й підтримувати структуровані карточки товарів комітентів, без дублів і хаосу.
Правила роботи:
* Кожен товар має: назву, короткий і розширений опис, категорію, атрибути (вага, об'єм, склад, алергени, строк придатності, умови зберігання), фото/медіа, зв'язок з комітентом.
* Перевіряй, чи не дублює новий товар вже існуючий; пропонуй об'єднання або чіткі відмінності.
* Підтримуй технічні коди/артикули, що однозначно ідентифікують товар.
* Не змінюй ціни, склади або партії — це робота інших агентів.
Взаємодія:
* Працюєш через GREENFOOD Assistant, приймаєш структуровані запити типу "створи/онови товар", "покажи список товарів комітента".
* Повертаєш чіткі структури (id товару, ключові поля), готові для використання іншими агентами.
"""
BATCH_QUALITY_PROMPT = """
Ти — Batch & Quality Agent GREENFOOD, менеджер партій та якості.
Твоя місія: забезпечити трасованість кожної партії товару та контроль якості на всіх етапах.
Правила роботи:
* Партія завжди пов'язана з конкретним товаром, комітентом, датою виробництва, строком придатності, початковим складом/хабом.
* Веди статуси партій: створена, в дорозі, на складі, частково реалізована, повністю реалізована, прострочена, повернення, утилізація.
* Слідкуй за строками придатності; заздалегідь сигналізуй, якщо партія наближається до критичної дати.
* Фіксуй інциденти якості, рекламації, акти повернення.
Взаємодія:
* Приймаєш запити від GREENFOOD Assistant та Warehouse/Logistics на створення/оновлення партій.
* Не редагуєш ціни та фінанси, але додаєш потрібні дані для фінансових і аналітичних агентів.
"""
VENDOR_SUCCESS_PROMPT = """
Ти — Vendor Success Agent GREENFOOD, менеджер успіху комітентів (виробників).
Твоя місія: зробити так, щоб кожен виробник міг швидко запуститися, правильно налаштувати систему й зростати разом із GREENFOOD.
Правила роботи:
* Веди чеклісти для onboarding'у: реквізити, документи, товари, склади, базові налаштування.
* Виявляй слабкі місця: порожній каталог, відсутні фото, нерелевантні описи, нестабільні запаси.
* Проактивно пропонуй комітенту кроки для покращення: що додати, які товари просунути, як оптимізувати запаси.
* Комунікуй людською, але конкретною мовою, без загальної «мотивації».
Взаємодія:
* Працюєш через GREENFOOD Assistant, який передає контекст конкретного комітента.
* Використовуєш дані Product & Catalog, Warehouse, Analytics & BI, Finance & Pricing.
"""
WAREHOUSE_PROMPT = """
Ти — Warehouse Agent GREENFOOD, начальник складу.
Твоя місія: завжди мати коректні й актуальні залишки товарів на всіх складах і хабах.
Правила роботи:
* Будь-який рух товару (прихід, переміщення, відвантаження, повернення, списання) має бути відображений у залишках.
* Підтримуй структуру складу: зони, стелажі, полиці, температурні зони.
* Працюй у зв'язці з Batch & Quality: кожен запис по залишках повинен належати до конкретних партій.
* Сигналізуй про критично низькі або надмірні залишки (для Vendor Success і Finance & Pricing).
Взаємодія:
* Приймаєш структуровані запити від GREENFOOD Assistant та Logistics.
* Повертаєш зрозумілі підсумки: залишок по товару/партії/складу, історію руху.
"""
LOGISTICS_PROMPT = """
Ти — Logistics & Delivery Agent GREENFOOD, логіст і диспетчер доставок.
Твоя місія: організовувати доставку замовлень з мінімальними затримками та витратами.
Правила роботи:
* Кожне замовлення з фізичною доставкою має маршрут: зі складу/хабу до покупця або іншого хабу.
* Веди статуси доставки: створено, передано перевізнику, в дорозі, на точці видачі, доставлено, не вручено, повернення.
* Інтегруйся з зовнішніми службами через API (якщо доступно): формуй трек-номери, лінки для відстеження.
* Повідомляй Customer Care та покупця про зміни статусу.
Взаємодія:
* Працюєш із даними Warehouse, Seller, Customer Care.
* Не керуєш оплатами, але надаєш інформацію для фінансових розрахунків.
"""
SELLER_PROMPT = """
Ти — Seller Agent GREENFOOD, менеджер з продажу.
Твоя місія: допомагати покупцям і B2B-клієнтам оформляти замовлення й підбирати оптимальний набір товарів.
Правила роботи:
* Розумій контекст: це роздрібний клієнт, оптовий, постійний чи новий.
* Допомагай формувати кошик: товари, кількість, варіанти упаковок, альтернативи.
* Працюй з пропозиціями: апсели, крос-сели, набори, але без агресивного нав'язування.
* Переконайся, що склад і логістика підтверджують можливість виконання замовлення (через Warehouse та Logistics).
Взаємодія:
* Приймаєш запити від GREENFOOD Assistant (діалог з покупцем/комітентом).
* Використовуєш Product & Catalog, Warehouse, Finance & Pricing, Logistics.
"""
CUSTOMER_CARE_PROMPT = """
Ти — Customer Care Agent GREENFOOD, служба підтримки покупців.
Твоя місія: швидко й коректно відповідати на питання клієнтів і вирішувати проблеми.
Правила роботи:
* Ідентифікуй клієнта та його замовлення: номер, контакти, спосіб доставки.
* Даючи відповідь, спирайся на фактичні дані замовлень, складу та логістики.
* Фіксуй звернення, рекламації, причини повернень — це важливо для якості й аналітики.
* Завжди пропонуй наступний крок: очікувати доставку, перезбирати замовлення, опрацювати повернення тощо.
Взаємодія:
* Спілкуєшся через GREENFOOD Assistant, який передає контекст діалогу.
* Використовуєш Logistics, Warehouse, Batch & Quality, Finance & Pricing.
"""
FINANCE_PRICING_PROMPT = """
Ти — Finance & Pricing Agent GREENFOOD, бухгалтер і фінансовий стратег.
Твоя місія: забезпечити прозорі взаєморозрахунки і здорову економіку платформи, хабів і комітентів.
Правила роботи:
* Веди баланси: хто, скільки і за що отримав або має отримати; які комісії та витрати застосовано.
* Підтримуй моделі ціноутворення: опт, роздріб, спец-умови, акції, промокоди.
* Не змінюй історію без пояснення: будь-яка корекція повинна бути обґрунтована й зафіксована.
* Працюй із токенами (DAAR/DAARION) і фіатом згідно заданих правил; не вигадуй свої фінансові механізми.
Взаємодія:
* Отримуєш дані від Seller, Warehouse, Logistics, Batch & Quality, Analytics & BI.
* Повертаєш: розрахунки виплат, звіти по обороту, рентабельність, рекомендації по цінах.
"""
SMM_CAMPAIGNS_PROMPT = """
Ти — SMM & Campaigns Agent GREENFOOD, маркетолог та контент-агент.
Твоя місія: допомагати просувати комітентів, їхні товари та хаби через цифрові канали.
Правила роботи:
* Створюй тексти для соцмереж, розсилок і банерів, орієнтуючись на реальні дані про товари, запаси та акції.
* Не обіцяй того, чого немає фізично на складах. Перед промо перевіряй доступність товарів (через Warehouse/Batch & Quality).
* Пропонуй кампанії з чіткою метою: розпродати надлишки, запустити новий продукт, активізувати певний регіон чи хаб.
* Пиши зрозуміло, чесно, без маніпуляцій.
Взаємодія:
* Працюєш із Product & Catalog, Warehouse, Finance & Pricing, Analytics & BI, SEO & Web.
* Формуєш структури даних для планування й подальшої аналітики кампаній.
"""
SEO_WEB_PROMPT = """
Ти — SEO & Web Experience Agent GREENFOOD.
Твоя місія: зробити сторінки товарів, комітентів та хабів видимими в пошуку і зрозумілими для користувачів.
Правила роботи:
* Оптимізуй заголовки, описи, сніпети, URL та метадані сторінок.
* Використовуй дані з каталогу: реальні характеристики, категорії, переваги.
* Пропонуй покращення структури контенту (списки, блоки «питання-відповіді», блоки довіри).
* Не змінюй бізнес-логіку або ціни; твоя зона відповідальності — контент і структура.
Взаємодія:
* Працюєш з Product & Catalog, SMM & Campaigns, Analytics & BI.
* Повертаєш рекомендовані тексти та структури для впровадження у веб-інтерфейс.
"""
ANALYTICS_BI_PROMPT = """
Ти — Analytics & BI Agent GREENFOOD, аналітик даних.
Твоя місія: перетворювати дані продажів, складів, маркетингу й фінансів на конкретні actionable insights.
Правила роботи:
* Працюй із агрегованими даними: не намагайся бути «живою БД», а формуй зрозумілі звіти й висновки.
* Пояснюй в простих термінах: тренди, сезонність, аномалії, рекомендації для дій.
* Вказуй джерела: на які періоди, хаби, товари й ролі спираються твої висновки.
* Не приймай бізнес-рішення за людей; пропонуй варіанти дій із вказанням ризиків.
Взаємодія:
* Отримуєш дані від Seller, Warehouse, Logistics, Finance & Pricing, SMM/SEO.
* Повертаєш звіти для Vendor Success, GREENFOOD Assistant, адміністрації платформи.
"""
COMPLIANCE_AUDIT_PROMPT = """
Ти — Compliance & Audit Agent GREENFOOD, внутрішній аудитор.
Твоя місія: стежити за тим, щоб дії в системі відповідали політикам, правилам безпеки та здоровій бізнес-логіці.
Правила роботи:
* Аналізуй лог подій: зміни цін, великі списання, атипові повернення, нетипові маршрути доставки, вручну змінені баланси.
* Виявляй ризикові операції і формулюй короткі попередження та рекомендації.
* Не блокуєш дії напряму, але пропонуєш адміністраторам, що перевірити і де посилити контроль.
* Дотримуйся нейтрального, фактичного стилю без звинувачень.
Взаємодія:
* Споживаєш дані від усіх інших агентів через журнали подій.
* Повертаєш сигнали для GREENFOOD Assistant, адміністраторів платформи, Vendor Success і Finance.
"""

View File

@@ -0,0 +1,36 @@
FROM python:3.11-slim
# Metadata
LABEL maintainer="DAARION Team <admin@daarion.city>"
LABEL service="node-registry"
LABEL version="0.1.0-stub"
# Set working directory
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y \
curl \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements and install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application code
COPY app/ ./app/
# Create non-root user
RUN useradd -m -u 1000 noderegistry && \
chown -R noderegistry:noderegistry /app
USER noderegistry
# Expose port
EXPOSE 9205
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:9205/health || exit 1
# Run application
CMD ["python", "-m", "app.main"]

View File

@@ -0,0 +1,404 @@
# Node Registry Service
**Version:** 0.1.0-stub
**Status:** 🟡 Stub Implementation (Infrastructure Ready)
**Port:** 9205 (Internal only)
Central registry for DAGI network nodes (Node #1, Node #2, Node #N).
---
## Overview
Node Registry Service provides:
- **Node Registration** — Register new nodes in DAGI network
- **Heartbeat Tracking** — Monitor node health and availability
- **Node Discovery** — Query available nodes and their capabilities
- **Profile Management** — Store node profiles (LLM configs, services, capabilities)
---
## Current Implementation
### ✅ Completed (Infrastructure)
- FastAPI application with /health and /metrics endpoints
- Docker container configuration
- PostgreSQL database schema
- docker-compose integration
- Deployment script for Node #1
### 🚧 To Be Implemented (by Cursor)
- Full REST API endpoints
- Node registration logic
- Heartbeat mechanism
- Database integration (SQLAlchemy models)
- Prometheus metrics export
- Node discovery algorithms
---
## Quick Start
### Local Development
```bash
# Install dependencies
cd services/node-registry
pip install -r requirements.txt
# Set environment variables
export NODE_REGISTRY_DB_HOST=localhost
export NODE_REGISTRY_DB_PORT=5432
export NODE_REGISTRY_DB_NAME=node_registry
export NODE_REGISTRY_DB_USER=node_registry_user
export NODE_REGISTRY_DB_PASSWORD=your_password
export NODE_REGISTRY_HTTP_PORT=9205
export NODE_REGISTRY_ENV=development
export NODE_REGISTRY_LOG_LEVEL=debug
# Run service
python -m app.main
```
Service will start on http://localhost:9205
### Docker (Recommended)
```bash
# Build image
docker-compose build node-registry
# Start service
docker-compose up -d node-registry
# Check logs
docker-compose logs -f node-registry
# Check health
curl http://localhost:9205/health
```
### Deploy to Node #1 (Production)
```bash
# From Node #2 (MacBook)
./scripts/deploy-node-registry.sh
```
This will:
1. Initialize PostgreSQL database
2. Configure environment variables
3. Build Docker image
4. Start service
5. Configure firewall rules (internal access only)
6. Verify deployment
---
## API Endpoints
### Health & Monitoring
#### GET /health
Health check endpoint (used by Docker, Prometheus, etc.)
**Response:**
```json
{
"status": "healthy",
"service": "node-registry",
"version": "0.1.0-stub",
"environment": "production",
"uptime_seconds": 3600.5,
"timestamp": "2025-01-17T14:30:00Z",
"database": {
"connected": true,
"host": "postgres",
"port": 5432,
"database": "node_registry"
}
}
```
#### GET /metrics
Prometheus-compatible metrics endpoint
**Response:**
```json
{
"service": "node-registry",
"uptime_seconds": 3600.5,
"total_nodes": 2,
"active_nodes": 1,
"timestamp": "2025-01-17T14:30:00Z"
}
```
### Node Management (Stub - To Be Implemented)
#### POST /api/v1/nodes/register
Register a new node
**Status:** 501 Not Implemented (stub)
#### POST /api/v1/nodes/{node_id}/heartbeat
Update node heartbeat
**Status:** 501 Not Implemented (stub)
#### GET /api/v1/nodes
List all registered nodes
**Status:** 501 Not Implemented (stub)
#### GET /api/v1/nodes/{node_id}
Get specific node information
**Status:** 501 Not Implemented (stub)
---
## Database Schema
### Tables
#### `nodes`
Core node registry
| Column | Type | Description |
|--------|------|-------------|
| id | UUID | Primary key |
| node_id | VARCHAR(255) | Unique node identifier (e.g. node-1-hetzner-gex44) |
| node_name | VARCHAR(255) | Human-readable name |
| node_role | VARCHAR(50) | production, development, backup |
| node_type | VARCHAR(50) | router, gateway, worker, etc. |
| ip_address | INET | Public IP |
| local_ip | INET | Local network IP |
| hostname | VARCHAR(255) | DNS hostname |
| status | VARCHAR(50) | online, offline, maintenance, degraded |
| last_heartbeat | TIMESTAMP | Last heartbeat time |
| registered_at | TIMESTAMP | Registration timestamp |
| updated_at | TIMESTAMP | Last update timestamp |
| metadata | JSONB | Additional node metadata |
#### `node_profiles`
Node capabilities and configurations
| Column | Type | Description |
|--------|------|-------------|
| id | UUID | Primary key |
| node_id | UUID | Foreign key to nodes.id |
| profile_name | VARCHAR(255) | Profile identifier |
| profile_type | VARCHAR(50) | llm, service, capability |
| config | JSONB | Profile configuration |
| enabled | BOOLEAN | Profile active status |
| created_at | TIMESTAMP | Creation timestamp |
| updated_at | TIMESTAMP | Last update timestamp |
#### `heartbeat_log`
Historical heartbeat data
| Column | Type | Description |
|--------|------|-------------|
| id | UUID | Primary key |
| node_id | UUID | Foreign key to nodes.id |
| timestamp | TIMESTAMP | Heartbeat timestamp |
| status | VARCHAR(50) | Node status at heartbeat |
| metrics | JSONB | System metrics (CPU, RAM, etc.) |
---
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| NODE_REGISTRY_DB_HOST | postgres | PostgreSQL host |
| NODE_REGISTRY_DB_PORT | 5432 | PostgreSQL port |
| NODE_REGISTRY_DB_NAME | node_registry | Database name |
| NODE_REGISTRY_DB_USER | node_registry_user | Database user |
| NODE_REGISTRY_DB_PASSWORD | - | Database password (required) |
| NODE_REGISTRY_HTTP_PORT | 9205 | HTTP server port |
| NODE_REGISTRY_ENV | production | Environment (development/production) |
| NODE_REGISTRY_LOG_LEVEL | info | Log level (debug/info/warning/error) |
---
## Security
### Network Access
- **Port 9205:** Internal network only (Node #1, Node #2, DAGI nodes)
- **Public Access:** Blocked by firewall (UFW rules)
- **Authentication:** To be implemented (API keys, JWT)
### Firewall Rules (Node #1)
```bash
# Allow from local network
ufw allow from 192.168.1.0/24 to any port 9205 proto tcp
# Allow from Docker network
ufw allow from 172.16.0.0/12 to any port 9205 proto tcp
# Deny from external
ufw deny 9205/tcp
```
---
## Database Initialization
### Manual Setup
```bash
# On Node #1
ssh root@144.76.224.179
# Copy SQL script to container
docker cp services/node-registry/migrations/init_node_registry.sql dagi-postgres:/tmp/
# Run initialization
docker exec -i dagi-postgres psql -U postgres < /tmp/init_node_registry.sql
# Verify
docker exec dagi-postgres psql -U postgres -d node_registry -c "\dt"
```
### Via Deployment Script
The `deploy-node-registry.sh` script automatically:
1. Checks if database exists
2. Creates database and user if needed
3. Generates secure password
4. Saves password to .env
---
## Monitoring & Health
### Docker Health Check
```bash
docker inspect dagi-node-registry | grep -A 5 Health
```
### Prometheus Scraping
Add to prometheus.yml:
```yaml
scrape_configs:
- job_name: 'node-registry'
static_configs:
- targets: ['node-registry:9205']
scrape_interval: 30s
```
### Grafana Dashboard
Add panel with query:
```promql
up{job="node-registry"}
```
---
## Development
### Testing Locally
```bash
# Run with development settings
export NODE_REGISTRY_ENV=development
python -m app.main
# Access interactive API docs
open http://localhost:9205/docs
```
### Adding New Endpoints
1. Edit `app/main.py`
2. Add route with `@app.get()` or `@app.post()`
3. Add Pydantic models for request/response
4. Implement database logic (when ready)
5. Test via /docs or curl
6. Update this README
---
## Troubleshooting
### Service won't start
```bash
# Check logs
docker logs dagi-node-registry
# Check database connection
docker exec dagi-postgres pg_isready
# Check environment variables
docker exec dagi-node-registry env | grep NODE_REGISTRY
```
### Database connection error
```bash
# Verify database exists
docker exec dagi-postgres psql -U postgres -l | grep node_registry
# Verify user exists
docker exec dagi-postgres psql -U postgres -c "\du" | grep node_registry_user
# Test connection
docker exec dagi-postgres psql -U node_registry_user -d node_registry -c "SELECT 1"
```
### Port not accessible
```bash
# Check firewall rules
sudo ufw status | grep 9205
# Check if service is listening
netstat -tlnp | grep 9205
# Test from Node #2
curl http://144.76.224.179:9205/health
```
---
## Next Steps (for Cursor)
1. **Implement Database Layer**
- SQLAlchemy models for nodes, profiles, heartbeat
- Database connection pool
- Migration system (Alembic)
2. **Implement API Endpoints**
- Node registration with validation
- Heartbeat updates with metrics
- Node listing with filters
- Profile CRUD operations
3. **Add Authentication**
- API key-based auth
- JWT tokens for inter-node communication
- Rate limiting
4. **Add Monitoring**
- Prometheus metrics export
- Health check improvements
- Performance metrics
5. **Add Tests**
- Unit tests (pytest)
- Integration tests
- API endpoint tests
---
## Links
- [INFRASTRUCTURE.md](../../INFRASTRUCTURE.md) — Infrastructure overview
- [WARP.md](../../WARP.md) — Main developer guide
- [docker-compose.yml](../../docker-compose.yml) — Service configuration
---
**Last Updated:** 2025-01-17
**Maintained by:** Ivan Tytar & DAARION Team
**Status:** 🟡 Infrastructure Ready — Awaiting Cursor implementation

View File

@@ -0,0 +1,187 @@
#!/usr/bin/env python3
"""
Node Registry Service
Central registry for DAGI network nodes (Node #1, Node #2, Node #N)
This is a stub implementation - full API will be implemented by Cursor.
"""
import os
import time
from datetime import datetime
from typing import Dict, Any
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse
from pydantic import BaseModel
import uvicorn
# Environment configuration
HTTP_PORT = int(os.getenv("NODE_REGISTRY_HTTP_PORT", "9205"))
ENV = os.getenv("NODE_REGISTRY_ENV", "development")
LOG_LEVEL = os.getenv("NODE_REGISTRY_LOG_LEVEL", "info")
DB_HOST = os.getenv("NODE_REGISTRY_DB_HOST", "postgres")
DB_PORT = int(os.getenv("NODE_REGISTRY_DB_PORT", "5432"))
DB_NAME = os.getenv("NODE_REGISTRY_DB_NAME", "node_registry")
DB_USER = os.getenv("NODE_REGISTRY_DB_USER", "node_registry_user")
DB_PASSWORD = os.getenv("NODE_REGISTRY_DB_PASSWORD", "")
# Service metadata
SERVICE_NAME = "node-registry"
VERSION = "0.1.0-stub"
START_TIME = time.time()
app = FastAPI(
title="Node Registry Service",
description="Central registry for DAGI network nodes",
version=VERSION,
docs_url="/docs" if ENV == "development" else None,
redoc_url="/redoc" if ENV == "development" else None,
)
# Models (stub - will be expanded by Cursor)
class HealthResponse(BaseModel):
status: str
service: str
version: str
environment: str
uptime_seconds: float
timestamp: str
database: Dict[str, Any]
class MetricsResponse(BaseModel):
service: str
uptime_seconds: float
total_nodes: int
active_nodes: int
timestamp: str
# Health check endpoint
@app.get("/health", response_model=HealthResponse)
async def health_check():
"""
Health check endpoint for monitoring systems.
Returns service status, version, and database connectivity.
"""
uptime = time.time() - START_TIME
# TODO: Implement actual DB health check
db_status = {
"connected": False,
"host": DB_HOST,
"port": DB_PORT,
"database": DB_NAME,
"message": "Not implemented (stub)"
}
return HealthResponse(
status="healthy",
service=SERVICE_NAME,
version=VERSION,
environment=ENV,
uptime_seconds=uptime,
timestamp=datetime.utcnow().isoformat() + "Z",
database=db_status
)
# Metrics endpoint (Prometheus-compatible format will be added by Cursor)
@app.get("/metrics", response_model=MetricsResponse)
async def metrics():
"""
Metrics endpoint for Prometheus scraping.
TODO: Add proper Prometheus format (prometheus_client library)
"""
uptime = time.time() - START_TIME
# TODO: Implement actual metrics from database
return MetricsResponse(
service=SERVICE_NAME,
uptime_seconds=uptime,
total_nodes=0,
active_nodes=0,
timestamp=datetime.utcnow().isoformat() + "Z"
)
# Root endpoint
@app.get("/")
async def root():
"""Root endpoint - service information"""
return {
"service": SERVICE_NAME,
"version": VERSION,
"status": "running",
"environment": ENV,
"message": "Node Registry Service (stub implementation)",
"endpoints": {
"health": "/health",
"metrics": "/metrics",
"docs": "/docs" if ENV == "development" else "disabled",
}
}
# Stub API endpoints (to be implemented by Cursor)
@app.post("/api/v1/nodes/register")
async def register_node():
"""
Register a new node in the registry.
TODO: Implement by Cursor
"""
raise HTTPException(status_code=501, detail="Not implemented - stub endpoint")
@app.post("/api/v1/nodes/{node_id}/heartbeat")
async def update_heartbeat(node_id: str):
"""
Update node heartbeat (keep-alive).
TODO: Implement by Cursor
"""
raise HTTPException(status_code=501, detail="Not implemented - stub endpoint")
@app.get("/api/v1/nodes")
async def list_nodes():
"""
List all registered nodes.
TODO: Implement by Cursor
"""
raise HTTPException(status_code=501, detail="Not implemented - stub endpoint")
@app.get("/api/v1/nodes/{node_id}")
async def get_node(node_id: str):
"""
Get specific node information.
TODO: Implement by Cursor
"""
raise HTTPException(status_code=501, detail="Not implemented - stub endpoint")
if __name__ == "__main__":
print(f"🚀 Starting {SERVICE_NAME} v{VERSION}")
print(f"📊 Environment: {ENV}")
print(f"🔌 Port: {HTTP_PORT}")
print(f"🗄️ Database: {DB_USER}@{DB_HOST}:{DB_PORT}/{DB_NAME}")
print(f"📝 Log level: {LOG_LEVEL}")
print()
uvicorn.run(
app,
host="0.0.0.0",
port=HTTP_PORT,
log_level=LOG_LEVEL.lower(),
access_log=True,
)

View File

@@ -0,0 +1,112 @@
-- Node Registry Database Initialization Script
-- For DAGI Stack Node Registry Service
-- Version: 0.1.0
-- Date: 2025-01-17
-- Create database (run as postgres superuser)
CREATE DATABASE node_registry;
-- Connect to database
\c node_registry;
-- Create user with secure password
-- NOTE: Replace 'CHANGE_ME_STRONG_PASSWORD' with actual strong password
CREATE USER node_registry_user WITH ENCRYPTED PASSWORD 'CHANGE_ME_STRONG_PASSWORD';
-- Grant privileges
GRANT ALL PRIVILEGES ON DATABASE node_registry TO node_registry_user;
GRANT ALL ON SCHEMA public TO node_registry_user;
GRANT CREATE ON SCHEMA public TO node_registry_user;
-- Enable necessary extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
-- Create nodes table (basic schema - will be expanded by Cursor)
CREATE TABLE IF NOT EXISTS nodes (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
node_id VARCHAR(255) UNIQUE NOT NULL,
node_name VARCHAR(255) NOT NULL,
node_role VARCHAR(50) NOT NULL, -- 'production', 'development', 'backup'
node_type VARCHAR(50) NOT NULL, -- 'router', 'gateway', 'worker', etc.
ip_address INET,
local_ip INET,
hostname VARCHAR(255),
status VARCHAR(50) DEFAULT 'offline', -- 'online', 'offline', 'maintenance'
last_heartbeat TIMESTAMP WITH TIME ZONE,
registered_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
metadata JSONB DEFAULT '{}',
CONSTRAINT valid_status CHECK (status IN ('online', 'offline', 'maintenance', 'degraded'))
);
-- Create node profiles table
CREATE TABLE IF NOT EXISTS node_profiles (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
node_id UUID REFERENCES nodes(id) ON DELETE CASCADE,
profile_name VARCHAR(255) NOT NULL,
profile_type VARCHAR(50) NOT NULL, -- 'llm', 'service', 'capability'
config JSONB NOT NULL DEFAULT '{}',
enabled BOOLEAN DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
UNIQUE(node_id, profile_name)
);
-- Create heartbeat log table (for monitoring)
CREATE TABLE IF NOT EXISTS heartbeat_log (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
node_id UUID REFERENCES nodes(id) ON DELETE CASCADE,
timestamp TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
status VARCHAR(50),
metrics JSONB DEFAULT '{}'
);
-- Create indexes
CREATE INDEX idx_nodes_status ON nodes(status);
CREATE INDEX idx_nodes_last_heartbeat ON nodes(last_heartbeat DESC);
CREATE INDEX idx_nodes_node_id ON nodes(node_id);
CREATE INDEX idx_node_profiles_node_id ON node_profiles(node_id);
CREATE INDEX idx_node_profiles_enabled ON node_profiles(enabled);
CREATE INDEX idx_heartbeat_log_node_id ON heartbeat_log(node_id);
CREATE INDEX idx_heartbeat_log_timestamp ON heartbeat_log(timestamp DESC);
-- Create function to update updated_at timestamp
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create triggers
CREATE TRIGGER update_nodes_updated_at
BEFORE UPDATE ON nodes
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_node_profiles_updated_at
BEFORE UPDATE ON node_profiles
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
-- Grant table permissions to user
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO node_registry_user;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO node_registry_user;
-- Insert initial nodes (Node #1 and Node #2)
INSERT INTO nodes (node_id, node_name, node_role, node_type, ip_address, local_ip, hostname, status)
VALUES
('node-1-hetzner-gex44', 'Hetzner GEX44 Production', 'production', 'router', '144.76.224.179', NULL, 'gateway.daarion.city', 'offline'),
('node-2-macbook-m4max', 'MacBook Pro M4 Max', 'development', 'router', NULL, '192.168.1.244', 'MacBook-Pro.local', 'offline')
ON CONFLICT (node_id) DO NOTHING;
-- Success message
DO $$
BEGIN
RAISE NOTICE '✅ Node Registry database initialized successfully';
RAISE NOTICE '📊 Tables created: nodes, node_profiles, heartbeat_log';
RAISE NOTICE '👤 User created: node_registry_user';
RAISE NOTICE '⚠️ IMPORTANT: Change default password in production!';
END $$;

View File

@@ -0,0 +1,10 @@
fastapi==0.115.0
uvicorn[standard]==0.32.0
pydantic==2.12.4
pydantic-settings==2.7.0
httpx==0.28.1
asyncpg==0.30.0
sqlalchemy[asyncio]==2.0.36
alembic==1.14.0
python-json-logger==3.2.1
prometheus-client==0.21.0