Skip to content

fix(desktop): self-heal stale model id + expose plan as 4th editMode#1699

Merged
esengine merged 2 commits into
mainfrom
fix/desktop-model-selfheal-plan-mode
May 24, 2026
Merged

fix(desktop): self-heal stale model id + expose plan as 4th editMode#1699
esengine merged 2 commits into
mainfrom
fix/desktop-model-selfheal-plan-mode

Conversation

@esengine

Copy link
Copy Markdown
Owner

Summary

Two desktop/dashboard UX regressions surfaced after 0.50.0:

  • Model picker showed "custom" / 自定义 for users upgrading from a
    pre-v4 config. The CLI's loadModel() self-healing (fix(model): self-heal stale model id on load; drop v3 ids from picker fallbacks #1663) maps
    stale v3 ids (deepseek-chat / deepseek-reasoner) to
    DEFAULT_MODEL, but the /settings GET endpoint still returned the
    raw cfg.model, so the desktop landed on the stale id and the
    picker rendered it as a custom id — looked like the app forgot which
    model it was on.

  • Plan mode was unreachable from the GUI surfaces. feat(plan): wire editMode="plan" into the ToolRegistry dispatch gate #1681 made
    editMode === "plan" the dispatch-gate source of truth, but neither
    the desktop nor the dashboard ever grew a control to set it: the
    settings API rejected "plan" with a 400, the composer's
    ModeSwitch hardcoded review/auto/yolo, and the settings page
    tri-state only listed the same three. Plan was only reachable via
    the CLI's /plan slash or a manual config.json edit.

Changes

  1. src/server/api/settings.ts — route GET model through
    loadModel(ctx.configPath) so the wire response is self-healed
    like the CLI's local read
  2. src/server/api/settings.ts, src/server/api/edit-mode.ts,
    src/cli/ui/slash/commands.ts — admit "plan" in the validation
    sets + /mode slash completer
  3. desktop/src/{protocol,App,ui/composer,ui/settings}.tsx +
    dashboard/src/{protocol,App,ui/composer,ui/settings}.tsx — extend
    the local EditMode unions, add a plan entry to MODE_INFO
    (with I.list), add a plan button to the settings tri-state
  4. {desktop,dashboard}/src/i18n/{en,zh-CN}.tseditMode.plan +
    editMode.planHint (and planDesc on desktop)

Test plan

  • tsc --noEmit passes for root, desktop, dashboard
  • existing settings-api.test.ts, slash.test.ts, and
    code-setup-lazy-subagent.test.ts (which already covers
    editMode = "plan" end-to-end through the dispatch gate) all pass
  • Manual: open desktop → settings → editMode shows a 4th plan
    button; selecting it persists, composer reflects the new option,
    write tools refuse to dispatch in plan mode

Closes the GUI-side gap left by #1681.

reasonix added 2 commits May 24, 2026 08:22
#1663 added `loadModel()` which maps unsupported model ids (e.g. v3
`deepseek-chat` / `deepseek-reasoner` left over in a user's config)
to `DEFAULT_MODEL` when no custom endpoint is set. The CLI uses it,
but the dashboard/desktop `/settings` GET endpoint still returned the
raw `cfg.model`, so users upgrading from a pre-v4 config saw their
desktop landing on the stale id and the model picker rendering it as
"custom" — looks like the app forgot which model it's on.

Route the GET through `loadModel(ctx.configPath)` so the same
self-heal applies on the wire. Custom-baseUrl users still keep their
custom ids unchanged (`loadModel` trusts non-empty `baseUrl`).
…d UIs

#1681 wired `editMode === "plan"` into the ToolRegistry dispatch gate
so plan mode is now a persisted state, not a slash-only toggle. The
desktop and dashboard surfaces never grew a control to set it though —
the settings API + edit-mode API still rejected "plan" with a 400, the
composer's ModeSwitch hardcoded review/auto/yolo, and the settings
page tri-state only listed the same three. Net: plan mode was
reachable from the CLI's `/plan` slash and direct config edits, but
not from either GUI surface.

Admit "plan" in both validation sets (`src/server/api/settings.ts`,
`src/server/api/edit-mode.ts`) and the `/mode` slash completer
(`src/cli/ui/slash/commands.ts`). Add a "plan" entry to MODE_INFO in
both composers with `I.list` and a planHint string. Add "plan" to the
settings page button maps. Extend the local `EditMode` string unions
in `desktop/src/{protocol,App,ui/composer}.tsx` and the dashboard
equivalents so TS accepts it everywhere.

i18n: add `editMode.plan` + `editMode.planHint` (and `planDesc` on
desktop) in both en + zh-CN for each surface.
@esengine esengine merged commit 56f3ffe into main May 24, 2026
4 checks passed
@esengine esengine deleted the fix/desktop-model-selfheal-plan-mode branch May 24, 2026 15:33
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