Skip to content

fix(setup): harden completion + reconnect, refresh header - #146

Merged
KrasimirKralev merged 3 commits into
betafrom
fix/credentials-step-mdns-probe
May 26, 2026
Merged

KrasimirKralev merged 3 commits into
betafrom
fix/credentials-step-mdns-probe

Conversation

@KrasimirKralev

@KrasimirKralev KrasimirKralev commented May 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Post-v3.0.5 hardening for the setup wizard. Three concerns bundled because they all surface around the late-wizard steps (3/5) and share user-impact (the customer sees an unrecoverable red error in cases where setup actually succeeded or would have succeeded with a brief retry).

1. Credentials step (step 3) — reconnect probe

After the hotspot/hostname change, the browser's connection to the device drops while avahi re-broadcasts and the WiFi AP cycles. The previous one-shot 5 s HEAD probe was too aggressive — users saw a red "Could not reach" error even when the device came back ~8 s later.

  • Progressive backoff: 3 + 5 + 7 + 10 + 12 + 15 s (~52 s total)
  • Soft green "Settings saved. Reconnecting to …" while probing
  • Red error only after the full schedule exhausts
  • Backoff timer is now cancellable on abort (no setState-after-unmount warning)

2. Setup completion (step 5) — retry + friendly error

POST /setup-api/setup/complete can fail transiently when the gateway restart from the AI step is still settling, or the browser's connection is briefly degraded after the step 3 hotspot reconfig. Until now this produced a dead-end "Failed to fetch" banner with no recovery path.

  • 3-attempt retry with [0, 2 s, 4 s] backoff
  • 15 s per-attempt AbortSignal.timeout so a hung request doesn't block the full backoff window
  • Friendly i18n string (wizard.completionUnreachable) added for all 10 locales — replaces raw browser error text
  • "Опитай отново" / Retry button rendered next to the error banner
  • t hoisted into a ref so a mid-completion locale switch can't re-fire the effect and double-POST

3. Header refresh

  • Icon swapped to the official openclawhardware.dev brand crab (192×192, square, sharp)
  • Version badge restyled inline next to "ClawBox" title with a muted slash separator and tabular monospace number — replaces the small green text below the title

Files

  • `src/components/CredentialsStep.tsx` — retry loop + cancellable timer
  • `src/components/SetupWizard.tsx` — postCompleteWithRetry, friendly error mapping, retry button, version badge restyle, `t` ref
  • `src/lib/translations.ts` — wizard.completionUnreachable for en/bg/de/es/fr/it/ja/nl/sv/zh
  • `public/clawbox-icon.png` — replaced with brand crab from openclawhardware.dev

Test plan

  • Tested end-to-end on a real Jetson (192.168.1.45): walked through wizard steps 1–5, confirmed:
    • Step 3 with hostname change → soft "reconnecting" toast, auto-redirect when device comes back
    • Step 5 Skip → completion completes cleanly
    • Header shows new icon + new version badge
  • Built standalone successfully (bun run build)
  • CI / typecheck

Summary by CodeRabbit

  • Bug Fixes

    • Improved recovery from connection interruptions during device credentials setup with automatic retries and clearer reconnect/retry messaging.
    • Enhanced setup completion with robust retry behavior and clearer fallback error text when the device is unreachable.
  • Improvements

    • More compact setup wizard header layout.
  • Tests

    • UI test updated to dismiss an intermittent modal that could block sending chat messages.

Review Change Stack

- credentials: probe new URL with progressive backoff (~52s) instead of
  one-shot 5s, show soft "reconnecting" toast rather than red error
  when the hotspot reconfig / hostname change drops the tab. Backoff
  timer is cancellable on abort to avoid setState-after-unmount.
- completion: retry POST /setup-api/setup/complete up to 3x with backoff
  to absorb gateway-restart timing from the AI step. Add 15s per-attempt
  timeout. Friendly i18n error with a "retry" button instead of raw
  "Failed to fetch" (10 locales).
- header: swap icon to the openclawhardware.dev brand crab; restyle
  version badge inline next to title with muted slash separator.
- internal: hoist t into a ref so locale switches during an in-flight
  completion don't trigger a duplicate POST.
@KrasimirKralev
KrasimirKralev requested a review from a team as a code owner May 26, 2026 19:20
@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@KrasimirKralev, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 45 minutes and 38 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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9285eec1-a61a-4885-96a2-e45391935646

📥 Commits

Reviewing files that changed from the base of the PR and between 99a14a9 and ef876e2.

