-- ========================================== -- Chat Switchboard - Initial Schema -- ========================================== -- PostgreSQL migration for backend support -- Enable UUID extension CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- Users table (optional, for multi-user support) CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), email VARCHAR(255) UNIQUE, password_hash VARCHAR(255), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- API configurations per user CREATE TABLE api_configs ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id UUID REFERENCES users(id) ON DELETE CASCADE, name VARCHAR(100) NOT NULL DEFAULT 'default', endpoint VARCHAR(500) NOT NULL, api_key_encrypted TEXT NOT NULL, is_default BOOLEAN DEFAULT FALSE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(user_id, name) ); -- User settings CREATE TABLE user_settings ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id UUID UNIQUE REFERENCES users(id) ON DELETE CASCADE, default_model VARCHAR(100) DEFAULT 'gpt-3.5-turbo', stream_responses BOOLEAN DEFAULT TRUE, show_thinking BOOLEAN DEFAULT TRUE, system_prompt TEXT, max_tokens INTEGER DEFAULT 4096, temperature DECIMAL(3,2) DEFAULT 0.7, top_p DECIMAL(3,2) DEFAULT 1.0, presence_penalty DECIMAL(3,2) DEFAULT 0.0, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Chats CREATE TABLE chats ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id UUID REFERENCES users(id) ON DELETE CASCADE, title VARCHAR(255) NOT NULL, model VARCHAR(100), api_config_id UUID REFERENCES api_configs(id) ON DELETE SET NULL, is_archived BOOLEAN DEFAULT FALSE, is_pinned BOOLEAN DEFAULT FALSE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Messages CREATE TABLE messages ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), chat_id UUID NOT NULL REFERENCES chats(id) ON DELETE CASCADE, role VARCHAR(20) NOT NULL CHECK (role IN ('system', 'user', 'assistant')), content TEXT NOT NULL, model VARCHAR(100), tokens_used INTEGER, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Cached models per API config CREATE TABLE cached_models ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), api_config_id UUID NOT NULL REFERENCES api_configs(id) ON DELETE CASCADE, model_id VARCHAR(100) NOT NULL, owned_by VARCHAR(100), cached_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(api_config_id, model_id) ); -- Indexes for performance CREATE INDEX idx_chats_user_id ON chats(user_id); CREATE INDEX idx_chats_updated_at ON chats(updated_at DESC); CREATE INDEX idx_messages_chat_id ON messages(chat_id); CREATE INDEX idx_messages_created_at ON messages(created_at); CREATE INDEX idx_api_configs_user_id ON api_configs(user_id); -- Updated at trigger function CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ language 'plpgsql'; -- Apply updated_at triggers CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_api_configs_updated_at BEFORE UPDATE ON api_configs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_user_settings_updated_at BEFORE UPDATE ON user_settings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_chats_updated_at BEFORE UPDATE ON chats FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); -- View for chat list with message count CREATE VIEW chat_list AS SELECT c.id, c.user_id, c.title, c.model, c.is_archived, c.is_pinned, c.created_at, c.updated_at, COUNT(m.id) as message_count, MAX(m.created_at) as last_message_at FROM chats c LEFT JOIN messages m ON m.chat_id = c.id GROUP BY c.id;