Repository navigation
feat: read a table, outline or grid as columns and rows with each row's element ID - #86
Merged
Merged
Conversation
This was referenced Oct 17, 2026
This was referenced Oct 17, 2026
Merged
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.
desktop_readwithtable: trueand ascopereads a table instead of text. It covers awkward item 5 in #75.What it returns
Which table. The scope is a table, outline or grid (AXTable, AXOutline, AXGrid; web tables and ARIA grids are AXTable), or an area that holds one, such as a scroll area or web area. The first table in it is read, and
tables_in_scopecounts the others.columns. The header titles, taken from the first of these that exists:Otherwise it is
null.rows. Each row has:cells: each cell's Accessibility text, in column order;element: the row's ID in the scope snapshot, fordesktop_click;selected;depth(0 at the top level) andexpanded.Counts.
row_countandrow_offset, plustruncated/truncation(row_limit,column_limit,cell_text_limit,text_limit,field_text_limit,output_limit, and the traversal's own limits).Bounds.
max_rowsdefaults to 100, at most 500, androw_offsetpages through. Cells are cut to 256 characters, rows to 64 cells, and a page to 96 KB of cell text. Native fields are cut to 512 characters and the native reply to 1.5 MB.How
tableread. It reads Accessibility only (inspectAccessibilityTree) withdesktop_read's wide budget, so there is no capture and no new snapshot. It finds the scope element again exactly as scoped read and inspect do, and returns the subtree as flat elements.null. The note says to inspect again withscopeset to the table, since a whole-window inspection stores only 200 elements.src/table.tsbuilds the table from the flat list, which keeps it testable on fixtures.peekaboo-row-disclosure.patch, last in the stack. Outline rows are flat siblings in AX, so the observation worker now addsdisclosureLevelanddisclosingto AXRow elements. It makes one extra read each, only for rows. No Bridge op is added. A worker test is included.Checks
npm run checkpasses.npm testpasses 33, includingtest/table.test.mjswith fixtures for:The tests also cover paging and every limit.
The Peekaboo
DetachedAXObservationWorkerTestssuite passes (33 tests, including the new disclosure test).Native and the signed dev app build. Smoke test against the dev app: a bogus scope snapshot is refused by the host, and a table read without a scope is refused.
Live checks are pending (screen locked). While the session is locked, AX returns no elements at all, so the fixtures model the standard AppKit and WebKit shapes; I couldn't survey them. The live checks in Run the live checks deferred while the screen was locked #42 will confirm or correct three assumptions: