- matrix-gateway: POST /internal/matrix/presence/online endpoint - usePresenceHeartbeat hook with activity tracking - Auto away after 5 min inactivity - Offline on page close/visibility change - Integrated in MatrixChatRoom component
338 lines
10 KiB
Markdown
338 lines
10 KiB
Markdown
# ✅ Виправлено: Агенти не відображалися в DAARION
|
||
|
||
**Дата:** 2025-11-23
|
||
**Проблема:** `http://localhost:8899/microdao/daarion` не показує агентів
|
||
**Статус:** ✅ ВИПРАВЛЕНО
|
||
|
||
---
|
||
|
||
## 🔍 Діагностика
|
||
|
||
### Проблема 1: API повертає HTML замість JSON
|
||
|
||
```bash
|
||
curl http://localhost:8899/api/microDAO/daarion
|
||
# Результат: HTML сторінка (Vite dev server)
|
||
```
|
||
|
||
**Причина:** Backend API не запущений або Vite проксі не налаштований.
|
||
|
||
### Проблема 2: Agent Cabinet Service не працює
|
||
|
||
```bash
|
||
curl http://localhost:8898/health
|
||
# Результат: Connection refused (exit code 7)
|
||
```
|
||
|
||
**Причина:** Сервіс на порту 8898 не запущений.
|
||
|
||
### Проблема 3: Агенти завантажуються, але не відображаються
|
||
|
||
**У коді:**
|
||
- `node1AgentsData` ✅ завантажується (7 агентів з NODE1)
|
||
- `orchestratorFromNode1` ✅ знаходить `agent-daarwizz`
|
||
- `agentsData` ❌ порожній (API не працює)
|
||
- `allAgents` ❌ не включає агенти з NODE1
|
||
|
||
---
|
||
|
||
## 🛠️ Виправлення
|
||
|
||
### 1. Додано error handling для `getAgents()`
|
||
|
||
**Файл:** `src/pages/MicroDaoCabinetPage.tsx` (рядки 110-123)
|
||
|
||
**Було:**
|
||
```typescript
|
||
const { data: agentsData } = useQuery({
|
||
queryKey: ['agents', microDaoId],
|
||
queryFn: async () => {
|
||
const result = await getAgents(microDaoId);
|
||
return result;
|
||
},
|
||
enabled: !!microDaoId,
|
||
staleTime: 60000,
|
||
gcTime: 300000,
|
||
refetchOnWindowFocus: false,
|
||
retry: false,
|
||
});
|
||
```
|
||
|
||
**Стало:**
|
||
```typescript
|
||
const { data: agentsData } = useQuery({
|
||
queryKey: ['agents', microDaoId],
|
||
queryFn: async () => {
|
||
try {
|
||
const result = await getAgents(microDaoId);
|
||
console.log('📥 Agents from API for', microDaoId, ':', result);
|
||
return result;
|
||
} catch (error) {
|
||
console.warn('⚠️ Failed to fetch agents from API, will use NODE1 fallback:', error);
|
||
// Повертаємо порожній список, щоб використати fallback з NODE1
|
||
return { items: [] };
|
||
}
|
||
},
|
||
enabled: !!microDaoId,
|
||
staleTime: 60000,
|
||
gcTime: 300000,
|
||
refetchOnWindowFocus: false,
|
||
retry: false,
|
||
});
|
||
```
|
||
|
||
**Ефект:** Тепер замість помилки повертається `{ items: [] }`, що дозволяє fallback логіці спрацювати.
|
||
|
||
---
|
||
|
||
### 2. Додано логування для orchestratorFromNode1
|
||
|
||
**Файл:** `src/pages/MicroDaoCabinetPage.tsx` (рядки 208-232)
|
||
|
||
**Додано:**
|
||
```typescript
|
||
const orchestratorFromNode1 = useMemo(() => {
|
||
if (!node1AgentsData?.items || !orchestratorAgentId) {
|
||
console.log('❌ No node1AgentsData or orchestratorAgentId:', {
|
||
hasData: !!node1AgentsData?.items,
|
||
orchestratorAgentId
|
||
});
|
||
return undefined;
|
||
}
|
||
|
||
const found = node1AgentsData.items.find(/* ... */);
|
||
|
||
console.log('🔍 Found orchestrator from NODE1:', found ? found.name : 'NOT FOUND');
|
||
return found;
|
||
}, [node1AgentsData, orchestratorAgentId, orchestratorMapping]);
|
||
```
|
||
|
||
**Ефект:** Діагностика в консолі браузера для відслідковування проблем.
|
||
|
||
---
|
||
|
||
### 3. Реалізовано fallback на агенти з NODE1
|
||
|
||
**Файл:** `src/pages/MicroDaoCabinetPage.tsx` (рядки 226-270)
|
||
|
||
**Було:**
|
||
```typescript
|
||
const allAgents = useMemo(() => {
|
||
const baseAgents = agentsData?.items || [];
|
||
if (!orchestratorFromNode1) return baseAgents;
|
||
|
||
// Перевіряємо чи оркестратор вже є в списку
|
||
const orchestratorExists = baseAgents.some((a: any) => a.id === orchestratorFromNode1.id);
|
||
if (orchestratorExists) return baseAgents;
|
||
|
||
return [
|
||
...baseAgents,
|
||
{
|
||
id: orchestratorFromNode1.id,
|
||
name: orchestratorFromNode1.name,
|
||
// ... тільки оркестратор
|
||
},
|
||
];
|
||
}, [agentsData?.items, orchestratorFromNode1]);
|
||
```
|
||
|
||
**Стало:**
|
||
```typescript
|
||
const allAgents = useMemo(() => {
|
||
const baseAgents = agentsData?.items || [];
|
||
|
||
console.log('🔄 Combining agents:', {
|
||
baseAgents: baseAgents.length,
|
||
hasOrchestrator: !!orchestratorFromNode1,
|
||
orchestratorName: orchestratorFromNode1?.name,
|
||
totalNode1Agents: node1AgentsData?.items?.length || 0,
|
||
});
|
||
|
||
// Якщо немає агентів з API, але є агенти з NODE1 - використовуємо їх
|
||
if (baseAgents.length === 0 && node1AgentsData?.items) {
|
||
console.log('✅ Using NODE1 agents as fallback');
|
||
return node1AgentsData.items.map((agent: Node1Agent) => ({
|
||
id: agent.id,
|
||
name: agent.name,
|
||
role: agent.role || 'Агент',
|
||
language: 'uk',
|
||
focus: agent.category || agent.department || 'Core',
|
||
enabled: agent.status === 'active' || agent.deployment_status?.deployed === true,
|
||
type: (agent.type || 'worker') as 'worker' | 'orchestrator',
|
||
node1Agent: agent,
|
||
}));
|
||
}
|
||
|
||
// Якщо є оркестратор, додаємо його до списку (якщо ще немає)
|
||
if (orchestratorFromNode1) {
|
||
const orchestratorExists = baseAgents.some((a: any) => a.id === orchestratorFromNode1.id);
|
||
if (!orchestratorExists) {
|
||
console.log('➕ Adding orchestrator to agents list:', orchestratorFromNode1.name);
|
||
return [
|
||
...baseAgents,
|
||
{
|
||
id: orchestratorFromNode1.id,
|
||
name: orchestratorFromNode1.name,
|
||
role: orchestratorFromNode1.role || 'Оркестратор мікроДАО',
|
||
language: 'uk',
|
||
focus: orchestratorFromNode1.category || 'Оркестрація',
|
||
enabled: orchestratorFromNode1.status === 'active' || orchestratorFromNode1.deployment_status?.deployed === true,
|
||
type: 'orchestrator' as const,
|
||
node1Agent: orchestratorFromNode1,
|
||
},
|
||
];
|
||
}
|
||
}
|
||
|
||
return baseAgents;
|
||
}, [agentsData?.items, orchestratorFromNode1, node1AgentsData?.items]);
|
||
```
|
||
|
||
**Ключові зміни:**
|
||
1. **Fallback на NODE1:** Якщо `baseAgents.length === 0`, використовуються всі агенти з `node1AgentsData`.
|
||
2. **Логування:** Додано console.log для діагностики.
|
||
3. **Dependency:** Додано `node1AgentsData?.items` до `useMemo` dependencies.
|
||
|
||
---
|
||
|
||
## 🎯 Результат
|
||
|
||
### Тепер на `http://localhost:8899/microdao/daarion`:
|
||
|
||
**Агенти (з NODE1):**
|
||
1. ✅ **agent-daarwizz** (Daarwizz) - Оркестратор DAARION
|
||
2. ✅ agent-devtools (DevTools Agent)
|
||
3. ✅ agent-microdao-orchestrator (MicroDAO Orchestrator)
|
||
4. ✅ agent-monitor-node1 (Monitor Agent)
|
||
5. ✅ agent-tokenomics-advisor (Tokenomics Advisor)
|
||
6. ✅ agent-greenfood-assistant (GREENFOOD Assistant)
|
||
7. ✅ agent-helion (Helion)
|
||
|
||
**Всього:** 7 агентів з NODE1
|
||
|
||
---
|
||
|
||
## 📊 Логування в консолі
|
||
|
||
При завантаженні сторінки `http://localhost:8899/microdao/daarion`:
|
||
|
||
```
|
||
📥 Agents from API for daarion-dao : { items: [] } // API не працює, fallback
|
||
❌ No node1AgentsData or orchestratorAgentId: { hasData: false, orchestratorAgentId: 'daarwizz' } // Перша ітерація
|
||
🔍 Found orchestrator from NODE1: Daarwizz // Знайдено оркестратора
|
||
🔄 Combining agents: { baseAgents: 0, hasOrchestrator: true, orchestratorName: 'Daarwizz', totalNode1Agents: 7 }
|
||
✅ Using NODE1 agents as fallback // Використано fallback
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 Тестування
|
||
|
||
### 1. Відкрити DAARION кабінет
|
||
|
||
```
|
||
http://localhost:8899/microdao/daarion
|
||
```
|
||
|
||
### 2. Перевірити консоль браузера (F12)
|
||
|
||
**Має бути:**
|
||
- `✅ Using NODE1 agents as fallback`
|
||
- Список з 7 агентів
|
||
|
||
### 3. Перевірити вкладку "Агенти"
|
||
|
||
**Має відображатися:**
|
||
- Daarwizz (оркестратор)
|
||
- DevTools Agent
|
||
- MicroDAO Orchestrator
|
||
- Monitor Agent (НОДА1)
|
||
- Tokenomics Advisor
|
||
- GREENFOOD Assistant
|
||
- Helion
|
||
|
||
---
|
||
|
||
## 🔧 Майбутні покращення
|
||
|
||
### 1. Запустити Agent Cabinet Service
|
||
|
||
**Порт:** 8898
|
||
**Сервіс:** `services/agent-cabinet-service/`
|
||
|
||
```bash
|
||
cd /Users/apple/github-projects/microdao-daarion/services/agent-cabinet-service
|
||
python -m venv venv
|
||
source venv/bin/activate
|
||
pip install -r requirements.txt
|
||
uvicorn app.main:app --host 0.0.0.0 --port 8898 --reload
|
||
```
|
||
|
||
**Після запуску:**
|
||
- API `/api/v1/agents?team_id=daarion-dao` повертатиме реальні дані
|
||
- Fallback на NODE1 не потрібен
|
||
|
||
### 2. Налаштувати Vite проксі
|
||
|
||
**Файл:** `vite.config.ts`
|
||
|
||
```typescript
|
||
export default defineConfig({
|
||
server: {
|
||
port: 8899,
|
||
proxy: {
|
||
'/api/v1': {
|
||
target: 'https://api.microdao.xyz',
|
||
changeOrigin: true,
|
||
secure: false,
|
||
},
|
||
'/api/agent': {
|
||
target: 'http://localhost:8898',
|
||
changeOrigin: true,
|
||
secure: false,
|
||
},
|
||
},
|
||
},
|
||
});
|
||
```
|
||
|
||
**Ефект:** Всі `/api/*` запити будуть проксуватися на відповідні backend сервіси.
|
||
|
||
### 3. Додати реальні метрики агентів
|
||
|
||
**Endpoint:** `http://localhost:8898/api/agent/{agentId}/metrics`
|
||
|
||
**Дані:**
|
||
- Uptime
|
||
- Total requests
|
||
- Avg response time
|
||
- Last active
|
||
|
||
### 4. Інтеграція з CrewAI
|
||
|
||
**Для Daarwizz:**
|
||
- Команда агентів (якщо є)
|
||
- Статус команди
|
||
- Останні виконання завдань
|
||
|
||
---
|
||
|
||
## ✅ Чекліст
|
||
|
||
- [x] Додано error handling для `getAgents()`
|
||
- [x] Додано логування для `orchestratorFromNode1`
|
||
- [x] Реалізовано fallback на агенти з NODE1
|
||
- [x] Додано `node1AgentsData?.items` до `useMemo` dependencies
|
||
- [x] Протестовано на `http://localhost:8899/microdao/daarion`
|
||
- [ ] Запущено Agent Cabinet Service (порт 8898)
|
||
- [ ] Налаштовано Vite проксі
|
||
- [ ] Додано реальні метрики агентів
|
||
- [ ] Інтеграція з CrewAI для команд
|
||
|
||
---
|
||
|
||
**СТАТУС:** ✅ ГОТОВО (fallback працює)
|
||
**Тестуйте:** `http://localhost:8899/microdao/daarion`
|
||
**Консоль:** F12 → Console → Шукайте `✅ Using NODE1 agents as fallback`
|
||
|