UI TestEngine: add listAllEntries for one-shot flat tree dump#5967
Merged
Conversation
Walking the UI tree via `ui.listEntries` costs 4-5 sequential round-
trips to reach a known widget. The new `ui.listAllEntries` MCP tool
(plus Python mirror `uiListAllEntries`) returns every entry in the
subtree at `path` (default empty = whole tree) as a flat depth-first
list of `(path, TypedEntry)` pairs — groups appear in the list with
their descendants on subsequent rows, so the tree structure is
recoverable from the flat output. `TypedEntry` and `ui.listEntries`
are untouched — purely additive.
- `PathedEntry = pair<vector<string>, TypedEntry>` alias in
MRUITestEngineControl.h keeps the signature readable.
- `typeOf(Entry)` factored out so `listEntries` and the new walker
share the variant switch; `mcpTypeStr(EntryType)` factored out so
the old and new MCP handlers share the enum-to-string.
- pybind11 auto-converts `pair` to tuple and `vector<pair<…>>` to
list of tuples — no new binding class needed.
Output schema: `Array(Object{path, name, type, status})`. Declared
recursive `children`-tree schemas in `Mcp::Schema` aren't supported
(no `\$ref`), and the flat-with-path form sidesteps that entirely
while remaining trivially serializable.
Live-verified via MCP on a default-state viewer:
* 84 entries returned, 9857 bytes serialized (under the 10 KB budget).
* Identical set of `(path, type)` tuples to a recursive
`ui.listEntries` walk (0 missing, 0 extra, 0 status drift).
* Subtree rooting at `["QuickAccess"]` returns 9 entries all with the
correct prefix; first-level matches `ui.listEntries` at that path.
* Bogus path returns the same "No such entry" error as `listEntries`.
* Omitting `path` defaults to empty (whole tree).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fedr
approved these changes
Apr 23, 2026
oitel
approved these changes
Apr 23, 2026
Signed-off-by: Grant Karapetyan <grant.karapetyan@meshinspector.com>
Master's #5968 landed while this PR was in review and refactored `composeStatus` to a single-argument form (blocking-modal formatting moved into `effectiveDisabledReason` upstream, and `rootLevelBlocked`/ `topBlockingModalName` were removed from this TU). Update `walkAll` and `listAllEntries` accordingly: - drop the `rootBlockingModal` and `isRootLevel` parameters from `walkAll` — every entry just calls `composeStatus(entryDisabledReason)` with the new 1-arg form; - drop the `blockingModal` local in `listAllEntries`. Side benefit: descendants now also surface `"disabled: blocked by modal '<name>'"` when applicable (previously the old 2-arg path special-cased only root-level entries; with the upstream refactor that special case is obsolete). Fixes the emscripten + macOS arm64 Release CI failures on this PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ui.listEntriescosts 4–5 sequential round-trips to reach a known widget. This PR addsui.listAllEntries(MCP) +uiListAllEntries(Python) returning every entry in the subtree atpath(default empty → whole tree) as a flat depth-first list of(path, TypedEntry)pairs. Groups appear in the list and their descendants follow on subsequent rows, so the tree structure is recoverable from the flat output.TypedEntryandui.listEntriesare unchanged — purely additive.Design notes
PathedEntry = std::pair<std::vector<std::string>, TypedEntry>alias inMRUITestEngineControl.hkeeps the signature readable.typeOf(Entry)inMRUITestEngineControl.cppso the flatlistEntriesand the new recursive walker share the variant switch.mcpTypeStr(EntryType)inMRViewerMcp.cppso the old and new MCP handlers share the enum→string.pair→ tuple andvector<pair<…>>→ list of tuples; no new binding class needed.Array(Object{path, name, type, status}).Mcp::Schemahas no$reffor recursive children, but the flat-with-path shape sidesteps that and is trivially serializable.Test plan
Live-verified end-to-end against a freshly-built MeshInspector via the MCP SSE endpoint:
ui.listAllEntries({path:[]})returns 84 entries, 9857 bytes serialized (under the ~10 KB budget from the plan).(path, type)tuples as a recursive walk viaui.listEntries— 0 missing, 0 extra, 0 status drift.["QuickAccess"]returns 9 entries all with the correctpathprefix; first-level set matchesui.listEntriesat the same path.pathreturns the same"No such entry: \…`. Known entries are: …"error shape aslistEntries(sharedfindGroup` helper).pathdefaults to empty (whole tree).tools/listshowsui.listAllEntriesregistered alongside the other 10ui.*tools.🤖 Generated with Claude Code