mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-10-29 18:44:34 +00:00
* feat(cursor): show the cursor.com sync in the apps, with an off switch status --format menubar-json gains an additive cursorSync block (enabled, state, lastSuccessAt, and a fixed errorCode/error on failure), read from the sync sidecar, the config and the Cursor app's login. It never syncs, never makes a request and never carries the token, the account hash or server text. It is absent when Cursor is not signed in and has never synced, and it is attached after the snapshot and per-device payloads. With the Cursor provider selected, the desktop overview, the macOS menu bar and the Windows tray show one line under the total: "Synced from cursor.com 12 min ago", or the error in a muted warning colour. A "Sync Cursor usage from cursor.com" switch writes config cursorSync: Settings > Providers > Cursor on the desktop, the Cursor settings pane on macOS and Windows. Desktop and mac strings are in all six locales; the tray stays English until its localization lands. * fix(cursor): guard config writes, show the env override in the switches The tray's shared config writer now refuses to write over a config.json that does not parse or is not an object (it used to replace it with an empty map plus the one key), which also protects the currency, budget and Claude config directory writers. The desktop writer rejects null and array configs the same way. With CODEBURN_CURSOR_SYNC=0 set, the desktop, mac and tray switches show "Turned off by CODEBURN_CURSOR_SYNC=0" and are disabled. A failed mac save now says so under the switch. The tray hero note uses the warning ink and maps errorCode to its own messages.
24 lines
1.9 KiB
TypeScript
24 lines
1.9 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import { cursorSyncLine } from './CursorSyncLine'
|
|
|
|
const NOW = Date.parse('2026-10-05T12:00:00Z')
|
|
const ago = (minutes: number) => new Date(NOW - minutes * 60_000).toISOString()
|
|
|
|
describe('cursorSyncLine', () => {
|
|
it('words each state, hiding the line when sync is off', () => {
|
|
expect(cursorSyncLine({ enabled: true, state: 'ok', lastSuccessAt: ago(0.5) }, NOW)).toEqual({ text: 'Synced from cursor.com just now', warn: false })
|
|
expect(cursorSyncLine({ enabled: true, state: 'ok', lastSuccessAt: ago(12) }, NOW)).toEqual({ text: 'Synced from cursor.com 12 minutes ago', warn: false })
|
|
expect(cursorSyncLine({ enabled: true, state: 'ok', lastSuccessAt: ago(180) }, NOW)?.text).toBe('Synced from cursor.com 3 hours ago')
|
|
expect(cursorSyncLine({ enabled: true, state: 'syncing-never', lastSuccessAt: null }, NOW)).toEqual({ text: 'Not synced from cursor.com yet', warn: false })
|
|
expect(cursorSyncLine({ enabled: false, state: 'off', lastSuccessAt: ago(5) }, NOW)).toBeNull()
|
|
})
|
|
|
|
it('maps error codes to fixed copy, never the CLI text', () => {
|
|
const error = 'raw text from somewhere'
|
|
expect(cursorSyncLine({ enabled: true, state: 'no-login', lastSuccessAt: null, errorCode: 'login', error }, NOW)).toEqual({ text: 'Cursor login expired, open Cursor to sign in again', warn: true })
|
|
expect(cursorSyncLine({ enabled: true, state: 'error', lastSuccessAt: ago(90), errorCode: 'network', error }, NOW)).toEqual({ text: "Couldn't reach cursor.com, will retry", warn: true })
|
|
expect(cursorSyncLine({ enabled: true, state: 'error', lastSuccessAt: null, errorCode: 'export', error }, NOW)?.text).toBe("Couldn't read the usage export from cursor.com, will retry")
|
|
expect(cursorSyncLine({ enabled: true, state: 'error', lastSuccessAt: null, errorCode: 'future' as 'export', error }, NOW)?.text).toBe("Couldn't read the usage export from cursor.com, will retry")
|
|
})
|
|
})
|