feat: computer use via agent-browser CDP bridge (#856)

This commit is contained in:
Jinwoo Hong
2026-04-20 20:56:14 -07:00
committed by GitHub
parent 22ae50e0ae
commit 7a9bc4ef6d
35 changed files with 13560 additions and 43 deletions
+154
View File
@@ -764,4 +764,158 @@ describe('OrcaRuntimeService', () => {
}
])
})
describe('browser page targeting', () => {
it('passes explicit page ids through without resolving the current worktree', async () => {
vi.mocked(listWorktrees).mockClear()
const runtime = createRuntime()
const snapshotMock = vi.fn().mockResolvedValue({
browserPageId: 'page-1',
snapshot: 'tree',
refs: [],
url: 'https://example.com',
title: 'Example'
})
runtime.setAgentBrowserBridge({
snapshot: snapshotMock
} as never)
const result = await runtime.browserSnapshot({ page: 'page-1' })
expect(result.browserPageId).toBe('page-1')
expect(snapshotMock).toHaveBeenCalledWith(undefined, 'page-1')
expect(listWorktrees).not.toHaveBeenCalled()
})
it('resolves explicit worktree selectors when page ids are also provided', async () => {
vi.mocked(listWorktrees).mockClear()
const runtime = createRuntime()
const snapshotMock = vi.fn().mockResolvedValue({
browserPageId: 'page-1',
snapshot: 'tree',
refs: [],
url: 'https://example.com',
title: 'Example'
})
runtime.setAgentBrowserBridge({
snapshot: snapshotMock,
getRegisteredTabs: vi.fn(() => new Map([['page-1', 1]]))
} as never)
await runtime.browserSnapshot({
worktree: 'branch:feature/foo',
page: 'page-1'
})
expect(snapshotMock).toHaveBeenCalledWith(TEST_WORKTREE_ID, 'page-1')
})
it('routes tab switch and capture start by explicit page id', async () => {
const runtime = createRuntime()
const tabSwitchMock = vi.fn().mockResolvedValue({
switched: 2,
browserPageId: 'page-2'
})
const captureStartMock = vi.fn().mockResolvedValue({
capturing: true
})
runtime.setAgentBrowserBridge({
tabSwitch: tabSwitchMock,
captureStart: captureStartMock
} as never)
await expect(runtime.browserTabSwitch({ page: 'page-2' })).resolves.toEqual({
switched: 2,
browserPageId: 'page-2'
})
await expect(runtime.browserCaptureStart({ page: 'page-2' })).resolves.toEqual({
capturing: true
})
expect(tabSwitchMock).toHaveBeenCalledWith(undefined, undefined, 'page-2')
expect(captureStartMock).toHaveBeenCalledWith(undefined, 'page-2')
})
it('does not silently drop invalid explicit worktree selectors for page-targeted commands', async () => {
vi.mocked(listWorktrees).mockResolvedValue(MOCK_GIT_WORKTREES)
const runtime = createRuntime()
const snapshotMock = vi.fn()
runtime.setAgentBrowserBridge({
snapshot: snapshotMock,
getRegisteredTabs: vi.fn(() => new Map([['page-1', 1]]))
} as never)
await expect(
runtime.browserSnapshot({
worktree: 'path:/tmp/missing-worktree',
page: 'page-1'
})
).rejects.toThrow('selector_not_found')
expect(snapshotMock).not.toHaveBeenCalled()
})
it('does not silently drop invalid explicit worktree selectors for non-page browser commands', async () => {
vi.mocked(listWorktrees).mockResolvedValue(MOCK_GIT_WORKTREES)
const runtime = createRuntime()
const tabListMock = vi.fn()
runtime.setAgentBrowserBridge({
tabList: tabListMock
} as never)
await expect(
runtime.browserTabList({
worktree: 'path:/tmp/missing-worktree'
})
).rejects.toThrow('selector_not_found')
expect(tabListMock).not.toHaveBeenCalled()
})
it('rejects closing an unknown page id instead of treating it as success', async () => {
vi.mocked(listWorktrees).mockResolvedValue(MOCK_GIT_WORKTREES)
const runtime = createRuntime()
runtime.setAgentBrowserBridge({
getRegisteredTabs: vi.fn(() => new Map([['page-1', 1]]))
} as never)
await expect(
runtime.browserTabClose({
page: 'missing-page'
})
).rejects.toThrow('Browser page missing-page was not found')
})
it('rejects closing a page outside the explicitly scoped worktree', async () => {
vi.mocked(listWorktrees).mockResolvedValue([
...MOCK_GIT_WORKTREES,
{
path: '/tmp/worktree-b',
head: 'def',
branch: 'feature/bar',
isBare: false,
isMainWorktree: false
}
])
const runtime = createRuntime()
const getRegisteredTabsMock = vi.fn((worktreeId?: string) =>
worktreeId === `${TEST_REPO_ID}::/tmp/worktree-b` ? new Map() : new Map([['page-1', 1]])
)
runtime.setAgentBrowserBridge({
getRegisteredTabs: getRegisteredTabsMock
} as never)
await expect(
runtime.browserTabClose({
page: 'page-1',
worktree: 'path:/tmp/worktree-b'
})
).rejects.toThrow('Browser page page-1 was not found in this worktree')
expect(getRegisteredTabsMock).toHaveBeenCalledWith(`${TEST_REPO_ID}::/tmp/worktree-b`)
})
})
})