feat(desktop): embed BoosAPI Desktop client as a subproject

Vendor the rebranded BoosAPI Desktop client (Tauri + Vue) into metapi as
a monorepo subdirectory under desktop/. Source only — node_modules,
dist, Cargo target and the upstream .git history are excluded.

desktop/ keeps its own independent Cargo workspace (desktop/src-tauri
with crates/*); it is not part of the backend boosapi crate, so a
`cargo check` at the metapi root still compiles only the backend. Build
the desktop app from desktop/src-tauri per desktop/README.md.

Note: app icons are still placeholder assets pending the final BoosAPI
logo. The updater signing keys live outside the repo and are not
included.
This commit is contained in:
boos
2026-06-22 11:32:57 +08:00
parent d9c78ecc73
commit e0a5f57793
2305 changed files with 449355 additions and 0 deletions
@@ -0,0 +1,9 @@
[package]
name = "boosapi-migration"
version = "0.0.1"
edition = "2021"
[dependencies]
sea-orm-migration = { version = "1", features = ["sqlx-sqlite", "runtime-tokio-native-tls"] }
async-trait = "0.1"
tokio = { workspace = true }
@@ -0,0 +1,292 @@
pub use sea_orm_migration::prelude::*;
mod m20240101_000001_init;
mod m20240102_000001_add_token_fields;
mod m20240103_000001_add_mcp_timeout_headers;
mod m20240104_000001_add_mcp_icon;
mod m20250105_000001_context_compression;
mod m20250106_000001_add_message_status;
mod m20250107_000001_add_provider_custom_headers;
mod m20250108_000001_add_provider_icon;
mod m20250109_000001_add_conversation_categories;
mod m20250110_000001_add_memory_item_index_status;
mod m20250111_000001_add_memory_item_index_error;
mod m20250113_000001_add_memory_namespace_settings;
mod m20250114_000001_add_memory_namespace_icon_sort;
mod m20250115_000001_add_knowledge_base_icon_sort;
mod m20250116_000001_add_knowledge_base_retrieval_settings;
mod m20250117_000001_add_knowledge_base_chunking_config;
mod m20250118_000001_add_knowledge_document_type;
mod m20250119_000001_add_knowledge_document_index_error;
mod m20250120_000001_add_message_timing;
mod m20250121_000001_add_conversation_parent_id;
mod m20250122_000001_merge_thinking_to_content;
mod m20250123_000001_add_category_system_prompt;
mod m20250717_000001_add_agent_support;
mod m20250718_000001_add_sdk_context_backup;
mod m20250719_000001_add_skill_states;
mod m20250720_000001_add_provider_builtin_id;
mod m20260417_000001_add_category_default_templates;
mod m20260428_000001_add_drawing_history;
mod m20260430_000001_add_conversation_thinking_level;
mod m20260501_000001_add_knowledge_base_rerank_settings;
mod m20260504_000001_split_openai_compatible_provider_types;
mod m20260515_000001_add_knowledge_base_index_schedule;
mod m20260518_000001_add_builtin_model_deletions;
pub struct Migrator;
#[async_trait::async_trait]
impl MigratorTrait for Migrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
vec![
Box::new(m20240101_000001_init::Migration),
Box::new(m20240102_000001_add_token_fields::Migration),
Box::new(m20240103_000001_add_mcp_timeout_headers::Migration),
Box::new(m20240104_000001_add_mcp_icon::Migration),
Box::new(m20250105_000001_context_compression::Migration),
Box::new(m20250106_000001_add_message_status::Migration),
Box::new(m20250107_000001_add_provider_custom_headers::Migration),
Box::new(m20250108_000001_add_provider_icon::Migration),
Box::new(m20250109_000001_add_conversation_categories::Migration),
Box::new(m20250110_000001_add_memory_item_index_status::Migration),
Box::new(m20250111_000001_add_memory_item_index_error::Migration),
Box::new(m20250113_000001_add_memory_namespace_settings::Migration),
Box::new(m20250114_000001_add_memory_namespace_icon_sort::Migration),
Box::new(m20250115_000001_add_knowledge_base_icon_sort::Migration),
Box::new(m20250116_000001_add_knowledge_base_retrieval_settings::Migration),
Box::new(m20250117_000001_add_knowledge_base_chunking_config::Migration),
Box::new(m20250118_000001_add_knowledge_document_type::Migration),
Box::new(m20250119_000001_add_knowledge_document_index_error::Migration),
Box::new(m20250120_000001_add_message_timing::Migration),
Box::new(m20250121_000001_add_conversation_parent_id::Migration),
Box::new(m20250122_000001_merge_thinking_to_content::Migration),
Box::new(m20250123_000001_add_category_system_prompt::Migration),
Box::new(m20250717_000001_add_agent_support::Migration),
Box::new(m20250718_000001_add_sdk_context_backup::Migration),
Box::new(m20250719_000001_add_skill_states::Migration),
Box::new(m20250720_000001_add_provider_builtin_id::Migration),
Box::new(m20260417_000001_add_category_default_templates::Migration),
Box::new(m20260428_000001_add_drawing_history::Migration),
Box::new(m20260430_000001_add_conversation_thinking_level::Migration),
Box::new(m20260501_000001_add_knowledge_base_rerank_settings::Migration),
Box::new(m20260504_000001_split_openai_compatible_provider_types::Migration),
Box::new(m20260515_000001_add_knowledge_base_index_schedule::Migration),
Box::new(m20260518_000001_add_builtin_model_deletions::Migration),
]
}
}
#[cfg(test)]
mod tests {
use super::*;
use sea_orm_migration::sea_orm::{
ConnectOptions, ConnectionTrait, Database, DatabaseConnection, DbBackend, Statement,
};
async fn sqlite_test_db() -> DatabaseConnection {
let mut opts = ConnectOptions::new("sqlite::memory:");
opts.max_connections(1)
.min_connections(1)
.sqlx_logging(false);
Database::connect(opts)
.await
.expect("connect sqlite test db")
}
#[tokio::test]
async fn migrator_up_adds_category_default_template_columns_on_sqlite() {
let db = sqlite_test_db().await;
Migrator::up(&db, None)
.await
.expect("run sqlite migrations");
let manager = SchemaManager::new(&db);
for column in [
"default_provider_id",
"default_model_id",
"default_temperature",
"default_max_tokens",
"default_top_p",
"default_frequency_penalty",
] {
assert!(
manager
.has_column("conversation_categories", column)
.await
.expect("check migrated column"),
"missing column {column}"
);
}
}
#[tokio::test]
async fn migrator_up_adds_drawing_history_tables_on_sqlite() {
let db = sqlite_test_db().await;
Migrator::up(&db, None)
.await
.expect("run sqlite migrations");
let manager = SchemaManager::new(&db);
for table in ["drawing_generations", "drawing_images"] {
assert!(
manager.has_table(table).await.expect("check drawing table"),
"missing table {table}"
);
}
}
#[tokio::test]
async fn migrator_up_adds_builtin_model_deletions_table_on_sqlite() {
let db = sqlite_test_db().await;
Migrator::up(&db, None)
.await
.expect("run sqlite migrations");
let manager = SchemaManager::new(&db);
assert!(
manager
.has_table("builtin_model_deletions")
.await
.expect("check builtin model deletions table"),
"missing builtin_model_deletions table"
);
}
#[tokio::test]
async fn migrator_up_adds_conversation_thinking_level_on_sqlite() {
let db = sqlite_test_db().await;
Migrator::up(&db, None)
.await
.expect("run sqlite migrations");
let manager = SchemaManager::new(&db);
assert!(
manager
.has_column("conversations", "thinking_level")
.await
.expect("check thinking level column"),
"missing conversations.thinking_level"
);
}
#[tokio::test]
async fn migrator_up_adds_knowledge_base_rerank_settings_on_sqlite() {
let db = sqlite_test_db().await;
Migrator::up(&db, None)
.await
.expect("run sqlite migrations");
let manager = SchemaManager::new(&db);
for column in ["rerank_provider", "rerank_candidate_k"] {
assert!(
manager
.has_column("knowledge_bases", column)
.await
.expect("check knowledge base rerank column"),
"missing knowledge_bases.{column}"
);
}
}
#[tokio::test]
async fn migrator_up_adds_knowledge_base_index_schedule_on_sqlite() {
let db = sqlite_test_db().await;
Migrator::up(&db, None)
.await
.expect("run sqlite migrations");
let manager = SchemaManager::new(&db);
for column in ["index_concurrency", "index_interval_ms"] {
assert!(
manager
.has_column("knowledge_bases", column)
.await
.expect("check knowledge base index schedule column"),
"missing knowledge_bases.{column}"
);
}
}
#[tokio::test]
async fn split_openai_compatible_provider_types_migration_updates_builtin_rows() {
let db = sqlite_test_db().await;
let manager = SchemaManager::new(&db);
m20240101_000001_init::Migration
.up(&manager)
.await
.expect("run init migration");
m20250720_000001_add_provider_builtin_id::Migration
.up(&manager)
.await
.expect("add builtin_id column");
db.execute_unprepared(
r#"INSERT INTO providers
(id, name, provider_type, api_host, enabled, sort_order, created_at, updated_at, builtin_id)
VALUES
('provider-deepseek', 'DeepSeek', 'openai', 'https://api.deepseek.com', 1, 0, 1, 1, 'deepseek'),
('provider-xai', 'xAI', 'openai', 'https://api.x.ai', 1, 0, 1, 1, 'xai'),
('provider-glm', 'GLM', 'openai', 'https://open.bigmodel.cn/api/paas', 1, 0, 1, 1, 'glm'),
('provider-siliconflow', 'SiliconFlow', 'openai', 'https://api.siliconflow.cn', 1, 0, 1, 1, 'siliconflow'),
('provider-custom', 'Custom', 'openai', 'https://api.example.com', 1, 0, 1, 1, NULL)"#,
)
.await
.expect("insert provider rows");
m20260504_000001_split_openai_compatible_provider_types::Migration
.up(&manager)
.await
.expect("split provider types");
let rows = db
.query_all(Statement::from_string(
DbBackend::Sqlite,
"SELECT id, provider_type FROM providers ORDER BY id".to_string(),
))
.await
.expect("query providers");
let values: Vec<(String, String)> = rows
.into_iter()
.map(|row| {
(
row.try_get("", "id").unwrap(),
row.try_get("", "provider_type").unwrap(),
)
})
.collect();
assert_eq!(
values,
vec![
("provider-custom".to_string(), "openai".to_string()),
("provider-deepseek".to_string(), "deepseek".to_string()),
("provider-glm".to_string(), "glm".to_string()),
(
"provider-siliconflow".to_string(),
"siliconflow".to_string()
),
("provider-xai".to_string(), "xai".to_string()),
]
);
}
#[tokio::test]
async fn migrator_refresh_round_trips_latest_sqlite_schema() {
let db = sqlite_test_db().await;
Migrator::up(&db, None)
.await
.expect("run sqlite migrations");
Migrator::refresh(&db)
.await
.expect("refresh sqlite migrations");
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,58 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Messages::Table)
.add_column(ColumnDef::new(Messages::PromptTokens).integer().null())
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(Messages::Table)
.add_column(ColumnDef::new(Messages::CompletionTokens).integer().null())
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Messages::Table)
.drop_column(Messages::PromptTokens)
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(Messages::Table)
.drop_column(Messages::CompletionTokens)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum Messages {
Table,
PromptTokens,
CompletionTokens,
}
@@ -0,0 +1,85 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(McpServers::Table)
.add_column(
ColumnDef::new(McpServers::DiscoverTimeoutSecs)
.integer()
.null(),
)
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(McpServers::Table)
.add_column(
ColumnDef::new(McpServers::ExecuteTimeoutSecs)
.integer()
.null(),
)
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(McpServers::Table)
.add_column(ColumnDef::new(McpServers::HeadersJson).string().null())
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(McpServers::Table)
.drop_column(McpServers::DiscoverTimeoutSecs)
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(McpServers::Table)
.drop_column(McpServers::ExecuteTimeoutSecs)
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(McpServers::Table)
.drop_column(McpServers::HeadersJson)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum McpServers {
Table,
DiscoverTimeoutSecs,
ExecuteTimeoutSecs,
HeadersJson,
}
@@ -0,0 +1,58 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(McpServers::Table)
.add_column(ColumnDef::new(McpServers::IconType).string().null())
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(McpServers::Table)
.add_column(ColumnDef::new(McpServers::IconValue).string().null())
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(McpServers::Table)
.drop_column(McpServers::IconType)
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(McpServers::Table)
.drop_column(McpServers::IconValue)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum McpServers {
Table,
IconType,
IconValue,
}
@@ -0,0 +1,133 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
// Add context_compression column to conversations
manager
.alter_table(
Table::alter()
.table(Conversations::Table)
.add_column(
ColumnDef::new(Conversations::ContextCompression)
.integer()
.not_null()
.default(0),
)
.to_owned(),
)
.await?;
// Create conversation_summaries table
manager
.create_table(
Table::create()
.table(ConversationSummaries::Table)
.if_not_exists()
.col(
ColumnDef::new(ConversationSummaries::Id)
.string()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(ConversationSummaries::ConversationId)
.string()
.not_null(),
)
.col(
ColumnDef::new(ConversationSummaries::SummaryText)
.string()
.not_null(),
)
.col(
ColumnDef::new(ConversationSummaries::CompressedUntilMessageId)
.string()
.null(),
)
.col(
ColumnDef::new(ConversationSummaries::TokenCount)
.integer()
.null(),
)
.col(
ColumnDef::new(ConversationSummaries::ModelUsed)
.string()
.null(),
)
.col(
ColumnDef::new(ConversationSummaries::CreatedAt)
.integer()
.not_null(),
)
.col(
ColumnDef::new(ConversationSummaries::UpdatedAt)
.integer()
.not_null(),
)
.foreign_key(
ForeignKey::create()
.from(
ConversationSummaries::Table,
ConversationSummaries::ConversationId,
)
.to(Conversations::Table, Conversations::Id)
.on_delete(ForeignKeyAction::Cascade),
)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_conv_summaries_conv_id")
.table(ConversationSummaries::Table)
.col(ConversationSummaries::ConversationId)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(ConversationSummaries::Table).to_owned())
.await?;
manager
.alter_table(
Table::alter()
.table(Conversations::Table)
.drop_column(Conversations::ContextCompression)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum Conversations {
Table,
Id,
ContextCompression,
}
#[derive(DeriveIden)]
enum ConversationSummaries {
Table,
Id,
ConversationId,
SummaryText,
CompressedUntilMessageId,
TokenCount,
ModelUsed,
CreatedAt,
UpdatedAt,
}
@@ -0,0 +1,49 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
// Add status column to messages: "complete" | "partial" | "error"
// - "complete": normal completion, include in context
// - "partial": user stopped generation, include in context
// - "error": API/network error, exclude from context
manager
.alter_table(
Table::alter()
.table(Messages::Table)
.add_column(
ColumnDef::new(Messages::Status)
.string()
.not_null()
.default("complete")
.to_owned(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Messages::Table)
.drop_column(Messages::Status)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum Messages {
Table,
Status,
}
@@ -0,0 +1,44 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Providers::Table)
.add_column(
ColumnDef::new(Providers::CustomHeaders)
.string()
.null()
.to_owned(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Providers::Table)
.drop_column(Providers::CustomHeaders)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum Providers {
Table,
CustomHeaders,
}
@@ -0,0 +1,39 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Providers::Table)
.add_column(ColumnDef::new(Providers::Icon).string().null().to_owned())
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Providers::Table)
.drop_column(Providers::Icon)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum Providers {
Table,
Icon,
}
@@ -0,0 +1,118 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
// Create conversation_categories table
manager
.create_table(
Table::create()
.table(ConversationCategories::Table)
.if_not_exists()
.col(
ColumnDef::new(ConversationCategories::Id)
.string()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(ConversationCategories::Name)
.string()
.not_null(),
)
.col(
ColumnDef::new(ConversationCategories::IconType)
.string()
.null(),
)
.col(
ColumnDef::new(ConversationCategories::IconValue)
.string()
.null(),
)
.col(
ColumnDef::new(ConversationCategories::SortOrder)
.integer()
.not_null()
.default(0),
)
.col(
ColumnDef::new(ConversationCategories::IsCollapsed)
.integer()
.not_null()
.default(0),
)
.col(
ColumnDef::new(ConversationCategories::CreatedAt)
.integer()
.not_null(),
)
.col(
ColumnDef::new(ConversationCategories::UpdatedAt)
.integer()
.not_null(),
)
.to_owned(),
)
.await?;
// Add category_id column to conversations table
manager
.alter_table(
Table::alter()
.table(Conversations::Table)
.add_column(
ColumnDef::new(Conversations::CategoryId)
.string()
.null(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Conversations::Table)
.drop_column(Conversations::CategoryId)
.to_owned(),
)
.await?;
manager
.drop_table(
Table::drop()
.table(ConversationCategories::Table)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum ConversationCategories {
Table,
Id,
Name,
IconType,
IconValue,
SortOrder,
IsCollapsed,
CreatedAt,
UpdatedAt,
}
#[derive(DeriveIden)]
enum Conversations {
Table,
CategoryId,
}
@@ -0,0 +1,51 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
// Add index_status column to memory_items: "pending" | "indexing" | "ready" | "failed" | "skipped"
// - "pending": just created, not yet indexed
// - "indexing": embedding generation in progress
// - "ready": successfully indexed
// - "failed": indexing failed
// - "skipped": namespace has no embedding provider
manager
.alter_table(
Table::alter()
.table(MemoryItems::Table)
.add_column(
ColumnDef::new(MemoryItems::IndexStatus)
.string()
.not_null()
.default("pending")
.to_owned(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(MemoryItems::Table)
.drop_column(MemoryItems::IndexStatus)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum MemoryItems {
Table,
IndexStatus,
}
@@ -0,0 +1,44 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(MemoryItems::Table)
.add_column(
ColumnDef::new(MemoryItems::IndexError)
.string_len(1024)
.null()
.to_owned(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(MemoryItems::Table)
.drop_column(MemoryItems::IndexError)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum MemoryItems {
Table,
IndexError,
}
@@ -0,0 +1,66 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
// Add embedding_dimensions column (nullable integer)
manager
.alter_table(
Table::alter()
.table(MemoryNamespaces::Table)
.add_column(
ColumnDef::new(MemoryNamespaces::EmbeddingDimensions)
.integer()
.null(),
)
.to_owned(),
)
.await?;
// Add retrieval_threshold column (nullable float, app default 0.1)
manager
.alter_table(
Table::alter()
.table(MemoryNamespaces::Table)
.add_column(
ColumnDef::new(MemoryNamespaces::RetrievalThreshold)
.float()
.null(),
)
.to_owned(),
)
.await?;
// Add retrieval_top_k column (nullable integer, app default 5)
manager
.alter_table(
Table::alter()
.table(MemoryNamespaces::Table)
.add_column(
ColumnDef::new(MemoryNamespaces::RetrievalTopK)
.integer()
.null(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
// SQLite does not support DROP COLUMN; skip for down migration
Ok(())
}
}
#[derive(DeriveIden)]
enum MemoryNamespaces {
Table,
EmbeddingDimensions,
RetrievalThreshold,
RetrievalTopK,
}
@@ -0,0 +1,55 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(MemoryNamespaces::Table)
.add_column(ColumnDef::new(MemoryNamespaces::IconType).string().null())
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(MemoryNamespaces::Table)
.add_column(ColumnDef::new(MemoryNamespaces::IconValue).string().null())
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(MemoryNamespaces::Table)
.add_column(
ColumnDef::new(MemoryNamespaces::SortOrder)
.integer()
.not_null()
.default(0),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
Ok(())
}
}
#[derive(DeriveIden)]
enum MemoryNamespaces {
Table,
IconType,
IconValue,
SortOrder,
}
@@ -0,0 +1,55 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(ColumnDef::new(KnowledgeBases::IconType).string().null())
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(ColumnDef::new(KnowledgeBases::IconValue).string().null())
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(
ColumnDef::new(KnowledgeBases::SortOrder)
.integer()
.not_null()
.default(0),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
Ok(())
}
}
#[derive(DeriveIden)]
enum KnowledgeBases {
Table,
IconType,
IconValue,
SortOrder,
}
@@ -0,0 +1,54 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(ColumnDef::new(KnowledgeBases::EmbeddingDimensions).integer().null())
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(
ColumnDef::new(KnowledgeBases::RetrievalThreshold)
.float()
.null(),
)
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(ColumnDef::new(KnowledgeBases::RetrievalTopK).integer().null())
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
Ok(())
}
}
#[derive(DeriveIden)]
enum KnowledgeBases {
Table,
EmbeddingDimensions,
RetrievalThreshold,
RetrievalTopK,
}
@@ -0,0 +1,50 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(ColumnDef::new(KnowledgeBases::ChunkSize).integer().null())
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(ColumnDef::new(KnowledgeBases::ChunkOverlap).integer().null())
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(ColumnDef::new(KnowledgeBases::Separator).string().null())
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
Ok(())
}
}
#[derive(DeriveIden)]
enum KnowledgeBases {
Table,
ChunkSize,
ChunkOverlap,
Separator,
}
@@ -0,0 +1,34 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(KnowledgeDocuments::Table)
.add_column(
ColumnDef::new(KnowledgeDocuments::DocType)
.string()
.not_null()
.default("file"),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
Ok(())
}
}
#[derive(DeriveIden)]
enum KnowledgeDocuments {
Table,
DocType,
}
@@ -0,0 +1,33 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(KnowledgeDocuments::Table)
.add_column(
ColumnDef::new(KnowledgeDocuments::IndexError)
.string()
.null(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
Ok(())
}
}
#[derive(DeriveIden)]
enum KnowledgeDocuments {
Table,
IndexError,
}
@@ -0,0 +1,64 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
// tokens_per_second: output tokens / generation duration
manager
.alter_table(
Table::alter()
.table(Messages::Table)
.add_column(ColumnDef::new(Messages::TokensPerSecond).double().null())
.to_owned(),
)
.await?;
// first_token_latency_ms: time from request start to first content token
manager
.alter_table(
Table::alter()
.table(Messages::Table)
.add_column(
ColumnDef::new(Messages::FirstTokenLatencyMs)
.big_integer()
.null(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Messages::Table)
.drop_column(Messages::TokensPerSecond)
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(Messages::Table)
.drop_column(Messages::FirstTokenLatencyMs)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum Messages {
Table,
TokensPerSecond,
FirstTokenLatencyMs,
}
@@ -0,0 +1,43 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Conversations::Table)
.add_column(
ColumnDef::new(Conversations::ParentConversationId)
.string()
.null(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Conversations::Table)
.drop_column(Conversations::ParentConversationId)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum Conversations {
Table,
ParentConversationId,
}
@@ -0,0 +1,27 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
// Merge non-empty `thinking` column into `content` as <think> blocks,
// then clear the `thinking` column.
let db = manager.get_connection();
db.execute_unprepared(
r#"UPDATE messages
SET content = '<think>' || char(10) || thinking || char(10) || '</think>' || char(10, 10) || content,
thinking = NULL
WHERE thinking IS NOT NULL AND thinking != ''"#,
)
.await?;
Ok(())
}
async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
// Not reversible — thinking content is now embedded in content
Ok(())
}
}
@@ -0,0 +1,41 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(ConversationCategories::Table)
.add_column(
ColumnDef::new(ConversationCategories::SystemPrompt)
.text()
.null(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(ConversationCategories::Table)
.drop_column(ConversationCategories::SystemPrompt)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum ConversationCategories {
Table,
SystemPrompt,
}
@@ -0,0 +1,109 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
// 1. conversations.mode
manager
.alter_table(
Table::alter()
.table(Alias::new("conversations"))
.add_column(
ColumnDef::new(Alias::new("mode"))
.string()
.not_null()
.default("chat"),
)
.to_owned(),
)
.await?;
// 2. tool_executions.approval_status
manager
.alter_table(
Table::alter()
.table(Alias::new("tool_executions"))
.add_column(
ColumnDef::new(Alias::new("approval_status"))
.string()
.null(),
)
.to_owned(),
)
.await?;
// 3. agent_sessions table
manager
.create_table(
Table::create()
.table(Alias::new("agent_sessions"))
.if_not_exists()
.col(
ColumnDef::new(Alias::new("id"))
.string()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(Alias::new("conversation_id"))
.string()
.not_null(),
)
.col(ColumnDef::new(Alias::new("cwd")).string().null())
.col(
ColumnDef::new(Alias::new("permission_mode"))
.string()
.not_null()
.default("default"),
)
.col(
ColumnDef::new(Alias::new("runtime_status"))
.string()
.not_null()
.default("idle"),
)
.col(
ColumnDef::new(Alias::new("sdk_context_json"))
.text()
.null(),
)
.col(
ColumnDef::new(Alias::new("total_tokens"))
.integer()
.not_null()
.default(0),
)
.col(
ColumnDef::new(Alias::new("total_cost_usd"))
.double()
.not_null()
.default(0.0),
)
.col(
ColumnDef::new(Alias::new("created_at"))
.string()
.not_null(),
)
.col(
ColumnDef::new(Alias::new("updated_at"))
.string()
.not_null(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Alias::new("agent_sessions")).to_owned())
.await?;
// SQLite doesn't support DROP COLUMN, so we skip reverting alter_table
Ok(())
}
}
@@ -0,0 +1,35 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Alias::new("agent_sessions"))
.add_column(
ColumnDef::new(Alias::new("sdk_context_backup_json"))
.text()
.null(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Alias::new("agent_sessions"))
.drop_column(Alias::new("sdk_context_backup_json"))
.to_owned(),
)
.await?;
Ok(())
}
}
@@ -0,0 +1,49 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(SkillStates::Table)
.if_not_exists()
.col(
ColumnDef::new(SkillStates::Name)
.string()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(SkillStates::Enabled)
.integer()
.not_null()
.default(1),
)
.col(
ColumnDef::new(SkillStates::UpdatedAt)
.integer()
.not_null(),
)
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(SkillStates::Table).to_owned())
.await
}
}
#[derive(DeriveIden)]
enum SkillStates {
Table,
Name,
Enabled,
UpdatedAt,
}
@@ -0,0 +1,44 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Providers::Table)
.add_column(
ColumnDef::new(Providers::BuiltinId)
.string()
.null()
.to_owned(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Providers::Table)
.drop_column(Providers::BuiltinId)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum Providers {
Table,
BuiltinId,
}
@@ -0,0 +1,108 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
for alter in [
Table::alter()
.table(ConversationCategories::Table)
.add_column(
ColumnDef::new(ConversationCategories::DefaultProviderId)
.string()
.null(),
)
.to_owned(),
Table::alter()
.table(ConversationCategories::Table)
.add_column(
ColumnDef::new(ConversationCategories::DefaultModelId)
.string()
.null(),
)
.to_owned(),
Table::alter()
.table(ConversationCategories::Table)
.add_column(
ColumnDef::new(ConversationCategories::DefaultTemperature)
.double()
.null(),
)
.to_owned(),
Table::alter()
.table(ConversationCategories::Table)
.add_column(
ColumnDef::new(ConversationCategories::DefaultMaxTokens)
.big_integer()
.null(),
)
.to_owned(),
Table::alter()
.table(ConversationCategories::Table)
.add_column(
ColumnDef::new(ConversationCategories::DefaultTopP)
.double()
.null(),
)
.to_owned(),
Table::alter()
.table(ConversationCategories::Table)
.add_column(
ColumnDef::new(ConversationCategories::DefaultFrequencyPenalty)
.double()
.null(),
)
.to_owned(),
] {
manager.alter_table(alter).await?;
}
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
for alter in [
Table::alter()
.table(ConversationCategories::Table)
.drop_column(ConversationCategories::DefaultFrequencyPenalty)
.to_owned(),
Table::alter()
.table(ConversationCategories::Table)
.drop_column(ConversationCategories::DefaultTopP)
.to_owned(),
Table::alter()
.table(ConversationCategories::Table)
.drop_column(ConversationCategories::DefaultMaxTokens)
.to_owned(),
Table::alter()
.table(ConversationCategories::Table)
.drop_column(ConversationCategories::DefaultTemperature)
.to_owned(),
Table::alter()
.table(ConversationCategories::Table)
.drop_column(ConversationCategories::DefaultModelId)
.to_owned(),
Table::alter()
.table(ConversationCategories::Table)
.drop_column(ConversationCategories::DefaultProviderId)
.to_owned(),
] {
manager.alter_table(alter).await?;
}
Ok(())
}
}
#[derive(DeriveIden)]
enum ConversationCategories {
Table,
DefaultProviderId,
DefaultModelId,
DefaultTemperature,
DefaultMaxTokens,
DefaultTopP,
DefaultFrequencyPenalty,
}
@@ -0,0 +1,217 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(DrawingGenerations::Table)
.if_not_exists()
.col(
ColumnDef::new(DrawingGenerations::Id)
.string()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(DrawingGenerations::ParentGenerationId)
.string()
.null(),
)
.col(
ColumnDef::new(DrawingGenerations::ProviderId)
.string()
.not_null(),
)
.col(
ColumnDef::new(DrawingGenerations::KeyId)
.string()
.not_null(),
)
.col(
ColumnDef::new(DrawingGenerations::ModelId)
.string()
.not_null(),
)
.col(
ColumnDef::new(DrawingGenerations::ApiKind)
.string()
.not_null(),
)
.col(
ColumnDef::new(DrawingGenerations::Action)
.string()
.not_null(),
)
.col(ColumnDef::new(DrawingGenerations::Prompt).text().not_null())
.col(
ColumnDef::new(DrawingGenerations::ParametersJson)
.text()
.not_null(),
)
.col(
ColumnDef::new(DrawingGenerations::ReferenceFileIdsJson)
.text()
.not_null(),
)
.col(
ColumnDef::new(DrawingGenerations::SourceImageIdsJson)
.text()
.not_null(),
)
.col(
ColumnDef::new(DrawingGenerations::MaskFileId)
.string()
.null(),
)
.col(
ColumnDef::new(DrawingGenerations::Status)
.string()
.not_null(),
)
.col(
ColumnDef::new(DrawingGenerations::ErrorMessage)
.text()
.null(),
)
.col(
ColumnDef::new(DrawingGenerations::ResponseId)
.string()
.null(),
)
.col(ColumnDef::new(DrawingGenerations::UsageJson).text().null())
.col(
ColumnDef::new(DrawingGenerations::CreatedAt)
.big_integer()
.not_null(),
)
.col(
ColumnDef::new(DrawingGenerations::CompletedAt)
.big_integer()
.null(),
)
.to_owned(),
)
.await?;
manager
.create_table(
Table::create()
.table(DrawingImages::Table)
.if_not_exists()
.col(
ColumnDef::new(DrawingImages::Id)
.string()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(DrawingImages::GenerationId)
.string()
.not_null(),
)
.col(
ColumnDef::new(DrawingImages::StoredFileId)
.string()
.not_null(),
)
.col(
ColumnDef::new(DrawingImages::StoragePath)
.string()
.not_null(),
)
.col(ColumnDef::new(DrawingImages::MimeType).string().not_null())
.col(ColumnDef::new(DrawingImages::Width).integer().null())
.col(ColumnDef::new(DrawingImages::Height).integer().null())
.col(ColumnDef::new(DrawingImages::RevisedPrompt).text().null())
.col(
ColumnDef::new(DrawingImages::CreatedAt)
.big_integer()
.not_null(),
)
.foreign_key(
ForeignKey::create()
.from(DrawingImages::Table, DrawingImages::GenerationId)
.to(DrawingGenerations::Table, DrawingGenerations::Id)
.on_delete(ForeignKeyAction::Cascade),
)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.if_not_exists()
.name("idx_drawing_generations_created_at")
.table(DrawingGenerations::Table)
.col(DrawingGenerations::CreatedAt)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.if_not_exists()
.name("idx_drawing_images_generation")
.table(DrawingImages::Table)
.col(DrawingImages::GenerationId)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(DrawingImages::Table).to_owned())
.await?;
manager
.drop_table(Table::drop().table(DrawingGenerations::Table).to_owned())
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum DrawingGenerations {
Table,
Id,
ParentGenerationId,
ProviderId,
KeyId,
ModelId,
ApiKind,
Action,
Prompt,
ParametersJson,
ReferenceFileIdsJson,
SourceImageIdsJson,
MaskFileId,
Status,
ErrorMessage,
ResponseId,
UsageJson,
CreatedAt,
CompletedAt,
}
#[derive(DeriveIden)]
enum DrawingImages {
Table,
Id,
GenerationId,
StoredFileId,
StoragePath,
MimeType,
Width,
Height,
RevisedPrompt,
CreatedAt,
}
@@ -0,0 +1,33 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Alias::new("conversations"))
.add_column(
ColumnDef::new(Alias::new("thinking_level"))
.string()
.null(),
)
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Alias::new("conversations"))
.drop_column(Alias::new("thinking_level"))
.to_owned(),
)
.await
}
}
@@ -0,0 +1,48 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(
ColumnDef::new(KnowledgeBases::RerankProvider)
.string()
.null(),
)
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(
ColumnDef::new(KnowledgeBases::RerankCandidateK)
.integer()
.null(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
Ok(())
}
}
#[derive(DeriveIden)]
enum KnowledgeBases {
Table,
RerankProvider,
RerankCandidateK,
}
@@ -0,0 +1,37 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
let db = manager.get_connection();
db.execute_unprepared(
r#"UPDATE providers
SET provider_type = CASE builtin_id
WHEN 'deepseek' THEN 'deepseek'
WHEN 'xai' THEN 'xai'
WHEN 'glm' THEN 'glm'
WHEN 'siliconflow' THEN 'siliconflow'
ELSE provider_type
END
WHERE builtin_id IN ('deepseek', 'xai', 'glm', 'siliconflow')"#,
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
let db = manager.get_connection();
db.execute_unprepared(
r#"UPDATE providers
SET provider_type = 'openai'
WHERE builtin_id IN ('deepseek', 'xai', 'glm', 'siliconflow')"#,
)
.await?;
Ok(())
}
}
@@ -0,0 +1,48 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(
ColumnDef::new(KnowledgeBases::IndexConcurrency)
.integer()
.null(),
)
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(KnowledgeBases::Table)
.add_column(
ColumnDef::new(KnowledgeBases::IndexIntervalMs)
.integer()
.null(),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
Ok(())
}
}
#[derive(DeriveIden)]
enum KnowledgeBases {
Table,
IndexConcurrency,
IndexIntervalMs,
}
@@ -0,0 +1,61 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(BuiltinModelDeletions::Table)
.if_not_exists()
.col(
ColumnDef::new(BuiltinModelDeletions::BuiltinId)
.string()
.not_null(),
)
.col(
ColumnDef::new(BuiltinModelDeletions::ModelId)
.string()
.not_null(),
)
.col(
ColumnDef::new(BuiltinModelDeletions::DeletedAt)
.integer()
.not_null(),
)
.primary_key(
Index::create()
.col(BuiltinModelDeletions::BuiltinId)
.col(BuiltinModelDeletions::ModelId),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(
Table::drop()
.table(BuiltinModelDeletions::Table)
.if_exists()
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum BuiltinModelDeletions {
Table,
BuiltinId,
ModelId,
DeletedAt,
}