fix(openclaw): persist language selection in overview page (#13992)

### What this PR does

Before this PR:

OpenClaw dashboard URLs were generated with auth in a hash fragment
(`#token=...`). This could overwrite SPA fragment state and cause the
Overview language selection to revert after navigation/reopen.

After this PR:

OpenClaw dashboard URLs now use query-string auth (`?token=...`) so the
dashboard can preserve its own fragment/UI state, and the language
setting no longer resets.

Fixes #13986

### Why we need it and why it was done in this way

The following tradeoffs were made:

- Moved token transport from URL fragment to query string to avoid
clobbering fragment-based SPA state.
- Added a focused unit test to lock the expected URL format.

The following alternatives were considered:

- Keeping `#token` and attempting dashboard-side state workarounds.
- Injecting language into URL parameters as a one-off workaround.

Links to places where the discussion took place:
https://github.com/CherryHQ/cherry-studio/issues/13986

### Breaking changes

None.

If this PR introduces breaking changes, please describe the changes and
the impact on users.

### Special notes for your reviewer

- Local checks run: `pnpm lint` (pass), `pnpm format` (pass).
- `pnpm test` has unrelated pre-existing failures in this environment
(filesystem symlink/path-separator tests and cherryclaw workspace
tests); `OpenClawService` tests pass including the newly added URL
assertion.

### Checklist

This checklist is not enforcing, but it's a reminder of items that could
be relevant to every PR.
Approvers are expected to review this list.

- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: [Write code that humans can
understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans)
and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle)
- [x] Refactor: You have [left the code cleaner than you found it (Boy
Scout
Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html)
- [x] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [x] Documentation: A [user-guide update](https://docs.cherry-ai.com)
was considered and is present (link) or not required. Check this only
when the PR introduces or changes a user-facing feature or behavior.
- [x] Self-review: I have reviewed my own code (e.g., via
[`/gh-pr-review`](/.claude/skills/gh-pr-review/SKILL.md), `gh pr diff`,
or GitHub UI) before requesting review from others

### Release note

```release-note
Fix OpenClaw Overview language selection persistence by using `?token=` dashboard auth URLs instead of `#token=...`, preventing language reset after navigation/reopen.
```

Signed-off-by: 404-Page-Found <Lucas20220605@gmail.com>
Co-authored-by: SuYao <sy20010504@gmail.com>
This commit is contained in:
404-Page-Found
2026-04-11 19:22:06 +10:00
committed by GitHub
parent bd61bad7ee
commit d75883d631
2 changed files with 13 additions and 1 deletions

View File

@@ -701,7 +701,9 @@ class OpenClawService {
}
let url = `http://127.0.0.1:${this.gatewayPort}`
if (this.gatewayAuthToken) {
url += `#token=${encodeURIComponent(this.gatewayAuthToken)}`
// Use query string (not URL fragment) so dashboard app state can persist correctly.
// Fragment (#...) is often used by SPAs for transient client-side state.
url += `?token=${encodeURIComponent(this.gatewayAuthToken)}`
}
return url
}

View File

@@ -84,6 +84,16 @@ describe('OpenClawService gateway status state machine', () => {
vi.restoreAllMocks()
})
describe('getDashboardUrl', () => {
it('uses query string token to preserve dashboard UI state', () => {
// @ts-expect-error -- accessing private field for testing
service.gatewayAuthToken = 'a b+c'
const url = service.getDashboardUrl()
expect(url).toBe(`http://127.0.0.1:18790?token=${encodeURIComponent('a b+c')}`)
})
})
// ─── getStatus ───────────────────────────────────────────────
describe('getStatus', () => {