⛔ Files ignored due to path filters (1)
  • public/clawbox-icon.png is excluded by !**/*.png
📒 Files selected for processing (4)
  • e2e-install/80-chat.spec.ts
  • src/components/CredentialsStep.tsx
  • src/components/SetupWizard.tsx
  • src/lib/translations.ts
📝 Walkthrough

Walkthrough

This PR adds backoff retry probing for mDNS after credential saves, implements a retrying, timeout-bound POST for setup completion, maps transient failures to localized unreachable messages, compacts the header layout, adds a step-5 retry button, updates translations across locales, and tolerantly dismisses a modal in an E2E test.

Changes

Setup Wizard Network Resilience

Layer / File(s) Summary
Credentials mDNS probing retry
src/components/CredentialsStep.tsx
Adds MDNS_PROBE_BACKOFF_MS and MDNS_PROBE_TIMEOUT_MS; replaces a single HEAD probe with a backoff retry loop that shows a reconnecting status, polls the new .local URL with per-attempt timeouts, redirects on first success, or shows an unreachable-after-retries error.
Setup completion POST retry and UI wiring
src/components/SetupWizard.tsx
Adds tRef to hold the latest translation function; introduces postCompleteWithRetry which POSTs /setup-api/setup/complete with a 15s AbortSignal.timeout and backoff retries; maps transient/network failures to wizard.completionUnreachable via tRef; compacts header version layout and adds a step-5 retry button that calls startCompletion.
Localized unreachable/reconnecting messages
src/lib/translations.ts
Adds credentials.reconnecting, credentials.reconnectFailed, and wizard.completionUnreachable keys across the project's ten locale sets for the reconnect and completion retry flows.
E2E: dismiss tier-celebration modal if present
e2e-install/80-chat.spec.ts
Playwright test attempts a short-timeout click on the "Let's go" button and ignores failures so a modal does not block the Send interaction.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

run-full-e2e

Suggested reviewers

  • GeorgiK77
  • yalexx

Poem

A rabbit hops through network delays,
With backoff loops and retry ways,
Soft reconnection, gentle grace,
Till the device is found in place. 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'fix(setup): harden completion + reconnect, refresh header' directly captures the three main changes: setup completion hardening, reconnect probe improvements, and header refresh.
Description check ✅ Passed The PR description comprehensively covers all three objectives with detailed explanations of changes, affected files, and test validation, aligning well with the required template sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/credentials-step-mdns-probe

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 26, 2026

Copy link
Copy Markdown

CI Summary

✅ Tests

  • Result: passed
  • View run
  • Coverage: statements 70.91%, branches 60.29%, functions 66.78%, lines 73.09%

✅ E2E

✅ E2E Install

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/components/CredentialsStep.tsx`:
- Around line 203-206: Replace the hardcoded English reconnect messages used in
the setStatus calls with calls to the existing i18n function t(...), e.g.,
change the strings that reference newSetupUrl.toString() to use t with an
interpolation placeholder; update both places where setStatus is called with
messages containing the URL (the calls that build a "Settings saved.
Reconnecting to …" style message) and add corresponding translation keys to your
locale files so non-English locales render correctly while still passing
newSetupUrl as a variable to t.
- Around line 219-223: The MDNS probe uses AbortSignal.timeout so it can't be
cancelled by the existing save/unmount AbortController; change the probe to use
the active controller (controller.signal) and implement a timeout that aborts
that controller (e.g., setTimeout(() => controller.abort(),
MDNS_PROBE_TIMEOUT_MS)) before calling fetch, pass controller.signal to fetch,
clear the timeout after the request, and after awaiting the fetch check
controller.signal.aborted and skip the window.location.replace(...) if aborted;
reference the existing controller variable, MDNS_PROBE_TIMEOUT_MS, the fetch
call doing method "HEAD", and the subsequent window.location.replace call to
locate where to apply these changes.

In `@src/components/SetupWizard.tsx`:
- Around line 394-414: postCompleteWithRetry currently returns the first fetch
Response even when it's an HTTP error (res.ok === false); change
postCompleteWithRetry to inspect the fetched Response from
fetch("/setup-api/setup/complete") and only return it when res.ok is true,
otherwise treat it like an error (store it or throw) so the retry loop
(backoffs) will continue; on final failure after all backoffs, throw a
meaningful Error that includes the last response status/text or the caught error
to aid debugging.
🪄 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: 18d9c546-9517-4784-9a9e-39e940a86b8e

📥 Commits

Reviewing files that changed from the base of the PR and between 99a14a9 and d909e5e.

⛔ Files ignored due to path filters (1)
  • public/clawbox-icon.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • src/components/CredentialsStep.tsx
  • src/components/SetupWizard.tsx
  • src/lib/translations.ts

Comment thread src/components/CredentialsStep.tsx
Comment thread src/components/CredentialsStep.tsx
Comment thread src/components/SetupWizard.tsx
- credentials: i18n the reconnect "saved/reconnecting" and "still
  unreachable" status messages (added credentials.reconnecting +
  credentials.reconnectFailed across 10 locales with {url} placeholder)
- credentials: probe fetch now uses AbortSignal.any([controller.signal,
  AbortSignal.timeout(...)]) so it cancels on save/unmount abort, not
  just on per-attempt timeout. Added post-fetch + post-catch
  controller.signal.aborted checks to skip the redirect after a late
  abort.
- completion: postCompleteWithRetry now treats non-OK HTTP responses as
  retryable (a transient 5xx during gateway-restart settle no longer
  short-circuits the backoff). On final failure includes the last
  response status/body in the thrown Error for debug.
CI e2e-install/80-chat.spec.ts started failing on the Send-button
click because the upstream ClawAI proxy now reports a paid tier on
fresh dashboard loads, which pops the TierUpgradeCelebration dialog
(z-[100001]) on top of the chat panel and intercepts pointer events.

Defensive dismiss: between fill() and the Send click, look for the
modal's "Let's go" button with a 3s timeout. If no modal appears, the
catch absorbs the timeout silently.

This is purely a test robustness fix — the celebration is correct
product behaviour for a Free→Paid transition.
@KrasimirKralev

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
✅ Actions performed

Full review triggered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant