fix: reset ClawKeep when the ClawBox AI account changes - #177
Conversation
ClawKeep pairs independently of the ClawBox AI account — its own claw_ token resolves on the portal to an account and a cloud-storage prefix. So after switching ClawBox AI accounts the device kept backing up to the OLD account's storage, and the dashboard kept showing the old account's stats. - ai-models/configure: detect an account switch (the clawai token changing from a previously-stored one) and unpair ClawKeep so it re-pairs against the current account. The token is opaque (no account id), so a changed token is the only available signal. Also clears the old account's stats as an offline-safe wipe. - clawkeep: add unpairLocal() — shared by the unpair route and the account-change reset so the two stay in lockstep — and syncStateFromCloud(), which seeds state.json from the account's real cloud snapshots on pair, so a re-authenticated account shows its existing backups immediately instead of "0 B / never" until the next local backup. - clawkeep/pair/poll: sync cloud state right after writing the new token. - setup/reset: a factory reset now also wipes ~/.clawkeep, so it can't leave the device paired to the previous account either. - ClawKeepApp: poll status on a single variable-cadence timer so an already-open window reflects the server-side unpair without a manual click.
|
Warning Review limit reached
More reviews will be available in 39 minutes and 50 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThis PR adds ClawKeep account-switch safety and cloud state synchronization. When a ClawBox AI token changes during reconfiguration, the app detects the change and unpairs ClawKeep with full stat reset to prevent backups from remaining associated with the old account. The changes also consolidate unpair/reset logic into library APIs, sync cloud snapshots after re-pairing, integrate ClawKeep cleanup into factory reset, and adapt dashboard polling to backup status. ChangesClawKeep Account Switch Safety and State Sync
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/setup-api/ai-models/configure/route.ts`:
- Around line 432-439: The code is currently swallowing errors from getAll(),
causing previousClawaiToken to default to empty and skipping the account-switch
unpair guard; change this so a failing getAll() does not "fail open": remove the
blanket .catch(() => ({})) or replace it with explicit error handling that
aborts the request (or returns an error response) when getAll() rejects, and
ensure previousClawaiToken is read only after a successful getAll() call; adjust
the logic in the isClawAI/account-switch detection (references: getAll,
previousClawaiToken, CLAWBOX_AI_TOKEN_CONFIG_KEY, and the isClawAI block) so an
error from getAll() prevents proceeding rather than defaulting to an empty
token.
In `@src/components/ClawKeepApp.tsx`:
- Around line 217-223: The polling useEffect in ClawKeepApp (the effect using
status, refresh, intervalMs and id) can start new refresh() calls before prior
ones finish; replace the setInterval approach with a single-flight loop: use an
async polling function that checks an in-flight boolean (e.g., isFetching) to
avoid concurrent calls, use setTimeout for adaptive scheduling (3s vs 10s via
isBackupRunning(status)) rather than setInterval, and add a per-request
timeout/abort (wrap refresh() with an AbortController or a timeout promise) plus
try/catch to ensure errors clear isFetching and schedule the next run; update
cleanup to cancel pending timeout/abort when unmounted or status/refresh change.
In `@src/lib/clawkeep.ts`:
- Around line 378-383: writeStateFile currently writes to a fixed temp file
`${STATE_PATH}.tmp`, causing rename races between concurrent callers; change
writeStateFile to write to a per-call unique temp file (e.g. include process id
+ timestamp or a random suffix) before renaming to STATE_PATH, keep the same
file mode (0o600), perform the atomic fs.rename from that unique temp to
STATE_PATH, and ensure any temporary file is cleaned up on error; refer to
writeStateFile and STATE_PATH to locate and update the logic.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7107c631-76ea-4a6b-9aaf-6919e9a3cd8c
📒 Files selected for processing (7)
src/app/setup-api/ai-models/configure/route.tssrc/app/setup-api/clawkeep/pair/poll/route.tssrc/app/setup-api/clawkeep/unpair/route.tssrc/app/setup-api/setup/reset/route.tssrc/components/ClawKeepApp.tsxsrc/lib/clawkeep.tssrc/tests/routes/ai-models/configure.test.ts
- configure: don't fail open when reading the prior clawai_token — abort the ClawBox AI save with 503 if getAll() throws, instead of defaulting to "" and silently skipping the account-switch unpair guard. - ClawKeepApp: skip a poll tick while the previous refresh is still in flight so a slow fetch can't stack concurrent requests on the Jetson. - clawkeep: give writeStateFile a per-call temp name (pid + counter) so concurrent writers can't clobber each other's temp before the atomic rename.
Problem
ClawKeep pairs independently of the ClawBox AI account — it has its own
claw_token that the portal resolves to an account and a cloud-storage prefix. So after switching ClawBox AI accounts:Fix
ai-models/configure— detect an account switch (theclawai_tokenchanging from a previously-stored one) and unpair ClawKeep so it re-pairs against the current account. The token is opaque (no embedded account id), so a changed token is the only available signal. Also clears the old account's stats (clearStats) as an offline-safe wipe.clawkeep— addunpairLocal()(shared by the unpair route + the account-change reset so they stay in lockstep) andsyncStateFromCloud(), which seedsstate.jsonfrom the account's real cloud snapshots on pair — so a re-authenticated account shows its existing backups immediately instead of0 B / neveruntil the next local backup.clawkeep/pair/poll— sync cloud state right after writing the new token.setup/reset— a factory reset now also wipes~/.clawkeep, so it can't leave the device paired to the previous account either.ClawKeepApp— poll status on a single variable-cadence timer (3s during a backup, 10s otherwise) so an already-open window reflects the server-side unpair without a manual click.Three-mechanism design (intentional)
clearStatswipe on switch — the offline safety net: ifsyncStateFromCloudcan't reach the portal on re-pair, the device still shows a clean slate, never the old account's numbers.syncStateFromCloudon pair — the steady-state correct value (the new account's real cloud backups).ClawKeepApppoll — transport: makes an already-open window observe the change.Testing
configure.test.ts: unpairs on token change (with{ clearStats: true }), does not unpair on unchanged token or first-time setup.journalctl+ the token file being cleared), backups then went to the new account's storage, andclawkeep snapshots→syncStateFromCloudcorrectly populated the dashboard with the account's existing backups.clawkeep-persistence,clawkeep-schedule, andconfiguretest suites pass.Summary by CodeRabbit
New Features
Improvements