Skip to content

# TASK_PHASE_CITY_ROOMS_AND_PUBLIC_CHAT_v1

Проєкт: DAARION.city
Мета: 1) оживити "Кімнати Міста" (City Rooms) – карта + список;
2) додати головний публічний чат з DAARWIZZ;
3) дозволити створювати кімнати всередині MicroDAO з перемикачем Public/Private.

## 0. Поточний стан

UI (за скріншотами):

- MicroDAO:
- є список MicroDAO з картками (DAARION DAO, Energy Union, GreenFood, Soul…).
- всередині MicroDAO є блок "Orchestrator Team Chat", але кімнати явно не підключені.
- City Rooms:
- вкладка "Мапа" показує сітку районів (Leadership Hall, System Control, Engineering, Marketing, Finance, Web3, Security, Vision, R&D, Memory, Welcome/General).
- вкладка "Список" показує "Кімнати не знайдено".
- Matrix / gateway:
- Matrix-інтеграція вже є (див. існуючі `matrix-architecture`/`gateway` доки).
- Є публічні кімнати, але вони не підв'язані до city-service Rooms API.

## 1. Scope

### Включено

1. Нова модель "кімнати міста" (City Rooms) в бекенді:

2. з прив'язкою до MicroDAO / району / Matrix roomId.

3. API для кімнат:

4. список, створення, оновлення visibility (Public/Private), отримання деталей.

5. Головна кімната "City Lobby" з DAARWIZZ:

6. спеціальний флаг `is_city_default`.

7. MicroDAO Rooms:

8. список кімнат MicroDAO;

9. кнопка `+ Створити кімнату` з перемикачем Public/Private.

10. City Rooms UI:

11. вкладка "Список" – реальні кімнати з фільтрами;
12. вкладка "Мапа" – tiles прив'язані до реальних кімнат (по district).

### Виключено

- Повна CrewAI-логіка (запуск декількох агентів як команди) – це окремий Task 3.
- Управління правами Matrix-кімнат (залишаємо базове: створює gateway, ACL мінімальні).

## 2. Backend – модель "кімнати"

### 2.1. Схема БД

Створити міграцію `migrations/043_city_rooms.sql`:

    -- City Rooms table for DAARION.city
    -- Supports: city rooms, microdao rooms, crew rooms, district rooms

    CREATE TABLE IF NOT EXISTS city_rooms (
      id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
      slug text UNIQUE NOT NULL,
      title text NOT NULL,
      description text,
      room_type text NOT NULL, -- 'city', 'microdao', 'crew', 'district'
      visibility text NOT NULL DEFAULT 'private', -- 'public', 'microdao', 'private'
      microdao_id text NULL REFERENCES microdaos(id),
      district_key text NULL, -- 'leadership', 'security', 'engineering', etc.
      matrix_room_id text NULL,
      is_city_default boolean NOT NULL DEFAULT false,
      is_microdao_default boolean NOT NULL DEFAULT false,
      orchestrator_agent_id text NULL REFERENCES agents(id),
      icon text NULL,
      color text NULL,
      created_by text NULL REFERENCES users(id),
      created_at timestamptz NOT NULL DEFAULT now(),
      updated_at timestamptz NOT NULL DEFAULT now(),
      archived_at timestamptz NULL
    );

    CREATE INDEX IF NOT EXISTS idx_city_rooms_microdao ON city_rooms (microdao_id);
    CREATE INDEX IF NOT EXISTS idx_city_rooms_district ON city_rooms (district_key);
    CREATE INDEX IF NOT EXISTS idx_city_rooms_visibility ON city_rooms (visibility);
    CREATE INDEX IF NOT EXISTS idx_city_rooms_type ON city_rooms (room_type);
    CREATE INDEX IF NOT EXISTS idx_city_rooms_archived ON city_rooms (archived_at) WHERE archived_at IS NULL;

    COMMENT ON TABLE city_rooms IS 'Кімнати міста DAARION - для чатів, команд, районів';
    COMMENT ON COLUMN city_rooms.room_type IS 'Тип кімнати: city (міська), microdao, crew (команда), district (район)';
    COMMENT ON COLUMN city_rooms.visibility IS 'Видимість: public (всім), microdao (членам MicroDAO), private (запрошеним)';
    COMMENT ON COLUMN city_rooms.is_city_default IS 'Головна кімната міста (City Lobby з DAARWIZZ)';
    COMMENT ON COLUMN city_rooms.is_microdao_default IS 'Головна кімната MicroDAO';

