mirror of
https://github.com/stablyai/orca.git
synced 2026-10-19 16:03:26 +00:00
* fix(computer): supervise desktop providers from main * fix(computer): remove unreachable provider timeout mapping * test(computer): flush stale supervisor response
127 lines
3.9 KiB
TypeScript
127 lines
3.9 KiB
TypeScript
import { afterEach, describe, expect, it } from 'vitest'
|
|
import {
|
|
createDesktopScriptProviderClient,
|
|
mockBridgeExecutionError,
|
|
mockBridgeResponse,
|
|
resetDesktopScriptProviderTestHarness,
|
|
sampleBridgeSnapshot,
|
|
sampleCapabilities
|
|
} from './desktop-script-provider-test-harness'
|
|
|
|
describe('DesktopScriptProviderClient errors and capabilities', () => {
|
|
afterEach(resetDesktopScriptProviderTestHarness)
|
|
|
|
it('explains screenshot capture failures while keeping accessibility state usable', async () => {
|
|
mockBridgeResponse({
|
|
ok: true,
|
|
snapshot: {
|
|
...sampleBridgeSnapshot('Text Editor', 'initial'),
|
|
screenshotPngBase64: null
|
|
}
|
|
})
|
|
|
|
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
|
|
|
|
await expect(client.snapshot({ app: 'Text Editor' })).resolves.toMatchObject({
|
|
snapshot: {
|
|
elementCount: 1
|
|
},
|
|
screenshotStatus: {
|
|
state: 'failed',
|
|
code: 'screenshot_failed',
|
|
message: expect.stringContaining('--no-screenshot')
|
|
}
|
|
})
|
|
})
|
|
|
|
it('preserves desktop provider screenshot failure reasons', async () => {
|
|
mockBridgeResponse({
|
|
ok: true,
|
|
snapshot: {
|
|
...sampleBridgeSnapshot('Text Editor', 'initial'),
|
|
screenshotPngBase64: null,
|
|
screenshotError: {
|
|
code: 'screenshot_failed',
|
|
message:
|
|
'screenshot exceeded the computer-use payload cap after downscaling; retry with --no-screenshot or target a smaller window'
|
|
}
|
|
}
|
|
})
|
|
|
|
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
|
|
|
|
await expect(client.snapshot({ app: 'Text Editor' })).resolves.toMatchObject({
|
|
snapshot: {
|
|
elementCount: 1
|
|
},
|
|
screenshotStatus: {
|
|
state: 'failed',
|
|
code: 'screenshot_failed',
|
|
message: expect.stringContaining('payload cap')
|
|
}
|
|
})
|
|
})
|
|
|
|
it('normalizes list-windows responses after provider handshake', async () => {
|
|
mockBridgeResponse({
|
|
ok: true,
|
|
capabilities: sampleCapabilities()
|
|
})
|
|
mockBridgeResponse({
|
|
ok: true,
|
|
app: { name: 'Text Editor', bundleIdentifier: 'Text Editor', pid: 100 },
|
|
windows: [
|
|
{
|
|
index: 0,
|
|
app: { name: 'Text Editor', bundleIdentifier: 'Text Editor', pid: 100 },
|
|
id: 99,
|
|
title: 'Document',
|
|
x: 10,
|
|
y: 20,
|
|
width: 300,
|
|
height: 200,
|
|
isMinimized: false,
|
|
isOffscreen: false,
|
|
screenIndex: null,
|
|
platform: { backend: 'at-spi' }
|
|
}
|
|
]
|
|
})
|
|
|
|
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
|
|
|
|
await expect(client.listWindows({ app: 'Text Editor' })).resolves.toMatchObject({
|
|
app: { name: 'Text Editor', bundleId: 'Text Editor', pid: 100 },
|
|
windows: [{ index: 0, id: 99, title: 'Document' }]
|
|
})
|
|
})
|
|
|
|
it('maps bridge app errors to RuntimeClientError codes', async () => {
|
|
mockBridgeResponse({ ok: false, error: 'appNotFound("Missing")' })
|
|
|
|
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
|
|
|
|
await expect(client.snapshot({ app: 'Missing' })).rejects.toMatchObject({
|
|
code: 'app_not_found'
|
|
})
|
|
})
|
|
|
|
it('maps blocked app bridge errors to a policy error', async () => {
|
|
mockBridgeResponse({ ok: false, error: 'appBlocked("1Password")' })
|
|
|
|
const client = await createDesktopScriptProviderClient('windows', '/tmp/runtime.ps1')
|
|
|
|
await expect(client.snapshot({ app: '1Password' })).rejects.toMatchObject({
|
|
code: 'app_blocked'
|
|
})
|
|
})
|
|
|
|
it('maps supervised provider process failures', async () => {
|
|
mockBridgeExecutionError('appNotFound("Missing")')
|
|
|
|
const client = await createDesktopScriptProviderClient('linux', '/tmp/runtime.py')
|
|
|
|
await expect(client.listApps()).rejects.toMatchObject({ code: 'app_not_found' })
|
|
})
|
|
})
|