feat: Node Self-Healing, DAGI Audit, Agent Prompts, Infra Invariants
### Backend (city-service) - Node Registry + Self-Healing API (migration 039) - Improved get_all_nodes() with robust fallback for node_registry/node_cache - Agent Prompts Runtime API for DAGI Router integration - DAGI Router Audit endpoints (phantom/stale detection) - Node Agents API (Guardian/Steward) - Node metrics extended (CPU/GPU/RAM/Disk) ### Frontend (apps/web) - Node Directory with improved error handling - Node Cabinet with metrics cards - DAGI Router Card component - Node Metrics Card component - useDAGIAudit hook ### Scripts - check-invariants.py - deploy verification - node-bootstrap.sh - node self-registration - node-guardian-loop.py - continuous self-healing - dagi_agent_audit.py - DAGI audit utility ### Migrations - 034: Agent prompts seed - 035: Agent DAGI audit - 036: Node metrics extended - 037: Node agents complete - 038: Agent prompts full coverage - 039: Node registry self-healing ### Tests - test_infra_smoke.py - test_agent_prompts_runtime.py - test_dagi_router_api.py ### Documentation - DEPLOY_CHECKLIST_2024_11_30.md - Multiple TASK_PHASE docs
This commit is contained in:
431
migrations/037_node_agents_complete.sql
Normal file
431
migrations/037_node_agents_complete.sql
Normal file
@@ -0,0 +1,431 @@
|
||||
-- Migration 037: Node Agents Complete Setup
|
||||
-- Забезпечує існування всіх Node Agents з повними даними
|
||||
|
||||
-- ============================================================================
|
||||
-- 1. Створити/оновити Node Guardian агентів
|
||||
-- ============================================================================
|
||||
|
||||
-- NODE1 Guardian
|
||||
INSERT INTO agents (
|
||||
id,
|
||||
external_id,
|
||||
name,
|
||||
display_name,
|
||||
kind,
|
||||
status,
|
||||
node_id,
|
||||
is_public,
|
||||
is_node_guardian,
|
||||
public_slug,
|
||||
public_title,
|
||||
public_tagline,
|
||||
public_skills,
|
||||
avatar_url,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
'monitor-node1',
|
||||
'agent:monitor-node1',
|
||||
'Node Guardian NODE1',
|
||||
'Node Guardian (НОДА1)',
|
||||
'node_guardian',
|
||||
'online',
|
||||
'node-1-hetzner-gex44',
|
||||
true,
|
||||
true,
|
||||
'monitor-node1',
|
||||
'Guardian of NODE1',
|
||||
'Слідкую за інфраструктурою, метриками та безпекою продакшн-ноди.',
|
||||
ARRAY['monitoring', 'security', 'infrastructure', 'alerts'],
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
external_id = EXCLUDED.external_id,
|
||||
name = EXCLUDED.name,
|
||||
display_name = EXCLUDED.display_name,
|
||||
kind = EXCLUDED.kind,
|
||||
status = EXCLUDED.status,
|
||||
node_id = EXCLUDED.node_id,
|
||||
is_public = EXCLUDED.is_public,
|
||||
is_node_guardian = EXCLUDED.is_node_guardian,
|
||||
public_slug = EXCLUDED.public_slug,
|
||||
public_title = EXCLUDED.public_title,
|
||||
public_tagline = EXCLUDED.public_tagline,
|
||||
public_skills = EXCLUDED.public_skills,
|
||||
updated_at = NOW();
|
||||
|
||||
-- NODE2 Guardian
|
||||
INSERT INTO agents (
|
||||
id,
|
||||
external_id,
|
||||
name,
|
||||
display_name,
|
||||
kind,
|
||||
status,
|
||||
node_id,
|
||||
is_public,
|
||||
is_node_guardian,
|
||||
public_slug,
|
||||
public_title,
|
||||
public_tagline,
|
||||
public_skills,
|
||||
avatar_url,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
'monitor-node2',
|
||||
'agent:monitor-node2',
|
||||
'Node Guardian NODE2',
|
||||
'Node Guardian (НОДА2)',
|
||||
'node_guardian',
|
||||
'online',
|
||||
'node-2-macbook-m4max',
|
||||
true,
|
||||
true,
|
||||
'monitor-node2',
|
||||
'Guardian of NODE2',
|
||||
'Слідкую за інфраструктурою, метриками та AI-сервісами девелопмент-ноди.',
|
||||
ARRAY['monitoring', 'ai-services', 'development', 'metrics'],
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
external_id = EXCLUDED.external_id,
|
||||
name = EXCLUDED.name,
|
||||
display_name = EXCLUDED.display_name,
|
||||
kind = EXCLUDED.kind,
|
||||
status = EXCLUDED.status,
|
||||
node_id = EXCLUDED.node_id,
|
||||
is_public = EXCLUDED.is_public,
|
||||
is_node_guardian = EXCLUDED.is_node_guardian,
|
||||
public_slug = EXCLUDED.public_slug,
|
||||
public_title = EXCLUDED.public_title,
|
||||
public_tagline = EXCLUDED.public_tagline,
|
||||
public_skills = EXCLUDED.public_skills,
|
||||
updated_at = NOW();
|
||||
|
||||
-- ============================================================================
|
||||
-- 2. Створити/оновити Node Steward агентів
|
||||
-- ============================================================================
|
||||
|
||||
-- NODE1 Steward
|
||||
INSERT INTO agents (
|
||||
id,
|
||||
external_id,
|
||||
name,
|
||||
display_name,
|
||||
kind,
|
||||
status,
|
||||
node_id,
|
||||
is_public,
|
||||
is_node_steward,
|
||||
public_slug,
|
||||
public_title,
|
||||
public_tagline,
|
||||
public_skills,
|
||||
avatar_url,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
'node-steward-node1',
|
||||
'agent:node-steward-node1',
|
||||
'Node Steward NODE1',
|
||||
'Node Steward (НОДА1)',
|
||||
'node_steward',
|
||||
'online',
|
||||
'node-1-hetzner-gex44',
|
||||
true,
|
||||
true,
|
||||
'node-steward-node1',
|
||||
'Steward of NODE1',
|
||||
'Представляю ноду як громадянина міста, відповідаю за комунікацію та взаємодію.',
|
||||
ARRAY['communication', 'operations', 'coordination', 'onboarding'],
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
external_id = EXCLUDED.external_id,
|
||||
name = EXCLUDED.name,
|
||||
display_name = EXCLUDED.display_name,
|
||||
kind = EXCLUDED.kind,
|
||||
status = EXCLUDED.status,
|
||||
node_id = EXCLUDED.node_id,
|
||||
is_public = EXCLUDED.is_public,
|
||||
is_node_steward = EXCLUDED.is_node_steward,
|
||||
public_slug = EXCLUDED.public_slug,
|
||||
public_title = EXCLUDED.public_title,
|
||||
public_tagline = EXCLUDED.public_tagline,
|
||||
public_skills = EXCLUDED.public_skills,
|
||||
updated_at = NOW();
|
||||
|
||||
-- NODE2 Steward
|
||||
INSERT INTO agents (
|
||||
id,
|
||||
external_id,
|
||||
name,
|
||||
display_name,
|
||||
kind,
|
||||
status,
|
||||
node_id,
|
||||
is_public,
|
||||
is_node_steward,
|
||||
public_slug,
|
||||
public_title,
|
||||
public_tagline,
|
||||
public_skills,
|
||||
avatar_url,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
'node-steward-node2',
|
||||
'agent:node-steward-node2',
|
||||
'Node Steward NODE2',
|
||||
'Node Steward (НОДА2)',
|
||||
'node_steward',
|
||||
'online',
|
||||
'node-2-macbook-m4max',
|
||||
true,
|
||||
true,
|
||||
'node-steward-node2',
|
||||
'Steward of NODE2',
|
||||
'Представляю девелопмент-ноду, допомагаю з тестуванням та розробкою.',
|
||||
ARRAY['development', 'testing', 'coordination', 'support'],
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
external_id = EXCLUDED.external_id,
|
||||
name = EXCLUDED.name,
|
||||
display_name = EXCLUDED.display_name,
|
||||
kind = EXCLUDED.kind,
|
||||
status = EXCLUDED.status,
|
||||
node_id = EXCLUDED.node_id,
|
||||
is_public = EXCLUDED.is_public,
|
||||
is_node_steward = EXCLUDED.is_node_steward,
|
||||
public_slug = EXCLUDED.public_slug,
|
||||
public_title = EXCLUDED.public_title,
|
||||
public_tagline = EXCLUDED.public_tagline,
|
||||
public_skills = EXCLUDED.public_skills,
|
||||
updated_at = NOW();
|
||||
|
||||
-- ============================================================================
|
||||
-- 3. Оновити node_cache з правильними guardian/steward ID
|
||||
-- ============================================================================
|
||||
|
||||
UPDATE node_cache SET
|
||||
guardian_agent_id = 'monitor-node1',
|
||||
steward_agent_id = 'node-steward-node1'
|
||||
WHERE node_id = 'node-1-hetzner-gex44';
|
||||
|
||||
UPDATE node_cache SET
|
||||
guardian_agent_id = 'monitor-node2',
|
||||
steward_agent_id = 'node-steward-node2'
|
||||
WHERE node_id = 'node-2-macbook-m4max';
|
||||
|
||||
-- ============================================================================
|
||||
-- 4. System Prompts для Node Agents
|
||||
-- ============================================================================
|
||||
|
||||
-- NODE1 Guardian - Core Prompt
|
||||
INSERT INTO agent_prompts (agent_id, kind, content, version, created_by, note)
|
||||
VALUES (
|
||||
'monitor-node1',
|
||||
'core',
|
||||
$$Ти — Node Guardian для НОДА1 (Hetzner GEX44 Production).
|
||||
Твоя місія: забезпечувати стабільну роботу продакшн-інфраструктури DAARION.city.
|
||||
|
||||
Твої обов'язки:
|
||||
- Моніторинг GPU (RTX 4090), CPU, RAM, Disk
|
||||
- Відстеження стану сервісів (DAGI Router, Matrix Synapse, PostgreSQL)
|
||||
- Сповіщення про anomalії та потенційні проблеми
|
||||
- Координація з іншими агентами для швидкого реагування
|
||||
|
||||
При виявленні проблем:
|
||||
1. Класифікуй серйозність (critical/warning/info)
|
||||
2. Збери діагностичну інформацію
|
||||
3. Сповісти відповідальних через Matrix
|
||||
4. Запропонуй кроки для вирішення
|
||||
|
||||
Завжди пріоритизуй: стабільність > продуктивність > нові фічі.$$,
|
||||
1, 'SYSTEM_SEED', 'Initial core prompt for NODE1 Guardian'
|
||||
)
|
||||
ON CONFLICT (agent_id, kind, version) DO NOTHING;
|
||||
|
||||
-- NODE1 Guardian - Safety Prompt
|
||||
INSERT INTO agent_prompts (agent_id, kind, content, version, created_by, note)
|
||||
VALUES (
|
||||
'monitor-node1',
|
||||
'safety',
|
||||
$$Ніколи не виконуй деструктивні команди без підтвердження від адміністратора.
|
||||
Не розкривай чутливу інформацію (паролі, API ключі, внутрішні IP).
|
||||
При невизначеності — ескалюй до людини.
|
||||
Логуй всі критичні події для аудиту.$$,
|
||||
1, 'SYSTEM_SEED', 'Initial safety prompt for NODE1 Guardian'
|
||||
)
|
||||
ON CONFLICT (agent_id, kind, version) DO NOTHING;
|
||||
|
||||
-- NODE2 Guardian - Core Prompt
|
||||
INSERT INTO agent_prompts (agent_id, kind, content, version, created_by, note)
|
||||
VALUES (
|
||||
'monitor-node2',
|
||||
'core',
|
||||
$$Ти — Node Guardian для НОДА2 (MacBook Pro M4 Max Development).
|
||||
Твоя місія: підтримувати девелопмент-середовище для команди DAARION.
|
||||
|
||||
Твої обов'язки:
|
||||
- Моніторинг Apple M4 Max GPU (40GB unified memory)
|
||||
- Відстеження локальних AI моделей (Ollama, DAGI Router)
|
||||
- Оптимізація ресурсів для розробки та тестування
|
||||
- Синхронізація з NODE1 для deployment workflow
|
||||
|
||||
Особливості девелопмент-ноди:
|
||||
- Експериментальні фічі можуть бути нестабільними
|
||||
- Пріоритет на швидку ітерацію та зворотній зв'язок
|
||||
- Інтеграція з локальними IDE та інструментами розробника$$,
|
||||
1, 'SYSTEM_SEED', 'Initial core prompt for NODE2 Guardian'
|
||||
)
|
||||
ON CONFLICT (agent_id, kind, version) DO NOTHING;
|
||||
|
||||
-- NODE1 Steward - Core Prompt
|
||||
INSERT INTO agent_prompts (agent_id, kind, content, version, created_by, note)
|
||||
VALUES (
|
||||
'node-steward-node1',
|
||||
'core',
|
||||
$$Ти — Node Steward для НОДА1 (Production).
|
||||
Представляєш ноду як громадянина DAARION.city.
|
||||
|
||||
Твої обов'язки:
|
||||
- Комунікація з користувачами та іншими агентами
|
||||
- Онбординг нових учасників екосистеми
|
||||
- Координація операційної діяльності
|
||||
- Підтримка governance процесів на ноді
|
||||
|
||||
Стиль спілкування:
|
||||
- Дружній, але професійний
|
||||
- Прозорість щодо статусу ноди
|
||||
- Проактивне інформування про важливі події$$,
|
||||
1, 'SYSTEM_SEED', 'Initial core prompt for NODE1 Steward'
|
||||
)
|
||||
ON CONFLICT (agent_id, kind, version) DO NOTHING;
|
||||
|
||||
-- NODE2 Steward - Core Prompt
|
||||
INSERT INTO agent_prompts (agent_id, kind, content, version, created_by, note)
|
||||
VALUES (
|
||||
'node-steward-node2',
|
||||
'core',
|
||||
$$Ти — Node Steward для НОДА2 (Development).
|
||||
Допомагаєш розробникам та тестувальникам.
|
||||
|
||||
Твої обов'язки:
|
||||
- Підтримка команди розробників
|
||||
- Допомога з налаштуванням локального середовища
|
||||
- Координація тестування нових фіч
|
||||
- Збір зворотного зв'язку
|
||||
|
||||
Стиль спілкування:
|
||||
- Технічно грамотний
|
||||
- Терплячий до помилок (це dev!)
|
||||
- Заохочуй експерименти та інновації$$,
|
||||
1, 'SYSTEM_SEED', 'Initial core prompt for NODE2 Steward'
|
||||
)
|
||||
ON CONFLICT (agent_id, kind, version) DO NOTHING;
|
||||
|
||||
-- ============================================================================
|
||||
-- 5. Оновити DAGI статуси для node agents
|
||||
-- ============================================================================
|
||||
|
||||
UPDATE agents SET
|
||||
dagi_status = 'active',
|
||||
last_seen_at = NOW()
|
||||
WHERE id IN ('monitor-node1', 'monitor-node2', 'node-steward-node1', 'node-steward-node2');
|
||||
|
||||
-- ============================================================================
|
||||
-- 6. Забезпечити що всі агенти з router-config мають записи
|
||||
-- Синхронізуємо ключових агентів з router-config.yml
|
||||
-- ============================================================================
|
||||
|
||||
-- DAARWIZZ
|
||||
INSERT INTO agents (id, external_id, name, display_name, kind, status, is_public, public_slug, dagi_status, created_at, updated_at)
|
||||
VALUES ('agent-daarwizz', 'agent:daarwizz', 'DAARWIZZ', 'DAARWIZZ', 'orchestrator', 'online', true, 'daarwizz', 'active', NOW(), NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET dagi_status = 'active', updated_at = NOW();
|
||||
|
||||
-- DevTools
|
||||
INSERT INTO agents (id, external_id, name, display_name, kind, status, is_public, public_slug, dagi_status, created_at, updated_at)
|
||||
VALUES ('agent-devtools', 'agent:devtools', 'DevTools Agent', 'DevTools Agent', 'developer', 'online', true, 'devtools', 'active', NOW(), NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET dagi_status = 'active', updated_at = NOW();
|
||||
|
||||
-- GREENFOOD
|
||||
INSERT INTO agents (id, external_id, name, display_name, kind, status, is_public, public_slug, dagi_status, created_at, updated_at)
|
||||
VALUES ('agent-greenfood', 'agent:greenfood', 'GREENFOOD Assistant', 'GREENFOOD ERP', 'erp', 'online', true, 'greenfood', 'active', NOW(), NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET dagi_status = 'active', updated_at = NOW();
|
||||
|
||||
-- Helion
|
||||
INSERT INTO agents (id, external_id, name, display_name, kind, status, is_public, public_slug, dagi_status, created_at, updated_at)
|
||||
VALUES ('agent-helion', 'agent:helion', 'Helion', 'Helion', 'energy', 'online', true, 'helion', 'active', NOW(), NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET dagi_status = 'active', updated_at = NOW();
|
||||
|
||||
-- SOUL
|
||||
INSERT INTO agents (id, external_id, name, display_name, kind, status, is_public, public_slug, dagi_status, created_at, updated_at)
|
||||
VALUES ('agent-soul', 'agent:soul', 'SOUL', 'SOUL / Spirit', 'soul', 'online', true, 'soul', 'active', NOW(), NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET dagi_status = 'active', updated_at = NOW();
|
||||
|
||||
-- DRUID
|
||||
INSERT INTO agents (id, external_id, name, display_name, kind, status, is_public, public_slug, dagi_status, created_at, updated_at)
|
||||
VALUES ('agent-druid', 'agent:druid', 'DRUID', 'DRUID', 'science', 'online', true, 'druid', 'active', NOW(), NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET dagi_status = 'active', updated_at = NOW();
|
||||
|
||||
-- NUTRA
|
||||
INSERT INTO agents (id, external_id, name, display_name, kind, status, is_public, public_slug, dagi_status, created_at, updated_at)
|
||||
VALUES ('agent-nutra', 'agent:nutra', 'NUTRA', 'NUTRA', 'science', 'online', true, 'nutra', 'active', NOW(), NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET dagi_status = 'active', updated_at = NOW();
|
||||
|
||||
-- EONARCH
|
||||
INSERT INTO agents (id, external_id, name, display_name, kind, status, is_public, public_slug, dagi_status, created_at, updated_at)
|
||||
VALUES ('agent-eonarch', 'agent:eonarch', 'EONARCH', 'EONARCH', 'vision', 'online', true, 'eonarch', 'active', NOW(), NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET dagi_status = 'active', updated_at = NOW();
|
||||
|
||||
-- Yaromir
|
||||
INSERT INTO agents (id, external_id, name, display_name, kind, status, is_public, public_slug, dagi_status, created_at, updated_at)
|
||||
VALUES ('agent-yaromir', 'agent:yaromir', 'Yaromir', 'Yaromir CrewAI', 'orchestrator', 'online', true, 'yaromir', 'active', NOW(), NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET dagi_status = 'active', updated_at = NOW();
|
||||
|
||||
-- Monitor
|
||||
INSERT INTO agents (id, external_id, name, display_name, kind, status, is_public, public_slug, dagi_status, created_at, updated_at)
|
||||
VALUES ('agent-monitor', 'agent:monitor', 'Monitor Agent', 'Monitor Agent', 'infra_monitor', 'online', true, 'monitor', 'active', NOW(), NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET dagi_status = 'active', updated_at = NOW();
|
||||
|
||||
-- MicroDAO Orchestrator
|
||||
INSERT INTO agents (id, external_id, name, display_name, kind, status, is_public, public_slug, dagi_status, created_at, updated_at)
|
||||
VALUES ('agent-microdao-orchestrator', 'agent:microdao_orchestrator', 'MicroDAO Orchestrator', 'MicroDAO Orchestrator', 'orchestrator', 'online', true, 'microdao-orchestrator', 'active', NOW(), NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET dagi_status = 'active', updated_at = NOW();
|
||||
|
||||
-- CLAN
|
||||
INSERT INTO agents (id, external_id, name, display_name, kind, status, is_public, public_slug, dagi_status, created_at, updated_at)
|
||||
VALUES ('agent-clan', 'agent:clan', 'CLAN', 'CLAN', 'community', 'online', true, 'clan', 'active', NOW(), NOW())
|
||||
ON CONFLICT (id) DO UPDATE SET dagi_status = 'active', updated_at = NOW();
|
||||
|
||||
-- ============================================================================
|
||||
-- 7. Результат
|
||||
-- ============================================================================
|
||||
|
||||
SELECT 'Migration 037 completed: Node Agents complete setup' AS result;
|
||||
|
||||
-- Перевірка
|
||||
SELECT
|
||||
id,
|
||||
display_name,
|
||||
kind,
|
||||
node_id,
|
||||
public_slug,
|
||||
dagi_status
|
||||
FROM agents
|
||||
WHERE kind IN ('node_guardian', 'node_steward')
|
||||
OR id LIKE 'monitor-node%'
|
||||
OR id LIKE 'node-steward-%'
|
||||
ORDER BY id;
|
||||
|
||||
Reference in New Issue
Block a user