diff --git a/services/computer-use-mcp/src/bin/smoke-workflow.ts b/services/computer-use-mcp/src/bin/smoke-workflow.ts index 47563bdf8..f9d6e5f52 100644 --- a/services/computer-use-mcp/src/bin/smoke-workflow.ts +++ b/services/computer-use-mcp/src/bin/smoke-workflow.ts @@ -44,7 +44,7 @@ function requireStructuredContent(result: unknown, label: string) { return structuredContent as Record } -function assert(condition: boolean, message: string) { +function assert(condition: boolean, message: string): asserts condition { if (!condition) { throw new Error(`Assertion failed: ${message}`) } diff --git a/services/computer-use-mcp/src/browser-dom/extension-bridge.test.ts b/services/computer-use-mcp/src/browser-dom/extension-bridge.test.ts index aa7ba8fe8..aff65ee40 100644 --- a/services/computer-use-mcp/src/browser-dom/extension-bridge.test.ts +++ b/services/computer-use-mcp/src/browser-dom/extension-bridge.test.ts @@ -317,14 +317,14 @@ describe('browserDomExtensionBridge', () => { bridge = result.bridge client = result.client - client.on('message', (raw) => { + client!.on('message', (raw) => { const data = JSON.parse(String(raw)) as Record if (typeof data.id !== 'string') return if (data.action !== 'getActiveTab') return - client.send(JSON.stringify({ + client!.send(JSON.stringify({ id: data.id, ok: false, error: 'unknown action: getActiveTab', diff --git a/services/computer-use-mcp/src/chrome-session-manager.test.ts b/services/computer-use-mcp/src/chrome-session-manager.test.ts index 699942c8d..f980310ed 100644 --- a/services/computer-use-mcp/src/chrome-session-manager.test.ts +++ b/services/computer-use-mcp/src/chrome-session-manager.test.ts @@ -14,6 +14,7 @@ import { createServer } from 'node:net' import { beforeEach, describe, expect, it, vi } from 'vitest' import { createChromeSessionManager } from './chrome-session-manager' +import { createTestConfig } from './test-fixtures' import { runProcess } from './utils/process' vi.mock('node:fs/promises', () => ({ @@ -39,7 +40,7 @@ const mockedWriteFile = vi.mocked(writeFile) const mockedCreateServer = vi.mocked(createServer) function makeConfig(): ComputerUseConfig { - return { + return createTestConfig({ executor: 'macos-local', sessionTag: 'test', sessionRoot: '/tmp/test', @@ -51,10 +52,14 @@ function makeConfig(): ComputerUseConfig { screencapture: '/usr/sbin/screencapture', open: '/usr/bin/open', osascript: '/usr/bin/osascript', + pbcopy: 'pbcopy', + pbpaste: 'pbpaste', + ssh: 'ssh', + tar: 'tar', }, - browserDomBridge: { enabled: false }, + browserDomBridge: { enabled: false, host: '127.0.0.1', port: 8765, requestTimeoutMs: 10_000 }, openableApps: [], - } as ComputerUseConfig + }) } function ok(stdout = ''): any { diff --git a/services/computer-use-mcp/src/chrome-session-manager.ts b/services/computer-use-mcp/src/chrome-session-manager.ts index 6f15bad15..50d70e3c2 100644 --- a/services/computer-use-mcp/src/chrome-session-manager.ts +++ b/services/computer-use-mcp/src/chrome-session-manager.ts @@ -375,7 +375,7 @@ export function createChromeSessionManager( createdAt: new Date().toISOString(), } - return session + return session! } catch (error) { await findAndTerminateChromeByProfile(activeProfileDir, cdpPort) diff --git a/services/computer-use-mcp/src/policy.ts b/services/computer-use-mcp/src/policy.ts index b04307513..343fd08ba 100644 --- a/services/computer-use-mcp/src/policy.ts +++ b/services/computer-use-mcp/src/policy.ts @@ -105,7 +105,7 @@ export function evaluateActionPolicy(params: { operationUnitsConsumed: number }): PolicyDecision { const reasons: string[] = [] - const estimatedOperationUnits = estimateOperationUnits(params.action) + const estimatedOperationUnits = estimateOperationUnits(params.action)! const mutating = isMutatingAction(params.action) let allowed = true let requiresApproval = false diff --git a/services/computer-use-mcp/src/server/action-executor.ts b/services/computer-use-mcp/src/server/action-executor.ts index 3ff02cb64..adc972078 100644 --- a/services/computer-use-mcp/src/server/action-executor.ts +++ b/services/computer-use-mcp/src/server/action-executor.ts @@ -508,20 +508,20 @@ export function createExecuteAction(runtime: ComputerUseServerRuntime): ExecuteA if (hasExplicitCoordinates) { const pointerTrace = buildPointerTrace({ from: runtime.session.getPointerPosition(), - to: { x: normalizedAction.input.x, y: normalizedAction.input.y }, + to: { x: normalizedAction.input.x!, y: normalizedAction.input.y! }, bounds: runtime.config.allowedBounds, }) // NOTICE: The preparatory click must succeed before we type. // If focus fails the text would go to the wrong element. try { await runtime.executor.click({ - x: normalizedAction.input.x, - y: normalizedAction.input.y, + x: normalizedAction.input.x!, + y: normalizedAction.input.y!, button: 'left', clickCount: 1, pointerTrace, }) - runtime.session.setPointerPosition({ x: normalizedAction.input.x, y: normalizedAction.input.y }) + runtime.session.setPointerPosition({ x: normalizedAction.input.x!, y: normalizedAction.input.y! }) backendResult.focusPointerTrace = pointerTrace backendResult.focusDisplayPoint = structuredDisplayPoint } diff --git a/services/computer-use-mcp/src/server/register-chrome-session.test.ts b/services/computer-use-mcp/src/server/register-chrome-session.test.ts index 5341b4a3a..451d52884 100644 --- a/services/computer-use-mcp/src/server/register-chrome-session.test.ts +++ b/services/computer-use-mcp/src/server/register-chrome-session.test.ts @@ -152,6 +152,7 @@ describe('registerChromeSessionTools', () => { it('consumes operation budget and persists chrome session when approvals are disabled', async () => { vi.mocked(runtime.chromeSessionManager.ensureAgentWindow).mockResolvedValue({ + ensureOutcome: 'launched', wasAlreadyRunning: false, windowId: 'chrome-window-1', pid: 4242, @@ -186,6 +187,7 @@ describe('registerChromeSessionTools', () => { approvalMode: 'all', }) vi.mocked(runtime.chromeSessionManager.getSessionInfo).mockReturnValue({ + ensureOutcome: 'reused', wasAlreadyRunning: false, windowId: 'chrome-window-existing', pid: 9999, diff --git a/services/computer-use-mcp/src/types.ts b/services/computer-use-mcp/src/types.ts index ee7db8597..0e67144cb 100644 --- a/services/computer-use-mcp/src/types.ts +++ b/services/computer-use-mcp/src/types.ts @@ -134,6 +134,8 @@ export interface ForegroundContext { * `RunState.chromeSession` for the lifetime of the agent session. */ export interface ChromeSessionInfo { + /** Result of the latest ensureAgentWindow call. */ + ensureOutcome: 'launched' | 'reused' | 'recreated_after_process_exit' | 'recreated_after_missing_window' /** Whether Chrome was already running before the agent launched it. */ wasAlreadyRunning: boolean /** Window identity string from observe-windows (ownerPid:layer:title). */