This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/server/database/migrations/sqlite/005_channels.sql
2026-03-11 11:22:38 +00:00

159 lines
6.9 KiB
SQL

-- Chat Switchboard — 005 Channels & Conversations (SQLite)
-- Consolidated v0.28.0
CREATE TABLE IF NOT EXISTS folders (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT NOT NULL,
parent_id TEXT REFERENCES folders(id) ON DELETE CASCADE,
sort_order INTEGER DEFAULT 0,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now')),
UNIQUE(user_id, name, parent_id)
);
CREATE INDEX IF NOT EXISTS idx_folders_user ON folders(user_id);
CREATE INDEX IF NOT EXISTS idx_folders_parent ON folders(parent_id);
CREATE TABLE IF NOT EXISTS channels (
id TEXT PRIMARY KEY,
user_id TEXT REFERENCES users(id) ON DELETE CASCADE,
title TEXT NOT NULL,
description TEXT,
type TEXT DEFAULT 'direct'
CHECK (type IN ('direct', 'dm', 'group', 'channel', 'workflow', 'service')),
model TEXT,
system_prompt TEXT,
provider_config_id TEXT REFERENCES provider_configs(id) ON DELETE SET NULL,
is_archived INTEGER DEFAULT 0,
is_pinned INTEGER DEFAULT 0,
folder_id TEXT REFERENCES folders(id) ON DELETE SET NULL,
folder TEXT,
team_id TEXT REFERENCES teams(id) ON DELETE SET NULL,
settings TEXT DEFAULT '{}',
tags TEXT DEFAULT '[]',
ai_mode TEXT NOT NULL DEFAULT 'auto',
topic TEXT,
allow_anonymous INTEGER NOT NULL DEFAULT 0,
workflow_id TEXT,
workflow_version INTEGER,
current_stage INTEGER DEFAULT 0,
stage_data TEXT DEFAULT '{}',
workflow_status TEXT DEFAULT 'active'
CHECK (workflow_status IN ('active', 'completed', 'stale', 'cancelled')),
last_activity_at TEXT DEFAULT (datetime('now')),
kb_auto_inject INTEGER NOT NULL DEFAULT 0,
project_id TEXT,
workspace_id TEXT,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_channels_user ON channels(user_id);
CREATE INDEX IF NOT EXISTS idx_channels_updated ON channels(updated_at);
CREATE INDEX IF NOT EXISTS idx_channels_type ON channels(type);
CREATE INDEX IF NOT EXISTS idx_channels_team ON channels(team_id);
CREATE INDEX IF NOT EXISTS idx_channels_folder ON channels(folder_id);
CREATE INDEX IF NOT EXISTS idx_channels_project ON channels(project_id);
CREATE INDEX IF NOT EXISTS idx_channels_workspace ON channels(workspace_id);
CREATE INDEX IF NOT EXISTS idx_channels_workflow ON channels(workflow_id);
CREATE TABLE IF NOT EXISTS messages (
id TEXT PRIMARY KEY,
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
role TEXT NOT NULL CHECK (role IN ('user', 'assistant', 'system', 'tool')),
content TEXT NOT NULL,
model TEXT,
tokens_used INTEGER,
tool_calls TEXT,
metadata TEXT DEFAULT '{}',
parent_id TEXT REFERENCES messages(id) ON DELETE SET NULL,
sibling_index INTEGER DEFAULT 0,
participant_type TEXT DEFAULT 'user',
participant_id TEXT,
provider_config_id TEXT REFERENCES provider_configs(id) ON DELETE SET NULL,
deleted_at TEXT,
created_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_messages_channel ON messages(channel_id, created_at);
CREATE INDEX IF NOT EXISTS idx_messages_parent ON messages(parent_id);
CREATE TABLE IF NOT EXISTS channel_participants (
id TEXT PRIMARY KEY,
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
participant_type TEXT NOT NULL DEFAULT 'user'
CHECK (participant_type IN ('user', 'persona', 'session')),
participant_id TEXT NOT NULL,
role TEXT NOT NULL DEFAULT 'member'
CHECK (role IN ('owner', 'member', 'observer')),
display_name TEXT,
avatar_url TEXT,
joined_at TEXT DEFAULT (datetime('now')),
last_read_at TEXT DEFAULT (datetime('now')),
last_read_message_id TEXT,
UNIQUE(channel_id, participant_type, participant_id)
);
CREATE INDEX IF NOT EXISTS idx_channel_participants_channel ON channel_participants(channel_id);
CREATE INDEX IF NOT EXISTS idx_channel_participants_ref ON channel_participants(participant_type, participant_id);
CREATE TABLE IF NOT EXISTS channel_models (
id TEXT PRIMARY KEY,
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
model_id TEXT NOT NULL,
provider_config_id TEXT REFERENCES provider_configs(id) ON DELETE SET NULL,
persona_id TEXT REFERENCES personas(id) ON DELETE SET NULL,
display_name TEXT,
system_prompt TEXT,
settings TEXT DEFAULT '{}',
is_default INTEGER DEFAULT 0,
added_at TEXT DEFAULT (datetime('now'))
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_channel_models_raw
ON channel_models(channel_id, model_id, provider_config_id) WHERE persona_id IS NULL;
CREATE UNIQUE INDEX IF NOT EXISTS idx_channel_models_persona
ON channel_models(channel_id, persona_id) WHERE persona_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_channel_models_channel ON channel_models(channel_id);
CREATE TABLE IF NOT EXISTS channel_cursors (
id TEXT PRIMARY KEY,
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
active_leaf_id TEXT REFERENCES messages(id) ON DELETE SET NULL,
updated_at TEXT DEFAULT (datetime('now')),
UNIQUE(channel_id, user_id)
);
CREATE INDEX IF NOT EXISTS idx_channel_cursors_channel ON channel_cursors(channel_id);
CREATE INDEX IF NOT EXISTS idx_channel_cursors_user ON channel_cursors(user_id);
CREATE TABLE IF NOT EXISTS user_model_settings (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
model_id TEXT NOT NULL,
provider_config_id TEXT REFERENCES provider_configs(id) ON DELETE CASCADE,
hidden INTEGER DEFAULT 0,
preferred_temperature REAL,
preferred_max_tokens INTEGER,
sort_order INTEGER DEFAULT 0,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now')),
UNIQUE(user_id, model_id, provider_config_id)
);
CREATE INDEX IF NOT EXISTS idx_user_model_settings_user ON user_model_settings(user_id);
CREATE TABLE IF NOT EXISTS session_participants (
id TEXT PRIMARY KEY,
session_token TEXT NOT NULL UNIQUE,
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
display_name TEXT NOT NULL DEFAULT 'Visitor',
fingerprint TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_session_participants_channel ON session_participants(channel_id);
CREATE INDEX IF NOT EXISTS idx_session_participants_token ON session_participants(session_token);