### 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
432 lines
17 KiB
SQL
432 lines
17 KiB
SQL
-- 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;
|
||
|