@@ -36,6 +36,8 @@ export interface CdpCallbacks {
3636const callbacksByContents = new WeakMap < WebContents , CdpCallbacks > ( )
3737/** Contents already instrumented (attach survives for the tab's lifetime). */
3838const instrumented = new WeakSet < WebContents > ( )
39+ /** Tracks trusted input currently being dispatched by the agent itself. */
40+ const agentInputDepthByContents = new WeakMap < WebContents , number > ( )
3941/** Flattened CDP child-target sessions keyed by their protocol frame/target id. */
4042const childSessionsByContents = new WeakMap < WebContents , Map < string , string > > ( )
4143const FRAME_WORLD_NAME = 'sim-browser-agent'
@@ -62,6 +64,7 @@ async function sendInput(
6264 method : string ,
6365 params : Record < string , unknown >
6466) : Promise < void > {
67+ agentInputDepthByContents . set ( contents , ( agentInputDepthByContents . get ( contents ) ?? 0 ) + 1 )
6568 let timer : NodeJS . Timeout | undefined
6669 const timeout = new Promise < never > ( ( _resolve , reject ) => {
6770 timer = setTimeout (
@@ -73,9 +76,17 @@ async function sendInput(
7376 await Promise . race ( [ send ( contents , method , params ) , timeout ] )
7477 } finally {
7578 clearTimeout ( timer )
79+ const nextDepth = ( agentInputDepthByContents . get ( contents ) ?? 1 ) - 1
80+ if ( nextDepth > 0 ) agentInputDepthByContents . set ( contents , nextDepth )
81+ else agentInputDepthByContents . delete ( contents )
7682 }
7783}
7884
85+ /** Distinguishes user input from CDP input when Electron mirrors it as an event. */
86+ export function isDispatchingAgentInput ( contents : WebContents ) : boolean {
87+ return ( agentInputDepthByContents . get ( contents ) ?? 0 ) > 0
88+ }
89+
7990/** Idempotently instruments a tab's WebContents. */
8091export async function ensureInstrumented ( contents : WebContents , cb : CdpCallbacks ) : Promise < void > {
8192 callbacksByContents . set ( contents , cb )
0 commit comments