@react-native/debugger-frontend
Version:
Debugger frontend for React Native based on Chrome DevTools
1 lines • 86.4 kB
JavaScript
import*as e from"../../core/common/common.js";import*as t from"../../third_party/diff/diff.js";import*as n from"../text_utils/text_utils.js";import*as i from"../workspace/workspace.js";import*as s from"../../core/host/host.js";import*as r from"../../core/root/root.js";import*as o from"../../core/i18n/i18n.js";import*as a from"../../panels/utils/utils.js";import*as l from"../bindings/bindings.js";import*as c from"../../panels/network/network.js";import*as d from"../logs/logs.js";import*as u from"../../panels/timeline/utils/utils.js";import*as h from"../trace/trace.js";import*as p from"../../core/platform/platform.js";import*as m from"../../core/sdk/sdk.js";import*as g from"../../panels/elements/elements.js";import*as f from"../../ui/legacy/legacy.js";import*as y from"../../ui/lit/lit.js";function w(){return Boolean(localStorage.getItem("debugAiAssistancePanelEnabled"))}function v(...e){w()&&console.log(...e)}globalThis.setDebugAiAssistanceEnabled=function(e){e?localStorage.setItem("debugAiAssistancePanelEnabled","true"):localStorage.removeItem("debugAiAssistancePanelEnabled")};class b{#e;#t=new Set(["inspector-stylesheet"]);#n=new Set;#i=0;#s;#r;#o=new Set;constructor(e={maxFilesChanged:5,maxLinesChanged:200}){this.#e=i.Workspace.WorkspaceImpl.instance().projectsForType(i.Workspace.projectTypes.Network),this.#s=e.maxFilesChanged,this.#r=e.maxLinesChanged}getProcessedFiles(){return Array.from(this.#o)}getFiles(){return this.#a().files}readFile(e){const{map:t}=this.#a(),n=t.get(e);if(!n)return;this.#o.add(e);const i=n.workingCopyContentData();return i.isTextContent?i.text:void 0}writeFile(e,n){const{map:i}=this.#a(),s=i.get(e);if(!s)throw new Error(`UISourceCode ${e} not found`);const r=this.readFile(e),o=/\r\n?|\n/;let a=0;if(r){const e=t.Diff.DiffWrapper.lineDiff(r.split(o),n.split(o));for(const n of e)n[0]!==t.Diff.Operation.Equal&&a++}else a+=n.split(o).length;if(this.#i+a>this.#r)throw new Error("Too many lines changed");if(this.#n.add(e),this.#n.size>this.#s)throw this.#n.delete(e),new Error("Too many files changed");this.#i+=a,s.setWorkingCopy(n),s.setContainsAiChanges(!0)}async searchFiles(e,t,i,{signal:s}={}){const{map:r}=this.#a(),o=[];for(const[a,l]of r.entries()){if(s?.aborted)break;await l.requestContentData(),v("searching in",a,"for",e);const r=l.isDirty()?l.workingCopyContentData():await l.requestContentData(),c=n.TextUtils.performSearchInContentData(r,e,t??!0,i??!1);for(const e of c)v("matches in",a),o.push({filepath:a,lineNumber:e.lineNumber,columnNumber:e.columnNumber,matchLength:e.matchLength})}return o}#a(){const t=new Map;for(const n of this.#e)for(const i of n.uiSourceCodes()){const{path:n}=new e.ParsedURL.ParsedURL(i.url());this.#t.has(i.name())||t.set(n,i)}return{files:Array.from(t.keys()),map:t}}}const S=10;class C{isOriginAllowed(e){return!e||this.getOrigin()===e}async refresh(){}getSuggestions(){}}class I{#l=crypto.randomUUID();#c;#d;confirmSideEffect;#u=new Map;#h=[];#p;#m;#g=crypto.randomUUID();#f=[];constructor(e){this.#c=e.aidaClient,this.#d=e.serverSideLoggingEnabled??!1,this.confirmSideEffect=e.confirmSideEffectForTest??(()=>Promise.withResolvers())}async enhanceQuery(e){return e}buildRequest(e,t){const n={parts:Array.isArray(e)?e:[e],role:t},i=[...this.#f],o=[];for(const[e,t]of this.#u.entries())o.push({name:e,description:t.description,parameters:t.parameters});const a=o.length&&!this.functionCallEmulationEnabled,l=s.AidaClient.convertToUserTierEnum(this.userTier),c=l===s.AidaClient.UserTier.TESTERS?this.preamble:void 0;var d;return{client:s.AidaClient.CLIENT_NAME,current_message:n,preamble:c,historical_contexts:i.length?i:void 0,...a?{function_declarations:o}:{},options:{temperature:(d=this.options.temperature,"number"==typeof d&&d>=0?d:void 0),model_id:this.options.modelId||void 0},metadata:{disable_user_content_logging:!this.#d,string_session_id:this.#l,user_tier:l,client_version:r.Runtime.getChromeVersion()},functionality_type:a?s.AidaClient.FunctionalityType.AGENTIC_CHAT:s.AidaClient.FunctionalityType.CHAT,client_feature:this.clientFeature}}get id(){return this.#g}get origin(){return this.#p}parseTextResponse(e){return{answer:e}}declareFunction(e,t){if(this.#u.has(e))throw new Error(`Duplicate function declaration ${e}`);this.#u.set(e,t)}formatParsedAnswer({answer:e}){return e}functionCallEmulationEnabled=!1;emulateFunctionCall(e){throw new Error("Unexpected emulateFunctionCall. Only StylingAgent implements function call emulation")}async*run(e,t,n,i){await(t.selected?.refresh()),t.selected&&void 0===this.#p&&t.selected&&(this.#p=t.selected.getOrigin()),t.selected&&!this.#m&&(this.#m=t.selected);const r=await this.enhanceQuery(e,t.selected,Boolean(n));let o;s.userMetrics.freestylerQueryLength(r.length),o=n?[{text:r},n]:[{text:r}];let a=this.buildRequest(o,s.AidaClient.Role.USER);yield{type:"user-query",query:e,imageInput:n,imageId:i},yield*this.handleContextDetails(t.selected);for(let e=0;e<10;e++){let n;yield{type:"querying"};let i,r="";try{for await(const e of this.#y(a,{signal:t.signal})){if(n=e.rpcId,r=e.text??"",i=e.functionCall,!i&&!e.completed){const e=this.parseTextResponse(r),t="answer"in e?e.answer:"";if(!t)continue;yield{type:"answer",text:t,complete:!1}}if(i)break}}catch(e){v("Error calling the AIDA API",e);let t="unknown";e instanceof s.AidaClient.AidaAbortError?t="abort":e instanceof s.AidaClient.AidaBlockError&&(t="block"),yield this.#w(t);break}if(this.#f.push(a.current_message),r){const e=this.parseTextResponse(r);if(!("answer"in e))throw new Error("Expected a completed response to have an answer");this.#f.push({parts:[{text:this.formatParsedAnswer(e)}],role:s.AidaClient.Role.MODEL}),s.userMetrics.actionTaken(s.UserMetrics.Action.AiAssistanceAnswerReceived),yield{type:"answer",text:e.answer,suggestions:e.suggestions,complete:!0,rpcId:n};break}if(!i){yield this.#w(e-1==10?"max-steps":"unknown");break}try{const e=yield*this.#v(i.name,i.args,t);if(t.signal?.aborted){yield this.#w("abort");break}o=this.functionCallEmulationEnabled?{text:"OBSERVATION: "+e.result}:{functionResponse:{name:i.name,response:e}},a=this.buildRequest(o,this.functionCallEmulationEnabled?s.AidaClient.Role.USER:s.AidaClient.Role.ROLE_UNSPECIFIED)}catch{yield this.#w("unknown");break}}w()&&window.dispatchEvent(new CustomEvent("aiassistancedone"))}async*#v(e,t,n){const i=this.#u.get(e);if(!i)throw new Error(`Function ${e} is not found.`);if(this.functionCallEmulationEnabled){if(!i.displayInfoFromArgs)throw new Error("functionCallEmulationEnabled requires all functions to provide displayInfoFromArgs");this.#f.push({parts:[{text:this.#b(i.displayInfoFromArgs(t))}],role:s.AidaClient.Role.MODEL})}else this.#f.push({parts:[{functionCall:{name:e,args:t}}],role:s.AidaClient.Role.MODEL});let r;if(i.displayInfoFromArgs){const{title:e,thought:n,action:s}=i.displayInfoFromArgs(t);r=s,e&&(yield{type:"title",title:e}),n&&(yield{type:"thought",thought:n})}let o=await i.handler(t,n);if("requiresApproval"in o){r&&(yield{type:"action",code:r,canceled:!1});const e=this.confirmSideEffect();e.promise.then((e=>{s.userMetrics.actionTaken(e?s.UserMetrics.Action.AiAssistanceSideEffectConfirmed:s.UserMetrics.Action.AiAssistanceSideEffectRejected)})),n?.signal?.aborted&&e.resolve(!1),n?.signal?.addEventListener("abort",(()=>{e.resolve(!1)}),{once:!0}),yield{type:"side-effect",confirm:t=>{e.resolve(t)}};const a=await e.promise;if(!a)return yield{type:"action",code:r,output:"Error: User denied code execution with side effects.",canceled:!0},{result:"Error: User denied code execution with side effects."};o=await i.handler(t,{...n,approved:a})}return"result"in o&&(yield{type:"action",code:r,output:"string"==typeof o.result?o.result:JSON.stringify(o.result),canceled:!1}),"error"in o&&(yield{type:"action",code:r,output:o.error,canceled:!1}),o}async*#y(e,t){let n,i,s="";for await(n of this.#c.fetch(e,t)){if(n.functionCalls?.length){v("functionCalls.length",n.functionCalls.length),yield{rpcId:i,functionCall:n.functionCalls[0],completed:!0};break}if(this.functionCallEmulationEnabled){const e=this.emulateFunctionCall(n);if("wait-for-completion"===e)continue;if("no-function-call"!==e){yield{rpcId:i,functionCall:e,completed:!0};break}}s=n.explanation,i=n.metadata.rpcGlobalId??i,yield{rpcId:i,text:n.explanation,completed:n.completed}}v({request:e,response:n}),w()&&(this.#h.push({request:structuredClone(e),response:s,aidaResponse:n}),localStorage.setItem("aiAssistanceStructuredLog",JSON.stringify(this.#h)))}#b(e){let t="";return e.thought&&(t=`THOUGHT: ${e.thought}`),e.title&&(t+=`\nTITLE: ${e.title}`),e.action&&(t+=`\nACTION\n${e.action}\nSTOP`),t}#S(){this.#f.splice(this.#f.findLastIndex((e=>e.role===s.AidaClient.Role.USER)))}#w(e){return this.#S(),"abort"!==e&&s.userMetrics.actionTaken(s.UserMetrics.Action.AiAssistanceError),{type:"error",error:e}}}class T{static allowHeader(e){return x.has(e.toLowerCase().trim())}static formatHeaders(e,t,n){return function(e,t,n){let i="";for(const e of t){if(i.length+e.length>n)break;i+=e}return i=i.trim(),i&&e?e+"\n"+i:i}(e,function(e){return e.map((e=>T.allowHeader(e.name)?e:{name:e.name,value:"<redacted>"}))}(t).map((e=>(n?"- ":"")+e.name+": "+e.value+"\n")),1e3)}static formatInitiatorUrl(e,t){return new URL(e).origin===t?e:"<redacted cross-origin initiator URL>"}#C;constructor(e){this.#C=e}formatRequestHeaders(){return T.formatHeaders("Request headers:",this.#C.requestHeaders())}formatResponseHeaders(){return T.formatHeaders("Response headers:",this.#C.responseHeaders)}formatNetworkRequest(){return`Request: ${this.#C.url()}\n\n${this.formatRequestHeaders()}\n\n${this.formatResponseHeaders()}\n\nResponse status: ${this.#C.statusCode} ${this.#C.statusText}\n\nRequest timing:\n${this.formatNetworkRequestTiming()}\n\nRequest initiator chain:\n${this.formatRequestInitiatorChain()}`}formatRequestInitiatorChain(){const e=new URL(this.#C.url()).origin;let t="",n="- URL: ";const i=d.NetworkLog.NetworkLog.instance().initiatorGraphForRequest(this.#C);for(const s of Array.from(i.initiators).reverse())t=t+n+T.formatInitiatorUrl(s.url(),e)+"\n",n="\t"+n,s===this.#C&&(t=this.#I(i.initiated,this.#C,t,n,e));return t.trim()}formatNetworkRequestTiming(){const e=c.NetworkPanel.NetworkPanel.instance().networkLogView.timeCalculator(),t=c.RequestTimingView.RequestTimingView.calculateRequestTimeRanges(this.#C,e.minimumBoundary());function n(e){const n=t.find((t=>t.name===e));if(n)return o.TimeUtilities.secondsToString(n.end-n.start,!0)}return[{label:"Queued at (timestamp)",value:e.formatValue(this.#C.issueTime(),2)},{label:"Started at (timestamp)",value:e.formatValue(this.#C.startTime,2)},{label:"Queueing (duration)",value:n("queueing")},{label:"Connection start (stalled) (duration)",value:n("blocking")},{label:"Request sent (duration)",value:n("sending")},{label:"Waiting for server response (duration)",value:n("waiting")},{label:"Content download (duration)",value:n("receiving")},{label:"Duration (duration)",value:n("total")}].filter((e=>!!e.value)).map((e=>`${e.label}: ${e.value}`)).join("\n")}#I(e,t,n,i,s){const r=new Set;r.add(this.#C);for(const[o,a]of e.entries())a===t&&(r.has(o)||(r.add(o),n=n+i+T.formatInitiatorUrl(o.url(),s)+"\n",n=this.#I(e,o,n,"\t"+i,s)));return n}}const x=new Set([":authority",":method",":path",":scheme","a-im","accept-ch","accept-charset","accept-datetime","accept-encoding","accept-language","accept-patch","accept-ranges","accept","access-control-allow-credentials","access-control-allow-headers","access-control-allow-methods","access-control-allow-origin","access-control-expose-headers","access-control-max-age","access-control-request-headers","access-control-request-method","age","allow","alt-svc","cache-control","connection","content-disposition","content-encoding","content-language","content-location","content-range","content-security-policy","content-type","correlation-id","date","delta-base","dnt","expect-ct","expect","expires","forwarded","front-end-https","host","http2-settings","if-modified-since","if-range","if-unmodified-source","im","last-modified","link","location","max-forwards","nel","origin","permissions-policy","pragma","preference-applied","proxy-connection","public-key-pins","range","referer","refresh","report-to","retry-after","save-data","sec-gpc","server","status","strict-transport-security","te","timing-allow-origin","tk","trailer","transfer-encoding","upgrade-insecure-requests","upgrade","user-agent","vary","via","warning","www-authenticate","x-att-deviceid","x-content-duration","x-content-security-policy","x-content-type-options","x-correlation-id","x-forwarded-for","x-forwarded-host","x-forwarded-proto","x-frame-options","x-http-method-override","x-powered-by","x-redirected-by","x-request-id","x-requested-with","x-ua-compatible","x-wap-profile","x-webkit-csp","x-xss-protection"]);class E{static formatSourceMapDetails(e,t){const n=[],i=[];if(e.contentType().isFromSourceMap()){for(const s of t.scriptsForUISourceCode(e)){const e=t.uiSourceCodeForScript(s);e&&(n.push(e.url()),void 0!==s.sourceMapURL&&i.push(s.sourceMapURL))}for(const t of l.SASSSourceMapping.SASSSourceMapping.uiSourceOrigin(e))n.push(t)}else if(e.contentType().isScript())for(const n of t.scriptsForUISourceCode(e))void 0!==n.sourceMapURL&&""!==n.sourceMapURL&&i.push(n.sourceMapURL);if(0===i.length)return"";let s="Source map: "+i;return n.length>0&&(s+="\nSource mapped from: "+n),s}#T;constructor(e){this.#T=e}formatFile(){const e=l.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance(),t=E.formatSourceMapDetails(this.#T,e),n=[`File name: ${this.#T.displayName()}`,`URL: ${this.#T.url()}`,t],i=l.ResourceUtils.resourceForURL(this.#T.url());return i?.request&&n.push(`Request initiator chain:\n${new T(i.request).formatRequestInitiatorChain()}`),n.push(`File content:\n${this.#x()}`),n.filter((e=>""!==e.trim())).join("\n")}#x(){const e=this.#T.workingCopyContentData(),t=e.isTextContent?e.text:"<binary data>";return`\`\`\`\n${t.length>1e4?t.slice(0,1e4)+"...":t}\n\`\`\``}}const R="Analyzing file",A=o.i18n.lockedString;class k extends C{#T;constructor(e){super(),this.#T=e}getOrigin(){return new URL(this.#T.url()).origin}getItem(){return this.#T}getIcon(){return a.PanelUtils.getIconForSourceFile(this.#T)}getTitle(){return this.#T.displayName()}async refresh(){await this.#T.requestContentData()}}class N extends I{type="drjones-file";preamble="You are a highly skilled software engineer with expertise in various programming languages and frameworks.\nYou are provided with the content of a file from the Chrome DevTools Sources panel. To aid your analysis, you've been given the below links to understand the context of the code and its relationship to other files. When answering questions, prioritize providing these links directly.\n* Source-mapped from: If this code is the source for a mapped file, you'll have a link to that generated file.\n* Source map: If this code has an associated source map, you'll have link to the source map.\n* If there is a request which caused the file to be loaded, you will be provided with the request initiator chain with URLs for those requests.\n\nAnalyze the code and provide the following information:\n* Describe the primary functionality of the code. What does it do? Be specific and concise. If the code snippet is too small or unclear to determine the functionality, state that explicitly.\n* If possible, identify the framework or library the code is associated with (e.g., React, Angular, jQuery). List any key technologies, APIs, or patterns used in the code (e.g., Fetch API, WebSockets, object-oriented programming).\n* (Only provide if available and accessible externally) External Resources: Suggest relevant documentation that could help a developer understand the code better. Prioritize official documentation if available. Do not provide any internal resources.\n* (ONLY if request initiator chain is provided) Why the file was loaded?\n\n# Considerations\n* Keep your analysis concise and focused, highlighting only the most critical aspects for a software engineer.\n* Answer questions directly, using the provided links whenever relevant.\n* Always double-check links to make sure they are complete and correct.\n* **CRITICAL** If the user asks a question about religion, race, politics, sexuality, gender, or other sensitive topics, answer with \"Sorry, I can't answer that. I'm best at questions about files.\"\n* **CRITICAL** You are a file analysis agent. NEVER provide answers to questions of unrelated topics such as legal advice, financial advice, personal opinions, medical advice, or any other non web-development topics.\n* **Important Note:** The provided code may represent an incomplete fragment of a larger file. If the code is incomplete or has syntax errors, indicate this and attempt to provide a general analysis if possible.\n* **Interactive Analysis:** If the code requires more context or is ambiguous, ask clarifying questions to the user. Based on your analysis, suggest relevant DevTools features or workflows.\n\n## Example session\n\n**User:** (Selects a file containing the following JavaScript code)\n\nfunction calculateTotal(price, quantity) {\n const total = price * quantity;\n return total;\n}\nExplain this file.\n\n\nThis code defines a function called calculateTotal that calculates the total cost by multiplying the price and quantity arguments.\nThis code is written in JavaScript and doesn't seem to be associated with a specific framework. It's likely a utility function.\nRelevant Technologies: JavaScript, functions, arithmetic operations.\nExternal Resources:\nMDN Web Docs: JavaScript Functions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions\n";clientFeature=s.AidaClient.ClientFeature.CHROME_FILE_AGENT;get userTier(){return r.Runtime.hostConfig.devToolsAiAssistanceFileAgent?.userTier}get options(){const e=r.Runtime.hostConfig.devToolsAiAssistanceFileAgent?.temperature,t=r.Runtime.hostConfig.devToolsAiAssistanceFileAgent?.modelId;return{temperature:e,modelId:t}}async*handleContextDetails(e){e&&(yield{type:"context",title:A(R),details:L(e)})}async enhanceQuery(e,t){return`${t?`# Selected file\n${new E(t.getItem()).formatFile()}\n\n# User request\n\n`:""}${e}`}}function L(e){return[{title:"Selected file",text:new E(e.getItem()).formatFile()}]}const q="Analyzing network data",M="Request",$="Response",D="Request URL",F="Timing",P="Response Status",O="Request initiator chain",U=o.i18n.lockedString;class H extends C{#C;constructor(e){super(),this.#C=e}getOrigin(){return new URL(this.#C.url()).origin}getItem(){return this.#C}getIcon(){return a.PanelUtils.getIconForNetworkRequest(this.#C)}getTitle(){return this.#C.name()}}class j extends I{type="drjones-network-request";preamble='You are the most advanced network request debugging assistant integrated into Chrome DevTools.\nThe user selected a network request in the browser\'s DevTools Network Panel and sends a query to understand the request.\nProvide a comprehensive analysis of the network request, focusing on areas crucial for a software engineer. Your analysis should include:\n* Briefly explain the purpose of the request based on the URL, method, and any relevant headers or payload.\n* Analyze timing information to identify potential bottlenecks or areas for optimization.\n* Highlight potential issues indicated by the status code.\n\n# Considerations\n* If the response payload or request payload contains sensitive data, redact or generalize it in your analysis to ensure privacy.\n* Tailor your explanations and suggestions to the specific context of the request and the technologies involved (if discernible from the provided details).\n* Keep your analysis concise and focused, highlighting only the most critical aspects for a software engineer.\n* **CRITICAL** If the user asks a question about religion, race, politics, sexuality, gender, or other sensitive topics, answer with "Sorry, I can\'t answer that. I\'m best at questions about network requests."\n* **CRITICAL** You are a network request debugging assistant. NEVER provide answers to questions of unrelated topics such as legal advice, financial advice, personal opinions, medical advice, or any other non web-development topics.\n\n## Example session\n\nExplain this network request\nRequest: https://api.example.com/products/search?q=laptop&category=electronics\nResponse Headers:\n Content-Type: application/json\n Cache-Control: max-age=300\n...\nRequest Headers:\n User-Agent: Mozilla/5.0\n...\nRequest Status: 200 OK\n\n\nThis request aims to retrieve a list of products matching the search query "laptop" within the "electronics" category. The successful 200 OK status confirms that the server fulfilled the request and returned the relevant data.\n';clientFeature=s.AidaClient.ClientFeature.CHROME_NETWORK_AGENT;get userTier(){return r.Runtime.hostConfig.devToolsAiAssistanceNetworkAgent?.userTier}get options(){const e=r.Runtime.hostConfig.devToolsAiAssistanceNetworkAgent?.temperature,t=r.Runtime.hostConfig.devToolsAiAssistanceNetworkAgent?.modelId;return{temperature:e,modelId:t}}async*handleContextDetails(e){e&&(yield{type:"context",title:U(q),details:z(e.getItem())})}async enhanceQuery(e,t){return`${t?`# Selected network request \n${new T(t.getItem()).formatNetworkRequest()}\n\n# User request\n\n`:""}${e}`}}function z(e){const t=new T(e);return[{title:U(M),text:U(D)+": "+e.url()+"\n\n"+t.formatRequestHeaders()},{title:U($),text:U(P)+": "+e.statusCode+" "+e.statusText+"\n\n"+t.formatResponseHeaders()},{title:U(F),text:t.formatNetworkRequestTiming()},{title:U(O),text:t.formatRequestInitiatorChain()}]}const W="Analyzing call tree",_=o.i18n.lockedString;class B extends C{#E;constructor(e){super(),this.#E=e}getOrigin(){const t=(this.#E.selectedNode??this.#E.rootNode).event,n=h.Handlers.Helpers.getNonResolvedURL(t,this.#E.parsedTrace);if(n){const t=e.ParsedURL.ParsedURL.extractOrigin(n);if(t)return t}return`${t.name}_${t.pid}_${t.tid}_${t.ts}`}getItem(){return this.#E}getIcon(){const e=a.PanelUtils.createIconElement({iconName:"performance",color:"var(--sys-color-on-surface-subtle)"},"Performance");return e.classList.add("icon"),e}getTitle(){const e=this.#E.selectedNode?.event??this.#E.rootNode.event;return e?u.EntryName.nameForEntry(e):"unknown"}}class G extends I{type="drjones-performance";preamble="You are an expert performance analyst embedded within Chrome DevTools.\nYou meticulously examine web application behavior captured by the Chrome DevTools Performance Panel and Chrome tracing.\nYou will receive a structured text representation of a call tree, derived from a user-selected call frame within a performance trace's flame chart.\nThis tree originates from the root task associated with the selected call frame.\n\nEach call frame is presented in the following format:\n\nNode: $id - $name\nSelected: true (if this is the call frame selected by the user)\nDuration: $duration (milliseconds, including children)\nSelf Time: $self (milliseconds, excluding children, defaults to 0)\nURL: $url_number (reference to the \"All URLs\" list)\nChildren:\n * $child.id - $child.name\n\nKey definitions:\n\n* name: A concise string describing the call frame (e.g., 'Evaluate Script', 'render', 'fetchData').\n* id: A unique numerical identifier for the call frame.\n* Selected: Indicates if this is the call frame the user focused on. **Only one node will have \"Selected: true\".**\n* URL: The index of the URL associated with this call frame, referencing the \"All URLs\" list.\n* Duration: The total execution time of the call frame, including its children.\n* Self Time: The time spent directly within the call frame, excluding its children's execution.\n* Children: A list of child call frames, showing their IDs and names.\n\nYour objective is to provide a comprehensive analysis of the **selected call frame and the entire call tree** and its context within the performance recording, including:\n\n1. **Functionality:** Clearly describe the purpose and actions of the selected call frame based on its properties (name, URL, etc.).\n2. **Execution Flow:**\n * **Ancestors:** Trace the execution path from the root task to the selected call frame, explaining the sequence of parent calls.\n * **Descendants:** Analyze the child call frames, identifying the tasks they initiate and any performance-intensive sub-tasks.\n3. **Performance Metrics:**\n * **Duration and Self Time:** Report the execution time of the call frame and its children.\n * **Relative Cost:** Evaluate the contribution of the call frame to the overall duration of its parent tasks and the entire trace.\n * **Bottleneck Identification:** Identify potential performance bottlenecks based on duration and self time, including long-running tasks or idle periods.\n4. **Optimization Recommendations:** Provide specific, actionable suggestions for improving the performance of the selected call frame and its related tasks, focusing on resource management and efficiency. Only provide recommendations if they are based on data present in the call tree.\n\n# Important Guidelines:\n\n* Maintain a concise and technical tone suitable for software engineers.\n* Exclude call frame IDs and URL indices from your response.\n* **Critical:** If asked about sensitive topics (religion, race, politics, sexuality, gender, etc.), respond with: \"My expertise is limited to website performance analysis. I cannot provide information on that topic.\".\n* **Critical:** Refrain from providing answers on non-web-development topics, such as legal, financial, medical, or personal advice.\n\n## Example Session:\n\nAll URLs:\n* 0 - app.js\n\nCall Tree:\n\nNode: 1 - main\nSelected: false\nDuration: 500\nSelf Time: 100\nChildren:\n * 2 - update\n\nNode: 2 - update\nSelected: false\nDuration: 200\nSelf Time: 50\nChildren:\n * 3 - animate\n\nNode: 3 - animate\nSelected: true\nDuration: 150\nSelf Time: 20\nURL: 0\nChildren:\n * 4 - calculatePosition\n * 5 - applyStyles\n\nNode: 4 - calculatePosition\nSelected: false\nDuration: 80\nSelf Time: 80\n\nNode: 5 - applyStyles\nSelected: false\nDuration: 50\nSelf Time: 50\n\nAnalyze the selected call frame.\n\nExample Response:\n\nThe selected call frame is 'animate', responsible for visual animations within 'app.js'.\nIt took 150ms total, with 20ms spent directly within the function.\nThe 'calculatePosition' and 'applyStyles' child functions consumed the remaining 130ms.\nThe 'calculatePosition' function, taking 80ms, is a potential bottleneck.\nConsider optimizing the position calculation logic or reducing the frequency of calls to improve animation performance.\n";clientFeature=s.AidaClient.ClientFeature.CHROME_PERFORMANCE_AGENT;get userTier(){return r.Runtime.hostConfig.devToolsAiAssistancePerformanceAgent?.userTier}get options(){const e=r.Runtime.hostConfig.devToolsAiAssistancePerformanceAgent?.temperature,t=r.Runtime.hostConfig.devToolsAiAssistancePerformanceAgent?.modelId;return{temperature:e,modelId:t}}async*handleContextDetails(e){yield{type:"context",title:_(W),details:[{title:"Selected call tree",text:e?.getItem().serialize()??""}]}}#R=new WeakSet;async enhanceQuery(e,t){const n=t?.getItem();let i=n?.serialize();n&&this.#R.has(n)&&i&&(i=void 0),n&&!this.#R.has(n)&&this.#R.add(n);return`${i?`${i}\n\n# User request\n\n`:""}${e}`}}class Y extends G{clientFeature=s.AidaClient.ClientFeature.CHROME_PERFORMANCE_ANNOTATIONS_AGENT;async generateAIEntryLabel(e){const t=new B(e),n=(await Array.fromAsync(this.run(J,{selected:t}))).at(-1);if(n&&"answer"===n.type&&!0===n.complete)return n.text.trim();throw new Error("Failed to generate AI entry label")}}const J="## Instruction:\nGenerate a concise label (max 60 chars, single line) describing the *user-visible effect* of the selected call tree's activity, based solely on the provided call tree data.\n\n## Strict Constraints:\n- Output must be a single line of text.\n- Maximum 60 characters.\n- No full stops.\n- Focus on user impact, not internal operations.\n- Do not include the name of the selected event.\n- Do not make assumptions about when the activity happened.\n- Base the description only on the information present within the call tree data.\n- Prioritize brevity.\n- Only include third-party script names if their identification is highly confident.\n- Very important: Only output the 60 character label text, your response will be used in full to show to the user as an annotation in the timeline.\n";function V(e){return void 0===e?"":o.TimeUtilities.preciseMillisToString(e,2)}function Q(e){return void 0===e?"":V(h.Helpers.Timing.microToMilli(e))}class K{#A;#k;constructor(e){this.#A=e.insight,this.#k=e.parsedTrace}#N(){if(!this.#A.navigationId)return"";if(!this.#A.frameId||!this.#A.navigationId)return"";const e=function(e,t,n){const i=e.PageLoadMetrics.metricScoresByFrameId.get(t)?.get(n);if(!i)return null;const s=i.get("LCP");if(!s||!h.Handlers.ModelHandlers.PageLoadMetrics.metricIsLCP(s))return null;const r=s?.event;return r&&h.Types.Events.isLargestContentfulPaintCandidate(r)?{lcpEvent:r,lcpRequest:e.LargestImagePaint.lcpRequestByNavigationId.get(n),metricScore:s}:null}(this.#k,this.#A.frameId,this.#A.navigationId);if(!e)return"";const{metricScore:t,lcpRequest:n}=e,i=[`The Largest Contentful Paint (LCP) time for this navigation was ${Q(t.timing)}.`];return n?i.push(`The LCP resource was fetched from \`${n.args.data.url}\`.`):i.push("The LCP is text based and was not fetched from the network."),i.join("\n")}formatInsight(){const{title:e}=this.#A;return`## Insight Title: ${e}\n\n## Insight Summary:\n${this.#L()}\n\n## Detailed analysis:\n${this.#q()}\n\n## External resources:\n${this.#M()}`}#q(){if(h.Insights.Models.LCPPhases.isLCPPhases(this.#A)){const{phases:e,lcpMs:t}=this.#A;if(!t)return"";const n=[];return e?.ttfb&&n.push({name:"Time to first byte",value:V(e.ttfb)}),e?.loadDelay&&n.push({name:"Load delay",value:V(e.loadDelay)}),e?.loadTime&&n.push({name:"Load time",value:V(e.loadTime)}),e?.renderDelay&&n.push({name:"Render delay",value:V(e.renderDelay)}),`${this.#N()}\n\nWe can break this time down into the ${n.length} phases that combine to make up the LCP time:\n\n${n.map((e=>`- ${e.name}: ${e.value}`)).join("\n")}`}if(h.Insights.Models.LCPDiscovery.isLCPDiscovery(this.#A)){const{checklist:e,lcpEvent:t,lcpRequest:n,earliestDiscoveryTimeTs:i}=this.#A;if(!(e&&t&&n&&i))return"";const s=[];return s.push({name:e.priorityHinted.label,passed:e.priorityHinted.value}),s.push({name:e.eagerlyLoaded.label,passed:e.eagerlyLoaded.value}),s.push({name:e.requestDiscoverable.label,passed:e.requestDiscoverable.value}),`${this.#N()}\n\nThe result of the checks for this insight are:\n${s.map((e=>`- ${e.name}: ${e.passed?"PASSED":"FAILED"}`)).join("\n")}`}if(h.Insights.Models.RenderBlocking.isRenderBlocking(this.#A)){return`Here is a list of the network requests that were render blocking on this page and their duration:\n\n${this.#A.renderBlockingRequests.map((e=>X.networkRequest(e,this.#k,{verbose:!1}))).join("\n\n")}`}if(h.Insights.Models.DocumentLatency.isDocumentLatency(this.#A)){if(!this.#A.data)return"";const{checklist:e,documentRequest:t}=this.#A.data;if(!t)return"";const n=[];return n.push({name:"The request was not redirected",passed:e.noRedirects.value}),n.push({name:"Server responded quickly",passed:e.serverResponseIsFast.value}),n.push({name:"Compression was applied",passed:e.usesCompression.value}),`${this.#N()}\n\n${X.networkRequest(t,this.#k,{verbose:!0,customTitle:"Document network request"})}\n\nThe result of the checks for this insight are:\n${n.map((e=>`- ${e.name}: ${e.passed?"PASSED":"FAILED"}`)).join("\n")}`}if(h.Insights.Models.InteractionToNextPaint.isINP(this.#A)){const e=this.#A.longestInteractionEvent;if(!e)return"";return`The longest interaction on the page was a \`${e.type}\` which had a total duration of \`${Q(e.dur)}\`. The timings of each of the three phases were:\n\n1. Input delay: ${Q(e.inputDelay)}\n2. Processing duration: ${Q(e.mainThreadHandling)}\n3. Presentation delay: ${Q(e.presentationDelay)}.`}return""}#M(){switch(this.#A.insightKey){case"CLSCulprits":case"DOMSize":case"DuplicatedJavaScript":case"FontDisplay":case"ForcedReflow":case"ImageDelivery":case"NetworkDependencyTree":case"SlowCSSSelector":case"ThirdParties":case"Viewport":case"Cache":case"ModernHTTP":case"LegacyJavaScript":return"";case"DocumentLatency":return"- https://web.dev/articles/optimize-ttfb";case"InteractionToNextPaint":return"- https://web.dev/articles/inp\n- https://web.dev/explore/how-to-optimize-inp\n- https://web.dev/articles/optimize-long-tasks\n- https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing";case"LCPDiscovery":case"LCPPhases":case"RenderBlocking":return"- https://web.dev/articles/lcp\n- https://web.dev/articles/optimize-lcp"}}#L(){switch(this.#A.insightKey){case"CLSCulprits":case"DOMSize":case"DuplicatedJavaScript":case"FontDisplay":case"ForcedReflow":case"ImageDelivery":case"NetworkDependencyTree":case"SlowCSSSelector":case"ThirdParties":case"Viewport":case"Cache":case"ModernHTTP":case"LegacyJavaScript":return"";case"DocumentLatency":return"This insight checks that the first request is responded to promptly. We use the following criteria to check this:\n1. Was the initial request redirected?\n2. Did the server respond in 600ms or less? We want developers to aim for as close to 100ms as possible, but our threshold for this insight is 600ms.\n3. Was there compression applied to the response to minimize the transfer size?";case"InteractionToNextPaint":return"Interaction to Next Paint (INP) is a metric that tracks the responsiveness of the page when the user interacts with it. INP is a Core Web Vital and the thresholds for how we categorize a score are:\n- Good: 200 milliseconds or less.\n- Needs improvement: more than 200 milliseconds and 500 milliseconds or less.\n- Bad: over 500 milliseconds.\n\nFor a given slow interaction, we can break it down into 3 phases:\n1. Input delay: starts when the user initiates an interaction with the page, and ends when the event callbacks for the interaction begin to run.\n2. Processing duration: the time it takes for the event callbacks to run to completion.\n3. Presentation delay: the time it takes for the browser to present the next frame which contains the visual result of the interaction.\n\nThe sum of these three phases is the total latency. It is important to optimize each of these phases to ensure interactions take as little time as possible. Focusing on the phase that has the largest score is a good way to start optimizing.";case"LCPDiscovery":return"This insight analyzes the time taken to discover the LCP resource and request it on the network. It only applies if LCP element was a resource like an image that has to be fetched over the network. There are 3 checks this insight makes:\n1. Did the resource have `fetchpriority=high` applied?\n2. Was the resource discoverable in the initial document, rather than injected from a script or stylesheet?\n3. The resource was not lazy loaded as this can delay the browser loading the resource.\n\nIt is important that all of these checks pass to minimize the delay between the initial page load and the LCP resource being loaded.";case"LCPPhases":return"This insight is used to analyze the time spent that contributed to the final LCP time and identify which of the 4 phases (or 2 if there was no LCP resource) are contributing most to the delay in rendering the LCP element. For this insight it can be useful to get a list of all network requests that happened before the LCP time and look for slow requests. You can also look for main thread activity during the phases, in particular the load delay and render delay phases.";case"RenderBlocking":return"This insight identifies network requests that were render blocking. Render blocking requests are impactful because they are deemed critical to the page and therefore the browser stops rendering the page until it has dealt with these resources. For this insight make sure you fully inspect the details of each render blocking network request and prioritize your suggestions to the user based on the impact of each render blocking request."}}}class X{static networkRequest(e,t,n){const{url:i,statusCode:s,initialPriority:r,priority:o,fromServiceWorker:a,mimeType:l,responseHeaders:c,syntheticData:d}=e.args.data,u=`## ${n.customTitle??"Network request"}`,p=h.Helpers.Trace.getNavigationForTraceEvent(e,e.args.data.frame,t.Meta.navigationsByFrameId),m=p?.ts??t.Meta.traceBounds.min,g={start:e.ts-m,queueing:d.downloadStart-m,requestSent:d.sendStartTime-m,downloadComplete:d.finishTime-m,processingComplete:e.ts+e.dur-m},f=g.processingComplete-g.downloadComplete,y=h.Helpers.Network.isSyntheticNetworkRequestEventRenderBlocking(e),w=t.NetworkRequests.eventToInitiator.get(e),v=[];r===o?v.push(`Priority: ${o}`):(v.push(`Initial priority: ${r}`),v.push(`Final priority: ${o}`));const b=e.args.data.redirects.map(((e,t)=>{const n=e.ts-m;return`#### Redirect ${t+1}: ${e.url}\n- Start time: ${Q(n)}\n- Duration: ${Q(e.dur)}`}));return n.verbose?`${u}: ${i}\nTimings:\n- Start time: ${Q(g.start)}\n- Queued at: ${Q(g.queueing)}\n- Request sent at: ${Q(g.requestSent)}\n- Download complete at: ${Q(g.downloadComplete)}\n- Completed at: ${Q(g.processingComplete)}\nDurations:\n- Main thread processing duration: ${Q(f)}\n- Total duration: ${Q(e.dur)}${w?`\nInitiator: ${w.args.data.url}`:""}\nRedirects:${b.length?"\n"+b.join("\n"):" no redirects"}\nStatus code: ${s}\nMIME Type: ${l}\n${v.join("\n")}\nRender blocking: ${y?"Yes":"No"}\nFrom a service worker: ${a?"Yes":"No"}\n${T.formatHeaders("Response headers",c,!0)}`:`${u}: ${i}\n- Start time: ${Q(g.start)}\n- Duration: ${Q(e.dur)}\n- MIME type: ${l}${y?"\n- This request was render blocking":""}`}}const Z="Investigating network activity…",ee="Investigating main thread activity…",te=o.i18n.lockedString;class ne extends C{#A;constructor(e){super(),this.#A=e}getOrigin(){return""}getItem(){return this.#A}getIcon(){const e=a.PanelUtils.createIconElement({iconName:"performance",color:"var(--sys-color-on-surface-subtle)"},"Performance");return e.classList.add("icon"),e}getTitle(){return`Insight: ${this.#A.title()}`}getSuggestions(){switch(this.#A.insight.insightKey){case"CLSCulprits":return["How can I improve my CLS score","How can I prevent layout shifts on this page?"];case"DocumentLatency":return["How do I decrease the initial loading time of my page?","Did anything slow down the request for this document?"];case"DOMSize":return["How can I reduce the size of my DOM?"];case"DuplicatedJavaScript":return["How do I deduplicate the identified scripts in my bundle?"];case"FontDisplay":return["How can I update my CSS to avoid layout shifts caused by incorrect `font-display` properties?"];case"ForcedReflow":return["How can I avoid layout thrashing?","What is forced reflow and why is it problematic?"];case"ImageDelivery":return["What should I do to improve and optimize the time taken to fetch and display images on the page?"];case"InteractionToNextPaint":return["Help me optimize my INP score","Help me understand why a large INP score is problematic","What was the biggest contributor to my longest interaction duration time?"];case"LCPDiscovery":return["Help me optimize my LCP score","What can I do to reduce my LCP discovery time?","Why is LCP discovery time important?"];case"LCPPhases":return["Help me optimize my LCP score","Which LCP phase was most problematic?","What can I do to reduce the LCP time for this page load?"];case"NetworkDependencyTree":return["How do I optimize my network dependency tree?"];case"RenderBlocking":return["Show me the render blocking requests, listed by impact","How can I reduce the number of render blocking requests?"];case"SlowCSSSelector":return["How can I optimize my CSS to increase the performance of CSS selectors?"];case"ThirdParties":return["Which third parties are having the largest impact on my page performance?"];case"Cache":return["What caching strategies can I apply to improve my page performance?"];case"Viewport":return["How do I make sure my page is optimized for mobile viewing?"];case"ModernHTTP":return["Is my site being served using the recommended HTTP best practices?"];case"LegacyJavaScript":return["Is my site polyfilling modern JavaScript features?"];default:p.assertNever(this.#A.insight.insightKey,"Unknown insight key")}}}class ie extends I{#A;#$;async*handleContextDetails(e){if(!e)return;const t=e.getItem(),n=t.title(),i=`Analyzing insight: ${n}`,s={title:n,text:new K(t).formatInsight()};yield{type:"context",title:i,details:[s]}}type="performance-insight";preamble="You are an AI-powered web performance optimization expert, simulating a highly skilled Chrome DevTools user. Your goal is to provide actionable advice to web developers based on Chrome Performance Panel insights.\n\nYou will be provided with an Insight from the Chrome Performance Panel. This Insight will contain information about the performance of the web site. It is your task to analyze the data available to you and suggest solutions to improve the performance of the page.\n\nYou will be told the following information about the Insight:\n- **Insight Title:** The name of the performance issue detected by Chrome DevTools.\n- **Insight Summary:** A brief explanation of the performance problem and its potential impact on the user experience.\n- **Detailed Analysis:** Specific data points and observations from the Chrome Performance Panel, including timestamps, durations, resource URLs, and function call stacks. Use this data to pinpoint the root cause of the performance issue.\n\nYou will be provided with a list of relevant URLs containing up-to-date information regarding web performance optimization. Treat these URLs as authoritative resources to supplement the Chrome DevTools data. Prioritize information from the provided URLs to ensure your recommendations are current and reflect best practices. Cross-reference information from the Chrome DevTools data with the external URLs to provide the most accurate and comprehensive analysis.\n\n*IMPORTANT*: All time units provided in the 'Detailed Analysis' are in milliseconds (ms). Ensure your response reflects this unit of measurement.\n\n## Step-by-step instructions\n\n- Utilize the provided functions (e.g., `getMainThreadActivity`, `getNetworkActivitySummary`) to retrieve detailed performance data. Prioritize function calls that provide context relevant to the Insight being analyzed.\n- Retrieve all necessary data through function calls before generating your response. Do not rely on assumptions or incomplete information.\n- Provide clear, actionable recommendations. Avoid technical jargon unless necessary, and explain any technical terms used.\n- Prioritize recommendations based on their potential impact on performance. Focus on the most significant bottlenecks.\n- Structure your response using markdown headings and bullet points for improved readability.\n- Your answer should contain the following sections:\n 1. **Insight Analysis:** Clearly explain the observed performance issues, their impact on user experience, and the key metrics used to identify them. Include relevant timestamps and durations from the provided data.\n 2. **Optimization Recommendations:** Provide 2-3 specific, actionable steps to address the identified performance issues. Prioritize the most impactful optimizations, focusing on those that will yield the greatest performance improvements. Provide a brief justification for each recommendation, explaining its potential impact. Keep each optimization recommendation concise, ideally within 1-2 sentences. Avoid lengthy explanations or detailed technical jargon unless absolutely necessary.\n 3. **Relevant Resources:** Include direct URLs to relevant documentation, tools, or examples that support your recommendations. Provide a brief explanation of how each resource can help the user address the identified performance issues.\n- Your response should immediately start with the \"Insight Analysis\" section.\n- Whenever possible, include direct URLs to relevant documentation, tools, or examples to support your recommendations. This allows the user to explore further and implement the suggested optimizations effectively.\n- Be direct and to the point. Avoid unnecessary introductory phrases or filler content. Focus on delivering actionable advice efficiently.\n\n## Strict Constraints\n\n- Adhere to the following critical requirements:\n - Execute `getMainThreadActivity` only once *per Insight context*. If the Insight changes, you may call this function again.\n - Execute `getNetworkActivitySummary` only once *per Insight context*. If the Insight changes, you may call this function again.\n - Ensure comprehensive data retrieval through function calls to provide accurate and complete recommendations.\n - Do not mention function names (e.g., `getMainThreadActivity`, `getNetworkActivitySummary`) in your output. These are internal implementation details.\n - Do not mention that you are an AI, or refer to yourself in the third person. You are simulating a performance expert.\n";clientFeature=s.AidaClient.ClientFeature.CHROME_PERFORMANCE_INSIGHTS_AGENT;get userTier(){return"TESTERS"}get options(){return{temperature:void 0,modelId:void 0}}constructor(e){super(e),this.declareFunction("getNetworkActivitySummary",{description:"Returns a summary of network activity for the selected insight. If you want to get more detailed information on a network request, you can pass the URL of a request into `getNetworkRequestDetail`.",parameters:{type:6,description:"",nullable:!0,properties:{}},displayInfoFromArgs:()=>({title:te(Z),action:"getNetworkActivitySummary()"}),handler:async()=>{if(v("Function call: getNetworkActivitySummary"),!this.#A)return{error:"No insight available"};const e=this.#A.getItem();return{result:{requests:u.InsightAIContext.AIQueries.networkRequests(e.insight,e.parsedTrace).map((t=>X.networkRequest(t,e.parsedTrace,{verbose:!1})))}}}}),this.declareFunction("getNetworkRequestDetail",{description:"Returns detailed debugging information about a specific network request",parameters:{type:6,description:"",nullable:!0,properties:{url:{type:1,description:"The URL of the network request",nullable:!1}}},displayInfoFromArgs:e=>({title:te(`Investigating network request ${e.url}…`),action:`getNetworkRequestDetail('${e.url}')`}),handler:async e=>{if(v("Function call: getNetworkRequestDetail",e),!this.#A)return{error:"No insight available"};const t=this.#A.getItem(),n=u.InsightAIContext.AIQueries.networkRequest(t.parsedTrace,e.url);if(!n)return{error:"Request not found"};return{result:{request:X.networkRequest(n,t.parsedTrace,{verbose:!0})}}}}),this.declareFunction("getMainThreadActivity",{description:"Returns the main thread activity for the selected insight.\n\nThe tree is represented as a call frame with a root task and a series of children.\nThe format of each callframe is:\n\n Node: $id – $name\n Selected: true\n dur: $duration\n self: $self\n URL #: $url_number\n Children:\n * $child.id – $child.name\n\nThe fields are:\n\n* name: A short string naming the callframe (e.g. 'Evaluate Script' or the JS function name 'InitializeApp')\n* id: A numerical identifier for the callframe\n* Selected: Set to true if this callframe is the one the user selected.\n* url_number: The number of the URL referenced in the \"All URLs\" list\n* dur: The total duration of the callframe (includes time spent in its descendants), in milliseconds.\n* self: The self duration of the callframe (excludes time spent in its descendants), in milliseconds. If omitted, assume the value is 0.\n* children: An list of child callframes, each denoted by their id and name",parameters:{type:6,description:"",nullable:!0,properties:{}},displayInfoFromArgs:()=>({title:te(ee),action:"getMainThreadActivity()"}),handler:async()=>{if(v("Function call: getMainThreadActivity"),!this.#A)return{error:"No insight available"};const e=this.#A.getItem(),t=u.InsightAIContext.AIQueries.mainThreadActivity(e.insight,e.parsedTrace);return t?{result:{activity:t.serialize()}}:{error:"No main thread activity found"}}})}parseTextResponse(e){const t=e.trim(),n="`````";if(t.startsWith(n)&&t.endsWith(n)){const e=t.slice(5,-5);return super.parseTextResponse(e)}return super.parseTextResponse(e)}async enhanceQuery(e,t){if(!t)return e;const n=new K(t.getItem()),i=`${(t!==this.#$?n.formatInsight()+"\n\n":"")+"# User request:\n"}${e}`;return this.#$=t,i}async*run(e,t){return this.#A=t.selected??void 0,yield*super.run(e,t)}}function se(e,t=2){const n=p.StringUtilities.toKebabCaseKeys(e);return Object.entries(n).map((([e,n])=>`${" ".repeat(t)}${e}: ${n};`)).join("\n")}class re{#D=new e.Mutex.Mutex;#F=new Map;#P=new Map;#O=new Map;async stashChanges(){for(const[e,t]of this.#F.entries()){const n=Array.from(t.values());await Promise.allSettled(n.map((async t=>{this.#O.set(t,this.#P.get(t)??[]),this.#P.delete(t),await e.setStyleSheetText(t,"",!0)})))}}dropStashedChanges(){this.#O.clear()}async popStashedChanges(){const e=Array.from(this.#F.entries());await Promise.allSettled(e.map((async([e,t])=>{const n=Array.from(t.entries());return await Promise.allSettled(n.map((async([t,n])=>{const i=this.#O.get(n)??[];return await Promise.allSettled(i.map((async n=>await this.addChange(e,t,n))))})))})))}async clear(){const e=Array.from(this.#F.keys()),t=await Promise.allSettled(e.map((async e=>{await this.#U({data:e})})));this.#F.clear(),this.#P.clear(),this.#O.clear();const n=t.find((e=>"rejected"===e.status));n&&console.error(n.reason)}async addChange(e,t,n){const i=await this.#H(e,t),s=this.#P.get(i)||[],r=s.find((e=>e.className===n.className));r?(Object.assign(r.styles,n.styles),r.groupId=n.groupId):s.push(n);const o=this.#j(s);return await e.setStyleSheetText(i,o,!0),this.#P.set(i,s),o}formatChangesForPatching(e,t=!1){return Array.from(this.#P.values()).flatMap((n=>n.filter((t=>t.groupId==