fix(ui): i18n locale before render + fix: tool_use mismatch suggest /new (#46366, #46365)#46373
fix(ui): i18n locale before render + fix: tool_use mismatch suggest /new (#46366, #46365)#46373xuwei-xy wants to merge 1 commit intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR bundles two bug fixes: (1) it detects Key changes:
Issues found:
Confidence Score: 3/5
Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/agents/pi-embedded-helpers/errors.ts
Line: 838-839
Comment:
**Overly broad `tool_use_id` alternative in regex**
The first branch of the regex — `tool_use_id` — matches any string that merely contains the substring `"tool_use_id"`, with no further constraints. This means error messages completely unrelated to a history-corruption mismatch (e.g. `"Invalid format for tool_use_id"`, `"tool_use_id is required"`, or `"Unsupported tool_use_id type"`) will all return `"Conversation history corruption detected. Please use /new to start a fresh session."`, which is incorrect advice and will confuse users.
The other two alternatives (`tool_result.*corresponding.*tool_use` and `unexpected.*tool.*block`) are adequately specific. The first alternative should be tightened to require additional context, for example:
```suggestion
const TOOL_USE_RESULT_MISMATCH_RE =
/tool_result.*tool_use_id.*not found|tool_result.*corresponding.*tool_use|unexpected.*tool.*block/i;
```
This matches the actual Anthropic API error strings exercised by the tests (`"tool_result block with tool_use_id … not found in the immediately preceding assistant message"`) while avoiding false positives on generic validation errors that happen to reference the field name.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: ui/src/ui/app.ts
Line: 119-133
Comment:
**Potential race condition between `i18n.ready` and `settingsLocale`**
Both `i18n.ready` (which loads the locale persisted in `localStorage` / derived from `navigator.language`) and `settingsLocale` (which loads the locale from app `settings`) are kicked off concurrently via `Promise.all`. Because `setLocale` is not re-entrant, whichever resolves *last* wins and sets `this.locale`.
If the two sources disagree — e.g. `localStorage` says `"zh-CN"` and `settings.locale` says `"fr"` — the final rendered locale will be whichever translation finishes loading later, which is non-deterministic. App settings should be the authoritative source, so `settingsLocale` ought to be applied *after* `i18n.ready` resolves to avoid being overwritten:
```
i18n.ready
.then(() => isSupportedLocale(this.settings.locale) ? i18n.setLocale(this.settings.locale) : Promise.resolve())
.then(() => { this.localeReady = true; }, () => { this.localeReady = true; });
```
This is a low-probability edge case (requires the two stores to diverge), but it would be an invisible, intermittent bug.
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: 55fa530 |
| const TOOL_USE_RESULT_MISMATCH_RE = | ||
| /tool_use_id|tool_result.*corresponding.*tool_use|unexpected.*tool.*block/i; |
There was a problem hiding this comment.
Overly broad tool_use_id alternative in regex
The first branch of the regex — tool_use_id — matches any string that merely contains the substring "tool_use_id", with no further constraints. This means error messages completely unrelated to a history-corruption mismatch (e.g. "Invalid format for tool_use_id", "tool_use_id is required", or "Unsupported tool_use_id type") will all return "Conversation history corruption detected. Please use /new to start a fresh session.", which is incorrect advice and will confuse users.
The other two alternatives (tool_result.*corresponding.*tool_use and unexpected.*tool.*block) are adequately specific. The first alternative should be tightened to require additional context, for example:
| const TOOL_USE_RESULT_MISMATCH_RE = | |
| /tool_use_id|tool_result.*corresponding.*tool_use|unexpected.*tool.*block/i; | |
| const TOOL_USE_RESULT_MISMATCH_RE = | |
| /tool_result.*tool_use_id.*not found|tool_result.*corresponding.*tool_use|unexpected.*tool.*block/i; |
This matches the actual Anthropic API error strings exercised by the tests ("tool_result block with tool_use_id … not found in the immediately preceding assistant message") while avoiding false positives on generic validation errors that happen to reference the field name.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-helpers/errors.ts
Line: 838-839
Comment:
**Overly broad `tool_use_id` alternative in regex**
The first branch of the regex — `tool_use_id` — matches any string that merely contains the substring `"tool_use_id"`, with no further constraints. This means error messages completely unrelated to a history-corruption mismatch (e.g. `"Invalid format for tool_use_id"`, `"tool_use_id is required"`, or `"Unsupported tool_use_id type"`) will all return `"Conversation history corruption detected. Please use /new to start a fresh session."`, which is incorrect advice and will confuse users.
The other two alternatives (`tool_result.*corresponding.*tool_use` and `unexpected.*tool.*block`) are adequately specific. The first alternative should be tightened to require additional context, for example:
```suggestion
const TOOL_USE_RESULT_MISMATCH_RE =
/tool_result.*tool_use_id.*not found|tool_result.*corresponding.*tool_use|unexpected.*tool.*block/i;
```
This matches the actual Anthropic API error strings exercised by the tests (`"tool_result block with tool_use_id … not found in the immediately preceding assistant message"`) while avoiding false positives on generic validation errors that happen to reference the field name.
How can I resolve this? If you propose a fix, please make it concise.| constructor() { | ||
| super(); | ||
| if (isSupportedLocale(this.settings.locale)) { | ||
| void i18n.setLocale(this.settings.locale); | ||
| } | ||
| const settingsLocale = isSupportedLocale(this.settings.locale) | ||
| ? i18n.setLocale(this.settings.locale) | ||
| : Promise.resolve(); | ||
| Promise.all([i18n.ready, settingsLocale]).then( | ||
| () => { | ||
| this.localeReady = true; | ||
| }, | ||
| () => { | ||
| // Locale load failed; render with the default locale. | ||
| this.localeReady = true; | ||
| }, | ||
| ); | ||
| } |
There was a problem hiding this comment.
Potential race condition between i18n.ready and settingsLocale
Both i18n.ready (which loads the locale persisted in localStorage / derived from navigator.language) and settingsLocale (which loads the locale from app settings) are kicked off concurrently via Promise.all. Because setLocale is not re-entrant, whichever resolves last wins and sets this.locale.
If the two sources disagree — e.g. localStorage says "zh-CN" and settings.locale says "fr" — the final rendered locale will be whichever translation finishes loading later, which is non-deterministic. App settings should be the authoritative source, so settingsLocale ought to be applied after i18n.ready resolves to avoid being overwritten:
i18n.ready
.then(() => isSupportedLocale(this.settings.locale) ? i18n.setLocale(this.settings.locale) : Promise.resolve())
.then(() => { this.localeReady = true; }, () => { this.localeReady = true; });
This is a low-probability edge case (requires the two stores to diverge), but it would be an invisible, intermittent bug.
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/ui/app.ts
Line: 119-133
Comment:
**Potential race condition between `i18n.ready` and `settingsLocale`**
Both `i18n.ready` (which loads the locale persisted in `localStorage` / derived from `navigator.language`) and `settingsLocale` (which loads the locale from app `settings`) are kicked off concurrently via `Promise.all`. Because `setLocale` is not re-entrant, whichever resolves *last* wins and sets `this.locale`.
If the two sources disagree — e.g. `localStorage` says `"zh-CN"` and `settings.locale` says `"fr"` — the final rendered locale will be whichever translation finishes loading later, which is non-deterministic. App settings should be the authoritative source, so `settingsLocale` ought to be applied *after* `i18n.ready` resolves to avoid being overwritten:
```
i18n.ready
.then(() => isSupportedLocale(this.settings.locale) ? i18n.setLocale(this.settings.locale) : Promise.resolve())
.then(() => { this.localeReady = true; }, () => { this.localeReady = true; });
```
This is a low-probability edge case (requires the two stores to diverge), but it would be an invisible, intermittent bug.
How can I resolve this? If you propose a fix, please make it concise.
Combines fixes from upstream PRs:
Merged from openclaw/openclaw PRs.