Skip to content

fix(desktop): reduce idle polling and checkpoint turns - #9731

Open
wqshan-cn wants to merge 5 commits into
esengine:main-v2from
wqshan-cn:fix/idle-background-runtime-poll
Open

fix(desktop): reduce idle polling and checkpoint turns#9731
wqshan-cn wants to merge 5 commits into
esengine:main-v2from
wqshan-cn:fix/idle-background-runtime-poll

Conversation

@wqshan-cn

@wqshan-cn wqshan-cn commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Improve two desktop reliability paths:

Changes

  • Keep TurnStarted as a lifecycle signal, then emit turn_phase=working only after the user message is in the session; desktop autosave checkpoints that post-append boundary.
  • Keep streaming deltas out of autosave while checkpointing tool results, prompts, compaction completion, committed user-turn state, and TurnDone.
  • TurnDone persistence barrier: Emit(TurnDone) now waits until (a) the autosave loop drains its current write plus any queued saveAgain pass (waitForTabSnapshot), and (b) the flushed display-only text finishes its current persist attempt including bounded retries (waitForPendingDisplayWrites). A process exit immediately after a completed turn can no longer lose the final transcript. Mid-turn checkpoint events stay asynchronous — no per-token disk writes.
  • Add a single-flight background runtime refresh coordinator.
  • Stop fallback polling when no background runtime is active; use a 5-second fallback while work remains.
  • Retry transient bridge failures with bounded exponential backoff and handle internal Promise rejections.
  • Order-insensitive runtime comparison: the backend builds BackgroundRuntimes from Go maps whose iteration order is unstable, so sameBackgroundRuntimeLists now compares by tabId instead of by array position; identical runtimes no longer trigger redundant React state updates.
  • Prevent overlapping WorkspaceConflictForTab requests and lower its fallback cadence to 1.5 seconds.
  • Ignore late results after coordinator disposal and avoid redundant React state updates.
  • Add regression tests: session content is readable from disk immediately after Emit(TurnDone) returns (TestTurnDoneWaitBlocksUntilSnapshotWritten), and reordered identical runtime lists compare equal.

Verification

  • go test ./internal/agent ./internal/control -count=1 passed (after rebase onto upstream/main-v2@c01ec347b).
  • Focused desktop autosave tests passed, including the new persistence-barrier regression test, TestScheduleSnapshotCoalesces, TestCloseTabNoResurrectionFromAutosave, and the cannot-persist guard tests.
  • background-runtime-refresh.test.ts passed (including the new order-insensitivity assertion).
  • tsc --noEmit passed after regenerating the local (gitignored) Wails bindings for this branch — earlier failures came from stale generated bindings left behind by the feat(subagents): allow per-profile max-steps cap #9659 work, not from PR code.
  • ESLint passed for changed frontend files. git diff --check passed.

Documentation-impact: none - this change affects internal desktop polling and persistence behavior; existing user-facing documentation does not describe these implementation details.

Cache-impact: none - no provider prompt, tool schema, or cache-prefix behavior changes.

Cache-guard: go test ./internal/agent ./internal/control -count=1, the focused desktop autosave tests (including the new TestTurnDoneWaitBlocksUntilSnapshotWritten barrier regression), and background-runtime-refresh.test.ts cover checkpoint ordering, the TurnDone persistence barrier, order-insensitive runtime comparison, refresh coalescing, retry behavior, and disposal.

System-prompt-review: no system-prompt or agent-instruction templates are touched; all changes are desktop event-sink persistence, autosave scheduling, and frontend refresh coordination.

@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development desktop Wails desktop app (desktop/**) labels Sep 2, 2026
@wqshan-cn
wqshan-cn force-pushed the fix/idle-background-runtime-poll branch 2 times, most recently from 7e96905 to 52ac7c9 Compare September 4, 2026 10:56
@github-actions github-actions Bot added the agent Core agent loop (internal/agent, internal/control) label Sep 4, 2026
Emit(TurnDone) returned as soon as the final snapshot was scheduled, so a
process exit immediately after a completed turn could lose the last
transcript: the autosave loop and the display-only write retry goroutine
were still running in the background.

- add waitForTabSnapshot: TurnDone waits until the autosave loop drains
  its current write and any queued saveAgain pass
- add waitForPendingDisplayWrites: TurnDone also waits for the flushed
  display-only text to finish its current persist attempt (bounded
  retries); mid-turn checkpoint events stay asynchronous
- compare background runtime lists order-insensitively by tabId; the
  backend iterates a map, so identical runtimes in a different order
  must not trigger React state updates
- regression tests: session content readable immediately after
  Emit(TurnDone) returns; reordered identical runtime lists compare equal
@wqshan-cn
wqshan-cn force-pushed the fix/idle-background-runtime-poll branch from 52ac7c9 to 6a2d086 Compare September 5, 2026 01:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Core agent loop (internal/agent, internal/control) desktop Wails desktop app (desktop/**) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: 桌面端会话持久化缺陷——仅TurnDone异步保存,长对话中间状态与版本更新时数据丢失

1 participant