Skip to content

Commit d9e91f8

Browse files
committed
fix(computer-use): keep disabled layout groups in the model's accessibility tree
1 parent 2bd3203 commit d9e91f8

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

‎apps/sim/lib/mothership/tools/client/computer-tool-result.test.ts‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,34 @@ describe('native computer model projection', () => {
227227
expect(result.omittedNodeCount).toBe(0)
228228
})
229229

230+
it('keeps an empty layout group that reports itself disabled', () => {
231+
const state = snapshot()
232+
state.nodes = [
233+
{ elementId: 'window', role: 'AXWindow', label: 'Fixture', actions: [], windowId: '1' },
234+
{
235+
elementId: 'pane',
236+
parentId: 'window',
237+
role: 'AXGroup',
238+
enabled: false,
239+
actions: [],
240+
windowId: '1',
241+
},
242+
{
243+
elementId: 'save',
244+
parentId: 'pane',
245+
role: 'AXButton',
246+
label: 'Save',
247+
actions: ['AXPress'],
248+
windowId: '1',
249+
},
250+
]
251+
const result = computerToolResultForModel(state)
252+
if (!('accessibilityTree' in result)) throw new Error('Missing projected tree')
253+
const rows = result.accessibilityTree.split('\n')
254+
expect(rows.find((row) => row.startsWith('pane '))).toContain('disabled')
255+
expect(rows.find((row) => row.startsWith('save '))).toContain('parent=pane')
256+
})
257+
230258
it('does not split an emoji when bounding text for the model', () => {
231259
const state = snapshot()
232260
state.nodes[0] = {

‎apps/sim/lib/mothership/tools/client/computer-tool-result.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function jsonBytes(value: unknown): number {
2626

2727
type SnapshotNode = ComputerUseSnapshot['nodes'][number]
2828

29-
/** Layout wrappers that carry no text, state or action; their children are shown under the nearest meaningful ancestor. */
29+
/** Layout wrappers that carry no text, state (including disabled) or action; their children are shown under the nearest meaningful ancestor. */
3030
const WRAPPER_ROLES = new Set([
3131
'AXGroup',
3232
'AXSplitGroup',
@@ -43,6 +43,7 @@ function isWrapper(node: SnapshotNode): boolean {
4343
!node.placeholder &&
4444
!node.focused &&
4545
!node.editable &&
46+
node.enabled !== false &&
4647
node.actions.length === 0
4748
)
4849
}

0 commit comments

Comments
 (0)