Files
orca/src/main/computer/desktop-script-provider-cache.test.ts
T
2026-06-07 17:49:01 -07:00

320 lines
8.9 KiB
TypeScript

import { afterEach, describe, expect, it } from 'vitest'
import {
createDesktopScriptProviderClient,
mockBridgeResponse,
resetDesktopScriptProviderTestHarness,
sampleBridgeSnapshot,
sampleCapabilities
} from './desktop-script-provider-test-harness'
describe('DesktopScriptProviderClient snapshot cache', () => {
afterEach(resetDesktopScriptProviderTestHarness)
it('targets cached ID-less snapshots by their provider window index on follow-up actions', async () => {
mockBridgeResponse({
ok: true,
snapshot: {
...sampleBridgeSnapshot('Text Editor', 'initial'),
windowId: null,
windowIndex: 3
}
})
mockBridgeResponse({
ok: true,
capabilities: sampleCapabilities()
})
mockBridgeResponse(
{
ok: true,
snapshot: {
...sampleBridgeSnapshot('Text Editor', 'changed'),
windowId: null,
windowIndex: 3
}
},
(operation) => {
expect(operation).toMatchObject({
tool: 'set_value',
app: 'Text Editor',
windowIndex: 3,
element: expect.objectContaining({ index: 0 })
})
expect(operation.windowId).toBeUndefined()
}
)
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
await client.snapshot({ app: 'Text Editor' })
await client.action('setValue', {
app: 'Text Editor',
elementIndex: 0,
value: 'changed',
noScreenshot: true
})
})
it('aliases provider window indexes for explicit follow-up actions after an ID-less snapshot', async () => {
mockBridgeResponse({
ok: true,
snapshot: {
...sampleBridgeSnapshot('Text Editor', 'initial'),
windowId: null,
windowIndex: 3
}
})
mockBridgeResponse({
ok: true,
capabilities: sampleCapabilities()
})
mockBridgeResponse(
{
ok: true,
snapshot: {
...sampleBridgeSnapshot('Text Editor', 'changed'),
windowId: null,
windowIndex: 3
}
},
(operation) => {
expect(operation).toMatchObject({
tool: 'set_value',
windowIndex: 3,
element: expect.objectContaining({ index: 0 })
})
expect(operation.windowId).toBeUndefined()
}
)
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
await client.snapshot({ app: 'Text Editor' })
await client.action('setValue', {
app: 'Text Editor',
windowIndex: 3,
elementIndex: 0,
value: 'changed',
noScreenshot: true
})
})
it('aliases cached snapshots by documented pid selector for follow-up actions', async () => {
mockBridgeResponse({
ok: true,
snapshot: sampleBridgeSnapshot('Text Editor', 'initial')
})
mockBridgeResponse({
ok: true,
capabilities: sampleCapabilities()
})
mockBridgeResponse(
{
ok: true,
snapshot: sampleBridgeSnapshot('Text Editor', 'changed')
},
(operation) => {
expect(operation).toMatchObject({
tool: 'set_value',
app: 'pid:100',
windowId: 99,
element: expect.objectContaining({ index: 0 })
})
}
)
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
await client.snapshot({ app: 'Text Editor' })
await client.action('setValue', {
app: 'pid:100',
elementIndex: 0,
value: 'changed',
noScreenshot: true
})
})
it('aliases cached window-index snapshots by documented pid selector', async () => {
mockBridgeResponse({
ok: true,
snapshot: {
...sampleBridgeSnapshot('Text Editor', 'initial'),
windowId: null,
windowIndex: 3
}
})
mockBridgeResponse({
ok: true,
capabilities: sampleCapabilities()
})
mockBridgeResponse(
{
ok: true,
snapshot: {
...sampleBridgeSnapshot('Text Editor', 'changed'),
windowId: null,
windowIndex: 3
}
},
(operation) => {
expect(operation).toMatchObject({
tool: 'set_value',
app: 'pid:100',
windowIndex: 3,
element: expect.objectContaining({ index: 0 })
})
expect(operation.windowId).toBeUndefined()
}
)
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
await client.snapshot({ app: 'Text Editor', windowIndex: 3 })
await client.action('setValue', {
app: 'pid:100',
windowIndex: 3,
elementIndex: 0,
value: 'changed',
noScreenshot: true
})
})
it('does not alias cached snapshots by invalid provider pids', async () => {
mockBridgeResponse({
ok: true,
snapshot: {
...sampleBridgeSnapshot('Text Editor', 'initial'),
app: { name: 'Text Editor', bundleIdentifier: 'Text Editor', pid: 0 }
}
})
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
await client.snapshot({ app: 'Text Editor' })
const cacheKeys = [
...(client as unknown as { snapshots: Map<string, unknown> }).snapshots.keys()
]
expect(cacheKeys).not.toContain('pid:0')
expect(cacheKeys).not.toContain('default:pid:0')
expect(cacheKeys).not.toContain('0')
expect(cacheKeys).not.toContain('default:0')
})
it('drops focused element ids that are not present in the rendered element records', async () => {
mockBridgeResponse({
ok: true,
snapshot: {
...sampleBridgeSnapshot('Text Editor', 'initial'),
focusedElementId: 99
}
})
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
const result = await client.snapshot({ app: 'Text Editor' })
expect(result.snapshot.focusedElementId).toBeNull()
})
it('does not retain screenshot bytes in the follow-up action cache', async () => {
const largeScreenshot = 'x'.repeat(1024 * 1024)
mockBridgeResponse({
ok: true,
snapshot: {
...sampleBridgeSnapshot('Text Editor', 'initial'),
screenshotPngBase64: largeScreenshot
}
})
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
const result = await client.snapshot({ app: 'Text Editor' })
const cached = [
...(
client as unknown as { snapshots: Map<string, { screenshotPngBase64?: string | null }> }
).snapshots.values()
]
expect(result.screenshot?.data).toBe(largeScreenshot)
expect(cached.length).toBeGreaterThan(0)
expect(cached.every((snapshot) => snapshot.screenshotPngBase64 === null)).toBe(true)
})
it('targets cached elements by session and window id after observe without a window selector', async () => {
mockBridgeResponse({
ok: true,
snapshot: sampleBridgeSnapshot('Text Editor', 'initial')
})
mockBridgeResponse({
ok: true,
capabilities: sampleCapabilities()
})
mockBridgeResponse(
{
ok: true,
snapshot: sampleBridgeSnapshot('Text Editor', 'changed')
},
(operation) => {
expect(operation).toMatchObject({
tool: 'click',
app: 'Text Editor',
windowId: 99,
element: expect.objectContaining({ index: 0 })
})
}
)
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
await client.snapshot({ app: 'Text Editor', session: 'agent-a' })
await client.action('click', {
app: 'Text Editor',
session: 'agent-a',
windowId: 99,
elementIndex: 0,
noScreenshot: true
})
})
it('targets cached elements by session and explicit window index without forwarding window id', async () => {
mockBridgeResponse({
ok: true,
snapshot: sampleBridgeSnapshot('Text Editor', 'initial')
})
mockBridgeResponse({
ok: true,
capabilities: sampleCapabilities()
})
mockBridgeResponse(
{
ok: true,
snapshot: sampleBridgeSnapshot('Text Editor', 'changed')
},
(operation) => {
expect(operation).toMatchObject({
tool: 'drag',
app: 'Text Editor',
windowIndex: 0,
fromElement: expect.objectContaining({ index: 0 }),
toElement: expect.objectContaining({ index: 0 })
})
expect(operation.windowId).toBeUndefined()
expect(operation.from_x).toBeUndefined()
expect(operation.to_x).toBeUndefined()
expect(operation.windowBounds).toBeNull()
}
)
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
await client.snapshot({ app: 'Text Editor', session: 'agent-a', windowIndex: 0 })
await client.action('drag', {
app: 'Text Editor',
session: 'agent-a',
windowIndex: 0,
fromElementIndex: 0,
toElementIndex: 0
})
})
})