Skip to main content

Overview

All models live in src/DualMind.API/Core/Models/. They use [JsonProperty("snake_case")] for Supabase compatibility.
All C# models use [JsonProperty("snake_case")] attributes because Supabase PostgREST returns snake_case column names. The backend serializes responses as camelCase for the frontend.

Entity models

User

public class User
{
    [JsonProperty("user_id")]    public Guid? UserId { get; set; }
    [JsonProperty("full_name")]  public string? FullName { get; set; }
    [JsonProperty("email")]      public string? Email { get; set; }
    [JsonProperty("role")]       public string? Role { get; set; } = "user";
    [JsonProperty("created_at")] public DateTime? CreatedAt { get; set; }
    [JsonProperty("last_login_at")] public DateTime? LastLoginAt { get; set; }
}

AIModel

public class AIModel
{
    [JsonProperty("model_id")]      public Guid? ModelId { get; set; }
    [JsonProperty("model_name")]    public string? ModelName { get; set; }
    [JsonProperty("provider_name")] public string? ProviderName { get; set; }
    [JsonProperty("api_url")]       public string? ApiUrl { get; set; }
    [JsonProperty("description")]   public string? Description { get; set; }
    [JsonProperty("status")]        public string? Status { get; set; } = "active";
    [JsonProperty("created_by")]    public Guid? CreatedBy { get; set; }
    [JsonProperty("created_at")]    public DateTime? CreatedAt { get; set; }
    [JsonProperty("updated_at")]    public DateTime? UpdatedAt { get; set; }
}

Comparison

public class Comparison
{
    [JsonProperty("comparison_id")]  public Guid? ComparisonId { get; set; }
    [JsonProperty("user_id")]        public Guid? UserId { get; set; }
    [JsonProperty("prompt_text")]    public string? PromptText { get; set; }
    [JsonProperty("model1_id")]      public Guid? Model1Id { get; set; }
    [JsonProperty("model2_id")]      public Guid? Model2Id { get; set; }
    [JsonProperty("model1_response")]public string? Model1Response { get; set; }
    [JsonProperty("model2_response")]public string? Model2Response { get; set; }
    [JsonProperty("model1_time_ms")] public int? Model1TimeMs { get; set; }
    [JsonProperty("model2_time_ms")] public int? Model2TimeMs { get; set; }
    [JsonProperty("created_at")]     public DateTime? CreatedAt { get; set; }
}

ModelVote

public class ModelVote
{
    [JsonProperty("vote_id")]         public Guid? VoteId { get; set; }
    [JsonProperty("user_id")]         public Guid? UserId { get; set; }
    [JsonProperty("comparison_id")]   public Guid? ComparisonId { get; set; }
    [JsonProperty("winner_model_id")] public Guid? WinnerModelId { get; set; }
    [JsonProperty("created_at")]      public DateTime? CreatedAt { get; set; }
}

ChatThread

public class ChatThread
{
    [JsonProperty("thread_id")]  public Guid? ThreadId { get; set; }
    [JsonProperty("user_id")]    public Guid? UserId { get; set; }
    [JsonProperty("title")]      public string? Title { get; set; }
    [JsonProperty("created_at")] public DateTime? CreatedAt { get; set; }
}

ThreadMessage

public class ThreadMessage
{
    [JsonProperty("message_id")]      public Guid? MessageId { get; set; }
    [JsonProperty("thread_id")]       public Guid? ThreadId { get; set; }
    [JsonProperty("prompt_text")]     public string? PromptText { get; set; }
    [JsonProperty("model1_id")]       public Guid? Model1Id { get; set; }
    [JsonProperty("model2_id")]       public Guid? Model2Id { get; set; }
    [JsonProperty("model1_response")] public string? Model1Response { get; set; }
    [JsonProperty("model2_response")] public string? Model2Response { get; set; }
    [JsonProperty("model1_time_ms")]  public int? Model1TimeMs { get; set; }
    [JsonProperty("model2_time_ms")]  public int? Model2TimeMs { get; set; }
    [JsonProperty("created_at")]      public DateTime? CreatedAt { get; set; }
}

