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:
151
migrations/010_create_city_backend.sql
Normal file
151
migrations/010_create_city_backend.sql
Normal file
@@ -0,0 +1,151 @@
|
||||
-- Migration 010: City Backend (Rooms, Feed, Second Me)
|
||||
-- DAARION City MVP Backend Completion
|
||||
|
||||
-- =============================================================================
|
||||
-- City Rooms (Public Rooms)
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS city_rooms (
|
||||
id TEXT PRIMARY KEY, -- room_city_general, room_city_science, etc.
|
||||
slug TEXT NOT NULL UNIQUE, -- general, science, builders
|
||||
name TEXT NOT NULL, -- General, Science, Builders
|
||||
description TEXT,
|
||||
is_default BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_by TEXT -- user_id (u_*) or NULL for system
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_city_rooms_slug ON city_rooms(slug);
|
||||
CREATE INDEX IF NOT EXISTS ix_city_rooms_created_at ON city_rooms(created_at DESC);
|
||||
|
||||
COMMENT ON TABLE city_rooms IS 'Публічні кімнати DAARION City';
|
||||
|
||||
-- =============================================================================
|
||||
-- City Room Messages
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS city_room_messages (
|
||||
id TEXT PRIMARY KEY, -- m_city_ulid
|
||||
room_id TEXT NOT NULL REFERENCES city_rooms(id) ON DELETE CASCADE,
|
||||
author_user_id TEXT, -- u_* (user who sent)
|
||||
author_agent_id TEXT, -- ag_* (agent who sent)
|
||||
body TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT check_author CHECK (
|
||||
(author_user_id IS NOT NULL AND author_agent_id IS NULL) OR
|
||||
(author_user_id IS NULL AND author_agent_id IS NOT NULL)
|
||||
)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_city_room_messages_room_time
|
||||
ON city_room_messages(room_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS ix_city_room_messages_author_user
|
||||
ON city_room_messages(author_user_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_city_room_messages_author_agent
|
||||
ON city_room_messages(author_agent_id);
|
||||
|
||||
COMMENT ON TABLE city_room_messages IS 'Повідомлення в публічних кімнатах City';
|
||||
|
||||
-- =============================================================================
|
||||
-- City Feed Events
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS city_feed_events (
|
||||
id TEXT PRIMARY KEY, -- evt_city_ulid
|
||||
kind TEXT NOT NULL, -- 'room_message', 'agent_reply', 'system', 'dao_event'
|
||||
room_id TEXT REFERENCES city_rooms(id) ON DELETE SET NULL,
|
||||
user_id TEXT, -- u_*
|
||||
agent_id TEXT, -- ag_*
|
||||
payload JSONB NOT NULL, -- flexible event data
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_city_feed_time ON city_feed_events(created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS ix_city_feed_kind ON city_feed_events(kind);
|
||||
CREATE INDEX IF NOT EXISTS ix_city_feed_room ON city_feed_events(room_id) WHERE room_id IS NOT NULL;
|
||||
|
||||
COMMENT ON TABLE city_feed_events IS 'City Feed — агрегатор всіх подій міста';
|
||||
|
||||
-- =============================================================================
|
||||
-- Second Me Sessions (персональний агент)
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS secondme_sessions (
|
||||
id TEXT PRIMARY KEY, -- smsess_ulid
|
||||
user_id TEXT NOT NULL, -- u_*
|
||||
agent_id TEXT, -- ag_secondme_*
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
last_interaction_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_secondme_sessions_user ON secondme_sessions(user_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_secondme_sessions_last_interaction
|
||||
ON secondme_sessions(user_id, last_interaction_at DESC NULLS LAST);
|
||||
|
||||
COMMENT ON TABLE secondme_sessions IS 'Сесії взаємодії користувачів з Second Me';
|
||||
|
||||
-- =============================================================================
|
||||
-- Second Me Messages
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS secondme_messages (
|
||||
id TEXT PRIMARY KEY, -- smmsg_ulid
|
||||
session_id TEXT NOT NULL REFERENCES secondme_sessions(id) ON DELETE CASCADE,
|
||||
user_id TEXT NOT NULL, -- u_*
|
||||
role TEXT NOT NULL CHECK (role IN ('user', 'assistant')),
|
||||
content TEXT NOT NULL,
|
||||
tokens_used INT, -- для assistant messages
|
||||
latency_ms INT, -- для assistant messages
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_secondme_messages_session_time
|
||||
ON secondme_messages(session_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS ix_secondme_messages_user
|
||||
ON secondme_messages(user_id);
|
||||
|
||||
COMMENT ON TABLE secondme_messages IS 'Історія розмов з Second Me';
|
||||
|
||||
-- =============================================================================
|
||||
-- Insert Default City Rooms
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO city_rooms (id, slug, name, description, is_default) VALUES
|
||||
('room_city_general', 'general', 'General', 'Головна кімната DAARION City — тут зустрічається вся спільнота', TRUE),
|
||||
('room_city_welcome', 'welcome', 'Welcome', 'Вітаємо нових учасників! Почніть свою подорож тут', TRUE),
|
||||
('room_city_builders', 'builders', 'Builders', 'Кімната для будівників та розробників DAARION', TRUE),
|
||||
('room_city_science', 'science', 'Science', 'Наукова спільнота — обговорення досліджень та експериментів', FALSE),
|
||||
('room_city_energy', 'energy', 'Energy Union', 'Енергетична спільнота — decarbonization, renewables', FALSE)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
-- =============================================================================
|
||||
-- Seed: Welcome Message
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO city_room_messages (id, room_id, author_agent_id, body, created_at) VALUES
|
||||
('m_city_welcome_001', 'room_city_welcome', 'ag_system',
|
||||
'Вітаємо в DAARION City! Це публічний простір для спілкування, співпраці та інновацій. Приєднуйтесь до обговорень! 🚀',
|
||||
NOW())
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
INSERT INTO city_room_messages (id, room_id, author_agent_id, body, created_at) VALUES
|
||||
('m_city_general_001', 'room_city_general', 'ag_system',
|
||||
'Головна кімната міста активна! Тут ви можете обговорювати будь-які теми, пов''язані з DAARION. 🌆',
|
||||
NOW())
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
-- =============================================================================
|
||||
-- Feed Event for Welcome
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO city_feed_events (id, kind, room_id, agent_id, payload, created_at) VALUES
|
||||
('evt_city_welcome_001', 'system', 'room_city_welcome', 'ag_system',
|
||||
'{"message": "Система ініціалізована", "type": "bootstrap"}',
|
||||
NOW())
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
-- =============================================================================
|
||||
-- END OF MIGRATION 010
|
||||
-- =============================================================================
|
||||
|
||||
Reference in New Issue
Block a user