SyncManager
Cloud sync via pull/push and SSE change feed
packages/desktop/src/main/sync-manager.ts orchestrates two-way synchronisation between local disk and the Cosmo cloud backend for onboarding data and memory files.
Sync Targets
| Local File | Cloud Endpoint | Direction |
|---|---|---|
users/{userId}.json | PUT/GET /api/v1/sync/profile | Both |
onboarding/{orgId}.json | PUT/GET /api/v1/sync/org-onboarding | Both |
memory/user-{userId}.md | PUT/GET /api/v1/sync/memory/user | Both |
memory/org-{orgId}.md | PUT/GET /api/v1/sync/memory/org | Both |
Startup Pull
pull() is called once when the app starts (after auth is confirmed). It fetches all four targets from the cloud and writes them to disk, overwriting any stale local data. This ensures the desktop always starts with the latest cloud state.
Sync metadata is tracked in userData/cosmo-data/.cosmo-sync-meta.json (last-synced timestamps per target).
Push Methods
Push methods are called by OnboardingManager whenever local data changes. They are fire-and-forget (exceptions are caught and logged).
| Method | Endpoint |
|---|---|
pushUserProfile(data) | PUT /api/v1/sync/profile |
pushOrgOnboarding(data) | PUT /api/v1/sync/org-onboarding |
pushUserMemory(content) | PUT /api/v1/sync/memory/user |
pushOrgMemory(content) | PUT /api/v1/sync/memory/org |
SSE Change Feed
startListening() connects to GET /api/v1/sync/changes — a Server-Sent Events stream. The server sends a heartbeat event every 30 seconds to keep the connection alive.
When a file-changed event arrives, handleRemoteChange(event) determines which local target changed and re-pulls only that file from the cloud.
When a remote change event arrives, main/index.ts forwards it to the renderer via webContents.send('sync:remote-change', event) so the UI can refresh affected data.
SyncClient
packages/desktop/src/main/sync-client.ts is a thin HTTP wrapper used by SyncManager and the IPC handlers. It wraps fetch with Bearer token auth and X-Org-Id header injection.
Endpoints Covered
SyncClient only wraps the sync/memory and onboarding endpoints. Other API calls (tasks, workspaces, billing, etc.) are made directly in main/index.ts IPC handlers.
| Method | Path | Purpose |
|---|---|---|
| PUT | /sync/profile | Store user profile |
| GET | /sync/profile | Retrieve user profile |
| PUT | /sync/org-onboarding | Store org onboarding |
| GET | /sync/org-onboarding | Retrieve org onboarding |
| PUT | /sync/memory/user | Store user memory |
| GET | /sync/memory/user | Retrieve user memory |
| PUT | /sync/memory/org | Store org memory |
| GET | /sync/memory/org | Retrieve org memory |
| GET | /sync/changes | SSE change feed |
| POST | /tasks/seed | Seed onboarding tasks |
| GET | /tasks | List tasks |
| POST | /tasks | Create task |
| PATCH | /tasks/:id | Update task |
| POST | /tasks/reprioritize | AI reprioritization |
| POST | /auth/seed-onboarding | Seed sample org data |
| GET | /workspaces | List workspaces |