Skip to content

feat(desktop): wallet + version, plan rail, i18n, gate fixes#701

Merged
esengine merged 6 commits into
mainfrom
fix/forget-stale-banner
May 12, 2026
Merged

feat(desktop): wallet + version, plan rail, i18n, gate fixes#701
esengine merged 6 commits into
mainfrom
fix/forget-stale-banner

Conversation

@esengine

Copy link
Copy Markdown
Owner

Summary

Desktop Tauri app was missing a lot of what the CLI TUI has and silently disagreed with the on-disk config in places. This PR fixes that.

Surfaces that didn't exist

  • Sidebar wallet card (DeepSeek /user/balance, polled on startup and after every turn) and live version chip in the brand area
  • Active-plan rail above the messages list — collapsible, per-step risk dots, completed-step results inline, progress bar, manual ✕ dismiss for plans without structured steps
  • Checkpoint card with Continue / Revise / Stop when a plan step finishes in review mode
  • Revision card for revise_plan (Accept / Reject / Cancel)
  • Edit-gate pill in the header (review / auto / yolo, color-coded) — no more digging into Settings to flip approval strictness

Bugs the desktop was carrying

  • pauseGate.on listener dropped plan_checkpoint and plan_revision requests, so mark_step_complete and revise_plan blocked forever with no UI affordance
  • Abort only flipped the per-turn AbortController; pending pause-gate Promises survived. Pressing Stop during a plan checkpoint was a no-op
  • Desktop UI saved editMode: "default" but loadEditMode() only accepts "review" | "auto" | "yolo" and silently coerces anything else to review — so YOLO was, in practice, review
  • ⌘K Settings was a fake "coming soon" toast despite SettingsPanel being mounted and wired
  • Hardcoded 0.39 brand chip, no version visible anywhere else

Where I removed duplication

  • New src/core/pause-policy.tsshouldAutoResolveCheckpoint(editMode) / autoResolveVerdict(req, editMode) are now the single source of truth for edit-mode→gate rules. CLI TUI (src/cli/ui/App.tsx) and the desktop CLI listener (src/cli/commands/desktop.ts) both call into it instead of inlining the same check
  • New pauseGate.cancel(id) so multi-tab hosts can free one waiting gate without blowing away the global queue. Abort + new_chat + session_load now drain per-tab pending gates and emit $plan_cleared when they tear down an active plan
  • $plan_cleared fires automatically on $turn_complete when all marked steps are done

i18n

  • New desktop/src/i18n/{index,en,zh-CN} — small React listener-based module, localStorage-only (no backend roundtrip). Auto-detects from navigator.language, switchable live from Settings
  • ⌘K palette, sidebar nav, App toasts, composer placeholder + kbd hints, plan/checkpoint/revision cards, modal placeholders, and the full Settings panel all flow through t()

UI cleanup

  • Removed the ThinkingBar Stop pill — composer's send button already turns into Stop when busy
  • Removed the redundant Stop button inside ActivePlanRail (overlapped progress text)
  • Decluttered header — version + wallet moved to sidebar; header keeps just title · workspace · turns · tokens · cache · cost · edit-mode pill · preset pill · ⌘K

Test plan

  • npm run verify (lint + typecheck + 2681 tests pass locally)
  • cd desktop && npm run build and load the app; ⌘K → Settings opens the existing panel
  • Wallet card shows ¥xx.xx in sidebar foot after first turn; falls back gracefully if /user/balance fails
  • Version chip in sidebar brand reflects package.json version
  • Submit a plan with structured steps → ActivePlanRail appears; in review mode each step prompts via CheckpointCard; in auto/yolo steps auto-continue and rail ticks; rail clears on turn_complete
  • Press Stop during a plan checkpoint → loop tears down cleanly, rail clears
  • Language toggle in Settings flips palette, sidebar, composer, settings, and toasts live
  • Header edit-mode pill saves through; pick auto → next checkpoint doesn't prompt

