diff --git a/features/conversation-assistant/frontend-macos-client/app.js b/features/conversation-assistant/frontend-macos-client/app.js
index e7599611c..157fcde5d 100644
--- a/features/conversation-assistant/frontend-macos-client/app.js
+++ b/features/conversation-assistant/frontend-macos-client/app.js
@@ -16,6 +16,7 @@ let state = {
syncErrorMessage: null,
messageCount: 0,
conversationCount: 0,
+ contactCount: 0,
lastSync: null,
needsFullDiskAccess: false,
isSyncing: false,
@@ -62,6 +63,7 @@ function cacheElements() {
elements.activitySection = document.getElementById('activity-section');
elements.statMessages = document.getElementById('stat-messages');
elements.statConversations = document.getElementById('stat-conversations');
+ elements.statContacts = document.getElementById('stat-contacts');
elements.statLastSync = document.getElementById('stat-last-sync');
elements.activityLog = document.getElementById('activity-log');
@@ -252,6 +254,7 @@ function updateFromStatus(status) {
state.syncErrorMessage = status.syncErrorMessage;
state.messageCount = status.messageCount || 0;
state.conversationCount = status.conversationCount || 0;
+ state.contactCount = status.contactCount || 0;
state.lastSync = status.lastSync;
state.needsFullDiskAccess = status.needsFullDiskAccess || false;
state.isSyncing = status.isSyncing || false;
@@ -431,6 +434,7 @@ function renderConnectedView() {
// Stats
elements.statMessages.textContent = formatNumber(state.messageCount);
elements.statConversations.textContent = formatNumber(state.conversationCount);
+ elements.statContacts.textContent = formatNumber(state.contactCount);
elements.statLastSync.textContent = formatRelativeTime(state.lastSync);
// Activity log
diff --git a/features/conversation-assistant/frontend-macos-client/index.html b/features/conversation-assistant/frontend-macos-client/index.html
index 9912f654a..588ae4663 100644
--- a/features/conversation-assistant/frontend-macos-client/index.html
+++ b/features/conversation-assistant/frontend-macos-client/index.html
@@ -81,6 +81,10 @@
Conversations
0
+
+ Contacts
+ 0
+
Last Sync
Never
diff --git a/features/conversation-assistant/macos/Sources/Services/APIClient.swift b/features/conversation-assistant/macos/Sources/Services/APIClient.swift
index 165c1587c..86d61f710 100644
--- a/features/conversation-assistant/macos/Sources/Services/APIClient.swift
+++ b/features/conversation-assistant/macos/Sources/Services/APIClient.swift
@@ -200,6 +200,7 @@ class APIClient {
return SyncStatsResponse(
totalMessages: json["data"]["totalMessages"].intValue,
totalConversations: json["data"]["totalConversations"].intValue,
+ totalContacts: json["data"]["totalContacts"].intValue,
lastSyncAt: lastSyncAt
)
}
@@ -391,6 +392,7 @@ struct SyncMessagePayload: Encodable {
struct SyncStatsResponse {
let totalMessages: Int
let totalConversations: Int
+ let totalContacts: Int
let lastSyncAt: Date?
}
diff --git a/features/conversation-assistant/macos/Sources/Services/LocalWebServer.swift b/features/conversation-assistant/macos/Sources/Services/LocalWebServer.swift
index 4c566ccb6..94ec1b646 100644
--- a/features/conversation-assistant/macos/Sources/Services/LocalWebServer.swift
+++ b/features/conversation-assistant/macos/Sources/Services/LocalWebServer.swift
@@ -193,6 +193,7 @@ class LocalWebServer {
"syncErrorMessage": syncErrorMessage as Any,
"messageCount": syncManager.stats.messageCount,
"conversationCount": syncManager.stats.conversationCount,
+ "contactCount": syncManager.stats.contactCount,
"lastSync": syncManager.lastSync.map { ISO8601DateFormatter().string(from: $0) } as Any,
"needsFullDiskAccess": syncManager.syncError == .fullDiskAccessRequired,
"isSyncing": syncManager.isSyncing,
diff --git a/features/conversation-assistant/macos/Sources/Services/SyncManager.swift b/features/conversation-assistant/macos/Sources/Services/SyncManager.swift
index a14a4bf20..bf22b6e52 100644
--- a/features/conversation-assistant/macos/Sources/Services/SyncManager.swift
+++ b/features/conversation-assistant/macos/Sources/Services/SyncManager.swift
@@ -5,6 +5,7 @@ import Foundation
struct SyncStats {
var messageCount: Int = 0
var conversationCount: Int = 0
+ var contactCount: Int = 0
}
enum SyncError: Equatable {
@@ -313,12 +314,13 @@ class SyncManager: ObservableObject {
NSLog("SyncManager: fetchStats starting")
do {
let response = try await apiClient.getStats()
- NSLog("SyncManager: fetchStats - got totalMessages: \(response.totalMessages), totalConversations: \(response.totalConversations)")
+ NSLog("SyncManager: fetchStats - got totalMessages: \(response.totalMessages), totalConversations: \(response.totalConversations), totalContacts: \(response.totalContacts)")
// Update stats from server response
let newStats = SyncStats(
messageCount: response.totalMessages,
- conversationCount: response.totalConversations
+ conversationCount: response.totalConversations,
+ contactCount: response.totalContacts
)
stats = newStats
diff --git a/features/conversation-assistant/server/src/modules/sync/sync.service.ts b/features/conversation-assistant/server/src/modules/sync/sync.service.ts
index 69a6b9d38..960901e7e 100644
--- a/features/conversation-assistant/server/src/modules/sync/sync.service.ts
+++ b/features/conversation-assistant/server/src/modules/sync/sync.service.ts
@@ -255,6 +255,7 @@ export class SyncService {
async getStats(deviceId: string): Promise<{
totalMessages: number;
totalConversations: number;
+ totalContacts: number;
lastSyncAt: string | null;
}> {
// Count conversations for this device
@@ -277,12 +278,16 @@ export class SyncService {
.getCount();
}
+ // Count all contacts (global, not per-device)
+ const totalContacts = await this.contactRepository.count();
+
// Get last sync time
const lastSync = await this.getLastSync(deviceId);
return {
totalMessages,
totalConversations,
+ totalContacts,
lastSyncAt: lastSync?.toISOString() ?? null,
};
}