Packages

phoenix_kit

1.7.200
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib phoenix_kit migrations postgres v34.ex
Raw

lib/phoenix_kit/migrations/postgres/v34.ex

defmodule PhoenixKit.Migrations.Postgres.V34 do
@moduledoc """
PhoenixKit V34 Migration: AI Endpoints System
This migration replaces the Accounts + Slots architecture with a unified
Endpoints system where each endpoint contains credentials, model selection,
and generation parameters in a single entity.
## Architecture Change
### Before (V32)
- **Accounts Table**: Provider credentials only
- **Slots**: Stored in Settings as JSON (4 types × 3 slots each)
- Slots referenced account_id for credentials
- Fallback chain: tries slot 0 → 1 → 2
### After (V34)
- **Endpoints Table**: Unified configuration
- Provider credentials (name, api_key, base_url, provider_settings)
- Model selection (single model per endpoint)
- Generation parameters (temperature, max_tokens, etc.)
- No type categorization (user decides endpoint purpose)
- No fallback chain (explicit endpoint targeting)
## Changes
### New Table: phoenix_kit_ai_endpoints
- Unified configuration combining account + slot fields
- All generation parameters in one place
- Sort order for display
### Modified Table: phoenix_kit_ai_requests
- Added endpoint_id for new requests
- Added endpoint_name for denormalized history
- Kept account_id/slot_index for backward compatibility
### Cleanup
- Remove slot Settings entries (ai_text_processing_slots, etc.)
- Keep ai_enabled setting
- Keep accounts table for historical request references
"""
use Ecto.Migration
@doc """
Run the V34 migration to add the AI Endpoints system.
"""
def up(%{prefix: prefix} = _opts) do
# ===========================================
# 1. CREATE AI ENDPOINTS TABLE
# ===========================================
create_if_not_exists table(:phoenix_kit_ai_endpoints, prefix: prefix) do
# Identity
add :name, :string, size: 100, null: false
add :description, :string, size: 500
# Provider configuration
add :provider, :string, size: 50, null: false, default: "openrouter"
add :api_key, :text, null: false
add :base_url, :string, size: 255
add :provider_settings, :map, null: true, default: %{}
# Model configuration
add :model, :string, size: 150, null: false
# Generation parameters
add :temperature, :float, default: 0.7
add :max_tokens, :integer
add :top_p, :float
add :top_k, :integer
add :frequency_penalty, :float
add :presence_penalty, :float
add :repetition_penalty, :float
add :stop, {:array, :string}
add :seed, :integer
# Image generation parameters
add :image_size, :string, size: 20
add :image_quality, :string, size: 20
# Embeddings parameters
add :dimensions, :integer
# Status
add :enabled, :boolean, null: false, default: true
add :sort_order, :integer, null: false, default: 0
add :last_validated_at, :utc_datetime_usec
timestamps(type: :utc_datetime_usec)
end
# Index for enabled endpoints
create_if_not_exists index(:phoenix_kit_ai_endpoints, [:enabled],
name: :phoenix_kit_ai_endpoints_enabled_idx,
prefix: prefix
)
# Index for sorting
create_if_not_exists index(:phoenix_kit_ai_endpoints, [:sort_order],
name: :phoenix_kit_ai_endpoints_sort_order_idx,
prefix: prefix
)
execute """
COMMENT ON TABLE #{prefix_table_name("phoenix_kit_ai_endpoints", prefix)} IS
'AI endpoints - unified configuration combining credentials, model, and parameters'
"""
execute """
COMMENT ON COLUMN #{prefix_table_name("phoenix_kit_ai_endpoints", prefix)}.provider_settings IS
'Provider-specific settings (http_referer, x_title for OpenRouter, etc.)'
"""
# ===========================================
# 2. UPDATE AI REQUESTS TABLE
# ===========================================
alter table(:phoenix_kit_ai_requests, prefix: prefix) do
add_if_not_exists :endpoint_id, :integer
add_if_not_exists :endpoint_name, :string, size: 100
end
# Index for endpoint_id
create_if_not_exists index(:phoenix_kit_ai_requests, [:endpoint_id],
name: :phoenix_kit_ai_requests_endpoint_id_idx,
prefix: prefix
)
# Add foreign key to endpoints (optional - endpoint can be deleted)
execute """
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_constraint
WHERE conname = 'phoenix_kit_ai_requests_endpoint_id_fkey'
AND conrelid = '#{prefix_table_name("phoenix_kit_ai_requests", prefix)}'::regclass
) THEN
ALTER TABLE #{prefix_table_name("phoenix_kit_ai_requests", prefix)}
ADD CONSTRAINT phoenix_kit_ai_requests_endpoint_id_fkey
FOREIGN KEY (endpoint_id)
REFERENCES #{prefix_table_name("phoenix_kit_ai_endpoints", prefix)}(id)
ON DELETE SET NULL;
END IF;
END $$;
"""
execute """
COMMENT ON COLUMN #{prefix_table_name("phoenix_kit_ai_requests", prefix)}.endpoint_id IS
'Reference to AI endpoint used (new system)'
"""
execute """
COMMENT ON COLUMN #{prefix_table_name("phoenix_kit_ai_requests", prefix)}.endpoint_name IS
'Denormalized endpoint name for historical display'
"""
# ===========================================
# 3. CLEANUP OLD SLOT SETTINGS
# ===========================================
execute """
DELETE FROM #{prefix_table_name("phoenix_kit_settings", prefix)}
WHERE key IN (
'ai_text_processing_slots',
'ai_vision_processing_slots',
'ai_image_gen_slots',
'ai_embeddings_slots'
)
"""
# ===========================================
# 4. UPDATE VERSION
# ===========================================
execute "COMMENT ON TABLE #{prefix_table_name("phoenix_kit", prefix)} IS '34'"
end
@doc """
Rollback the V34 migration.
"""
def down(%{prefix: prefix} = _opts) do
# Drop foreign key from requests
execute """
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM pg_constraint
WHERE conname = 'phoenix_kit_ai_requests_endpoint_id_fkey'
AND conrelid = '#{prefix_table_name("phoenix_kit_ai_requests", prefix)}'::regclass
) THEN
ALTER TABLE #{prefix_table_name("phoenix_kit_ai_requests", prefix)}
DROP CONSTRAINT phoenix_kit_ai_requests_endpoint_id_fkey;
END IF;
END $$;
"""
# Drop index from requests
drop_if_exists index(:phoenix_kit_ai_requests, [:endpoint_id],
name: :phoenix_kit_ai_requests_endpoint_id_idx,
prefix: prefix
)
# Remove columns from requests
alter table(:phoenix_kit_ai_requests, prefix: prefix) do
remove_if_exists :endpoint_id, :integer
remove_if_exists :endpoint_name, :string
end
# Drop endpoints indexes
drop_if_exists index(:phoenix_kit_ai_endpoints, [:sort_order],
name: :phoenix_kit_ai_endpoints_sort_order_idx,
prefix: prefix
)
drop_if_exists index(:phoenix_kit_ai_endpoints, [:enabled],
name: :phoenix_kit_ai_endpoints_enabled_idx,
prefix: prefix
)
# Drop endpoints table
drop_if_exists table(:phoenix_kit_ai_endpoints, prefix: prefix)
# Restore default slot settings
default_text_slots =
JSON.encode!(%{
"slots" => [
%{
"name" => "Slot 1",
"description" => "",
"account_id" => nil,
"model" => "",
"temperature" => 0.7,
"max_tokens" => 1000,
"enabled" => false
},
%{
"name" => "Slot 2",
"description" => "",
"account_id" => nil,
"model" => "",
"temperature" => 0.7,
"max_tokens" => 2000,
"enabled" => false
},
%{
"name" => "Slot 3",
"description" => "",
"account_id" => nil,
"model" => "",
"temperature" => 0.7,
"max_tokens" => 4000,
"enabled" => false
}
]
})
execute """
INSERT INTO #{prefix_table_name("phoenix_kit_settings", prefix)} (key, value_json, module, date_added, date_updated)
VALUES
('ai_text_processing_slots', '#{default_text_slots}'::jsonb, 'ai', NOW(), NOW())
ON CONFLICT (key) DO NOTHING
"""
# Update version
execute "COMMENT ON TABLE #{prefix_table_name("phoenix_kit", prefix)} IS '33'"
end
# Helper to build prefixed table name
defp prefix_table_name(table, nil), do: table
defp prefix_table_name(table, "public"), do: table
defp prefix_table_name(table, prefix), do: "#{prefix}.#{table}"
end