Skip to content

feat: streamline desktop local dev workflow#640

Merged
PerishCode merged 16 commits intofeat/windows-distribution-smokefrom
feat/local-dev-workflow-optimization
Mar 28, 2026
Merged

feat: streamline desktop local dev workflow#640
PerishCode merged 16 commits intofeat/windows-distribution-smokefrom
feat/local-dev-workflow-optimization

Conversation

@PerishCode
Copy link
Copy Markdown
Contributor

$(cat <<'EOF'

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2b9100d5ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const lines = output.split(/\r?\n/);

for (const line of lines) {
if (!line.includes(`:${port}`) || !line.includes("LISTENING")) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Use cross-platform port-state matching in dev port probe

getListeningPortPid is now hard-wired to parse lines containing LISTENING, but the same waitForListeningPortPid path is used by pnpm dev start openclaw|controller|web in scripts/dev on non-Windows hosts too. On macOS/Linux the socket-state token is typically LISTEN (and some environments do not provide netstat -ano), so the probe never resolves even when the service is up, causing false startup failures like "did not open port"; the previous codebase already handled non-Windows probing separately (e.g. with lsof).

Useful? React with 👍 / 👎.

return;
}

event.preventDefault();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Quit app when launchd bootstrap is unavailable

In the launchd shutdown coordinator, the before-quit handler calls event.preventDefault() when launchdResult is null but never performs any fallback shutdown/quit path. In main/index.ts, cold-start failures are caught and shutdownCoordinator.install(...) is still called with launchdResult unset, so on mac launchd mode a failed bootstrap can leave the app unable to quit (Cmd+Q is intercepted indefinitely).

Useful? React with 👍 / 👎.

@PerishCode PerishCode merged commit c8bd5e2 into feat/windows-distribution-smoke Mar 28, 2026
5 of 9 checks passed
PerishCode added a commit that referenced this pull request Apr 3, 2026
* fix(desktop): make local startup work on Windows

* fix(desktop): sanitize persisted startup logs

* test(desktop): add Feishu websocket smoke harness

* fix(smoke): improve Feishu websocket diagnostics

* build(desktop): add Windows smoke distribution flow

* build(desktop): align Windows sidecar archives with zip flow

* build(desktop): align Windows packaging with NSIS defaults

* build(desktop): refine Windows distribution commands

* build(desktop): improve Windows installer UX

Switch the NSIS flow to an assisted installer so Windows install and uninstall are visible and data cleanup can be opted into without silent surprises. Restore executable resource editing and use tombstone-based app-data cleanup so shortcuts show the Nexu icon and uninstall stays fast without flashing a console window.

* fix(desktop): stabilize Windows dist and runtime install (#538)

* build(desktop): skip exe editing for unsigned Windows dist

* fix(openclaw-runtime): stabilize Windows postinstall

Keep the full install path available for debugging while making pruned installs skip Windows-native optional dependencies that break postinstall flows.

* fix(desktop): align dev health check with runtime state

* fix(openclaw-runtime): refresh cache on installer changes

* build(desktop): add windows CI coverage

* fix(desktop): avoid sidecar copy symlink loops on windows

* fix(desktop): clean runtime plugin self-links on windows

* build(desktop): scope windows CI to build validation

* fix(desktop): restore mac dist executable discovery

---------

Co-authored-by: mRcfps <1402401442@qq.com>

* build(desktop): stabilize Windows startup and shell polish

* fix(web): refine Windows sidebar toggle layout

* fix(desktop): harden Windows packaged runtime startup

* feat: streamline desktop local dev workflow (#640)

* feat: add local dev supervisor workflow

* feat: refine local dev workflow and desktop runtime scaffolding

* docs: add dev workflow faq

* fix: remove nested controller tsx watcher

* refactor: share ensure guards across dev process helpers

* chore: remove stale task notes

* refactor: centralize local dev path resolution

* refactor: move dev orchestration into scripts/dev

Keep @nexu/dev-utils focused on atomic helpers so service-level controller and web flows stay easier to reason about and recover. Add lightweight session tracing so leaked dev processes can be correlated and cleaned up without heavy self-healing.

* refactor: clarify scripts dev module boundaries

* feat: externalize dev runtime ownership

* feat: split local dev into explicit service controls

* refactor: remove legacy desktop dev launchers

* fix: run desktop local dev through the Vite supervisor

* fix: harden local dev stack flow

* chore: sync workspace lockfiles

* fix: restore desktop dev auth session

* chore: unify scripts dev logging

* chore: stabilize launchd encapsulation and windows desktop smoke flow (#651)

* chore: introduce shared desktop lifecycle contract

* chore: move desktop platform lifecycle behind adapters

* chore: centralize desktop platform compatibility

* chore: stage patched OpenClaw runtime for local dev

* chore: log staged OpenClaw runtime usage

* chore: speed up windows desktop build iteration

* chore: disable win executable editing for local builds

* chore: ignore local build cache

* fix(desktop): support windows openclaw sidecar archives

* chore: unify desktop dev launch under scripts/dev (#654)

* chore(ci): add windows packaging to desktop dist full

* chore(ci): opt desktop dist full into node 24 actions

* Revert "chore(ci): opt desktop dist full into node 24 actions"

This reverts commit b19336e.

* fix(desktop): harden windows packaging and installer flow

* chore: remove task handoff note

* chore: align desktop tests with platform runtime changes

* chore: fix linux desktop test platform mocks

* chore: stabilize dev check service supervision

* chore: fix packaged launchd path test platform setup

* fix(desktop): preserve explicit dev runtime env overrides

* fix(dev): preserve openclaw supervisor pid lock

* chore(ci): track scripts dev changes in desktop dev checks

* chore(ci): support manual desktop workflow dispatch

* fix(dev): treat active openclaw port as running

* fix(dev): align desktop runtime ports with CI contract

* fix(dev): wait for openclaw gateway before controller start

* chore(ci): capture dev logs and read desktop pid lock

* fix(dev): wait for openclaw health before reporting ready

* fix(controller): debounce sync on all skill dir events

* fix(dev): derive openclaw status from runtime health

* fix(dev): disable bonjour in desktop CI smoke

* fix(desktop): harden Windows packaging and cleanup flows

* fix(dev): stabilize Windows desktop dev lifecycle

* fix(dev): allow overriding desktop dev ports

* fix(dev): require openclaw readiness for running status

* fix(dev): expose builtin openclaw extensions in local controller

* fix(desktop): stabilize windows packaging workflows

* fix: restore windows dev UI and openclaw startup compatibility

* fix(desktop): clear stale startup errors after runtime recovery

* fix(desktop): use packaged openclaw sidecars in windows builds

* chore: refresh lockfile for desktop dependency changes

* fix: make nexu runtime model plugin reload state by content

---------

Co-authored-by: Marc Chan <mrc@powerformer.com>
Co-authored-by: mRcfps <1402401442@qq.com>
anthhub pushed a commit that referenced this pull request Apr 3, 2026
* fix(desktop): make local startup work on Windows

* fix(desktop): sanitize persisted startup logs

* test(desktop): add Feishu websocket smoke harness

* fix(smoke): improve Feishu websocket diagnostics

* build(desktop): add Windows smoke distribution flow

* build(desktop): align Windows sidecar archives with zip flow

* build(desktop): align Windows packaging with NSIS defaults

* build(desktop): refine Windows distribution commands

* build(desktop): improve Windows installer UX

Switch the NSIS flow to an assisted installer so Windows install and uninstall are visible and data cleanup can be opted into without silent surprises. Restore executable resource editing and use tombstone-based app-data cleanup so shortcuts show the Nexu icon and uninstall stays fast without flashing a console window.

* fix(desktop): stabilize Windows dist and runtime install (#538)

* build(desktop): skip exe editing for unsigned Windows dist

* fix(openclaw-runtime): stabilize Windows postinstall

Keep the full install path available for debugging while making pruned installs skip Windows-native optional dependencies that break postinstall flows.

* fix(desktop): align dev health check with runtime state

* fix(openclaw-runtime): refresh cache on installer changes

* build(desktop): add windows CI coverage

* fix(desktop): avoid sidecar copy symlink loops on windows

* fix(desktop): clean runtime plugin self-links on windows

* build(desktop): scope windows CI to build validation

* fix(desktop): restore mac dist executable discovery

---------

Co-authored-by: mRcfps <1402401442@qq.com>

* build(desktop): stabilize Windows startup and shell polish

* fix(web): refine Windows sidebar toggle layout

* fix(desktop): harden Windows packaged runtime startup

* feat: streamline desktop local dev workflow (#640)

* feat: add local dev supervisor workflow

* feat: refine local dev workflow and desktop runtime scaffolding

* docs: add dev workflow faq

* fix: remove nested controller tsx watcher

* refactor: share ensure guards across dev process helpers

* chore: remove stale task notes

* refactor: centralize local dev path resolution

* refactor: move dev orchestration into scripts/dev

Keep @nexu/dev-utils focused on atomic helpers so service-level controller and web flows stay easier to reason about and recover. Add lightweight session tracing so leaked dev processes can be correlated and cleaned up without heavy self-healing.

* refactor: clarify scripts dev module boundaries

* feat: externalize dev runtime ownership

* feat: split local dev into explicit service controls

* refactor: remove legacy desktop dev launchers

* fix: run desktop local dev through the Vite supervisor

* fix: harden local dev stack flow

* chore: sync workspace lockfiles

* fix: restore desktop dev auth session

* chore: unify scripts dev logging

* chore: stabilize launchd encapsulation and windows desktop smoke flow (#651)

* chore: introduce shared desktop lifecycle contract

* chore: move desktop platform lifecycle behind adapters

* chore: centralize desktop platform compatibility

* chore: stage patched OpenClaw runtime for local dev

* chore: log staged OpenClaw runtime usage

* chore: speed up windows desktop build iteration

* chore: disable win executable editing for local builds

* chore: ignore local build cache

* fix(desktop): support windows openclaw sidecar archives

* chore: unify desktop dev launch under scripts/dev (#654)

* chore(ci): add windows packaging to desktop dist full

* chore(ci): opt desktop dist full into node 24 actions

* Revert "chore(ci): opt desktop dist full into node 24 actions"

This reverts commit b19336e.

* fix(desktop): harden windows packaging and installer flow

* chore: remove task handoff note

* chore: align desktop tests with platform runtime changes

* chore: fix linux desktop test platform mocks

* chore: stabilize dev check service supervision

* chore: fix packaged launchd path test platform setup

* fix(desktop): preserve explicit dev runtime env overrides

* fix(dev): preserve openclaw supervisor pid lock

* chore(ci): track scripts dev changes in desktop dev checks

* chore(ci): support manual desktop workflow dispatch

* fix(dev): treat active openclaw port as running

* fix(dev): align desktop runtime ports with CI contract

* fix(dev): wait for openclaw gateway before controller start

* chore(ci): capture dev logs and read desktop pid lock

* fix(dev): wait for openclaw health before reporting ready

* fix(controller): debounce sync on all skill dir events

* fix(dev): derive openclaw status from runtime health

* fix(dev): disable bonjour in desktop CI smoke

* fix(desktop): harden Windows packaging and cleanup flows

* fix(dev): stabilize Windows desktop dev lifecycle

* fix(dev): allow overriding desktop dev ports

* fix(dev): require openclaw readiness for running status

* fix(dev): expose builtin openclaw extensions in local controller

* fix(desktop): stabilize windows packaging workflows

* fix: restore windows dev UI and openclaw startup compatibility

* fix(desktop): clear stale startup errors after runtime recovery

* fix(desktop): use packaged openclaw sidecars in windows builds

* chore: refresh lockfile for desktop dependency changes

* fix: make nexu runtime model plugin reload state by content

---------

Co-authored-by: Marc Chan <mrc@powerformer.com>
Co-authored-by: mRcfps <1402401442@qq.com>
lefarcen added a commit that referenced this pull request Apr 8, 2026
…esktop (#789)

* feat: add desktop rewards center

* feat(quota): add fallback and restore managed model endpoints

- Introduced new API endpoints for triggering automatic fallback to BYOK provider and restoring the default model to a managed (cloud) model.
- Updated OpenAPI schema to include new properties related to BYOK usage and fallback status.
- Implemented QuotaFallbackService to handle fallback logic and model restoration.
- Added BudgetWarningBanner component to notify users about credit status in the UI.
- Enhanced existing services and routes to integrate new quota management features.

* refactor(workspace-layout): enhance rewards link layout and styling

- Updated the rewards link to use a flex layout for better alignment and spacing.
- Increased the size of the Coins icon for improved visibility.
- Adjusted the display of claimed and total credits to enhance readability.
- Refined the progress bar styling for a more polished appearance.

* feat(rewards): integrate cloud balance feature into rewards system

- Updated OpenAPI schema to include cloud balance properties.
- Implemented CloudRewardService for managing rewards status and claims.
- Enhanced NexuConfigStore to fetch and convert cloud rewards status.
- Added tests for CloudRewardService and updated existing tests for NexuConfigStore.
- Updated UI components to display cloud balance information.
- Localized new cloud balance strings in English and Chinese.

* feat(budget-warning-banner): enhance budget warning banner functionality and localization

- Introduced a status configuration for the BudgetWarningBanner to manage different states (warning and depleted) with corresponding styles and texts.
- Updated the component to utilize the new configuration for rendering, improving code readability and maintainability.
- Added new localization strings for budget warning and depleted states in English and Chinese.
- Implemented a debug panel for development purposes to simulate budget banner states.
- Added tests for the BudgetWarningBanner to ensure correct rendering based on status.

* feat(desktop-rewards): implement auto-fallback logic and enhance rewards status handling

- Added logic to automatically trigger a fallback to BYOK when the managed model's cloud balance is depleted.
- Integrated logging for fallback failures to improve error tracking.
- Created unit tests for the new fallback functionality to ensure reliability.
- Updated the BudgetWarningBanner and related UI components to reflect changes in rewards status and actions.
- Enhanced localization strings for clarity in user messaging regarding rewards and credits.

* feat(desktop-rewards): implement auto-fallback logic and enhance rewards status handling

- Added logic to automatically trigger a fallback to BYOK when the managed model's cloud balance is depleted.
- Integrated logging for fallback failures to improve error tracking.
- Created a new test suite for desktop rewards routes to validate fallback behavior and status retrieval.
- Updated existing UI components and localization strings to reflect changes in rewards status messaging.

* refactor(web): extract shared cloud connect hook and fix state bug

- Remove 5 investigation markdown files accidentally committed to repo root
- Fix cloudConnecting state not reset in "Connection already in progress" path
- Extract handleCloudConnect + polling effects into shared useCloudConnect hook
- Deduplicate formatRewardAmount by exporting from home-rewards-teaser

* feat(rewards): add reward share assets and download functionality

- Introduced six new PNG images for reward sharing.
- Created a new module for managing reward share assets, including types and functions for selecting and downloading assets.
- Implemented tests to ensure the integrity of the reward share assets and their download functionality.

* chore: fix import sort order in home.tsx

* feat(rewards): add loading skeleton, auto-fallback toast, and 60s polling

- Show skeleton placeholders instead of fallback tasks during loading
- Add autoFallbackTriggered flag to rewards status schema
- Display warning toast when BYOK auto-fallback is triggered
- Add refetchInterval: 60s to detect balance changes in background

* feat(budget-warning-banner): update warning and depleted states with new headlines and actions

- Refactored the BudgetWarningBanner to use new headline keys for warning and depleted states.
- Updated the UI to include an upgrade action button and removed the previous earn credits button.
- Enhanced localization strings for better clarity in user messaging regarding budget status.
- Added a new RewardTaskIcon component for rendering task icons dynamically.

* feat(rewards): enhance rewards display and localization

- Updated the rewards status hook to disable retries for fetching data.
- Added new localization strings for balance details in English and Chinese.
- Improved the WorkspaceLayout to display rewards balance information with a detailed popup.
- Refactored HomePage to manage session and channel data more effectively, ensuring proper rendering based on session history.
- Added tests to verify the rendering of rewards components and their behavior during loading states.

* feat(rewards): implement virtual reward check and enhance localization

- Added a new module for handling virtual reward checks, including functions to manage task status and delay.
- Updated localization strings in English and Chinese for task checking and claiming processes.
- Refactored the RewardConfirmModal to utilize the new virtual check functionality, improving user feedback during reward processing.
- Introduced tests to validate the behavior of the virtual reward check and description key retrieval.

* fix(rewards): polish desktop credits flows

* feat(controller): implement controller readiness management and budget banner enhancements

- Introduced a new `ensureDesktopControllerReady` function to manage the readiness of the desktop controller, including polling and recovery logic.
- Refactored the `DesktopShell` and `useDesktopRuntimeConfig` to utilize the new controller readiness management.
- Enhanced the budget banner functionality in the `HomePage` to handle dismissal states more effectively, using session storage for tracking.
- Added a new `BudgetDepletedDialog` component to provide user feedback when budget is exhausted.
- Implemented tests for the controller readiness logic and budget banner dismissal behavior to ensure reliability.

* feat(rewards): implement GitHub star verification and proof URL handling

- Added a new `GithubStarVerificationService` to manage GitHub star session preparation and verification.
- Enhanced the desktop rewards routes to include a new endpoint for preparing GitHub star verification sessions.
- Updated the claim reward logic to validate proof URLs and GitHub session IDs before processing claims.
- Introduced new localization strings for handling proof URL inputs and GitHub session errors.
- Added tests to ensure the correct behavior of the new verification and proof handling features.

* fix(rewards): harden desktop reward validation

* chore: format skill watcher workspace test

* fix: unify low-credit prompts and byok fallback

* fix: move home budget banner below hero

* fix: avoid zero balance while rewards sync

* fix: route balance detail to environment billing

* build(desktop): stabilize Windows dev and distribution workflows (#449)

* fix(desktop): make local startup work on Windows

* fix(desktop): sanitize persisted startup logs

* test(desktop): add Feishu websocket smoke harness

* fix(smoke): improve Feishu websocket diagnostics

* build(desktop): add Windows smoke distribution flow

* build(desktop): align Windows sidecar archives with zip flow

* build(desktop): align Windows packaging with NSIS defaults

* build(desktop): refine Windows distribution commands

* build(desktop): improve Windows installer UX

Switch the NSIS flow to an assisted installer so Windows install and uninstall are visible and data cleanup can be opted into without silent surprises. Restore executable resource editing and use tombstone-based app-data cleanup so shortcuts show the Nexu icon and uninstall stays fast without flashing a console window.

* fix(desktop): stabilize Windows dist and runtime install (#538)

* build(desktop): skip exe editing for unsigned Windows dist

* fix(openclaw-runtime): stabilize Windows postinstall

Keep the full install path available for debugging while making pruned installs skip Windows-native optional dependencies that break postinstall flows.

* fix(desktop): align dev health check with runtime state

* fix(openclaw-runtime): refresh cache on installer changes

* build(desktop): add windows CI coverage

* fix(desktop): avoid sidecar copy symlink loops on windows

* fix(desktop): clean runtime plugin self-links on windows

* build(desktop): scope windows CI to build validation

* fix(desktop): restore mac dist executable discovery

---------

Co-authored-by: mRcfps <1402401442@qq.com>

* build(desktop): stabilize Windows startup and shell polish

* fix(web): refine Windows sidebar toggle layout

* fix(desktop): harden Windows packaged runtime startup

* feat: streamline desktop local dev workflow (#640)

* feat: add local dev supervisor workflow

* feat: refine local dev workflow and desktop runtime scaffolding

* docs: add dev workflow faq

* fix: remove nested controller tsx watcher

* refactor: share ensure guards across dev process helpers

* chore: remove stale task notes

* refactor: centralize local dev path resolution

* refactor: move dev orchestration into scripts/dev

Keep @nexu/dev-utils focused on atomic helpers so service-level controller and web flows stay easier to reason about and recover. Add lightweight session tracing so leaked dev processes can be correlated and cleaned up without heavy self-healing.

* refactor: clarify scripts dev module boundaries

* feat: externalize dev runtime ownership

* feat: split local dev into explicit service controls

* refactor: remove legacy desktop dev launchers

* fix: run desktop local dev through the Vite supervisor

* fix: harden local dev stack flow

* chore: sync workspace lockfiles

* fix: restore desktop dev auth session

* chore: unify scripts dev logging

* chore: stabilize launchd encapsulation and windows desktop smoke flow (#651)

* chore: introduce shared desktop lifecycle contract

* chore: move desktop platform lifecycle behind adapters

* chore: centralize desktop platform compatibility

* chore: stage patched OpenClaw runtime for local dev

* chore: log staged OpenClaw runtime usage

* chore: speed up windows desktop build iteration

* chore: disable win executable editing for local builds

* chore: ignore local build cache

* fix(desktop): support windows openclaw sidecar archives

* chore: unify desktop dev launch under scripts/dev (#654)

* chore(ci): add windows packaging to desktop dist full

* chore(ci): opt desktop dist full into node 24 actions

* Revert "chore(ci): opt desktop dist full into node 24 actions"

This reverts commit b19336e.

* fix(desktop): harden windows packaging and installer flow

* chore: remove task handoff note

* chore: align desktop tests with platform runtime changes

* chore: fix linux desktop test platform mocks

* chore: stabilize dev check service supervision

* chore: fix packaged launchd path test platform setup

* fix(desktop): preserve explicit dev runtime env overrides

* fix(dev): preserve openclaw supervisor pid lock

* chore(ci): track scripts dev changes in desktop dev checks

* chore(ci): support manual desktop workflow dispatch

* fix(dev): treat active openclaw port as running

* fix(dev): align desktop runtime ports with CI contract

* fix(dev): wait for openclaw gateway before controller start

* chore(ci): capture dev logs and read desktop pid lock

* fix(dev): wait for openclaw health before reporting ready

* fix(controller): debounce sync on all skill dir events

* fix(dev): derive openclaw status from runtime health

* fix(dev): disable bonjour in desktop CI smoke

* fix(desktop): harden Windows packaging and cleanup flows

* fix(dev): stabilize Windows desktop dev lifecycle

* fix(dev): allow overriding desktop dev ports

* fix(dev): require openclaw readiness for running status

* fix(dev): expose builtin openclaw extensions in local controller

* fix(desktop): stabilize windows packaging workflows

* fix: restore windows dev UI and openclaw startup compatibility

* fix(desktop): clear stale startup errors after runtime recovery

* fix(desktop): use packaged openclaw sidecars in windows builds

* chore: refresh lockfile for desktop dependency changes

* fix: make nexu runtime model plugin reload state by content

---------

Co-authored-by: Marc Chan <mrc@powerformer.com>
Co-authored-by: mRcfps <1402401442@qq.com>

* fix(i18n): update English and Chinese translations for rewards and balance tooltips; improve workspace layout with balance popup functionality

* feat(rewards): enhance GitHub star session handling and add token support for rate limiting; update rewards page to manage session preparation and error handling

* fix(rewards): simplify balance popup and enable github star auth token

- Drop plan/consumed rows from sidebar balance popup so only the cumulative
  reward credits row remains, matching the latest design.
- Update zh/en earned tooltip to spell out the consumption order
  (plan -> packs -> reward) and the funding sources.
- GithubStarVerificationService now reads NEXU_GITHUB_TOKEN from env to
  authenticate against api.github.com (5000 req/h) and reports rate-limit
  headers plus auth state in error messages for easier diagnosis.
- Remove the obsolete checkin total footer from the rewards page bottom strip.

* refactor(workspace-layout): enhance balance popup tooltip functionality

- Updated the balance popup to include a tooltip that appears on hover, providing additional context for earned rewards.
- Improved the styling and accessibility of the tooltip for better user experience.

* fix(i18n): update English and Chinese translations for balance popup earned credits

* feat(api): add new endpoint for retrieving desktop-local auth session and update reward sharing tasks

- Introduced the `/api/auth/get-session` endpoint to fetch the current desktop-local authentication session, including user and session details.
- Updated reward sharing tasks to replace specific platforms with a generalized "mobile_share" task, enhancing flexibility in sharing options.
- Revised English and Chinese translations for mobile sharing prompts and reward descriptions to reflect the new task structure.

* refactor(rewards): remove unused desktop cloud status and simplify QR code sharing

- Eliminated the use of desktop cloud status in the rewards page.
- Updated QR code sharing functionality to use a fixed mobile share URL instead of resolving from cloud URL.

* feat(rewards): add mobile QR code link hint and enhance mobile sharing UI

- Introduced a new hint for the mobile QR code that directs users to the Nexu GitHub repository.
- Improved the mobile sharing section's UI with enhanced styling and animations for better user experience.
- Updated English and Chinese translations to reflect the new mobile QR code link hint.

* fix(rewards): add mobile_share task id and surface silent cloud failures

The rewards UI silently failed to render the cloud balance popup
because the cloud API returned a `mobile_share` task that wasn't in
`rewardTaskIdSchema`. Zod parse failed → cloud-reward-service returned
parse_error → nexu-config-store fell through to the default branch
returning cloudBalance: null and tasks: []. The error was swallowed by
empty catches at every layer, so the only visible symptom was
"clicking the credits button does nothing".

- Add `mobile_share` to `rewardTaskIdSchema` enum and `rewardTasks`
  fallback array (group=social, icon=smartphone, image/weekly,
  requiresScreenshot, matching wechat/feishu/jike).
- Regenerate openapi.json + web SDK.
- Log cloud_rewards_status_{http,parse,network}_error in
  cloud-reward-service so future schema drift surfaces immediately.
- Log desktop_rewards_status_cloud_fallback in nexu-config-store when
  the non-auth_failed branch falls through, so the dropped reason is
  visible in controller logs.

* fix(rewards): wire credits popup detail button to cloud usage page

The "view usage detail" button in the sidebar credits popup was navigating
to the local /workspace/rewards page instead of the actual usage detail
page on the connected cloud profile. Open the cloud profile's
/workspace/usage URL in the system browser via openExternalUrl, mirroring
how the cloud bill links work elsewhere.

Also correct resolveCloudUsageUrl's fallback host from nexu.net to nexu.io
(nexu.net is not the production domain).

* feat(analytics): wire growth event tracking on PostHog base

Add the analytics events the activation funnel needs from the desktop
client side, on top of the PR #778 PostHog migration:

- workspace_growth_rewards_click — fired when the sidebar "share nexu /
  earn extra credits" growth banner is clicked.
- workspace_click_usage_detail — fired when the credits balance popup
  "view usage detail" button is clicked.
- user_message_sent.state — controller analytics service now tags each
  user_message_sent with state="Success" or state="false". Failure is
  detected by openclaw:prompt-error transcript entries arriving before
  the assistant response; success is the default and gets confirmed
  when the assistant message lands.
- AnalyticsAuthSource type now also accepts "home" so the home page
  can be the source of an auth click. The desktop side of the
  signup_success / login_success plumbing (source pass-through to
  cloud) is still pending — that side has to be done together with the
  cloud auth-init schema and is intentionally left out of this commit.

The user_message_sent.credit_charged property the funnel spec also
mentions cannot be implemented client-side: there is no per-message
credit consumption pipeline yet. cloud's credit_usages table is empty
of llm-call entries, link writes link.usage_events (USD cost) but
nothing transforms USD into credit and writes credit_usages, and link
does not record channel either. That work belongs to the cloud team
under the existing credit consumption track and is documented in
specs/current/credit.md.

* develop menu: set balance

* feat(auth): pass auth source from desktop to cloud through device-init

The cloud auth page (apps/web/src/pages/auth.tsx in nexu-io/cloud) is
already firing signup_success / login_success with the right method
field, but it sources `source` from a `?source=...` query string and
falls back to "welcome_page" otherwise. The desktop side never set
that query string, so every auth event from the desktop client showed
up as welcome_page regardless of where the user actually clicked.

This wires the desktop side end-to-end so the cloud event gets the
real source:

- packages/shared: cloudConnectBodySchema (new) and
  cloudProfileConnectBodySchema both accept an optional `source`
  string.
- controller (nexu-config-store / desktop-local-service / route):
  connect endpoints accept `source` in the request body and append it
  as `&source=…` to the cloud /auth browser URL.
- apps/web hook (use-cloud-connect): handleCloudConnect accepts an
  optional AnalyticsAuthSource parameter and forwards it.
- callers tagged with the page they fire from:
  - welcome.tsx → "welcome_page" (both initial connect and the
    retry-after-error path).
  - workspace-layout.tsx sidebar growth-card → derived from current
    route via existing isHomePage / isModelsPage flags
    (home / settings / fallback home).
  - rewards.tsx (task action and login CTA) → "home", since the
    rewards page is reached from home and the funnel spec only lists
    welcome_page / settings / home as valid sources.

Cloud-side counterpart (still pending, separate PR in nexu-io/cloud):
add "home" to the validSources allowlist in apps/web/src/pages/auth.tsx
so the postApiV1MeAuthSource backfill accepts the new value.

* fix(rewards): resolve CI failures and address Codex review feedback

- rewards.tsx: guard i18n.language access with optional chaining to prevent
  SSR/test crash when i18n instance is not fully initialized
- models.tsx: treat 'Connection attempt already in progress' as pending and
  keep polling instead of dropping user into error state (Codex P2)
- controller-ready.ts: give final recovery attempt a bounded
  finalAttemptTimeoutMs (default 4x attemptTimeoutMs) so crash-looping
  controller eventually surfaces as false instead of leaking polling loops
  (Codex P2)
- tests: align reward-share-assets / home locale / controller-ready tests
  with consolidated mobile_share task and new docs URL format

* fix(desktop): stabilize packaged webview startup

* fix(ci): assert web surface origin instead of /workspace pathname

Verify packaged runtime unit health used to require that some embedded
webview have lastUrl.includes("/workspace"), but that asserts product
state ("the user has reached the workspace route") rather than runtime
health.

In fresh-state CI runs the renderer mounts /workspace, then the SPA's
AuthLayout (apps/web/src/layouts/auth-layout.tsx:14-16) and
WorkspaceLayout (apps/web/src/layouts/workspace-layout.tsx:346-349)
immediately Navigate('/') because there is no auth session and
SETUP_COMPLETE_KEY is unset. The desktop diagnostics reporter records
contents.getURL() at did-finish-load time
(apps/desktop/main/index.ts:1035-1056), so it captures the
post-redirect URL — webview ends up with lastUrl="http://127.0.0.1:50810/"
and the old check reported "workspace webview diagnostics are missing".

Local runs accidentally passed because the developer machine had a
persisted Local Storage with nexu_setup_complete=1 from earlier sessions,
which suppressed the redirect. CI is ephemeral and never had it.

The actual runtime health invariant is that an embedded webview
successfully loaded a page from the local web sidecar's origin — the
embed handshake worked, the renderer is alive, and there was no
fail-load. The path under that origin (/, /workspace, /welcome, ...)
is product state, not health.

- Add webOrigin to readinessUrls (parsed from the web URL).
- Replace getLatestWorkspaceWebview with getLatestWebSurfaceWebview that
  filters embedded entries by same-origin against webOrigin and ignores
  pathname entirely.
- Thread webOrigin through diagnosticsChecksPassed,
  collectDiagnosticsFailures, probesPassed, verifyRuntime.
- Failure message now reads "web surface webview diagnostics are
  missing (no embedded webview reported origin <origin>)".

Verified locally with two fixtures:
- {id:3, lastUrl:"http://127.0.0.1:50810/"}      → matches (used to miss)
- {id:3, lastUrl:"http://127.0.0.1:50810/workspace"} → still matches

* fix(desktop): show NexuLoader instead of error card while controller is starting (#893)

On relaunch, users saw a white card titled "Starting controller..." with
"Retry controller" and "Open control plane" buttons during the short
window where the local controller was booting but not yet ready. It
looked like the app had landed on an error page instead of the home
page, which is what issue #876 reported.

The only difference between the "polling" and "failed" states in the
old fallback UI was the heading text — both rendered the same card and
the same Retry button, so users could not tell "still starting" from
"actually broken".

Split the fallback into three branches:
- desktopWebUrl ready -> SurfaceFrame with the webview (unchanged)
- controller failed / recovering -> the original error card with Retry
- normal polling -> SurfaceFrame with src=null, which reuses the built-in
  NexuLoader overlay that SurfaceFrame already shows before webview
  did-finish-load

The polling loader and the post-mount webview loader are now the same
NexuLoader component with the same animation, so the transition from
"controller starting" to "home page" is visually seamless and never
exposes any text or buttons that could be mistaken for an error page.

Closes #876

* refresh after set balance

* perf(desktop): unblock event loop during packaged sidecar extraction

The async openclaw sidecar materializer was named "Async" and wrapped
in async/await, but it called execFileSync("/usr/bin/tar", …) and
rmSync(…) internally. execFileSync blocks the Node.js event loop until
the child process exits, so for the ~14s tar extraction on first
install / post-update the main process could not respond to anything,
including IPC handshake from the renderer's preload. As a result the
renderer's loadFile took ~28s to fire did-finish-load (measured locally:
12:13:42.805 dispatched → 12:14:10.463 finished, while extraction ran
12:13:42 → 12:13:56), and the setup-animation video did not start
playing until extraction was complete — defeating the entire point of
showing the window with a white background "before loadFile, before
React, before anything" (apps/desktop/main/index.ts:945-955).

Switch the tar invocation to promisify(execFile), which still spawns a
real /usr/bin/tar child process but waits for it via libuv asynchronously
so the event loop stays responsive. Also replace the matching rmSync of
the previous extracted sidecar root with the async fs/promises rm to
keep the function uniformly non-blocking.

Sync materializer (createSyncTarSidecarMaterializer) is left untouched
because it is intentionally synchronous for early-bootstrap call sites.

Effect: renderer mounts and the setup-animation video starts playing
within seconds of window.show(), in parallel with extraction, instead
of after extraction finishes.

* fix(desktop): refresh packaged runtime on build changes

Avoid reusing stale extracted runtime sidecars when a rebuilt app keeps the same app version but changes CFBundleVersion, and keep the desktop rewards balance popup reachable while cloud balance data is still loading.

* fix(desktop): tear down stale runtime before replace

When packaged runtime identity changes, boot out launchd services and clear surviving Nexu processes before replacing the extracted runner and controller sidecar so reinstall flows cannot keep stale runtime code alive.

* fix(desktop): sign openclaw native sidecar binaries

Sign all packaged OpenClaw native binary candidates directly during mac builds and invalidate stale archived sidecar payloads so notarization cannot fail on unsigned canvas/skia artifacts.

* fix(rewards): address remaining PR review feedback

Recover stale desktop cloud connect sessions, validate reward group IDs and profile renames more defensively, and route desktop test balance operations through the host bridge instead of renderer-origin fetches.

* test(desktop): make webview preload URL test portable

Build the expected file URL with Node path/url helpers so the desktop preload URL assertion passes on Windows as well as Unix runners.

---------

Co-authored-by: PerishFire <39043006+PerishCode@users.noreply.github.com>
Co-authored-by: Marc Chan <mrc@powerformer.com>
Co-authored-by: mRcfps <1402401442@qq.com>
Co-authored-by: lefarcen <935902669@qq.com>
Co-authored-by: nettee <nettee.liu@gmail.com>
PerishCode added a commit that referenced this pull request Apr 9, 2026
* fix(desktop): make local startup work on Windows

* fix(desktop): sanitize persisted startup logs

* test(desktop): add Feishu websocket smoke harness

* fix(smoke): improve Feishu websocket diagnostics

* build(desktop): add Windows smoke distribution flow

* build(desktop): align Windows sidecar archives with zip flow

* build(desktop): align Windows packaging with NSIS defaults

* build(desktop): refine Windows distribution commands

* build(desktop): improve Windows installer UX

Switch the NSIS flow to an assisted installer so Windows install and uninstall are visible and data cleanup can be opted into without silent surprises. Restore executable resource editing and use tombstone-based app-data cleanup so shortcuts show the Nexu icon and uninstall stays fast without flashing a console window.

* fix(desktop): stabilize Windows dist and runtime install (#538)

* build(desktop): skip exe editing for unsigned Windows dist

* fix(openclaw-runtime): stabilize Windows postinstall

Keep the full install path available for debugging while making pruned installs skip Windows-native optional dependencies that break postinstall flows.

* fix(desktop): align dev health check with runtime state

* fix(openclaw-runtime): refresh cache on installer changes

* build(desktop): add windows CI coverage

* fix(desktop): avoid sidecar copy symlink loops on windows

* fix(desktop): clean runtime plugin self-links on windows

* build(desktop): scope windows CI to build validation

* fix(desktop): restore mac dist executable discovery

---------

Co-authored-by: mRcfps <1402401442@qq.com>

* build(desktop): stabilize Windows startup and shell polish

* fix(web): refine Windows sidebar toggle layout

* fix(desktop): harden Windows packaged runtime startup

* feat: streamline desktop local dev workflow (#640)

* feat: add local dev supervisor workflow

* feat: refine local dev workflow and desktop runtime scaffolding

* docs: add dev workflow faq

* fix: remove nested controller tsx watcher

* refactor: share ensure guards across dev process helpers

* chore: remove stale task notes

* refactor: centralize local dev path resolution

* refactor: move dev orchestration into scripts/dev

Keep @nexu/dev-utils focused on atomic helpers so service-level controller and web flows stay easier to reason about and recover. Add lightweight session tracing so leaked dev processes can be correlated and cleaned up without heavy self-healing.

* refactor: clarify scripts dev module boundaries

* feat: externalize dev runtime ownership

* feat: split local dev into explicit service controls

* refactor: remove legacy desktop dev launchers

* fix: run desktop local dev through the Vite supervisor

* fix: harden local dev stack flow

* chore: sync workspace lockfiles

* fix: restore desktop dev auth session

* chore: unify scripts dev logging

* chore: stabilize launchd encapsulation and windows desktop smoke flow (#651)

* chore: introduce shared desktop lifecycle contract

* chore: move desktop platform lifecycle behind adapters

* chore: centralize desktop platform compatibility

* chore: stage patched OpenClaw runtime for local dev

* chore: log staged OpenClaw runtime usage

* chore: speed up windows desktop build iteration

* chore: disable win executable editing for local builds

* chore: ignore local build cache

* fix(desktop): support windows openclaw sidecar archives

* chore: unify desktop dev launch under scripts/dev (#654)

* chore(ci): add windows packaging to desktop dist full

* chore(ci): opt desktop dist full into node 24 actions

* Revert "chore(ci): opt desktop dist full into node 24 actions"

This reverts commit b19336e.

* fix(desktop): harden windows packaging and installer flow

* chore: remove task handoff note

* chore: align desktop tests with platform runtime changes

* chore: fix linux desktop test platform mocks

* chore: stabilize dev check service supervision

* chore: fix packaged launchd path test platform setup

* fix(desktop): preserve explicit dev runtime env overrides

* fix(dev): preserve openclaw supervisor pid lock

* chore(ci): track scripts dev changes in desktop dev checks

* chore(ci): support manual desktop workflow dispatch

* fix(dev): treat active openclaw port as running

* fix(dev): align desktop runtime ports with CI contract

* fix(dev): wait for openclaw gateway before controller start

* chore(ci): capture dev logs and read desktop pid lock

* fix(dev): wait for openclaw health before reporting ready

* fix(controller): debounce sync on all skill dir events

* fix(dev): derive openclaw status from runtime health

* fix(dev): disable bonjour in desktop CI smoke

* fix(desktop): harden Windows packaging and cleanup flows

* fix(dev): stabilize Windows desktop dev lifecycle

* fix(dev): allow overriding desktop dev ports

* fix(dev): require openclaw readiness for running status

* fix(dev): expose builtin openclaw extensions in local controller

* fix(desktop): stabilize windows packaging workflows

* fix: restore windows dev UI and openclaw startup compatibility

* fix(desktop): clear stale startup errors after runtime recovery

* fix(desktop): use packaged openclaw sidecars in windows builds

* chore: refresh lockfile for desktop dependency changes

* fix: make nexu runtime model plugin reload state by content

* chore: extract openclaw runtime boundary helpers

* chore: consolidate openclaw runtime integration boundary

* chore: route windows packaging through scripts/pkg

Move the root Windows packaging entrypoints onto scripts/pkg and add shared packaging/platform helper packages so the packaging path is easier to reuse and evolve.

* fix: restore Windows packaged startup path

Pass the managed Windows controller the Electron runner and add targeted packaging/startup diagnostics so fresh packaged builds use the correct OpenClaw launch contract. Remove the stale root Windows dist wrapper so future validation follows the real desktop packaging entrypoints.

* fix: enforce exe-relative Windows runtime packaging

Require packaged Windows builds to resolve OpenClaw from the current exe resources, fail fast when the packaged runtime is incomplete, and stop reusing stale Windows dist artifacts during validation. Keep the sidecar unpacked for Windows builds so portable validation can move through fast 7z-based transfers instead of unreliable copy/install paths.

* fix: speed up windows custom installer extraction

* fix: add windows nightly update redirect flow

* fix: converge windows packaging on dist:win

* fix: guard windows nightly cache purge secrets

* fix: skip windows nightly purge when secrets are missing

* fix: align qqbot runtime mapping and controller tests

* chore: align windows beta and release CI with dist-win

* chore: migrate openclaw runtime helpers back to root

* chore: narrow windows branch scope to desktop delivery

* chore: stabilize desktop workflow version metadata

* chore: vendor windows packaging 7zip

* test: align launchd runner stamp expectations

* chore: format desktop package version script

* chore: install nsis in desktop dist full CI

* chore: accept unarchived windows sidecar in dist CI

* fix: stabilize packaged openclaw mdns hostname

* fix: disable openclaw mdns discovery in CI

* fix: move openclaw CI discovery config to top level

* fix: harden desktop packaged update flows

* fix: disable openclaw bonjour in CI

---------

Co-authored-by: Marc Chan <mrc@powerformer.com>
Co-authored-by: mRcfps <1402401442@qq.com>
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