Provider and ProviderApiKey

public class Provider
{
    [JsonProperty("provider_name")] public string? ProviderName { get; set; }
    [JsonProperty("display_name")]  public string? DisplayName { get; set; }
    [JsonProperty("is_enabled")]    public bool IsEnabled { get; set; }
    [JsonProperty("priority")]      public int Priority { get; set; }
    [JsonProperty("created_at")]    public DateTime? CreatedAt { get; set; }
    [JsonProperty("updated_at")]    public DateTime? UpdatedAt { get; set; }
}

public class ProviderApiKey
{
    [JsonProperty("key_id")]             public Guid KeyId { get; set; }
    [JsonProperty("provider_name")]      public string? ProviderName { get; set; }
    [JsonProperty("api_key")]            public string? ApiKey { get; set; }
    [JsonProperty("display_mask")]       public string? DisplayMask { get; set; }
    [JsonProperty("is_active")]          public bool IsActive { get; set; }
    [JsonProperty("failure_count")]      public int FailureCount { get; set; }
    [JsonProperty("total_calls")]        public int TotalCalls { get; set; }
    [JsonProperty("last_used_at")]       public DateTime? LastUsedAt { get; set; }
    [JsonProperty("last_error_type")]    public string? LastErrorType { get; set; }
    [JsonProperty("cooldown_until")]     public DateTime? CooldownUntil { get; set; }
    [JsonProperty("created_by")]         public Guid? CreatedBy { get; set; }
}

Request DTOs

ChatRequest (AI contracts)

public class ChatRequest
{
    public string? ThreadId { get; set; }
    public string? Prompt { get; set; }
    public string? System { get; set; }
    public string? Model { get; set; }
    public string? Model1 { get; set; }
    public string? Model2 { get; set; }
    public string? SelectionMode { get; set; }
    public int? MaxTokens { get; set; }
    public double? Temperature { get; set; }
}

VoteRequest

public class VoteRequest
{
    public Guid ComparisonId { get; set; }
    public string WinnerModelName { get; set; }
    public Guid? UserId { get; set; }
}

CreateThreadRequest

public class CreateThreadRequest
{
    public string? Title { get; set; }
    public Guid? UserId { get; set; }
}

SyncUserRequest

public class SyncUserRequest
{
    public string Id { get; set; }
    public string Email { get; set; }
    public string? Phone { get; set; }
    public string? Name { get; set; }
    public string? AvatarUrl { get; set; }
    public string? Provider { get; set; }
}

Response DTOs

ChatResponse

public class ChatResponse
{
    public string Object { get; set; }       // "ai.response"
    public ContentOutput Output { get; set; }
    public bool Success { get; set; }
    public string Message { get; set; }      // Convenience shortcut
    public ModelInfo Model { get; set; }
    public string Prompt { get; set; }
    public string SelectionMode { get; set; }
    public long ResponseTimeMs { get; set; }
    public UsageInfo Usage { get; set; }
    public DateTime Timestamp { get; set; }
}

public class ModelInfo
{
    public string Name { get; set; }
    public string DisplayName { get; set; }
    public string Provider { get; set; }
}

public class UsageInfo
{
    public int PromptTokens { get; set; }
    public int CompletionTokens { get; set; }
    public int TotalTokens { get; set; }
}

GroqResponse (internal)

public class GroqResponse
{
    public string Message { get; set; }
    public string Model { get; set; }
    public int PromptTokens { get; set; }
    public int CompletionTokens { get; set; }
    public int TotalTokens { get; set; }
}

ModelStatsDto

public class ModelStatsDto
{
    public Guid ModelId { get; set; }
    public string ModelName { get; set; }
    public string ProviderName { get; set; }
    public int TotalWins { get; set; }
    public int TotalResponses { get; set; }
    public double WinRate { get; set; }
}

FeatureFlagResponse

public class FeatureFlagResponse
{
    public string Key { get; set; }
    public bool Enabled { get; set; }
}