diff --git a/packages/runtime/src/__tests__/computer-use-tools.test.ts b/packages/runtime/src/__tests__/computer-use-tools.test.ts index b829aa8312..f8e1e5d9a9 100644 --- a/packages/runtime/src/__tests__/computer-use-tools.test.ts +++ b/packages/runtime/src/__tests__/computer-use-tools.test.ts @@ -1446,6 +1446,42 @@ describe('buildComputerUseTools — the `maka_computer` MakaTool', () => { } }); + test('clearSession fences failed host-reading results that complete after stop', async () => { + for (const action of ['cursor_position', 'wait'] as const) { + let release!: () => void; + let started!: () => void; + const gate = new Promise((resolve) => { release = resolve; }); + const entered = new Promise((resolve) => { started = resolve; }); + const backend = fakeBackend(); + backend.run = async () => { + started(); + await gate; + return { + outcome: { + ok: false, + error: 'service_unavailable', + message: 'service failed after stop', + }, + }; + }; + const tools = buildComputerUseTools({ backend }); + const [tool] = tools; + const pending = tool.impl( + action === 'wait' + ? { action, duration: 0.001 } as never + : { action } as never, + ctx(), + ); + await entered; + tools.clearSession('s1'); + release(); + + const result = await pending as { text: string }; + assert.match(result.text, /user_stopped/, action); + assert.doesNotMatch(result.text, /service_unavailable/, action); + } + }); + test('S17: surfaces the typed backend failure code without leaking raw driver text', async () => { const backend = fakeBackend({ result: { outcome: { ok: false, error: 'capture_failed', message: 'AXPress err -25202', completedSubSteps: 0 } } }); const r = await callComputer(backend, { action: 'wait' }); diff --git a/packages/runtime/src/computer-use-tools.ts b/packages/runtime/src/computer-use-tools.ts index 98cf16472e..9df4603779 100644 --- a/packages/runtime/src/computer-use-tools.ts +++ b/packages/runtime/src/computer-use-tools.ts @@ -1495,7 +1495,7 @@ export function buildComputerUseTools(deps: { if (presentation.blocked) return presentation.blocked; result = presentation.result; if (result) applyTypedOutcomeState(state, result.outcome); - if (result?.outcome.ok && observationLease?.ok) { + if (observationLease?.ok) { const validated = state.validateObservationLease( observationLease.lease, );