### 2.2. Repo / models / routes

- У `models_city.py`:

- додати `CityRoom` / `CityRoomSummary` з полями вище.

- У `repo_city.py`:

- `get_city_rooms(filter_by_visibility, filter_by_microdao, filter_by_district)`
- `get_city_room_by_slug(slug)`
- `create_city_room(...)`

- `update_city_room_visibility(slug, visibility)`

- У `routes_city.py`:

- `GET /api/v1/city/rooms`
  - query params: `visibility`, `microdao_slug`, `district`.
- `POST /api/v1/city/rooms`
  - body: `{ title, description?, room_type, visibility, microdao_slug?, district_key? }`.
- `PATCH /api/v1/city/rooms/{slug}`
  - змінити: `title`, `description`, `visibility`, `archived_at`.

### 2.3. Matrix інтеграція

Для створення нової кімнати:

- при `POST /api/v1/city/rooms`:
- бекенд:
  - викликає gateway / internal service:
  - напр. `POST /internal/matrix/create-room` з payload:
    - `{ "slug": "...", "title": "...", "visibility": "public|private" }`;
  - отримує `matrix_room_id`.
  - записує `matrix_room_id` в `city_rooms`.

Фактичний URL/сервіс знайти в існуючих доках `gateway` / `matrix-architecture` і використати.

## 3. Seed даних

### 3.1. City Lobby з DAARWIZZ

Створити `scripts/seed_city_rooms.py`:

- Якщо немає кімнати `slug = 'city-lobby'`:
- створити запис:

    {
      "slug": "city-lobby",
      "title": "DAARION City Lobby",
      "description": "Головний публічний чат з DAARWIZZ.",
      "room_type": "city",
      "visibility": "public",
      "is_city_default": true,
      "orchestrator_agent_id": "daarwizz"
    }

- Викликати Matrix-gateway для створення відповідної Matrix-кімнати.
- Прив'язати до MicroDAO DAARION (якщо потрібно – через окрему таблицю або поле).

### 3.2. Default кімнати MicroDAO (по 1 на платформу)

Для кожної з платформ:

- `daarion` (DAARION DAO)
- `energy-union` (Energy Union)
- `greenfood` (GreenFood DAO)
- `soul` (Soul Retreat Hub)

створити room:

    {
      "slug": "microdao-<slug>-lobby",
      "title": "<Name> Lobby",
      "room_type": "microdao",
      "visibility": "microdao",
      "microdao_id": "...",
      "is_microdao_default": true
    }

### 3.3. District Rooms (10 районів)

Для кожного району з `agents_city_mapping.yaml`:

- leadership → "Leadership Hall"
- system → "System Control Center"
- engineering → "Engineering Lab"
- marketing → "Marketing Hub"
- finance → "Finance Office"
- web3 → "Web3 District"
- security → "Security Bunker"
- vision → "Vision Studio"
- rnd → "R&D Laboratory"
- memory → "Memory Vault"

створити room:

    {
      "slug": "district-<key>",
      "title": "<Name>",
      "room_type": "district",
      "visibility": "public",
      "district_key": "<key>"
    }

## 4. Frontend – MicroDAO сторінка

Файли: `apps/web/src/app/microdao/page.tsx`, `apps/web/src/app/microdao/[slug]/page.tsx` та пов'язані компоненти.

### 4.1. API hook

