Skip to content

Commit 150bb3e

Browse files
committed
feat(sync): Phase 2 — surface adopted/error counts in sync-updated event
Autonomous decisions: - Always emit numeric adopted_count/error_count (0 when none) — simpler than conditional JSON omission and frontend already guards with > 0 - Use warning toast when error_count > 0, info when only adoptions — visually distinct from the all-failed syncFailed warning while still surfacing partial errors Signed-off-by: crimsonsunset <jsangio1@gmail.com>
1 parent 93f06ca commit 150bb3e

4 files changed

Lines changed: 32 additions & 2 deletions

File tree

apps/desktop/src-tauri/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,8 @@ pub fn run() {
662662
"added": result.added,
663663
"updated": result.updated,
664664
"removed": result.removed,
665+
"adopted_count": result.adopted.len(),
666+
"error_count": result.errors.len(),
665667
}),
666668
) {
667669
warn!("[FileWatcher] Failed to emit event: {}", e);

apps/desktop/src/features/servers/ServersPage.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,8 +519,28 @@ export function ServersPage() {
519519
return;
520520
}
521521
void loadData();
522+
523+
const adoptedCount = payload.adopted_count ?? 0;
524+
const errorCount = payload.error_count ?? 0;
525+
if (adoptedCount > 0 || errorCount > 0) {
526+
const detailParts: string[] = [];
527+
if (adoptedCount > 0) {
528+
detailParts.push(
529+
t('configEditorModal.toast.syncPartialAdopted', { count: adoptedCount }),
530+
);
531+
}
532+
if (errorCount > 0) {
533+
detailParts.push(
534+
t('configEditorModal.toast.syncPartialErrors', { count: errorCount }),
535+
);
536+
}
537+
showToast(
538+
`${t('configEditorModal.toast.syncPartialTitle')}: ${t('configEditorModal.toast.syncPartialBody', { detail: detailParts.join('; ') })}`,
539+
errorCount > 0 ? 'warning' : 'info',
540+
);
541+
}
522542
});
523-
}, [loadData, subscribe, viewSpace]);
543+
}, [loadData, showToast, subscribe, t, viewSpace]);
524544

525545
useEffect(() => {
526546
return subscribe('space-servers-sync-failed', (payload) => {

apps/desktop/src/lib/backend/events/useDomainEvents.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ export interface MCPNotificationPayload extends DomainEventPayload {
178178
/** Space config file sync succeeded (desktop file watcher). */
179179
export interface SpaceServersUpdatedPayload extends DomainEventPayload {
180180
space_id: string;
181+
adopted_count?: number;
182+
error_count?: number;
181183
}
182184

183185
/** Space config file sync failed (desktop file watcher). */

apps/desktop/src/locales/en/servers.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,13 @@
251251
"invalidJsonTitle": "Invalid JSON",
252252
"saveFailed": "Failed to save configuration",
253253
"syncFailedTitle": "Config saved, sync failed",
254-
"syncFailedBody": "{{message}} — JSON is on disk; fix the entry and save again."
254+
"syncFailedBody": "{{message}} — JSON is on disk; fix the entry and save again.",
255+
"syncPartialTitle": "Config synced",
256+
"syncPartialBody": "{{detail}}",
257+
"syncPartialAdopted_one": "{{count}} server took over an existing entry",
258+
"syncPartialAdopted_other": "{{count}} servers took over existing entries",
259+
"syncPartialErrors_one": "{{count}} server failed to sync",
260+
"syncPartialErrors_other": "{{count}} servers failed to sync"
255261
},
256262
"validation": {
257263
"invalidJsonPrefix": "Invalid JSON:",

0 commit comments

Comments
 (0)