Skip to content

feat: tool metadata cache, tool call toggle, stale-closure fix, and perf optimizations#479

Merged
shanselman merged 3 commits into
openclaw:masterfrom
christineyan4:christiney/chat-caching
May 21, 2026
Merged

feat: tool metadata cache, tool call toggle, stale-closure fix, and perf optimizations#479
shanselman merged 3 commits into
openclaw:masterfrom
christineyan4:christiney/chat-caching

Conversation

@christineyan4
Copy link
Copy Markdown
Contributor

Summary

Improves the chat experience with tool call caching, a toggle UI, and critical bug fixes.

Tool Metadata Cache

  • Persists tool call metadata (name, label, timestamp) to disk so flattened tool outputs from gateway history replay can be recovered with proper tool names/icons
  • Sequential order matching between cache and history entries
  • Session limits (20 sessions, 500 entries per session)
  • Debounced saves (500ms quiescence timer) to prevent concurrent file writes
  • Atomic file writes (write .tmp then File.Move) to prevent partial JSON on crash

Tool Call Toggle

  • Wrench icon in the toolbar to show/hide tool calls in chat
  • 0.55 opacity when hidden, full opacity when shown
  • Tooltips on all toolbar buttons for accessibility
  • Collapses all expanded tool chips when hiding

Stale-Closure Fix (Critical)

  • Fixed a bug where UseState closures in ChatExplorationState.Changed handlers captured the initial value (0), causing Set(1) to be a no-op after the first toggle
  • Affected all 4 components: Timeline, Composer, ChatRoot, ExplorationsPanel
  • Fixed with UseRef-based counter pattern

Performance Optimizations

  • Pre-clear native StackPanel before render so SyncChildren only does inserts
  • SyncChildren fast path for empty panels (skip RemoveFromParent scans)
  • ChatRoot reads explorationRevRef.Current inside dispatcher lambda

Tests

  • 19 new tests (1161 total): ToolMetaCacheTests (sequential matching, exhaustion, guards), classifier edge cases
  • All existing tests pass

Other

  • ChatPage NavigationCacheMode=Enabled, suppressAutoDispose on FunctionalHostControl
  • Improved ClassifyFlattenedToolOutput heuristics (bash, view, grep, git, edit, glob detection)

Christine Yan and others added 3 commits May 20, 2026 17:34
- Cache tool metadata (name, label) to local JSON so tool call types
  persist across app restarts instead of falling back to 'exec'
- Improve ClassifyFlattenedToolOutput heuristic to detect bash, view,
  grep, git, edit, glob from output text patterns
- Add tool call show/hide toggle button to composer toolbar with
  tooltips on all toolbar buttons
- Add CompactSummary as default tool burst style with expand/collapse
- Fix stale-closure bug in ChatExplorationState.Changed handlers
  across Timeline, Composer, ChatRoot, and ExplorationsPanel — event
  handler captured initial UseState value (0), so Set(1) only triggered
  one re-render; subsequent toggles were no-ops
- Optimize SyncChildren with fast path for empty panels (skip
  RemoveFromParent O(n) scan) and pre-clear panel on visibility toggle
- Enable NavigationCacheMode on ChatPage to avoid full reload on
  navigation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tests

- Debounce SaveToolMetaCache with 500ms timer instead of Task.Run per event
- Atomic file write (write .tmp then File.Move) to prevent partial JSON
- ChatRoot: read explorationRevRef.Current inside dispatcher lambda
- Revert in-place HashSet mutation to proper Set(new HashSet)
- Add ToolMetaCacheTests (10 tests): sequential matching, exhaustion, guards
- Add classifier edge case tests (9 tests): view, git, exec defaults

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move tool metadata timer replacement under the provider lock, version debounced saves so stale timer callbacks cannot overwrite newer snapshots, and serialize unique-temp-file writes to avoid cache corruption under rapid tool events.

Add coverage that concurrent metadata additions flush complete valid JSON without leaving temporary files behind.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@shanselman
Copy link
Copy Markdown
Contributor

@christineyan4 I found and pushed a fix for the tool metadata cache race I was worried about. The new commit serializes debounced saves, uses unique temp files for atomic writes, prevents stale timer callbacks from overwriting newer snapshots, flushes on provider disposal, and adds a concurrent-cache test that verifies complete valid JSON with no leftover temp files.\n\nLocal validation on the pushed branch: ./build.ps1, dotnet test ./tests/OpenClaw.Shared.Tests/OpenClaw.Shared.Tests.csproj --no-restore, and dotnet test ./tests/OpenClaw.Tray.Tests/OpenClaw.Tray.Tests.csproj --no-restore all passed.

@shanselman shanselman merged commit 9478e95 into openclaw:master May 21, 2026
11 checks passed
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.

2 participants