feat: Add presence heartbeat for Matrix online status
- 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
This commit is contained in:
443
docs/services/AGENTS_SERVICE_SPEC.md
Normal file
443
docs/services/AGENTS_SERVICE_SPEC.md
Normal file
@@ -0,0 +1,443 @@
|
||||
# AGENTS SERVICE SPEC (PORT 7002)
|
||||
# Version: 1.0.0
|
||||
|
||||
---
|
||||
|
||||
## 0. PURPOSE
|
||||
|
||||
`Agents Service` — це центральний сервіс текстових агентів DAGI:
|
||||
|
||||
- надає API для виклику Helion, Helix, Metamorph та інших текстових агентів;
|
||||
- інтегрується з DAGI Router / ProjectBus / Mesh Directory;
|
||||
- застосовує:
|
||||
- Agent Registry,
|
||||
- Context Router,
|
||||
- Silence Policy,
|
||||
- Throttling,
|
||||
- TeamDefinition/ProjectBus контекст.
|
||||
|
||||
Це логічний "Runtime осередок" для текстової частини DAGI.
|
||||
|
||||
Порт за замовчуванням (NODE1/NODE2): **7002**.
|
||||
|
||||
---
|
||||
|
||||
## 1. HIGH-LEVEL ARCHITECTURE
|
||||
|
||||
```text
|
||||
[ Gateway (Telegram/Web/Matrix/...) ]
|
||||
↓
|
||||
[ DAGI Router (gateway.daarion.city) ]
|
||||
↓
|
||||
[ Agents Service (7002) ]
|
||||
↓
|
||||
[ LLM Providers / Swapper / DAGI Mesh ]
|
||||
```
|
||||
|
||||
Agents Service отримує **RouterEvent-like** запити від DAGI Router (або внутрішніх сервісів) та:
|
||||
|
||||
1. Визначає, які агенти доступні (через AgentRegistry + Mesh Directory + TeamDefinition).
|
||||
2. Обирає найвідповіднішого/декількох (Context Router).
|
||||
3. Перевіряє Silence Policy.
|
||||
4. Застосовує throttling.
|
||||
5. Викликає відповідний LLM / backend агента.
|
||||
6. Повертає відповідь + metadata.
|
||||
|
||||
---
|
||||
|
||||
## 2. DEPENDENCIES
|
||||
|
||||
### 2.1. Внутрішні модулі
|
||||
|
||||
Agents Service використовує:
|
||||
|
||||
* `configs/AGENT_REGISTRY.yaml`
|
||||
* `configs/AGENT_REGISTRY_SCHEMA.yaml`
|
||||
* `services/agent_registry_loader.py`
|
||||
* `services/agent_context_router.py`
|
||||
* `services/agent_silence_policy.py`
|
||||
* `services/agent_throttle.py`
|
||||
* `services/agent_mesh_directory.py`
|
||||
* `configs/team_definition.yaml`
|
||||
* `configs/project_bus_config.yaml`
|
||||
|
||||
### 2.2. Зовнішні сервіси
|
||||
|
||||
* **LLM Provider / Swapper Service** (NODE1/NODE2)
|
||||
* **NATS** (або інший event-bus) для:
|
||||
|
||||
* ProjectBus,
|
||||
* Mesh Directory,
|
||||
* M2M-комунікації між агентами.
|
||||
* **PostgreSQL / Redis** (опційно) для:
|
||||
|
||||
* кешу відповідей,
|
||||
* logging / traces.
|
||||
|
||||
---
|
||||
|
||||
## 3. CONFIGURATION
|
||||
|
||||
ENV-змінні:
|
||||
|
||||
```env
|
||||
AGENTS_SERVICE_PORT=7002
|
||||
|
||||
AGENT_REGISTRY_PATH=configs/AGENT_REGISTRY.yaml
|
||||
AGENT_REGISTRY_SCHEMA_PATH=configs/AGENT_REGISTRY_SCHEMA.yaml
|
||||
|
||||
TEAM_DEFINITION_PATH=configs/team_definition.yaml
|
||||
PROJECT_BUS_CONFIG_PATH=configs/project_bus_config.yaml
|
||||
|
||||
MESH_DIRECTORY_MODE=inprocess # "inprocess" | "nats" | "http"
|
||||
MESH_DIRECTORY_NATS_SUBJECT_BASE=agent.directory
|
||||
|
||||
LLM_PROVIDER_BASE_URL=http://localhost:8890 # або інший super-service/swapper
|
||||
|
||||
AGENT_THROTTLE_LIMIT_PER_MINUTE=3
|
||||
AGENT_THROTTLE_WINDOW_SECONDS=60
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. PUBLIC API (HTTP)
|
||||
|
||||
### 4.1. `POST /agents/invoke`
|
||||
|
||||
Основний endpoint для DAGI Router та внутрішніх сервісів.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"event": {
|
||||
"event_id": "tg:123",
|
||||
"source": "telegram",
|
||||
"chat": { "id": "123", "type": "group" },
|
||||
"user": { "id": "user1", "username": "alex" },
|
||||
"team_id": "team-daariandao-core",
|
||||
"project_id": "proj-daariandao",
|
||||
"text": "helix, перевір api",
|
||||
"attachments": {
|
||||
"images": [],
|
||||
"docs": [],
|
||||
"audio": [],
|
||||
"geo": [],
|
||||
"tables": []
|
||||
},
|
||||
"flags": {
|
||||
"command": null,
|
||||
"reply_to": null,
|
||||
"confidential_mode": "public"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"force_agent_id": null, // якщо заповнено, обійти context router
|
||||
"allow_panel_mode": true, // дозволити кільком агентам відповісти
|
||||
"max_agents": 2 // верхня межа для panel-режиму
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response (успішний сценарій):**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"replies": [
|
||||
{
|
||||
"agent_id": "ag_helix",
|
||||
"text": "Ось аналіз API ...",
|
||||
"meta": {
|
||||
"model": "HELIX_ENGINEER_MODEL",
|
||||
"tokens_in": 123,
|
||||
"tokens_out": 256,
|
||||
"latency_ms": 900
|
||||
}
|
||||
}
|
||||
],
|
||||
"context": {
|
||||
"project_id": "proj-daariandao",
|
||||
"team_id": "team-daariandao-core",
|
||||
"reply_mode": "panel"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response (ніхто не має відповідати):**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "silent",
|
||||
"reason": "no_agent_or_policy",
|
||||
"context": {
|
||||
"project_id": "proj-daariandao",
|
||||
"team_id": "team-daariandao-core"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response (throttling):**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "throttled",
|
||||
"reason": "rate_limit",
|
||||
"agent_id": "ag_helion"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.2. `GET /agents/registry`
|
||||
|
||||
Повертає список агентів (тільки для адміністраторів / системних агентів):
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": [
|
||||
{
|
||||
"agent_id": "ag_helion",
|
||||
"name": "Helion",
|
||||
"role": "assistant",
|
||||
"priority": 5,
|
||||
"model": "HELION_TEXT_MODEL",
|
||||
"skills": ["допоможи", "поясни"],
|
||||
"modalities": ["text"],
|
||||
"description": "Головний асистент DAARION."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.3. `GET /agents/instances`
|
||||
|
||||
Проксі до Mesh Directory (видно інстанси):
|
||||
|
||||
```json
|
||||
{
|
||||
"instances": [
|
||||
{
|
||||
"agent_id": "ag_helion",
|
||||
"instance_id": "ag_helion@noda1-01",
|
||||
"node_id": "NODA1",
|
||||
"status": "online",
|
||||
"project_ids": ["proj-daariandao"],
|
||||
"microdao_id": "microdao-root",
|
||||
"last_seen": 1732450200.123
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. INTERNAL LOGIC
|
||||
|
||||
### 5.1. Pipeline для `/agents/invoke`
|
||||
|
||||
Покроковий алгоритм:
|
||||
|
||||
1. **Parse event**
|
||||
|
||||
* прийняти `event` (RouterEvent-сумісний payload),
|
||||
* витягнути `project_id`, `team_id`, `chat.id`.
|
||||
|
||||
2. **Load TeamDefinition**
|
||||
|
||||
* знайти команду по `team_id` (або по `project_id` → команди, які працюють у цьому проекті),
|
||||
* зчитати `reply_mode`:
|
||||
|
||||
* `single` / `panel` / `silent`,
|
||||
* `max_agents_per_message`.
|
||||
|
||||
3. **Load AgentRegistry & MeshDirectory**
|
||||
|
||||
* завантажити список агентів із registry,
|
||||
* для кожного, хто в TeamDefinition:
|
||||
|
||||
* перевірити, чи є онлайн інстанси (Mesh Directory).
|
||||
|
||||
4. **Context Router**
|
||||
|
||||
* побудувати `AgentDescriptor` для кожного доступного агента (з skills, priority),
|
||||
* викликати `select_best_agent(event, descriptors)`:
|
||||
|
||||
* для `single`: обрати 1,
|
||||
* для `panel`: обрати до `max_agents_per_message`,
|
||||
* для `silent`: можна одразу повернути `status: silent`.
|
||||
|
||||
5. **Silence Policy** (per-agent)
|
||||
Для кожного кандидата:
|
||||
|
||||
* `should_agent_reply(agent_id, event)`:
|
||||
|
||||
* прямі згадки,
|
||||
* команди,
|
||||
* приватні чати,
|
||||
* контекстна релевантність.
|
||||
|
||||
Якщо жоден не проходить → `status: silent`.
|
||||
|
||||
6. **Throttling** (per-agent, per-chat)
|
||||
Для кожного, хто пройшов silence policy:
|
||||
|
||||
* `throttle.can_reply(agent_id, chat_id)`:
|
||||
|
||||
* якщо ні → позначити `throttled`,
|
||||
* якщо хоча б один агент може відповідати → продовжуємо.
|
||||
|
||||
7. **Invoke agents (LLM Provider)**
|
||||
Для кожного дозволеного агента:
|
||||
|
||||
* сформувати system prompt (на основі `AGENT_REGISTRY`, ролі, skills),
|
||||
* сформувати user/context prompt (із події),
|
||||
* відправити в LLM Provider / Swapper Service:
|
||||
|
||||
* `POST /llm/invoke` (або NATS subject `llm.invoke`).
|
||||
|
||||
8. **Aggregate response**
|
||||
|
||||
* зібрати `replies` (до N агентів),
|
||||
* зібрати `meta` (latency, tokens),
|
||||
* повернути у DAGI Router HTTP-відповідь.
|
||||
|
||||
---
|
||||
|
||||
## 6. INTEGRATION WITH DAGI ROUTER
|
||||
|
||||
### 6.1. З боку DAGI Router
|
||||
|
||||
При текстовій гілці (без мультимодальності):
|
||||
|
||||
```python
|
||||
# dagi_router.py (схематично)
|
||||
resp = http.post("http://agents-service:7002/agents/invoke", json={
|
||||
"event": router_event_dict,
|
||||
"options": {
|
||||
"force_agent_id": None,
|
||||
"allow_panel_mode": True,
|
||||
"max_agents": 2
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Router далі:
|
||||
|
||||
* бере `resp["replies"]`,
|
||||
* конвертує в повідомлення для Gateway (Telegram/Web/Matrix),
|
||||
* застосовує свої policy (наприклад, фільтрацію ненормативу, якщо треба).
|
||||
|
||||
---
|
||||
|
||||
## 7. NATS / PROJECT BUS INTEGRATION
|
||||
|
||||
Agents Service також:
|
||||
|
||||
1. Слухає ProjectBus:
|
||||
|
||||
* `project.<project_id>.chat.mixed` (через DAGI Router),
|
||||
* `project.<project_id>.tasks` (можна робити автоматичну обробку задач).
|
||||
|
||||
2. Може публікувати події:
|
||||
|
||||
* `project.<project_id>.agents` (наприклад, "Helix взяв task t123"),
|
||||
* `project.<project_id>.m2m.*` (M2M/R2D2 комунікація).
|
||||
|
||||
Це дозволяє:
|
||||
|
||||
* агентам працювати в командах,
|
||||
* не тільки як chatbot, а як учасники mesh-процесів.
|
||||
|
||||
---
|
||||
|
||||
## 8. HEALTHCHECK & METRICS
|
||||
|
||||
### 8.1. Healthcheck
|
||||
|
||||
`GET /healthz`:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"registry_loaded": true,
|
||||
"mesh_directory_mode": "inprocess",
|
||||
"uptime_seconds": 12345
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2. Prometheus метрики
|
||||
|
||||
* `agents_invocations_total{agent_id, project_id, status}`
|
||||
* `agents_throttled_total{agent_id}`
|
||||
* `agents_silent_decisions_total{reason}`
|
||||
* `agents_llm_latency_ms_bucket{agent_id, le=...}`
|
||||
|
||||
---
|
||||
|
||||
## 9. LOGGING
|
||||
|
||||
Кожен виклик `/agents/invoke` логувати:
|
||||
|
||||
* `event_id`, `source`, `chat.id`, `project_id`, `team_id`,
|
||||
* кандидатів агентів + scores (debug-level),
|
||||
* остаточно обраних агентів,
|
||||
* статус: `ok` / `silent` / `throttled` / `error`,
|
||||
* latency LLM.
|
||||
|
||||
Формат: JSON-лог для подальшого аналізу (ELK / Loki / Grafana).
|
||||
|
||||
---
|
||||
|
||||
## 10. TEST PLAN (SHORT)
|
||||
|
||||
Unit-тести (pytest):
|
||||
|
||||
1. `test_single_agent_selection()`
|
||||
|
||||
* один агент у команді, простий текст, немає throttling → відповідає.
|
||||
|
||||
2. `test_panel_mode_two_agents()`
|
||||
|
||||
* `reply_mode: panel`, `max_agents_per_message: 2`,
|
||||
* питання, релевантне Helix і Guardian → відповідають двоє.
|
||||
|
||||
3. `test_silence_policy_mentions()`
|
||||
|
||||
* повідомлення без згадок і без ключових слів → `status: silent`.
|
||||
|
||||
4. `test_throttling_per_agent()`
|
||||
|
||||
* 4 виклики поспіль у межах 60 сек,
|
||||
* `limit_per_minute=3`,
|
||||
* 4-й → `status: throttled`.
|
||||
|
||||
5. `test_team_definition_loading()`
|
||||
|
||||
* агрегація команд з `team_definition.yaml`,
|
||||
* мапінг на project_id.
|
||||
|
||||
---
|
||||
|
||||
## 11. SUMMARY
|
||||
|
||||
Agents Service (7002) — це:
|
||||
|
||||
* офіційний текстовий runtime DAGI,
|
||||
* точка входу для Helion/Helix/Metamorph та інших текстових агентів,
|
||||
* шар, який:
|
||||
|
||||
* "бачить" всю конфігурацію агентів (Registry),
|
||||
* "бачить" живі інстанси (Mesh Directory),
|
||||
* враховує TeamDefinition/ProjectBus,
|
||||
* контролює поведінку агентів у чатах (silence/panel/throttle).
|
||||
|
||||
Після реалізації цього сервісу DAGI Router зможе:
|
||||
|
||||
* делегувати всю текстову логіку в єдиний, стандартизований компонент,
|
||||
* який легко масштабувати між НОДА1/НОДА2 і далі.
|
||||
|
||||
382
docs/services/CITY_SERVICE_SPEC.md
Normal file
382
docs/services/CITY_SERVICE_SPEC.md
Normal file
@@ -0,0 +1,382 @@
|
||||
# CITY SERVICE SPEC (PORT 7001)
|
||||
# Version: 1.0.0
|
||||
|
||||
---
|
||||
|
||||
## 0. PURPOSE
|
||||
|
||||
`City Service` — геопросторовий та соціальний шар DAARION.city.
|
||||
|
||||
Цей сервіс забезпечує:
|
||||
|
||||
1. **Living Map** — стан міста в реальному часі:
|
||||
- райони,
|
||||
- локації,
|
||||
- структури microDAO,
|
||||
- активні агенти та користувачі.
|
||||
|
||||
2. **Presence System** — відстеження присутності:
|
||||
- хто знаходиться в якому районі/секторі/каналі,
|
||||
- статуси присутності користувачів і агентів.
|
||||
|
||||
3. **Geo Intelligence**:
|
||||
- обробка геолокаційних даних,
|
||||
- інтеграція з Geo-agent (мультимодальність),
|
||||
- аналіз шляхів, зон та кластерів.
|
||||
|
||||
4. **Project / MicroDAO Mapping**:
|
||||
- кожен microDAO має свій "віртуальний район",
|
||||
- кожен проєкт — "будівлю/кластер".
|
||||
|
||||
5. **Integration with TeamDefinition & ProjectBus**:
|
||||
- локації = канали / контексти,
|
||||
- routing для комунікації між агентами у межах "районів".
|
||||
|
||||
Порт сервісу: **7001**.
|
||||
|
||||
---
|
||||
|
||||
## 1. FUNCTIONAL OVERVIEW
|
||||
|
||||
```text
|
||||
[ Gateway / Web UI / Living Map UI ]
|
||||
↓
|
||||
[ DAGI Router ] — (text/multimodal events)
|
||||
↓
|
||||
[ City Service (7001) ]
|
||||
↓
|
||||
[ PostgreSQL + NATS + Geo-agent ]
|
||||
```
|
||||
|
||||
City Service синхронізує:
|
||||
|
||||
* *місто як карту* (Region/Area/Point),
|
||||
* *місто як соціальну мережу* (Presence),
|
||||
* *місто як структуру проектів і microDAO*.
|
||||
|
||||
---
|
||||
|
||||
## 2. CORE DATA STRUCTURES
|
||||
|
||||
### 2.1. Region (Регіон)
|
||||
|
||||
Віртуальний район DAARION.city:
|
||||
|
||||
```json
|
||||
{
|
||||
"region_id": "district-greenfood",
|
||||
"name": "GREENFOOD District",
|
||||
"type": "microdao", // microdao | project | custom
|
||||
"microdao_id": "microdao-greenfood",
|
||||
"geometry": { "type": "Polygon", "coordinates": [...] },
|
||||
"meta": { "color": "#2ecc71" }
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2. Area / Building / Sector
|
||||
|
||||
Локальні локації всередині регіонів:
|
||||
|
||||
```json
|
||||
{
|
||||
"area_id": "area-greenfood-core",
|
||||
"region_id": "district-greenfood",
|
||||
"name": "Core Operations",
|
||||
"geometry": { "type": "Polygon", "coordinates": [...] },
|
||||
"project_id": "proj-greenfood",
|
||||
"meta": {}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3. Presence
|
||||
|
||||
Хто перебуває де:
|
||||
|
||||
```json
|
||||
{
|
||||
"subject_id": "ag_helix",
|
||||
"subject_type": "agent",
|
||||
"region_id": "district-greenfood",
|
||||
"area_id": "area-greenfood-core",
|
||||
"status": "active", // active|idle|offline
|
||||
"updated_at": "2025-11-24T10:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 2.4. Location Update Event
|
||||
|
||||
```json
|
||||
{
|
||||
"subject_id": "user123",
|
||||
"subject_type": "user",
|
||||
"geo": { "lat": 52.52, "lon": 13.40 },
|
||||
"region_id": "district-greenfood",
|
||||
"area_id": "area-greenfood-core"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. DATABASE SCHEMA (PostgreSQL + PostGIS)
|
||||
|
||||
City Service повинен мати PostGIS.
|
||||
|
||||
### 3.1. regions
|
||||
|
||||
```sql
|
||||
CREATE TABLE regions (
|
||||
region_id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
microdao_id TEXT,
|
||||
geometry GEOMETRY(POLYGON, 4326),
|
||||
meta JSONB DEFAULT '{}'::jsonb
|
||||
);
|
||||
```
|
||||
|
||||
### 3.2. areas
|
||||
|
||||
```sql
|
||||
CREATE TABLE areas (
|
||||
area_id TEXT PRIMARY KEY,
|
||||
region_id TEXT REFERENCES regions(region_id),
|
||||
name TEXT NOT NULL,
|
||||
project_id TEXT,
|
||||
geometry GEOMETRY(POLYGON, 4326),
|
||||
meta JSONB DEFAULT '{}'::jsonb
|
||||
);
|
||||
```
|
||||
|
||||
### 3.3. presence
|
||||
|
||||
```sql
|
||||
CREATE TABLE presence (
|
||||
subject_id TEXT NOT NULL,
|
||||
subject_type TEXT NOT NULL,
|
||||
region_id TEXT NOT NULL,
|
||||
area_id TEXT,
|
||||
status TEXT NOT NULL,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (subject_id, subject_type)
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. PUBLIC HTTP API (CITY SERVICE)
|
||||
|
||||
### 4.1. `GET /regions`
|
||||
|
||||
Список усіх регіонів міста.
|
||||
|
||||
### 4.2. `POST /regions`
|
||||
|
||||
Створити новий регіон (переважно для microDAO).
|
||||
|
||||
### 4.3. `GET /areas?region_id=...`
|
||||
|
||||
Список локацій у межах регіону.
|
||||
|
||||
### 4.4. `POST /presence/update`
|
||||
|
||||
Оновити присутність учасника/агента.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"subject_id": "ag_helion",
|
||||
"subject_type": "agent",
|
||||
"geo": { "lat": 50.45, "lon": 30.52 }
|
||||
}
|
||||
```
|
||||
|
||||
Відповідь після визначення регіону/зони:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"region_id": "district-daariandao",
|
||||
"area_id": "area-governance"
|
||||
}
|
||||
```
|
||||
|
||||
### 4.5. `GET /presence?region_id=...`
|
||||
|
||||
Повертає, хто зараз у районі.
|
||||
|
||||
---
|
||||
|
||||
## 5. GEO-AGENT INTEGRATION
|
||||
|
||||
Geo-agent (мультимодальність) використовується для:
|
||||
|
||||
1. **Інтерпретація геоданих**:
|
||||
|
||||
* визначити район по координатам,
|
||||
* визначити найближчу зону,
|
||||
* кластеризація.
|
||||
|
||||
2. **Запити від користувача**:
|
||||
|
||||
* "Покажи активність агентів у районі GREENFOOD"
|
||||
* "Яким шляхом рухається агент X?"
|
||||
* "Які агенти у проекті Y зараз активні?"
|
||||
|
||||
3. **Генерація інсайтів**:
|
||||
|
||||
* heat maps,
|
||||
* аномалії присутності,
|
||||
* навігація робочих потоків.
|
||||
|
||||
City Service викликає Geo-agent через:
|
||||
|
||||
```
|
||||
POST /multimodal/geo/infer
|
||||
```
|
||||
|
||||
або NATS subject:
|
||||
|
||||
```
|
||||
dagi.geo.infer
|
||||
```
|
||||
|
||||
Payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"lat": 50.45,
|
||||
"lon": 30.52,
|
||||
"regions": [...],
|
||||
"areas": [...]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. PROJECT BUS INTEGRATION
|
||||
|
||||
City Service взаємодіє з ProjectBus:
|
||||
|
||||
* коли створюється новий microDAO → створюється новий регіон;
|
||||
* коли створюється новий проект → нова area/cluster;
|
||||
* агенти/користувачі приєднуються до проектів → presence оновлюється.
|
||||
|
||||
Оновлення:
|
||||
|
||||
* `project.<id>.events` — події щодо присутності,
|
||||
* `project.<id>.map.events` — події для UI living map.
|
||||
|
||||
Приклад події:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "presence_updated",
|
||||
"project_id": "proj-greenfood",
|
||||
"subject_id": "ag_helix",
|
||||
"region_id": "district-greenfood",
|
||||
"area_id": "area-greenfood-core",
|
||||
"ts": "2025-11-24T10:10:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. DAGI ROUTER INTEGRATION
|
||||
|
||||
City Service інформує DAGI Router про:
|
||||
|
||||
* зміни регіону/зони:
|
||||
|
||||
* агенти отримують контекст `region_id` / `area_id`,
|
||||
* Router може маршрутизувати події за локацією,
|
||||
* routing за region-каналами (геочати),
|
||||
* особливі правила поведінки в певних регіонах (через TeamDefinition).
|
||||
|
||||
Router додає в кожен RouterEvent:
|
||||
|
||||
```json
|
||||
{
|
||||
"context": {
|
||||
"region_id": "...",
|
||||
"area_id": "...",
|
||||
"project_id": "...",
|
||||
"microdao_id": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. MULTINODE SUPPORT
|
||||
|
||||
City Service може бути:
|
||||
|
||||
* один на всі ноди (centralized),
|
||||
* або розгорнутий на кожній НОДА:
|
||||
|
||||
* локальна кешована карта,
|
||||
* синхронізація через NATS.
|
||||
|
||||
Оптимально:
|
||||
|
||||
```
|
||||
NODE1 = primary city-service
|
||||
NODE2/NODE3 = read replicas cache + local geo-routing
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. HEALTHCHECK & METRICS
|
||||
|
||||
### 9.1. `GET /healthz`
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"db": "ok",
|
||||
"geo_agent": "ok",
|
||||
"uptime_seconds": 21344
|
||||
}
|
||||
```
|
||||
|
||||
### 9.2. Prometheus metrics
|
||||
|
||||
* `presence_updates_total`
|
||||
* `active_subjects{region_id}`
|
||||
* `geo_queries_total`
|
||||
* `geo_inference_latency_ms_bucket`
|
||||
* `area_popularity{region_id, area_id}`
|
||||
|
||||
---
|
||||
|
||||
## 10. LIVING MAP UI (FUTURE)
|
||||
|
||||
City Service підтримує:
|
||||
|
||||
* API для реального часу (WebSocket/NATS),
|
||||
* 2D-UI та 3D-UI клієнти:
|
||||
|
||||
* Three.js / Babylon.js / Unity WebGL.
|
||||
|
||||
Плани:
|
||||
|
||||
* місто як **візуальна карта** проектів,
|
||||
* агентські маршрути,
|
||||
* стан об'єктів, сервісів та microDAO,
|
||||
* heatmap активності.
|
||||
|
||||
---
|
||||
|
||||
## 11. SUMMARY
|
||||
|
||||
City Service (7001):
|
||||
|
||||
* геопросторовий та "соціальний" шар DAARION,
|
||||
* формує логіку районів microDAO та проектних зон,
|
||||
* управляє присутністю користувачів і агентів,
|
||||
* інтегрується з DAGI Router, Geo-agent, ProjectBus, MicroDAO Service,
|
||||
* основа для 2D/3D карт та мультимодальних геоаналітик.
|
||||
|
||||
Це ключовий сервіс, який робить DAARION.city "живим містом", а не просто набором мікросервісів.
|
||||
|
||||
560
docs/services/MICRODAO_SERVICE_SPEC.md
Normal file
560
docs/services/MICRODAO_SERVICE_SPEC.md
Normal file
@@ -0,0 +1,560 @@
|
||||
# MICRODAO SERVICE SPEC (PORT 7004)
|
||||
# Version: 1.0.0
|
||||
|
||||
---
|
||||
|
||||
## 0. PURPOSE
|
||||
|
||||
`MicroDAO Service` — це базовий сервіс DAO-логіки для DAARION.city:
|
||||
|
||||
- створення та управління microDAO (райони, команди, проєкти),
|
||||
- членство, ролі та entitlements (RBAC),
|
||||
- пропозиції (proposals) та голосування (voting),
|
||||
- інтеграція з ProjectBus, TeamDefinition та Agents Service,
|
||||
- точка правди про те, хто що може в межах кожного microDAO.
|
||||
|
||||
**Фокус цієї версії (MVP):**
|
||||
|
||||
- Off-chain governance (Postgres + NATS),
|
||||
- без обов'язкового підключення до on-chain токенів (місце закладене, але може бути пустим).
|
||||
|
||||
Порт за замовчуванням: **7004**.
|
||||
|
||||
---
|
||||
|
||||
## 1. CORE CONCEPTS
|
||||
|
||||
### 1.1. MicroDAO
|
||||
|
||||
Легка DAO-одиниця в екосистемі DAARION:
|
||||
|
||||
- має `microdao_id` (наприклад, `microdao-root`, `microdao-greenfood`),
|
||||
- опис, місію, набір учасників,
|
||||
- пов'язане з одним або кількома `project_id`,
|
||||
- має власні:
|
||||
- ролі,
|
||||
- entitlements (доступи, дозволи),
|
||||
- voting-параметри.
|
||||
|
||||
### 1.2. Membership
|
||||
|
||||
Учасники microDAO:
|
||||
|
||||
- `user_id` (людина),
|
||||
- `agent_id` (агент),
|
||||
- `role_id` (роль у DAO),
|
||||
- статус: `active`, `pending`, `banned`, `left`.
|
||||
|
||||
### 1.3. Roles & Entitlements
|
||||
|
||||
Ролі визначають, що можна робити в межах microDAO:
|
||||
|
||||
- `role_id`: `"owner"`, `"admin"`, `"member"`, `"observer"`, `"agent-core"`, ...
|
||||
- кожна роль має набір `entitlements`:
|
||||
- `can_create_proposals`,
|
||||
- `can_vote`,
|
||||
- `can_manage_members`,
|
||||
- `can_manage_projects`,
|
||||
- `can_manage_teams`,
|
||||
- `can_manage_tokens` (закладка під on-chain).
|
||||
|
||||
### 1.4. Proposals & Voting
|
||||
|
||||
Пропозиції:
|
||||
|
||||
- створюються учасниками (люди/агенти) згідно entitlements,
|
||||
- приклади:
|
||||
- додати нового агента в команду,
|
||||
- змінити пріоритети сервісів,
|
||||
- створити новий проект,
|
||||
- змінити політику доступу,
|
||||
- мають статуси:
|
||||
- `draft`, `open`, `accepted`, `rejected`, `expired`.
|
||||
|
||||
Голосування:
|
||||
|
||||
- голоси від учасників microDAO,
|
||||
- правила підрахунку/кворуму задаються у параметрах DAO.
|
||||
|
||||
---
|
||||
|
||||
## 2. HIGH-LEVEL ARCHITECTURE
|
||||
|
||||
```text
|
||||
[ Users / Agents / UI ]
|
||||
↓
|
||||
[ Gateway (Telegram/Web/Matrix/Front) ]
|
||||
↓
|
||||
[ DAGI Router ]
|
||||
↓
|
||||
[ MicroDAO Service (7004) ]
|
||||
↓
|
||||
[ Postgres (microdao_db) + NATS (events) + Agents Service ]
|
||||
```
|
||||
|
||||
MicroDAO Service:
|
||||
|
||||
* тримає модель DAO в Postgres,
|
||||
* публікує події в NATS:
|
||||
|
||||
* `microdao.<id>.events`,
|
||||
* взаємодіє з:
|
||||
|
||||
* Agents Service (щоб агенти розуміли, що їм дозволено),
|
||||
* ProjectBus (для створення/оновлення проектних каналів),
|
||||
* Mesh Directory (через параметри доступу для агентів).
|
||||
|
||||
---
|
||||
|
||||
## 3. DATA MODEL (MVP-Рівень)
|
||||
|
||||
### 3.1. microdao
|
||||
|
||||
```sql
|
||||
CREATE TABLE microdao (
|
||||
microdao_id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'active', -- active|archived|pending
|
||||
created_at TIMESTAMP NOT NULL DEFAULT now(),
|
||||
created_by TEXT NOT NULL, -- user_id/agent_id
|
||||
meta JSONB DEFAULT '{}'::jsonb
|
||||
);
|
||||
```
|
||||
|
||||
### 3.2. microdao_project
|
||||
|
||||
```sql
|
||||
CREATE TABLE microdao_project (
|
||||
microdao_id TEXT NOT NULL REFERENCES microdao(microdao_id),
|
||||
project_id TEXT NOT NULL,
|
||||
PRIMARY KEY (microdao_id, project_id)
|
||||
);
|
||||
```
|
||||
|
||||
### 3.3. microdao_role
|
||||
|
||||
```sql
|
||||
CREATE TABLE microdao_role (
|
||||
role_id TEXT PRIMARY KEY,
|
||||
microdao_id TEXT NOT NULL REFERENCES microdao(microdao_id),
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
entitlements JSONB NOT NULL, -- { "can_create_proposals": true, ... }
|
||||
meta JSONB DEFAULT '{}'::jsonb
|
||||
);
|
||||
```
|
||||
|
||||
### 3.4. microdao_member
|
||||
|
||||
```sql
|
||||
CREATE TABLE microdao_member (
|
||||
microdao_id TEXT NOT NULL REFERENCES microdao(microdao_id),
|
||||
subject_id TEXT NOT NULL, -- user_id or agent_id
|
||||
subject_type TEXT NOT NULL, -- 'user' | 'agent'
|
||||
role_id TEXT NOT NULL REFERENCES microdao_role(role_id),
|
||||
status TEXT NOT NULL DEFAULT 'active', -- active|pending|banned|left
|
||||
joined_at TIMESTAMP NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (microdao_id, subject_id, subject_type)
|
||||
);
|
||||
```
|
||||
|
||||
### 3.5. microdao_proposal
|
||||
|
||||
```sql
|
||||
CREATE TABLE microdao_proposal (
|
||||
proposal_id TEXT PRIMARY KEY,
|
||||
microdao_id TEXT NOT NULL REFERENCES microdao(microdao_id),
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
creator_id TEXT NOT NULL,
|
||||
creator_type TEXT NOT NULL, -- 'user' | 'agent'
|
||||
status TEXT NOT NULL DEFAULT 'open', -- draft|open|accepted|rejected|expired
|
||||
created_at TIMESTAMP NOT NULL DEFAULT now(),
|
||||
opens_at TIMESTAMP,
|
||||
closes_at TIMESTAMP,
|
||||
params JSONB DEFAULT '{}'::jsonb -- voting rules overrides, payload
|
||||
);
|
||||
```
|
||||
|
||||
### 3.6. microdao_vote
|
||||
|
||||
```sql
|
||||
CREATE TABLE microdao_vote (
|
||||
proposal_id TEXT NOT NULL REFERENCES microdao_proposal(proposal_id),
|
||||
voter_id TEXT NOT NULL,
|
||||
voter_type TEXT NOT NULL, -- 'user' | 'agent'
|
||||
choice TEXT NOT NULL, -- 'yes'|'no'|'abstain'|custom
|
||||
weight NUMERIC NOT NULL DEFAULT 1,
|
||||
voted_at TIMESTAMP NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (proposal_id, voter_id, voter_type)
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. CONFIGURATION
|
||||
|
||||
ENV:
|
||||
|
||||
```env
|
||||
MICRODAO_SERVICE_PORT=7004
|
||||
|
||||
MICRODAO_DB_DSN=postgres://...
|
||||
MICRODAO_NATS_URL=nats://...
|
||||
|
||||
PROJECT_BUS_CONFIG_PATH=configs/project_bus_config.yaml
|
||||
TEAM_DEFINITION_PATH=configs/team_definition.yaml
|
||||
AGENT_REGISTRY_PATH=configs/AGENT_REGISTRY.yaml
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. PUBLIC HTTP API
|
||||
|
||||
### 5.1. `POST /microdaos`
|
||||
|
||||
Створити новий microDAO.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"microdao_id": "microdao-greenfood",
|
||||
"name": "GREENFOOD DAO",
|
||||
"description": "Управління екосистемою GREENFOOD AI-ERP",
|
||||
"created_by": "user:owner1"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"microdao": {
|
||||
"microdao_id": "microdao-greenfood",
|
||||
"name": "GREENFOOD DAO",
|
||||
"description": "...",
|
||||
"status": "active"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.2. `GET /microdaos`
|
||||
|
||||
Список microDAO.
|
||||
|
||||
`GET /microdaos?status=active`
|
||||
|
||||
---
|
||||
|
||||
### 5.3. `GET /microdaos/{microdao_id}`
|
||||
|
||||
Деталі одного microDAO (включно з ролями/параметрами).
|
||||
|
||||
---
|
||||
|
||||
### 5.4. `POST /microdaos/{microdao_id}/members`
|
||||
|
||||
Додати учасника (людину/агента).
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"subject_id": "ag_helion",
|
||||
"subject_type": "agent",
|
||||
"role_id": "agent-core"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"member": {
|
||||
"microdao_id": "microdao-greenfood",
|
||||
"subject_id": "ag_helion",
|
||||
"subject_type": "agent",
|
||||
"role_id": "agent-core",
|
||||
"status": "active"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.5. `GET /microdaos/{microdao_id}/members`
|
||||
|
||||
Список учасників.
|
||||
|
||||
---
|
||||
|
||||
### 5.6. `POST /microdaos/{microdao_id}/proposals`
|
||||
|
||||
Створити пропозицію.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "Додати нового агента до команди GREENFOOD",
|
||||
"description": "Пропоную додати vision_agent до team-greenfood.",
|
||||
"creator_id": "user:owner1",
|
||||
"creator_type": "user",
|
||||
"params": {
|
||||
"required_quorum": 0.5,
|
||||
"required_yes_ratio": 0.6
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"proposal": {
|
||||
"proposal_id": "prop-123",
|
||||
"status": "open"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.7. `POST /proposals/{proposal_id}/votes`
|
||||
|
||||
Голосування.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"voter_id": "user:member1",
|
||||
"voter_type": "user",
|
||||
"choice": "yes"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"vote": {
|
||||
"proposal_id": "prop-123",
|
||||
"voter_id": "user:member1",
|
||||
"choice": "yes",
|
||||
"weight": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.8. `GET /microdaos/{microdao_id}/proposals`
|
||||
|
||||
Список пропозицій DAO.
|
||||
|
||||
---
|
||||
|
||||
### 5.9. `GET /proposals/{proposal_id}`
|
||||
|
||||
Деталі пропозиції + поточний стан голосування.
|
||||
|
||||
---
|
||||
|
||||
## 6. EVENT BUS (NATS)
|
||||
|
||||
MicroDAO Service публікує події:
|
||||
|
||||
* `microdao.{microdao_id}.events`
|
||||
|
||||
Приклади payload:
|
||||
|
||||
### 6.1. MicroDAO Created
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "microdao_created",
|
||||
"microdao_id": "microdao-greenfood",
|
||||
"name": "GREENFOOD DAO",
|
||||
"created_by": "user:owner1",
|
||||
"ts": "2025-11-24T10:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2. Member Added
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "member_added",
|
||||
"microdao_id": "microdao-greenfood",
|
||||
"subject_id": "ag_helion",
|
||||
"subject_type": "agent",
|
||||
"role_id": "agent-core",
|
||||
"ts": "2025-11-24T10:01:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 6.3. Proposal Created
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "proposal_created",
|
||||
"microdao_id": "microdao-greenfood",
|
||||
"proposal_id": "prop-123",
|
||||
"title": "Додати vision_agent до команди GREENFOOD",
|
||||
"ts": "2025-11-24T10:05:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 6.4. Proposal Finalized
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "proposal_finalized",
|
||||
"microdao_id": "microdao-greenfood",
|
||||
"proposal_id": "prop-123",
|
||||
"final_status": "accepted",
|
||||
"result": {
|
||||
"yes": 10,
|
||||
"no": 1,
|
||||
"abstain": 2,
|
||||
"quorum": 0.7
|
||||
},
|
||||
"ts": "2025-11-24T11:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. INTEGRATION WITH OTHER SERVICES
|
||||
|
||||
### 7.1. Agents Service (7002)
|
||||
|
||||
Agents Service при кожному виклику:
|
||||
|
||||
* запитує MicroDAO Service (або кешує його рішення), щоб:
|
||||
|
||||
* перевірити, чи має агент право:
|
||||
|
||||
* відповідати в конкретному `project_id` / `microdao_id`,
|
||||
* виконувати певні дії (наприклад, створювати команду, керувати іншими агентами).
|
||||
|
||||
Простий варіант: HTTP-запит:
|
||||
|
||||
`GET /microdaos/{microdao_id}/members?subject_id=ag_helix&subject_type=agent`
|
||||
|
||||
Можливий кеш у Redis.
|
||||
|
||||
### 7.2. ProjectBus / TeamDefinition
|
||||
|
||||
При створенні microDAO + прив'язці project_id MicroDAO Service може:
|
||||
|
||||
* генерувати (або оновлювати) записи в:
|
||||
|
||||
* `project_bus_config.yaml`,
|
||||
* `team_definition.yaml` (або їх runtime-аналогах в БД),
|
||||
* публікувати події:
|
||||
|
||||
* `project.<project_id>.events` про появу нового microDAO/team.
|
||||
|
||||
### 7.3. Mesh Directory
|
||||
|
||||
MicroDAO Service може:
|
||||
|
||||
* впливати на видимість агентів:
|
||||
|
||||
* наприклад, якщо агент виключений з microDAO → його інстанси в Directory позначаються з обмеженими правами в цьому проекті.
|
||||
|
||||
---
|
||||
|
||||
## 8. SECURITY / RBAC
|
||||
|
||||
Важливі моменти:
|
||||
|
||||
1. Усі операції (створення DAO, додавання членів, створення пропозицій, голосування) повинні проходити через перевірку entitlements:
|
||||
|
||||
* `can_create_microdao`
|
||||
* `can_manage_members`
|
||||
* `can_create_proposals`
|
||||
* `can_vote`
|
||||
|
||||
2. MicroDAO Service не займається аутентифікацією — він приймає вже ідентифіковані `user_id` / `agent_id` (з gateway або auth-сервісу).
|
||||
|
||||
3. Системні агенти ( типу `ag_guardian`, `ag_cryptodetective` ) можуть мати особливі ролі з підвищеними entitlements (наприклад, аудит без права голосу).
|
||||
|
||||
---
|
||||
|
||||
## 9. HEALTHCHECK & METRICS
|
||||
|
||||
### 9.1. `GET /healthz`
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"db": "ok",
|
||||
"nats": "ok",
|
||||
"uptime_seconds": 1234
|
||||
}
|
||||
```
|
||||
|
||||
### 9.2. Prometheus
|
||||
|
||||
* `microdao_count{status}`
|
||||
* `microdao_members_count{microdao_id}`
|
||||
* `microdao_proposals_count{microdao_id,status}`
|
||||
* `microdao_votes_total{microdao_id,proposal_id,choice}`
|
||||
|
||||
---
|
||||
|
||||
## 10. TEST PLAN (SHORT)
|
||||
|
||||
Unit/Integration-тести (pytest):
|
||||
|
||||
1. `test_create_microdao_and_get()`
|
||||
|
||||
* створення DAO, перевірка читання.
|
||||
|
||||
2. `test_add_member_and_query()`
|
||||
|
||||
* додати члена, перевірити список.
|
||||
|
||||
3. `test_create_proposal_and_vote()`
|
||||
|
||||
* створити пропозицію, декілька голосів, підбиття результатів.
|
||||
|
||||
4. `test_entitlements_block_unauthorized_actions()`
|
||||
|
||||
* спроба створення пропозиції користувачем без `can_create_proposals`.
|
||||
|
||||
5. `test_events_published_on_actions()`
|
||||
|
||||
* перевірити, що при створенні DAO/пропозиції/результату йдуть NATS-івенти.
|
||||
|
||||
---
|
||||
|
||||
## 11. SUMMARY
|
||||
|
||||
MicroDAO Service (7004):
|
||||
|
||||
* є "governance ядром" для DAARION.city,
|
||||
* формально описує:
|
||||
|
||||
* хто до якого microDAO належить,
|
||||
* які ролі/entitlements має,
|
||||
* як приймаються рішення (proposals/voting),
|
||||
* тісно інтегрований з:
|
||||
|
||||
* Agents Service (поведінка агентів),
|
||||
* ProjectBus (потоки подій проектів),
|
||||
* Mesh Directory (видимість/скили/обмеження агентів).
|
||||
|
||||
Цей сервіс робить всі твої фрактальні команди та мережу агентів формально керованими через DAO-рівень.
|
||||
|
||||
392
docs/services/SECOND_ME_SERVICE_SPEC.md
Normal file
392
docs/services/SECOND_ME_SERVICE_SPEC.md
Normal file
@@ -0,0 +1,392 @@
|
||||
# SECOND ME SERVICE SPEC (PORT 7003)
|
||||
# Version: 1.0.0
|
||||
|
||||
---
|
||||
|
||||
## 0. PURPOSE
|
||||
|
||||
`Second Me Service` — це сервіс створення та управління **персональними цифровими двійниками** користувачів та агентів у DAARION.city.
|
||||
|
||||
Це ядро системи персоналізації:
|
||||
|
||||
- кожен користувач має SecondMe-профіль,
|
||||
- SecondMe є persistent-пам'яттю,
|
||||
- SecondMe може діяти як мультиагентний "асистент у тіні",
|
||||
- SecondMe синхронізується з мультимодальністю (audio → текст, image → профіль),
|
||||
- SecondMe допомагає іншим агентам (в т.ч. Метаморфу) адаптувати поведінку.
|
||||
|
||||
SecondMe працює як:
|
||||
|
||||
- storage (пам'ять користувача),
|
||||
- continuous learning module,
|
||||
- персональна reasoning-прошивка.
|
||||
|
||||
Порт сервісу: **7003**.
|
||||
|
||||
---
|
||||
|
||||
## 1. HIGH-LEVEL ARCHITECTURE
|
||||
|
||||
```text
|
||||
[ User ]
|
||||
/ | \
|
||||
Telegram Web Matrix
|
||||
\ | /
|
||||
[ DAGI Router ]
|
||||
↓
|
||||
[ Second Me Service (7003) ]
|
||||
↓
|
||||
[ Vector DB + Redis + Postgres ]
|
||||
↓
|
||||
[ Agents ]
|
||||
```
|
||||
|
||||
SecondMe Service перехоплює:
|
||||
|
||||
* історію взаємодії,
|
||||
* мультимодальний контент (image/audio/doc),
|
||||
* профіль користувача,
|
||||
* поведінкові патерни.
|
||||
|
||||
---
|
||||
|
||||
## 2. CORE RESPONSIBILITIES
|
||||
|
||||
### 2.1. Профіль SecondMe
|
||||
|
||||
Містить:
|
||||
|
||||
* user_id,
|
||||
* персональні налаштування,
|
||||
* пам'ять (context store),
|
||||
* переваги, хобі, стилі,
|
||||
* NFTs / achievements (майбутнє),
|
||||
* зв'язки з microDAO.
|
||||
|
||||
### 2.2. Персональна пам'ять
|
||||
|
||||
SecondMe має 3 типи пам'яті:
|
||||
|
||||
1. **Short-term** (до 48 год, швидкий доступ)
|
||||
2. **Long-term** (векторна пам'ять)
|
||||
3. **Structured Memory**:
|
||||
|
||||
* knowledge cards,
|
||||
* tasks,
|
||||
* goals,
|
||||
* архіви розмов.
|
||||
|
||||
### 2.3. Learning Pipeline
|
||||
|
||||
SecondMe автоматично:
|
||||
|
||||
* аналізує повідомлення та файли,
|
||||
* перетворює їх у structured facts,
|
||||
* зберігає у векторну пам'ять,
|
||||
* оновлює профіль (переваги/мету/поведінку),
|
||||
* генерує особисті інсайти.
|
||||
|
||||
### 2.4. Behavior Assistant
|
||||
|
||||
SecondMe допомагає іншим агентам:
|
||||
|
||||
* підказувати Helion/Helix, що знає про користувача,
|
||||
* спрощує пояснення контексту,
|
||||
* додає пам'ять у DAGI Router подіями типу:
|
||||
|
||||
* `user.context_update`,
|
||||
* `user.preference_update`,
|
||||
* `user.knowledge_card`.
|
||||
|
||||
---
|
||||
|
||||
## 3. DATA MODEL (Postgres + Vector DB)
|
||||
|
||||
### 3.1. Users
|
||||
|
||||
```sql
|
||||
CREATE TABLE users (
|
||||
user_id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT now(),
|
||||
meta JSONB DEFAULT '{}'::jsonb
|
||||
);
|
||||
```
|
||||
|
||||
### 3.2. SecondMe Profile
|
||||
|
||||
```sql
|
||||
CREATE TABLE secondme_profile (
|
||||
user_id TEXT PRIMARY KEY,
|
||||
preferences JSONB DEFAULT '{}'::jsonb,
|
||||
traits JSONB DEFAULT '{}'::jsonb,
|
||||
skills JSONB DEFAULT '{}'::jsonb,
|
||||
settings JSONB DEFAULT '{}'::jsonb,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT now()
|
||||
);
|
||||
```
|
||||
|
||||
### 3.3. Memory — Short Term
|
||||
|
||||
```sql
|
||||
CREATE TABLE secondme_memory_short (
|
||||
memory_id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL,
|
||||
text TEXT NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT now()
|
||||
);
|
||||
```
|
||||
|
||||
### 3.4. Memory — Long Term (Vector DB)
|
||||
|
||||
Хоститься в твоєму VectorDB (8898).
|
||||
|
||||
Документ:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "mem123",
|
||||
"user_id": "u1",
|
||||
"text": "користувач любить працювати з GREENFOOD",
|
||||
"embedding": [...1024 floats...],
|
||||
"metadata": {
|
||||
"type": "preference",
|
||||
"timestamp": "2025-11-24T12:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. PUBLIC API (HTTP)
|
||||
|
||||
### 4.1. `POST /secondme/update_from_event`
|
||||
|
||||
Вхідна точка для DAGI Router.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"event": {
|
||||
"source": "telegram",
|
||||
"user": { "id": "u1" },
|
||||
"project_id": "proj-greenfood",
|
||||
"text": "мені дуже подобається зелена аналітика",
|
||||
"attachments": { "images": [], "audio": [] }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"actions": [
|
||||
"short_memory_added",
|
||||
"long_memory_indexed",
|
||||
"profile_trait_updated"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.2. `GET /secondme/profile/{user_id}`
|
||||
|
||||
Отримати повний профіль користувача.
|
||||
|
||||
---
|
||||
|
||||
### 4.3. `GET /secondme/memory/{user_id}`
|
||||
|
||||
Повертає коротку + довгу пам'ять.
|
||||
|
||||
---
|
||||
|
||||
### 4.4. `POST /secondme/query`
|
||||
|
||||
Пошук у пам'яті:
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": "u1",
|
||||
"query": "що цей користувач любить робити?"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"text": "користувач любить працювати з GREENFOOD",
|
||||
"score": 0.92
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.5. `POST /secondme/summarize`
|
||||
|
||||
Генерує персональний summary користувача для агентів:
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"summary": "Користувач працює над GREENFOOD, любить аналітику, часто дає задачі Helix."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. AGENT INTEGRATION
|
||||
|
||||
### 5.1. Helion integration
|
||||
|
||||
Helion отримує SecondMe-summary для:
|
||||
|
||||
* кращих відповідей,
|
||||
* виконання задач з персональним контекстом.
|
||||
|
||||
### 5.2. Helix integration
|
||||
|
||||
SecondMe → Helix:
|
||||
|
||||
* історія рішень користувача,
|
||||
* технічні вподобання,
|
||||
* деталі проектів користувача.
|
||||
|
||||
### 5.3. Metamorph integration
|
||||
|
||||
SecondMe → Metamorph:
|
||||
|
||||
* персоналізація поведінки агентів,
|
||||
* рекомендації по агентах, які потрібні користувачу.
|
||||
|
||||
### 5.4. Geo-agent
|
||||
|
||||
Якщо користувач дає гео-події:
|
||||
|
||||
* SecondMe зберігає маршрути / активність,
|
||||
* може допомагати City Service сортувати події.
|
||||
|
||||
---
|
||||
|
||||
## 6. LEARNING PIPELINE
|
||||
|
||||
SecondMe обробляє кожну подію:
|
||||
|
||||
1. **Extract facts**
|
||||
Визначає, чи є текст чи медіа важливим для пам'яті.
|
||||
|
||||
2. **Classify type**
|
||||
|
||||
* preference
|
||||
* skill
|
||||
* long-term fact
|
||||
* behavioural pattern
|
||||
* project affinity
|
||||
|
||||
3. **Embed**
|
||||
|
||||
* створює embedding (через твою bge-m3 модель).
|
||||
|
||||
4. **Index**
|
||||
|
||||
* зберігає у Vector DB.
|
||||
|
||||
5. **Profile Update**
|
||||
|
||||
* якщо знайдені нові патерни → оновити SecondMe Profile.
|
||||
|
||||
6. **Emit Events**
|
||||
Публікує в NATS:
|
||||
|
||||
* `secondme.{user_id}.memory_added`
|
||||
* `secondme.{user_id}.profile_updated`
|
||||
|
||||
---
|
||||
|
||||
## 7. INTERACTION WITH DAGI ROUTER
|
||||
|
||||
DAGI Router повинен:
|
||||
|
||||
* при кожному `RouterEvent` викликати `POST /secondme/update_from_event`,
|
||||
* отримувати у відповідь:
|
||||
|
||||
* пам'ять-дії,
|
||||
* профільні зміни.
|
||||
|
||||
SecondMe діє як **фонова підсистема**, що збагачує контекст.
|
||||
|
||||
---
|
||||
|
||||
## 8. PROJECT BUS INTEGRATION
|
||||
|
||||
SecondMe може бути підписаним на:
|
||||
|
||||
```
|
||||
project.<project_id>.events
|
||||
project.<project_id>.chat.human
|
||||
```
|
||||
|
||||
щоб вчитися на:
|
||||
|
||||
* командних подіях,
|
||||
* рішеннях,
|
||||
* поведінці користувача всередині проекту.
|
||||
|
||||
---
|
||||
|
||||
## 9. MULTIMODAL SUPPORT
|
||||
|
||||
SecondMe працює з мультимодальністю:
|
||||
|
||||
* image → Vision-agent → SecondMe ("користувач показує X"),
|
||||
* audio → STT → SecondMe (зберігає розмови і суть),
|
||||
* docs → Doc-agent → SecondMe (пам'ятає PDF-документи користувача).
|
||||
|
||||
---
|
||||
|
||||
## 10. HEALTHCHECK & METRICS
|
||||
|
||||
### 10.1. `GET /healthz`
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"db": "ok",
|
||||
"vector": "ok",
|
||||
"uptime_seconds": 21344
|
||||
}
|
||||
```
|
||||
|
||||
### 10.2. Prometheus
|
||||
|
||||
* `secondme_events_total`
|
||||
* `memory_added_total`
|
||||
* `profile_updates_total`
|
||||
* `embedding_latency_ms_bucket`
|
||||
* `vector_search_latency_ms_bucket`
|
||||
|
||||
---
|
||||
|
||||
## 11. SUMMARY
|
||||
|
||||
Second Me Service (7003):
|
||||
|
||||
* персональна пам'ять,
|
||||
* особистісний профіль,
|
||||
* обробка мультимодальних подій,
|
||||
* забезпечує глибинну персоналізацію системи,
|
||||
* розуміє контекст користувача,
|
||||
* допомагає іншим агентам приймати кращі рішення,
|
||||
* працює автономно, мовчки, але є ключовим "мозком користувача".
|
||||
|
||||
Reference in New Issue
Block a user