import pathlib,sys
p=pathlib.Path(sys.argv[1])/'apps/server/src/preview/ServerBrowser.ts'; s=p.read_text()
# Instrument real page/CDP calls, adding only externally controlled synthetic gates.
hook='''
    if (process.env.T3_CAPTURE_CONTROL) {
      const root = process.env.T3_CAPTURE_CONTROL;
      const log = (event: string, detail: unknown = {}) => console.log("CAPTURE " + JSON.stringify({time:new Date().toISOString(),tabId:tab.tabId,event,detail}));
      const gate = async (op: string, args: unknown[]) => {
        let config: any = {};
        try { config = JSON.parse(await NodeFSP.readFile(root + "/gates.json", "utf8"))[tab.tabId]?.[op] ?? {}; } catch {}
        if (op === "emulateMedia" && (args[0] as any)?.colorScheme !== "dark") config = {};
        if (config.dialog) await page.evaluate(() => confirm("Synthetic overdue dialog"));
        if (config.delay) await new Promise(resolve => setTimeout(resolve, config.delay));
        if (config.hold) {
          log(op+".held");
          while (true) { try { const value = await NodeFSP.readFile(root+"/release-"+tab.tabId,"utf8"); if(value.trim()==="reject") throw new Error("Synthetic gate rejection"); break; } catch(e) { if ((e as any)?.message === "Synthetic gate rejection") throw e; await new Promise(resolve=>setTimeout(resolve,20)); } }
        }
        if (config.fail) throw new Error("Synthetic one-shot rendering failure");
      };
      for (const op of ["emulateMedia","setViewportSize","close"] as const) {
        const original = (page[op] as Function).bind(page);
        (page as any)[op] = async (...args: unknown[]) => { log(op+".start",args); try { await gate(op,args); const result=await original(...args); log(op+".end"); return result; } catch(e) { log(op+".error",String(e)); throw e; } };
      }
      const send = cdp.send.bind(cdp);
      (cdp as any).send = async (method: string, params: unknown) => {
        const trace = ["Page.reload","Network.clearBrowserCookies","Network.clearBrowserCache","Emulation.setDeviceMetricsOverride"].includes(method);
        if(trace) log("cdp.start",{method,params});
        try { const value=await (send as Function)(method,params); if(trace) log("cdp.end",{method}); return value; } catch(e) { if(trace) log("cdp.error",{method,error:String(e)}); throw e; }
      };
      const ctxClose=context.close.bind(context);
      context.close=async (...args: any[])=>{log("context.close.start"); const result=await (ctxClose as Function)(...args);log("context.close.end");return result;};
      log("tab.created", {desktop:!!desktop,isolatedContext});
      page.on("dialog",dialog=>log("dialog.open",{type:dialog.type(),message:dialog.message()}));
      page.on("close",()=>log("page.closed"));
    }
'''
needle='    if (!desktop) {\n      await page.setViewportSize(fixedViewportSize(tab.setting) ?? UNATTACHED_FILL_VIEWPORT);'
assert needle in s;s=s.replace(needle,hook+needle,1)
s=s.replace('    const input = request.input;\n    switch (request.operation)', '''    console.log("CAPTURE " + JSON.stringify({time:new Date().toISOString(),event:"request.start",operation:request.operation,requestId:request.requestId,tabId:request.tabId,timeoutMs:request.timeoutMs,agentSessionId:request.agentSessionId,connectionId:hostConnectionId}));
    if(request.operation === "status" && process.env.T3_CAPTURE_CONTROL && request.tabId) {
      try { const gates=JSON.parse(await NodeFSP.readFile(process.env.T3_CAPTURE_CONTROL+"/gates.json","utf8")); if(gates[request.tabId]?.statusDelay) await new Promise(resolve=>setTimeout(resolve,gates[request.tabId].statusDelay)); } catch {}
    }
    const input = request.input;
    switch (request.operation)''',1)
s=s.replace('    const key = tabKey(tab.threadId, tab.tabId);\n    if (tabs.get(key) !== tab) return;','    console.log("CAPTURE "+JSON.stringify({time:new Date().toISOString(),event:"dropTab",tabId:tab.tabId,recording:!!tab.recording}));\n    const key = tabKey(tab.threadId, tab.tabId);\n    if (tabs.get(key) !== tab) return;',1)
s=s.replace('      const recording = tab.recording;\n      if (!recording)', '      console.log("CAPTURE "+JSON.stringify({time:new Date().toISOString(),event:"recording.stop.start",tabId:tab.tabId}));\n      const recording = tab.recording;\n      if (!recording)',1)
s=s.replace('        await recording.encoder.close().catch(constVoid);\n        tab.recording = null;', '        await recording.encoder.close().catch(constVoid);\n        console.log("CAPTURE "+JSON.stringify({time:new Date().toISOString(),event:"recording.encoder.closed",tabId:tab.tabId}));\n        tab.recording = null;',1)
s=s.replace('              hostConnectionId = event.connectionId;','              console.log("CAPTURE "+JSON.stringify({time:new Date().toISOString(),event:"host.connected",connectionId:event.connectionId}));\n              hostConnectionId = event.connectionId;',1)
s=s.replace('      if (event.type === "resized") {','      console.log("CAPTURE "+JSON.stringify({time:new Date().toISOString(),event:"mirror.received",type:event.type,tabId:event.tabId}));\n      if (event.type === "resized") {',1)
p.write_text(s)
