Changeset 0.23.0 (#153)

This commit is contained in:
2026-03-05 22:40:26 +00:00
parent 40d9834f64
commit 2fc620e1ac
62 changed files with 6214 additions and 362 deletions

View File

@@ -1,7 +1,7 @@
-- ==========================================
-- Chat Switchboard — 005 Channels & Conversations
-- ==========================================
-- Channels, messages, members, models, cursors, folders, user prefs.
-- Channels, messages, participants, models, cursors, folders, user prefs.
-- ICD §3 (Channels & Conversations)
-- Note: project_id and workspace_id FKs added by 010_projects.sql
-- ==========================================
@@ -38,7 +38,7 @@ CREATE TABLE IF NOT EXISTS channels (
title VARCHAR(500) NOT NULL,
description TEXT,
type VARCHAR(20) DEFAULT 'direct'
CHECK (type IN ('direct', 'group', 'channel')),
CHECK (type IN ('direct', 'group', 'workflow')),
model VARCHAR(100),
system_prompt TEXT,
provider_config_id UUID REFERENCES provider_configs(id) ON DELETE SET NULL,
@@ -73,7 +73,7 @@ DO $$ BEGIN
END $$;
CREATE INDEX IF NOT EXISTS idx_channels_folder ON channels(folder_id) WHERE folder_id IS NOT NULL;
COMMENT ON COLUMN channels.type IS 'direct=1:1 AI chat, group=multi-model, channel=named persistent';
COMMENT ON COLUMN channels.type IS 'direct=single-user chat, group=multi-user/multi-model, workflow=staged channel';
-- =========================================
@@ -94,6 +94,7 @@ CREATE TABLE IF NOT EXISTS messages (
sibling_index INTEGER DEFAULT 0,
participant_type VARCHAR(10) DEFAULT 'user',
participant_id VARCHAR(255),
provider_config_id UUID REFERENCES provider_configs(id) ON DELETE SET NULL,
deleted_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);
@@ -110,35 +111,53 @@ COMMENT ON COLUMN messages.sibling_index IS 'Position among siblings (0-indexed)
-- =========================================
-- CHANNEL MEMBERS & MODELS
-- CHANNEL PARTICIPANTS & MODELS
-- =========================================
-- ICD §3.7: Polymorphic participant system.
-- participant_type determines what participant_id references:
-- user → users.id
-- persona → personas.id
-- session → opaque session token
-- =========================================
CREATE TABLE IF NOT EXISTS channel_members (
CREATE TABLE IF NOT EXISTS channel_participants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
channel_id UUID NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
role VARCHAR(20) DEFAULT 'member',
participant_type VARCHAR(10) NOT NULL DEFAULT 'user'
CHECK (participant_type IN ('user', 'persona', 'session')),
participant_id UUID NOT NULL,
role VARCHAR(10) NOT NULL DEFAULT 'member'
CHECK (role IN ('owner', 'member', 'observer')),
display_name VARCHAR(200),
avatar_url TEXT,
joined_at TIMESTAMPTZ DEFAULT NOW(),
last_read_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(channel_id, user_id)
UNIQUE(channel_id, participant_type, participant_id)
);
CREATE INDEX IF NOT EXISTS idx_channel_members_channel ON channel_members(channel_id);
CREATE INDEX IF NOT EXISTS idx_channel_members_user ON channel_members(user_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 UUID PRIMARY KEY DEFAULT gen_random_uuid(),
channel_id UUID NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
model_id VARCHAR(255) NOT NULL,
provider_config_id UUID REFERENCES provider_configs(id) ON DELETE SET NULL,
persona_id UUID REFERENCES personas(id) ON DELETE SET NULL,
display_name VARCHAR(100),
system_prompt TEXT,
settings JSONB DEFAULT '{}'::jsonb,
is_default BOOLEAN DEFAULT false,
added_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(channel_id, model_id)
added_at TIMESTAMPTZ DEFAULT NOW()
);
-- Raw model entries (no persona): unique per channel+model+provider
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;
-- Persona entries: one per persona per channel (same model allowed for different personas)
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);
@@ -167,13 +186,14 @@ CREATE TABLE IF NOT EXISTS user_model_settings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
model_id TEXT NOT NULL,
provider_config_id UUID REFERENCES provider_configs(id) ON DELETE CASCADE,
hidden BOOLEAN DEFAULT false,
preferred_temperature FLOAT,
preferred_max_tokens INT,
sort_order INT DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(user_id, model_id)
UNIQUE(user_id, model_id, provider_config_id)
);
CREATE INDEX IF NOT EXISTS idx_user_model_settings_user ON user_model_settings(user_id);