Skip to main content

Conversation Model - Detailed Explanation

What is a Conversation?

A conversation represents a chat/interaction between a user and the AI system about a specific case. It contains:

  • User messages (questions, requests)
  • System messages (AI responses)
  • Metadata about the conversation (which case, when, etc.)

Issue 1: isActive vs isArchived - Explained

Current Situation:

// In TotoConversation interface (app):
isActive: boolean // true = active, false = archived

// In saveConversation (storage):
isArchived: false // false = active, true = archived

// In transformConversationDoc (conversion):
isActive: !data.isArchived // Converts isArchived to isActive

The Problem:

  • Storage uses isArchived (true/false)
  • App interface uses isActive (true/false)
  • They're opposites: isActive = !isArchived
  • This creates confusion and requires conversion

Example:

// Storage has: isArchived: false
// App expects: isActive: true
// Conversion needed: isActive = !isArchived

Recommendation:

Use isArchived everywhere because:

  • More explicit: "Is this archived?" vs "Is this active?"
  • Common pattern in email/messaging apps
  • No conversion needed
  • Clearer intent: isArchived: true is more obvious than isActive: false

Issue 2: Missing updatedAt - Explained

Current Situation:

// Conversation has:
createdAt: string // When conversation was created
lastMessageAt: string // When last message was added

// But missing:
updatedAt: string // When conversation metadata was updated

The Problem:

  • lastMessageAt tracks when messages are added
  • But if you update caseName, isArchived, or other metadata, there's no timestamp
  • Can't track when conversation was last modified (not just new messages)

Example:

// User archives conversation
conversation.isArchived = true;
// No updatedAt field to track when this happened

Recommendation:

Add updatedAt field:

  • Set to createdAt on creation
  • Update whenever conversation metadata changes (not just messages)
  • Useful for: "When did user archive this?", "When was case name updated?"

Issue 3: Timestamp Type Mismatch - Explained

Current Situation:

// In TotoConversation interface:
createdAt: string // ISO 8601 string
lastMessageAt: string // ISO 8601 string
messages[].timestamp: Date // JavaScript Date object

// In saveConversation (storage):
createdAt: Timestamp // Firestore Timestamp
lastMessageAt: Timestamp // Firestore Timestamp
messages[].timestamp: Timestamp // Firestore Timestamp

The Problem:

  • App code uses string (ISO 8601) and Date objects
  • Storage uses Firestore Timestamp objects
  • Conversion needed every time: Timestamp.fromDate() or timestamp.toDate()
  • Inconsistent types cause confusion

Example:

// App expects:
createdAt: "2025-01-15T10:30:00Z" // string

// Storage has:
createdAt: Timestamp { seconds: 1736944200, nanoseconds: 0 } // Firestore Timestamp

// Conversion needed:
const createdAt = timestamp.toDate().toISOString(); // Convert to string

Recommendation:

Standardize on string (ISO 8601) in the model:

  • Consistent with other models (Cases, Users, etc.)
  • Easier to work with in TypeScript
  • Convert to Firestore Timestamp only when saving to database
  • Convert back to string when reading from database

Issue 4: actionTaken Field - Explained

Current Situation:

// In ConversationData (for saving):
actionTaken: string // Required: 'chat', 'donate', 'share', etc.

// In TotoConversation (app interface):
// Missing - not included

// In saveConversation (storage):
actionTaken: conversationData.actionTaken || 'chat' // Optional, defaults to 'chat'

The Problem:

  • actionTaken tracks what the user did in the conversation (donated, shared, etc.)
  • It's required when saving but missing from the app interface
  • App can't access this information

Example:

// User starts conversation about a case
// User asks: "How can I donate?"
// AI responds with donation instructions
// User completes donation
// actionTaken: 'donate' // Tracks that donation happened

// But TotoConversation interface doesn't have this field!
// App can't display "This conversation led to a donation"

Recommendation:

Add actionTaken?: string to base model:

  • Optional field (not all conversations have actions)
  • Tracks what happened: 'chat', 'donate', 'share', 'follow', etc.
  • Useful for analytics and UI display

Issue 5: Platform Field Confusion - Explained

Current Situation:

// At conversation level:
platform?: string[] // ['casecard', 'inbox', 'chat']

// At message level:
platform?: string // 'casecard' or 'inbox'

// In storage:
platform: ['casecard'] // Required array at conversation level

The Problem:

  • Platform is stored at both conversation and message level
  • Conversation has array: ['casecard', 'inbox']
  • Message has single: 'casecard'
  • Redundant - if conversation is on 'casecard', all messages are too
  • Confusing which one to use

Example:

// Conversation created on case card
conversation.platform = ['casecard'] // Array
message.platform = 'casecard' // Single string

// User continues conversation in inbox
conversation.platform = ['casecard', 'inbox'] // Array (both platforms)
// But which platform for each message? Confusing!

Recommendation:

Keep platform at conversation level only:

  • Conversation tracks all platforms where it occurred: ['casecard', 'inbox']
  • Messages don't need platform (they're part of the conversation)
  • Simpler, less redundant
  • If needed, you can infer message platform from conversation platform

Issue 6: Message ID Inconsistency - Explained

Current Situation:

// In TotoMessage interface:
id: string // Required

// In ConversationData.messages:
id?: string // Optional

// In saveConversation:
id: msg.id || `msg_${Date.now()}_${index}_${Math.random()...}` // Auto-generated if missing

The Problem:

  • Message ID is required in app interface
  • But optional when saving (auto-generated if missing)
  • Inconsistent - should messages always have IDs?

Example:

// Saving new message without ID:
{
type: 'user',
message: 'Hello',
timestamp: '2025-01-15T10:30:00Z'
// No ID - will be auto-generated
}

// But TotoMessage requires ID:
interface TotoMessage {
id: string; // Required!
// ...
}

Recommendation:

Make message ID required:

  • Always generate ID when creating message
  • Required in all interfaces
  • Consistent across the system

Summary of Recommendations

  1. Use isArchived instead of isActive (more explicit)
  2. Add updatedAt field (track metadata changes)
  3. Standardize timestamps to string (ISO 8601) in model
  4. Add actionTaken as optional field (track user actions)
  5. Remove platform from messages (keep only at conversation level)
  6. Make message ID required (always generate IDs)

These changes will make the conversation model:

  • More consistent
  • Easier to understand
  • Better aligned with storage
  • Less confusing conversions