fix: clear stale cloud model on disconnect and hide plan credits row#1079
fix: clear stale cloud model on disconnect and hide plan credits row#1079alchemistklk wants to merge 3 commits intomainfrom
Conversation
After cloud disconnect, the defaultModelId still pointed to a cloud/link model, allowing the bot to keep using it. Three fixes: 1. cloud-disconnect route now calls ensureValidDefaultModel() + syncAll() so BYOK fallback works (matches cloud-profile/disconnect pattern) 2. disconnectDesktopCloud() clears defaultModelId when it was a cloud model, preventing stale refs when no BYOK is available 3. onCloudStateChanged restarts OpenClaw on both connect and disconnect (was connect-only) to flush cached provider credentials Also removes the plan credits (套餐积分) row from the sidebar balance popup.
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a89239e29e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const result = await container.desktopLocalService.disconnectCloud(); | ||
| await container.modelProviderService.ensureValidDefaultModel(); | ||
| const { configPushed } = await container.openclawSyncService.syncAll(); | ||
| return c.json({ ...result, configPushed }, 200); |
There was a problem hiding this comment.
Update cloud-disconnect schema to include configPushed
This handler now returns configPushed, but the route is still declared with cloudDisconnectResponseSchema (currently just { ok: boolean } in packages/shared/src/schemas/provider.ts). That leaves the OpenAPI contract and generated SDK types out of sync for /api/internal/desktop/cloud-disconnect, so typed clients cannot rely on configPushed and schema-driven consumers may strip/reject it. Please either extend the shared response schema (and regenerate types) or remove the extra field from the response.
Useful? React with 👍 / 👎.
Add ensureValidDefaultModel() to onCloudStateChanged callback so that after re-login, a cloud model is auto-selected when defaultModelId is empty. This fixes the "No model configured" state after logout + re-login.
The nexu-runtime-model plugin reads the model ref from disk on every
turn. When selectedModelRef is "" (after cloud disconnect), the plugin
was still returning { modelOverride: "" } which let OpenClaw fall back
to the session's cached provider. Now it returns early with no override,
so OpenClaw uses whatever is in the current compiled config (which has
no link provider after disconnect).
What
Clear stale cloud model reference after cloud disconnect and remove the plan credits row from the sidebar balance popup.
Why
After logging out of a Nexu cloud account, the bot could still use cloud/Link models because:
defaultModelIdwas never reset — it kept pointing to the old cloud modelensureValidDefaultModel()was not called in the disconnect route (unlike all other cloud mutation routes)The plan credits (套餐积分) row in the sidebar balance popup is no longer needed.
How
Cloud disconnect fix (3 changes):
desktop-compat-routes.ts: AddensureValidDefaultModel()+syncAll()tocloud-disconnecthandler, matching thecloud-profile/disconnectpattern. Handles BYOK fallback.nexu-config-store.ts: IndisconnectDesktopCloud(), check ifdefaultModelIdwas a cloud model usingresolveManagedCloudModel()(already imported). If so, clear it to"". Handles the no-BYOK case.container.ts: ChangeonCloudStateChangedcondition from!hadCloud && hasCloudtohadCloud !== hasCloudso OpenClaw restarts on both connect and disconnect.UI fix:
workspace-layout.tsx: Remove the recharged/plan credits row from the sidebar balance popup.Affected areas
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpassespnpm generate-typesrun (if API routes/schemas changed)anytypes introduced (useunknownwith narrowing)Notes for reviewers
The OpenClaw restart via
openclawProcess.stop()/.start()is a no-op in launchd mode (controller doesn't own the process). Existing sessions may still use cached link provider until they expire or OpenClaw is fully restarted by the desktop process. A follow-up may be needed to havesyncAll()trigger session invalidation when model providers are removed (similar to the existingtouchAnySkillMarker()approach for skills).