mirror of
https://github.com/Dvorinka/Trackeep.git
synced 2026-07-29 05:53:50 +00:00
Remove AI/chat/search features, add solidtime integration and workspace setup
This commit is contained in:
@@ -1,153 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AIRecommendation represents an AI-generated recommendation
|
||||
type AIRecommendation struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
|
||||
// User information
|
||||
UserID uint `json:"user_id" gorm:"not null;index"`
|
||||
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
||||
|
||||
// Recommendation details
|
||||
RecommendationType string `json:"recommendation_type" gorm:"not null;index"` // content, task, learning, connection
|
||||
ContentType string `json:"content_type" gorm:"index"` // bookmark, note, task, course, user
|
||||
ContentID *uint `json:"content_id,omitempty" gorm:"index"`
|
||||
Title string `json:"title" gorm:"not null"`
|
||||
Description string `json:"description"`
|
||||
Reasoning string `json:"reasoning"` // Why this was recommended
|
||||
|
||||
// Content details (for display without additional queries)
|
||||
ContentTitle string `json:"content_title"`
|
||||
ContentURL string `json:"content_url"`
|
||||
ContentPreview string `json:"content_preview"`
|
||||
AuthorName string `json:"author_name"`
|
||||
Tags string `json:"tags" gorm:"serializer:json"`
|
||||
|
||||
// Recommendation metadata
|
||||
Confidence float64 `json:"confidence" gorm:"default:0.0"` // 0.0 to 1.0
|
||||
Priority string `json:"priority" gorm:"default:medium"` // low, medium, high
|
||||
Category string `json:"category"` // productivity, learning, collaboration, etc.
|
||||
ExpiresAt *time.Time `json:"expires_at"`
|
||||
Clicked bool `json:"clicked" gorm:"default:false"`
|
||||
Dismissed bool `json:"dismissed" gorm:"default:false"`
|
||||
ClickedAt *time.Time `json:"clicked_at"`
|
||||
DismissedAt *time.Time `json:"dismissed_at"`
|
||||
|
||||
// Feedback
|
||||
Feedback string `json:"feedback"` // helpful, not_helpful, irrelevant
|
||||
FeedbackAt *time.Time `json:"feedback_at"`
|
||||
FeedbackText string `json:"feedback_text"`
|
||||
|
||||
// Source information
|
||||
SourceModel string `json:"source_model"` // Which AI model generated this
|
||||
SourceVersion string `json:"source_version"` // Version of the recommendation engine
|
||||
TrainingData string `json:"training_data"` // What data was used for training
|
||||
}
|
||||
|
||||
// UserPreference represents user preferences for recommendations
|
||||
type UserPreference struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
|
||||
// User information
|
||||
UserID uint `json:"user_id" gorm:"not null;uniqueIndex"`
|
||||
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
||||
|
||||
// Recommendation preferences
|
||||
EnableRecommendations bool `json:"enable_recommendations" gorm:"default:true"`
|
||||
ContentRecommendations bool `json:"content_recommendations" gorm:"default:true"`
|
||||
TaskRecommendations bool `json:"task_recommendations" gorm:"default:true"`
|
||||
LearningRecommendations bool `json:"learning_recommendations" gorm:"default:true"`
|
||||
ConnectionRecommendations bool `json:"connection_recommendations" gorm:"default:false"`
|
||||
|
||||
// Frequency and timing
|
||||
MaxRecommendationsPerDay int `json:"max_recommendations_per_day" gorm:"default:5"`
|
||||
PreferredCategories []string `json:"preferred_categories" gorm:"serializer:json"`
|
||||
BlockedCategories []string `json:"blocked_categories" gorm:"serializer:json"`
|
||||
PreferredContentTypes []string `json:"preferred_content_types" gorm:"serializer:json"`
|
||||
|
||||
// Quality thresholds
|
||||
MinConfidenceThreshold float64 `json:"min_confidence_threshold" gorm:"default:0.6"`
|
||||
MaxAgeHours int `json:"max_age_hours" gorm:"default:168"` // 1 week
|
||||
|
||||
// Learning and adaptation
|
||||
EnablePersonalization bool `json:"enable_personalization" gorm:"default:true"`
|
||||
EnableFeedbackLearning bool `json:"enable_feedback_learning" gorm:"default:true"`
|
||||
LastRecommendationAt *time.Time `json:"last_recommendation_at"`
|
||||
}
|
||||
|
||||
// RecommendationInteraction tracks user interactions with recommendations
|
||||
type RecommendationInteraction struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
|
||||
// Related entities
|
||||
UserID uint `json:"user_id" gorm:"not null;index"`
|
||||
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
||||
RecommendationID uint `json:"recommendation_id" gorm:"not null;index"`
|
||||
Recommendation AIRecommendation `json:"recommendation,omitempty" gorm:"foreignKey:RecommendationID"`
|
||||
|
||||
// Interaction details
|
||||
InteractionType string `json:"interaction_type" gorm:"not null;index"` // view, click, dismiss, feedback, share
|
||||
InteractionData string `json:"interaction_data" gorm:"serializer:json"` // Additional context
|
||||
Duration int `json:"duration"` // Time spent in seconds (for views)
|
||||
Context string `json:"context"` // Where the interaction occurred (dashboard, search, etc.)
|
||||
|
||||
// Machine learning features
|
||||
UserActivityBefore string `json:"user_activity_before"` // What user was doing before
|
||||
UserActivityAfter string `json:"user_activity_after"` // What user did after
|
||||
SessionID string `json:"session_id"`
|
||||
DeviceType string `json:"device_type"`
|
||||
}
|
||||
|
||||
// TableName returns the table name for AIRecommendation
|
||||
func (AIRecommendation) TableName() string {
|
||||
return "ai_recommendations"
|
||||
}
|
||||
|
||||
// TableName returns the table name for UserPreference
|
||||
func (UserPreference) TableName() string {
|
||||
return "user_preferences"
|
||||
}
|
||||
|
||||
// TableName returns the table name for RecommendationInteraction
|
||||
func (RecommendationInteraction) TableName() string {
|
||||
return "recommendation_interactions"
|
||||
}
|
||||
|
||||
// BeforeCreate hooks
|
||||
func (r *AIRecommendation) BeforeCreate(tx *gorm.DB) error {
|
||||
if r.Priority == "" {
|
||||
r.Priority = "medium"
|
||||
}
|
||||
if r.Confidence == 0 {
|
||||
r.Confidence = 0.5
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (up *UserPreference) BeforeCreate(tx *gorm.DB) error {
|
||||
if up.MaxRecommendationsPerDay == 0 {
|
||||
up.MaxRecommendationsPerDay = 5
|
||||
}
|
||||
if up.MinConfidenceThreshold == 0 {
|
||||
up.MinConfidenceThreshold = 0.6
|
||||
}
|
||||
if up.MaxAgeHours == 0 {
|
||||
up.MaxAgeHours = 168 // 1 week
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// UserAISettings stores user-specific AI provider configurations
|
||||
type UserAISettings struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
|
||||
UserID uint `json:"user_id" gorm:"not null;uniqueIndex"`
|
||||
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
||||
|
||||
// Mistral Settings
|
||||
MistralEnabled *bool `json:"mistral_enabled" gorm:"default:false"`
|
||||
MistralAPIKey string `json:"-" gorm:"column:mistral_api_key"` // Encrypted
|
||||
MistralModel string `json:"mistral_model" gorm:"default:mistral-small-latest"`
|
||||
MistralModelThinking string `json:"mistral_model_thinking" gorm:"default:mistral-large-latest"`
|
||||
|
||||
// Grok Settings
|
||||
GrokEnabled *bool `json:"grok_enabled" gorm:"default:false"`
|
||||
GrokAPIKey string `json:"-" gorm:"column:grok_api_key"` // Encrypted
|
||||
GrokBaseURL string `json:"grok_base_url" gorm:"default:https://api.x.ai/v1"`
|
||||
GrokModel string `json:"grok_model" gorm:"default:grok-4-1-fast-non-reasoning-latest"`
|
||||
GrokModelThinking string `json:"grok_model_thinking" gorm:"default:grok-4-1-fast-reasoning-latest"`
|
||||
|
||||
// DeepSeek Settings
|
||||
DeepSeekEnabled *bool `json:"deepseek_enabled" gorm:"default:false"`
|
||||
DeepSeekAPIKey string `json:"-" gorm:"column:deepseek_api_key"` // Encrypted
|
||||
DeepSeekBaseURL string `json:"deepseek_base_url" gorm:"default:https://api.deepseek.com"`
|
||||
DeepSeekModel string `json:"deepseek_model" gorm:"default:deepseek-chat"`
|
||||
DeepSeekModelThinking string `json:"deepseek_model_thinking" gorm:"default:deepseek-reasoner"`
|
||||
|
||||
// Ollama Settings
|
||||
OllamaEnabled *bool `json:"ollama_enabled" gorm:"default:false"`
|
||||
OllamaBaseURL string `json:"ollama_base_url" gorm:"default:http://localhost:11434"`
|
||||
OllamaModel string `json:"ollama_model" gorm:"default:llama3.1"`
|
||||
OllamaModelThinking string `json:"ollama_model_thinking" gorm:"default:llama3.1"`
|
||||
|
||||
// LongCat Settings
|
||||
LongCatEnabled *bool `json:"longcat_enabled" gorm:"default:false"`
|
||||
LongCatAPIKey string `json:"-" gorm:"column:longcat_api_key"` // Encrypted
|
||||
LongCatBaseURL string `json:"longcat_base_url" gorm:"default:https://api.longcat.chat"`
|
||||
LongCatOpenAIEndpoint string `json:"longcat_openai_endpoint" gorm:"default:https://api.longcat.chat/openai"`
|
||||
LongCatAnthropicEndpoint string `json:"longcat_anthropic_endpoint" gorm:"default:https://api.longcat.chat/anthropic"`
|
||||
LongCatModel string `json:"longcat_model" gorm:"default:LongCat-Flash-Chat"`
|
||||
LongCatModelThinking string `json:"longcat_model_thinking" gorm:"default:LongCat-Flash-Thinking"`
|
||||
LongCatModelThinkingUpgraded string `json:"longcat_model_thinking_upgraded" gorm:"default:LongCat-Flash-Thinking-2601"`
|
||||
LongCatFormat string `json:"longcat_format" gorm:"default:openai"`
|
||||
|
||||
// OpenRouter Settings
|
||||
OpenRouterEnabled *bool `json:"openrouter_enabled" gorm:"default:false"`
|
||||
OpenRouterAPIKey string `json:"-" gorm:"column:openrouter_api_key"` // Encrypted
|
||||
OpenRouterBaseURL string `json:"openrouter_base_url" gorm:"default:https://openrouter.ai/api"`
|
||||
OpenRouterModel string `json:"openrouter_model" gorm:"default:openrouter/auto"`
|
||||
OpenRouterModelThinking string `json:"openrouter_model_thinking" gorm:"default:openrouter/auto"`
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ChatMessage represents a chat message in the AI conversation
|
||||
type ChatMessage struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
|
||||
UserID uint `json:"user_id" gorm:"not null;index"`
|
||||
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
||||
|
||||
Content string `json:"content" gorm:"not null"`
|
||||
Role string `json:"role" gorm:"not null"` // "user" or "assistant"
|
||||
|
||||
// Session tracking
|
||||
SessionID string `json:"session_id" gorm:"not null;index"`
|
||||
|
||||
// Metadata
|
||||
TokenCount int `json:"token_count"`
|
||||
ModelUsed string `json:"model_used"`
|
||||
ProcessingMs int64 `json:"processing_ms"`
|
||||
ContextItems []string `json:"context_items" gorm:"serializer:json"` // IDs of referenced items
|
||||
}
|
||||
|
||||
// ChatSession represents a chat session
|
||||
type ChatSession struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
|
||||
UserID uint `json:"user_id" gorm:"not null;index"`
|
||||
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
||||
|
||||
Title string `json:"title"`
|
||||
|
||||
// Session metadata
|
||||
MessageCount int `json:"message_count" gorm:"default:0"`
|
||||
LastMessageAt *time.Time `json:"last_message_at"`
|
||||
|
||||
// Context configuration
|
||||
IncludeBookmarks bool `json:"include_bookmarks" gorm:"default:true"`
|
||||
IncludeTasks bool `json:"include_tasks" gorm:"default:true"`
|
||||
IncludeFiles bool `json:"include_files" gorm:"default:true"`
|
||||
IncludeNotes bool `json:"include_notes" gorm:"default:true"`
|
||||
|
||||
// Relationships
|
||||
Messages []ChatMessage `json:"messages,omitempty" gorm:"foreignKey:SessionID"`
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ConversationType represents the type of a conversation.
|
||||
type ConversationType string
|
||||
|
||||
const (
|
||||
ConversationTypeGlobal ConversationType = "global"
|
||||
ConversationTypeTeam ConversationType = "team"
|
||||
ConversationTypeGroup ConversationType = "group"
|
||||
ConversationTypeDM ConversationType = "dm"
|
||||
ConversationTypeSelf ConversationType = "self"
|
||||
ConversationTypePasswordVault ConversationType = "password_vault"
|
||||
)
|
||||
|
||||
// ConversationMemberRole represents the role of a user in a conversation.
|
||||
type ConversationMemberRole string
|
||||
|
||||
const (
|
||||
ConversationMemberRoleOwner ConversationMemberRole = "owner"
|
||||
ConversationMemberRoleAdmin ConversationMemberRole = "admin"
|
||||
ConversationMemberRoleMember ConversationMemberRole = "member"
|
||||
ConversationMemberRoleViewer ConversationMemberRole = "viewer"
|
||||
)
|
||||
|
||||
// SuggestionStatus is the lifecycle state of a message suggestion.
|
||||
type SuggestionStatus string
|
||||
|
||||
const (
|
||||
SuggestionStatusPending SuggestionStatus = "pending"
|
||||
SuggestionStatusAccepted SuggestionStatus = "accepted"
|
||||
SuggestionStatusDismissed SuggestionStatus = "dismissed"
|
||||
)
|
||||
|
||||
// Conversation is a user-to-user chat space (global/team/group/dm/self/password).
|
||||
type Conversation struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
|
||||
Type ConversationType `json:"type" gorm:"not null;index"`
|
||||
Name string `json:"name" gorm:"not null"`
|
||||
Topic string `json:"topic"`
|
||||
TeamID *uint `json:"team_id,omitempty" gorm:"index"`
|
||||
Team *Team `json:"team,omitempty" gorm:"foreignKey:TeamID"`
|
||||
CreatedBy uint `json:"created_by" gorm:"not null;index"`
|
||||
Creator User `json:"creator,omitempty" gorm:"foreignKey:CreatedBy"`
|
||||
IsDefault bool `json:"is_default" gorm:"default:false;index"`
|
||||
IsArchived bool `json:"is_archived" gorm:"default:false;index"`
|
||||
|
||||
LastMessageAt *time.Time `json:"last_message_at"`
|
||||
|
||||
Members []ConversationMember `json:"members,omitempty" gorm:"foreignKey:ConversationID"`
|
||||
Messages []Message `json:"messages,omitempty" gorm:"foreignKey:ConversationID"`
|
||||
}
|
||||
|
||||
// ConversationMember links users to conversations.
|
||||
type ConversationMember struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
|
||||
ConversationID uint `json:"conversation_id" gorm:"not null;index:idx_conv_member,unique"`
|
||||
UserID uint `json:"user_id" gorm:"not null;index:idx_conv_member,unique"`
|
||||
Role ConversationMemberRole `json:"role" gorm:"not null;default:member"`
|
||||
JoinedAt time.Time `json:"joined_at"`
|
||||
|
||||
LastReadMessageID *uint `json:"last_read_message_id,omitempty" gorm:"index"`
|
||||
LastReadAt *time.Time `json:"last_read_at,omitempty"`
|
||||
MutedUntil *time.Time `json:"muted_until,omitempty"`
|
||||
IsHidden bool `json:"is_hidden" gorm:"default:false"`
|
||||
|
||||
Conversation Conversation `json:"conversation,omitempty" gorm:"foreignKey:ConversationID"`
|
||||
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
||||
}
|
||||
|
||||
// Message is a single chat message in a conversation.
|
||||
type Message struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
ConversationID uint `json:"conversation_id" gorm:"not null;index"`
|
||||
Conversation Conversation `json:"conversation,omitempty" gorm:"foreignKey:ConversationID"`
|
||||
SenderID uint `json:"sender_id" gorm:"not null;index"`
|
||||
Sender User `json:"sender,omitempty" gorm:"foreignKey:SenderID"`
|
||||
|
||||
Body string `json:"body" gorm:"type:text"`
|
||||
IsSensitive bool `json:"is_sensitive" gorm:"default:false"`
|
||||
EditedAt *time.Time `json:"edited_at,omitempty"`
|
||||
DeletedAt *time.Time `json:"deleted_at,omitempty" gorm:"index"`
|
||||
|
||||
MetadataJSON string `json:"metadata_json" gorm:"type:text"`
|
||||
|
||||
Attachments []MessageAttachment `json:"attachments,omitempty" gorm:"foreignKey:MessageID"`
|
||||
References []MessageReference `json:"references,omitempty" gorm:"foreignKey:MessageID"`
|
||||
Suggestions []MessageSuggestion `json:"suggestions,omitempty" gorm:"foreignKey:MessageID"`
|
||||
Reactions []MessageReaction `json:"reactions,omitempty" gorm:"foreignKey:MessageID"`
|
||||
}
|
||||
|
||||
// MessageAttachment represents file/link-style message attachments.
|
||||
type MessageAttachment struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
MessageID uint `json:"message_id" gorm:"not null;index"`
|
||||
Message Message `json:"message,omitempty" gorm:"foreignKey:MessageID"`
|
||||
|
||||
Kind string `json:"kind" gorm:"not null;index"` // file,image,youtube,github,website,bookmark,task,event,calendar,activity,learning_path,saved_search,voice_note
|
||||
FileID *uint `json:"file_id,omitempty" gorm:"index"`
|
||||
URL string `json:"url"`
|
||||
Title string `json:"title"`
|
||||
PreviewJSON string `json:"preview_json" gorm:"type:text"`
|
||||
}
|
||||
|
||||
// MessageReference maps chat messages to Trackeep entities.
|
||||
type MessageReference struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
MessageID uint `json:"message_id" gorm:"not null;index"`
|
||||
Message Message `json:"message,omitempty" gorm:"foreignKey:MessageID"`
|
||||
|
||||
EntityType string `json:"entity_type" gorm:"not null;index"`
|
||||
EntityID uint `json:"entity_id" gorm:"not null;index"`
|
||||
DeepLink string `json:"deep_link" gorm:"not null"`
|
||||
}
|
||||
|
||||
// MessageSuggestion stores non-blocking smart suggestions triggered by message text.
|
||||
type MessageSuggestion struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
MessageID uint `json:"message_id" gorm:"not null;index"`
|
||||
Message Message `json:"message,omitempty" gorm:"foreignKey:MessageID"`
|
||||
|
||||
Type string `json:"type" gorm:"not null;index"` // create_task, create_event, save_bookmark, ...
|
||||
PayloadJSON string `json:"payload_json" gorm:"type:text"`
|
||||
Status SuggestionStatus `json:"status" gorm:"not null;default:pending;index"`
|
||||
}
|
||||
|
||||
// MessageReaction stores emoji reactions.
|
||||
type MessageReaction struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
MessageID uint `json:"message_id" gorm:"not null;index:idx_message_reaction,unique"`
|
||||
Message Message `json:"message,omitempty" gorm:"foreignKey:MessageID"`
|
||||
UserID uint `json:"user_id" gorm:"not null;index:idx_message_reaction,unique"`
|
||||
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
||||
Emoji string `json:"emoji" gorm:"not null;index:idx_message_reaction,unique"`
|
||||
}
|
||||
|
||||
// PasswordVaultItem is encrypted secret data owned by a user.
|
||||
type PasswordVaultItem struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
OwnerUserID uint `json:"owner_user_id" gorm:"not null;index"`
|
||||
OwnerUser User `json:"owner_user,omitempty" gorm:"foreignKey:OwnerUserID"`
|
||||
|
||||
Label string `json:"label" gorm:"not null"`
|
||||
EncryptedSecret string `json:"-" gorm:"type:text;not null"`
|
||||
EncryptedNotes string `json:"-" gorm:"type:text"`
|
||||
SourceMessageID *uint `json:"source_message_id,omitempty" gorm:"index"`
|
||||
SourceMessage *Message `json:"source_message,omitempty" gorm:"foreignKey:SourceMessageID"`
|
||||
CreatedBy uint `json:"created_by" gorm:"not null;index"`
|
||||
LastAccessedAt *time.Time `json:"last_accessed_at,omitempty"`
|
||||
|
||||
Shares []PasswordVaultShare `json:"shares,omitempty" gorm:"foreignKey:VaultItemID"`
|
||||
}
|
||||
|
||||
// PasswordVaultShare controls explicit sharing of vault items.
|
||||
type PasswordVaultShare struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
VaultItemID uint `json:"vault_item_id" gorm:"not null;index"`
|
||||
VaultItem PasswordVaultItem `json:"vault_item,omitempty" gorm:"foreignKey:VaultItemID"`
|
||||
|
||||
SharedByUserID uint `json:"shared_by_user_id" gorm:"not null;index"`
|
||||
SharedByUser User `json:"shared_by_user,omitempty" gorm:"foreignKey:SharedByUserID"`
|
||||
TargetConversationID uint `json:"target_conversation_id" gorm:"not null;index"`
|
||||
TargetConversation Conversation `json:"target_conversation,omitempty" gorm:"foreignKey:TargetConversationID"`
|
||||
ExpiresAt *time.Time `json:"expires_at,omitempty"`
|
||||
AllowReveal bool `json:"allow_reveal" gorm:"default:false"`
|
||||
}
|
||||
+12
-39
@@ -127,36 +127,18 @@ func AutoMigrate() error {
|
||||
{name: "BrowserExtension", model: &BrowserExtension{}},
|
||||
{name: "TimeEntry", model: &TimeEntry{}},
|
||||
{name: "FileAnalysis", model: &FileAnalysis{}},
|
||||
{name: "ChatSession", model: &ChatSession{}},
|
||||
{name: "ChatMessage", model: &ChatMessage{}},
|
||||
{name: "LearningPath", model: &LearningPath{}},
|
||||
{name: "LearningModule", model: &LearningModule{}},
|
||||
{name: "ModuleResource", model: &ModuleResource{}},
|
||||
{name: "Enrollment", model: &Enrollment{}},
|
||||
{name: "Progress", model: &Progress{}},
|
||||
{name: "Course", model: &Course{}},
|
||||
{name: "LearningPathCourse", model: &LearningPathCourse{}},
|
||||
{name: "CalendarEvent", model: &CalendarEvent{}},
|
||||
{name: "RecurrenceRule", model: &RecurrenceRule{}},
|
||||
{name: "CalendarSettings", model: &CalendarSettings{}},
|
||||
{name: "ContentEmbedding", model: &ContentEmbedding{}},
|
||||
{name: "SavedSearch", model: &SavedSearch{}},
|
||||
{name: "SavedSearchTag", model: &SavedSearchTag{}},
|
||||
{name: "SearchAnalytics", model: &SearchAnalytics{}},
|
||||
{name: "SearchSuggestion", model: &SearchSuggestion{}},
|
||||
{name: "AISummary", model: &AISummary{}},
|
||||
{name: "AITaskSuggestion", model: &AITaskSuggestion{}},
|
||||
{name: "UserAISettings", model: &UserAISettings{}},
|
||||
{name: "UserSearchSettings", model: &UserSearchSettings{}},
|
||||
{name: "UserUpdateSettings", model: &UserUpdateSettings{}},
|
||||
{name: "AITagSuggestion", model: &AITagSuggestion{}},
|
||||
{name: "AIContentGeneration", model: &AIContentGeneration{}},
|
||||
{name: "AICodeReview", model: &AICodeReview{}},
|
||||
{name: "AILearningRecommendation", model: &AILearningRecommendation{}},
|
||||
{name: "AIRecommendation", model: &AIRecommendation{}},
|
||||
{name: "UserPreference", model: &UserPreference{}},
|
||||
{name: "RecommendationInteraction", model: &RecommendationInteraction{}},
|
||||
{name: "Integration", model: &Integration{}},
|
||||
{name: "LearningPath", model: &LearningPath{}},
|
||||
{name: "LearningModule", model: &LearningModule{}},
|
||||
{name: "ModuleResource", model: &ModuleResource{}},
|
||||
{name: "Enrollment", model: &Enrollment{}},
|
||||
{name: "Progress", model: &Progress{}},
|
||||
{name: "Course", model: &Course{}},
|
||||
{name: "LearningPathCourse", model: &LearningPathCourse{}},
|
||||
{name: "CalendarEvent", model: &CalendarEvent{}},
|
||||
{name: "RecurrenceRule", model: &RecurrenceRule{}},
|
||||
{name: "CalendarSettings", model: &CalendarSettings{}},
|
||||
{name: "UserUpdateSettings", model: &UserUpdateSettings{}},
|
||||
{name: "Integration", model: &Integration{}},
|
||||
{name: "SyncLog", model: &SyncLog{}},
|
||||
{name: "WebhookEvent", model: &WebhookEvent{}},
|
||||
{name: "ControlServiceSession", model: &ControlServiceSession{}},
|
||||
@@ -208,15 +190,6 @@ func AutoMigrate() error {
|
||||
{name: "MentorshipRequest", model: &MentorshipRequest{}},
|
||||
{name: "YouTubeChannelCache", model: &YouTubeChannelCache{}},
|
||||
{name: "VideoBookmark", model: &VideoBookmark{}},
|
||||
{name: "Conversation", model: &Conversation{}},
|
||||
{name: "ConversationMember", model: &ConversationMember{}},
|
||||
{name: "Message", model: &Message{}},
|
||||
{name: "MessageAttachment", model: &MessageAttachment{}},
|
||||
{name: "MessageReference", model: &MessageReference{}},
|
||||
{name: "MessageSuggestion", model: &MessageSuggestion{}},
|
||||
{name: "MessageReaction", model: &MessageReaction{}},
|
||||
{name: "PasswordVaultItem", model: &PasswordVaultItem{}},
|
||||
{name: "PasswordVaultShare", model: &PasswordVaultShare{}},
|
||||
}
|
||||
|
||||
criticalModels := map[string]bool{
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ContentEmbedding stores vector embeddings for semantic search
|
||||
type ContentEmbedding struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
|
||||
// Content reference
|
||||
ContentType string `json:"content_type" gorm:"not null;index"` // 'bookmark', 'task', 'note', 'file'
|
||||
ContentID uint `json:"content_id" gorm:"not null;index"`
|
||||
|
||||
// Embedding data
|
||||
Embedding string `json:"embedding" gorm:"type:text"` // JSON array of floats
|
||||
Model string `json:"model" gorm:"not null"` // AI model used
|
||||
Dimensions int `json:"dimensions" gorm:"not null"` // Vector dimensions
|
||||
TextContent string `json:"text_content" gorm:"type:text"` // Original text for embedding
|
||||
|
||||
// Metadata
|
||||
UserID uint `json:"user_id" gorm:"not null;index"`
|
||||
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
||||
}
|
||||
|
||||
// SavedSearch represents a user's saved search query
|
||||
type SavedSearch struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
|
||||
UserID uint `json:"user_id" gorm:"not null;index"`
|
||||
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
||||
|
||||
Name string `json:"name" gorm:"not null"`
|
||||
Query string `json:"query" gorm:"not null"`
|
||||
Filters string `json:"filters" gorm:"type:json"` // JSON serialized filters
|
||||
Alert bool `json:"alert" gorm:"default:false"`
|
||||
LastRun *time.Time `json:"last_run"`
|
||||
RunCount int `json:"run_count" gorm:"default:0"`
|
||||
IsPublic bool `json:"is_public" gorm:"default:false"`
|
||||
Description string `json:"description"`
|
||||
Tags []SavedSearchTag `json:"tags,omitempty" gorm:"many2many:saved_search_tags;"`
|
||||
}
|
||||
|
||||
// SavedSearchTag represents tags for saved searches
|
||||
type SavedSearchTag struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
Name string `json:"name" gorm:"unique;not null"`
|
||||
Color string `json:"color" gorm:"default:#3b82f6"`
|
||||
}
|
||||
|
||||
// SearchAnalytics stores search analytics data
|
||||
type SearchAnalytics struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
|
||||
UserID uint `json:"user_id" gorm:"not null;index"`
|
||||
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
||||
|
||||
Query string `json:"query" gorm:"not null;index"`
|
||||
Filters string `json:"filters" gorm:"type:json"`
|
||||
ResultsCount int `json:"results_count"`
|
||||
Took int `json:"took"` // Time in milliseconds
|
||||
ContentType string `json:"content_type"`
|
||||
ClickedResultID *uint `json:"clicked_result_id"` // Track which result was clicked
|
||||
SessionID string `json:"session_id" gorm:"index"`
|
||||
IPAddress string `json:"ip_address"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
}
|
||||
|
||||
// SearchSuggestion represents search suggestions
|
||||
type SearchSuggestion struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
|
||||
Text string `json:"text" gorm:"not null;uniqueIndex"`
|
||||
Type string `json:"type" gorm:"not null"` // 'query', 'tag', 'content'
|
||||
Frequency int `json:"frequency" gorm:"default:1"`
|
||||
LastUsed time.Time `json:"last_used"`
|
||||
ContentType *string `json:"content_type,omitempty"`
|
||||
IsPublic bool `json:"is_public" gorm:"default:true"`
|
||||
}
|
||||
|
||||
// BeforeCreate hook for ContentEmbedding
|
||||
func (ce *ContentEmbedding) BeforeCreate(tx *gorm.DB) error {
|
||||
// Set default model if not specified
|
||||
if ce.Model == "" {
|
||||
ce.Model = "text-embedding-ada-002"
|
||||
}
|
||||
|
||||
// Set default dimensions if not specified
|
||||
if ce.Dimensions == 0 {
|
||||
ce.Dimensions = 1536 // Default for OpenAI embeddings
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user