esengine added 6 commits May 12, 2026 01:53
The top-level /forget command was removed in the slash refactor, but
the resumed-session and new-session banners + the context-overflow
error still told users to type it. Point them at the surviving paths
instead: /new for a fresh start, /sessions ([d] to delete) for
manage / rename / drop.

Closes #697
Tauri shell had no visible version or DeepSeek balance, and ⌘K's
Settings was a stub toast despite SettingsPanel being mounted.

- $settings now carries VERSION → version chip in Sidebar brand
- new $balance event polls /user/balance on startup, after each
  turn, and after key/workspace changes → wallet card in Sidebar
- ⌘K Settings opens the existing panel; About shows real version
- ⌘K gains New/Close tab, Stop turn, Copy/Export reply, Pick workspace
Tauri shell was a mix of English labels and Chinese hints with no
way to switch. Add a small React i18n module (localStorage + listener-
based re-render), seed en / zh-CN dictionaries, and surface a Language
picker in Settings.

- new desktop/src/i18n/{index,en,zh-CN}
- migrate ⌘K palette items, sidebar nav + wallet label, App toasts,
  composer placeholder + kbd hints, plan/choice modal placeholders
- Settings grows a Language section; auto-detect from navigator.language
  on first launch, sticky via reasonix.lang
Desktop dropped plan_checkpoint and plan_revision pause-gate requests on
the floor and abort only flipped the per-turn AbortController, so once
mark_step_complete fired the user was wedged with no UI response and no
way out.

- pause-gate: new cancel(id) using existing safeCancelVerdict
- desktop CLI: per-tab pendingGateIds + completedStepIds; abort now
  drains gates via cancel(id), emits $plan_cleared
- desktop CLI: emit $plan_required steps, $checkpoint_required (with
  done/total), $revision_required, $step_completed, $plan_cleared
- desktop UI: state grows activePlan, pendingCheckpoints,
  pendingRevisions; reducer wires resolve_plan(approve) → activePlan,
  resolve_revision(accepted) → swap remaining steps
- desktop UI: new ActivePlanRail above messages (collapsible, progress
  bar, per-step risk + result), CheckpointCard (continue/revise/stop),
  RevisionCard (accept/reject/cancel); Stop button in rail when busy
- i18n: plan / checkpoint / revision strings in en + zh-CN
Settings panel still rendered every section label, hint, and option
description in hardcoded English. Toggling the language picker did
nothing for the panel itself.

ThinkingBar had its own Stop pill on the right while the composer's
send button already turns into Stop when a turn is in flight. Two
buttons for the same action.

- migrate every SettingsSection label / hint / option name + desc
  through t(); editor presets and api-key inline buttons too
- new settings.* keys in en + zh-CN
- ThinkingBar: drop onStop prop + button + .thinking-bar-stop CSS
- App.tsx: stop passing onStop={abort} to ThinkingBar
Two real bugs from the desktop diverging from CLI TUI behavior:

1. YOLO still asked at every plan_checkpoint. Two causes:
   a. Desktop UI's editMode union used "default" but config.ts canonical
      values are "review" | "auto" | "yolo". loadEditMode() coerces
      anything else to "review", so picking "default" silently wrote
      review and every checkpoint paused.
   b. Even with the right wire value, the desktop's pauseGate.on listener
      had no auto-resolve branch — only CLI TUI App.tsx did.

2. ActivePlanRail never cleared. No "plan done" signal existed; rail
   lingered after the final mark_step_complete.

Fixes:

- new src/core/pause-policy.ts — one source of truth for editMode→gate
  rules; CLI TUI App.tsx and desktop CLI listener both call
  shouldAutoResolveCheckpoint / autoResolveVerdict instead of inlining
  the same `mode === "auto" || mode === "yolo"` check
- desktop CLI listener auto-resolves plan_checkpoint via the shared
  helper, still emitting $step_completed so the rail ticks
- desktop CLI emits $plan_cleared on turn_complete when all steps done
- desktop UI: editMode union retyped to "review" | "auto" | "yolo"
  end-to-end (App, Header pill, SettingsPanel, protocol); CSS class
  .edit-pill-default renamed to .edit-pill-auto
