mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-25 07:00:48 +09:00
refactor: unify providers and models tables
- Rename `llm_providers` → `providers`, `llm_provider_oauth_tokens` → `provider_oauth_tokens` - Remove `tts_providers` and `tts_models` tables; speech models now live in the unified `models` table with `type = 'speech'` - Replace top-level `api_key`/`base_url` columns with a JSONB `config` field on `providers` - Rename `llm_provider_id` → `provider_id` across all references - Add `edge-speech` client type and `conf/providers/edge.yaml` default provider - Create new read-only speech endpoints (`/speech-providers`, `/speech-models`) backed by filtered views of the unified tables - Remove old TTS CRUD handlers; simplify speech page to read-only + test - Update registry loader to skip malformed YAML files instead of failing entirely - Fix YAML quoting for model names containing colons in openrouter.yaml - Regenerate sqlc, swagger, and TypeScript SDK
This commit is contained in:
@@ -20,12 +20,13 @@ DROP TABLE IF EXISTS email_outbox;
|
||||
DROP TABLE IF EXISTS bot_email_bindings;
|
||||
DROP TABLE IF EXISTS email_oauth_tokens;
|
||||
DROP TABLE IF EXISTS email_providers;
|
||||
DROP TABLE IF EXISTS provider_oauth_tokens;
|
||||
DROP TABLE IF EXISTS bots;
|
||||
DROP TABLE IF EXISTS memory_providers;
|
||||
DROP TABLE IF EXISTS model_variants;
|
||||
DROP TABLE IF EXISTS models;
|
||||
DROP TABLE IF EXISTS search_providers;
|
||||
DROP TABLE IF EXISTS llm_providers;
|
||||
DROP TABLE IF EXISTS providers;
|
||||
DROP TABLE IF EXISTS user_channel_bindings;
|
||||
DROP TABLE IF EXISTS channel_identities;
|
||||
DROP TABLE IF EXISTS users;
|
||||
|
||||
@@ -57,19 +57,21 @@ CREATE TABLE IF NOT EXISTS user_channel_bindings (
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_user_channel_bindings_user_id ON user_channel_bindings(user_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS llm_providers (
|
||||
CREATE TABLE IF NOT EXISTS providers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
base_url TEXT NOT NULL,
|
||||
api_key TEXT NOT NULL,
|
||||
client_type TEXT NOT NULL DEFAULT 'openai-completions',
|
||||
icon TEXT,
|
||||
enable BOOLEAN NOT NULL DEFAULT true,
|
||||
config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CONSTRAINT llm_providers_name_unique UNIQUE (name),
|
||||
CONSTRAINT llm_providers_client_type_check CHECK (client_type IN ('openai-responses', 'openai-completions', 'anthropic-messages', 'google-generative-ai', 'openai-codex'))
|
||||
CONSTRAINT providers_name_unique UNIQUE (name),
|
||||
CONSTRAINT providers_client_type_check CHECK (client_type IN (
|
||||
'openai-responses', 'openai-completions', 'anthropic-messages',
|
||||
'google-generative-ai', 'openai-codex', 'edge-speech'
|
||||
))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS search_providers (
|
||||
@@ -87,13 +89,13 @@ CREATE TABLE IF NOT EXISTS models (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
model_id TEXT NOT NULL,
|
||||
name TEXT,
|
||||
llm_provider_id UUID NOT NULL REFERENCES llm_providers(id) ON DELETE CASCADE,
|
||||
provider_id UUID NOT NULL REFERENCES providers(id) ON DELETE CASCADE,
|
||||
type TEXT NOT NULL DEFAULT 'chat',
|
||||
config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CONSTRAINT models_provider_model_id_unique UNIQUE (llm_provider_id, model_id),
|
||||
CONSTRAINT models_type_check CHECK (type IN ('chat', 'embedding'))
|
||||
CONSTRAINT models_provider_id_model_id_unique UNIQUE (provider_id, model_id),
|
||||
CONSTRAINT models_type_check CHECK (type IN ('chat', 'embedding', 'speech'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS model_variants (
|
||||
@@ -120,30 +122,6 @@ CREATE TABLE IF NOT EXISTS memory_providers (
|
||||
CONSTRAINT memory_providers_name_unique UNIQUE (name)
|
||||
);
|
||||
|
||||
-- tts_providers: pluggable TTS service backends
|
||||
CREATE TABLE IF NOT EXISTS tts_providers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
enable BOOLEAN NOT NULL DEFAULT false,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CONSTRAINT tts_providers_name_unique UNIQUE (name)
|
||||
);
|
||||
|
||||
-- tts_models: available models per TTS provider with per-model configuration
|
||||
CREATE TABLE IF NOT EXISTS tts_models (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
model_id TEXT NOT NULL,
|
||||
name TEXT,
|
||||
tts_provider_id UUID NOT NULL REFERENCES tts_providers(id) ON DELETE CASCADE,
|
||||
config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_tts_models_provider_id ON tts_models(tts_provider_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS browser_contexts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
@@ -179,7 +157,7 @@ CREATE TABLE IF NOT EXISTS bots (
|
||||
title_model_id UUID REFERENCES models(id) ON DELETE SET NULL,
|
||||
image_model_id UUID REFERENCES models(id) ON DELETE SET NULL,
|
||||
discuss_probe_model_id UUID REFERENCES models(id) ON DELETE SET NULL,
|
||||
tts_model_id UUID REFERENCES tts_models(id) ON DELETE SET NULL,
|
||||
tts_model_id UUID REFERENCES models(id) ON DELETE SET NULL,
|
||||
browser_context_id UUID REFERENCES browser_contexts(id) ON DELETE SET NULL,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
@@ -651,3 +629,20 @@ CREATE TABLE IF NOT EXISTS email_outbox (
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_email_outbox_provider_id ON email_outbox(provider_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_email_outbox_bot_id ON email_outbox(bot_id, created_at DESC);
|
||||
|
||||
-- provider_oauth_tokens: OAuth token storage for providers (e.g. OpenAI Codex OAuth)
|
||||
CREATE TABLE IF NOT EXISTS provider_oauth_tokens (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
provider_id UUID NOT NULL UNIQUE REFERENCES providers(id) ON DELETE CASCADE,
|
||||
access_token TEXT NOT NULL DEFAULT '',
|
||||
refresh_token TEXT NOT NULL DEFAULT '',
|
||||
expires_at TIMESTAMPTZ,
|
||||
scope TEXT NOT NULL DEFAULT '',
|
||||
token_type TEXT NOT NULL DEFAULT '',
|
||||
state TEXT NOT NULL DEFAULT '',
|
||||
pkce_code_verifier TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_oauth_tokens_state ON provider_oauth_tokens(state) WHERE state != '';
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
-- 0010_client_type_to_model
|
||||
-- Move client_type from llm_providers to models, rename to new values, drop unsupported types.
|
||||
-- NOTE: This migration is a no-op on fresh databases where the canonical schema already applies.
|
||||
|
||||
-- 1) Add client_type column to models (nullable)
|
||||
ALTER TABLE models ADD COLUMN IF NOT EXISTS client_type TEXT;
|
||||
|
||||
-- 2-5) Only run data migration when upgrading from old schema that had client_type on llm_providers.
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'llm_providers') THEN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
-- 1) Add client_type column to models (nullable)
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'models' AND column_name = 'client_type') THEN
|
||||
ALTER TABLE models ADD COLUMN client_type TEXT;
|
||||
END IF;
|
||||
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = 'llm_providers' AND column_name = 'client_type'
|
||||
) THEN
|
||||
-- Migrate data from provider to model with name mapping
|
||||
UPDATE models SET client_type = CASE p.client_type
|
||||
WHEN 'openai' THEN 'openai-responses'
|
||||
WHEN 'openai-compat' THEN 'openai-completions'
|
||||
@@ -22,17 +27,10 @@ BEGIN
|
||||
WHERE models.llm_provider_id = p.id
|
||||
AND p.client_type IN ('openai', 'openai-compat', 'anthropic', 'google');
|
||||
|
||||
-- Delete models whose provider had an unsupported client_type
|
||||
DELETE FROM models WHERE client_type IS NULL AND type = 'chat';
|
||||
|
||||
-- Delete providers with unsupported client_type
|
||||
DELETE FROM llm_providers WHERE client_type NOT IN ('openai', 'openai-compat', 'anthropic', 'google');
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 6) Add CHECK constraints (skip if already present from init migration)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'models_client_type_check') THEN
|
||||
ALTER TABLE models ADD CONSTRAINT models_client_type_check
|
||||
CHECK (client_type IS NULL OR client_type IN ('openai-responses', 'openai-completions', 'anthropic-messages', 'google-generative-ai'));
|
||||
@@ -41,8 +39,7 @@ BEGIN
|
||||
ALTER TABLE models ADD CONSTRAINT models_chat_client_type_check
|
||||
CHECK (type != 'chat' OR client_type IS NOT NULL);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 7) Drop client_type from llm_providers
|
||||
ALTER TABLE llm_providers DROP CONSTRAINT IF EXISTS llm_providers_client_type_check;
|
||||
ALTER TABLE llm_providers DROP COLUMN IF EXISTS client_type;
|
||||
ALTER TABLE llm_providers DROP CONSTRAINT IF EXISTS llm_providers_client_type_check;
|
||||
ALTER TABLE llm_providers DROP COLUMN IF EXISTS client_type;
|
||||
END $$;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
-- 0013_model_id_unique_per_provider
|
||||
-- Change model_id uniqueness from global to per provider.
|
||||
-- NOTE: On fresh databases the canonical schema already has the correct constraint.
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
@@ -7,9 +8,12 @@ BEGIN
|
||||
ALTER TABLE models DROP CONSTRAINT models_model_id_unique;
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'models_provider_model_id_unique') THEN
|
||||
ALTER TABLE models
|
||||
ADD CONSTRAINT models_provider_model_id_unique UNIQUE (llm_provider_id, model_id);
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'models_provider_model_id_unique')
|
||||
AND NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'models_provider_id_model_id_unique') THEN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'models' AND column_name = 'llm_provider_id') THEN
|
||||
ALTER TABLE models
|
||||
ADD CONSTRAINT models_provider_model_id_unique UNIQUE (llm_provider_id, model_id);
|
||||
END IF;
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
|
||||
@@ -1,41 +1,54 @@
|
||||
-- 0029_tts_provider
|
||||
-- Add TTS provider/model tables and bots.tts_model_id for existing databases.
|
||||
-- NOTE: On fresh databases these tables are replaced by unified providers/models via 0061.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tts_providers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT tts_providers_name_unique UNIQUE (name)
|
||||
);
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'tts_providers') THEN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tts_models (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
model_id TEXT NOT NULL,
|
||||
name TEXT,
|
||||
tts_provider_id UUID NOT NULL REFERENCES tts_providers(id) ON DELETE CASCADE,
|
||||
config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT tts_models_provider_model_id_unique UNIQUE (tts_provider_id, model_id)
|
||||
);
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'providers') THEN
|
||||
CREATE TABLE IF NOT EXISTS tts_providers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT tts_providers_name_unique UNIQUE (name)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_tts_models_provider_id ON tts_models(tts_provider_id);
|
||||
CREATE TABLE IF NOT EXISTS tts_models (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
model_id TEXT NOT NULL,
|
||||
name TEXT,
|
||||
tts_provider_id UUID NOT NULL REFERENCES tts_providers(id) ON DELETE CASCADE,
|
||||
config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT tts_models_provider_model_id_unique UNIQUE (tts_provider_id, model_id)
|
||||
);
|
||||
|
||||
ALTER TABLE bots
|
||||
ADD COLUMN IF NOT EXISTS tts_model_id UUID;
|
||||
CREATE INDEX IF NOT EXISTS idx_tts_models_provider_id ON tts_models(tts_provider_id);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
ALTER TABLE bots ADD COLUMN IF NOT EXISTS tts_model_id UUID;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'bots_tts_model_id_fkey'
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'bots_tts_model_id_fkey'
|
||||
) THEN
|
||||
ALTER TABLE bots
|
||||
ADD CONSTRAINT bots_tts_model_id_fkey
|
||||
FOREIGN KEY (tts_model_id) REFERENCES tts_models(id) ON DELETE SET NULL;
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'tts_models') THEN
|
||||
ALTER TABLE bots
|
||||
ADD CONSTRAINT bots_tts_model_id_fkey
|
||||
FOREIGN KEY (tts_model_id) REFERENCES tts_models(id) ON DELETE SET NULL;
|
||||
ELSE
|
||||
ALTER TABLE bots
|
||||
ADD CONSTRAINT bots_tts_model_id_fkey
|
||||
FOREIGN KEY (tts_model_id) REFERENCES models(id) ON DELETE SET NULL;
|
||||
END IF;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
-- 0030_drop_tts_model_unique
|
||||
-- Drop unique constraint on (tts_provider_id, model_id) to allow multiple
|
||||
-- models with the same model_id under one provider (different configs).
|
||||
-- NOTE: No-op on fresh databases where tts_models no longer exists.
|
||||
|
||||
ALTER TABLE tts_models
|
||||
DROP CONSTRAINT IF EXISTS tts_models_provider_model_id_unique;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'tts_models') THEN
|
||||
ALTER TABLE tts_models DROP CONSTRAINT IF EXISTS tts_models_provider_model_id_unique;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
-- 0041_provider_model_refactor
|
||||
-- Move client_type to llm_providers, add icon, replace model columns with config JSONB.
|
||||
-- NOTE: This migration is a no-op on fresh databases where the canonical schema already applies.
|
||||
|
||||
-- 1. Add client_type and icon to llm_providers
|
||||
ALTER TABLE llm_providers
|
||||
ADD COLUMN IF NOT EXISTS client_type TEXT NOT NULL DEFAULT 'openai-completions',
|
||||
ADD COLUMN IF NOT EXISTS icon TEXT;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'llm_providers') THEN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
ALTER TABLE llm_providers
|
||||
ADD COLUMN IF NOT EXISTS client_type TEXT NOT NULL DEFAULT 'openai-completions',
|
||||
ADD COLUMN IF NOT EXISTS icon TEXT;
|
||||
|
||||
-- 2–6. Backfill and migrate only when old columns exist (idempotent for fresh DBs).
|
||||
DO $$ BEGIN
|
||||
-- Back-fill provider client_type from models.client_type (old column)
|
||||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'models' AND column_name = 'client_type') THEN
|
||||
UPDATE llm_providers p
|
||||
SET client_type = sub.client_type
|
||||
@@ -21,19 +24,16 @@ DO $$ BEGIN
|
||||
WHERE p.id = sub.llm_provider_id;
|
||||
END IF;
|
||||
|
||||
-- Add CHECK constraint (skip if already present)
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'llm_providers_client_type_check') THEN
|
||||
ALTER TABLE llm_providers
|
||||
ADD CONSTRAINT llm_providers_client_type_check
|
||||
CHECK (client_type IN ('openai-responses', 'openai-completions', 'anthropic-messages', 'google-generative-ai'));
|
||||
END IF;
|
||||
|
||||
-- Add config JSONB to models
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'models' AND column_name = 'config') THEN
|
||||
ALTER TABLE models ADD COLUMN config JSONB NOT NULL DEFAULT '{}'::jsonb;
|
||||
END IF;
|
||||
|
||||
-- Migrate existing columns into config (only when old columns exist)
|
||||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'models' AND column_name = 'dimensions') THEN
|
||||
UPDATE models SET config = jsonb_strip_nulls(jsonb_build_object(
|
||||
'dimensions', dimensions,
|
||||
@@ -51,11 +51,9 @@ DO $$ BEGIN
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Drop old columns and constraints (IF EXISTS makes these safe on fresh DBs)
|
||||
ALTER TABLE models DROP CONSTRAINT IF EXISTS models_client_type_check;
|
||||
ALTER TABLE models DROP CONSTRAINT IF EXISTS models_chat_client_type_check;
|
||||
ALTER TABLE models DROP CONSTRAINT IF EXISTS models_dimensions_check;
|
||||
|
||||
ALTER TABLE models DROP COLUMN IF EXISTS client_type;
|
||||
ALTER TABLE models DROP COLUMN IF EXISTS dimensions;
|
||||
ALTER TABLE models DROP COLUMN IF EXISTS input_modalities;
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
-- 0042_provider_enable
|
||||
-- Add enable column to llm_providers for built-in provider registry support.
|
||||
-- NOTE: This migration is a no-op on fresh databases where the canonical schema already applies.
|
||||
|
||||
ALTER TABLE llm_providers
|
||||
ADD COLUMN IF NOT EXISTS enable BOOLEAN NOT NULL DEFAULT true;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'llm_providers') THEN
|
||||
ALTER TABLE llm_providers ADD COLUMN IF NOT EXISTS enable BOOLEAN NOT NULL DEFAULT true;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
@@ -1,18 +1,38 @@
|
||||
-- 0046_llm_provider_oauth
|
||||
-- Add OAuth token storage for LLM providers to support OpenAI Codex OAuth.
|
||||
-- Add OAuth token storage for providers to support OpenAI Codex OAuth.
|
||||
-- NOTE: On fresh databases, table is named provider_oauth_tokens via 0061.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS llm_provider_oauth_tokens (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
llm_provider_id UUID NOT NULL UNIQUE REFERENCES llm_providers(id) ON DELETE CASCADE,
|
||||
access_token TEXT NOT NULL DEFAULT '',
|
||||
refresh_token TEXT NOT NULL DEFAULT '',
|
||||
expires_at TIMESTAMPTZ,
|
||||
scope TEXT NOT NULL DEFAULT '',
|
||||
token_type TEXT NOT NULL DEFAULT '',
|
||||
state TEXT NOT NULL DEFAULT '',
|
||||
pkce_code_verifier TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_llm_provider_oauth_tokens_state ON llm_provider_oauth_tokens(state) WHERE state != '';
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'llm_providers') THEN
|
||||
CREATE TABLE IF NOT EXISTS llm_provider_oauth_tokens (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
llm_provider_id UUID NOT NULL UNIQUE REFERENCES llm_providers(id) ON DELETE CASCADE,
|
||||
access_token TEXT NOT NULL DEFAULT '',
|
||||
refresh_token TEXT NOT NULL DEFAULT '',
|
||||
expires_at TIMESTAMPTZ,
|
||||
scope TEXT NOT NULL DEFAULT '',
|
||||
token_type TEXT NOT NULL DEFAULT '',
|
||||
state TEXT NOT NULL DEFAULT '',
|
||||
pkce_code_verifier TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_llm_provider_oauth_tokens_state ON llm_provider_oauth_tokens(state) WHERE state != '';
|
||||
ELSIF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'provider_oauth_tokens') THEN
|
||||
CREATE TABLE IF NOT EXISTS provider_oauth_tokens (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
provider_id UUID NOT NULL UNIQUE REFERENCES providers(id) ON DELETE CASCADE,
|
||||
access_token TEXT NOT NULL DEFAULT '',
|
||||
refresh_token TEXT NOT NULL DEFAULT '',
|
||||
expires_at TIMESTAMPTZ,
|
||||
scope TEXT NOT NULL DEFAULT '',
|
||||
token_type TEXT NOT NULL DEFAULT '',
|
||||
state TEXT NOT NULL DEFAULT '',
|
||||
pkce_code_verifier TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_oauth_tokens_state ON provider_oauth_tokens(state) WHERE state != '';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
-- 0047_add_openai_codex_client_type
|
||||
-- Add openai-codex as a first-class client_type and migrate existing codex-oauth providers.
|
||||
-- NOTE: This migration is a no-op on fresh databases where the canonical schema already applies.
|
||||
|
||||
ALTER TABLE llm_providers DROP CONSTRAINT IF EXISTS llm_providers_client_type_check;
|
||||
ALTER TABLE llm_providers ADD CONSTRAINT llm_providers_client_type_check
|
||||
CHECK (client_type IN ('openai-responses', 'openai-completions', 'anthropic-messages', 'google-generative-ai', 'openai-codex'));
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'llm_providers') THEN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
UPDATE llm_providers
|
||||
SET client_type = 'openai-codex',
|
||||
updated_at = now()
|
||||
WHERE client_type = 'openai-responses'
|
||||
AND metadata->>'auth_type' = 'openai-codex-oauth';
|
||||
ALTER TABLE llm_providers DROP CONSTRAINT IF EXISTS llm_providers_client_type_check;
|
||||
ALTER TABLE llm_providers ADD CONSTRAINT llm_providers_client_type_check
|
||||
CHECK (client_type IN ('openai-responses', 'openai-completions', 'anthropic-messages', 'google-generative-ai', 'openai-codex'));
|
||||
|
||||
UPDATE llm_providers
|
||||
SET client_type = 'openai-codex',
|
||||
updated_at = now()
|
||||
WHERE client_type = 'openai-responses'
|
||||
AND metadata->>'auth_type' = 'openai-codex-oauth';
|
||||
END $$;
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
-- 0050_tts_provider_enable
|
||||
-- Add enable column to tts_providers table for toggling providers on/off.
|
||||
-- NOTE: No-op on fresh databases where tts_providers no longer exists.
|
||||
|
||||
ALTER TABLE tts_providers ADD COLUMN IF NOT EXISTS enable BOOLEAN NOT NULL DEFAULT false;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'tts_providers') THEN
|
||||
ALTER TABLE tts_providers ADD COLUMN IF NOT EXISTS enable BOOLEAN NOT NULL DEFAULT false;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
-- 0061_unify_providers (rollback)
|
||||
-- Reverse the provider unification: restore llm_providers, tts_providers, tts_models.
|
||||
|
||||
-- Step 1: Rename provider_oauth_tokens back
|
||||
ALTER INDEX IF EXISTS idx_provider_oauth_tokens_state RENAME TO idx_llm_provider_oauth_tokens_state;
|
||||
ALTER TABLE provider_oauth_tokens RENAME COLUMN provider_id TO llm_provider_id;
|
||||
ALTER TABLE provider_oauth_tokens RENAME TO llm_provider_oauth_tokens;
|
||||
|
||||
-- Step 2: Recreate tts_providers and tts_models
|
||||
CREATE TABLE IF NOT EXISTS tts_providers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
enable BOOLEAN NOT NULL DEFAULT false,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CONSTRAINT tts_providers_name_unique UNIQUE (name)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tts_models (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
model_id TEXT NOT NULL,
|
||||
name TEXT,
|
||||
tts_provider_id UUID NOT NULL REFERENCES tts_providers(id) ON DELETE CASCADE,
|
||||
config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_tts_models_provider_id ON tts_models(tts_provider_id);
|
||||
|
||||
-- Step 3: Migrate speech providers back to tts_providers
|
||||
INSERT INTO tts_providers (id, name, provider, config, enable, created_at, updated_at)
|
||||
SELECT id, name,
|
||||
CASE WHEN client_type = 'edge-speech' THEN 'edge' ELSE client_type END,
|
||||
config, enable, created_at, updated_at
|
||||
FROM providers
|
||||
WHERE client_type = 'edge-speech';
|
||||
|
||||
-- Step 4: Migrate speech models back to tts_models
|
||||
INSERT INTO tts_models (id, model_id, name, tts_provider_id, config, created_at, updated_at)
|
||||
SELECT id, model_id, name, provider_id, config, created_at, updated_at
|
||||
FROM models
|
||||
WHERE type = 'speech';
|
||||
|
||||
-- Step 5: Update bots FK back to tts_models
|
||||
ALTER TABLE bots DROP CONSTRAINT IF EXISTS bots_tts_model_id_fkey;
|
||||
ALTER TABLE bots ADD CONSTRAINT bots_tts_model_id_fkey
|
||||
FOREIGN KEY (tts_model_id) REFERENCES tts_models(id) ON DELETE SET NULL;
|
||||
|
||||
-- Step 6: Remove speech models and providers from unified tables
|
||||
DELETE FROM models WHERE type = 'speech';
|
||||
DELETE FROM providers WHERE client_type = 'edge-speech';
|
||||
|
||||
-- Step 7: Restore models type CHECK
|
||||
ALTER TABLE models DROP CONSTRAINT models_type_check;
|
||||
ALTER TABLE models ADD CONSTRAINT models_type_check CHECK (type IN ('chat', 'embedding'));
|
||||
|
||||
-- Step 8: Rename provider_id back to llm_provider_id
|
||||
ALTER TABLE models RENAME CONSTRAINT models_provider_id_model_id_unique TO models_provider_model_id_unique;
|
||||
ALTER TABLE models RENAME COLUMN provider_id TO llm_provider_id;
|
||||
|
||||
-- Step 9: Restore client_type CHECK
|
||||
ALTER TABLE providers DROP CONSTRAINT providers_client_type_check;
|
||||
ALTER TABLE providers ADD CONSTRAINT llm_providers_client_type_check CHECK (
|
||||
client_type IN ('openai-responses', 'openai-completions', 'anthropic-messages', 'google-generative-ai', 'openai-codex')
|
||||
);
|
||||
|
||||
-- Step 10: Restore api_key and base_url columns from config
|
||||
ALTER TABLE providers ADD COLUMN base_url TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE providers ADD COLUMN api_key TEXT NOT NULL DEFAULT '';
|
||||
UPDATE providers SET
|
||||
base_url = COALESCE(config->>'base_url', ''),
|
||||
api_key = COALESCE(config->>'api_key', '');
|
||||
ALTER TABLE providers DROP COLUMN config;
|
||||
|
||||
-- Step 11: Rename providers back to llm_providers
|
||||
ALTER TABLE providers RENAME CONSTRAINT providers_name_unique TO llm_providers_name_unique;
|
||||
ALTER TABLE providers RENAME TO llm_providers;
|
||||
@@ -0,0 +1,94 @@
|
||||
-- 0061_unify_providers
|
||||
-- Unify llm_providers and tts_providers/tts_models into a single providers/models schema.
|
||||
-- Merge api_key and base_url into a config JSONB column. Add speech model type.
|
||||
-- NOTE: On fresh databases the canonical schema already applies; all guards are IF EXISTS.
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
-- Only run full migration if old llm_providers table still exists
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'llm_providers') THEN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
-- Step 1: Rename llm_providers → providers
|
||||
ALTER TABLE llm_providers RENAME TO providers;
|
||||
ALTER TABLE providers RENAME CONSTRAINT llm_providers_name_unique TO providers_name_unique;
|
||||
ALTER TABLE providers DROP CONSTRAINT IF EXISTS llm_providers_client_type_check;
|
||||
|
||||
-- Step 2: Add config JSONB and migrate api_key + base_url into it
|
||||
ALTER TABLE providers ADD COLUMN IF NOT EXISTS config JSONB NOT NULL DEFAULT '{}'::jsonb;
|
||||
UPDATE providers SET config = jsonb_build_object('api_key', api_key, 'base_url', base_url)
|
||||
WHERE api_key IS NOT NULL;
|
||||
ALTER TABLE providers DROP COLUMN IF EXISTS api_key;
|
||||
ALTER TABLE providers DROP COLUMN IF EXISTS base_url;
|
||||
|
||||
-- Step 3: Expand client_type CHECK
|
||||
ALTER TABLE providers ADD CONSTRAINT providers_client_type_check CHECK (
|
||||
client_type IN (
|
||||
'openai-responses', 'openai-completions', 'anthropic-messages',
|
||||
'google-generative-ai', 'openai-codex', 'edge-speech'
|
||||
)
|
||||
);
|
||||
|
||||
-- Step 4: Rename llm_provider_id → provider_id in models table
|
||||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'models' AND column_name = 'llm_provider_id') THEN
|
||||
ALTER TABLE models RENAME COLUMN llm_provider_id TO provider_id;
|
||||
END IF;
|
||||
IF EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'models_provider_model_id_unique') THEN
|
||||
ALTER TABLE models RENAME CONSTRAINT models_provider_model_id_unique TO models_provider_id_model_id_unique;
|
||||
END IF;
|
||||
|
||||
-- Step 5: Expand models type CHECK to include speech
|
||||
ALTER TABLE models DROP CONSTRAINT IF EXISTS models_type_check;
|
||||
ALTER TABLE models ADD CONSTRAINT models_type_check CHECK (type IN ('chat', 'embedding', 'speech'));
|
||||
|
||||
-- Step 6: Migrate tts_providers into providers
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'tts_providers') THEN
|
||||
INSERT INTO providers (id, name, client_type, icon, enable, config, metadata, created_at, updated_at)
|
||||
SELECT
|
||||
tp.id,
|
||||
tp.name,
|
||||
CASE WHEN tp.provider = 'edge' THEN 'edge-speech' ELSE tp.provider END,
|
||||
NULL,
|
||||
tp.enable,
|
||||
tp.config,
|
||||
'{}'::jsonb,
|
||||
tp.created_at,
|
||||
tp.updated_at
|
||||
FROM tts_providers tp
|
||||
WHERE NOT EXISTS (SELECT 1 FROM providers p WHERE p.id = tp.id);
|
||||
END IF;
|
||||
|
||||
-- Step 7: Migrate tts_models into models
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'tts_models') THEN
|
||||
INSERT INTO models (id, model_id, name, provider_id, type, config, created_at, updated_at)
|
||||
SELECT
|
||||
tm.id,
|
||||
tm.model_id,
|
||||
tm.name,
|
||||
tm.tts_provider_id,
|
||||
'speech',
|
||||
tm.config,
|
||||
tm.created_at,
|
||||
tm.updated_at
|
||||
FROM tts_models tm
|
||||
WHERE NOT EXISTS (SELECT 1 FROM models m WHERE m.id = tm.id);
|
||||
END IF;
|
||||
|
||||
-- Step 8: Update bots.tts_model_id FK to reference models instead of tts_models
|
||||
ALTER TABLE bots DROP CONSTRAINT IF EXISTS bots_tts_model_id_fkey;
|
||||
ALTER TABLE bots ADD CONSTRAINT bots_tts_model_id_fkey
|
||||
FOREIGN KEY (tts_model_id) REFERENCES models(id) ON DELETE SET NULL;
|
||||
|
||||
-- Step 9: Drop tts_models and tts_providers
|
||||
DROP INDEX IF EXISTS idx_tts_models_provider_id;
|
||||
DROP TABLE IF EXISTS tts_models;
|
||||
DROP TABLE IF EXISTS tts_providers;
|
||||
|
||||
-- Step 10: Rename llm_provider_oauth_tokens → provider_oauth_tokens
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'llm_provider_oauth_tokens') THEN
|
||||
ALTER TABLE llm_provider_oauth_tokens RENAME TO provider_oauth_tokens;
|
||||
ALTER TABLE provider_oauth_tokens RENAME COLUMN llm_provider_id TO provider_id;
|
||||
ALTER INDEX IF EXISTS idx_llm_provider_oauth_tokens_state RENAME TO idx_provider_oauth_tokens_state;
|
||||
END IF;
|
||||
END $$;
|
||||
@@ -1,52 +0,0 @@
|
||||
-- name: UpsertLlmProviderOAuthToken :one
|
||||
INSERT INTO llm_provider_oauth_tokens (
|
||||
llm_provider_id,
|
||||
access_token,
|
||||
refresh_token,
|
||||
expires_at,
|
||||
scope,
|
||||
token_type,
|
||||
state,
|
||||
pkce_code_verifier
|
||||
)
|
||||
VALUES (
|
||||
sqlc.arg(llm_provider_id),
|
||||
sqlc.arg(access_token),
|
||||
sqlc.arg(refresh_token),
|
||||
sqlc.arg(expires_at),
|
||||
sqlc.arg(scope),
|
||||
sqlc.arg(token_type),
|
||||
sqlc.arg(state),
|
||||
sqlc.arg(pkce_code_verifier)
|
||||
)
|
||||
ON CONFLICT (llm_provider_id) DO UPDATE SET
|
||||
access_token = EXCLUDED.access_token,
|
||||
refresh_token = EXCLUDED.refresh_token,
|
||||
expires_at = EXCLUDED.expires_at,
|
||||
scope = EXCLUDED.scope,
|
||||
token_type = EXCLUDED.token_type,
|
||||
state = EXCLUDED.state,
|
||||
pkce_code_verifier = EXCLUDED.pkce_code_verifier,
|
||||
updated_at = now()
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetLlmProviderOAuthTokenByProvider :one
|
||||
SELECT * FROM llm_provider_oauth_tokens WHERE llm_provider_id = sqlc.arg(llm_provider_id);
|
||||
|
||||
-- name: GetLlmProviderOAuthTokenByState :one
|
||||
SELECT * FROM llm_provider_oauth_tokens WHERE state = sqlc.arg(state) AND state != '';
|
||||
|
||||
-- name: UpdateLlmProviderOAuthState :exec
|
||||
INSERT INTO llm_provider_oauth_tokens (llm_provider_id, state, pkce_code_verifier)
|
||||
VALUES (
|
||||
sqlc.arg(llm_provider_id),
|
||||
sqlc.arg(state),
|
||||
sqlc.arg(pkce_code_verifier)
|
||||
)
|
||||
ON CONFLICT (llm_provider_id) DO UPDATE SET
|
||||
state = EXCLUDED.state,
|
||||
pkce_code_verifier = EXCLUDED.pkce_code_verifier,
|
||||
updated_at = now();
|
||||
|
||||
-- name: DeleteLlmProviderOAuthToken :exec
|
||||
DELETE FROM llm_provider_oauth_tokens WHERE llm_provider_id = sqlc.arg(llm_provider_id);
|
||||
+69
-32
@@ -1,52 +1,50 @@
|
||||
-- name: CreateLlmProvider :one
|
||||
INSERT INTO llm_providers (name, base_url, api_key, client_type, icon, enable, metadata)
|
||||
-- name: CreateProvider :one
|
||||
INSERT INTO providers (name, client_type, icon, enable, config, metadata)
|
||||
VALUES (
|
||||
sqlc.arg(name),
|
||||
sqlc.arg(base_url),
|
||||
sqlc.arg(api_key),
|
||||
sqlc.arg(client_type),
|
||||
sqlc.arg(icon),
|
||||
sqlc.arg(enable),
|
||||
sqlc.arg(config),
|
||||
sqlc.arg(metadata)
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetLlmProviderByID :one
|
||||
SELECT * FROM llm_providers WHERE id = sqlc.arg(id);
|
||||
-- name: GetProviderByID :one
|
||||
SELECT * FROM providers WHERE id = sqlc.arg(id);
|
||||
|
||||
-- name: GetLlmProviderByName :one
|
||||
SELECT * FROM llm_providers WHERE name = sqlc.arg(name);
|
||||
-- name: GetProviderByName :one
|
||||
SELECT * FROM providers WHERE name = sqlc.arg(name);
|
||||
|
||||
-- name: ListLlmProviders :many
|
||||
SELECT * FROM llm_providers
|
||||
-- name: ListProviders :many
|
||||
SELECT * FROM providers
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: UpdateLlmProvider :one
|
||||
UPDATE llm_providers
|
||||
-- name: UpdateProvider :one
|
||||
UPDATE providers
|
||||
SET
|
||||
name = sqlc.arg(name),
|
||||
base_url = sqlc.arg(base_url),
|
||||
api_key = sqlc.arg(api_key),
|
||||
client_type = sqlc.arg(client_type),
|
||||
icon = sqlc.arg(icon),
|
||||
enable = sqlc.arg(enable),
|
||||
config = sqlc.arg(config),
|
||||
metadata = sqlc.arg(metadata),
|
||||
updated_at = now()
|
||||
WHERE id = sqlc.arg(id)
|
||||
RETURNING *;
|
||||
|
||||
-- name: DeleteLlmProvider :exec
|
||||
DELETE FROM llm_providers WHERE id = sqlc.arg(id);
|
||||
-- name: DeleteProvider :exec
|
||||
DELETE FROM providers WHERE id = sqlc.arg(id);
|
||||
|
||||
-- name: CountLlmProviders :one
|
||||
SELECT COUNT(*) FROM llm_providers;
|
||||
-- name: CountProviders :one
|
||||
SELECT COUNT(*) FROM providers;
|
||||
|
||||
-- name: CreateModel :one
|
||||
INSERT INTO models (model_id, name, llm_provider_id, type, config)
|
||||
INSERT INTO models (model_id, name, provider_id, type, config)
|
||||
VALUES (
|
||||
sqlc.arg(model_id),
|
||||
sqlc.arg(name),
|
||||
sqlc.arg(llm_provider_id),
|
||||
sqlc.arg(provider_id),
|
||||
sqlc.arg(type),
|
||||
sqlc.arg(config)
|
||||
)
|
||||
@@ -74,19 +72,19 @@ ORDER BY created_at DESC;
|
||||
|
||||
-- name: ListModelsByProviderID :many
|
||||
SELECT * FROM models
|
||||
WHERE llm_provider_id = sqlc.arg(llm_provider_id)
|
||||
WHERE provider_id = sqlc.arg(provider_id)
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: ListModelsByProviderIDAndType :many
|
||||
SELECT * FROM models
|
||||
WHERE llm_provider_id = sqlc.arg(llm_provider_id)
|
||||
WHERE provider_id = sqlc.arg(provider_id)
|
||||
AND type = sqlc.arg(type)
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: ListModelsByProviderClientType :many
|
||||
SELECT m.*
|
||||
FROM models m
|
||||
JOIN llm_providers p ON m.llm_provider_id = p.id
|
||||
JOIN providers p ON m.provider_id = p.id
|
||||
WHERE p.client_type = sqlc.arg(client_type)
|
||||
ORDER BY m.created_at DESC;
|
||||
|
||||
@@ -95,7 +93,7 @@ UPDATE models
|
||||
SET
|
||||
model_id = sqlc.arg(model_id),
|
||||
name = sqlc.arg(name),
|
||||
llm_provider_id = sqlc.arg(llm_provider_id),
|
||||
provider_id = sqlc.arg(provider_id),
|
||||
type = sqlc.arg(type),
|
||||
config = sqlc.arg(config),
|
||||
updated_at = now()
|
||||
@@ -116,18 +114,23 @@ SELECT COUNT(*) FROM models WHERE type = sqlc.arg(type);
|
||||
|
||||
|
||||
-- name: UpsertRegistryProvider :one
|
||||
INSERT INTO llm_providers (name, base_url, api_key, client_type, icon, enable, metadata)
|
||||
VALUES (sqlc.arg(name), sqlc.arg(base_url), '', sqlc.arg(client_type), sqlc.arg(icon), false, '{}')
|
||||
INSERT INTO providers (name, client_type, icon, enable, config, metadata)
|
||||
VALUES (sqlc.arg(name), sqlc.arg(client_type), sqlc.arg(icon), false, sqlc.arg(config), '{}')
|
||||
ON CONFLICT (name) DO UPDATE SET
|
||||
icon = EXCLUDED.icon,
|
||||
client_type = EXCLUDED.client_type,
|
||||
config = CASE
|
||||
WHEN providers.config->>'api_key' IS NOT NULL AND providers.config->>'api_key' != ''
|
||||
THEN jsonb_set(EXCLUDED.config, '{api_key}', providers.config->'api_key')
|
||||
ELSE EXCLUDED.config
|
||||
END,
|
||||
updated_at = now()
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpsertRegistryModel :one
|
||||
INSERT INTO models (model_id, name, llm_provider_id, type, config)
|
||||
VALUES (sqlc.arg(model_id), sqlc.arg(name), sqlc.arg(llm_provider_id), sqlc.arg(type), sqlc.arg(config))
|
||||
ON CONFLICT (llm_provider_id, model_id) DO UPDATE SET
|
||||
INSERT INTO models (model_id, name, provider_id, type, config)
|
||||
VALUES (sqlc.arg(model_id), sqlc.arg(name), sqlc.arg(provider_id), sqlc.arg(type), sqlc.arg(config))
|
||||
ON CONFLICT (provider_id, model_id) DO UPDATE SET
|
||||
name = EXCLUDED.name,
|
||||
type = EXCLUDED.type,
|
||||
config = EXCLUDED.config,
|
||||
@@ -137,14 +140,14 @@ RETURNING *;
|
||||
-- name: ListEnabledModels :many
|
||||
SELECT m.*
|
||||
FROM models m
|
||||
JOIN llm_providers p ON m.llm_provider_id = p.id
|
||||
JOIN providers p ON m.provider_id = p.id
|
||||
WHERE p.enable = true
|
||||
ORDER BY m.created_at DESC;
|
||||
|
||||
-- name: ListEnabledModelsByType :many
|
||||
SELECT m.*
|
||||
FROM models m
|
||||
JOIN llm_providers p ON m.llm_provider_id = p.id
|
||||
JOIN providers p ON m.provider_id = p.id
|
||||
WHERE p.enable = true
|
||||
AND m.type = sqlc.arg(type)
|
||||
ORDER BY m.created_at DESC;
|
||||
@@ -152,7 +155,7 @@ ORDER BY m.created_at DESC;
|
||||
-- name: ListEnabledModelsByProviderClientType :many
|
||||
SELECT m.*
|
||||
FROM models m
|
||||
JOIN llm_providers p ON m.llm_provider_id = p.id
|
||||
JOIN providers p ON m.provider_id = p.id
|
||||
WHERE p.enable = true
|
||||
AND p.client_type = sqlc.arg(client_type)
|
||||
ORDER BY m.created_at DESC;
|
||||
@@ -171,3 +174,37 @@ RETURNING *;
|
||||
SELECT * FROM model_variants
|
||||
WHERE model_uuid = sqlc.arg(model_uuid)
|
||||
ORDER BY weight DESC, created_at DESC;
|
||||
|
||||
-- name: GetSpeechModelWithProvider :one
|
||||
SELECT
|
||||
m.*,
|
||||
p.client_type AS provider_type
|
||||
FROM models m
|
||||
JOIN providers p ON p.id = m.provider_id
|
||||
WHERE m.id = sqlc.arg(id)
|
||||
AND m.type = 'speech';
|
||||
|
||||
-- name: ListSpeechProviders :many
|
||||
SELECT * FROM providers
|
||||
WHERE client_type = 'edge-speech'
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: ListSpeechModels :many
|
||||
SELECT m.*,
|
||||
p.client_type AS provider_type
|
||||
FROM models m
|
||||
JOIN providers p ON p.id = m.provider_id
|
||||
WHERE m.type = 'speech'
|
||||
ORDER BY m.created_at DESC;
|
||||
|
||||
-- name: ListSpeechModelsByProviderID :many
|
||||
SELECT * FROM models
|
||||
WHERE provider_id = sqlc.arg(provider_id)
|
||||
AND type = 'speech'
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: GetModelByProviderAndModelID :one
|
||||
SELECT * FROM models
|
||||
WHERE provider_id = sqlc.arg(provider_id)
|
||||
AND model_id = sqlc.arg(model_id)
|
||||
LIMIT 1;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
-- name: UpsertProviderOAuthToken :one
|
||||
INSERT INTO provider_oauth_tokens (
|
||||
provider_id,
|
||||
access_token,
|
||||
refresh_token,
|
||||
expires_at,
|
||||
scope,
|
||||
token_type,
|
||||
state,
|
||||
pkce_code_verifier
|
||||
)
|
||||
VALUES (
|
||||
sqlc.arg(provider_id),
|
||||
sqlc.arg(access_token),
|
||||
sqlc.arg(refresh_token),
|
||||
sqlc.arg(expires_at),
|
||||
sqlc.arg(scope),
|
||||
sqlc.arg(token_type),
|
||||
sqlc.arg(state),
|
||||
sqlc.arg(pkce_code_verifier)
|
||||
)
|
||||
ON CONFLICT (provider_id) DO UPDATE SET
|
||||
access_token = EXCLUDED.access_token,
|
||||
refresh_token = EXCLUDED.refresh_token,
|
||||
expires_at = EXCLUDED.expires_at,
|
||||
scope = EXCLUDED.scope,
|
||||
token_type = EXCLUDED.token_type,
|
||||
state = EXCLUDED.state,
|
||||
pkce_code_verifier = EXCLUDED.pkce_code_verifier,
|
||||
updated_at = now()
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetProviderOAuthTokenByProvider :one
|
||||
SELECT * FROM provider_oauth_tokens WHERE provider_id = sqlc.arg(provider_id);
|
||||
|
||||
-- name: GetProviderOAuthTokenByState :one
|
||||
SELECT * FROM provider_oauth_tokens WHERE state = sqlc.arg(state) AND state != '';
|
||||
|
||||
-- name: UpdateProviderOAuthState :exec
|
||||
INSERT INTO provider_oauth_tokens (provider_id, state, pkce_code_verifier)
|
||||
VALUES (
|
||||
sqlc.arg(provider_id),
|
||||
sqlc.arg(state),
|
||||
sqlc.arg(pkce_code_verifier)
|
||||
)
|
||||
ON CONFLICT (provider_id) DO UPDATE SET
|
||||
state = EXCLUDED.state,
|
||||
pkce_code_verifier = EXCLUDED.pkce_code_verifier,
|
||||
updated_at = now();
|
||||
|
||||
-- name: DeleteProviderOAuthToken :exec
|
||||
DELETE FROM provider_oauth_tokens WHERE provider_id = sqlc.arg(provider_id);
|
||||
@@ -27,7 +27,7 @@ LEFT JOIN models AS title_models ON title_models.id = bots.title_model_id
|
||||
LEFT JOIN models AS image_models ON image_models.id = bots.image_model_id
|
||||
LEFT JOIN search_providers ON search_providers.id = bots.search_provider_id
|
||||
LEFT JOIN memory_providers ON memory_providers.id = bots.memory_provider_id
|
||||
LEFT JOIN tts_models ON tts_models.id = bots.tts_model_id
|
||||
LEFT JOIN models AS tts_models ON tts_models.id = bots.tts_model_id
|
||||
LEFT JOIN browser_contexts ON browser_contexts.id = bots.browser_context_id
|
||||
WHERE bots.id = $1;
|
||||
|
||||
@@ -84,7 +84,7 @@ LEFT JOIN models AS title_models ON title_models.id = updated.title_model_id
|
||||
LEFT JOIN models AS image_models ON image_models.id = updated.image_model_id
|
||||
LEFT JOIN search_providers ON search_providers.id = updated.search_provider_id
|
||||
LEFT JOIN memory_providers ON memory_providers.id = updated.memory_provider_id
|
||||
LEFT JOIN tts_models ON tts_models.id = updated.tts_model_id
|
||||
LEFT JOIN models AS tts_models ON tts_models.id = updated.tts_model_id
|
||||
LEFT JOIN browser_contexts ON browser_contexts.id = updated.browser_context_id;
|
||||
|
||||
-- name: DeleteSettingsByBotID :exec
|
||||
|
||||
@@ -31,7 +31,7 @@ SELECT
|
||||
COALESCE(SUM((m.usage->>'outputTokens')::bigint), 0)::bigint AS output_tokens
|
||||
FROM bot_history_messages m
|
||||
LEFT JOIN models mo ON mo.id = m.model_id
|
||||
LEFT JOIN llm_providers lp ON lp.id = mo.llm_provider_id
|
||||
LEFT JOIN providers lp ON lp.id = mo.provider_id
|
||||
WHERE m.bot_id = sqlc.arg(bot_id)
|
||||
AND m.usage IS NOT NULL
|
||||
AND m.created_at >= sqlc.arg(from_time)
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
-- name: CreateTtsModel :one
|
||||
INSERT INTO tts_models (model_id, name, tts_provider_id, config)
|
||||
VALUES (
|
||||
sqlc.arg(model_id),
|
||||
sqlc.arg(name),
|
||||
sqlc.arg(tts_provider_id),
|
||||
sqlc.arg(config)
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetTtsModelByID :one
|
||||
SELECT * FROM tts_models WHERE id = sqlc.arg(id);
|
||||
|
||||
-- name: GetTtsModelWithProvider :one
|
||||
SELECT
|
||||
tm.*,
|
||||
tp.provider AS provider_type
|
||||
FROM tts_models tm
|
||||
JOIN tts_providers tp ON tp.id = tm.tts_provider_id
|
||||
WHERE tm.id = sqlc.arg(id);
|
||||
|
||||
-- name: ListTtsModels :many
|
||||
SELECT * FROM tts_models
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: ListTtsModelsByProviderID :many
|
||||
SELECT * FROM tts_models
|
||||
WHERE tts_provider_id = sqlc.arg(tts_provider_id)
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: UpdateTtsModel :one
|
||||
UPDATE tts_models
|
||||
SET
|
||||
name = sqlc.arg(name),
|
||||
config = sqlc.arg(config),
|
||||
updated_at = now()
|
||||
WHERE id = sqlc.arg(id)
|
||||
RETURNING *;
|
||||
|
||||
-- name: DeleteTtsModel :exec
|
||||
DELETE FROM tts_models WHERE id = sqlc.arg(id);
|
||||
|
||||
-- name: DeleteTtsModelsByProviderID :exec
|
||||
DELETE FROM tts_models WHERE tts_provider_id = sqlc.arg(tts_provider_id);
|
||||
|
||||
-- name: GetTtsModelByProviderAndModelID :one
|
||||
SELECT * FROM tts_models
|
||||
WHERE tts_provider_id = sqlc.arg(tts_provider_id)
|
||||
AND model_id = sqlc.arg(model_id)
|
||||
LIMIT 1;
|
||||
@@ -1,38 +0,0 @@
|
||||
-- name: CreateTtsProvider :one
|
||||
INSERT INTO tts_providers (name, provider, config, enable)
|
||||
VALUES (
|
||||
sqlc.arg(name),
|
||||
sqlc.arg(provider),
|
||||
sqlc.arg(config),
|
||||
sqlc.arg(enable)
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetTtsProviderByID :one
|
||||
SELECT * FROM tts_providers WHERE id = sqlc.arg(id);
|
||||
|
||||
-- name: GetTtsProviderByName :one
|
||||
SELECT * FROM tts_providers WHERE name = sqlc.arg(name);
|
||||
|
||||
-- name: ListTtsProviders :many
|
||||
SELECT * FROM tts_providers
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: ListTtsProvidersByProvider :many
|
||||
SELECT * FROM tts_providers
|
||||
WHERE provider = sqlc.arg(provider)
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: UpdateTtsProvider :one
|
||||
UPDATE tts_providers
|
||||
SET
|
||||
name = sqlc.arg(name),
|
||||
provider = sqlc.arg(provider),
|
||||
config = sqlc.arg(config),
|
||||
enable = sqlc.arg(enable),
|
||||
updated_at = now()
|
||||
WHERE id = sqlc.arg(id)
|
||||
RETURNING *;
|
||||
|
||||
-- name: DeleteTtsProvider :exec
|
||||
DELETE FROM tts_providers WHERE id = sqlc.arg(id);
|
||||
Reference in New Issue
Block a user