@@ -14,10 +14,14 @@ import {
1414 type RecordCaptureController ,
1515} from "@/content/record-capture" ;
1616import {
17- HELP_RESPONSE ,
17+ HELP_ACK ,
18+ HELP_FINISH ,
19+ HELP_QUERY ,
20+ type HelpAckMessage ,
1821 type HelpCancelMessage ,
22+ type HelpFinishMessage ,
23+ type HelpQueryResponse ,
1924 type HelpRequestMessage ,
20- type HelpResponseMessage ,
2125 isHelpCancelMessage ,
2226 isHelpRequestMessage ,
2327} from "@/lib/help-bridge" ;
@@ -55,8 +59,6 @@ export default defineContentScript({
5559 if ( window . top !== window ) return ;
5660
5761 const overlays = new OverlayController ( ) ;
58- let activeHelpRespond : ( ( outcome : "continued" | "cancelled" , note ?: string ) => void ) | null =
59- null ;
6062 let recordCapture : RecordCaptureController | null = null ;
6163 let activeRecordRequestId : string | null = null ;
6264 let reactRoot : ReactDOM . Root | null = null ;
@@ -116,8 +118,7 @@ export default defineContentScript({
116118 function resetAgentOverlayState ( sessionId : string ) {
117119 const previousHelp = overlays . resetAgentOverlays ( sessionId ) ;
118120 if ( previousHelp ) {
119- activeHelpRespond ?.( "cancelled" ) ;
120- activeHelpRespond = null ;
121+ void sendHelpFinish ( previousHelp . id , "cancelled" ) ;
121122 }
122123 recordCapture ?. dispose ( ) ;
123124 recordCapture = null ;
@@ -156,7 +157,7 @@ export default defineContentScript({
156157 | OverlayAgentOverlayResetMessage
157158 | OverlayAutomationBypassMessage ,
158159 _sender : chrome . runtime . MessageSender ,
159- sendResponse : ( response : BorrowResponseMessage | HelpResponseMessage ) => void ,
160+ sendResponse : ( response : BorrowResponseMessage | HelpAckMessage ) => void ,
160161 ) => {
161162 if ( isRecordContentMessage ( message ) ) {
162163 const needsAsync = handleRecordContentMessage (
@@ -220,41 +221,30 @@ export default defineContentScript({
220221 if ( isHelpCancelMessage ( message ) ) {
221222 const state = overlays . snapshot ( ) ;
222223 if ( state . activeHelp && state . activeHelp . id === message . requestId ) {
223- activeHelpRespond ?.( "cancelled" ) ;
224+ overlays . clearAgentHelpRequest ( message . requestId ) ;
225+ renderOverlay ( ) ;
224226 }
225227 return false ;
226228 }
227229
228230 if ( isHelpRequestMessage ( message ) ) {
229231 const helpMsg = message as HelpRequestMessage ;
230- let responded = false ;
231- const respond = ( outcome : "continued" | "cancelled" , note ?: string ) => {
232- if ( responded ) return ;
233- responded = true ;
234- const reply : HelpResponseMessage = {
235- type : HELP_RESPONSE ,
236- outcome,
237- ...( note ? { note } : { } ) ,
238- } ;
239- sendResponse ( reply ) ;
240- activeHelpRespond = null ;
241- overlays . clearAgentHelpRequest ( helpMsg . requestId ) ;
242- renderOverlay ( ) ;
243- } ;
244232 const previousHelp = overlays . setAgentHelpRequest ( {
245233 id : helpMsg . requestId ,
246234 prompt : helpMsg . prompt ,
247235 ...( helpMsg . title ? { title : helpMsg . title } : { } ) ,
236+ ...( helpMsg . displayMode ? { displayMode : helpMsg . displayMode } : { } ) ,
248237 selectors : helpMsg . selectors ,
249- onContinue : ( note : string ) => respond ( "continued" , note . trim ( ) ? note : undefined ) ,
250- onCancel : ( ) => respond ( "cancelled" ) ,
238+ onContinue : ( note : string ) =>
239+ void sendHelpFinish ( helpMsg . requestId , "continued" , note . trim ( ) ? note : undefined ) ,
240+ onCancel : ( ) => void sendHelpFinish ( helpMsg . requestId , "cancelled" ) ,
251241 } ) ;
252- if ( previousHelp ) {
253- activeHelpRespond ?. ( "cancelled" ) ;
242+ if ( previousHelp && previousHelp . id !== helpMsg . requestId ) {
243+ void sendHelpFinish ( previousHelp . id , "cancelled" ) ;
254244 }
255- activeHelpRespond = respond ;
256245 renderOverlay ( ) ;
257- return true ; // async sendResponse
246+ sendResponse ( { type : HELP_ACK , ok : true } ) ;
247+ return false ;
258248 }
259249
260250 if ( message . type === "borrow-request" ) {
@@ -282,9 +272,60 @@ export default defineContentScript({
282272 return false ;
283273 } ;
284274
275+ async function sendHelpFinish (
276+ requestId : string ,
277+ outcome : "continued" | "cancelled" ,
278+ note ?: string ,
279+ ) : Promise < void > {
280+ const msg : HelpFinishMessage = {
281+ type : HELP_FINISH ,
282+ requestId,
283+ outcome,
284+ ...( note ? { note } : { } ) ,
285+ } ;
286+ overlays . clearAgentHelpRequest ( requestId ) ;
287+ renderOverlay ( ) ;
288+ await chrome . runtime . sendMessage ( msg ) . catch ( ( err ) => {
289+ console . debug ( "[bsk overlay] help finish failed" , err ) ;
290+ } ) ;
291+ }
292+
293+ function mountHelpRequest ( helpMsg : Omit < HelpRequestMessage , "type" > ) : void {
294+ overlays . setAgentHelpRequest ( {
295+ id : helpMsg . requestId ,
296+ prompt : helpMsg . prompt ,
297+ ...( helpMsg . title ? { title : helpMsg . title } : { } ) ,
298+ ...( helpMsg . displayMode ? { displayMode : helpMsg . displayMode } : { } ) ,
299+ selectors : helpMsg . selectors ,
300+ onContinue : ( note : string ) =>
301+ void sendHelpFinish ( helpMsg . requestId , "continued" , note . trim ( ) ? note : undefined ) ,
302+ onCancel : ( ) => void sendHelpFinish ( helpMsg . requestId , "cancelled" ) ,
303+ } ) ;
304+ }
305+
306+ async function queryActiveHelpWithRetry ( ) : Promise < boolean > {
307+ for ( let attempt = 0 ; attempt < 6 ; attempt += 1 ) {
308+ try {
309+ const helpQuery = ( await chrome . runtime . sendMessage ( {
310+ type : HELP_QUERY ,
311+ } ) ) as HelpQueryResponse | undefined ;
312+ if ( helpQuery ?. active && helpQuery . request ) {
313+ mountHelpRequest ( helpQuery . request ) ;
314+ renderOverlay ( ) ;
315+ return true ;
316+ }
317+ } catch ( err ) {
318+ console . debug ( "[bsk overlay] help query failed" , err ) ;
319+ }
320+ await new Promise ( ( resolve ) => window . setTimeout ( resolve , 150 ) ) ;
321+ }
322+ return false ;
323+ }
324+
285325 async function syncAgentOverlay ( ) : Promise < void > {
286326 if ( ! ( await anySessionLive ( ) ) ) return ;
287327 try {
328+ const helpActive = await queryActiveHelpWithRetry ( ) ;
288329 const reply = ( await chrome . runtime . sendMessage ( {
289330 kind : OVERLAY_MSG_WHO_AM_I ,
290331 } ) ) as OverlayWhoAmIResponse | undefined ;
@@ -319,6 +360,10 @@ export default defineContentScript({
319360 } ) ;
320361 }
321362
363+ if ( ! helpActive && overlays . snapshot ( ) . activeHelp === null ) {
364+ void queryActiveHelpWithRetry ( ) ;
365+ }
366+
322367 overlays . activateAgentSession ( reply . sessionId ) ;
323368 renderOverlay ( ) ;
324369 } catch ( err ) {
0 commit comments