- ActivePlanRail: optional onDismiss × button for manual clear of plans
  that arrive with no structured steps (and thus no turn_complete trigger)
@esengine esengine merged commit 0b2a295 into main May 12, 2026
2 checks passed
@esengine esengine deleted the fix/forget-stale-banner branch May 12, 2026 10:38
esengine added a commit that referenced this pull request May 12, 2026
…il, CardStream fix (#705)

npm-only release. The Tauri desktop source is in the repo and the CLI
subcommand works, but installer bundles for macOS / Windows / Linux
don't ship this round (separate release once signing's settled).

Highlights:
- Tauri desktop client with multi-tab concurrent runtimes (#689)
  plus a near-full polish pass: wallet balance, version chip, active-
  plan rail, abortable pause-gates, edit-gate pill, en + zh-CN i18n,
  shared pause-policy module dedup'd with the CLI TUI (#701)
- checkpoint API + git-changes panel in the embedded dashboard (#682)
- outside-sandbox file access approval modal (#696)
- MCP loading pill + readiness gate on tool dispatch (#687)
- escalate-after flag for flash → pro threshold (#699)

Fixes:
- CardStream Maximum-update-depth crash, quantize window so boundary
  cards stop oscillating (#700, #702)
- `reasonix code` bridges config key to env + lazy subagent client so
  fresh installs can reach the setup wizard (#703)
- pinned-mode scroll shrinks coalesced (#666), generic CSI key decode
  (#692), shell-confirm preview clamp (#691), frontmatter BOM/folded
  lines (#690), MCP error classification (#688), and more
ChasLui pushed a commit to ChasLui/DeepSeek-Reasonix that referenced this pull request May 23, 2026
…e#701)

* fix(i18n): point session banners + overflow error at /new and /sessions

The top-level /forget command was removed in the slash refactor, but
the resumed-session and new-session banners + the context-overflow
error still told users to type it. Point them at the surviving paths
instead: /new for a fresh start, /sessions ([d] to delete) for
manage / rename / drop.

Closes esengine#697

* feat(desktop): surface version + wallet balance, fix ⌘K Settings

Tauri shell had no visible version or DeepSeek balance, and ⌘K's
Settings was a stub toast despite SettingsPanel being mounted.

- $settings now carries VERSION → version chip in Sidebar brand
- new $balance event polls /user/balance on startup, after each
  turn, and after key/workspace changes → wallet card in Sidebar
- ⌘K Settings opens the existing panel; About shows real version
- ⌘K gains New/Close tab, Stop turn, Copy/Export reply, Pick workspace

* feat(desktop): localize UI strings (en + zh-CN) with live toggle

Tauri shell was a mix of English labels and Chinese hints with no
way to switch. Add a small React i18n module (localStorage + listener-
based re-render), seed en / zh-CN dictionaries, and surface a Language
picker in Settings.

- new desktop/src/i18n/{index,en,zh-CN}
- migrate ⌘K palette items, sidebar nav + wallet label, App toasts,
  composer placeholder + kbd hints, plan/choice modal placeholders
- Settings grows a Language section; auto-detect from navigator.language
  on first launch, sticky via reasonix.lang

* feat(desktop): active-plan rail + checkpoint card, abortable plan gates

Desktop dropped plan_checkpoint and plan_revision pause-gate requests on
the floor and abort only flipped the per-turn AbortController, so once
mark_step_complete fired the user was wedged with no UI response and no
way out.

- pause-gate: new cancel(id) using existing safeCancelVerdict
- desktop CLI: per-tab pendingGateIds + completedStepIds; abort now
  drains gates via cancel(id), emits $plan_cleared
- desktop CLI: emit $plan_required steps, $checkpoint_required (with
  done/total), $revision_required, $step_completed, $plan_cleared
- desktop UI: state grows activePlan, pendingCheckpoints,
  pendingRevisions; reducer wires resolve_plan(approve) → activePlan,
  resolve_revision(accepted) → swap remaining steps
- desktop UI: new ActivePlanRail above messages (collapsible, progress
  bar, per-step risk + result), CheckpointCard (continue/revise/stop),
  RevisionCard (accept/reject/cancel); Stop button in rail when busy
- i18n: plan / checkpoint / revision strings in en + zh-CN

* feat(desktop): localize Settings panel, drop ThinkingBar Stop button

Settings panel still rendered every section label, hint, and option
description in hardcoded English. Toggling the language picker did
nothing for the panel itself.

ThinkingBar had its own Stop pill on the right while the composer's
send button already turns into Stop when a turn is in flight. Two
buttons for the same action.

- migrate every SettingsSection label / hint / option name + desc
  through t(); editor presets and api-key inline buttons too
- new settings.* keys in en + zh-CN
- ThinkingBar: drop onStop prop + button + .thinking-bar-stop CSS
- App.tsx: stop passing onStop={abort} to ThinkingBar

* fix(desktop): yolo + plan-rail bugs; dedupe auto-resolve policy

Two real bugs from the desktop diverging from CLI TUI behavior:

1. YOLO still asked at every plan_checkpoint. Two causes:
   a. Desktop UI's editMode union used "default" but config.ts canonical
      values are "review" | "auto" | "yolo". loadEditMode() coerces
      anything else to "review", so picking "default" silently wrote
      review and every checkpoint paused.
   b. Even with the right wire value, the desktop's pauseGate.on listener
      had no auto-resolve branch — only CLI TUI App.tsx did.

2. ActivePlanRail never cleared. No "plan done" signal existed; rail
   lingered after the final mark_step_complete.

Fixes:

- new src/core/pause-policy.ts — one source of truth for editMode→gate
  rules; CLI TUI App.tsx and desktop CLI listener both call
  shouldAutoResolveCheckpoint / autoResolveVerdict instead of inlining
  the same `mode === "auto" || mode === "yolo"` check
- desktop CLI listener auto-resolves plan_checkpoint via the shared
  helper, still emitting $step_completed so the rail ticks
- desktop CLI emits $plan_cleared on turn_complete when all steps done
- desktop UI: editMode union retyped to "review" | "auto" | "yolo"
  end-to-end (App, Header pill, SettingsPanel, protocol); CSS class
  .edit-pill-default renamed to .edit-pill-auto
- ActivePlanRail: optional onDismiss × button for manual clear of plans
  that arrive with no structured steps (and thus no turn_complete trigger)
ChasLui pushed a commit to ChasLui/DeepSeek-Reasonix that referenced this pull request May 23, 2026
…il, CardStream fix (esengine#705)

npm-only release. The Tauri desktop source is in the repo and the CLI
subcommand works, but installer bundles for macOS / Windows / Linux
don't ship this round (separate release once signing's settled).

Highlights:
- Tauri desktop client with multi-tab concurrent runtimes (esengine#689)
  plus a near-full polish pass: wallet balance, version chip, active-
  plan rail, abortable pause-gates, edit-gate pill, en + zh-CN i18n,
  shared pause-policy module dedup'd with the CLI TUI (esengine#701)
- checkpoint API + git-changes panel in the embedded dashboard (esengine#682)
- outside-sandbox file access approval modal (esengine#696)
- MCP loading pill + readiness gate on tool dispatch (esengine#687)
- escalate-after flag for flash → pro threshold (esengine#699)

Fixes:
- CardStream Maximum-update-depth crash, quantize window so boundary
  cards stop oscillating (esengine#700, esengine#702)
- `reasonix code` bridges config key to env + lazy subagent client so
  fresh installs can reach the setup wizard (esengine#703)
- pinned-mode scroll shrinks coalesced (esengine#666), generic CSI key decode
  (esengine#692), shell-confirm preview clamp (esengine#691), frontmatter BOM/folded
  lines (esengine#690), MCP error classification (esengine#688), and more
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