Створити хук:

    // apps/web/src/hooks/useMicrodaoRooms.ts
    import useSWR from 'swr';
    import { fetcher } from '@/lib/fetcher';

    export function useMicrodaoRooms(slug: string) {
      return useSWR(slug ? `/api/city/rooms?microdao_slug=${slug}` : null, fetcher);
    }

(через існуючий proxy `/api/...` до бекенду).

### 4.2. Блок "Кімнати MicroDAO"

На сторінці MicroDAO:

- додати секцію під Branding / перед "Orchestrator Team Chat":

Макет:

- Заголовок: `Кімнати MicroDAO`
- Кнопка праворуч: `+ Створити кімнату`
- Список карток:

    [ DAARION DAO Lobby ]  [ Leadership Crew ]  [ Security Council ]

### 4.3. Модалка "Створити кімнату"

Поля:

- Назва кімнати
- Опис (опційно)
- Тип (read-only: `MicroDAO`)
- Перемикач: `Публічна кімната`
- якщо вимкнено → `visibility = 'microdao'` (лише члени MicroDAO);
- якщо увімкнено → `visibility = 'public'`.

On submit → `POST /api/city/rooms`.

## 5. Frontend – City Rooms сторінка

Файл: `apps/web/src/app/city/page.tsx` або `apps/web/src/app/city/rooms/page.tsx` (подивитись фактичний).

### 5.1. Вкладка "Список"

- Використати `GET /api/city/rooms?visibility=public` за замовчанням.
- Відображати таблицею/картками:

Поля:

- Назва
- Тип / District / MicroDAO
- Іконки:
- Public / MicroDAO / Private
- Лічильник:
- `X агентів` (опційно, якщо буде окремий endpoint; на MVP можна не показувати).

### 5.2. Вкладка "Мапа"

- Для tile'ів районів (Leadership Hall, Security Bunker, Web3 District, …):
- під'єднати відповідні `city_rooms` через `district_key`.
- Клік по tile → переходить на `/city/rooms/[slug]` або відкриває чат.

## 6. Frontend – головний CTA з DAARWIZZ

На головній сторінці `apps/web/src/app/page.tsx`:

- додати основну кнопку (у hero-секції):

`Поспілкуватися з DAARWIZZ`

- дія:
- `router.push('/city/rooms/city-lobby')`
- або відкриває вбудований чат-віджет, якщо він уже реалізований.

## 7. Acceptance Criteria

1. `GET /api/v1/city/rooms` повертає список кімнат (мінімум: `city-lobby` + 4 MicroDAO лобі + 10 district rooms).

2. На сторінці MicroDAO:

3. видно блок "Кімнати MicroDAO";
4. кнопка `+ Створити кімнату` створює запис у БД;

5. нова кімната з'являється у списку без перезавантаження.

6. На сторінці City Rooms:

7. вкладка "Список" показує реальні кімнати;

8. вкладка "Мапа" не показує помилок, tile'и районів прив'язані до відповідних кімнат (або до лобі за замовчанням).

9. При переході на `/city/rooms/city-lobby` відкривається чат з DAARWIZZ (Matrix roomId збережений у `city_rooms`).

10. Нові кімнати MicroDAO мають коректний visibility:

11. без галочки – не видно у `?visibility=public`;
12. з галочкою – видно у публічному списку.

## 8. Наступні кроки (Task 3)

Після реалізації цього таска:

- ти матимеш головний публічний чат з DAARWIZZ на головній;
- кожне MicroDAO зможе створювати свої кімнати з вибором публічності;
- сторінка "Кімнати Міста" перестане бути пустою й стане справжнім лобі міста.

А керування агентами (створення/видалення, Crew-кімнати) винесемо в наступний Task 3: - Глобальна кнопка "Створити агента" на `/agents` - Локальна кнопка "Додати агента цієї ноди" в Node Cabinet - Видалення/архівація агента в кабінеті агента - Групи агентів = кімнати команд (CrewAI)