## Agents Added - Alateya: R&D, biotech, innovations - Clan (Spirit): Community spirit agent - Eonarch: Consciousness evolution agent ## Changes - docker-compose.node1.yml: Added tokens for all 3 new agents - gateway-bot/http_api.py: Added configs and webhook endpoints - gateway-bot/clan_prompt.txt: New prompt file - gateway-bot/eonarch_prompt.txt: New prompt file ## Fixes - Fixed ROUTER_URL from :9102 to :8000 (internal container port) - All 9 Telegram agents now working ## Documentation - Created PROJECT-MASTER-INDEX.md - single entry point - Added various status documents and scripts Tokens configured: - Helion, NUTRA, Agromatrix (existing) - Alateya, Clan, Eonarch (new) - Druid, GreenFood, DAARWIZZ (configured)
408 lines
16 KiB
PL/PgSQL
408 lines
16 KiB
PL/PgSQL
-- Migration 049: Human Memory Model v3.0 for Helion
|
|
-- Full identity, roles, session state, and organizational memory schema
|
|
-- Created: 2026-01-17
|
|
|
|
-- ============================================================================
|
|
-- L2: PLATFORM IDENTITY & ROLES (PIR)
|
|
-- ============================================================================
|
|
|
|
-- Global platform users (cross-channel identity)
|
|
CREATE TABLE IF NOT EXISTS platform_users (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
status TEXT DEFAULT 'active', -- active, inactive, banned, deleted
|
|
-- Aggregated profile (derived from channel_identities)
|
|
preferred_language TEXT DEFAULT 'uk',
|
|
timezone TEXT,
|
|
metadata JSONB DEFAULT '{}'
|
|
);
|
|
|
|
-- Channel-specific identities (Telegram, Discord, Email, etc.)
|
|
CREATE TABLE IF NOT EXISTS channel_identities (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
platform_user_id UUID NOT NULL REFERENCES platform_users(id) ON DELETE CASCADE,
|
|
channel TEXT NOT NULL, -- telegram, discord, email, web
|
|
channel_user_id TEXT NOT NULL, -- Telegram from.id, Discord user_id, etc.
|
|
username TEXT, -- @username
|
|
display_name TEXT, -- first_name + last_name
|
|
avatar_url TEXT,
|
|
verified BOOLEAN DEFAULT FALSE,
|
|
first_seen_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
last_seen_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
metadata JSONB DEFAULT '{}', -- channel-specific data
|
|
UNIQUE(channel, channel_user_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_channel_identities_platform_user ON channel_identities(platform_user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_channel_identities_channel_user ON channel_identities(channel, channel_user_id);
|
|
|
|
-- Platform roles (mentor, dev, investor, ops, moderator)
|
|
CREATE TABLE IF NOT EXISTS platform_roles (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
code TEXT NOT NULL UNIQUE, -- mentor, developer, investor, ops, moderator, admin
|
|
display_name TEXT NOT NULL,
|
|
scope TEXT NOT NULL DEFAULT 'platform', -- platform, group, thread
|
|
description TEXT,
|
|
permissions JSONB DEFAULT '[]', -- list of permission codes
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
-- User-role assignments
|
|
CREATE TABLE IF NOT EXISTS user_roles (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
platform_user_id UUID NOT NULL REFERENCES platform_users(id) ON DELETE CASCADE,
|
|
role_id UUID NOT NULL REFERENCES platform_roles(id) ON DELETE CASCADE,
|
|
scope_ref TEXT, -- group_id for group-scoped roles, null for platform-wide
|
|
confidence REAL DEFAULT 1.0, -- 0.0-1.0, lower for inferred roles
|
|
assigned_by TEXT, -- 'system', 'admin', 'helion_inferred', user_id
|
|
assigned_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
revoked_at TIMESTAMP WITH TIME ZONE, -- null if active
|
|
notes TEXT,
|
|
UNIQUE(platform_user_id, role_id, scope_ref)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_user_roles_platform_user ON user_roles(platform_user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_user_roles_active ON user_roles(platform_user_id) WHERE revoked_at IS NULL;
|
|
|
|
-- ============================================================================
|
|
-- L1: SESSION STATE MEMORY (SSM)
|
|
-- ============================================================================
|
|
|
|
-- Conversations (chat sessions)
|
|
CREATE TABLE IF NOT EXISTS helion_conversations (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
channel TEXT NOT NULL, -- telegram, discord, web
|
|
chat_id TEXT NOT NULL, -- Telegram chat_id, Discord channel_id
|
|
thread_id TEXT, -- Optional thread within chat
|
|
platform_user_id UUID REFERENCES platform_users(id), -- Primary user (for DMs)
|
|
started_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
last_activity_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
status TEXT DEFAULT 'active', -- active, archived, deleted
|
|
metadata JSONB DEFAULT '{}',
|
|
UNIQUE(channel, chat_id, thread_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_conversations_chat ON helion_conversations(channel, chat_id);
|
|
CREATE INDEX IF NOT EXISTS idx_conversations_user ON helion_conversations(platform_user_id);
|
|
|
|
-- Session state (SSM) - per conversation
|
|
CREATE TABLE IF NOT EXISTS helion_conversation_state (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
conversation_id UUID NOT NULL REFERENCES helion_conversations(id) ON DELETE CASCADE,
|
|
|
|
-- Addressing state
|
|
last_addressed_to_helion BOOLEAN DEFAULT FALSE,
|
|
last_user_id TEXT,
|
|
last_user_nick TEXT,
|
|
|
|
-- Topic/context tracking
|
|
active_topic_id TEXT,
|
|
active_context_open BOOLEAN DEFAULT FALSE,
|
|
closed_context_ids TEXT[] DEFAULT '{}',
|
|
|
|
-- Media handling
|
|
last_media_id TEXT,
|
|
last_media_type TEXT,
|
|
last_media_handled BOOLEAN DEFAULT FALSE,
|
|
|
|
-- Anti-repeat mechanism
|
|
last_answer_fingerprint TEXT,
|
|
last_answer_at TIMESTAMP WITH TIME ZONE,
|
|
|
|
-- Group settings
|
|
group_trust_mode BOOLEAN DEFAULT FALSE,
|
|
apprentice_mode BOOLEAN DEFAULT FALSE,
|
|
|
|
-- Proactive question limits
|
|
proactive_questions_today INTEGER DEFAULT 0,
|
|
last_proactive_question_at TIMESTAMP WITH TIME ZONE,
|
|
proactive_question_reset_date DATE DEFAULT CURRENT_DATE,
|
|
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
state_json JSONB DEFAULT '{}', -- Additional flexible state
|
|
|
|
UNIQUE(conversation_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_conversation_state_conv ON helion_conversation_state(conversation_id);
|
|
|
|
-- Media index (for tracking processed media)
|
|
CREATE TABLE IF NOT EXISTS helion_media_index (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
conversation_id UUID NOT NULL REFERENCES helion_conversations(id) ON DELETE CASCADE,
|
|
message_id TEXT NOT NULL,
|
|
media_type TEXT NOT NULL, -- photo, voice, video, document, video_note
|
|
file_id TEXT NOT NULL,
|
|
file_hash TEXT, -- For deduplication
|
|
handled BOOLEAN DEFAULT FALSE,
|
|
handled_at TIMESTAMP WITH TIME ZONE,
|
|
result_summary TEXT, -- Brief summary of what was extracted
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
UNIQUE(conversation_id, file_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_media_index_conv ON helion_media_index(conversation_id);
|
|
CREATE INDEX IF NOT EXISTS idx_media_index_file ON helion_media_index(file_id);
|
|
|
|
-- ============================================================================
|
|
-- L3: ORGANIZATIONAL MEMORY (OM)
|
|
-- ============================================================================
|
|
|
|
-- Extended memory items (long-term facts)
|
|
CREATE TABLE IF NOT EXISTS helion_memory_items (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
platform_user_id UUID REFERENCES platform_users(id) ON DELETE SET NULL,
|
|
|
|
-- Memory classification
|
|
type TEXT NOT NULL, -- preference, decision, agreement, profile_fact, mentor_lesson, project_fact
|
|
category TEXT, -- personal, technical, organizational, stylistic
|
|
|
|
-- Content
|
|
text TEXT NOT NULL,
|
|
summary TEXT, -- Short summary for retrieval brief
|
|
|
|
-- Source tracking
|
|
source_ref TEXT, -- conversation_id, message_id, or external source
|
|
source_type TEXT, -- conversation, manual, import, inferred
|
|
|
|
-- Confidence and verification
|
|
confidence REAL DEFAULT 0.7, -- 0.0-1.0
|
|
verified BOOLEAN DEFAULT FALSE,
|
|
verified_by TEXT,
|
|
verified_at TIMESTAMP WITH TIME ZONE,
|
|
|
|
-- Visibility and scope
|
|
visibility TEXT DEFAULT 'platform', -- private_dm, group_only, platform
|
|
scope_ref TEXT, -- group_id if group_only
|
|
|
|
-- Lifecycle
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
expires_at TIMESTAMP WITH TIME ZONE, -- null = never expires
|
|
archived_at TIMESTAMP WITH TIME ZONE,
|
|
|
|
-- Vector reference
|
|
embedding_id TEXT, -- Qdrant point ID
|
|
|
|
metadata JSONB DEFAULT '{}'
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_memory_items_user ON helion_memory_items(platform_user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_memory_items_type ON helion_memory_items(type);
|
|
CREATE INDEX IF NOT EXISTS idx_memory_items_visibility ON helion_memory_items(visibility);
|
|
CREATE INDEX IF NOT EXISTS idx_memory_items_active ON helion_memory_items(platform_user_id)
|
|
WHERE archived_at IS NULL AND (expires_at IS NULL OR expires_at > NOW());
|
|
|
|
-- Memory events (audit log)
|
|
CREATE TABLE IF NOT EXISTS helion_memory_events (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
platform_user_id UUID REFERENCES platform_users(id),
|
|
memory_item_id UUID REFERENCES helion_memory_items(id) ON DELETE SET NULL,
|
|
event_type TEXT NOT NULL, -- add, update, verify, revoke, retrieve, archive
|
|
actor TEXT NOT NULL, -- user, helion, admin, system
|
|
actor_ref TEXT, -- user_id or service name
|
|
payload_json JSONB DEFAULT '{}',
|
|
ts TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_memory_events_user ON helion_memory_events(platform_user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_memory_events_item ON helion_memory_events(memory_item_id);
|
|
CREATE INDEX IF NOT EXISTS idx_memory_events_ts ON helion_memory_events(ts);
|
|
|
|
-- ============================================================================
|
|
-- MENTORS & TRUSTED GROUPS (Updated from v2.3)
|
|
-- ============================================================================
|
|
|
|
-- Mentors table (platform-wide or group-specific)
|
|
CREATE TABLE IF NOT EXISTS helion_mentors (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
platform_user_id UUID REFERENCES platform_users(id),
|
|
scope TEXT DEFAULT 'platform', -- platform, group
|
|
scope_ref TEXT, -- group chat_id if group-scoped
|
|
|
|
-- Telegram info (for matching)
|
|
telegram_user_id TEXT,
|
|
telegram_username TEXT,
|
|
display_name TEXT,
|
|
phone_hash TEXT, -- Hashed phone for matching (privacy)
|
|
|
|
-- Status
|
|
confidence TEXT DEFAULT 'configured', -- configured, confirmed, inferred
|
|
active BOOLEAN DEFAULT TRUE,
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
UNIQUE(platform_user_id, scope, scope_ref)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_mentors_telegram ON helion_mentors(telegram_user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_mentors_username ON helion_mentors(telegram_username);
|
|
|
|
-- Trusted groups/chats
|
|
CREATE TABLE IF NOT EXISTS helion_trusted_groups (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
channel TEXT NOT NULL DEFAULT 'telegram',
|
|
chat_id TEXT NOT NULL,
|
|
chat_username TEXT, -- @energyunionofficial
|
|
chat_title TEXT,
|
|
|
|
-- Settings
|
|
trust_mode BOOLEAN DEFAULT TRUE,
|
|
apprentice_mode BOOLEAN DEFAULT TRUE,
|
|
auto_respond BOOLEAN DEFAULT FALSE, -- Respond even without mention
|
|
|
|
-- Limits
|
|
proactive_questions_per_day INTEGER DEFAULT 3,
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
UNIQUE(channel, chat_id)
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- INITIAL DATA
|
|
-- ============================================================================
|
|
|
|
-- Insert default roles
|
|
INSERT INTO platform_roles (code, display_name, scope, description) VALUES
|
|
('admin', 'Administrator', 'platform', 'Full platform access'),
|
|
('mentor', 'Mentor', 'platform', 'Can teach Helion, elevated trust'),
|
|
('developer', 'Developer', 'platform', 'Technical team member'),
|
|
('investor', 'Investor', 'platform', 'Token holder or investor'),
|
|
('ops', 'Operations', 'platform', 'Operations team member'),
|
|
('moderator', 'Moderator', 'group', 'Group moderator'),
|
|
('member', 'Member', 'platform', 'Regular platform member')
|
|
ON CONFLICT (code) DO NOTHING;
|
|
|
|
-- Insert known mentors
|
|
INSERT INTO helion_mentors (telegram_username, display_name, confidence) VALUES
|
|
('@ivantytar', 'Іван Титар', 'configured'),
|
|
('@archenvis', 'Александр Вертій', 'configured'),
|
|
('@olegarch88', 'Олег Ковальчук', 'configured')
|
|
ON CONFLICT DO NOTHING;
|
|
|
|
-- Insert trusted groups
|
|
INSERT INTO helion_trusted_groups (channel, chat_id, chat_username, chat_title, trust_mode, apprentice_mode) VALUES
|
|
('telegram', '-1001234567890', '@energyunionofficial', 'Energy Union Official', TRUE, TRUE),
|
|
('telegram', '-1009876543210', '@energyunionteam', 'Energy Union Team', TRUE, TRUE)
|
|
ON CONFLICT (channel, chat_id) DO UPDATE SET
|
|
chat_username = EXCLUDED.chat_username,
|
|
chat_title = EXCLUDED.chat_title;
|
|
|
|
-- ============================================================================
|
|
-- HELPER FUNCTIONS
|
|
-- ============================================================================
|
|
|
|
-- Function to resolve or create platform user from channel identity
|
|
CREATE OR REPLACE FUNCTION resolve_platform_user(
|
|
p_channel TEXT,
|
|
p_channel_user_id TEXT,
|
|
p_username TEXT DEFAULT NULL,
|
|
p_display_name TEXT DEFAULT NULL
|
|
) RETURNS UUID AS $$
|
|
DECLARE
|
|
v_platform_user_id UUID;
|
|
v_identity_id UUID;
|
|
BEGIN
|
|
-- Check if identity exists
|
|
SELECT platform_user_id INTO v_platform_user_id
|
|
FROM channel_identities
|
|
WHERE channel = p_channel AND channel_user_id = p_channel_user_id;
|
|
|
|
IF v_platform_user_id IS NULL THEN
|
|
-- Create new platform user
|
|
INSERT INTO platform_users (status) VALUES ('active')
|
|
RETURNING id INTO v_platform_user_id;
|
|
|
|
-- Create channel identity
|
|
INSERT INTO channel_identities (platform_user_id, channel, channel_user_id, username, display_name)
|
|
VALUES (v_platform_user_id, p_channel, p_channel_user_id, p_username, p_display_name);
|
|
ELSE
|
|
-- Update last seen and username if changed
|
|
UPDATE channel_identities
|
|
SET last_seen_at = NOW(),
|
|
username = COALESCE(p_username, username),
|
|
display_name = COALESCE(p_display_name, display_name)
|
|
WHERE channel = p_channel AND channel_user_id = p_channel_user_id;
|
|
END IF;
|
|
|
|
RETURN v_platform_user_id;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- Function to get or create conversation
|
|
CREATE OR REPLACE FUNCTION get_or_create_conversation(
|
|
p_channel TEXT,
|
|
p_chat_id TEXT,
|
|
p_thread_id TEXT DEFAULT NULL,
|
|
p_platform_user_id UUID DEFAULT NULL
|
|
) RETURNS UUID AS $$
|
|
DECLARE
|
|
v_conversation_id UUID;
|
|
BEGIN
|
|
SELECT id INTO v_conversation_id
|
|
FROM helion_conversations
|
|
WHERE channel = p_channel
|
|
AND chat_id = p_chat_id
|
|
AND COALESCE(thread_id, '') = COALESCE(p_thread_id, '');
|
|
|
|
IF v_conversation_id IS NULL THEN
|
|
INSERT INTO helion_conversations (channel, chat_id, thread_id, platform_user_id)
|
|
VALUES (p_channel, p_chat_id, p_thread_id, p_platform_user_id)
|
|
RETURNING id INTO v_conversation_id;
|
|
ELSE
|
|
UPDATE helion_conversations
|
|
SET last_activity_at = NOW()
|
|
WHERE id = v_conversation_id;
|
|
END IF;
|
|
|
|
RETURN v_conversation_id;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- Function to check if user is mentor
|
|
CREATE OR REPLACE FUNCTION is_mentor(
|
|
p_telegram_user_id TEXT DEFAULT NULL,
|
|
p_telegram_username TEXT DEFAULT NULL
|
|
) RETURNS BOOLEAN AS $$
|
|
BEGIN
|
|
RETURN EXISTS (
|
|
SELECT 1 FROM helion_mentors
|
|
WHERE active = TRUE
|
|
AND (telegram_user_id = p_telegram_user_id OR telegram_username = p_telegram_username)
|
|
);
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- Function to check if chat is trusted
|
|
CREATE OR REPLACE FUNCTION is_trusted_group(
|
|
p_channel TEXT,
|
|
p_chat_id TEXT
|
|
) RETURNS BOOLEAN AS $$
|
|
BEGIN
|
|
RETURN EXISTS (
|
|
SELECT 1 FROM helion_trusted_groups
|
|
WHERE channel = p_channel AND chat_id = p_chat_id AND trust_mode = TRUE
|
|
);
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- ============================================================================
|
|
-- COMMENTS
|
|
-- ============================================================================
|
|
|
|
COMMENT ON TABLE platform_users IS 'Global user identity across all channels (L2 PIR)';
|
|
COMMENT ON TABLE channel_identities IS 'Channel-specific user identities linked to platform users';
|
|
COMMENT ON TABLE platform_roles IS 'Available roles in the platform';
|
|
COMMENT ON TABLE user_roles IS 'User role assignments with scope and confidence';
|
|
COMMENT ON TABLE helion_conversations IS 'Chat sessions/conversations';
|
|
COMMENT ON TABLE helion_conversation_state IS 'Session state memory (L1 SSM) per conversation';
|
|
COMMENT ON TABLE helion_media_index IS 'Index of processed media to avoid re-processing';
|
|
COMMENT ON TABLE helion_memory_items IS 'Long-term memory facts (L3 OM)';
|
|
COMMENT ON TABLE helion_memory_events IS 'Audit log of memory operations';
|
|
COMMENT ON TABLE helion_mentors IS 'Configured and confirmed mentors';
|
|
COMMENT ON TABLE helion_trusted_groups IS 'Trusted groups with special settings';
|