forked from boos/BoosAPI
e0a5f57793
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.
2384 lines
82 KiB
Rust
2384 lines
82 KiB
Rust
use sea_orm_migration::prelude::*;
|
||
|
||
#[derive(DeriveMigrationName)]
|
||
pub struct Migration;
|
||
|
||
// ===========================================================================
|
||
// Iden enums – one per table, all columns included
|
||
// ===========================================================================
|
||
|
||
#[derive(DeriveIden)]
|
||
enum Providers {
|
||
Table,
|
||
Id,
|
||
Name,
|
||
ProviderType,
|
||
ApiHost,
|
||
ApiPath,
|
||
Enabled,
|
||
ProxyConfig,
|
||
SortOrder,
|
||
CreatedAt,
|
||
UpdatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum ProviderKeys {
|
||
Table,
|
||
Id,
|
||
ProviderId,
|
||
KeyEncrypted,
|
||
KeyPrefix,
|
||
Enabled,
|
||
LastValidatedAt,
|
||
LastError,
|
||
RotationIndex,
|
||
CreatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum Models {
|
||
Table,
|
||
ProviderId,
|
||
ModelId,
|
||
Name,
|
||
Capabilities,
|
||
MaxTokens,
|
||
Enabled,
|
||
ParamOverrides,
|
||
ModelType,
|
||
GroupName,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum Conversations {
|
||
Table,
|
||
Id,
|
||
Title,
|
||
ModelId,
|
||
ProviderId,
|
||
AppId,
|
||
SystemPrompt,
|
||
Temperature,
|
||
MaxTokens,
|
||
TopP,
|
||
FrequencyPenalty,
|
||
MessageCount,
|
||
IsPinned,
|
||
IsArchived,
|
||
WorkspaceSnapshotJson,
|
||
ActiveBranchId,
|
||
ActiveArtifactId,
|
||
ResearchMode,
|
||
SearchEnabled,
|
||
SearchProviderId,
|
||
ThinkingBudget,
|
||
EnabledMcpServerIds,
|
||
EnabledKnowledgeBaseIds,
|
||
EnabledMemoryNamespaceIds,
|
||
CreatedAt,
|
||
UpdatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum Messages {
|
||
Table,
|
||
Id,
|
||
ConversationId,
|
||
Role,
|
||
Content,
|
||
ProviderId,
|
||
ModelId,
|
||
TokenCount,
|
||
Attachments,
|
||
Thinking,
|
||
ParentMessageId,
|
||
VersionIndex,
|
||
IsActive,
|
||
BranchId,
|
||
ToolCallsJson,
|
||
ToolCallId,
|
||
CreatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum Categories {
|
||
Table,
|
||
Id,
|
||
Name,
|
||
SortOrder,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum Apps {
|
||
Table,
|
||
Id,
|
||
Name,
|
||
Description,
|
||
Icon,
|
||
IconColor,
|
||
SystemPrompt,
|
||
DefaultModelId,
|
||
DefaultProviderId,
|
||
Temperature,
|
||
MaxTokens,
|
||
TopP,
|
||
CategoryId,
|
||
IsFavorite,
|
||
Variables,
|
||
SearchPolicyJson,
|
||
ToolBindingJson,
|
||
KnowledgeBindingJson,
|
||
MemoryPolicyJson,
|
||
CreatedAt,
|
||
UpdatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum GatewayKeys {
|
||
Table,
|
||
Id,
|
||
Name,
|
||
KeyHash,
|
||
KeyPrefix,
|
||
EncryptedKey,
|
||
Enabled,
|
||
CreatedAt,
|
||
LastUsedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum GatewayUsage {
|
||
Table,
|
||
Id,
|
||
KeyId,
|
||
ProviderId,
|
||
ModelId,
|
||
RequestTokens,
|
||
ResponseTokens,
|
||
CreatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum Settings {
|
||
Table,
|
||
Key,
|
||
Value,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum SearchProviders {
|
||
Table,
|
||
Id,
|
||
Name,
|
||
ProviderType,
|
||
Endpoint,
|
||
ApiKeyRef,
|
||
Enabled,
|
||
Region,
|
||
Language,
|
||
SafeSearch,
|
||
ResultLimit,
|
||
TimeoutMs,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum SearchCitations {
|
||
Table,
|
||
Id,
|
||
ConversationId,
|
||
MessageId,
|
||
Title,
|
||
Url,
|
||
Snippet,
|
||
ProviderId,
|
||
Rank,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum McpServers {
|
||
Table,
|
||
Id,
|
||
Name,
|
||
Transport,
|
||
Command,
|
||
ArgsJson,
|
||
Endpoint,
|
||
EnvJson,
|
||
Enabled,
|
||
PermissionPolicy,
|
||
Source,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum ToolDescriptors {
|
||
Table,
|
||
Id,
|
||
ServerId,
|
||
Name,
|
||
Description,
|
||
InputSchemaJson,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum ToolExecutions {
|
||
Table,
|
||
Id,
|
||
ConversationId,
|
||
MessageId,
|
||
ServerId,
|
||
ToolName,
|
||
Status,
|
||
InputPreview,
|
||
OutputPreview,
|
||
ErrorMessage,
|
||
DurationMs,
|
||
CreatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum KnowledgeBases {
|
||
Table,
|
||
Id,
|
||
Name,
|
||
Description,
|
||
EmbeddingProvider,
|
||
Enabled,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum KnowledgeDocuments {
|
||
Table,
|
||
Id,
|
||
KnowledgeBaseId,
|
||
Title,
|
||
SourcePath,
|
||
MimeType,
|
||
SizeBytes,
|
||
IndexingStatus,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum RetrievalHits {
|
||
Table,
|
||
Id,
|
||
ConversationId,
|
||
MessageId,
|
||
KnowledgeBaseId,
|
||
DocumentId,
|
||
ChunkRef,
|
||
Score,
|
||
Preview,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum MemoryNamespaces {
|
||
Table,
|
||
Id,
|
||
Name,
|
||
Scope,
|
||
AppId,
|
||
EmbeddingProvider,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum MemoryItems {
|
||
Table,
|
||
Id,
|
||
NamespaceId,
|
||
Title,
|
||
Content,
|
||
Source,
|
||
UpdatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum Artifacts {
|
||
Table,
|
||
Id,
|
||
ConversationId,
|
||
Kind,
|
||
Title,
|
||
Content,
|
||
Format,
|
||
Pinned,
|
||
UpdatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum ContextPacks {
|
||
Table,
|
||
Id,
|
||
AppId,
|
||
Name,
|
||
Content,
|
||
EnabledByDefault,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum ContextSources {
|
||
Table,
|
||
Id,
|
||
ConversationId,
|
||
MessageId,
|
||
#[sea_orm(iden = "type")]
|
||
SourceType,
|
||
RefId,
|
||
Title,
|
||
Enabled,
|
||
Summary,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum ConversationBranches {
|
||
Table,
|
||
Id,
|
||
ConversationId,
|
||
ParentMessageId,
|
||
BranchLabel,
|
||
BranchIndex,
|
||
ComparedMessageIdsJson,
|
||
CreatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum BackupManifests {
|
||
Table,
|
||
Id,
|
||
Version,
|
||
CreatedAt,
|
||
Encrypted,
|
||
Checksum,
|
||
ObjectCountsJson,
|
||
SourceAppVersion,
|
||
FilePath,
|
||
FileSize,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum BackupTargets {
|
||
Table,
|
||
Id,
|
||
Kind,
|
||
ConfigJson,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum ImportJobs {
|
||
Table,
|
||
Id,
|
||
SourceType,
|
||
Status,
|
||
SummaryJson,
|
||
ConflictCount,
|
||
CreatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum ProgramPolicies {
|
||
Table,
|
||
Id,
|
||
ProgramName,
|
||
AllowedProviderIdsJson,
|
||
AllowedModelIdsJson,
|
||
DefaultProviderId,
|
||
DefaultModelId,
|
||
RateLimitPerMinute,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum GatewayDiagnostics {
|
||
Table,
|
||
Id,
|
||
Category,
|
||
Status,
|
||
Message,
|
||
CreatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum DesktopState {
|
||
Table,
|
||
WindowKey,
|
||
Width,
|
||
Height,
|
||
X,
|
||
Y,
|
||
Maximized,
|
||
Visible,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum StoredFiles {
|
||
Table,
|
||
Id,
|
||
Hash,
|
||
OriginalName,
|
||
MimeType,
|
||
SizeBytes,
|
||
StoragePath,
|
||
ConversationId,
|
||
CreatedAt,
|
||
}
|
||
|
||
#[derive(DeriveIden)]
|
||
enum GatewayRequestLogs {
|
||
Table,
|
||
Id,
|
||
KeyId,
|
||
KeyName,
|
||
Method,
|
||
Path,
|
||
Model,
|
||
ProviderId,
|
||
StatusCode,
|
||
DurationMs,
|
||
RequestTokens,
|
||
ResponseTokens,
|
||
ErrorMessage,
|
||
CreatedAt,
|
||
}
|
||
|
||
// ===========================================================================
|
||
// Migration implementation
|
||
// ===========================================================================
|
||
|
||
#[async_trait::async_trait]
|
||
impl MigrationTrait for Migration {
|
||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||
// =================================================================
|
||
// 1. Providers
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(Providers::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(Providers::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(Providers::Name).string().not_null())
|
||
.col(ColumnDef::new(Providers::ProviderType).string().not_null())
|
||
.col(ColumnDef::new(Providers::ApiHost).string().not_null())
|
||
.col(ColumnDef::new(Providers::ApiPath).string().null())
|
||
.col(
|
||
ColumnDef::new(Providers::Enabled)
|
||
.integer()
|
||
.not_null()
|
||
.default(1),
|
||
)
|
||
.col(ColumnDef::new(Providers::ProxyConfig).string().null())
|
||
.col(
|
||
ColumnDef::new(Providers::SortOrder)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(ColumnDef::new(Providers::CreatedAt).integer().not_null())
|
||
.col(ColumnDef::new(Providers::UpdatedAt).integer().not_null())
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 2. Provider Keys
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(ProviderKeys::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(ProviderKeys::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(ProviderKeys::ProviderId).string().not_null())
|
||
.col(
|
||
ColumnDef::new(ProviderKeys::KeyEncrypted)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ProviderKeys::KeyPrefix)
|
||
.string()
|
||
.not_null()
|
||
.default(""),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ProviderKeys::Enabled)
|
||
.integer()
|
||
.not_null()
|
||
.default(1),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ProviderKeys::LastValidatedAt)
|
||
.integer()
|
||
.null(),
|
||
)
|
||
.col(ColumnDef::new(ProviderKeys::LastError).string().null())
|
||
.col(
|
||
ColumnDef::new(ProviderKeys::RotationIndex)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(ColumnDef::new(ProviderKeys::CreatedAt).integer().not_null())
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(ProviderKeys::Table, ProviderKeys::ProviderId)
|
||
.to(Providers::Table, Providers::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 3. Models (composite primary key)
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(Models::Table)
|
||
.if_not_exists()
|
||
.col(ColumnDef::new(Models::ProviderId).string().not_null())
|
||
.col(ColumnDef::new(Models::ModelId).string().not_null())
|
||
.col(ColumnDef::new(Models::Name).string().not_null())
|
||
.col(
|
||
ColumnDef::new(Models::Capabilities)
|
||
.string()
|
||
.not_null()
|
||
.default("[]"),
|
||
)
|
||
.col(ColumnDef::new(Models::MaxTokens).integer().null())
|
||
.col(
|
||
ColumnDef::new(Models::Enabled)
|
||
.integer()
|
||
.not_null()
|
||
.default(1),
|
||
)
|
||
.col(ColumnDef::new(Models::ParamOverrides).string().null())
|
||
.col(
|
||
ColumnDef::new(Models::ModelType)
|
||
.string()
|
||
.not_null()
|
||
.default("chat"),
|
||
)
|
||
.col(ColumnDef::new(Models::GroupName).string().null())
|
||
.primary_key(Index::create().col(Models::ProviderId).col(Models::ModelId))
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(Models::Table, Models::ProviderId)
|
||
.to(Providers::Table, Providers::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 4. Conversations
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(Conversations::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(Conversations::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(Conversations::Title).string().not_null())
|
||
.col(ColumnDef::new(Conversations::ModelId).string().not_null())
|
||
.col(
|
||
ColumnDef::new(Conversations::ProviderId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(ColumnDef::new(Conversations::AppId).string().null())
|
||
.col(ColumnDef::new(Conversations::SystemPrompt).string().null())
|
||
.col(
|
||
ColumnDef::new(Conversations::Temperature)
|
||
.float()
|
||
.null()
|
||
.to_owned(),
|
||
)
|
||
.col(ColumnDef::new(Conversations::MaxTokens).integer().null())
|
||
.col(
|
||
ColumnDef::new(Conversations::TopP)
|
||
.float()
|
||
.null()
|
||
.to_owned(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::FrequencyPenalty)
|
||
.float()
|
||
.null()
|
||
.to_owned(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::MessageCount)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::IsPinned)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::IsArchived)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::WorkspaceSnapshotJson)
|
||
.string()
|
||
.not_null()
|
||
.default("{}"),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::ActiveBranchId)
|
||
.string()
|
||
.null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::ActiveArtifactId)
|
||
.string()
|
||
.null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::ResearchMode)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::SearchEnabled)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::SearchProviderId)
|
||
.string()
|
||
.null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::ThinkingBudget)
|
||
.integer()
|
||
.null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::EnabledMcpServerIds)
|
||
.string()
|
||
.not_null()
|
||
.default("[]"),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::EnabledKnowledgeBaseIds)
|
||
.string()
|
||
.not_null()
|
||
.default("[]"),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::EnabledMemoryNamespaceIds)
|
||
.string()
|
||
.not_null()
|
||
.default("[]"),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::CreatedAt)
|
||
.integer()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Conversations::UpdatedAt)
|
||
.integer()
|
||
.not_null(),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 5. Messages
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(Messages::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(Messages::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(Messages::ConversationId).string().not_null())
|
||
.col(ColumnDef::new(Messages::Role).string().not_null())
|
||
.col(ColumnDef::new(Messages::Content).string().not_null())
|
||
.col(ColumnDef::new(Messages::ProviderId).string().null())
|
||
.col(ColumnDef::new(Messages::ModelId).string().null())
|
||
.col(ColumnDef::new(Messages::TokenCount).integer().null())
|
||
.col(
|
||
ColumnDef::new(Messages::Attachments)
|
||
.string()
|
||
.not_null()
|
||
.default("[]"),
|
||
)
|
||
.col(ColumnDef::new(Messages::Thinking).string().null())
|
||
.col(ColumnDef::new(Messages::ParentMessageId).string().null())
|
||
.col(
|
||
ColumnDef::new(Messages::VersionIndex)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Messages::IsActive)
|
||
.integer()
|
||
.not_null()
|
||
.default(1),
|
||
)
|
||
.col(ColumnDef::new(Messages::BranchId).string().null())
|
||
.col(ColumnDef::new(Messages::ToolCallsJson).string().null())
|
||
.col(ColumnDef::new(Messages::ToolCallId).string().null())
|
||
.col(ColumnDef::new(Messages::CreatedAt).integer().not_null())
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(Messages::Table, Messages::ConversationId)
|
||
.to(Conversations::Table, Conversations::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 6. Categories
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(Categories::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(Categories::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(Categories::Name).string().not_null())
|
||
.col(
|
||
ColumnDef::new(Categories::SortOrder)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 7. Apps
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(Apps::Table)
|
||
.if_not_exists()
|
||
.col(ColumnDef::new(Apps::Id).string().not_null().primary_key())
|
||
.col(ColumnDef::new(Apps::Name).string().not_null())
|
||
.col(
|
||
ColumnDef::new(Apps::Description)
|
||
.string()
|
||
.not_null()
|
||
.default(""),
|
||
)
|
||
.col(ColumnDef::new(Apps::Icon).string().not_null().default("🤖"))
|
||
.col(
|
||
ColumnDef::new(Apps::IconColor)
|
||
.string()
|
||
.not_null()
|
||
.default("#22c55e"),
|
||
)
|
||
.col(ColumnDef::new(Apps::SystemPrompt).string().not_null())
|
||
.col(ColumnDef::new(Apps::DefaultModelId).string().null())
|
||
.col(ColumnDef::new(Apps::DefaultProviderId).string().null())
|
||
.col(ColumnDef::new(Apps::Temperature).float().null().to_owned())
|
||
.col(ColumnDef::new(Apps::MaxTokens).integer().null())
|
||
.col(ColumnDef::new(Apps::TopP).float().null().to_owned())
|
||
.col(ColumnDef::new(Apps::CategoryId).string().null())
|
||
.col(
|
||
ColumnDef::new(Apps::IsFavorite)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Apps::Variables)
|
||
.string()
|
||
.not_null()
|
||
.default("[]"),
|
||
)
|
||
.col(ColumnDef::new(Apps::SearchPolicyJson).string().null())
|
||
.col(ColumnDef::new(Apps::ToolBindingJson).string().null())
|
||
.col(ColumnDef::new(Apps::KnowledgeBindingJson).string().null())
|
||
.col(ColumnDef::new(Apps::MemoryPolicyJson).string().null())
|
||
.col(ColumnDef::new(Apps::CreatedAt).integer().not_null())
|
||
.col(ColumnDef::new(Apps::UpdatedAt).integer().not_null())
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(Apps::Table, Apps::CategoryId)
|
||
.to(Categories::Table, Categories::Id)
|
||
.on_delete(ForeignKeyAction::SetNull),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 8. Gateway Keys
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(GatewayKeys::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(GatewayKeys::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(GatewayKeys::Name).string().not_null())
|
||
.col(
|
||
ColumnDef::new(GatewayKeys::KeyHash)
|
||
.string()
|
||
.not_null()
|
||
.unique_key()
|
||
.to_owned(),
|
||
)
|
||
.col(ColumnDef::new(GatewayKeys::KeyPrefix).string().not_null())
|
||
.col(ColumnDef::new(GatewayKeys::EncryptedKey).string().null())
|
||
.col(
|
||
ColumnDef::new(GatewayKeys::Enabled)
|
||
.integer()
|
||
.not_null()
|
||
.default(1),
|
||
)
|
||
.col(ColumnDef::new(GatewayKeys::CreatedAt).integer().not_null())
|
||
.col(ColumnDef::new(GatewayKeys::LastUsedAt).integer().null())
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 9. Gateway Usage
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(GatewayUsage::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(GatewayUsage::Id)
|
||
.integer()
|
||
.not_null()
|
||
.auto_increment()
|
||
.primary_key()
|
||
.to_owned(),
|
||
)
|
||
.col(ColumnDef::new(GatewayUsage::KeyId).string().not_null())
|
||
.col(ColumnDef::new(GatewayUsage::ProviderId).string().not_null())
|
||
.col(ColumnDef::new(GatewayUsage::ModelId).string().null())
|
||
.col(
|
||
ColumnDef::new(GatewayUsage::RequestTokens)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayUsage::ResponseTokens)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(ColumnDef::new(GatewayUsage::CreatedAt).integer().not_null())
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(GatewayUsage::Table, GatewayUsage::KeyId)
|
||
.to(GatewayKeys::Table, GatewayKeys::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 10. Settings
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(Settings::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(Settings::Key)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(Settings::Value).string().not_null())
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 11. Search Providers
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(SearchProviders::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(SearchProviders::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(SearchProviders::Name).string().not_null())
|
||
.col(
|
||
ColumnDef::new(SearchProviders::ProviderType)
|
||
.string()
|
||
.not_null()
|
||
.default("tavily"),
|
||
)
|
||
.col(ColumnDef::new(SearchProviders::Endpoint).string().null())
|
||
.col(ColumnDef::new(SearchProviders::ApiKeyRef).string().null())
|
||
.col(
|
||
ColumnDef::new(SearchProviders::Enabled)
|
||
.integer()
|
||
.not_null()
|
||
.default(1),
|
||
)
|
||
.col(ColumnDef::new(SearchProviders::Region).string().null())
|
||
.col(ColumnDef::new(SearchProviders::Language).string().null())
|
||
.col(ColumnDef::new(SearchProviders::SafeSearch).integer().null())
|
||
.col(
|
||
ColumnDef::new(SearchProviders::ResultLimit)
|
||
.integer()
|
||
.not_null()
|
||
.default(10),
|
||
)
|
||
.col(
|
||
ColumnDef::new(SearchProviders::TimeoutMs)
|
||
.integer()
|
||
.not_null()
|
||
.default(5000),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_search_providers_enabled")
|
||
.table(SearchProviders::Table)
|
||
.col(SearchProviders::Enabled)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 12. Search Citations
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(SearchCitations::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(SearchCitations::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(SearchCitations::ConversationId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(SearchCitations::MessageId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(ColumnDef::new(SearchCitations::Title).string().not_null())
|
||
.col(ColumnDef::new(SearchCitations::Url).string().not_null())
|
||
.col(ColumnDef::new(SearchCitations::Snippet).string().null())
|
||
.col(
|
||
ColumnDef::new(SearchCitations::ProviderId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(SearchCitations::Rank)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(SearchCitations::Table, SearchCitations::ConversationId)
|
||
.to(Conversations::Table, Conversations::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_search_citations_conv")
|
||
.table(SearchCitations::Table)
|
||
.col(SearchCitations::ConversationId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_search_citations_msg")
|
||
.table(SearchCitations::Table)
|
||
.col(SearchCitations::MessageId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 13. MCP Servers
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(McpServers::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(McpServers::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(McpServers::Name).string().not_null())
|
||
.col(
|
||
ColumnDef::new(McpServers::Transport)
|
||
.string()
|
||
.not_null()
|
||
.default("stdio"),
|
||
)
|
||
.col(ColumnDef::new(McpServers::Command).string().null())
|
||
.col(ColumnDef::new(McpServers::ArgsJson).string().null())
|
||
.col(ColumnDef::new(McpServers::Endpoint).string().null())
|
||
.col(ColumnDef::new(McpServers::EnvJson).string().null())
|
||
.col(
|
||
ColumnDef::new(McpServers::Enabled)
|
||
.integer()
|
||
.not_null()
|
||
.default(1),
|
||
)
|
||
.col(
|
||
ColumnDef::new(McpServers::PermissionPolicy)
|
||
.string()
|
||
.not_null()
|
||
.default("ask"),
|
||
)
|
||
.col(
|
||
ColumnDef::new(McpServers::Source)
|
||
.string()
|
||
.not_null()
|
||
.default("custom"),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_mcp_servers_enabled")
|
||
.table(McpServers::Table)
|
||
.col(McpServers::Enabled)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 14. Tool Descriptors
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(ToolDescriptors::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(ToolDescriptors::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ToolDescriptors::ServerId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(ColumnDef::new(ToolDescriptors::Name).string().not_null())
|
||
.col(ColumnDef::new(ToolDescriptors::Description).string().null())
|
||
.col(
|
||
ColumnDef::new(ToolDescriptors::InputSchemaJson)
|
||
.string()
|
||
.null(),
|
||
)
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(ToolDescriptors::Table, ToolDescriptors::ServerId)
|
||
.to(McpServers::Table, McpServers::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_tool_descriptors_server")
|
||
.table(ToolDescriptors::Table)
|
||
.col(ToolDescriptors::ServerId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 15. Tool Executions
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(ToolExecutions::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(ToolExecutions::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ToolExecutions::ConversationId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(ColumnDef::new(ToolExecutions::MessageId).string().null())
|
||
.col(ColumnDef::new(ToolExecutions::ServerId).string().not_null())
|
||
.col(ColumnDef::new(ToolExecutions::ToolName).string().not_null())
|
||
.col(
|
||
ColumnDef::new(ToolExecutions::Status)
|
||
.string()
|
||
.not_null()
|
||
.default("pending"),
|
||
)
|
||
.col(ColumnDef::new(ToolExecutions::InputPreview).string().null())
|
||
.col(
|
||
ColumnDef::new(ToolExecutions::OutputPreview)
|
||
.string()
|
||
.null(),
|
||
)
|
||
.col(ColumnDef::new(ToolExecutions::ErrorMessage).string().null())
|
||
.col(ColumnDef::new(ToolExecutions::DurationMs).integer().null())
|
||
.col(
|
||
ColumnDef::new(ToolExecutions::CreatedAt)
|
||
.string()
|
||
.not_null()
|
||
.default(Expr::current_timestamp()),
|
||
)
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(ToolExecutions::Table, ToolExecutions::ConversationId)
|
||
.to(Conversations::Table, Conversations::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_tool_executions_conv")
|
||
.table(ToolExecutions::Table)
|
||
.col(ToolExecutions::ConversationId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_tool_executions_msg")
|
||
.table(ToolExecutions::Table)
|
||
.col(ToolExecutions::MessageId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_tool_executions_server")
|
||
.table(ToolExecutions::Table)
|
||
.col(ToolExecutions::ServerId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 16. Knowledge Bases
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(KnowledgeBases::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(KnowledgeBases::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(KnowledgeBases::Name).string().not_null())
|
||
.col(ColumnDef::new(KnowledgeBases::Description).string().null())
|
||
.col(
|
||
ColumnDef::new(KnowledgeBases::EmbeddingProvider)
|
||
.string()
|
||
.null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(KnowledgeBases::Enabled)
|
||
.integer()
|
||
.not_null()
|
||
.default(1),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_knowledge_bases_enabled")
|
||
.table(KnowledgeBases::Table)
|
||
.col(KnowledgeBases::Enabled)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 17. Knowledge Documents
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(KnowledgeDocuments::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(KnowledgeDocuments::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(KnowledgeDocuments::KnowledgeBaseId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(KnowledgeDocuments::Title)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(KnowledgeDocuments::SourcePath)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(KnowledgeDocuments::MimeType)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(KnowledgeDocuments::SizeBytes)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(KnowledgeDocuments::IndexingStatus)
|
||
.string()
|
||
.not_null()
|
||
.default("pending"),
|
||
)
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(
|
||
KnowledgeDocuments::Table,
|
||
KnowledgeDocuments::KnowledgeBaseId,
|
||
)
|
||
.to(KnowledgeBases::Table, KnowledgeBases::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_knowledge_documents_kb")
|
||
.table(KnowledgeDocuments::Table)
|
||
.col(KnowledgeDocuments::KnowledgeBaseId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 18. Retrieval Hits
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(RetrievalHits::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(RetrievalHits::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(RetrievalHits::ConversationId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(ColumnDef::new(RetrievalHits::MessageId).string().not_null())
|
||
.col(
|
||
ColumnDef::new(RetrievalHits::KnowledgeBaseId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(RetrievalHits::DocumentId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(ColumnDef::new(RetrievalHits::ChunkRef).string().not_null())
|
||
.col(
|
||
ColumnDef::new(RetrievalHits::Score)
|
||
.float()
|
||
.not_null()
|
||
.default(0.0),
|
||
)
|
||
.col(ColumnDef::new(RetrievalHits::Preview).string().not_null())
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(RetrievalHits::Table, RetrievalHits::ConversationId)
|
||
.to(Conversations::Table, Conversations::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(RetrievalHits::Table, RetrievalHits::KnowledgeBaseId)
|
||
.to(KnowledgeBases::Table, KnowledgeBases::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_retrieval_hits_conv")
|
||
.table(RetrievalHits::Table)
|
||
.col(RetrievalHits::ConversationId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_retrieval_hits_msg")
|
||
.table(RetrievalHits::Table)
|
||
.col(RetrievalHits::MessageId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_retrieval_hits_kb")
|
||
.table(RetrievalHits::Table)
|
||
.col(RetrievalHits::KnowledgeBaseId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 19. Memory Namespaces
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(MemoryNamespaces::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(MemoryNamespaces::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(MemoryNamespaces::Name).string().not_null())
|
||
.col(
|
||
ColumnDef::new(MemoryNamespaces::Scope)
|
||
.string()
|
||
.not_null()
|
||
.default("global"),
|
||
)
|
||
.col(ColumnDef::new(MemoryNamespaces::AppId).string().null())
|
||
.col(
|
||
ColumnDef::new(MemoryNamespaces::EmbeddingProvider)
|
||
.string()
|
||
.null(),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_memory_namespaces_scope")
|
||
.table(MemoryNamespaces::Table)
|
||
.col(MemoryNamespaces::Scope)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 20. Memory Items
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(MemoryItems::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(MemoryItems::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(MemoryItems::NamespaceId).string().not_null())
|
||
.col(ColumnDef::new(MemoryItems::Title).string().not_null())
|
||
.col(ColumnDef::new(MemoryItems::Content).string().not_null())
|
||
.col(
|
||
ColumnDef::new(MemoryItems::Source)
|
||
.string()
|
||
.not_null()
|
||
.default("manual"),
|
||
)
|
||
.col(
|
||
ColumnDef::new(MemoryItems::UpdatedAt)
|
||
.string()
|
||
.not_null()
|
||
.default(Expr::current_timestamp()),
|
||
)
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(MemoryItems::Table, MemoryItems::NamespaceId)
|
||
.to(MemoryNamespaces::Table, MemoryNamespaces::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_memory_items_ns")
|
||
.table(MemoryItems::Table)
|
||
.col(MemoryItems::NamespaceId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 21. Artifacts
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(Artifacts::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(Artifacts::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Artifacts::ConversationId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Artifacts::Kind)
|
||
.string()
|
||
.not_null()
|
||
.default("draft"),
|
||
)
|
||
.col(ColumnDef::new(Artifacts::Title).string().not_null())
|
||
.col(
|
||
ColumnDef::new(Artifacts::Content)
|
||
.string()
|
||
.not_null()
|
||
.default(""),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Artifacts::Format)
|
||
.string()
|
||
.not_null()
|
||
.default("markdown"),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Artifacts::Pinned)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(Artifacts::UpdatedAt)
|
||
.string()
|
||
.not_null()
|
||
.default(Expr::current_timestamp()),
|
||
)
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(Artifacts::Table, Artifacts::ConversationId)
|
||
.to(Conversations::Table, Conversations::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_artifacts_conv")
|
||
.table(Artifacts::Table)
|
||
.col(Artifacts::ConversationId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_artifacts_pinned")
|
||
.table(Artifacts::Table)
|
||
.col(Artifacts::Pinned)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 22. Context Packs
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(ContextPacks::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(ContextPacks::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(ContextPacks::AppId).string().not_null())
|
||
.col(ColumnDef::new(ContextPacks::Name).string().not_null())
|
||
.col(
|
||
ColumnDef::new(ContextPacks::Content)
|
||
.string()
|
||
.not_null()
|
||
.default(""),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ContextPacks::EnabledByDefault)
|
||
.integer()
|
||
.not_null()
|
||
.default(1),
|
||
)
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(ContextPacks::Table, ContextPacks::AppId)
|
||
.to(Apps::Table, Apps::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_context_packs_app")
|
||
.table(ContextPacks::Table)
|
||
.col(ContextPacks::AppId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 23. Context Sources
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(ContextSources::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(ContextSources::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ContextSources::ConversationId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(ColumnDef::new(ContextSources::MessageId).string().null())
|
||
.col(
|
||
ColumnDef::new(ContextSources::SourceType)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(ColumnDef::new(ContextSources::RefId).string().not_null())
|
||
.col(ColumnDef::new(ContextSources::Title).string().not_null())
|
||
.col(
|
||
ColumnDef::new(ContextSources::Enabled)
|
||
.integer()
|
||
.not_null()
|
||
.default(1),
|
||
)
|
||
.col(ColumnDef::new(ContextSources::Summary).string().null())
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(ContextSources::Table, ContextSources::ConversationId)
|
||
.to(Conversations::Table, Conversations::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_context_sources_conv")
|
||
.table(ContextSources::Table)
|
||
.col(ContextSources::ConversationId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_context_sources_msg")
|
||
.table(ContextSources::Table)
|
||
.col(ContextSources::MessageId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 24. Conversation Branches
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(ConversationBranches::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(ConversationBranches::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ConversationBranches::ConversationId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ConversationBranches::ParentMessageId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ConversationBranches::BranchLabel)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ConversationBranches::BranchIndex)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ConversationBranches::ComparedMessageIdsJson)
|
||
.string()
|
||
.null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ConversationBranches::CreatedAt)
|
||
.string()
|
||
.not_null()
|
||
.default(Expr::current_timestamp()),
|
||
)
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(
|
||
ConversationBranches::Table,
|
||
ConversationBranches::ConversationId,
|
||
)
|
||
.to(Conversations::Table, Conversations::Id)
|
||
.on_delete(ForeignKeyAction::Cascade),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_conv_branches_parent")
|
||
.table(ConversationBranches::Table)
|
||
.col(ConversationBranches::ParentMessageId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 25. Backup Manifests
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(BackupManifests::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(BackupManifests::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(BackupManifests::Version).string().not_null())
|
||
.col(
|
||
ColumnDef::new(BackupManifests::CreatedAt)
|
||
.string()
|
||
.not_null()
|
||
.default(Expr::current_timestamp()),
|
||
)
|
||
.col(
|
||
ColumnDef::new(BackupManifests::Encrypted)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(BackupManifests::Checksum)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(BackupManifests::ObjectCountsJson)
|
||
.string()
|
||
.not_null()
|
||
.default("{}"),
|
||
)
|
||
.col(
|
||
ColumnDef::new(BackupManifests::SourceAppVersion)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(ColumnDef::new(BackupManifests::FilePath).string().null())
|
||
.col(
|
||
ColumnDef::new(BackupManifests::FileSize)
|
||
.big_integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 26. Backup Targets
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(BackupTargets::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(BackupTargets::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(BackupTargets::Kind)
|
||
.string()
|
||
.not_null()
|
||
.default("local"),
|
||
)
|
||
.col(
|
||
ColumnDef::new(BackupTargets::ConfigJson)
|
||
.string()
|
||
.not_null()
|
||
.default("{}"),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_backup_targets_kind")
|
||
.table(BackupTargets::Table)
|
||
.col(BackupTargets::Kind)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 27. Import Jobs
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(ImportJobs::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(ImportJobs::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(ImportJobs::SourceType).string().not_null())
|
||
.col(
|
||
ColumnDef::new(ImportJobs::Status)
|
||
.string()
|
||
.not_null()
|
||
.default("scanning"),
|
||
)
|
||
.col(ColumnDef::new(ImportJobs::SummaryJson).string().null())
|
||
.col(
|
||
ColumnDef::new(ImportJobs::ConflictCount)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ImportJobs::CreatedAt)
|
||
.string()
|
||
.not_null()
|
||
.default(Expr::current_timestamp()),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_import_jobs_status")
|
||
.table(ImportJobs::Table)
|
||
.col(ImportJobs::Status)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_import_jobs_created")
|
||
.table(ImportJobs::Table)
|
||
.col(ImportJobs::CreatedAt)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 28. Program Policies
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(ProgramPolicies::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(ProgramPolicies::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ProgramPolicies::ProgramName)
|
||
.string()
|
||
.not_null()
|
||
.unique_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ProgramPolicies::AllowedProviderIdsJson)
|
||
.string()
|
||
.not_null()
|
||
.default("[]"),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ProgramPolicies::AllowedModelIdsJson)
|
||
.string()
|
||
.not_null()
|
||
.default("[]"),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ProgramPolicies::DefaultProviderId)
|
||
.string()
|
||
.null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ProgramPolicies::DefaultModelId)
|
||
.string()
|
||
.null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(ProgramPolicies::RateLimitPerMinute)
|
||
.integer()
|
||
.null(),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_program_policies_name")
|
||
.table(ProgramPolicies::Table)
|
||
.col(ProgramPolicies::ProgramName)
|
||
.unique()
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 29. Gateway Diagnostics
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(GatewayDiagnostics::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(GatewayDiagnostics::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayDiagnostics::Category)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayDiagnostics::Status)
|
||
.string()
|
||
.not_null()
|
||
.default("ok"),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayDiagnostics::Message)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayDiagnostics::CreatedAt)
|
||
.string()
|
||
.not_null()
|
||
.default(Expr::current_timestamp()),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_gateway_diagnostics_cat")
|
||
.table(GatewayDiagnostics::Table)
|
||
.col(GatewayDiagnostics::Category)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_gateway_diagnostics_created")
|
||
.table(GatewayDiagnostics::Table)
|
||
.col(GatewayDiagnostics::CreatedAt)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 30. Desktop State
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(DesktopState::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(DesktopState::WindowKey)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(DesktopState::Width)
|
||
.integer()
|
||
.not_null()
|
||
.default(1200),
|
||
)
|
||
.col(
|
||
ColumnDef::new(DesktopState::Height)
|
||
.integer()
|
||
.not_null()
|
||
.default(800),
|
||
)
|
||
.col(ColumnDef::new(DesktopState::X).integer().null())
|
||
.col(ColumnDef::new(DesktopState::Y).integer().null())
|
||
.col(
|
||
ColumnDef::new(DesktopState::Maximized)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(DesktopState::Visible)
|
||
.integer()
|
||
.not_null()
|
||
.default(1),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 31. Stored Files
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(StoredFiles::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(StoredFiles::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(ColumnDef::new(StoredFiles::Hash).string().not_null())
|
||
.col(
|
||
ColumnDef::new(StoredFiles::OriginalName)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(StoredFiles::MimeType)
|
||
.string()
|
||
.not_null()
|
||
.default("application/octet-stream"),
|
||
)
|
||
.col(ColumnDef::new(StoredFiles::SizeBytes).integer().not_null())
|
||
.col(ColumnDef::new(StoredFiles::StoragePath).string().not_null())
|
||
.col(ColumnDef::new(StoredFiles::ConversationId).string().null())
|
||
.col(
|
||
ColumnDef::new(StoredFiles::CreatedAt)
|
||
.string()
|
||
.not_null()
|
||
.default(Expr::current_timestamp()),
|
||
)
|
||
.foreign_key(
|
||
ForeignKey::create()
|
||
.from(StoredFiles::Table, StoredFiles::ConversationId)
|
||
.to(Conversations::Table, Conversations::Id)
|
||
.on_delete(ForeignKeyAction::SetNull),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_stored_files_hash")
|
||
.table(StoredFiles::Table)
|
||
.col(StoredFiles::Hash)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
manager
|
||
.create_index(
|
||
Index::create()
|
||
.if_not_exists()
|
||
.name("idx_stored_files_conversation")
|
||
.table(StoredFiles::Table)
|
||
.col(StoredFiles::ConversationId)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// 32. Gateway Request Logs
|
||
// =================================================================
|
||
manager
|
||
.create_table(
|
||
Table::create()
|
||
.table(GatewayRequestLogs::Table)
|
||
.if_not_exists()
|
||
.col(
|
||
ColumnDef::new(GatewayRequestLogs::Id)
|
||
.string()
|
||
.not_null()
|
||
.primary_key(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayRequestLogs::KeyId)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayRequestLogs::KeyName)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayRequestLogs::Method)
|
||
.string()
|
||
.not_null(),
|
||
)
|
||
.col(ColumnDef::new(GatewayRequestLogs::Path).string().not_null())
|
||
.col(ColumnDef::new(GatewayRequestLogs::Model).string().null())
|
||
.col(
|
||
ColumnDef::new(GatewayRequestLogs::ProviderId)
|
||
.string()
|
||
.null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayRequestLogs::StatusCode)
|
||
.integer()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayRequestLogs::DurationMs)
|
||
.integer()
|
||
.not_null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayRequestLogs::RequestTokens)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayRequestLogs::ResponseTokens)
|
||
.integer()
|
||
.not_null()
|
||
.default(0),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayRequestLogs::ErrorMessage)
|
||
.string()
|
||
.null(),
|
||
)
|
||
.col(
|
||
ColumnDef::new(GatewayRequestLogs::CreatedAt)
|
||
.integer()
|
||
.not_null(),
|
||
)
|
||
.to_owned(),
|
||
)
|
||
.await?;
|
||
|
||
// =================================================================
|
||
// FTS5 virtual table and triggers (raw SQL for SQLite-specific features)
|
||
// =================================================================
|
||
let db = manager.get_connection();
|
||
|
||
db.execute_unprepared(
|
||
"CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(\
|
||
content, \
|
||
content=messages, \
|
||
content_rowid=rowid, \
|
||
tokenize='unicode61'\
|
||
)",
|
||
)
|
||
.await?;
|
||
|
||
db.execute_unprepared(
|
||
"CREATE TRIGGER IF NOT EXISTS messages_ai AFTER INSERT ON messages BEGIN \
|
||
INSERT INTO messages_fts(rowid, content) VALUES (new.rowid, new.content); \
|
||
END",
|
||
)
|
||
.await?;
|
||
|
||
db.execute_unprepared(
|
||
"CREATE TRIGGER IF NOT EXISTS messages_ad AFTER DELETE ON messages BEGIN \
|
||
INSERT INTO messages_fts(messages_fts, rowid, content) VALUES('delete', old.rowid, old.content); \
|
||
END",
|
||
)
|
||
.await?;
|
||
|
||
db.execute_unprepared(
|
||
"CREATE TRIGGER IF NOT EXISTS messages_au AFTER UPDATE OF content ON messages BEGIN \
|
||
INSERT INTO messages_fts(messages_fts, rowid, content) VALUES('delete', old.rowid, old.content); \
|
||
INSERT INTO messages_fts(rowid, content) VALUES (new.rowid, new.content); \
|
||
END",
|
||
)
|
||
.await?;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||
// Drop triggers and FTS5 table first
|
||
let db = manager.get_connection();
|
||
db.execute_unprepared("DROP TRIGGER IF EXISTS messages_au")
|
||
.await?;
|
||
db.execute_unprepared("DROP TRIGGER IF EXISTS messages_ad")
|
||
.await?;
|
||
db.execute_unprepared("DROP TRIGGER IF EXISTS messages_ai")
|
||
.await?;
|
||
db.execute_unprepared("DROP TABLE IF EXISTS messages_fts")
|
||
.await?;
|
||
|
||
// Drop tables in reverse creation order
|
||
macro_rules! drop_tbl {
|
||
($t:expr) => {
|
||
manager
|
||
.drop_table(Table::drop().table($t).if_exists().to_owned())
|
||
.await?;
|
||
};
|
||
}
|
||
drop_tbl!(GatewayRequestLogs::Table);
|
||
drop_tbl!(StoredFiles::Table);
|
||
drop_tbl!(DesktopState::Table);
|
||
drop_tbl!(GatewayDiagnostics::Table);
|
||
drop_tbl!(ProgramPolicies::Table);
|
||
drop_tbl!(ImportJobs::Table);
|
||
drop_tbl!(BackupTargets::Table);
|
||
drop_tbl!(BackupManifests::Table);
|
||
drop_tbl!(ConversationBranches::Table);
|
||
drop_tbl!(ContextSources::Table);
|
||
drop_tbl!(ContextPacks::Table);
|
||
drop_tbl!(Artifacts::Table);
|
||
drop_tbl!(MemoryItems::Table);
|
||
drop_tbl!(MemoryNamespaces::Table);
|
||
drop_tbl!(RetrievalHits::Table);
|
||
drop_tbl!(KnowledgeDocuments::Table);
|
||
drop_tbl!(KnowledgeBases::Table);
|
||
drop_tbl!(ToolExecutions::Table);
|
||
drop_tbl!(ToolDescriptors::Table);
|
||
drop_tbl!(McpServers::Table);
|
||
drop_tbl!(SearchCitations::Table);
|
||
drop_tbl!(SearchProviders::Table);
|
||
drop_tbl!(Settings::Table);
|
||
drop_tbl!(GatewayUsage::Table);
|
||
drop_tbl!(GatewayKeys::Table);
|
||
drop_tbl!(Apps::Table);
|
||
drop_tbl!(Categories::Table);
|
||
drop_tbl!(Messages::Table);
|
||
drop_tbl!(Conversations::Table);
|
||
drop_tbl!(Models::Table);
|
||
drop_tbl!(ProviderKeys::Table);
|
||
drop_tbl!(Providers::Table);
|
||
|
||
Ok(())
|
||
}
|
||
}
|