Skip to content

Commit aff62c7

Browse files
committed
Fix duplicate keyUp after interrupt in performAutomationPress
In performAutomationPress, the send helper dispatches the CDP keyUp command and then checks the control epoch. If human input bumps the epoch between CDP dispatch and the post-check, send fails with PreviewAutomationControlInterruptedError before keyReleased is set to true. The Effect.ensuring cleanup then sends a second keyUp via sendCleanup, duplicating the release. Fix by snapshotting the epoch before the keyUp send and using Effect.tapError to detect when the epoch changed during the call. Since the epoch snapshot and send's pre-check are both synchronous Ref reads with no async operations in between, a changed epoch in tapError means the pre-check passed (CDP was dispatched) and only the post-check failed. Mark keyReleased = true in that case to prevent the cleanup from issuing a duplicate keyUp.
1 parent 239e8b2 commit aff62c7

1 file changed

Lines changed: 15 additions & 1 deletion

File tree

apps/desktop/src/preview/Manager.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2226,7 +2226,21 @@ const makeNativeOperations = Effect.fn("PreviewManager.makeOperations")(function
22262226
yield* send("Emulation.setFocusEmulationEnabled", { enabled: true });
22272227
yield* expectAgentInput(tabId, { kind: "key", key, code: params.code });
22282228
yield* send("Input.dispatchKeyEvent", { type: "keyDown", ...params });
2229-
yield* send("Input.dispatchKeyEvent", { type: "keyUp", ...params });
2229+
const preKeyUpEpoch = (yield* Ref.get(controlEpochRef)).get(tabId) ?? 0;
2230+
yield* send("Input.dispatchKeyEvent", { type: "keyUp", ...params }).pipe(
2231+
Effect.tapError(() =>
2232+
Ref.get(controlEpochRef).pipe(
2233+
Effect.map((epochs) => {
2234+
// If the epoch changed during send, the CDP keyUp was dispatched
2235+
// (pre-check passed) before the post-check detected the change.
2236+
// Mark released to prevent a duplicate cleanup keyUp.
2237+
if ((epochs.get(tabId) ?? 0) !== preKeyUpEpoch) {
2238+
keyReleased = true;
2239+
}
2240+
}),
2241+
),
2242+
),
2243+
);
22302244
keyReleased = true;
22312245
}).pipe(Effect.ensuring(releaseInput));
22322246
});

0 commit comments

Comments
 (0)