browsentic 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -180,5 +180,5 @@ ${t}
180
180
  return entries;
181
181
  })()`}function Gd(e,t,n){if(!document.documentElement.hasAttribute(`data-browsentic-toolkit`))throw new I(`No toolkit is installed in this page.`,Hd);let r=crypto.randomUUID();return new Promise((i,a)=>{let o=e=>{let t=Kd(e.detail);t?.id===r&&(c(),t.ok?i(t.value??null):a(new I(t.error??`The function threw.`,Ud)))},s=setTimeout(()=>{c(),a(new I(`“${e}” did not finish within ${n}ms.`,`TIMEOUT`))},n);function c(){clearTimeout(s),window.removeEventListener(Bd,o)}window.addEventListener(Bd,o),window.dispatchEvent(new CustomEvent(zd,{detail:JSON.stringify({id:r,fn:e,args:t})}))})}function Kd(e){if(typeof e!=`string`)return null;try{return JSON.parse(e)}catch{return null}}var qd=F({name:`page.runCode`,description:`Call one function from the toolkit page.injectCode installed in this tab, with fresh arguments. This is the cheap, repeatable half of the pair: the user approved the code once, so every call runs without another prompt, and a page reload re-installs the approved toolkit on its own. It refuses if nothing is installed here, or if the tab has moved to a different site than the one the code was approved on — inject again in either case. The function’s return value comes back as JSON.`,input:N({function:k().min(1).describe("Name of a function the installed toolkit assigned onto `tools`."),args:$a(Ya()).default([]).describe(`Arguments passed to the function, in order. JSON values only — this is where per-call data like a tag name belongs.`),timeoutMs:j().int().min(100).max(12e4).default(1e4).describe(`How long the call may run before it is abandoned. Raise it for functions that wait on the page.`)}),async execute({function:e,args:t,timeoutMs:n}){return{function:e,returned:await Gd(e,t,n)}}}),Jd=F({name:`page.screenshot`,description:`Capture the tab as a JPEG/PNG image — the current viewport by default, or the full scroll view, or a single targeted element. The viewport capture is the fast one: it is a single grab that returns in well under a second. fullPage: true has to scroll the page in viewport-sized steps and wait out the browser’s capture rate limit between each, so it costs a second or more per screenful — ask for it only when you need what is below the fold. Nothing is written to disk unless you pass save: true — the image comes back in the result either way, so a capture you take to look at the page for yourself leaves no file behind.`,input:N({target:z.optional().describe(`Capture only this element’s box (a specific block). When set, fullPage is ignored.`),fullPage:M().default(!1).describe(`With no target: false (the default) captures only the current viewport and is much faster; true captures the entire scroll view by tiling, which costs roughly a second per screenful.`),format:P([`png`,`jpeg`]).default(`jpeg`).describe(`Image format. JPEG (the default) is far smaller and quicker to encode; PNG is lossless and keeps transparency, at several times the size and time.`),quality:j().int().min(1).max(100).optional().describe(`JPEG quality, 1–100, defaulting to 80. Only valid when format is "jpeg".`),maxLongSide:j().int().positive().default(1600).describe(`Downscale the result so its longest side is at most this many pixels. The default is sized for reading a page, not for pixel-level inspection — raise it when fine detail matters.`),save:M().default(!1).describe(`Write the image to ~/browsentic/screenshot/ and report the path as savedTo. Off by default: a capture you take to see the page for yourself is handed to you in the result and should leave nothing behind. Set true only when the user asked for a picture they can keep.`),filename:k().optional().describe(`Base filename when saving; defaults to screenshot-<timestamp>.<ext>. Sanitized before use.`)}),execute({target:e,fullPage:t,format:n,quality:r,maxLongSide:i}){if(r!==void 0&&n!==`jpeg`)throw new I(`"quality" only applies when format is "jpeg"`,`INVALID_INPUT`);let a=window.devicePixelRatio||1,o={w:window.innerWidth,h:window.innerHeight},s=document.documentElement,c={w:s.scrollWidth,h:s.scrollHeight},l,u;if(e){let t=dc(B(e));if(t.width===0||t.height===0)throw new I(`Target element has no visible box to capture`,`INVALID_TARGET`);l=`element`,u={x:t.x,y:t.y,w:t.width,h:t.height}}else t?(l=`fullPage`,u={x:0,y:0,w:c.w,h:c.h}):(l=`viewport`,u={x:Math.round(window.scrollX),y:Math.round(window.scrollY),w:o.w,h:o.h});let d={x:Math.round(window.scrollX),y:Math.round(window.scrollY)};return{mode:l,dpr:a,viewport:o,page:c,region:u,scroll:d,format:n,quality:r,maxLongSide:i}}}),Yd=F({name:`page.scrollTo`,description:`Scroll the page to an element, an absolute position, or by one viewport in a direction.`,input:N({target:z.optional().describe(`Element to bring into view`),position:N({x:j().default(0).describe(`Document x coordinate`),y:j().describe(`Document y coordinate`)}).optional().describe(`Absolute document coordinates to scroll to`),direction:P([`up`,`down`,`top`,`bottom`]).optional().describe(`Scroll one viewport up or down, or jump to an edge`),behavior:P([`smooth`,`instant`]).default(`smooth`).describe(`Animation of the scroll`)}),async execute({target:e,position:t,direction:n,behavior:r}){if(e)B(e).scrollIntoView({behavior:r,block:`center`});else if(t)window.scrollTo({left:t.x,top:t.y,behavior:r});else{let e={up:window.scrollY-window.innerHeight,down:window.scrollY+window.innerHeight,top:0,bottom:document.documentElement.scrollHeight}[n??`down`];window.scrollTo({top:e,behavior:r})}return r===`smooth`&&await Xd(),{scrollX:Math.round(window.scrollX),scrollY:Math.round(window.scrollY)}}});function Xd(){return new Promise(e=>{let t=()=>{window.removeEventListener(`scrollend`,t),clearTimeout(n),e()},n=setTimeout(t,1e3);window.addEventListener(`scrollend`,t)})}var Zd=F({name:`page.searchSite`,description:`Search the site you are on, using that site’s own search rather than a web search engine. It works out how this site searches — the URL its search form would land on, or the search box itself — and does it in one call. Reach for it whenever what the user is looking for lives on the site in front of you: a product, an order, a document, an issue, a message. A web search is for things this site does not know about. It stays on the current site: if this site hands its search to another host, it refuses and names the URL so you can open it with page.navigate. It leaves you on the results page and reports where it landed — read the results with page.getPageInfo or page.extractText afterwards, and act on them with the ordinary tools.`,input:N({query:k().min(1).max(200).describe(`What to look for on this site`),strategy:P([`auto`,`url`,`field`]).default(`auto`).describe(`How to search: "auto" goes straight to the site’s search URL when one can be worked out and types into the box otherwise, "url" insists on the URL, "field" insists on typing — which is what a search box that filters as you type needs`),target:z.optional().describe(`The search box to use, when the page has several or the one picked was wrong`)}),execute({query:e,strategy:t,target:n}){let r=Qd(n),i=t===`field`?null:$l(r,e);if(i){if(i.url.origin!==location.origin)throw tf(i.url.href);return location.assign(i.url.href),{searchedFor:e,via:`url`,templateFrom:i.from,navigatingTo:i.url.href,field:r?tu(r):void 0}}if(t===`url`)throw new I(`No search URL could be worked out here — this site’s search is not a GET form and the address carries no query parameter. Try strategy "field".`,`TARGET_NOT_FOUND`);return $d(r,e)}});function Qd(e){return e?Yl(B(e,{includeHidden:!0})):Jl(ql())}function $d(e,t){if(!e)throw new I(`No search box on this page. Call page.findSearch to see what search this site does have, if any.`,`TARGET_NOT_FOUND`);if(e.hidden)throw new I(`The search box on this page is hidden${ef()}.`,`TARGET_NOT_FOUND`);let n=e.form?.getAttribute(`action`),r=n&&new URL(n,location.href);if(r&&r.origin!==location.origin)throw tf(r.href);e.element.focus();let{submitted:i}=wl(e.element,t,{clear:!0,pressEnter:!0});return{searchedFor:t,via:`field`,submitted:i,field:tu(e)}}function ef(){let e=Xl(ql())[0];return e?` — click ${V(e)} to reveal it, then search again`:`, and nothing on the page reveals it`}function tf(e){return new I(`This site hands its search to another host. Open ${e} with page.navigate instead, so it goes through the usual checks.`,`UNSUPPORTED`)}var nf=F({name:`page.selectOption`,description:`Choose an option in a <select> dropdown by value, visible label, or position.`,input:N({target:z.describe(`The select element`),value:k().optional().describe(`Match by option value`),label:k().optional().describe(`Match by visible option text, case-insensitive`),index:j().int().nonnegative().optional().describe(`Match by option position`)}),execute({target:e,value:t,label:n,index:r}){let i=B(e);if(!(i instanceof HTMLSelectElement))throw new I(`Target <${i.tagName.toLowerCase()}> is not a <select>`,`INVALID_TARGET`);let a=[...i.options],o;if(t!==void 0)o=a.find(e=>e.value===t);else if(n!==void 0){let e=n.trim().toLowerCase();o=a.find(t=>(t.label||t.text).trim().toLowerCase()===e)}else if(r!==void 0)o=a[r];else throw new I(`Provide a "value", "label", or "index" to choose`,`INVALID_INPUT`);if(!o){let e=a.slice(0,20).map(e=>(e.label||e.text).trim());throw new I(`No option matches ${JSON.stringify({value:t,label:n,index:r})}; options are: ${e.join(`, `)}`,`TARGET_NOT_FOUND`)}return Object.getOwnPropertyDescriptor(HTMLSelectElement.prototype,`value`).set.call(i,o.value),i.dispatchEvent(new Event(`input`,{bubbles:!0})),i.dispatchEvent(new Event(`change`,{bubbles:!0})),{selected:{value:o.value,label:o.label||o.text,index:o.index}}}}),rf=F({name:`page.selectText`,description:`Select text on the page, from a target element or by finding an exact phrase.`,input:N({target:z.optional().describe(`Element whose entire text content to select`),search:k().optional().describe(`Exact text to find and select, case-insensitive`),occurrence:j().int().nonnegative().default(0).describe(`Which match to select when the text appears multiple times`)}),execute({target:e,search:t,occurrence:n}){if(!!e==!!t)throw new I(`Provide either "target" or "search"`,`INVALID_INPUT`);let r=document.createRange();if(e)r.selectNodeContents(B(e));else if(t){let e=af(),i=e.map(e=>e.node.data).join(``),a=t.toLowerCase(),o=-1;for(let e=0,t=0;t<=n&&(o=i.toLowerCase().indexOf(a,e),o!==-1);t++)e=o+1;if(o===-1)throw new I(`Text "${t}" not found on the page`,`TARGET_NOT_FOUND`);r.setStart(...of(e,o)),r.setEnd(...of(e,o+t.length))}let i=getSelection();i?.removeAllRanges(),i?.addRange(r);let a=r.startContainer;return(a instanceof Element?a:a.parentElement)?.scrollIntoView({block:`center`}),{selectedText:(i?.toString()??``).slice(0,500)}}});function af(){let e=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT),t=[],n=0,r;for(;r=e.nextNode();){let e=r.parentElement;!e||e.closest(`script,style`)||!sc(e)||(t.push({node:r,start:n}),n+=r.data.length)}return t}function of(e,t){for(let n of e)if(t<=n.start+n.node.data.length)return[n.node,t-n.start];let n=e[e.length-1];return[n.node,n.node.data.length]}var sf=F({name:`page.solveCaptcha`,description:`Tick a captcha’s “I am a human” checkbox with a real browser-level click and wait for the widget to settle. Works where an ordinary click cannot reach: the checkbox lives inside a closed shadow root inside a cross-origin iframe, and it only responds to genuine pointer input. Returns state "solved" when the widget accepted it. When the vendor escalates to a challenge a person has to answer — an image grid, Arkose, AWS WAF — it returns state "needsHuman" with the widget bounds and does not attempt the challenge; screenshot that region, tell the user it needs them, and poll page.findCaptcha until they are done. State "invisible" means a scoring captcha with nothing to click. Chrome only, shows the debugger bar while it runs, and it is gated for approval because it acts on another site’s security control.`,input:N({waitMs:j().int().min(0).max(12e4).default(2e4).describe(`How long to wait after clicking for the widget to report a verdict.`),timeoutMs:j().int().min(1e3).max(18e4).default(6e4).describe(`Overall budget for the whole attempt, including finding the widget.`)}),execute(){throw new I(`page.solveCaptcha is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),cf=F({name:`page.startDiagnostics`,description:`Start recording what a page reports rather than what it shows — console messages, uncaught exceptions and every request the tab makes. Console and network events only exist while Chrome’s debugger is attached, so this has to be running before the thing you are diagnosing happens: start it, then reload or click, then read. Chrome shows a “Browsentic is debugging this browser” bar for as long as it runs, and attaching fails while DevTools is open on that tab. Read what it collected with page.readConsole and page.readNetwork, and end it with page.stopDiagnostics. Inside a Browsentic side-panel conversation a recording belongs to the turn that started it and detaches when that turn ends, so start it, cause the problem and read it in one go. Chrome only.`,input:N({capture:$a(P([`console`,`network`])).default([`console`,`network`]).describe(`What to record. Narrow it to one when the other would only add noise.`),reload:M().default(!1).describe(`Reload the page once recording has started, so errors thrown during load are caught — they are otherwise long gone by the time anything attaches`),tabId:j().int().optional().describe(`Tab to record, from page.openTab or page.switchTab. Defaults to the active tab.`),timeoutMs:j().int().min(ad).max(sd).default(od).describe(`Detach on its own after this long, so the debugger bar cannot be left behind. Chrome will not fire an alarm sooner than 30 s.`)}),execute(){throw new I(`page.startDiagnostics is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),lf=F({name:`page.startMonitor`,description:`Watch one tab in the background until a progress condition completes — an upload reaching 100%, a build log announcing success, a spinner disappearing. Returns a monitorId immediately; the extension pins the tab, keeps watching with no further tool calls even while the user works elsewhere, and notifies them on completion. Call page.findProgress first to pick a real signal. Check on it with page.monitorStatus, block for it with page.awaitMonitor, end it with page.stopMonitor.`,input:N({until:N({kind:P([`element-appears`,`element-vanishes`,`text-matches`,`progress-reaches`,`title-matches`]).describe(`What ends the watch`),target:z.optional().describe(`Element to watch — required for element-appears, element-vanishes and progress-reaches; optional scope for text-matches`),pattern:k().max(200).optional().describe(`Case-insensitive regular expression — required for text-matches and title-matches, e.g. "upload complete|processing finished"`),threshold:j().min(1).max(100).default(100).describe(`For progress-reaches: the watch completes when progress reaches this percent`)}).describe(`The condition that completes the watch`),label:k().max(80).optional().describe(`Short name shown in the side panel and the completion notification, e.g. "YouTube upload"`),tabId:j().int().optional().describe(`Tab to watch, from page.openTab or page.switchTab. Defaults to the active tab.`),timeoutMs:j().int().positive().max(bc).default(yc).describe(`Give up and report a timeout after this long`)}),execute(){throw new I(`page.startMonitor is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),uf=3e4,df=1440*6e4,ff=2e3,pf=6e4,mf=`browsentic/timer:`,hf=e=>`${mf}${e}`,gf=`browsentic-timer:`;function _f(e){let t=Math.round(e/1e3);if(t<90)return`${t}s`;let n=Math.round(t/60);return n<90?`${n} min`:`${Number((e/36e5).toFixed(1))}h`}function vf(e){return e.repeat?`every ${_f(e.afterMs)}, up to ${e.maxRuns} times`:`once in ${_f(e.afterMs)}`}var yf=F({name:`page.startTimer`,description:`Schedule work for later — “in ten minutes check whether the build finished”, “every two minutes refresh the queue and tell me when something lands”. Returns a timerId immediately; the extension keeps the schedule with no further tool calls and wakes this conversation with your prompt each time it fires, so set it and end your turn. Reach for page.startMonitor instead when the browser can watch for the finish itself — a timer is for work that has to be re-done, not a condition to wait on. Check on it with page.timerStatus, end it with page.stopTimer.`,input:N({prompt:k().min(1).max(ff).describe(`What to do when the timer fires, written as an instruction to yourself starting a fresh turn — “Reload the deploy page and tell me whether it finished.” The conversation carries on, so you will still know what you were working on. With deliver “notify” this is the text the user reads in the notification instead.`),afterMs:j().int().min(uf).max(df).describe(`How long to wait before firing, and for a repeating timer the gap between fires. 30 seconds is the shortest interval the browser can keep.`),repeat:M().default(!1).describe(`Keep firing every afterMs instead of once — “every two minutes” rather than “in two minutes”.`),maxRuns:j().int().min(1).max(500).default(12).describe(`Stop a repeating timer after this many fires so it cannot run forever. Ignored when repeat is false.`),label:k().max(80).optional().describe(`Short name shown in the side panel and in notifications, e.g. “deploy check”.`),deliver:P([`agent`,`notify`]).default(`agent`).describe(`“agent” wakes this conversation with the prompt so you do the work. “notify” only shows the user a browser notification carrying the prompt as its text and never wakes you — use it for a plain reminder, and when no Browsentic conversation is attached.`)}),execute(){throw new I(`page.startTimer is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),bf=F({name:`page.stopDiagnostics`,description:`Detach the debugger and take Chrome’s “Browsentic is debugging this browser” bar away. What was collected stays readable by page.readConsole and page.readNetwork afterwards, minus response bodies, which only exist while attached. Call this as soon as you have what you need rather than leaving the bar up.`,input:N({diagnosticsId:k().optional().describe(`Omit when only one recording is running; with several running an omitted id stops nothing and the candidates are listed.`)}),execute(){throw new I(`page.stopDiagnostics is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),xf=F({name:`page.stopMonitor`,description:`Stop a background monitor before it completes. The tab is unpinned again if the monitor pinned it. No notification is shown — the stop was asked for.`,input:N({monitorId:k().optional().describe(`Omit when only one monitor is running; with several running an omitted id stops nothing and the candidates are listed.`)}),execute(){throw new I(`page.stopMonitor is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),Sf=F({name:`page.stopTimer`,description:`Cancel a scheduled job before it has run out. Nothing further fires and no notification is shown — the stop was asked for.`,input:N({timerId:k().optional().describe(`Omit when only one timer is scheduled; with several an omitted id stops nothing and the candidates are listed.`)}),execute(){throw new I(`page.stopTimer is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),Cf=F({name:`page.submitForm`,description:`Submit a form, firing its submit event and validation as if the user pressed Enter.`,input:N({target:z.optional().describe(`The form, or any element inside it; defaults to the first form on the page`)}),execute({target:e}){let t=e?B(e).closest(`form`):document.querySelector(`form`);if(!t)throw new I(`No form found to submit`,`TARGET_NOT_FOUND`);return typeof t.requestSubmit==`function`?t.requestSubmit():t.submit(),{form:V(t),action:t.getAttribute(`action`)||void 0,method:(t.getAttribute(`method`)||`get`).toLowerCase()}}}),wf=F({name:`page.switchTab`,description:`Bring another open tab to the front, making it the tab every later page action targets. Call it with no arguments to list the open tabs and their ids first.`,input:N({tabId:j().int().optional().describe(`Id of the tab to switch to, as reported by page.openTab or a no-argument page.switchTab.`),match:k().optional().describe(`Instead of an id, switch to the tab whose title or URL contains this text (case-insensitive). If several tabs match, nothing is switched and the candidates are listed.`)}),execute(){throw new I(`page.switchTab is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),Tf=F({name:`page.timerStatus`,description:`Report on scheduled jobs started with page.startTimer: how many times each has fired, how many fires were skipped because the conversation was still busy, when the next one is due, and the latest log lines.`,input:N({timerId:k().optional().describe(`One timer to report. Omit to list every scheduled and recently finished timer.`)}),execute(){throw new I(`page.timerStatus is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),Ef=F({name:`page.trustedClick`,description:`Click with a real browser-level mouse event — isTrusted is true, exactly as if the user had clicked. The pointer travels to the target over a short path and dwells before pressing, so widgets that only react after genuine pointer movement (drag handles, hover menus, canvas tools, captcha checkboxes) see the sequence they wait for. Use it when page.clickElement was ignored: pages that check event.isTrusted, and the browser features only a genuine gesture unlocks — native file pickers, fullscreen, clipboard reads, popups, WebAuthn prompts. Give it either a "target" or a raw viewport "point". It attaches Chrome’s debugger for the duration, so the browser shows a “Browsentic is debugging this browser” bar while it runs, it cannot run on a tab that has DevTools open, and it is unavailable on Firefox. page.clickElement stays the default for ordinary clicks.`,input:N({target:z.optional().describe(`Element to click. Give this or "point", never both.`),point:Vc.optional().describe(`Exact viewport coordinates to click, in CSS pixels. Use this when the thing to click has no reachable element — inside a cross-origin iframe or a closed shadow root, as page.findCaptcha reports.`),button:P([`left`,`right`,`middle`]).default(`left`).describe(`Mouse button to press`),clickCount:j().int().min(1).max(3).default(1).describe(`1 for a single click, 2 for a double click, 3 for a triple click`),modifiers:$a(P([`ctrl`,`shift`,`alt`,`meta`])).default([]).describe(`Modifier keys held during the click, e.g. ["meta"] to open a link in a new tab`),scrollIntoView:M().default(!0).describe(`Bring the element into view before clicking. Ignored with "point".`),moveSteps:j().int().min(1).max(60).default(8).describe(`Pointer move events dispatched along the way in. Raise it for widgets that sample the path.`),hoverMs:j().int().min(0).max(2e3).default(60).describe(`Pause on the target after arriving, before pressing.`),holdMs:j().int().min(0).max(2e3).default(50).describe(`How long the button stays down between press and release.`)}),execute({target:e,point:t,button:n,clickCount:r,modifiers:i,scrollIntoView:a,moveSteps:o,hoverMs:s,holdMs:c}){if(!e==!t)throw new I(`Give either a "target" to click or a "point" to click at — not both, not neither`,`INVALID_INPUT`);let l=e?B(e):null;l&&a&&l.scrollIntoView({block:`center`,behavior:`instant`});let u=l?Uc(l):Wc(t);l&&qc(l,u);let d=Kc(u);return{...l?H(l):{over:d?V(d):void 0},point:u,from:Gc(u),button:n,clickCount:r,modifiers:i,moveSteps:o,hoverMs:s,holdMs:c,submits:l?fc(l):!1}}}),Df={slow:400,natural:220,fast:110,instant:0},Of={".":3,"?":3,"!":3,"\n":2.5,",":2,";":2,":":2},kf=12e4,Af=(e,t)=>[...e].map(e=>t*(Of[e]??1)),jf=(e,t)=>Math.round(e.reduce((e,t)=>e+t,0)*(1+t)),Mf=e=>new Promise(t=>setTimeout(t,e)),Nf=F({name:`page.typeText`,description:`Stream text into a field one keystroke at a time, at a human pace — a real key event per character, pauses that vary, and longer breaths after punctuation. Use page.fillInput when you just need the value in the field; use this when the page should watch someone type.`,input:N({target:z.optional().describe(`Element to type into; defaults to the currently focused element`),text:k().min(1).max(2e3).describe(`Text to type, character by character`),speed:P([`slow`,`natural`,`fast`,`instant`]).default(`natural`).describe(`Typing pace: "slow" ≈ 30 wpm, "natural" ≈ 55 wpm, "fast" ≈ 110 wpm, "instant" fires every keystroke back to back with no pause`),charDelayMs:j().int().min(0).max(2e3).optional().describe(`Average milliseconds between keystrokes; overrides "speed" when given`),jitter:j().min(0).max(1).default(.35).describe(`How much each pause varies at random, as a fraction of it — 0 types in an even machine rhythm, 1 is wildly uneven`),clear:M().default(!0).describe(`Replace existing content instead of appending`),pressEnter:M().default(!1).describe(`Press Enter afterwards, which submits many forms`)}),async execute({target:e,text:t,speed:n,charDelayMs:r,jitter:i,clear:a,pressEnter:o}){let s=e?B(e):document.activeElement??document.body;if(!(s instanceof HTMLInputElement||s instanceof HTMLTextAreaElement)&&!s.isContentEditable)throw new I(`<${s.tagName.toLowerCase()}> is not an editable element`,`INVALID_TARGET`);if(t.includes(`
182
182
  `)&&s instanceof HTMLInputElement)throw new I(`A single-line <input> cannot take newlines — drop them from "text", or set pressEnter to submit`,`INVALID_INPUT`);let c=r??Df[n],l=Af(t,c),u=jf(l,i);if(u>kf)throw new I(`Typing ${t.length} characters at ${c}ms each would take about ${Math.round(u/1e3)}s — raise "speed", lower "charDelayMs", or send the text in shorter pieces`,`INVALID_INPUT`);a&&Ff(s),If(s);let d=performance.now(),f=[...t];for(let[e,t]of f.entries()){let n=e?Math.round(l[e-1]*(1+(Math.random()*2-1)*i)):0;n>0&&await Mf(n),Rf(s,t)}let p=!1;if(o){let e=Sl(`Enter`),t=s.dispatchEvent(new KeyboardEvent(`keydown`,e));if(s.dispatchEvent(new KeyboardEvent(`keyup`,e)),t&&!(s instanceof HTMLTextAreaElement)){let e=s.closest(`form`);e?.requestSubmit(),p=!!e}}return{element:H(s),typed:f.length,charDelayMs:c,elapsedMs:Math.round(performance.now()-d),appended:!a,submitted:p}}});function Pf(e,t){let n=e instanceof HTMLInputElement?HTMLInputElement.prototype:HTMLTextAreaElement.prototype;Object.getOwnPropertyDescriptor(n,`value`)?.set?.call(e,t)}function Ff(e){e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement?Pf(e,``):e.textContent=``,e.dispatchEvent(new InputEvent(`input`,{bubbles:!0,inputType:`deleteContentBackward`}))}function If(e){if(e.focus(),e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){let t=e.value.length;try{e.setSelectionRange(t,t)}catch{}return}let t=document.createRange();t.selectNodeContents(e),t.collapse(!1);let n=window.getSelection();n?.removeAllRanges(),n?.addRange(t)}function Lf(e,t){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){let n=e.selectionStart??e.value.length,r=e.selectionEnd??e.value.length;Pf(e,e.value.slice(0,n)+t+e.value.slice(r));let i=n+t.length;try{e.setSelectionRange(i,i)}catch{}}else if(document.execCommand(`insertText`,!1,t))return;else e.textContent=(e.textContent??``)+t;e.dispatchEvent(new InputEvent(`input`,{bubbles:!0,data:t,inputType:`insertText`}))}function Rf(e,t){let n=Sl(t===`
183
- `?`Enter`:t);e.dispatchEvent(new KeyboardEvent(`keydown`,n))&&(e.dispatchEvent(new KeyboardEvent(`keypress`,n)),Lf(e,t)),e.dispatchEvent(new KeyboardEvent(`keyup`,n))}var zf=F({name:`page.waitForElement`,description:`Wait until an element reaches a state: attached, visible, hidden, or detached.`,input:N({target:z.describe(`Element to wait for`),state:P([`attached`,`visible`,`hidden`,`detached`]).default(`visible`).describe(`State to wait for: present in the DOM, present and visible, invisible or absent, or absent`),timeoutMs:j().int().positive().max(3e4).default(5e3).describe(`Give up after this many milliseconds`)}),async execute({target:e,state:t,timeoutMs:n}){let r=()=>{try{return B(e,{includeHidden:!0})}catch(e){if(e instanceof I&&e.code===`INVALID_TARGET`)throw e;return null}},i=e=>({attached:!!e,visible:!!e&&sc(e),hidden:!e||!sc(e),detached:!e})[t],a=performance.now(),o=r();return i(o)?{state:t,elapsedMs:0,element:o?H(o):void 0}:(await new Promise((e,a)=>{let s=()=>{o=r(),i(o)&&(d(),e())},c=new MutationObserver(s);c.observe(document.documentElement,{subtree:!0,childList:!0,attributes:!0});let l=setInterval(s,250),u=setTimeout(()=>{d(),a(new I(`Timed out after ${n}ms waiting for element to be ${t}`,`TIMEOUT`))},n),d=()=>{c.disconnect(),clearInterval(l),clearTimeout(u)}}),{state:t,elapsedMs:Math.round(performance.now()-a),element:o?H(o):void 0})}}),Bf=new Map([vu,Yd,Lc,Ef,El,sf,ju,cl,du,Cl,Nf,nf,rf,yl,td,nd,Cf,zf,Mu,qd,Iu,Pc,Al,uu,Cd,hc,Hs,cf,vd,yd,bf,lf,Lu,Nc,xf,yf,Tf,Sf,Au,Zd,Bu,Vu,wf,fu,Rc,Jd,Pu,pc,Fc,Nu,Fu,bd].map(e=>[e.name,e]));function Vf(){return[...Bf.values()].map(({name:e,description:t,input:n})=>({name:e,description:t,inputSchema:ea(n,{io:`input`})}))}var Hf=`data-browsentic-frame`,Uf=`browsentic/frameFocus`,Wf=null;async function Gf(){return Wf||(Wf=(await t.storage.session.get(`browsentic/frameFocus`))[`browsentic/frameFocus`]??{},Wf)}async function Kf(e){Wf=e,await t.storage.session.set({[Uf]:e})}async function qf(e){return(await Gf())[String(e)]??[]}async function Jf(e){return(await qf(e)).at(-1)?.frameId??0}async function Yf(e,t){return(await qf(e)).at(-1)?.url??t}async function Xf(e,t){let{[String(e)]:n,...r}=await Gf();await Kf(t.length?{...r,[String(e)]:t}:r)}function Zf(e){return Xf(e,[])}function Qf(){t.tabs.onRemoved.addListener(e=>void Zf(e)),t.tabs.onUpdated.addListener((e,t)=>{t.status===`loading`&&Zf(e)})}async function $f(e,n,r){try{return await t.tabs.sendMessage(e,{channel:`browsentic/frame`,...r},{frameId:n})??null}catch{return null}}var ep=(e,t)=>$f(e,t,{op:`describe`}),tp=(e,t,n)=>$f(e,t,{op:`mark`,token:n}),np=(e,t)=>$f(e,t,{op:`unmark`}),rp=(e,t,n)=>$f(e,t,{op:`locate`,frameId:n});async function ip(e){let t=await qf(e),n={x:0,y:0},r=0;for(let{frameId:i}of t){let t=await rp(e,r,i);if(!t)return null;n={x:n.x+t.x,y:n.y+t.y},r=i}return n}var ap=`the frame in focus is gone or blocks scripts — call page.switchFrame with no arguments to return to the top document`,op=`Receiving end does not exist`,sp=new Set([`page.getPageInfo`,`page.extractText`,`page.waitForElement`,`page.navigate`]);async function U(e,t,...[n]){return cp(e,await Jf(e),t,n)}async function cp(e,r,i,...[a]){let o=typeof i==`string`?i:i.name,c=async()=>await t.tabs.sendMessage(e,{channel:n,action:o,input:a},{frameId:r}),l=e=>s(`TAB_UNREACHABLE`,r===0?`${e} — the page may not allow content scripts`:`${e} — ${ap}`);try{return await c()}catch(t){let n=t instanceof Error?t.message:String(t);if(!n.includes(op)||!await up(e,r))return l(n);if(!sp.has(o))return s(`TAB_UNREACHABLE`,`This tab had no content script; one has just been injected and the tab is reachable now. Take a fresh page.getPageInfo snapshot — the page may have changed — then retry the action.`);try{return await c()}catch(e){return s(`TAB_UNREACHABLE`,`${e instanceof Error?e.message:String(e)} — the content script was injected but the page still did not answer`)}}}var lp=5e3;async function up(e,n=0){let r=(t.runtime.getManifest().content_scripts??[]).flatMap(e=>e.js??[]);if(!r.length)return!1;try{return await dp(t.scripting.executeScript({target:{tabId:e,frameIds:[n]},files:r,injectImmediately:!0})),!0}catch{return!1}}function dp(e){return Promise.race([e,new Promise((e,t)=>setTimeout(()=>t(Error(`injection timed out`)),lp))])}var fp=`browsentic.`;`${fp}`;var pp=`${fp}startRecording`,mp=`${fp}stopRecording`;`${fp}`,`${fp}`;var hp=`browsentic/record`,gp=2e3,_p=15*6e4,vp=13*6e4,yp=/pass|ssn|card|cvv|cvc|otp|secret|token|pin\b/i,bp=/cc-|new-password|current-password|one-time-code/i;function xp(e){let t=(e.type??``).toLowerCase();return t===`password`||t===`hidden`||bp.test(e.autocomplete??``)||yp.test(e.name??``)||yp.test(e.id??``)?!0:Sp(e.value??``)}function Sp(e){let t=e.replace(/[\s-]/g,``);if(!/^\d{13,19}$/.test(t))return!1;let n=0,r=!1;for(let e=t.length-1;e>=0;--e){let i=t.charCodeAt(e)-48;r&&(i*=2,i>9&&(i-=9)),n+=i,r=!r}return n%10==0}function Cp(e){try{return new URL(e).hostname.toLowerCase()}catch{return``}}function wp(e){try{return new URL(e).origin}catch{return``}}var Tp={head:0,tail:0},Ep=[[`pass`,`word`],[`pass`,`wd`],[`pass`,`phrase`],[`pass`,`code`],[`pwd`],[`otp`],[`one`,`time`,`code`]],Dp=[[`secret`],[`token`],[`api`,`key`],[`access`,`key`],[`access`,`token`],[`secret`,`key`],[`client`,`secret`],[`refresh`,`token`],[`auth`,`token`],[`authorization`],[`bearer`],[`credential`],[`credentials`],[`signing`,`key`],[`private`,`key`],[`connection`,`string`]],Op=[[`cookie`],[`session`,`id`],[`session`,`key`],[`session`,`token`],[`csrf`,`token`],[`xsrf`,`token`]],kp=e=>e.map(e=>e.join(String.raw`[_\-\s]?`)).join(`|`),Ap=kp(Ep),jp=kp(Dp),Mp=kp(Op),Np=[[`password`,Ep],[`token`,Dp],[`cookie`,Op]];function Pp(e){let t=e.toLowerCase().replace(/[^a-z0-9]/g,``);if(!t)return null;let n=t.endsWith(`s`)?[t,t.slice(0,-1)]:[t];for(let[e,t]of Np)if(t.some(e=>n.some(t=>t.endsWith(e.join(``)))))return e;return null}[...Ep,...Dp,...Op].map(e=>e.join(`_`));var Fp=String.raw`(?:Bearer\s+|Basic\s+|Token\s+)?(?:"([^"\r\n]{4,400})"|'([^'\r\n]{4,400})'|([^\s,;&"'<>{}\[\]]{4,400}))`,Ip=e=>new RegExp(String.raw`(?<![A-Za-z0-9])(?:${e})["']?\s*[:=]\s*${Fp}`,`gi`),Lp=String.raw`(?:"([^"\r\n]{4,400})"|'([^'\r\n]{4,400})'|([^\s"'<>]{3,399}[^\s"'<>.,;:!?]))`,Rp=e=>new RegExp(String.raw`(?<![A-Za-z0-9])(?:${e})\s+(?:is|are|was|will\s+be)\s*:?\s+${Lp}`,`gi`),zp=/\d|[!@#$%^&*()_+=\[\]{}|\\<>~/&]|[a-z][A-Z]/;function Bp(e){return e.length>=6&&Hp(e)&&zp.test(e)}var Vp=/^(?:null|nil|none|true|false|undefined|n\/?a|empty|blank|test|demo|example|sample|changeme|hidden|redacted|your[-_\s].*|my[-_\s].*|x{3,}|\*+|•+|\.{3,}|…+|-+|_+|\[[^\]]*\]|<[^>]*>|\{\{.*\}\}|\$\{.*\})$/i;function Hp(e){return Vp.test(e)||/^(.)\1*$/.test(e)?!1:!e.includes(`…`)}var Up=[{id:`private-key`,kind:`private-key`,guard:`-----begin`,pattern:/-----BEGIN(?:[A-Z ]{0,32})PRIVATE KEY-----[A-Za-z0-9+/=\s]{0,8000}-----END(?:[A-Z ]{0,32})PRIVATE KEY-----/g},{id:`jwt`,kind:`jwt`,guard:`eyj`,pattern:/\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}/g},{id:`anthropic-key`,kind:`api-key`,guard:`sk-ant-`,pattern:/\bsk-ant-[A-Za-z0-9_-]{16,}/g,reveal:{head:7,tail:0}},{id:`openai-key`,kind:`api-key`,guard:`sk-`,pattern:/\bsk-(?:proj-|svcacct-|admin-)?[A-Za-z0-9_-]{20,}/g,reveal:{head:3,tail:0}},{id:`google-key`,kind:`api-key`,guard:`aiza`,pattern:/\bAIza[0-9A-Za-z_-]{35}\b/g,reveal:{head:4,tail:0}},{id:`aws-access-key`,kind:`api-key`,pattern:/\b(?:AKIA|ASIA|AIDA|AROA|AGPA|ANPA)[0-9A-Z]{16}\b/g,reveal:{head:4,tail:0}},{id:`github-pat`,kind:`token`,guard:`github_pat_`,pattern:/\bgithub_pat_[A-Za-z0-9_]{40,}/g,reveal:{head:11,tail:0}},{id:`github-token`,kind:`token`,guard:`gh`,pattern:/\bgh[pousr]_[A-Za-z0-9]{30,}/g,reveal:{head:4,tail:0}},{id:`slack-token`,kind:`token`,guard:`xox`,pattern:/\bxox[abposr]-[A-Za-z0-9-]{10,}/g,reveal:{head:4,tail:0}},{id:`stripe-key`,kind:`api-key`,guard:`k_`,pattern:/\b[rs]k_(?:live|test)_[A-Za-z0-9]{16,}/g,reveal:{head:8,tail:0}},{id:`npm-token`,kind:`token`,guard:`npm_`,pattern:/\bnpm_[A-Za-z0-9]{36}\b/g,reveal:{head:4,tail:0}},{id:`gitlab-token`,kind:`token`,guard:`glpat-`,pattern:/\bglpat-[A-Za-z0-9_-]{20,}/g,reveal:{head:6,tail:0}},{id:`sendgrid-key`,kind:`api-key`,guard:`sg.`,pattern:/\bSG\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}/g,reveal:{head:3,tail:0}},{id:`basic-auth`,kind:`password`,guard:`@`,pattern:/\bhttps?:\/\/[^\s/:@]{1,64}:([^\s/@]{3,128})@/g},{id:`cookie-header`,kind:`cookie`,guard:`cookie`,pattern:/(?:^|\n)[ \t]*(?:set-)?cookie[ \t]*:[ \t]*([^\r\n]{4,4000})/gi},{id:`labelled-password`,kind:`password`,pattern:Ip(Ap),validate:Hp},{id:`labelled-token`,kind:`token`,pattern:Ip(jp),validate:Hp},{id:`labelled-cookie`,kind:`cookie`,pattern:Ip(Mp),validate:Hp},{id:`prose-password`,kind:`password`,pattern:Rp(Ap),validate:Bp},{id:`prose-token`,kind:`token`,pattern:Rp(jp),validate:Bp},{id:`card`,kind:`card`,pattern:/\b\d(?:[ -]?\d){12,18}\b/g,reveal:{head:0,tail:4},validate:Sp}],Wp=/(?<![A-Za-z0-9+/_=-])[A-Za-z0-9+/_-]{32,4096}={0,2}(?![A-Za-z0-9+/_-])/g,Gp=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Kp=4.3,qp=.5,Jp=/\bdata:[^\s;,]{0,80};base64,[A-Za-z0-9+/=]+/g;function Yp(e,t=[]){if(!e)return[];let n=[...t,...tm(e,Jp)].sort((e,t)=>e.start-t.start),r=e.toLowerCase(),i=[],a=e=>{nm(n,e)||(n.push(e),n.sort((e,t)=>e.start-t.start),i.push(e))};for(let t of Up)if(!(t.guard&&!r.includes(t.guard)))for(let n of e.matchAll(t.pattern)){let e=Xp(n);e&&(t.validate&&!t.validate(e.value)||a({...e,kind:t.kind,shape:t.id,reveal:t.reveal??Tp}))}for(let t of e.matchAll(Wp)){let e=t[0];Zp(e)&&a({start:t.index,end:t.index+e.length,value:e,kind:`secret`,shape:`high-entropy`,reveal:Tp})}return i.sort((e,t)=>e.start-t.start)}function Xp(e){if(e.index===void 0)return null;let t=e.slice(1).find(e=>e!==void 0);if(t===void 0)return{start:e.index,end:e.index+e[0].length,value:e[0]};if(!t)return null;let n=e[0].lastIndexOf(t);return n<0?null:{start:e.index+n,end:e.index+n+t.length,value:t}}function Zp(e){return e.length<32||Gp.test(e)||/^[0-9a-f]+$/i.test(e)||!/[a-z]/.test(e)||!/[A-Z]/.test(e)||!/[0-9]/.test(e)?!1:em(e)>=Kp&&Qp(e)>=qp}function Qp(e){let t=e.replace(/[^A-Za-z]/g,``);if(t.length<2)return 0;let n=0;for(let e=1;e<t.length;e+=1)$p(t[e])!==$p(t[e-1])&&(n+=1);return n/(t.length-1)}var $p=e=>e===e.toUpperCase();function em(e){let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=0;for(let r of t.values()){let t=r/e.length;n-=t*Math.log2(t)}return n}function tm(e,t){return[...e.matchAll(t)].map(e=>({start:e.index,end:e.index+e[0].length}))}function nm(e,t){return e.some(e=>t.start<e.end&&e.start<t.end)}var rm=/⟦([a-z-]+):([0-9a-z]+)(?:@([A-Za-z0-9._:\[\]-]{1,255}))?#([0-9a-f]{6,32})⟧/g;function im(e,t){let n=e.origin?`@${e.origin}`:``;return`⟦${e.kind}:${e.id}${n}#${t}⟧`}function am(e,t){return e.includes(`⟦`)?[...e.matchAll(rm)].map(e=>({kind:e[1],id:e[2],origin:e[3],tag:e[4],text:e[0]})).filter(e=>!t||e.tag===t):[]}function om(e,t){if(!e||e.length<4)return{value:e,found:[]};let n=fm(e,t.tag),r=t.tag?pm(e,n):e,i=Yp(r,n);if(!i.length)return{value:r,found:[]};let a=[],o=``,s=0;for(let e of i){let n=t.mint(e.value,e.kind,e.shape);a.push({kind:e.kind,shape:e.shape,handle:n}),o+=r.slice(s,e.start)+dm(e.value,e.reveal,n),s=e.end}return{value:o+r.slice(s),found:a}}var sm=new Set([`selector`]),cm=4;function lm(e,t){let n=[],r=(e,r)=>{let i=Yp(e).find(t=>t.start===0&&t.end===e.length),a=i?{kind:i.kind,shape:i.shape,reveal:i.reveal}:{kind:r,shape:`keyed`,reveal:Tp},o=t.mint(e,a.kind,a.shape);return n.push({kind:a.kind,shape:a.shape,handle:o}),dm(e,a.reveal,o)},i=(e,a,o)=>{if(typeof e==`string`){if(e.startsWith(`data:`))return e;if(o&&e.length>=cm&&Hp(e)&&!am(e).length)return r(e,o);let i=om(e,t);return n.push(...i.found),i.value}if(a>=mm||typeof e!=`object`||!e)return e;if(Array.isArray(e))return e.map(e=>i(e,a+1,o));let s={};for(let[t,n]of Object.entries(e))s[t]=sm.has(t)?n:i(n,a+1,Pp(t));return s};return{value:i(e,0,null),found:n}}function um(e,t,n){let r=[],i=[];return{text:e.replace(rm,(e,a,o,s,c)=>{let l={kind:a,id:o,origin:s,tag:c,text:e};if(c!==t)return i.push(l),e;let u=n(l);return u===null?(i.push(l),e):(r.push(l),u)}),released:r,unresolved:i}}function dm(e,t,n){let r=Math.max(0,e.length-4),i=e.slice(0,Math.min(t.head,r)),a=t.tail&&e.length-t.tail>i.length?e.slice(-t.tail):``;return`${i}${i?`…`:``}${n}${a?`…`:``}${a}`}function fm(e,t){return e.includes(`⟦`)?[...e.matchAll(rm)].filter(e=>!t||e[4]===t).map(e=>({start:e.index,end:e.index+e[0].length})):[]}function pm(e,t){if(!e.includes(`⟦`)&&!e.includes(`⟧`))return e;let n=e=>t.some(t=>e>=t.start&&e<t.end),r=``;for(let t=0;t<e.length;t+=1){let i=e[t];n(t)?r+=i:i===`⟦`?r+=`⟨`:i===`⟧`?r+=`⟩`:r+=i}return r}var mm=12,hm={"page.fillInput":[`value`],"page.typeText":[`text`]},gm=`A sealed secret can only be released into page.fillInput “value” or page.typeText “text”. Browsentic swaps the placeholder for the real value at the moment it reaches the page, so the secret is never yours to move: pass the placeholder through unchanged and let the field it belongs in do it.`,_m=`That sealed secret is no longer held — it expired, or it was read in an earlier browser session. Read the value from the page again, or ask the user for it.`;function vm(e){return hm[e]??[]}function ym(e,t,n,r){let i=vm(e),a=[],o=[],s=[];if(!t||typeof t!=`object`||Array.isArray(t))return{input:t,released:a,refused:bm(t,o),unresolved:s};let c={};for(let[e,l]of Object.entries(t)){if(i.includes(e)&&typeof l==`string`){let t=um(l,n,r);a.push(...t.released),s.push(...t.unresolved),c[e]=t.text;continue}bm(l,o),c[e]=l}return{input:c,released:a,refused:o,unresolved:s}}function bm(e,t,n=0){if(typeof e==`string`)t.push(...am(e));else if(n<12&&e&&typeof e==`object`)for(let r of Object.values(e))bm(r,t,n+1);return t}var xm=`browsentic/secrets`,Sm=120*6e4,Cm=Promise.resolve();function wm(e){let t=Cm.then(e,e);return Cm=t.catch(()=>void 0),t}function Tm(e,t){return wm(async()=>{let n=await Dm(),r=Date.now(),i=n.entries.filter(e=>r-e.at<Sm),a=[],o=lm(e,{mint:(e,o,s)=>{let c=[...i,...a].find(n=>n.value===e&&n.origin===t);if(c)return c.at=r,im(c,n.tag);let l={id:jm(),value:e,kind:o,shape:s,origin:t,at:r};return a.push(l),im(l,n.tag)},tag:n.tag});return(a.length||i.length!==n.entries.length)&&await Om({tag:n.tag,entries:[...i,...a].slice(-64)}),o})}function Em(e,t){return wm(async()=>{let n=await Dm(),r=Date.now(),i=[],a=ym(e,t,n.tag,e=>{let t=n.entries.find(t=>t.id===e.id);return!t||r-t.at>=Sm?null:(t.at=r,i.push(t),t.value)});return i.length&&await Om(n),a})}async function Dm(){let e=(await t.storage.session.get(xm).catch(()=>({})))[xm];if(e?.tag&&Array.isArray(e.entries))return{tag:e.tag,entries:e.entries};let n={tag:Am(),entries:[]};return await Om(n),n}function Om(e){return t.storage.session.set({[xm]:e}).catch(()=>void 0)}var km=e=>[...crypto.getRandomValues(new Uint8Array(e))].map(e=>e.toString(16).padStart(2,`0`)).join(``),Am=()=>km(8),jm=()=>km(4),Mm=[{id:`turnstile`,label:`Cloudflare Turnstile`,kind:`checkbox`,hostMarkers:[`.cf-turnstile`,`#cf-turnstile`,`#challenge-stage`,`#cf-challenge-running`,`#challenge-running`],frame:`challenges.cloudflare.com`,checkbox:`input[type="checkbox"]`,solvedInPage:`!!document.querySelector('input[name="cf-turnstile-response"]')?.value`},{id:`recaptcha-v2`,label:`reCAPTCHA v2`,kind:`checkbox`,hostMarkers:[`.g-recaptcha`,`#g-recaptcha`,`iframe[src*="recaptcha/api2/anchor"]`,`iframe[src*="recaptcha/enterprise/anchor"]`],frame:`recaptcha/api2/anchor`,challengeFrame:`recaptcha/api2/bframe`,checkbox:`#recaptcha-anchor`,solvedInFrame:`!!document.querySelector('#recaptcha-anchor.recaptcha-checkbox-checked')`,solvedInPage:`!!document.querySelector('textarea#g-recaptcha-response')?.value`},{id:`hcaptcha`,label:`hCaptcha`,kind:`checkbox`,hostMarkers:[`.h-captcha`,`[data-hcaptcha-widget-id]`,`iframe[src*="hcaptcha.com/captcha"]`],frame:`frame=checkbox`,challengeFrame:`frame=challenge`,checkbox:`#checkbox`,solvedInPage:`!!document.querySelector('textarea[name="h-captcha-response"]')?.value`},{id:`geetest`,label:`GeeTest`,kind:`checkbox`,hostMarkers:[`.geetest_holder`,`.geetest_radar_tip`,`.geetest_btn`],checkbox:`.geetest_radar_tip`,solvedInPage:`!!document.querySelector('.geetest_success_radar_tip')`},{id:`arkose`,label:`Arkose FunCaptcha`,kind:`interactive`,hostMarkers:[`#funcaptcha`,`#arkose`,`[data-pkey]`,`iframe[src*="arkoselabs.com"]`],frame:`arkoselabs.com`},{id:`aws-waf`,label:`AWS WAF Captcha`,kind:`interactive`,hostMarkers:[`#captcha-container`,`script[src*="captcha.awswaf.com"]`,`iframe[src*="awswaf.com"]`],frame:`awswaf.com`},{id:`recaptcha-v3`,label:`reCAPTCHA v3`,kind:`invisible`,hostMarkers:[`script[src*="recaptcha/api.js?render="]`,`script[src*="recaptcha/enterprise.js?render="]`],solvedInPage:`!!document.querySelector('textarea#g-recaptcha-response')?.value`}],Nm=t.debugger,Pm=`1.3`,Fm=250,Im=150,Lm=4,W=e=>new Promise(t=>setTimeout(t,e)),Rm=new Set;function zm(){Nm.onEvent.addListener((e,t,n)=>{for(let r of Rm)r(e,t,n)})}function Bm(e){return Rm.add(e),()=>Rm.delete(e)}async function Vm(e){try{return await Nm.attach({tabId:e},Pm),{ok:!0}}catch(e){return{ok:!1,message:Jm(e)}}}async function Hm(e){let t={tabId:e};await G(t,`Target.setAutoAttach`,Km).catch(()=>{}),await Nm.detach(t).catch(()=>{})}function Um(e){Nm.onDetach.addListener((t,n)=>{t.tabId!=null&&e(t.tabId,n)})}function G(e,t,n){return Nm.sendCommand(e,t,n)}async function Wm(e,t,n){let r={tabId:e};try{await Nm.attach(r,Pm)}catch(e){return s(`DEBUGGER_UNAVAILABLE`,Jm(e))}try{return await W(Fm),await n(r)}catch(e){return s(`ACTION_FAILED`,e instanceof Error?e.message:String(e))}finally{await G(r,`Target.setAutoAttach`,Km).catch(()=>{}),await Nm.detach(r).catch(()=>{})}}var Gm={autoAttach:!0,flatten:!0,waitForDebuggerOnStart:!1,filter:[{type:`iframe`}]},Km={autoAttach:!1,flatten:!0,waitForDebuggerOnStart:!1};async function qm(e){let t=[],n=Bm((e,n,r)=>{if(n!==`Target.attachedToTarget`)return;let i=r;i?.targetInfo?.type===`iframe`&&t.push({sessionId:i.sessionId,url:i.targetInfo.url,parent:e.sessionId})});try{let n=[e];for(let r=0;r<Lm&&n.length;r+=1){let r=t.length;for(let e of n)await G(e,`Target.setAutoAttach`,Gm).catch(()=>{});await W(Im),n=t.slice(r).map(({sessionId:t})=>({tabId:e.tabId,sessionId:t}))}}finally{n()}return t}function Jm(e){let t=e instanceof Error?e.message:String(e);return/already attached|another debugger/i.test(t)?`${t} — close DevTools for this tab, then retry.`:`${t} — Chrome’s debugger could not attach to this tab.`}var Ym={alt:1,ctrl:2,meta:4,shift:8},Xm={left:1,right:2,middle:4},Zm=12,Qm=`A trusted click needs Chrome’s debugger, which Firefox does not expose — use page.clickElement instead.`,$m=`A trusted drag needs Chrome’s debugger, which Firefox does not expose — drop "trusted" to drag with synthetic events instead.`;function eh(e,t){return Wm(e,Qm,async n=>{let r=await U(e,Ef.name,t);if(!r.ok)return r;let i=await ip(e);if(!i)return s(`TAB_UNREACHABLE`,`The click could not be placed — ${ap}`);let a=r.data;return await rh(n,{...a,point:nh(a.point,i),from:nh(a.from,i)}),o({...r.data,trusted:!0})})}function th(e,t){return Wm(e,$m,async n=>{let r=await U(e,cl.name,t);if(!r.ok)return r;let i=await ip(e);if(!i)return s(`TAB_UNREACHABLE`,`The drag could not be placed — ${ap}`);let a=r.data;return await ih(n,{...a,approach:nh(a.approach,i),grip:nh(a.grip,i),drop:nh(a.drop,i)}),o({...r.data,trusted:!0})})}var nh=(e,t)=>({x:e.x+t.x,y:e.y+t.y});async function rh(e,t){let{point:n,from:r,button:i,clickCount:a,modifiers:o,moveSteps:s,hoverMs:c,holdMs:l}=t,u={modifiers:o.reduce((e,t)=>e|(Ym[t]??0),0),pointerType:`mouse`},d=t=>G(e,`Input.dispatchMouseEvent`,t),f=e=>d({...u,...e,type:`mouseMoved`,button:`none`,buttons:0});await f(r);for(let e of Yc(r,n,s))await W(Zm),await f(e);await W(c);for(let e=1;e<=a;e+=1)await d({...u,...n,type:`mousePressed`,button:i,buttons:Xm[i],clickCount:e}),await W(l),await d({...u,...n,type:`mouseReleased`,button:i,buttons:0,clickCount:e})}async function ih(e,t){let{approach:n,grip:r,drop:i,steps:a,holdMs:o,settleMs:s}=t,c={modifiers:0,pointerType:`mouse`},l=t=>G(e,`Input.dispatchMouseEvent`,t),u=(e,t)=>l({...c,...e,type:`mouseMoved`,button:t?`left`:`none`,buttons:t});for(let e of Yc(n,r,4))await W(Zm),await u(e,0);await l({...c,...r,type:`mousePressed`,button:`left`,buttons:1,clickCount:1}),await W(o);for(let e of Yc(r,i,a))await W(Zm),await u(e,1);await W(s),await l({...c,...i,type:`mouseReleased`,button:`left`,buttons:0,clickCount:1})}var ah=`Reading a captcha needs Chrome’s debugger, which Firefox does not expose — solve the captcha in the page yourself.`,oh=500,sh={button:`left`,clickCount:1,modifiers:[],moveSteps:14,hoverMs:120,holdMs:70};function ch(e){return Wm(e,ah,async e=>{let t=await fh(e);return o(t?dh(t):{found:!1})})}function lh(e,t){let n=sf.input.safeParse(t??{});if(!n.success)return Promise.resolve(s(`INVALID_INPUT`,x(n.error)));let{waitMs:r,timeoutMs:i}=n.data;return Wm(e,ah,async e=>{let t=Date.now()+i,n=await fh(e);return n?!n.point||n.state!==`idle`?o({...dh(n),clicked:!1}):(await rh(e,uh(n.point)),o({...dh(await hh(e,n,Math.min(r,t-Date.now()))),clicked:!0})):s(`CAPTCHA_NOT_FOUND`,`No captcha widget on this page. If the page is still blocked, take a fresh page.getPageInfo — the block may be something else.`)})}function uh(e){return{point:e,from:{x:Math.max(e.x-140,0),y:Math.max(e.y-90,0)},...sh}}function dh(e){return{found:!0,vendor:e.vendor.id,label:e.vendor.label,kind:e.vendor.kind,state:e.state,solved:e.state===`solved`,hasToken:e.hasToken,bounds:e.bounds,point:e.point,note:e.note}}async function fh(e){await Sh(e);for(let t of Mm)if(await ph(e,t))return mh(e,t);return null}async function ph(e,t){for(let n of t.hostMarkers)if((await Ch(e,n)).length)return!0;return!1}async function mh(e,t){let n=t.frame?await qm(e):[],r=t.solvedInPage?await Th(e,t.solvedInPage):!1;if(r||await _h(e,t,n))return{vendor:t,frames:n,state:`solved`,hasToken:r};if(t.kind===`invisible`)return{vendor:t,frames:n,state:`invisible`,hasToken:r,note:`${t.label} scores in the background — there is nothing to click.`};if(t.challengeFrame&&await Th(e,yh(t.challengeFrame)))return{vendor:t,frames:n,state:`needsHuman`,hasToken:r,bounds:await vh(e,t.challengeFrame),note:`${t.label} has escalated to a challenge only a person can answer.`};if(t.kind===`interactive`)return{vendor:t,frames:n,state:`needsHuman`,hasToken:r,bounds:t.frame?await vh(e,t.frame):void 0,note:`${t.label} asks for a puzzle rather than a checkbox.`};let i=await gh(e,t,n);return{vendor:t,frames:n,state:i.point?`idle`:`needsHuman`,hasToken:r,bounds:i.bounds,point:i.point,note:i.note}}async function hh(e,t,n){let{vendor:r,frames:i}=t,a=Date.now()+Math.max(0,n);for(;Date.now()<a;){await W(oh);let n=r.solvedInPage?await Th(e,r.solvedInPage):!1;if(n||await _h(e,r,i))return{...t,state:`solved`,hasToken:n};if(r.challengeFrame&&await Th(e,yh(r.challengeFrame)))return{...t,state:`needsHuman`,hasToken:n,bounds:await vh(e,r.challengeFrame)??t.bounds,note:`${r.label} answered the checkbox with a challenge only a person can answer.`}}return{...t,state:`pending`,note:`${r.label} accepted the click but had not settled within the wait — call page.findCaptcha again to re-check.`}}async function gh(e,t,n){if(!t.checkbox)return{note:`${t.label} exposes no checkbox to click.`};if(!t.frame){let[n]=await Ch(e,t.checkbox),r=n?await wh(e,n):null;return r?{bounds:r,point:bh(r)}:{note:`${t.label}’s checkbox is in the page but has no box on screen — scroll it into view, then retry.`}}let[r]=await Ch(e,`iframe[src*="${t.frame}"]`),i=r?await wh(e,r):null;if(!i)return{note:`${t.label}’s widget iframe is not painted — scroll it into view, then retry.`};let a=n.find(e=>e.url.includes(t.frame));if(!a)return{bounds:i,note:`Chrome did not expose ${t.label}’s widget frame, so its checkbox cannot be located.`};let o={tabId:e.tabId,sessionId:a.sessionId};await Sh(o).catch(()=>{});let[s]=await Ch(o,t.checkbox),c=s?await wh(o,s):null;if(!c)return{bounds:i,note:`${t.label}’s widget is open but its checkbox could not be located inside the frame.`};let l={x:Math.round(i.x+c.x+c.width/2),y:Math.round(i.y+c.y+c.height/2)};return xh(i,l)?{bounds:i,point:l}:{bounds:i,note:`${t.label}’s checkbox resolved outside its own frame — refusing to click a guessed point.`}}async function _h(e,t,n){if(!t.solvedInFrame||!t.frame)return!1;let r=n.find(e=>e.url.includes(t.frame));return r?Th({tabId:e.tabId,sessionId:r.sessionId},t.solvedInFrame):!1}async function vh(e,t){let[n]=await Ch(e,`iframe[src*="${t}"]`);return(n?await wh(e,n):null)??void 0}var yh=e=>`[...document.querySelectorAll('iframe')].some((f) => f.src.includes(${JSON.stringify(e)}) && f.getBoundingClientRect().height > 40 && getComputedStyle(f).visibility !== 'hidden' && getComputedStyle(f.parentElement || f).visibility !== 'hidden')`,bh=e=>({x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}),xh=(e,t)=>t.x>=e.x&&t.x<=e.x+e.width&&t.y>=e.y&&t.y<=e.y+e.height;async function Sh(e){await G(e,`DOM.enable`),await G(e,`DOM.getDocument`,{depth:-1,pierce:!0})}async function Ch(e,t){let n=await G(e,`DOM.performSearch`,{query:t,includeUserAgentShadowDOM:!1}).catch(()=>null);if(!n?.searchId)return[];let r=n.resultCount?await G(e,`DOM.getSearchResults`,{searchId:n.searchId,fromIndex:0,toIndex:n.resultCount}).catch(()=>null):null;return await G(e,`DOM.discardSearchResults`,{searchId:n.searchId}).catch(()=>{}),r?.nodeIds??[]}async function wh(e,t){let n=(await G(e,`DOM.getBoxModel`,{nodeId:t}).catch(()=>null))?.model?.content;if(!n||n.length<8)return null;let r=[n[0],n[2],n[4],n[6]],i=[n[1],n[3],n[5],n[7]],a=Math.min(...r),o=Math.min(...i),s=Math.max(...r)-a,c=Math.max(...i)-o;return s>0&&c>0?{x:Math.round(a),y:Math.round(o),width:Math.round(s),height:Math.round(c)}:null}async function Th(e,t){return(await G(e,`Runtime.evaluate`,{expression:t,returnByValue:!0}).catch(()=>null))?.result?.value===!0}var Eh=/^[a-z0-9][a-z0-9-]{0,47}$/;function Dh(e){let t=0;for(let n=0;n<e.length;n++){let r=e.charCodeAt(n);r<128?t+=1:r<2048?t+=2:r>=55296&&r<=56319?(t+=4,n++):t+=3}return t}var Oh=48;function kh(e){let t;try{t=new URL(e)}catch{return null}if(t.protocol!==`http:`&&t.protocol!==`https:`)return null;let n=t.hostname.toLowerCase().replace(/^www\./,``);if(!n)return null;let[r=``]=t.pathname.split(`/`).filter(Boolean);return{host:n,segment:Mh(r)||`root`}}function Ah(e,t){return`${e.host}:${e.segment}:${t}`}function jh(e,t){let n=kh(t);return!!n&&n.host===e.host&&n.segment===e.segment}function Mh(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,Oh).replace(/-+$/,``)}var Nh=new Set([`a`,`an`,`and`,`for`,`from`,`in`,`of`,`on`,`the`,`this`,`to`,`with`]);function Ph(e,t){return Mh(e.toLowerCase().replace(/[^a-z0-9\s-]+/g,` `).split(/[\s-]+/).filter(e=>e&&!Nh.has(e)).join(`-`))||Mh(t)||`tool`}function Fh(e,t){let n=Mh(`tool-${e.host}-${e.segment}-${t}`).slice(0,48).replace(/-+$/,``);return Eh.test(n)?n:`tool-${Mh(t).slice(0,42)}`}var Ih=50;async function Lh(e){let t=await Jf(e.tabId);if(t===0)return{session:e};let n=crypto.randomUUID();if(!await tp(e.tabId,t,n))return null;try{let t=(await qm(e)).map(({sessionId:t})=>({tabId:e.tabId,sessionId:t}));for(let r of[e,...t])for(let e of await Rh(r))if(await zh(r,e)===n)return{session:r,contextId:e};return null}finally{np(e.tabId,t)}}async function Rh(e){let t=[],n=Bm((n,r,i)=>{if(r!==`Runtime.executionContextCreated`||n.tabId!==e.tabId||n.sessionId!==e.sessionId)return;let a=i.context;a?.auxData?.isDefault&&t.push(a.id)});try{await G(e,`Runtime.enable`),await W(Ih)}catch{return[]}finally{n(),await G(e,`Runtime.disable`).catch(()=>{})}return t}async function zh(e,t){return(await G(e,`Runtime.evaluate`,{expression:`document.documentElement.getAttribute(${JSON.stringify(Hf)})`,returnByValue:!0,contextId:t}).catch(()=>null))?.result?.value}var Bh=`browsentic/savedTools`,Vh=({code:e,...t})=>t;async function Hh(){let e=(await t.storage.local.get(Bh))[Bh];return Array.isArray(e)?e:[]}async function Uh(e){return(await Hh()).find(t=>t.id===e)??null}async function Wh(e){let n=(await Hh()).filter(t=>t.name!==e.name);await t.storage.local.set({[Bh]:[e,...n].slice(0,100)})}async function Gh(e){let n=await Hh(),r=n.find(t=>t.id===e);return r?(await t.storage.local.set({[Bh]:n.filter(t=>t.id!==e)}),Vh(r)):null}async function Kh(e,t){let n=new Set((await Hh()).map(e=>e.name)),r=Ah(e,t);if(!n.has(r))return r;for(let e=2;e<100;e++){let t=`${r}-${e}`;if(!n.has(t))return t}return`${r}-${Date.now()}`}function qh(e,t){if(!t||!kh(t))return!1;let n;try{n=new URL(t).origin}catch{return!1}return n===e.origin&&jh(e.scope,t)}var Jh=`browsentic/codeToolkits`,Yh=`Installing page code needs Chrome’s debugger, which Firefox does not expose — use the ordinary page tools instead.`,Xh=600,Zh=`Chrome’s debugger found no script context for the frame in focus — call page.switchFrame with no arguments and inject from the top document, or enter the frame again once it has loaded.`,Qh=1e3,$h=new Set;function eg(e){$h.add(e)}async function tg(){return(await t.storage.session.get(Jh))[Jh]??{}}async function ng(e,n){let r=await tg();n?r[String(e)]=n:delete r[String(e)],await t.storage.session.set({[Jh]:r})}async function rg(e){await ng(e,null)}function ig(){t.tabs.onRemoved.addListener(e=>void rg(e))}function ag(e){if(e)try{let t=new URL(e).origin;return t===`null`?void 0:t}catch{return}}async function og(e,t,n){let r=Mu.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let i=ag(t);if(!i)return s(`UNSUPPORTED`,`Page code can only be installed on an http(s) page.`);let{purpose:a,code:c,call:l}=r.data,u={id:crypto.randomUUID(),origin:i,purpose:a,code:c,entries:[],installedAt:Date.now()},d=await dg(e,u);if(!d.ok)return d;u.entries=d.data,await ng(e,u);let f={toolkitId:u.id,origin:i,purpose:a,functions:u.entries.map(e=>e.name)},p=l?await ug(e,t,{function:l.function,args:l.args}):null;return sg(u,t,l?.function),p?p.ok?o({...f,called:p.data}):o({...f,callFailed:p.error}):o(f)}function sg(e,t,n){let r=e.entries.filter(e=>e.arity===0),i=r.find(e=>e.name===n)??(r.length===1?r[0]:null),a=t?kh(t):null;!i||!a||setTimeout(()=>{let t={toolkitId:e.id,fn:i.name,purpose:e.purpose,suggestedSlug:Ph(e.purpose,i.name),host:a.host,segment:a.segment,origin:e.origin};for(let e of $h)e(t)},Qh)}async function cg(e,t,n){let r=await Uh(n);if(!r)return s(`UNKNOWN_TOOL`,`That tool is no longer saved.`);if(!qh(r,t))return s(`TOOLKIT_SCOPE`,`“${r.name}” was saved for ${r.origin}/${r.scope.segment}, and this tab is somewhere else.`);let i={id:r.id,origin:r.origin,purpose:r.description,code:r.code,entries:[],installedAt:Date.now()},a=await dg(e,i);return a.ok?(i.entries=a.data,await ng(e,i),U(e,qd.name,{function:r.fn,args:[],timeoutMs:1e4})):a}async function lg(e,t){let n=(await tg())[String(e)];return n&&n.id===t?n.code:null}async function ug(e,t,n){let r=qd.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let i=(await tg())[String(e)];if(!i)return s(Hd,`No toolkit is installed in this tab. Call page.injectCode first, and the user will be asked to approve the code.`);let a=ag(t);if(a!==i.origin)return await rg(e),s(`TOOLKIT_SCOPE`,`That toolkit was approved for ${i.origin}, but this tab is on ${a??`another page`}. Install it again here if the job continues.`);if(!i.entries.some(e=>e.name===r.data.function))return s(`UNKNOWN_FUNCTION`,`This toolkit has no function named “${r.data.function}”. It defines: ${i.entries.map(e=>e.name).join(`, `)}.`);let o=await U(e,qd.name,r.data);if(o.ok||o.error.code!==`TOOLKIT_MISSING`)return o;let c=await dg(e,i);return c.ok?U(e,qd.name,r.data):c}function dg(e,t){return Wm(e,Yh,async e=>{let n=await Lh(e);if(!n)return s(`FRAME_UNREACHABLE`,Zh);let r=await fg(n,Wd(t.id,t.code)),i=r.exceptionDetails;if(i)return s(`CODE_ERROR`,`The code failed while installing: ${pg(i)}`);let a=r.result?.value;return Array.isArray(a)?o(a):s(`CODE_ERROR`,`The code installed but reported no functions.`)})}function fg({session:e,contextId:t},n){return G(e,`Runtime.evaluate`,{expression:n,returnByValue:!0,awaitPromise:!0,...t==null?{}:{contextId:t}})}function pg(e){let t=e.exception?.description??e.text??`unknown error`;return t.length>Xh?`${t.slice(0,Xh)}…`:t}async function mg(e,t,n){let r=fu.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let i=await qf(e);if(!r.data.frame){let n=r.data.to===`top`?[]:i.slice(0,-1);return await Xf(e,n),o(gg(n,t))}let a=await U(e,fu.name,r.data);if(!a.ok)return a;let c=a.data,l=await hg(e,c.frameId);if(!l)return s(`FRAME_UNREACHABLE`,`${c.selector} cannot be entered — ${c.sandbox&&!c.sandbox.includes(`allow-scripts`)?`its sandbox forbids scripts`:`it is a browser-internal frame or has not loaded`}. page.screenshot still shows it and page.trustedClick with a "point" still reaches it.`);let u=[...i,{frameId:c.frameId,url:l.url,selector:c.selector}];return await Xf(e,u),o({entered:a.data,...gg(u,t)})}async function hg(e,t){return await ep(e,t)||(await up(e,t)?ep(e,t):null)}function gg(e,t){let n=e.at(-1);return{frame:{depth:e.length,frameId:n?.frameId??0,url:n?.url??t,path:e.map(({selector:e,url:t})=>({selector:e,url:t}))}}}var _g=`⟪browsentic:site-tool-timeout⟫`;async function vg(e){try{let t=document.modelContext,n=navigator.modelContext,r=t??n;if(!r)return{ok:!0,api:null,tools:[]};let i=t?`document.modelContext`:`navigator.modelContext`,a=r.getTools??r.listTools;if(typeof a!=`function`)return{ok:!0,api:i,tools:[]};let o=await Promise.resolve(a.call(r)),s=Array.isArray(o)?o:Array.isArray(o?.tools)?o.tools:[],c=e=>{try{return e===void 0?void 0:JSON.parse(JSON.stringify(e))}catch{return}};return{ok:!0,api:i,tools:s.filter(e=>!!e&&typeof e.name==`string`).map(t=>({name:String(t.name),description:typeof t.description==`string`?t.description.slice(0,e?500:140):void 0,...e?{inputSchema:c(t.inputSchema??t.input_schema??t.parameters),annotations:c(t.annotations)}:{}}))}}catch(e){return{ok:!1,error:String(e?.message??e)}}}async function yg(e,t,n,r){try{let i=document.modelContext,a=navigator.modelContext,o=i??a;if(!o)return{ok:!1,code:`NO_SITE_TOOLS`,error:`This site registers no WebMCP tools.`};let s=o.getTools??o.listTools;if(typeof s==`function`){let t=await Promise.resolve(s.call(o)),n=(Array.isArray(t)?t:Array.isArray(t?.tools)?t.tools:[]).map(e=>e?.name).filter(e=>typeof e==`string`);if(n.length&&!n.includes(e))return{ok:!1,code:`SITE_TOOL_NOT_FOUND`,error:`This site registers no tool named “${e}”.`,tools:n}}let c=o.executeTool??o.callTool;if(typeof c!=`function`)return{ok:!1,code:`NO_SITE_TOOLS`,error:`This site’s model context offers no way to execute a tool.`};let l=await Promise.race([Promise.resolve(c.call(o,e,t)),new Promise(e=>setTimeout(()=>e(r),n))]);if(l===r)return{ok:!1,code:`TIMEOUT`,error:`“${e}” did not finish within ${n}ms.`};try{return{ok:!0,value:l===void 0?null:JSON.parse(JSON.stringify(l))}}catch{return{ok:!1,code:`SITE_TOOL_FAILED`,error:`The tool returned something that is not JSON.`}}}catch(e){return{ok:!1,code:`SITE_TOOL_FAILED`,error:String(e?.message??e)}}}async function bg(e,n,r){try{return(await t.scripting.executeScript({target:{tabId:e,frameIds:[await Jf(e)]},world:`MAIN`,func:n,args:r}))[0]?.result??null}catch{return null}}async function xg(e){let t=await bg(e,vg,[!1]);return!t?.ok||!t.tools.length?null:{api:t.api,count:t.tools.length,tools:t.tools}}async function Sg(e,t,n){let[r,i,a]=await Promise.all([U(e,vu.name,n),xg(e),qf(e)]);return r.ok?o({...r.data,...i?{siteTools:i}:{},...a.length?gg(a,t):{}}):r}async function Cg(e,t){if(!ag(t))return s(`UNSUPPORTED`,`Site tools can only be read on an http(s) page.`);let n=await bg(e,vg,[!0]);return n?n.ok?n.tools.length?o({api:n.api,count:n.tools.length,tools:n.tools}):s(`NO_SITE_TOOLS`,`This site registers no WebMCP tools — the ordinary page tools are the way to work here.`):s(`ACTION_FAILED`,`The site’s model context failed while listing its tools: ${n.error}`):s(`UNSUPPORTED`,`Reading site tools needs main-world scripting, which this browser does not allow here.`)}async function wg(e,t,n){let r=Pc.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));if(!ag(t))return s(`UNSUPPORTED`,`Site tools can only be called on an http(s) page.`);let{tool:i,args:a,timeoutMs:c}=r.data,l=await bg(e,yg,[i,a,c,_g]);if(!l)return s(`UNSUPPORTED`,`Calling site tools needs main-world scripting, which this browser does not allow here.`);if(!l.ok){let e=l.tools?.length?` It defines: ${l.tools.join(`, `)}.`:``;return s(l.code,`${l.error}${e}`)}return o({tool:i,returned:l.value})}var Tg=15e3;async function Eg(e,n){let r=Fc.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let{target:i,url:a,timeoutMs:c}=r.data;try{Ic(r.data)}catch(e){return e instanceof I?s(e.code,e.message):s(`INVALID_INPUT`,String(e))}if(!t.downloads)return s(`DOWNLOADS_UNAVAILABLE`,`This browser build has no downloads permission — reload the Browsentic extension and accept the new permission prompt.`);let l=jg(c),u=null;try{a?l.expect(await t.downloads.download({url:a})):u=await U(e,Lc.name,{target:i})}catch(e){return l.cancel(),s(`DOWNLOAD_FAILED`,e instanceof Error?e.message:String(e))}if(u&&!u.ok)return l.cancel(),u;let d=await l.settled;if(!d.ok)return d;let f=d.data;try{await t.downloads.erase({id:f.id})}catch{}return o({triggeredBy:a?`url`:`click`,...u?.ok?{clicked:u.data}:{},item:Og(f)})}async function Dg(e){let[n]=await t.downloads.search({id:e});return n??null}function Og(e){let t=e.filename;return{browserPath:t,name:kg(t),mime:e.mime??``,size:typeof e.fileSize==`number`&&e.fileSize>0?e.fileSize:e.totalBytes??0,url:e.finalUrl||e.url,host:Ag(e.finalUrl||e.url)}}function kg(e){return e.split(/[\\/]/).pop()||`download`}function Ag(e){try{return new URL(e).hostname.toLowerCase()||void 0}catch{return}}function jg(e){let n=null,r=()=>{},i=new Promise(e=>{r=e}),a=setTimeout(()=>{n===null&&m(s(`NO_DOWNLOAD_STARTED`,`Nothing downloaded. The click may have opened a page instead — check where the tab landed, or pass the file’s url directly.`))},Math.min(Tg,e)),c=setTimeout(()=>m(s(`TIMEOUT`,`The download did not finish within ${e}ms.`)),e),l=e=>{n===null&&d(e.id)},u=e=>{e.id===n&&(e.state?.current===`complete`?p(e.id):e.state?.current===`interrupted`&&m(s(`DOWNLOAD_FAILED`,`The browser stopped the download: ${e.error?.current??`interrupted`}.`)))};function d(e){n=e,clearTimeout(a),f(e)}async function f(e){let t=await Dg(e);t?.state===`complete`?p(e):t?.state===`interrupted`&&m(s(`DOWNLOAD_FAILED`,`The browser stopped the download: ${t.error??`interrupted`}.`))}async function p(e){let t=await Dg(e);if(!t?.filename){m(s(`DOWNLOAD_FAILED`,`The download finished but the browser reported no file.`));return}m(o(t))}function m(e){clearTimeout(a),clearTimeout(c),t.downloads.onCreated.removeListener(l),t.downloads.onChanged.removeListener(u),r(e)}return t.downloads.onCreated.addListener(l),t.downloads.onChanged.addListener(u),{settled:i,expect:d,cancel:()=>m(s(`CANCELLED`,`The capture was abandoned before a download started.`))}}function Mg(e){let t=2166136261,n=JSON.stringify([...e].sort((e,t)=>e.name<t.name?-1:+(e.name>t.name)).map(({name:e,description:t,inputSchema:n})=>[e,t,n]));for(let e=0;e<n.length;e++)t^=n.charCodeAt(e),t=Math.imul(t,16777619);return(t>>>0).toString(16).padStart(8,`0`)}var Ng=16,Pg=`|`,Fg=25e4,Ig=new TextEncoder,Lg=new TextDecoder;function Rg(){return Jg(crypto.getRandomValues(new Uint8Array(Ng)))}function zg(e){return typeof e==`string`&&e.length>=16}async function Bg(e,t){let n=await crypto.subtle.importKey(`raw`,Ig.encode(e),`PBKDF2`,!1,[`deriveBits`]),r=Ig.encode(qg(`browsentic/pair`,t.clientNonce,t.serverNonce)),i=await crypto.subtle.deriveBits({name:`PBKDF2`,salt:r,iterations:Fg,hash:`SHA-256`},n,256);return Jg(new Uint8Array(i))}async function Vg(e,t){return Jg(await Gg(e,`browsentic/client`,t))}async function Hg(e,t,n){return Jg(await Gg(e,`browsentic/server`,t,qg(n.daemonVersion,n.manifestHash,String(n.manifestInSync),n.sealedSessionKey??``)))}async function Ug(e,t,n){let r=Yg(n);if(!r)return null;let i=await Kg(e,t,r.length);return Lg.decode(r.map((e,t)=>e^i[t]))}function Wg(e,t){if(typeof e!=`string`||e.length!==t.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=e.charCodeAt(r)^t.charCodeAt(r);return n===0}async function Gg(e,t,n,r=``){let i=await crypto.subtle.importKey(`raw`,Ig.encode(e),{name:`HMAC`,hash:`SHA-256`},!1,[`sign`]),a=qg(t,String(n.protocolVersion),n.extensionVersion,n.manifestHash,n.clientNonce,n.serverNonce,r);return new Uint8Array(await crypto.subtle.sign(`HMAC`,i,Ig.encode(a)))}async function Kg(e,t,n){let r=new Uint8Array(n);for(let i=0,a=0;i<n;i+=32,a++){let o=await Gg(e,`browsentic/seal`,t,String(a));r.set(o.subarray(0,Math.min(32,n-i)),i)}return r}function qg(...e){return e.join(Pg)}function Jg(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function Yg(e){try{return Uint8Array.from(atob(e.replace(/-/g,`+`).replace(/_/g,`/`)),e=>e.charCodeAt(0))}catch{return null}}var Xg=`browsentic/daemon`,Zg=`browsentic/reconnect`,Qg=`browsentic/sessionKey`,$g=1e3,e_=3e4,t_=5e3,n_=2e4,K=null,r_=0,i_,a_=null,o_=new Set,s_=null;function c_(e){s_=e}function l_(e){a_=e}function u_(e){o_.add(e)}function d_(e,t){let n=crypto.randomUUID();return q({t:`instruct`,id:n,text:e,context:t})?n:null}var f_=9e4,p_=new Map;function m_(e){let t=crypto.randomUUID();return q({t:`analyzeFile`,id:t,...e})?new Promise(e=>{let n=setTimeout(()=>{p_.delete(t),e(s(`TIMEOUT`,`The daemon did not return a summary in time.`))},f_);p_.set(t,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var h_=12e4,g_=new Map;function __(e){let t=crypto.randomUUID();return q({t:`analyzeRecording`,id:t,recording:e})?new Promise(e=>{let n=setTimeout(()=>{g_.delete(t),e(s(`TIMEOUT`,`The daemon did not return a workflow in time.`))},h_);g_.set(t,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var v_=2e4,y_=new Map;function b_(e){let t=crypto.randomUUID();return q({t:`nameSession`,id:t,...e})?new Promise(e=>{let n=setTimeout(()=>{y_.delete(t),e(s(`TIMEOUT`,`The daemon did not return a name in time.`))},v_);y_.set(t,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var x_=15e3,S_=new Map;function C_(e){return O_({t:`saveSkill`,id:crypto.randomUUID(),skill:e})}function w_(e){return O_({t:`deleteSkill`,id:crypto.randomUUID(),name:e})}function T_(e){return O_({t:`deleteSiteMap`,id:crypto.randomUUID(),name:e})}function E_(e,t=!1){return O_({t:`activateSiteMap`,id:crypto.randomUUID(),stagingId:e,exactHost:t})}function D_(e){return O_({t:`discardSiteMap`,id:crypto.randomUUID(),stagingId:e})}function O_(e){return q(e)?new Promise(t=>{let n=setTimeout(()=>{S_.delete(e.id),t(s(`TIMEOUT`,`The daemon did not answer in time.`))},x_);S_.set(e.id,e=>{clearTimeout(n),t(e)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var k_=2e4,A_=new Map;function j_(e=!1){return F_({t:`agentState`,id:crypto.randomUUID(),refresh:e})}function M_(e){return F_({t:`setAgent`,id:crypto.randomUUID(),agent:e})}function N_(e,t){return F_({t:`setAgentModel`,id:crypto.randomUUID(),agent:e,model:t})}function P_(e){return F_({t:`grantAgent`,id:crypto.randomUUID(),agent:e})}function F_(e){return q(e)?new Promise(t=>{let n=setTimeout(()=>{A_.delete(e.id),t(s(`TIMEOUT`,`The daemon did not answer in time.`))},k_);A_.set(e.id,e=>{clearTimeout(n),t(e)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var I_=new Map;function L_(e=!1){let t={t:`listSkills`,id:crypto.randomUUID(),refresh:e};return q(t)?new Promise(e=>{let n=setTimeout(()=>{I_.delete(t.id),e(s(`TIMEOUT`,`The daemon did not answer in time.`))},k_);I_.set(t.id,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var R_=new Map;function z_(){return V_({t:`guardrails`,id:crypto.randomUUID()})}function B_(e,t){return V_({t:`setGuardrail`,id:crypto.randomUUID(),setting:e,value:t})}function V_(e){return q(e)?new Promise(t=>{let n=setTimeout(()=>{R_.delete(e.id),t(s(`TIMEOUT`,`The daemon did not answer in time.`))},k_);R_.set(e.id,e=>{clearTimeout(n),t(e)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}function H_(e){return q({t:`cancel`,id:e})}function U_(e,t,n,r){q({t:`decision`,id:e,toolId:t,allow:n,remember:r})}function W_(e){q({t:`reset`,sessionId:e})}function q(e){return!K||K.readyState!==WebSocket.OPEN?!1:(iv(K,e),!0)}async function G_(){if(X_())return;let e=await cv();if(!e){await sv({connected:!1,paired:!1,error:void 0,lastChangeAt:Date.now()});return}let t=await ov();t&&!t.paired&&t.error||(clearTimeout(i_),Q_({kind:`session`,secret:e},0))}async function K_(e){let t=e.replace(/[\s-]/g,``).toUpperCase();return t?(Z_(),clearTimeout(i_),r_=0,new Promise(e=>{J_=e,Q_({kind:`pair`,secret:t},0),setTimeout(()=>Y_({ok:!1,error:`No Browsentic daemon is running. Start one with "browsentic pair".`}),n_)})):{ok:!1,error:`Enter the pairing code from "browsentic pair".`}}async function q_(){clearTimeout(i_),Z_(),await t.storage.local.remove(Qg),await sv({connected:!1,paired:!1,error:void 0,agent:void 0,lastChangeAt:Date.now()})}var J_=null;function Y_(e){J_?.(e),J_=null}function X_(){return!!K&&(K.readyState===WebSocket.OPEN||K.readyState===WebSocket.CONNECTING)}function Z_(){let e=K;if(K=null,e){e.onopen=null,e.onmessage=null,e.onclose=null;try{e.close(1e3,`client disconnecting`)}catch{}}}function Q_(e,n,r){if(n>=i.length)return tv(e,r);let a=i[n],o=new WebSocket(`ws://127.0.0.1:${a}/extension`);K=o;let s=!1,c=!1,l=r,u={credential:e,port:a,hello:{extensionVersion:t.runtime.getManifest().version,manifestHash:Mg(Vf()),nonce:Rg()},done(){s=!0,c=!0,clearTimeout(d)},walk(e){if(!s){s=!0,l=e??r,clearTimeout(d);try{o.close(1e3,`unproven daemon`)}catch{}}}},d=setTimeout(()=>u.walk(),t_);o.onopen=()=>{iv(o,{t:`hello`,protocolVersion:16,extensionVersion:u.hello.extensionVersion,manifestHash:u.hello.manifestHash,auth:{kind:e.kind},nonce:u.hello.nonce})},o.onmessage=e=>{rv(o,String(e.data),u)},o.onclose=t=>{if(clearTimeout(d),K===o&&(K=null),l??=ev(t),!c)return Q_(e,n+1,l);sv({connected:!1,paired:!0,error:void 0,lastChangeAt:Date.now()}),e.kind===`session`&&av(e)}}var $_=new Set([`unproven daemon`,``]);function ev(e){let t=e.reason?.trim();if(!(!t||$_.has(t)))return/protocol version mismatch/i.test(t)?{reason:`${t}. Rebuild and reload the extension — “yarn build”, then Reload at chrome://extensions.`,retryable:!1}:{reason:t,retryable:!0}}function tv(e,t){if(t&&!t.retryable){Y_({ok:!1,error:t.reason}),sv({connected:!1,paired:!1,error:t.reason,lastChangeAt:Date.now()});return}Y_({ok:!1,error:t?.reason??`No Browsentic daemon is running.`}),e.kind===`session`&&av(e)}function nv(e){return{protocolVersion:16,extensionVersion:e.hello.extensionVersion,manifestHash:e.hello.manifestHash,clientNonce:e.hello.nonce,serverNonce:e.serverNonce??``}}async function rv(e,n,r){let i=a(n);if(i)switch(i.t){case`ping`:return iv(e,{t:`pong`,id:i.id});case`challenge`:{if(!zg(i.nonce)||r.serverNonce)return r.walk();r.serverNonce=i.nonce;let t=nv(r);return r.secret=r.credential.kind===`pair`?await Bg(r.credential.secret,t):r.credential.secret,iv(e,{t:`prove`,proof:await Vg(r.secret,t)})}case`unauthorized`:return r.walk({reason:i.reason,retryable:i.retryable!==!1});case`welcome`:{let e=r.secret;if(!e)return r.walk();let n=nv(r),a=i.sealedSessionKey??``;if(!Wg(i.proof,await Hg(e,n,i)))return r.walk({reason:`Whatever is listening on port ${r.port} could not prove it is the Browsentic daemon.`,retryable:!0});let o=a?await Ug(e,n,a):null;if(!o&&(a||r.credential.kind===`pair`))return r.walk();r.done(),r_=0,o&&await t.storage.local.set({[Qg]:o}),Y_({ok:!0}),await sv({connected:!0,paired:!0,port:r.port,daemonVersion:i.daemonVersion,manifestInSync:i.manifestInSync,error:void 0,lastChangeAt:Date.now()});for(let e of o_)e();return}case`describe`:return iv(e,{t:`manifest`,id:i.id,tools:Vf()});case`invoke`:return iv(e,{t:`result`,id:i.id,result:await kS(i.action,i.input,i.tabId,i.runId)});case`run`:return a_?.(i.id,i.event);case`fileSummary`:p_.get(i.id)?.(i.result),p_.delete(i.id);return;case`skillResult`:S_.get(i.id)?.(i.result),S_.delete(i.id);return;case`sessionName`:y_.get(i.id)?.(i.result),y_.delete(i.id);return;case`recordingWorkflow`:g_.get(i.id)?.(i.result),g_.delete(i.id);return;case`agentInfo`:A_.get(i.id)?.(i.result),A_.delete(i.id),i.result.ok&&await sv({agent:i.result.data,lastChangeAt:Date.now()});return;case`guardrailInfo`:R_.get(i.id)?.(i.result),R_.delete(i.id);return;case`skillCatalog`:I_.get(i.id)?.(i.result),I_.delete(i.id),i.result.ok&&await sv({skillCatalog:i.result.data,lastChangeAt:Date.now()});return;case`siteMapDraft`:return s_?.(i.id,i.draft);default:return}}function iv(e,t){e.readyState===WebSocket.OPEN&&e.send(JSON.stringify(t))}function av(e){let t=Math.min(e_,$g*2**r_++)*(.5+Math.random()/2);clearTimeout(i_),i_=setTimeout(()=>Q_(e,0),t)}async function ov(){return(await t.storage.session.get(Xg))[Xg]}async function sv(e){let n=await ov()??{connected:!1,paired:!1,lastChangeAt:0};await t.storage.session.set({[Xg]:{...n,...e}})}async function cv(){let e=(await t.storage.local.get(Qg))[Qg];return typeof e==`string`&&e?e:null}var lv=`browsentic:files`,uv=e=>`browsentic:file:${e}`;async function dv(){let e=(await t.storage.local.get(lv))[lv];return Array.isArray(e)?e:[]}async function fv(e){await t.storage.local.set({[lv]:e})}async function pv(e){let n=uv(e),r=(await t.storage.local.get(n))[n];return r&&typeof r.content==`string`?r:null}async function mv(e,t){await fv((await dv()).map(n=>n.id===e?{...n,...t}:n))}async function hv(e){let t=await pv(e);if(!t){await mv(e,{status:`error`,error:`File bytes are missing from storage.`});return}let n=(await dv()).find(t=>t.id===e),r=await m_({name:t.name,mime:t.mime,size:n?.size??0,content:t.content});r.ok?await mv(e,{status:`ready`,summary:r.data.summary,digest:r.data.digest,error:void 0}):await mv(e,{status:`error`,error:`${r.error.code}: ${r.error.message}`})}var gv=RegExp(`[\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f\\u200b-\\u200f\\u202a-\\u202e\\u2066-\\u2069\\ufeff]`,`g`),_v=/^[a-zA-Z0-9 .#>+~*,_:[\]="'()-]{1,120}$/;function J(e,t){return typeof e==`string`?e.replace(/[\r\n\t]+/g,` `).replace(gv,``).replace(/^[\s#>*\-+|`~=]+/,``).replace(/[`|]/g,``).replace(/\s+/g,` `).trim().slice(0,t):``}function vv(e){return/\b(?:ignore (?:all |any )?previous|disregard (?:the |all )?(?:above|previous)|you (?:must|should|will) (?:now|always|never)|instead(?:,)? (?:navigate|go|send|email|transfer|click)|do not tell|without asking|system prompt|new instructions?)\b/i.test(e)}function yv(e){return _v.test(e)&&e.trim().split(/\s+/).length<=8}function bv(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}var xv={goal:160,summary:400,intent:120,note:160,value:200,text:80,variable:40,field:80,kind:24,caveat:200},Sv=[`page.navigate`,`page.clickElement`,`page.fillInput`,`page.selectOption`,`page.pressKey`,`page.submitForm`,`page.scrollTo`,`page.hoverElement`,`page.focusInput`,`page.selectText`,`page.waitForElement`,`page.extractText`,`page.getPageInfo`];function Cv(e,t){if(!e||typeof e!=`object`)return{ok:!1,message:`The workflow must be an object.`};let n=e,r=[],i=J(n.goal??``,xv.goal);if(!i)return{ok:!1,message:`The workflow needs a one-line goal.`};let a=J(n.summary??``,xv.summary),o=[];for(let e of Array.isArray(n.steps)?n.steps.slice(0,80):[]){let n=wv(e,t.origin,r);n&&o.push({...n,ordinal:o.length+1})}if(!o.length)return{ok:!1,message:`The workflow lists no replayable steps.`};let s=new Set,c=[];for(let e of Array.isArray(n.variables)?n.variables.slice(0,20):[]){let t=J(e?.name??``,xv.variable).replace(/[{}]/g,``);!t||s.has(t)||(s.add(t),c.push({name:t,field:J(e?.field??``,xv.field)||t,kind:J(e?.kind??``,xv.kind)||`text`}))}let l={goal:i,summary:a,steps:o,variables:c,caveats:(Array.isArray(n.caveats)?n.caveats:[]).slice(0,8).map(e=>J(e,xv.caveat)).filter(Boolean)};kv(l,r);for(let e of Dv(l))vv(e)&&r.push(`Reads like an instruction rather than an observation: “${bv(e,80)}”`);return{ok:!0,workflow:l,warnings:r}}function wv(e,t,n){let r=typeof e?.action==`string`?e.action.trim():``;if(!Sv.includes(r))return r&&n.push(`Dropped a step naming an action that cannot be replayed: ${bv(r,40)}`),null;let i=J(e?.intent??``,xv.intent);if(!i)return null;let a=Tv(e?.target,n),o=Ev(e?.url,t);return r===`page.navigate`&&!o||r!==`page.navigate`&&r!==`page.getPageInfo`&&!a?null:{ordinal:0,intent:i,action:r,target:a,value:J(e?.value??``,xv.value)||void 0,url:o||void 0,note:J(e?.note??``,xv.note)||void 0}}function Tv(e,t){if(!e||typeof e!=`object`)return;let n=typeof e.selector==`string`?e.selector.trim():``;n&&!yv(n)&&(t.push(`Dropped a step selector that did not look like a selector: ${bv(n,40)}`),n=``);let r=J(e.text??``,xv.text),i=J(e.role??``,xv.kind);if(!(!n&&!r))return{selector:n||void 0,text:r||void 0,role:i||void 0}}function Ev(e,t){if(typeof e!=`string`||!e.trim())return``;try{let n=new URL(t),r=new URL(e.trim(),t);return r.origin!==n.origin||r.protocol!==`http:`&&r.protocol!==`https:`?``:bv(r.href,300)}catch{return``}}function Dv(e){return[e.goal,e.summary,...e.steps.flatMap(e=>[e.intent,e.note??``,e.target?.text??``]),...e.variables.map(e=>e.field),...e.caveats].filter(Boolean)}function Ov(e){return Dv(e).reduce((e,t)=>e+Dh(t),0)}function kv(e,t){if(Ov(e)<=12288)return;let n=(n,r)=>{Ov(e)<=12288||(r(),t.push(`The workflow was over its size budget, so ${n} was left out.`))};for(n(`the per-step notes`,()=>{for(let t of e.steps)t.note=void 0}),n(`some of the caveats`,()=>{e.caveats=e.caveats.slice(0,3)}),n(`the longer step descriptions`,()=>{for(let t of e.steps)t.intent=bv(t.intent,60)});Ov(e)>12288&&e.steps.length>1;)e.steps.pop();e.steps.length===1&&t.push(`Only the first step fitted in the workflow.`)}var Av=`browsentic:recordings`,jv=e=>`browsentic:recording:${e}`,Mv=20;async function Nv(){let e=(await t.storage.local.get(Av))[Av];return Array.isArray(e)?e:[]}async function Pv(e){await t.storage.local.set({[Av]:e})}async function Fv(e,n){await t.storage.local.set({[jv(e.id)]:n});let r=await Nv(),i=[{...r.find(t=>t.id===e.id),...e},...r.filter(t=>t.id!==e.id)],a=i.slice(Mv);a.length&&await t.storage.local.remove(a.map(e=>jv(e.id))),await Pv(i.slice(0,Mv))}async function Iv(e){let n=jv(e),r=(await t.storage.local.get(n))[n];return r&&Array.isArray(r.events)?r:null}async function Lv(e,t){let n=await Nv();n.some(t=>t.id===e)&&await Pv(n.map(n=>n.id===e?{...n,...t,updatedAt:Date.now()}:n))}async function Rv(e){let n=(await Nv()).find(t=>t.id===e);if(!n)return;let r=await Iv(e);if(!r||!r.events.length){await Lv(e,{status:`error`,error:`The recorded steps are missing from storage.`});return}await Lv(e,{status:`analyzing`,error:void 0});let i=await __({id:n.id,name:n.name,host:n.host,startUrl:n.startUrl,captureValues:n.capturedValues,durationMs:n.durationMs,events:r.events});if(!i.ok){await Lv(e,{status:`error`,error:`${i.error.code}: ${i.error.message}`});return}let a=Cv(i.data.workflow,{origin:wp(n.startUrl)});if(!a.ok){await Lv(e,{status:`error`,error:a.message});return}await t.storage.local.set({[jv(e)]:{...r,workflow:a.workflow}}),await Lv(e,{status:`ready`,goal:a.workflow.goal,summary:a.workflow.summary,steps:a.workflow.steps.length,warnings:[...i.data.warnings,...a.warnings].slice(0,8),name:n.name===Bv(n.host,n.createdAt)?a.workflow.goal:n.name,error:void 0})}async function zv(){let e=await Nv();for(let t of e)(t.status===`analyzing`||t.error?.startsWith(`EXTENSION_OFFLINE`))&&await Rv(t.id)}function Bv(e,t){let n=new Date(t),r=`${n.getFullYear()}-${Vv(n.getMonth()+1)}-${Vv(n.getDate())} ${Vv(n.getHours())}:${Vv(n.getMinutes())}`;return`${e||`Browsing`} — ${r}`}function Vv(e){return String(e).padStart(2,`0`)}function Hv(e){return{id:e.id,name:e.name,host:e.host||Cp(e.startUrl),goal:e.goal,steps:e.steps,capturedValues:e.capturedValues,durationMs:e.durationMs}}var Uv=`browsentic/recording`,Wv=`browsentic/recording-warn`,Gv=`browsentic/recording-stop`,Kv=null;function qv(e){Kv=e}async function Jv(){let e=(await t.storage.session.get(Uv))[Uv];return e&&Array.isArray(e.events)?e:null}async function Yv(e){e?await t.storage.session.set({[Uv]:e}):await t.storage.session.remove(Uv)}function Xv(e,t){return{id:e.id,startedAt:e.startedAt,elapsedMs:Date.now()-e.startedAt,events:e.events.length,captureValues:e.captureValues,host:e.host,warning:t}}async function Zv(){let e=await Jv();return e?Xv(e):null}async function Qv(e){let t=await Jv(),n=!!t&&t.tabId===e;return{recording:n,captureValues:n?t.captureValues:!1}}async function $v(e){let n=(await t.tabs.query({active:!0,currentWindow:!0}))[0];return n?.id==null||!n.url?s(`NO_ACTIVE_TAB`,`No active tab to record.`):ey({tabId:n.id,url:n.url,captureValues:e})}async function ey(e){if(await Jv())return s(`RECORDING_IN_PROGRESS`,`A recording is already running — stop it before starting another.`);if(!/^https?:/.test(e.url))return s(`UNSUPPORTED`,`Only http(s) pages can be recorded.`);let n={id:crypto.randomUUID(),tabId:e.tabId,host:Cp(e.url),startUrl:e.url,startedAt:Date.now(),captureValues:e.captureValues,events:[{t:Date.now(),kind:`navigate`,url:e.url}],warned:!1};await Yv(n),await t.alarms.create(Wv,{when:n.startedAt+vp}),await t.alarms.create(Gv,{when:n.startedAt+_p}),await t.tabs.sendMessage(e.tabId,{channel:hp,op:`begin`}).catch(()=>void 0);let r=Xv(n);return Kv?.(r),o(r)}async function ty(e,t){if(!t.length)return;let n=await Jv();if(!(!n||n.tabId!==e)){if(n.events.length>=2e3){await ny(`timeout`);return}n.events.push(...t.slice(0,gp-n.events.length)),await Yv(n),Kv?.(Xv(n))}}async function ny(e){let n=await Jv();if(await t.alarms.clear(Wv),await t.alarms.clear(Gv),!n)return Kv?.(null),o(null);await Yv(null),e!==`tab-closed`&&await t.tabs.sendMessage(n.tabId,{channel:hp,op:`end`}).catch(()=>void 0),Kv?.(null);let r=n.startedAt;return await Fv({id:n.id,name:Bv(n.host,r),host:n.host,startUrl:n.startUrl,status:`analyzing`,capturedValues:n.captureValues,events:n.events.length,durationMs:Date.now()-n.startedAt,createdAt:r,updatedAt:Date.now()},{id:n.id,events:n.events}),Rv(n.id),o({id:n.id})}function ry(){t.tabs.onUpdated.addListener((e,t)=>{t.url&&(async()=>{let n=await Jv();if(!n||n.tabId!==e)return;let r=n.events[n.events.length-1];r?.kind===`navigate`&&r.url===t.url||await ty(e,[{t:Date.now(),kind:`navigate`,url:t.url}])})()}),t.tabs.onRemoved.addListener(e=>{(async()=>{(await Jv())?.tabId===e&&await ny(`tab-closed`)})()}),t.alarms.onAlarm.addListener(e=>{if(e.name===`browsentic/recording-stop`){ny(`timeout`);return}e.name===`browsentic/recording-warn`&&(async()=>{let e=await Jv();if(!e||e.warned)return;e.warned=!0,await Yv(e);let t=Math.max(0,_p-(Date.now()-e.startedAt));Kv?.(Xv(e,`Recording stops automatically in ${iy(t)}.`))})()})}function iy(e){let t=Math.round(e/1e3);return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}var ay=1e4,oy=120,sy=20,cy=50,ly=10;async function uy(e,n){let r=Vu.input.safeParse(e??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let{url:i,active:a}=r.data;if(!i.trim())return s(`INVALID_INPUT`,`page.openTab needs a "url" — a blank new tab is a browser page that no page action can reach.`);let c=n?await t.tabs.get(n.id).catch(()=>void 0):(await t.tabs.query({active:!0,currentWindow:!0}))[0],l=c?.url&&Ty(c.url)?c.url:void 0,u;try{let e=zu({url:i},l);if(e.kind!==`url`)return s(`INVALID_INPUT`,`page.openTab opens a URL — it has no history to walk.`);u=e.href}catch(e){return e instanceof I?s(e.code,e.message):s(`ACTION_FAILED`,String(e))}let d=c?.id!=null&&c.windowId!=null?{windowId:c.windowId,openerTabId:c.id}:{},f;try{f=await t.tabs.create({url:u,active:a,...d})}catch(e){return s(`ACTION_FAILED`,e instanceof Error?e.message:String(e))}if(f.id==null)return s(`ACTION_FAILED`,`The browser opened a tab but reported no id for it.`);let p=await my(f.id),m=a?f.id:c?.id;return o({performed:`opened ${Ey(u)} in a new ${a?`tab`:`background tab`}`,openedUrl:u,tabId:f.id,index:f.index,loaded:p,...m==null?{}:{activeTabId:m},...a&&c?.id!=null?{previousTabId:c.id}:{}})}async function dy(e,n){let r=wf.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let{tabId:i,match:a}=r.data;if(i!=null&&a!=null)return s(`INVALID_INPUT`,`Give either "tabId" or "match", not both.`);let c=await yy(e);if(i==null&&a==null)return o(_y(c,e));let l=await gy(c,{tabId:i,match:a},`switch to`);if(!l.ok)return l.result;let u=l.tab;if(!Ty(u.url))return s(`UNSUPPORTED`,`Tab ${u.id} is a browser page, not a web page — page actions cannot read or act on it, so there is nothing to switch to.`);try{await t.tabs.update(u.id,{active:!0})}catch(e){return s(`ACTION_FAILED`,e instanceof Error?e.message:String(e))}return o({performed:`switched to ${xy(u)}`,activeTabId:u.id,previousTabId:e.id,tab:by({...u,active:!0})})}async function fy(e,n){let r=Rc.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let{tabId:i,match:a}=r.data;if(i!=null&&a!=null)return s(`INVALID_INPUT`,`Give either "tabId" or "match", not both.`);let c=await yy(e),l=i==null&&a==null?hy(c,e):await gy(c,{tabId:i,match:a},`close`);if(!l.ok)return l.result;let u=l.tab;if(c.length<=1)return s(`INVALID_TARGET`,`${xy(u)} is the only tab in this window — closing it would close the window and the Browsentic panel with it. Open another tab first, or leave this one alone.`);if(u.pinned)return s(`INVALID_TARGET`,`${xy(u)} is pinned, which means the user wants to keep it. Ask them to unpin it if it really should close.`);if(!Ty(u.url))return s(`UNSUPPORTED`,`Tab ${u.id} is a browser page, not a web page — Browsentic cannot see what it is, so it will not close it.`);if((await Qv(u.id)).recording)return s(`INVALID_TARGET`,`A recording is in progress in ${xy(u)} — closing it would cut the recording short. Stop the recording first.`);try{await t.tabs.remove(u.id)}catch(e){return s(`ACTION_FAILED`,e instanceof Error?e.message:String(e))}let d=await vy(e,u.id),f=d.active?.url?Ey(d.active.url):void 0;return o({performed:f?`closed ${xy(u)} — now on ${f}`:`closed ${xy(u)}`,closed:by(u),...f?{nowOn:f}:{},...d.active?.id==null?{}:{activeTabId:d.active.id},remaining:d.remaining})}function py(e){let n,r=new Promise(e=>{n=e}),i=e=>{t.tabs.onUpdated.removeListener(a),clearTimeout(o),n(e)},a=(t,n)=>{t===e&&n.status===`complete`&&i(!0)},o=setTimeout(()=>i(!1),ay);return t.tabs.onUpdated.addListener(a),{settled:r,cancel:()=>i(!1)}}async function my(e){let n=py(e),r=(await t.tabs.get(e).catch(()=>null))?.status;return r==null||r===`complete`?(n.cancel(),r===`complete`):n.settled}function hy(e,t){let n=e.find(e=>e.id===t.id);return n?{ok:!0,tab:n}:{ok:!1,result:s(`TARGET_NOT_FOUND`,`The tab page actions were targeting is already gone.`)}}async function gy(e,n,r){if(n.tabId!=null){let r=e.find(e=>e.id===n.tabId);return r?{ok:!0,tab:r}:{ok:!1,result:await t.tabs.get(n.tabId).catch(()=>null)?s(`INVALID_TARGET`,`Tab ${n.tabId} is in a different browser window. Browsentic only acts within the window it was opened in — ${Cy(e)}`):s(`TARGET_NOT_FOUND`,`No tab with id ${n.tabId} — it has probably been closed. ${Cy(e)}`)}}let i=n.match.trim().toLowerCase();if(!i)return{ok:!1,result:s(`INVALID_INPUT`,`"match" cannot be empty.`)};let a=e.filter(wy).filter(e=>`${e.title??``} ${e.url??``}`.toLowerCase().includes(i));return a.length?a.length>1?{ok:!1,result:s(`INVALID_TARGET`,`"${Ey(n.match)}" matches ${a.length} tabs, so nothing was touched — ${r} one of them by id: ${Sy(a)}`)}:{ok:!0,tab:a[0]}:{ok:!1,result:s(`TARGET_NOT_FOUND`,`No open tab matches "${Ey(n.match)}". ${Cy(e)}`)}}function _y(e,t){let n=e.filter(wy),r=e.length-n.length,i=n.slice(0,sy);return{performed:`${n.length} open tab${n.length===1?``:`s`} in this window`,activeTabId:t.id,tabs:i.map(by),...r?{hidden:r}:{},...i.length<n.length?{truncated:!0}:{}}}async function vy(e,t){let n=[];for(let r=0;r<ly;r++){n=await yy(e);let r=n.find(e=>e.active);if(r&&!n.some(e=>e.id===t))return{active:r,remaining:n.length};await Dy(cy)}let r=n.filter(e=>e.id!==t);return{active:r.find(e=>e.active),remaining:r.length}}async function yy(e){return await t.tabs.query(e.windowId==null?{currentWindow:!0}:{windowId:e.windowId})}function by(e){return{tabId:e.id,title:Ey(e.title??``),url:Ey(e.url??``),...e.active?{active:!0}:{}}}function xy(e){let t=Ey(e.title??``),n=Ey(e.url??``);return t&&n?`“${t}” — ${n}`:t||n||`tab ${e.id}`}function Sy(e){let t=e.slice(0,sy),n=t.map(e=>`#${e.id} ${xy(e)}`).join(`; `);return t.length<e.length?`${n}; …and ${e.length-t.length} more`:n}function Cy(e){let t=e.filter(wy);return t.length?`Open tabs: ${Sy(t)}`:`No other web page is open in this window.`}var wy=e=>Ty(e.url),Ty=e=>!!e&&/^https?:/i.test(e);function Ey(e){let t=e.replace(/\s+/g,` `).trim();return t.length>oy?`${t.slice(0,oy-1)}…`:t}var Dy=e=>new Promise(t=>setTimeout(t,e)),Oy=`browsentic/diagnostics`,ky=30,Ay=400,jy=null,My=[],Ny;async function Py(){return jy||(jy=(await t.storage.session.get(Oy).catch(()=>({})))[Oy]??{},jy)}function Fy(){return clearTimeout(Ny),Ny=void 0,jy?t.storage.session.set({[Oy]:jy}).catch(()=>void 0):Promise.resolve()}function Iy(){Ny||=setTimeout(()=>void Fy(),200)}var Ly=e=>Object.values(e).filter(e=>e.phase===`watching`);function Ry(e,t){return Ly(e).find(e=>e.tabId===t)}async function zy(e,n,r){let i=e.tabId??n,a=i==null?(await t.tabs.query({active:!0,currentWindow:!0}))[0]:await t.tabs.get(i).catch(()=>void 0);if(a?.id==null||!a.url)return i==null?s(`NO_ACTIVE_TAB`,`No active tab to record.`):s(`TARGET_NOT_FOUND`,`No tab with id ${i} — it has probably been closed.`);if(!/^https?:/i.test(a.url))return s(`UNSUPPORTED`,`Only http(s) pages report a console and network activity — browser pages do not.`);if(!e.capture.length)return s(`INVALID_INPUT`,`Give "capture" at least one of "console" or "network" — there is nothing to record otherwise.`);let c=await Py();await Qy(c);let l=Ry(c,a.id);if(l)return s(`DIAGNOSTICS_IN_PROGRESS`,`This tab is already being recorded by ${l.diagnosticsId} — read it with page.readConsole, or stop it first.`);if(Ly(c).length>=2)return s(`DIAGNOSTICS_LIMIT`,`2 tabs are already being recorded — stop one with page.stopDiagnostics first.`);let u=await Vm(a.id);if(!u.ok)return s(`DEBUGGER_UNAVAILABLE`,u.message);let d=await Vy(a.id,e.capture);if(d)return await Hm(a.id),s(`DEBUGGER_UNAVAILABLE`,d);let f=Date.now(),p={diagnosticsId:crypto.randomUUID(),tabId:a.id,url:a.url,host:Cp(a.url),owner:r,capture:e.capture,phase:`watching`,startedAt:f,expiresAt:f+e.timeoutMs,console:[],network:[],droppedConsole:0,droppedNetwork:0};c[p.diagnosticsId]=p,await Fy(),await t.alarms.create(id(p.diagnosticsId),{when:p.expiresAt}),await W(150);let m=e.reload?await By(a.id):void 0;return o({..._d(p),reloaded:m,notice:dd})}async function By(e){let n=py(e);try{await t.tabs.reload(e)}catch{return n.cancel(),!1}return n.settled}async function Vy(e,t){let n={tabId:e};try{return t.includes(`console`)&&(await G(n,`Runtime.enable`),await G(n,`Log.enable`)),t.includes(`network`)&&await G(n,`Network.enable`),null}catch(e){return`Chrome attached but refused to start reporting: ${e instanceof Error?e.message:String(e)}`}}async function Hy(e){let t=await Jy(e.diagnosticsId);if(!t.ok)return t;let n=t.data,r=e.contains?.toLowerCase(),i=n.console.filter(t=>(e.level===`all`||hd(t.level,e.level))&&(!r||t.text.toLowerCase().includes(r))),a=i.slice(-e.limit),s=n.droppedConsole;if(e.drain){let e=new Set(a);n.console=n.console.filter(t=>!e.has(t)),n.droppedConsole=0,await Fy()}return o({..._d(n),messages:a,matched:i.length,returned:a.length,droppedConsole:s,truncated:i.length>a.length?`${i.length-a.length} older messages not shown — raise "limit" or narrow with "contains".`:void 0})}async function Uy(e){let t=await Jy(e.diagnosticsId);if(!t.ok)return t;let n=t.data,r=e.urlContains?.toLowerCase(),i=e.method?.toUpperCase(),a=n.network.filter(t=>Wy(t,e.status)&&(!r||t.url.toLowerCase().includes(r))&&(!i||t.method===i)),s=a.slice(-e.limit),c=e.includeBodies?await Ky(n,s):void 0,l=n.droppedNetwork;if(e.drain){let e=new Set(s);n.network=n.network.filter(t=>!e.has(t)),n.droppedNetwork=0,await Fy()}return o({..._d(n),requests:s.map(t=>Gy(t,e.includeHeaders,c)),matched:a.length,returned:s.length,droppedNetwork:l,truncated:a.length>s.length?`${a.length-s.length} older requests not shown — raise "limit" or narrow with "urlContains".`:void 0})}function Wy(e,t){return t===`all`?!0:t===`failed`?e.failed!=null:t===`pending`?e.failed==null&&e.status==null:e.failed!=null||e.status!=null&&e.status>=400}function Gy(e,t,n){let{mono:r,requestHeaders:i,responseHeaders:a,...o}=e;return{...o,requestHeaders:t?i:void 0,responseHeaders:t?a:void 0,body:n?.get(e.requestId)}}async function Ky(e,t){let n=new Map;if(e.phase!==`watching`){for(let e of t.slice(-5))n.set(e.requestId,`Not available — this recording has stopped, and Chrome keeps response bodies only while attached.`);return n}for(let r of t.slice(-5))if(r.status!=null)try{let t=await G({tabId:e.tabId},`Network.getResponseBody`,{requestId:r.requestId});n.set(r.requestId,t.base64Encoded?`[${t.body.length} bytes of binary]`:gd(t.body,ud))}catch{n.set(r.requestId,`Not available — Chrome has already discarded this body.`)}return n}async function qy(e){let t=await Py();await Qy(t);let n=Ly(t);if(e!=null){let n=await Yy(e,`stopped`);if(n)return o(_d(n));let r=t[e];return r?s(`DIAGNOSTICS_NOT_FOUND`,`Recording ${e} already ended (${r.phase}) — there is nothing to stop.`):s(`DIAGNOSTICS_NOT_FOUND`,`No recording with id “${e}”.`)}if(!n.length)return s(`DIAGNOSTICS_NOT_FOUND`,`Nothing is being recorded.`);if(n.length>1){let e=n.map(e=>`${e.diagnosticsId} · ${e.host} (tab ${e.tabId})`).join(`; `);return s(`INVALID_TARGET`,`${n.length} recordings are running, so nothing was stopped — stop one by id: ${e}`)}let r=await Yy(n[0].diagnosticsId,`stopped`);return r?o(_d(r)):s(`DIAGNOSTICS_NOT_FOUND`,`That recording just ended on its own.`)}async function Jy(e){let t=await Py();if(await Qy(t),e!=null){let n=t[e];return n?o(n):s(`DIAGNOSTICS_NOT_FOUND`,`No recording with id “${e}”. Start one with page.startDiagnostics.`)}let n=Object.values(t),r=Ly(t),i=r.length?r:n;if(!i.length)return s(`DIAGNOSTICS_NOT_FOUND`,`Nothing has been recorded. Call page.startDiagnostics first — a page’s console and network activity only exist while Browsentic is attached to it.`);if(i.length>1){let e=i.map(e=>`${e.diagnosticsId} · ${e.host} (tab ${e.tabId})`).join(`; `);return s(`INVALID_TARGET`,`${i.length} recordings to choose from — name one with "diagnosticsId": ${e}`)}return o(i[0])}async function Yy(e,n,r){let i=await Py(),a=i[e];return!a||a.phase!==`watching`?null:(a.phase=n,a.message=r??Xy(n),await t.alarms.clear(id(e)).catch(()=>void 0),n!==`detached`&&n!==`tab-closed`&&await Hm(a.tabId),Zy(i),await Fy(),a)}function Xy(e){return{stopped:`Stopped. What was collected is still readable; response bodies are not.`,timeout:`Detached on its own after its timeout, so Chrome’s debugger bar did not stay up. What was collected is still readable.`,detached:`Chrome took the debugger away — DevTools was opened on this tab, or the debugging bar was dismissed.`,"tab-closed":`The tab was closed.`}[e]}function Zy(e){let t=Object.values(e).filter(e=>e.phase!==`watching`).sort((e,t)=>e.startedAt-t.startedAt);for(let n of t.slice(0,Math.max(0,t.length-2)))delete e[n.diagnosticsId]}async function Qy(e){let t=Date.now();for(let n of Ly(e))n.expiresAt<=t&&await Yy(n.diagnosticsId,`timeout`)}async function $y(e,t){if(!e.length)return;let n=await Py();for(let r of e)await Yy(r.diagnosticsId,t),delete n[r.diagnosticsId];await Fy()}async function eb(e){let t=await Py();await $y(Object.values(t).filter(t=>t.owner===e),`stopped`)}async function tb(e){let t=await Py();await $y(Object.values(t).filter(t=>t.tabId===e),`tab-closed`)}function nb(){Bm((e,t,n)=>{e.sessionId||e.tabId==null||rb(e.tabId,t,n??{})}),Um(e=>{Py().then(t=>{let n=Ry(t,e);n&&Yy(n.diagnosticsId,`detached`)})}),t.alarms.onAlarm.addListener(e=>{e.name.startsWith(`browsentic/diagnostics-timeout:`)&&Yy(e.name.slice(rd.length),`timeout`)}),t.tabs.onRemoved.addListener(e=>void tb(e))}function rb(e,t,n){if(!jy){My.push({tabId:e,method:t,params:n}),Py().then(()=>{let e=My;My=[];for(let t of e)ib(t.tabId,t.method,t.params);Iy()});return}ib(e,t,n)}function ib(e,t,n){let r=jy?Ry(jy,e):void 0;if(!r)return;let i=ab[t]??ob[t];i&&(i(r,n),Iy())}var ab={"Runtime.consoleAPICalled":(e,t)=>{let n=t.args??[],r=fb(t.stackTrace);lb(e,{t:Date.now(),level:pd(t.type),kind:`console`,text:gd(n.slice(0,6).map(db).filter(Boolean).join(` `)),url:r[0]?.url,line:r[0]?.line,column:r[0]?.column,stack:r.length>1?r.map(pb):void 0})},"Runtime.exceptionThrown":(e,t)=>{let n=t.exceptionDetails??{},r=fb(n.stackTrace);lb(e,{t:Date.now(),level:`error`,kind:`exception`,text:gd(n.exception?.description??n.text??`Uncaught exception`),url:n.url??r[0]?.url,line:n.lineNumber==null?r[0]?.line:n.lineNumber+1,column:n.columnNumber==null?r[0]?.column:n.columnNumber+1,stack:r.length?r.map(pb):void 0})},"Log.entryAdded":(e,t)=>{let n=t.entry??{};lb(e,{t:Date.now(),level:pd(n.level),kind:`browser`,text:gd(n.source?`[${n.source}] ${n.text??``}`:n.text??``),url:n.url,line:n.lineNumber==null?void 0:n.lineNumber+1})}},ob={"Network.requestWillBeSent":(e,t)=>{let n=t.requestId,r=t.request??{},i=t.redirectResponse;if(i){let t=sb(e,n);t&&(t.status=i.status,t.statusText=i.statusText||void 0,t.responseHeaders=mb(i.headers),t.requestId=`${n}:${t.t}`)}ub(e,{t:t.wallTime?t.wallTime*1e3:Date.now(),mono:t.timestamp??0,requestId:n,method:(r.method??`GET`).toUpperCase(),url:gd(r.url??``),type:t.type,requestHeaders:mb(r.headers)})},"Network.responseReceived":(e,t)=>{let n=sb(e,t.requestId);if(!n)return;let r=t.response??{};n.status=r.status,n.statusText=r.statusText||void 0,n.mimeType=r.mimeType,n.fromCache=r.fromDiskCache===!0||r.fromPrefetchCache===!0||void 0,n.responseHeaders=mb(r.headers),n.type=t.type??n.type,n.durationMs=cb(n,t.timestamp)},"Network.loadingFinished":(e,t)=>{let n=sb(e,t.requestId);n&&(n.sizeBytes=t.encodedDataLength,n.durationMs=cb(n,t.timestamp)??n.durationMs)},"Network.loadingFailed":(e,t)=>{let n=sb(e,t.requestId);if(!n)return;let r=t.blockedReason,i=t.errorText??`Request failed`;n.failed=t.canceled===!0&&!r?`${i} (cancelled)`:r?`${i} (blocked: ${r})`:i,n.durationMs=cb(n,t.timestamp)??n.durationMs}};function sb(e,t){for(let n=e.network.length-1;n>=0;--n)if(e.network[n].requestId===t)return e.network[n]}var cb=(e,t)=>t!=null&&e.mono?Math.max(0,Math.round((t-e.mono)*1e3)):void 0;function lb(e,t){e.console.push(t);let n=e.console.length-500;n>0&&(e.droppedConsole+=n,e.console.splice(0,n))}function ub(e,t){e.network.push(t);let n=e.network.length-cd;n>0&&(e.droppedNetwork+=n,e.network.splice(0,n))}function db(e){if(e.value!==void 0)return typeof e.value==`string`?e.value:JSON.stringify(e.value);if(e.preview?.properties?.length){let t=e.preview.properties.map(e=>`${e.name}: ${e.value??`…`}`).join(`, `);return`${e.preview.description??e.type??``} {${t}${e.preview.overflow?`, …`:``}}`.trim()}return e.description??e.type??``}function fb(e){return(e?.callFrames??[]).slice(0,8).map(e=>({url:e.url||void 0,line:e.lineNumber==null?void 0:e.lineNumber+1,column:e.columnNumber==null?void 0:e.columnNumber+1,fn:e.functionName||`(anonymous)`}))}var pb=e=>`${e.fn} (${e.url??`<unknown>`}:${e.line??0}:${e.column??0})`;function mb(e){if(!e)return;let t={};for(let[n,r]of Object.entries(e).slice(0,ky))t[n.toLowerCase()]=gd(String(r),Ay);return t}var hb=`browsentic/toast`,gb=1e4;function _b(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.channel===`browsentic/toast`&&t.op===`activate`&&typeof t.tabId==`number`}var vb=[{id:`ember`,name:`Ember`,note:`Warm near-black, cyan brand.`},{id:`midnight`,name:`Midnight`,note:`Cool blue-black, violet brand.`},{id:`phosphor`,name:`Phosphor`,note:`A green CRT, grain turned up.`},{id:`daylight`,name:`Daylight`,note:`Ink on paper, for a bright room.`}],yb=`ember`,bb=`browsentic/theme`;function xb(e){return vb.some(t=>t.id===e)?e:yb}async function Sb(){return xb((await t.storage.local.get(bb))[bb])}var Cb=`Receiving end does not exist`;async function wb(e,t){let n={channel:hb,op:`show`,view:{...e,theme:await Sb(),durationMs:gb}};for(let e of await Tb(t))if(await Eb(e,n))return!0;return!1}async function Tb(e){let n=[],r=e=>{e!=null&&!n.includes(e)&&n.push(e)},[i]=await t.tabs.query({active:!0,lastFocusedWindow:!0}).catch(()=>[]);if(r(i?.id),e==null)return n;let a=await t.tabs.get(e).catch(()=>null);if(a?.windowId==null)return n;let[o]=await t.tabs.query({active:!0,windowId:a.windowId}).catch(()=>[]);return r(o?.id),n}async function Eb(e,n){let r=async()=>(await t.tabs.sendMessage(e,n))?.ok===!0;try{return await r()}catch(t){return!(t instanceof Error?t.message:String(t)).includes(Cb)||!await up(e)?!1:r().catch(()=>!1)}}function Db(){t.runtime.onMessage.addListener((e,t,n)=>{_b(e)&&(Ob(e.tabId),n({ok:!0}))})}async function Ob(e){let n=await t.tabs.update(e,{active:!0}).catch(()=>null);n?.windowId!=null&&await t.windows.update(n.windowId,{focused:!0}).catch(()=>void 0)}var kb=`browsentic/monitors`,Ab=`browsentic/monitorsDone`,jb=`Receiving end does not exist`,Mb=new Set,Nb=new Map,Pb=Promise.resolve();function Fb(e){Mb.add(e)}function Ib(e){for(let t of Mb)t(e)}function Lb(e){let t=Pb.then(e,e);return Pb=t.catch(()=>void 0),t}async function Y(){return(await t.storage.session.get(kb))[kb]??{}}function Rb(e){return t.storage.session.set({[kb]:e})}async function zb(){let e=(await t.storage.session.get(Ab))[Ab];return Array.isArray(e)?e:[]}function Bb(e){return t.storage.session.set({[Ab]:e})}function Vb(e,t=`watching`,n){let r=Date.now(),{percent:i,etaMs:a}=jc(e.samples,e.until.threshold),o=r-e.lastProgressAt;return{monitorId:e.id,tabId:e.tabId,host:e.host,label:e.label,until:e.until,startedAt:e.startedAt,elapsedMs:r-e.startedAt,timeoutMs:e.timeoutMs,phase:t,percent:i,etaMs:t===`watching`?a:void 0,stalledForMs:t===`watching`&&o>=12e4?o:void 0,logs:e.logs,message:n}}function Hb(e){return{...e,logs:e.logs.slice(-5)}}function Ub(e,t){e.logs.push({t:Date.now(),text:t}),e.logs.length>50&&e.logs.splice(0,e.logs.length-50)}async function Wb(e,n){let r=kc(e.until);if(r)return s(`INVALID_INPUT`,r);let i=e.tabId??n,a=i==null?(await t.tabs.query({active:!0,currentWindow:!0}))[0]:await t.tabs.get(i).catch(()=>void 0);if(a?.id==null||!a.url)return i==null?s(`NO_ACTIVE_TAB`,`No active tab to watch.`):s(`TARGET_NOT_FOUND`,`No tab with id ${i} — it has probably been closed.`);if(!/^https?:/i.test(a.url))return s(`UNSUPPORTED`,`Only http(s) pages can be watched — browser pages expose nothing to observe.`);let c=await Lb(async()=>{let t=await Y(),n=Object.values(t).find(e=>e.tabId===a.id);if(n)return s(`MONITOR_IN_PROGRESS`,`This tab is already being watched by monitor ${n.id}${n.label?` (“${n.label}”)`:``} — stop it first, or watch a different tab.`);if(Object.keys(t).length>=3)return s(`MONITOR_LIMIT`,`3 monitors are already running — stop one with page.stopMonitor first. page.monitorStatus lists them.`);let r=Date.now(),i={id:crypto.randomUUID(),tabId:a.id,host:Cp(a.url),startUrl:a.url,origin:wp(a.url),label:e.label,until:e.until,startedAt:r,timeoutMs:e.timeoutMs,restorePinned:a.pinned===!0,samples:[],logs:[],lastProgressAt:r,lastLogAt:r,warnedStall:!1};return Ub(i,`Watching ${i.host} ${Ac(i.until)}.`),t[i.id]=i,await Rb(t),o(i)});if(!c.ok)return c;let l=c.data;l.restorePinned||await t.tabs.update(l.tabId,{pinned:!0}).catch(()=>void 0),await t.alarms.create(Tc(l.id),{when:l.startedAt+l.timeoutMs}),await t.alarms.create(Cc,{periodInMinutes:1}),await Gb(l);let u=Vb(l);return Ib(u),o(Hb(u))}async function Gb(e){let n={channel:vc,op:`watch`,monitorId:e.id,until:e.until};try{await t.tabs.sendMessage(e.tabId,n)}catch(r){if(!(r instanceof Error?r.message:String(r)).includes(jb))return;await up(e.tabId)&&await t.tabs.sendMessage(e.tabId,n).catch(()=>void 0)}}async function Kb(e,t,n){let r=await Lb(async()=>{let r=await Y(),i=r[t];if(!i||i.tabId!==e)return null;let a=i.samples.at(-1);i.samples.push(n),i.samples.length>24&&i.samples.splice(0,i.samples.length-24),(n.percent!=null&&(a?.percent==null||n.percent>a.percent)||n.text!==void 0&&n.text!==a?.text||n.matched!==a?.matched)&&(i.lastProgressAt=n.t,i.warnedStall=!1);let{percent:o,etaMs:s}=jc(i.samples,i.until.threshold);return o!=null&&(i.lastLogPercent==null||o-i.lastLogPercent>=5||n.t-i.lastLogAt>=3e4)?(Ub(i,`Progress ${Math.round(o)}%${s==null?``:`, ETA ${Mc(s)}`}.`),i.lastLogAt=n.t,i.lastLogPercent=o):o==null&&n.text&&n.t-i.lastLogAt>=3e4&&(Ub(i,`“${n.text}”`),i.lastLogAt=n.t),await Rb(r),{monitor:{...i},complete:n.matched===!0}});if(r){if(r.complete){await qb(t,`done`);return}Ib(Vb(r.monitor))}}async function qb(e,n,r){let i=await Lb(async()=>{let t=await Y(),i=t[e];if(!i)return null;delete t[e],await Rb(t),Ub(i,r??Jb(n));let a=Vb(i,n,r),o=await zb();return o.push(a),await Bb(o.slice(-6)),{monitor:i,state:a,remaining:Object.keys(t).length}});if(!i)return null;let{monitor:a,state:o,remaining:s}=i;await t.alarms.clear(Tc(e)),s===0&&await t.alarms.clear(Cc),await Yb(a),n!==`tab-closed`&&await t.tabs.sendMessage(a.tabId,{channel:vc,op:`unwatch`,monitorId:e}).catch(()=>void 0);for(let t of Nb.get(e)??[])t(o);return Nb.delete(e),n!==`stopped`&&await ax(o),Ib(o),o}function Jb(e){return{done:`The watched condition completed.`,timeout:`Gave up: the time limit passed without completing.`,stopped:`Stopped by the user.`,"tab-closed":`The tab was closed.`,"tab-navigated":`The tab left the watched site.`}[e]}async function Yb(e){e.restorePinned||(await t.tabs.get(e.tabId).catch(()=>null))?.pinned&&await t.tabs.update(e.tabId,{pinned:!1}).catch(()=>void 0)}async function Xb(e){let t=await Y(),n=Object.values(t);if(e!=null){if(!t[e]){let t=(await zb()).find(t=>t.monitorId===e);return t?s(`MONITOR_NOT_FOUND`,`Monitor ${e} already finished (${t.phase}) — there is nothing to stop.`):s(`MONITOR_NOT_FOUND`,`No monitor with id “${e}”. page.monitorStatus lists what is running.`)}let n=await qb(e,`stopped`);return n?o(Hb(n)):s(`MONITOR_NOT_FOUND`,`Monitor ${e} just finished on its own.`)}if(n.length===0)return s(`MONITOR_NOT_FOUND`,`No monitor is running.`);if(n.length>1){let e=n.map(e=>`${e.id} · ${e.label??e.host}`).join(`; `);return s(`INVALID_TARGET`,`${n.length} monitors are running, so nothing was stopped — stop one by id: ${e}`)}let r=await qb(n[0].id,`stopped`);return r?o(Hb(r)):s(`MONITOR_NOT_FOUND`,`That monitor just finished on its own.`)}async function Zb(e){let t=await Y(),n=await zb();if(e!=null){let r=t[e];if(r)return o(Hb(Vb(r)));let i=n.find(t=>t.monitorId===e);return i?o(Hb(i)):s(`MONITOR_NOT_FOUND`,`No monitor with id “${e}” is running or recently finished.`)}return o({monitors:[...Object.values(t).map(e=>Hb(Vb(e))),...n.map(Hb)]})}async function Qb(e,t){if(!(await Y())[e]){let t=(await zb()).find(t=>t.monitorId===e);return t?o({settled:!0,state:t}):s(`MONITOR_NOT_FOUND`,`No monitor with id “${e}” is running or recently finished.`)}return new Promise(n=>{let r=Nb.get(e)??new Set,i=e=>{clearTimeout(a),r.delete(i),n(o({settled:!0,state:e}))};r.add(i),Nb.set(e,r);let a=setTimeout(()=>{(async()=>{r.delete(i);let t=(await Y())[e];if(t)return n(o({settled:!1,state:Hb(Vb(t))}));let a=(await zb()).find(t=>t.monitorId===e);n(a?o({settled:!0,state:a}):s(`MONITOR_NOT_FOUND`,`Monitor ${e} disappeared while waiting.`))})()},Math.min(t,Sc))})}async function $b(e){if(e==null)return o({monitors:[]});let t=await Y();return o({monitors:Object.values(t).filter(t=>t.tabId===e).map(e=>({monitorId:e.id,until:e.until}))})}async function ex(){let e=await Y();return Object.values(e).map(e=>Vb(e))}async function tx(){return zb()}async function nx(e){if(e==null)return Bb([]);await Bb((await zb()).filter(t=>t.monitorId!==e))}function rx(){t.tabs.onRemoved.addListener(e=>{(async()=>{for(let t of Object.values(await Y()))t.tabId===e&&await qb(t.id,`tab-closed`,`The tab was closed.`)})()}),t.tabs.onUpdated.addListener((e,t)=>{t.url&&(async()=>{for(let n of Object.values(await Y()))if(n.tabId===e)if(wp(t.url)===n.origin){let e=await Lb(async()=>{let e=await Y(),r=e[n.id];return r?(Ub(r,`Navigated to ${ix(t.url)} — still watching.`),await Rb(e),{...r}):null});e&&Ib(Vb(e))}else await qb(n.id,`tab-navigated`,`The tab left ${n.host} for ${Cp(t.url)||`another page`}.`)})()}),t.alarms.onAlarm.addListener(e=>{if(e.name.startsWith(`browsentic/monitor-timeout:`)){qb(e.name.slice(wc.length),`timeout`);return}e.name===`browsentic/monitor-watch`&&(async()=>{let e=Date.now();for(let t of Object.values(await Y())){if(await Gb(t),e-t.lastProgressAt<12e4||t.warnedStall)continue;let n=await Lb(async()=>{let n=await Y(),r=n[t.id];return!r||r.warnedStall?null:(r.warnedStall=!0,Ub(r,`No change for ${Math.round((e-r.lastProgressAt)/6e4)} minutes.`),await Rb(n),{...r})});n&&Ib(Vb(n))}})()}),t.notifications?.onClicked.addListener(e=>{if(!e.startsWith(`browsentic-monitor:`))return;let n=e.slice(Ec.length);(async()=>{let r=(await zb()).find(e=>e.monitorId===n)?.tabId??(await Y())[n]?.tabId;if(r==null)return;let i=await t.tabs.update(r,{active:!0}).catch(()=>null);i?.windowId!=null&&await t.windows.update(i.windowId,{focused:!0}).catch(()=>void 0),await t.notifications.clear(e).catch(()=>void 0)})()})}function ix(e){try{let t=new URL(e);return t.pathname+t.search}catch{return e}}async function ax(e){let n=ox(e);n&&(await wb({toastId:e.monitorId,tone:e.phase===`done`?`live`:`warn`,title:n.title,body:n.message,tabId:e.phase===`tab-closed`?void 0:e.tabId},e.tabId)||await t.notifications?.create(`${Ec}${e.monitorId}`,{type:`basic`,iconUrl:sx(),title:n.title,message:n.message}).catch(()=>void 0))}function ox(e){let t=e.label??e.host;return{done:{title:`Done: ${t}`,message:`Finished after ${cx(e.elapsedMs)}.`},timeout:{title:`Still going: ${t}`,message:`Watched for ${cx(e.elapsedMs)} without completing.`},"tab-closed":{title:`Monitor ended — tab closed`,message:`${t} was closed before finishing.`},"tab-navigated":{title:`Monitor ended — tab moved on`,message:e.message??`The tab left ${e.host}.`}}[e.phase]}function sx(){let e=t.runtime.getManifest().icons??{};return e[Object.keys(e).map(Number).sort((e,t)=>t-e)[0]]??``}function cx(e){let t=Math.round(e/1e3);return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}var lx=`browsentic/timers`,ux=`browsentic/timersDone`,dx=null,fx=Promise.resolve();function px(e){dx=e}function mx(e){let t=fx.then(e,e);return fx=t.catch(()=>void 0),t}async function hx(){return(await t.storage.session.get(lx))[lx]??{}}function gx(e){return t.storage.session.set({[lx]:e})}async function _x(){let e=(await t.storage.session.get(ux))[ux];return Array.isArray(e)?e:[]}function vx(e){return t.storage.session.set({[ux]:e})}function yx(e,t=`scheduled`,n){return{timerId:e.id,label:e.label,prompt:e.prompt,deliver:e.deliver,sessionId:e.sessionId,afterMs:e.afterMs,repeat:e.repeat,maxRuns:e.maxRuns,runs:e.runs,skipped:e.skipped,createdAt:e.createdAt,nextFireAt:t===`scheduled`?e.nextFireAt:void 0,lastFiredAt:e.lastFiredAt,phase:t,logs:e.logs,message:n}}function bx(e){return{...e,logs:e.logs.slice(-5)}}function xx(e,t){e.logs.push({t:Date.now(),text:t}),e.logs.length>20&&e.logs.splice(0,e.logs.length-20)}var Sx=e=>e.label??`timer`;async function Cx(e,t){if(e.deliver===`agent`&&!t)return s(`NO_CONVERSATION`,`Nothing here can be woken with a prompt — a timer only hands work back inside a Browsentic side-panel conversation. Pass deliver: "notify" to remind the user at that time instead, or schedule the job with your own client’s scheduler.`);let n=await mx(async()=>{let n=await hx();if(Object.keys(n).length>=5)return s(`TIMER_LIMIT`,`5 timers are already scheduled — cancel one with page.stopTimer first. page.timerStatus lists them.`);let r=Date.now(),i={id:crypto.randomUUID(),sessionId:t,label:e.label,prompt:e.prompt,deliver:e.deliver,afterMs:e.afterMs,repeat:e.repeat,maxRuns:e.repeat?e.maxRuns:1,runs:0,skipped:0,createdAt:r,nextFireAt:r+e.afterMs,logs:[]};return xx(i,`Scheduled to fire ${vf(i)}.`),n[i.id]=i,await gx(n),o(i)});if(!n.ok)return n;let r=n.data;return await wx(r),o(bx(yx(r)))}function wx(e){return t.alarms.create(hf(e.id),{when:e.nextFireAt,...e.repeat?{periodInMinutes:e.afterMs/6e4}:{}})}async function Tx(e){let n=(await hx())[e];if(!n){await t.alarms.clear(hf(e));return}let r=await Ex(n);if(r===`gone`){await Dx(e,`orphaned`,`The conversation this timer belonged to is gone.`);return}let i=await mx(async()=>{let t=await hx(),n=t[e];if(!n)return null;let i=Date.now();return r===`busy`?(n.skipped+=1,xx(n,`Skipped — the conversation was still working on the previous turn.`)):(n.runs+=1,n.lastFiredAt=i,xx(n,`Fired — run ${n.runs}${n.repeat?` of ${n.maxRuns}`:``}.`)),n.nextFireAt=i+(n.repeat||r===`delivered`?n.afterMs:pf),await gx(t),{...n}});if(i){if(i.skipped>=20){await Dx(e,`finished`,`Gave up after ${i.skipped} fires found the conversation still busy — the job takes longer than the interval it was given.`);return}if(!i.repeat){r===`delivered`?await Dx(e,`finished`):await wx(i);return}i.runs>=i.maxRuns&&await Dx(e,`finished`,`Fired ${i.runs} times, which is the limit that was set.`)}}async function Ex(e){return e.deliver===`notify`?(await Nx(e.id,e.label??`Browsentic timer`,e.prompt),`delivered`):!e.sessionId||!dx?`gone`:dx(e.sessionId,e.prompt,Sx(e))}async function Dx(e,n,r){let i=await mx(async()=>{let t=await hx(),i=t[e];if(!i)return null;delete t[e],await gx(t),xx(i,r??Ox(n));let a=yx(i,n,r);return await vx([...await _x(),a].slice(-6)),a});return i?(await t.alarms.clear(hf(e)),n===`orphaned`&&await Nx(e,`Timer ended: ${i.label??`scheduled job`}`,`The conversation it was set in has closed, so it was cancelled.`),i):null}function Ox(e){return{finished:`The schedule ran out.`,stopped:`Cancelled.`,orphaned:`The conversation this timer belonged to is gone.`}[e]}async function kx(e){let t=Object.values(await hx());if(e!=null){let t=await Dx(e,`stopped`);if(t)return o(bx(t));let n=(await _x()).find(t=>t.timerId===e);return n?s(`TIMER_NOT_FOUND`,`Timer ${e} already ended (${n.phase}) — there is nothing to cancel.`):s(`TIMER_NOT_FOUND`,`No timer with id “${e}”. page.timerStatus lists what is scheduled.`)}if(t.length===0)return s(`TIMER_NOT_FOUND`,`No timer is scheduled.`);if(t.length>1){let e=t.map(e=>`${e.id} · ${Sx(e)} (${vf(e)})`).join(`; `);return s(`INVALID_TARGET`,`${t.length} timers are scheduled, so nothing was cancelled — cancel one by id: ${e}`)}let n=await Dx(t[0].id,`stopped`);return n?o(bx(n)):s(`TIMER_NOT_FOUND`,`That timer just ended on its own.`)}async function Ax(e){let t=await hx(),n=await _x();if(e!=null){let r=t[e];if(r)return o(bx(yx(r)));let i=n.find(t=>t.timerId===e);return i?o(bx(i)):s(`TIMER_NOT_FOUND`,`No timer with id “${e}” is scheduled or recently finished.`)}return o({timers:[...Object.values(t).map(e=>bx(yx(e))),...n.map(bx)]})}async function jx(e){for(let t of Object.values(await hx()))t.sessionId===e&&await Dx(t.id,`orphaned`,`The conversation was ended.`)}function Mx(){t.alarms.onAlarm.addListener(e=>{e.name.startsWith(`browsentic/timer:`)&&Tx(e.name.slice(mf.length))}),t.notifications?.onClicked.addListener(e=>{e.startsWith(`browsentic-timer:`)&&t.notifications.clear(e).catch(()=>void 0)})}async function Nx(e,n,r){await t.notifications?.create(`${gf}${e}`,{type:`basic`,iconUrl:Px(),title:n,message:r}).catch(()=>void 0)}function Px(){let e=t.runtime.getManifest().icons??{};return e[Object.keys(e).map(Number).sort((e,t)=>t-e)[0]]??``}var Fx=`browsentic:shots`,Ix=e=>`browsentic:shot:${e}`,Lx=2,Rx=4e6,zx=new Set;function Bx(e){zx.add(e)}async function Vx(e,t){if(!e.thumbnail)return;let n=crypto.randomUUID(),r=await Hx(n,e.dataUrl),i={previewId:n,thumbnail:e.thumbnail,width:e.width,height:e.height,full:r};for(let e of zx)e(i,t)}async function Hx(e,n){if(n.length>Rx)return!1;try{let r=await t.storage.session.get(Fx),i=[e,...(Array.isArray(r[Fx])?r[Fx]:[]).filter(t=>t!==e)],a=i.slice(Lx);return await t.storage.session.set({[Ix(e)]:n,[Fx]:i.slice(0,Lx)}),a.length&&await t.storage.session.remove(a.map(Ix)),!0}catch{return!1}}var Ux=500,Wx=48,Gx=16384,Kx=Gx*Gx;async function qx(e,t,n){let r=await cp(e.id,0,`page.screenshot`,t);if(!r.ok)return r;let i=r.data;try{let t=await Yx(e,i);return Jx(t,n),o(t)}catch(e){return e instanceof I?s(e.code,e.message):s(`CAPTURE_FAILED`,e instanceof Error?e.message:String(e))}finally{cp(e.id,0,`page.scrollTo`,{position:{x:i.scroll.x,y:i.scroll.y},behavior:`instant`})}}async function Jx(e,t){try{await Vx({...e,thumbnail:await Qx(e.dataUrl)},t)}catch{}}async function Yx(e,t){let{viewport:n,format:r,quality:i,maxLongSide:a}=t,o={...t.region},s=Math.max(1,Math.ceil(o.w/n.w)),c=Math.max(1,Math.floor(Wx/Math.min(s,Wx))),l=!1;s>Wx&&(o.w=Wx*n.w,l=!0),Math.ceil(o.h/n.h)>c&&(o.h=c*n.h,l=!0);let u=rS(o.x,o.w,n.w),d=rS(o.y,o.h,n.h),f=u.length===1&&d.length===1&&t.mode===`viewport`,p=null,m=null,h=1,g=1,_=0;for(let s of d)for(let c of u){let u=await cp(e.id,0,`page.scrollTo`,{position:{x:c,y:s},behavior:`instant`});if(!u.ok)throw new I(u.error.message,u.error.code);let d=u.data,v=Date.now()-_;_&&v<Ux&&await iS(Ux-v);let ee=await nS(e.windowId,r,i);_=Date.now();let te=ee.bitmap;if(!m){let e=te.width/n.w||t.dpr||1;if(g=tS(o.w*e,o.h*e,a),h=e*g,f&&g===1){let{width:e,height:t}=te;return te.close(),{format:r,width:e,height:t,dataUrl:ee.dataUrl,...l?{truncated:l}:{}}}if(m=new OffscreenCanvas(Math.max(1,Math.round(o.w*h)),Math.max(1,Math.round(o.h*h))),p=m.getContext(`2d`),!p)throw te.close(),new I(`OffscreenCanvas 2D context unavailable`,`CAPTURE_FAILED`)}p.drawImage(te,(d.scrollX-o.x)*h,(d.scrollY-o.y)*h,te.width*g,te.height*g),te.close()}if(!m)throw new I(`Nothing was captured`,`CAPTURE_FAILED`);return eS(m,r,i,l)}var Xx=640,Zx=.6;async function Qx(e){let t=await createImageBitmap(await(await fetch(e)).blob()),n=Math.min(1,Xx/Math.max(t.width,t.height,1)),r=new OffscreenCanvas(Math.max(1,Math.round(t.width*n)),Math.max(1,Math.round(t.height*n))),i=r.getContext(`2d`);return i?(i.drawImage(t,0,0,r.width,r.height),t.close(),aS(await r.convertToBlob({type:`image/jpeg`,quality:Zx}),`image/jpeg`)):(t.close(),``)}var $x=80;async function eS(e,t,n,r){let i=t===`jpeg`?`image/jpeg`:`image/png`,a=await aS(await e.convertToBlob(t===`jpeg`?{type:i,quality:(n??$x)/100}:{type:i}),i);return{format:t,width:e.width,height:e.height,dataUrl:a,...r?{truncated:r}:{}}}function tS(e,t,n){let r=Math.min(n,Gx)/Math.max(e,t,1),i=Math.sqrt(Kx/Math.max(e*t,1));return Math.min(1,r,i)}async function nS(e,n,r){let i=n===`jpeg`?r??$x:void 0;for(let r=0;;r++)try{let r=e==null?await t.tabs.captureVisibleTab({format:n,quality:i}):await t.tabs.captureVisibleTab(e,{format:n,quality:i});return{dataUrl:r,bitmap:await createImageBitmap(await(await fetch(r)).blob())}}catch(e){let t=e instanceof Error?e.message:String(e);if(r<2&&/MAX_CAPTURE_VISIBLE_TAB_CALLS_PER_SECOND/i.test(t)){await iS(Ux);continue}throw new I(`Cannot capture this tab (${t}) — it may be a chrome:// page, the Web Store, or a PDF, which browsers refuse to screenshot`,`CAPTURE_UNSUPPORTED`)}}function rS(e,t,n){let r=[];for(let i=e;i<e+t;i+=n)r.push(i);return r.length?r:[e]}var iS=e=>new Promise(t=>setTimeout(t,e));function aS(e,t){return e.arrayBuffer().then(e=>{let n=new Uint8Array(e),r=``,i=32768;for(let e=0;e<n.length;e+=i)r+=String.fromCharCode(...n.subarray(e,e+i));return`data:${t};base64,${btoa(r)}`})}var oS=16,sS=1200,cS=.85,lS=120;async function uS(e,t){let n=await U(e.id,td.name,t);if(!n.ok)return n;let{capture:r,...i}=n.data,a=r?await dS(e.id,r):null,s=a?await fS(e.windowId,a).catch(()=>null):null;return o(s?{...i,shot:s}:i)}async function dS(e,t){if(await Jf(e)===0)return t;let[n,r]=await Promise.all([ip(e),ep(e,0)]);return!n||!r?null:{...t,region:{...t.region,x:t.region.x+n.x,y:t.region.y+n.y},viewport:r.viewport}}async function fS(e,t){let{viewport:n,dpr:r}=t,i=Math.max(0,t.region.x-oS),a=Math.max(0,t.region.y-oS),o=Math.min(n.w,t.region.x+t.region.w+oS)-i,s=Math.min(n.h,t.region.y+t.region.h+oS)-a;if(o<1||s<1)return null;await new Promise(e=>setTimeout(e,lS));let{bitmap:c}=await nS(e,`jpeg`,Math.round(cS*100)),l=c.width/n.w||r,u=Math.min(1,sS/Math.max(o*l,s*l,1)),d=new OffscreenCanvas(Math.max(1,Math.round(o*l*u)),Math.max(1,Math.round(s*l*u))),f=d.getContext(`2d`);return f?(f.drawImage(c,i*l,a*l,o*l,s*l,0,0,d.width,d.height),c.close(),{dataUrl:await aS(await d.convertToBlob({type:`image/jpeg`,quality:cS}),`image/jpeg`),width:d.width,height:d.height}):(c.close(),null)}var pS=`browsentic/tabSessions`,mS=null,hS=Promise.resolve();function gS(e){let t=hS.then(e,e);return hS=t.catch(()=>void 0),t}async function X(){return mS||(mS=(await t.storage.session.get(`browsentic/tabSessions`))[`browsentic/tabSessions`]??{},mS)}function _S(e){return gS(async()=>{let n={...await X()},r=await e(n);return mS=n,await t.storage.session.set({[pS]:n}),r})}async function vS(e){let t=await X();return Object.values(t).find(t=>t.tabIds.includes(e))??null}async function yS(e){let t=await X();return Object.values(t).find(t=>t.runId===e)??null}async function bS(e){return _S(t=>{let n=Object.values(t).find(t=>t.tabIds.includes(e.tabId));if(n)return n.lastActivityAt=Date.now(),e.url&&(n.url=e.url,n.host=OS(e.url)??n.host),e.title&&(n.title=e.title),{ok:!0,session:n};if(Object.keys(t).length>=8)return{ok:!1,message:`8 tab sessions are already open — close one of those tabs, or end a session, before starting another.`};let r=Date.now(),i={sessionId:crypto.randomUUID(),mainTabId:e.tabId,tabIds:[e.tabId],currentTabId:e.tabId,windowId:e.windowId??-1,title:e.title??OS(e.url)??`This tab`,url:e.url,host:OS(e.url),runId:null,turns:0,createdAt:r,lastActivityAt:r};return t[i.sessionId]=i,{ok:!0,session:i}})}function xS(e,t){return _S(n=>{for(let[e,r]of Object.entries(n))r.tabIds.includes(t.tabId)&&!r.runId&&delete n[e];let r=Date.now(),i={sessionId:e.sessionId,mainTabId:t.tabId,tabIds:[t.tabId],currentTabId:t.tabId,windowId:t.windowId??-1,title:e.title??t.title??OS(e.url)??`This tab`,url:e.url??t.url,host:OS(e.url??t.url),runId:null,agent:e.agent,agentSessionId:e.agentSessionId,usage:e.usage,turns:e.turns,createdAt:r,lastActivityAt:r};return n[i.sessionId]=i,i})}function SS(e,t,n){return _S(r=>{let i=r[e];if(i){for(let n of Object.values(r))n.sessionId!==e&&(n.tabIds=n.tabIds.filter(e=>e!==t));i.tabIds.includes(t)||i.tabIds.push(t),n&&(i.currentTabId=t),i.lastActivityAt=Date.now()}})}function CS(e,t){return _S(n=>{let r=n[e];!r||!r.tabIds.includes(t)||(r.currentTabId=t,r.lastActivityAt=Date.now())})}function wS(e,t){return _S(n=>{let r=n[e];r&&Object.assign(r,t,{lastActivityAt:Date.now()})})}function TS(e){return _S(t=>{let n=t[e]??null;return delete t[e],n})}function ES(e){return _S(t=>{for(let n of Object.values(t))if(n.tabIds.includes(e))return n.mainTabId===e?(delete t[n.sessionId],{closed:n,shrunk:null}):(n.tabIds=n.tabIds.filter(t=>t!==e),n.currentTabId===e&&(n.currentTabId=n.mainTabId),{closed:null,shrunk:n});return{closed:null,shrunk:null}})}function DS(e,t){return _S(n=>{for(let r of Object.values(n))r.tabIds.includes(e)&&(r.tabIds=r.tabIds.map(n=>n===e?t:n),r.mainTabId===e&&(r.mainTabId=t),r.currentTabId===e&&(r.currentTabId=t))})}function OS(e){if(e)try{return new URL(e).host||void 0}catch{return}}async function kS(e,t,n,r){let i=await Em(e,t);if(i.refused.length)return s(`SECRET_NOT_RELEASABLE`,gm);if(i.unresolved.length)return s(`SECRET_EXPIRED`,_m);let{value:a}=await Tm(await MS(e,i.input,n,r),await AS(n,r));return a}async function AS(e,t){let n=await FS(e,t?await yS(t):null),r=n?.id==null?n?.url:await Yf(n.id,n.url);return r?jS(r):void 0}function jS(e){try{return new URL(e).hostname.toLowerCase()||void 0}catch{return}}async function MS(e,t,n,r){if(e===Pu.name)return YS(t);if(e===Fu.name)return XS(t);if(e===bd.name)return ZS(t);let i=r?await yS(r):null;if(e===Vu.name)return IS(t,i);if(e===cf.name)return RS(t,n??i?.currentTabId,i?.sessionId);if(e===vd.name)return zS(t);if(e===yd.name)return BS(t);if(e===bf.name)return VS(t);if(e===lf.name)return HS(t,n??i?.currentTabId);if(e===Lu.name)return US(t);if(e===xf.name)return WS(t);if(e===Nc.name)return GS(t);if(e===yf.name)return KS(t,i?.sessionId);if(e===Tf.name)return qS(t);if(e===Sf.name)return JS(t);let a=await FS(n,i);return a?.id==null?i?s(`SESSION_TAB_CLOSED`,`The tab this conversation was working in has been closed.`):n==null?s(`NO_ACTIVE_TAB`,`No active tab to control`):s(`MAPPING_TAB_CHANGED`,`The tab this run started in has been closed.`):e===Bu.name?eC(a.id,t):e===Zd.name?rC(a.id,t):e===wf.name?LS({id:a.id,windowId:a.windowId},t,i):e===fu.name?mg(a.id,a.url,t):e===Rc.name?fy({id:a.id,windowId:a.windowId},t):e===Jd.name?qx({id:a.id,windowId:a.windowId},t,r):e===td.name?uS({id:a.id,windowId:a.windowId},t):e===pc.name?QS(a.id,t):e===Fc.name?Eg(a.id,t):e===Mu.name?og(a.id,await Yf(a.id,a.url),t):e===qd.name?ug(a.id,await Yf(a.id,a.url),t):e===vu.name?Sg(a.id,a.url,t):e===Iu.name?Cg(a.id,await Yf(a.id,a.url)):e===Pc.name?wg(a.id,await Yf(a.id,a.url),t):e===Ef.name?eh(a.id,t):e===cl.name&&NS(t)?th(a.id,t):e===El.name?ch(a.id):e===sf.name?lh(a.id,t):U(a.id,e,t)}function NS(e){return e?.trusted===!0}async function PS(e){try{return await t.tabs.get(e)}catch{return}}async function FS(e,n){return n?await PS(n.currentTabId)??await PS(n.mainTabId):e==null?(await t.tabs.query({active:!0,currentWindow:!0}))[0]:PS(e)}async function IS(e,t){if(!t)return uy(e);let n=await PS(t.currentTabId)??await PS(t.mainTabId),r=await uy(e,n?.id==null?void 0:{id:n.id,windowId:n.windowId});if(!r.ok)return r;let i=r.data.tabId;return typeof i==`number`&&await SS(t.sessionId,i,r.data.activeTabId===i),r}async function LS(e,t,n){if(!n)return dy(e,t);let r=t??{};if(typeof r.tabId==`number`&&!n.tabIds.includes(r.tabId)&&await vS(r.tabId))return s(`TAB_IN_USE`,`Another Browsentic conversation is working in tab ${r.tabId}. Leave it alone, or ask the user to end that session first.`);let i=await dy(e,t);if(!i.ok)return i;let a=i.data.activeTabId;return typeof a!=`number`||a===e.id||(n.tabIds.includes(a)?await CS(n.sessionId,a):await vS(a)||await SS(n.sessionId,a,!0)),i}async function RS(e,t,n){let r=cf.input.safeParse(e??{});return r.success?zy(r.data,t,n):s(`INVALID_INPUT`,x(r.error))}async function zS(e){let t=vd.input.safeParse(e??{});return t.success?Hy(t.data):s(`INVALID_INPUT`,x(t.error))}async function BS(e){let t=yd.input.safeParse(e??{});return t.success?Uy(t.data):s(`INVALID_INPUT`,x(t.error))}async function VS(e){let t=bf.input.safeParse(e??{});return t.success?qy(t.data.diagnosticsId):s(`INVALID_INPUT`,x(t.error))}async function HS(e,t){let n=lf.input.safeParse(e??{});return n.success?Wb(n.data,t):s(`INVALID_INPUT`,x(n.error))}async function US(e){let t=Lu.input.safeParse(e??{});return t.success?Zb(t.data.monitorId):s(`INVALID_INPUT`,x(t.error))}async function WS(e){let t=xf.input.safeParse(e??{});return t.success?Xb(t.data.monitorId):s(`INVALID_INPUT`,x(t.error))}async function GS(e){let t=Nc.input.safeParse(e??{});return t.success?Qb(t.data.monitorId,t.data.timeoutMs):s(`INVALID_INPUT`,x(t.error))}async function KS(e,t){let n=yf.input.safeParse(e??{});return n.success?Cx(n.data,t):s(`INVALID_INPUT`,x(n.error))}async function qS(e){let t=Tf.input.safeParse(e??{});return t.success?Ax(t.data.timerId):s(`INVALID_INPUT`,x(t.error))}async function JS(e){let t=Sf.input.safeParse(e??{});return t.success?kx(t.data.timerId):s(`INVALID_INPUT`,x(t.error))}async function YS(e){let t=e?.nameContains,n=typeof t==`string`?t.toLowerCase():null;return o({files:(await dv()).filter(e=>!n||e.name.toLowerCase().includes(n)).map(({id:e,name:t,mime:n,size:r,status:i,summary:a,addedAt:o})=>({id:e,name:t,mime:n,size:r,status:i,summary:a,addedAt:o}))})}async function XS(e){let t=e,n=typeof t?.host==`string`?t.host.toLowerCase():null,r=typeof t?.nameContains==`string`?t.nameContains.toLowerCase():null;return o({recordings:(await Nv()).filter(e=>!n||e.host.toLowerCase()===n).filter(e=>!r||`${e.name} ${e.goal??``}`.toLowerCase().includes(r)).map(({id:e,name:t,host:n,status:r,goal:i,summary:a,steps:o,capturedValues:s,durationMs:c,createdAt:l})=>({id:e,name:t,host:n,status:r,goal:i,summary:a,steps:o,capturedValues:s,durationMs:c,createdAt:l}))})}async function ZS(e){let t=e?.recordingId;if(typeof t!=`string`||!t)return s(`INVALID_INPUT`,`Provide the "recordingId" of a recording from page.listRecordings.`);let n=(await Nv()).find(e=>e.id===t);if(!n)return s(`RECORDING_NOT_FOUND`,`No recording with id "${t}".`);let r=await Iv(t);return r?.workflow?o({id:n.id,name:n.name,host:n.host,startUrl:n.startUrl,capturedValues:n.capturedValues,durationMs:n.durationMs,goal:r.workflow.goal,summary:r.workflow.summary,variables:r.workflow.variables,caveats:r.workflow.caveats,steps:r.workflow.steps}):s(`RECORDING_NOT_READY`,n.status===`error`?`That recording could not be turned into steps: ${n.error??`unknown error`}`:`That recording is still being turned into steps — try again shortly.`)}async function QS(e,t){let n=t??{};if(typeof n.content==`string`&&n.content)return U(e,pc.name,t);let{fileId:r,target:i}=n;if(typeof r!=`string`||!r)return s(`INVALID_INPUT`,`attachFile needs a "fileId" from page.listFiles or a "downloadId" from page.captureDownload.`);let a=await pv(r);return a?U(e,pc.name,{fileId:r,target:i,name:a.name,mime:a.mime,content:a.content}):s(`FILE_NOT_FOUND`,`No stored file with id "${r}". Call page.listFiles to see stored files.`)}var $S=`Receiving end does not exist`;async function eC(e,t){await Zf(e);let n=await cp(e,0,Bu.name,t);return n.ok?o({...n.data,loaded:await py(e).settled}):n.error.code===`TAB_UNREACHABLE`?n.error.message.includes($S)?tC(e,t):o({navigating:!0,loaded:await py(e).settled}):n}async function tC(e,n){let r=Bu.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let i;try{i=zu(r.data)}catch(e){return e instanceof I?s(e.code,e.message):s(`ACTION_FAILED`,String(e))}let a=py(e);try{i.kind===`url`?await t.tabs.update(e,{url:i.href}):i.action===`reload`?await t.tabs.reload(e):i.action===`back`?await t.tabs.goBack(e):await t.tabs.goForward(e)}catch(e){a.cancel();let t=e instanceof Error?e.message:String(e);return s(`ACTION_FAILED`,i.kind===`history`&&i.action!==`reload`?`Cannot go ${i.action}: this tab has no ${i.action===`back`?`previous`:`next`} page in its history (${t})`:t)}let c=await a.settled;return o(i.kind===`url`?{navigatedTo:i.href,loaded:c}:{performed:i.action,loaded:c})}var nC=2e3;async function rC(e,t){let n=await U(e,Zd.name,t);if(!n.ok)return n;let r=n.data,i=await iC(e,r.via===`url`||r.submitted===!0);return o({...n.data,loaded:i,landedOn:(await PS(e))?.url})}async function iC(e,t){let n=py(e);if(t)return n.settled;let r=await Promise.race([n.settled,new Promise(e=>setTimeout(()=>e(null),nC))]);return r===null&&n.cancel(),r??!1}var aC=`browsentic:skills`,oC=e=>`browsentic:skill:${e}`;async function sC(){let e=(await t.storage.local.get(aC))[aC];return Array.isArray(e)?e:[]}async function cC(e){await t.storage.local.set({[aC]:e})}async function lC(e){let n=oC(e),r=(await t.storage.local.get(n))[n];return r&&typeof r.body==`string`?r:null}async function uC(e,t){await cC((await sC()).map(n=>n.id===e?{...n,...t}:n))}async function dC(e){let t=(await sC()).find(t=>t.id===e);if(t?.origin===`generated`)return;let n=await lC(e);if(!t||!n){await uC(e,{status:`error`,error:`The skill is missing from storage.`});return}let r=await C_({name:t.name,description:t.description,category:t.category,domains:t.domains,triggers:n.triggers,body:n.body});r.ok?await uC(e,{status:`saved`,path:r.data.path,error:void 0}):await uC(e,{status:`error`,error:`${r.error.code}: ${r.error.message}`})}async function fC(e){let n=(await sC()).find(t=>t.id===e);n&&await(n.origin===`generated`?T_(n.name):w_(n.name)),await t.storage.local.remove(oC(e)),await cC((await sC()).filter(t=>t.id!==e))}async function pC(e){let t=await sC();await cC([{id:crypto.randomUUID(),name:e.name,description:`Mapped ${e.domain} — ${e.pages} pages.`,category:`site-exploration`,domains:[e.domain],status:`saved`,path:e.directory,addedAt:Date.parse(e.generatedAt)||Date.now(),origin:`generated`,pages:e.pages},...t.filter(t=>t.name!==e.name)])}async function mC(){for(let e of await sC())e.status!==`saved`&&e.origin!==`generated`&&await dC(e.id)}var hC=`browsentic:sessions`,gC=e=>`browsentic:session:${e}`,_C=50,vC=[1,5,15];async function yC(){let e=(await t.storage.local.get(hC))[hC];return Array.isArray(e)?e:[]}async function bC(e){await t.storage.local.set({[hC]:e})}async function xC(e,n){if(!n.length)return;let r={id:e.id,items:n.slice(-500).map(SC)};await t.storage.local.set({[gC(e.id)]:r});let i=await yC(),a=[{...i.find(t=>t.id===e.id),...e},...i.filter(t=>t.id!==e.id)],o=a.slice(_C);o.length&&await t.storage.local.remove(o.map(e=>gC(e.id))),await bC(a.slice(0,_C))}function SC(e){if(e.kind!==`tool`||!e.preview)return e;let{preview:t,...n}=e;return n}async function CC(e){let n=gC(e),r=(await t.storage.local.get(n))[n];return r&&Array.isArray(r.items)?r:null}async function wC(e,t){let n=await yC();n.some(t=>t.id===e)&&await bC(n.map(n=>n.id===e?{...n,...t}:n))}var TC=60;async function EC(e){let t=(await yC()).find(t=>t.id===e);if(!t)return;let n=((await CC(e))?.items??[]).filter(e=>e.kind===`user`).map(e=>e.text).slice(-12);if(!n.length)return;let r=t.turns;await wC(e,{namingAt:Date.now()});let i=await b_({host:t.host,messages:n});if(i.ok&&i.data.title.trim()){await wC(e,{title:i.data.title.replace(/\s+/g,` `).trim().slice(0,TC),titledAtTurn:r,namingAt:void 0});return}await wC(e,{titledAtTurn:r,namingAt:void 0})}function DC(e,t=0){let n=vC.filter(t=>e>=t).at(-1);return n!==void 0&&n>t?n:null}var OC=`/context`,kC=e=>e.trim().toLowerCase()===OC;async function AC(e){let{offer:t,code:n}=e,r={host:t.host,segment:t.segment},i=Mh(e.slug??``)||t.suggestedSlug,a=await Kh(r,i),o={id:crypto.randomUUID(),name:a,skillName:Fh(r,i),description:t.purpose,scope:r,origin:t.origin,code:n,fn:t.fn,createdAt:Date.now()};return await Wh(o),await C_(MC(o)).catch(()=>void 0),Vh(o)}async function jC(e){let t=await Gh(e);return t&&await w_(t.skillName).catch(()=>void 0),t}function MC(e){let t=e.scope.segment===`root`?e.scope.host:`${e.scope.host}/${e.scope.segment}`;return{name:e.skillName,description:`Saved tool on ${t}: ${e.description}`,category:`site-exploration`,domains:[e.scope.host],triggers:[e.name,e.scope.host],body:[`# ${e.name}`,``,`The user saved a tool for **${t}**, out of page code they read and approved:`,``,`> ${e.description}`,``,`## How it runs`,``,`It runs from the side panel, by typing \`/${e.name}\`. It is already approved, so it`,`needs no further permission and costs no round trip.`,``,`## What you should do`,``,`You cannot call it yourself: it is not a page action, and its code lives in the extension`,`rather than here. If the user asks for this on this page, tell them the tool exists and to`,`run \`/${e.name}\`, rather than writing the same thing again with page.injectCode.`,``,`If they want it changed, write fresh code with page.injectCode as usual and let them save`,`that over the old one.`].join(`
184
- `)}}var NC=/\b([a-z0-9][a-z0-9-]*)\s+dot\s+(com|net|org|io|dev|co|ai|app|edu|gov|me|uk|xyz)\b/g,PC=/^(?:hey|hi|ok|okay|yo|um|uh|please|browsentic|assistant|can you|could you|would you|will you|i want you to|i would like you to|id like you to|lets|just|now|go ahead and)\s+/,FC=/\s+(?:please|thanks|thank you|for me|now|a bit|a little|a lot|some more|more|slightly|real quick|quickly)$/,IC=/[^a-z0-9\s./:&=@_+#-]/g;function LC(e){let t=e.trim(),n=t.toLowerCase().replace(/['‘’]/g,``);n=n.replace(NC,`$1.$2`),n=n.replace(IC,` `).replace(/\s+/g,` `).trim();let r=!1,i;do i=n,n=n.replace(PC,``).replace(FC,``).trim(),r||=n!==i;while(n!==i);return{text:n.replace(/\.$/,``),raw:t,question:/\?\s*$/.test(t)&&!r}}var RC={google:`google.com`,"google maps":`maps.google.com`,maps:`maps.google.com`,"google drive":`drive.google.com`,drive:`drive.google.com`,"google calendar":`calendar.google.com`,calendar:`calendar.google.com`,gmail:`mail.google.com`,youtube:`youtube.com`,github:`github.com`,reddit:`reddit.com`,wikipedia:`wikipedia.org`,twitter:`twitter.com`,linkedin:`linkedin.com`,facebook:`facebook.com`,instagram:`instagram.com`,amazon:`amazon.com`,netflix:`netflix.com`,"stack overflow":`stackoverflow.com`,stackoverflow:`stackoverflow.com`,"hacker news":`news.ycombinator.com`,chatgpt:`chatgpt.com`,claude:`claude.ai`},zC=new Set([`enter`,`return`]),BC={escape:`Escape`,esc:`Escape`,tab:`Tab`,space:` `,spacebar:` `,backspace:`Backspace`,delete:`Delete`,"page up":`PageUp`,"page down":`PageDown`,home:`Home`,end:`End`,"up arrow":`ArrowUp`,"down arrow":`ArrowDown`,"left arrow":`ArrowLeft`,"right arrow":`ArrowRight`,"arrow up":`ArrowUp`,"arrow down":`ArrowDown`,"arrow left":`ArrowLeft`,"arrow right":`ArrowRight`},VC=Object.keys(BC).join(`|`),HC=/\b(?:buy|buy now|purchase|pay|payment|checkout|place order|order now|delete|remove|send|submit|transfer|withdraw|deposit|unsubscribe|subscribe|donate|book now|confirm)\b/,UC=/^(?:it|that|this|there|them|those|these|him|her|thing|one)$/,WC=8,GC=[{id:`history.back`,action:Bu.name,certainty:.97,pattern:/^(?:go\s+)?back(?:\s+(?:a|one)\s+page)?$/,build:()=>qC({action:`back`},`Go back`)},{id:`history.forward`,action:Bu.name,certainty:.97,pattern:/^(?:go\s+)?forwards?(?:\s+(?:a|one)\s+page)?$/,build:()=>qC({action:`forward`},`Go forward`)},{id:`history.reload`,action:Bu.name,certainty:.97,pattern:/^(?:reload|refresh)(?:\s+(?:the|this)\s+page)?$/,build:()=>qC({action:`reload`},`Reload the page`)},{id:`tab.open`,action:Vu.name,certainty:.95,pattern:/^(?:go\s+to|goto|open|visit|navigate\s+to|take\s+me\s+to|load|pull\s+up)\s+(?:the\s+)?(?<dest>\S+(?:\s+\S+)?)\s+in\s+(?:an?\s+)?(?:new|another|separate)\s+tab$/,build:({dest:e})=>{let t=RC[e];if(t)return JC({url:`https://${t}`},`Open ${t} in a new tab`,1);let n=ZC(e);return n?JC({url:n},`Open ${e} in a new tab`,/^https?:\/\//.test(e)?1:.97):null}},{id:`navigate.url`,action:Bu.name,certainty:.95,pattern:/^(?:go\s+to|goto|open|visit|navigate\s+to|take\s+me\s+to|load|pull\s+up)\s+(?:the\s+)?(?<dest>\S+(?:\s+\S+)?)$/,build:({dest:e})=>{let t=RC[e];if(t)return qC({url:`https://${t}`},`Open ${t}`,1);let n=ZC(e);return n?qC({url:n},`Open ${e}`,/^https?:\/\//.test(e)?1:.97):null}},{id:`navigate.search`,action:Bu.name,certainty:.9,pattern:/^(?<verb>google|search\s+(?:the\s+web|google)\s+for|web\s+search\s+for)\s+(?<q>.+)$/,build:({verb:e,q:t})=>{let n=t.trim();return e===`google`&&n.split(` `).length<2?null:qC({url:`https://www.google.com/search?q=${encodeURIComponent(n)}`},`Search the web for "${n}"`,e===`google`?.95:1)}},{id:`site.search`,action:Zd.name,certainty:.95,pattern:/^search\s+(?:(?:on|in)\s+)?(?:(?:this|the)\s+(?:site|website)|here)\s+for\s+(?<q>.+)$/,build:({q:e})=>{let t=e.trim();return t?KC({query:t},`Search this site for "${t}"`):null}},{id:`scroll.direction`,action:Yd.name,certainty:.95,pattern:/^(?:scroll|jump|move|go)(?:\s+(?:to|down\s+to|back\s+to|all\s+the\s+way\s+to))?\s+(?:the\s+)?(?<dir>up|down|top|bottom)(?:\s+of\s+(?:the\s+)?page)?$/,build:({dir:e})=>YC({direction:e},`Scroll ${e}`)},{id:`scroll.page`,action:Yd.name,certainty:.95,pattern:/^page\s+(?<dir>up|down)$/,build:({dir:e})=>YC({direction:e},`Scroll ${e}`)},{id:`scroll.element`,action:Yd.name,certainty:.85,pattern:/^scroll\s+(?:down\s+)?to\s+(?:the\s+)?(?<label>.+)$/,build:({label:e})=>{let t=XC(e);return t&&YC({target:{text:t.value}},`Scroll to ${t.value}`,t.confidence)}},{id:`key.press`,action:nd.name,certainty:.97,pattern:RegExp(`^(?:press|hit|tap|push)(?:\\s+the)?\\s+(?<key>${VC})(?:\\s+key)?$`),build:({key:e})=>{let t=BC[e];return t?KC({key:t},`Press ${e}`):null}},{id:`recording.start`,action:pp,certainty:.95,pattern:/^(?:start\s+record(?:ing)?(?:\s+(?:my|this|the))?(?:\s+(?:browsing|browser))?(?:\s+session)?|record(?:ing)?(?:\s+(?:my|this|the))?(?:\s+(?:browsing|browser))?\s+session)$/,build:()=>KC({captureValues:!1},`Start recording this session`)},{id:`recording.stop`,action:mp,certainty:.95,pattern:/^(?:stop|end|finish)\s+(?:the\s+)?recording$/,build:()=>KC({},`Stop recording`)},{id:`monitor.stop`,action:xf.name,certainty:.95,pattern:/^(?:stop|end|quit|cancel)\s+(?:the\s+)?(?:monitor(?:ing)?|watching)(?:\s+(?:the|this|that)\s+\S{1,20})?$/,build:()=>KC({},`Stop monitoring`)},{id:`click.text`,action:Lc.name,certainty:.9,pattern:/^(?:click|tap|press|hit|push)(?:\s+on)?(?:\s+the)?\s+(?<label>.+?)(?:\s+(?<role>button|link|tab|checkbox))?$/,build:({label:e,role:t})=>{let n=XC(e);return!n||!t&&zC.has(n.value.toLowerCase())?null:{input:{target:t?{text:n.value,role:t}:{text:n.value}},label:`Click ${n.value}`,confidence:n.confidence,risky:HC.test(n.value)}}}],KC=(e,t,n=1)=>({input:e,label:t,confidence:n}),qC=(e,t,n=1)=>KC(e,t,n),JC=(e,t,n=1)=>KC(e,t,n),YC=(e,t,n=1)=>KC(e,t,n);function XC(e){let t=e.trim();if(!t)return null;let n=t.split(/\s+/);if(n.length>WC)return null;if(UC.test(t))return{value:t,confidence:.55};let r=1;return n.length>4&&(r-=.12*(n.length-4)),t.length<2&&(r-=.4),{value:t,confidence:Math.max(0,r)}}function ZC(e){return/^https?:\/\/\S+$/.test(e)?e:/^localhost(?::\d+)?(?:\/\S*)?$/.test(e)?`http://${e}`:/^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z]{2,}(?::\d+)?(?:\/\S*)?$/.test(e)?`https://${e}`:null}var QC=/^(?:what|whats|why|how|who|when|where|which|is|are|was|were|do|does|did|can|could|should|would|tell|explain|describe|summarize|summarise|read|find|show|check|look|see|list|compare|help|write|draft|fill)\b/,$C=/\b(?:and then|then|after that|and also|followed by)\b/,ew=/\b(?:if|unless|whenever|maybe|might|try to|see if|as soon as|in case|otherwise)\b/;function tw(e){let t=LC(e);if(t.raw.startsWith(`@`))return nw(`skill-prefix`,0);if(!t.text)return nw(`no-match`,0);if(t.question||QC.test(t.text))return nw(`question`,0);if($C.test(t.text))return nw(`multi-step`,0);if(ew.test(t.text))return nw(`conditional`,0);let n=null;for(let e of GC){let r=e.pattern.exec(t.text);if(!r)continue;let i=e.build(r.groups??{});if(!i)continue;let a=rw(e.certainty*i.confidence);(!n||a>n.score)&&(n={rule:e,score:a,label:i.label,input:i.input,risky:i.risky===!0})}return n?n.risky?nw(`consequential`,n.score,n.rule.id):n.score<.75?nw(`below-threshold`,n.score,n.rule.id):{decision:`act`,intent:{ruleId:n.rule.id,action:n.rule.action,input:n.input,label:n.label,score:n.score}}:nw(`no-match`,0)}var nw=(e,t,n)=>({decision:`escalate`,reason:e,score:t,ruleId:n}),rw=e=>Math.round(e*1e3)/1e3;async function iw(e,t,n){let r=tw(e);if(r.decision!==`act`)return!1;let{action:i,input:a,label:o,ruleId:s,score:c}=r.intent,l=`local-${crypto.randomUUID()}`;t({kind:`tool`,toolId:l,action:i,input:a,source:`local`});let u=Date.now(),d=await aw(i,a,n),f=Date.now()-u;return t({kind:`toolResult`,toolId:l,ok:d.ok,summary:d.ok?`${o} · ${f} ms`:`${d.error.code}: ${d.error.message}`}),d.ok||ow(i)?!0:(console.debug(`[browsentic] fast path ${s} (${c}) failed, escalating:`,d.error.code),!1)}async function aw(e,t,n){return e===pp?$v(t?.captureValues===!0):e===mp?ny(`user`):kS(e,t,n)}function ow(e){return e===pp||e===mp}var sw=`browsentic/indicator`,cw=`#ff7a3d`,lw=`browsentic/rail`;function uw(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.channel===`browsentic/rail`&&(t.op===`open`||t.op===`sync`)}var dw=`browsentic/panelCollapsed`,fw=`browsentic/panelTab`;async function pw(){return(await t.storage.local.get(dw))[dw]===!0}async function mw(){let e=(await t.storage.local.get(fw))[fw];return typeof e==`string`?e:`chat`}function hw(e){return t.sidePanel.open({windowId:e})}var gw=`browsentic/daemon`;async function _w(e){await t.storage.local.set({[dw]:e}),await xw()}var vw=null,yw=!1,bw=null;function xw(){return vw?(yw=!0,vw):(vw=(async()=>{do yw=!1,await Cw();while(yw);vw=null})(),vw)}async function Sw(){await pw()||(bw=null,await xw())}async function Cw(){let e=await pw();if(!e&&bw===!1)return;let n=e?{channel:lw,op:`show`,view:await Ew()}:{channel:lw,op:`hide`},r=await t.tabs.query({});await Promise.all(r.map(e=>Tw(e.id,e.discarded,n))),bw=e}async function ww(e){await pw()&&await Tw(e,!1,{channel:lw,op:`show`,view:await Ew()})}function Tw(e,n,r){if(!(e==null||n))return t.tabs.sendMessage(e,r).catch(()=>void 0)}async function Ew(){let[e,t,n,r,i,a,o,s]=await Promise.all([Ow(),yC(),sC(),Nv(),X(),mw(),kw(),Sb()]),c=Object.values(i).filter(e=>e.runId).length,l=Dw(e,c>0);return{tab:a,theme:s,side:o,running:c,tone:l.tone,status:l.label,counts:{history:t.length,skills:n.length,recordings:r.length}}}function Dw(e,t){return e?.paired?e.connected?t?{tone:`busy`,label:`Working`}:{tone:`live`,label:`Online`}:{tone:`pending`,label:`Reconnecting`}:{tone:`off`,label:`Not paired`}}async function Ow(){return(await t.storage.session.get(gw))[gw]??null}async function kw(){let e=t.sidePanel;if(!e.getLayout)return`right`;try{return(await e.getLayout()).side===`left`?`left`:`right`}catch{return`right`}}function Aw(){t.runtime.onMessage.addListener((e,n)=>{if(!uw(e))return;let{id:r,windowId:i}=n.tab??{};if(!(r==null||i==null))return e.op===`sync`?(ww(r),Promise.resolve({ok:!0})):(hw(i).catch(()=>void 0),t.storage.local.set({[fw]:e.tab}),Promise.resolve({ok:!0}))}),t.tabs.onUpdated.addListener((e,t)=>{t.status===`complete`&&ww(e)}),t.storage.local.onChanged.addListener(e=>{(`browsentic/panelCollapsed`in e||`browsentic/panelTab`in e||`browsentic/theme`in e)&&xw()}),t.storage.session.onChanged.addListener(e=>{gw in e&&xw()})}var jw=`●`,Mw=new Set;function Nw(){return t.action??null}async function Pw(){let e=new Set;for(let t of Object.values(await X()))if(t.runId)for(let n of t.tabIds)e.add(n);for(let t of e)Mw.has(t)||await Iw(t,!0);for(let t of[...Mw])e.has(t)||await Iw(t,!1);await xw()}function Fw(e){Mw.delete(e)}async function Iw(e,n){n?Mw.add(e):Mw.delete(e);let r=Nw();if(r)try{await r.setBadgeBackgroundColor({tabId:e,color:cw}),await r.setBadgeText({tabId:e,text:n?jw:``})}catch{Mw.delete(e)}await t.tabs.sendMessage(e,{channel:sw,op:n?`busy`:`idle`}).catch(()=>void 0)}var Lw=`[redacted]`,Rw=200,zw=20,Bw=4;function Vw(e,t,n){if(typeof t==`string`)return xp({name:e,id:e,value:t})?Lw:t.length>Rw?`${t.slice(0,Rw)}…`:t;if(typeof t==`number`||typeof t==`boolean`||t===null)return t;if(n>=Bw)return`[…]`;if(Array.isArray(t)){let r=t.slice(0,zw).map(t=>Vw(e,t,n+1));return t.length>zw?[...r,`…`]:r}if(typeof t==`object`){let e={};for(let[r,i]of Object.entries(t))e[r]=xp({name:r,id:r})?Lw:Vw(r,i,n+1);return e}return null}var Hw={"page.fillInput":`value`,"page.typeText":`text`},Uw={"page.injectCode":[`purpose`,`code`]};function Ww(e,t){if(!t||typeof t!=`object`)return Vw(``,t,0);let n=Vw(``,t,0);for(let r of Uw[e]??[]){let e=t[r];typeof e==`string`&&(n[r]=e)}let r=Hw[e];if(r&&r in n){let e=t[r],i=typeof e==`string`?am(e):[];n[r]=i.length?i.map(e=>e.text).join(` `):Lw}return n}var Gw=()=>crypto.randomUUID();function Kw(e,t){switch(t.kind){case`started`:{let n=t.attached?` + attached: ${t.attached}`:``,r=t.overlays?.length?` + site notes: ${t.overlays.join(`, `)}`:``;return[...e,{kind:`notice`,id:Gw(),tone:`info`,text:`Loaded skill: ${t.skill}${n}${r}`}]}case`text`:{let n=e.at(-1);return n?.kind===`assistant`?[...e.slice(0,-1),{...n,text:n.text+t.delta}]:[...e,{kind:`assistant`,id:Gw(),text:t.delta}]}case`tool`:return[...e,{kind:`tool`,id:t.toolId,action:t.action,input:Ww(t.action,t.input),source:t.source}];case`approval`:return qw(e,t.toolId,{awaiting:!0,site:t.site});case`toolResult`:return qw(e,t.toolId,{ok:t.ok,summary:t.summary,awaiting:!1});case`session`:case`usage`:return e;case`done`:return t.stopReason===`end_turn`?e:[...e,{kind:`notice`,id:Gw(),tone:`info`,text:`Stopped: ${t.stopReason}`}];case`error`:return[...e,{kind:`notice`,id:Gw(),tone:`error`,text:`${t.code}: ${t.message}`}]}}function qw(e,t,n){return e.map(e=>e.kind===`tool`&&e.id===t?{...e,...n}:e)}function Jw(e,t){for(let n=e.length-1;n>=0;n--){let r=e[n];if(r.kind===`tool`&&r.action===Jd.name&&!r.preview){let i=[...e];return i[n]={...r,preview:t},i}}return e}function Yw(e,t){return{kind:`notice`,id:Gw(),tone:e,text:t}}function Xw(e){let t=e.label??e.host,n=Zw(e.elapsedMs);switch(e.phase){case`done`:return{tone:`info`,text:`Monitor “${t}” finished after ${n}.`};case`stopped`:return{tone:`info`,text:`Monitor “${t}” stopped.`};case`timeout`:return{tone:`error`,text:`Monitor “${t}” gave up after ${n} without completing.`};case`tab-closed`:return{tone:`error`,text:`Monitor “${t}” ended — the tab was closed.`};default:return{tone:`error`,text:`Monitor “${t}” ended — ${e.message??`the tab left the watched site.`}`}}}function Zw(e){let t=Math.floor(e/1e3);return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}var Qw=`local`,$w=4e3,eT=800,tT=new Set,nT=new Set,rT=new Set,Z=new Map,iT=new Set,aT=new Map,oT=new Map,sT=[],cT=new Map,lT=new Map,uT=Promise.resolve();function Q(e){let t=uT.then(e,e);return uT=t.catch(()=>void 0),t}function dT(){l_((e,t)=>{Q(()=>_T(e,t))}),Bx((e,t)=>{Q(async()=>{let n=t?await yS(t):null;if(n){let t=Jw(await DT(n.sessionId),e);Z.set(n.sessionId,t)}$({op:`preview`,sessionId:n?.sessionId,preview:e})})}),eg(e=>{lT.set(e.toolkitId,e),$({op:`toolOffer`,offer:e})}),Fb(e=>{$({op:`monitor`,state:e}),e.phase!==`watching`&&(Q(async()=>{let t=e.tabId==null?null:await vS(e.tabId);t&&await OT(t.sessionId,Yw(...BT(e)))}),tT.size>0&&nx(e.monitorId))}),px((e,t,n)=>Q(async()=>{let r=(await X())[e];return r?r.runId||iT.has(e)?`busy`:(await OT(e,Yw(`info`,`Timer “${n}” fired.`)),await bT(r,t,{fastPath:!1}),`delivered`):`gone`})),c_((e,t)=>{Q(async()=>{let n=await yS(e);if(n)for(let[e,t]of cT)t.sessionId===n.sessionId&&cT.delete(e);cT.set(t.stagingId,{sessionId:n?.sessionId,draft:t}),$({op:`mapDraft`,sessionId:n?.sessionId,draft:t})})}),u_(()=>{Q(async()=>{for(let e of Object.values(await X()))e.runId&&await CT(e.sessionId,`The connection to the daemon dropped, so that run is over.`)})}),qv(e=>{e?.warning&&$({op:`event`,runId:Qw,event:{kind:`error`,code:`RECORDING_LIMIT`,message:e.warning}}),$({op:`recording`,state:e})}),t.runtime.onConnect.addListener(e=>{if(e.name===`browsentic/run`){if(tT.add(e),e.sender?.url?.includes(`sidepanel.html`)&&(nT.add(e),nT.size===1))for(let e of rT)e(!0);for(let t of cT.values())UT(e,{op:`mapDraft`,sessionId:t.sessionId,draft:t.draft});Zv().then(t=>UT(e,{op:`recording`,state:t})),Hh().then(t=>UT(e,{op:`tools`,tools:t.map(Vh)})),ex().then(t=>{for(let n of t)UT(e,{op:`monitor`,state:n})}),tx().then(t=>{if(t.length){for(let n of t)UT(e,{op:`monitor`,state:n});nx()}}),e.onMessage.addListener(e=>mT(e)),e.onDisconnect.addListener(()=>{if(tT.delete(e),nT.delete(e)&&nT.size===0)for(let e of rT)e(!1)})}})}function fT(e){rT.add(e)}function pT(){for(let e of nT)UT(e,{op:`close`})}function mT(e){switch(e.op){case`instruct`:Q(()=>yT(e.text,e.tab,e.agentSkillId,e.focus,e.liveTools));return;case`cancel`:Q(()=>ST(e.sessionId));return;case`decision`:Q(async()=>{let t=(await X())[e.sessionId];t?.runId&&(Z.set(e.sessionId,qw(await DT(e.sessionId),e.toolId,{awaiting:!1})),await wS(e.sessionId,{pendingApproval:void 0}),U_(t.runId,e.toolId,e.allow,e.remember))});return;case`endSession`:Q(()=>TT(e.sessionId));return;case`replay`:Q(async()=>{$({op:`items`,sessionId:e.sessionId,items:await DT(e.sessionId)})});return;case`restore`:Q(()=>ET(e.sessionId,e.tab));return;case`activateMap`:case`discardMap`:{let t=cT.get(e.stagingId);(e.op===`activateMap`?E_(e.stagingId,e.exactHost):D_(e.stagingId)).then(n=>{if(n.ok&&e.op===`activateMap`&&t){let{draft:n}=t;pC({name:n.name,domain:e.exactHost?n.host:n.domain,directory:n.directory,pages:n.pages,generatedAt:n.generatedAt})}cT.delete(e.stagingId),$({op:`mapSettled`,sessionId:t?.sessionId,stagingId:e.stagingId,ok:n.ok,message:n.ok?void 0:`${n.error.code}: ${n.error.message}`})});return}case`startRecording`:MT(e.captureValues);return;case`stopRecording`:ny(`user`);return;case`stopMonitor`:Xb(e.monitorId);return;case`keepTool`:Q(async()=>{let t=lT.get(e.toolkitId),n=t?await lg(e.tabId,e.toolkitId):null;t&&n&&await AC({offer:t,code:n,slug:e.slug}).catch(()=>void 0),lT.delete(e.toolkitId),$({op:`toolOfferSettled`,toolkitId:e.toolkitId}),await gT()});return;case`dismissTool`:lT.delete(e.toolkitId),$({op:`toolOfferSettled`,toolkitId:e.toolkitId});return;case`forgetTool`:Q(async()=>{await jC(e.id),await gT()});return;case`runTool`:Q(async()=>{let t=await cg(e.tab.tabId,e.tab.url,e.id);$({op:`item`,item:hT(e.id,t)})});return;case`listTools`:gT();return}}function hT(e,t){return t.ok?{kind:`tool`,id:Gw(),action:`savedTool`,input:{tool:e},ok:!0,source:`local`}:Yw(`error`,`${t.error?.code}: ${t.error?.message}`)}async function gT(){$({op:`tools`,tools:(await Hh()).map(Vh)})}async function _T(e,t){if(e===`external`){sT=Kw(sT,t).slice(-100),$({op:`event`,runId:e,event:t});return}let n=await yS(e);if(!n)return;let{sessionId:r}=n;Z.set(r,Kw(await DT(r),t)),$({op:`event`,sessionId:r,runId:e,event:t}),t.kind===`session`?await wS(r,{agent:t.agent,agentSessionId:t.agentSessionId??void 0}):t.kind===`approval`?await wS(r,{pendingApproval:{toolId:t.toolId,action:t.action,input:t.input,site:t.site}}):t.kind===`toolResult`?await wS(r,{pendingApproval:void 0}):t.kind===`usage`&&await wS(r,{usage:t.usage}),t.kind===`done`||t.kind===`error`?await vT(r):kT(r)}async function vT(e){clearTimeout(oT.get(e)),oT.delete(e),await eb(e),await wS(e,{runId:null,pendingApproval:void 0}),await Pw();let n=(await X())[e];if(n){let r=await t.tabs.get(n.currentTabId).catch(()=>null);r?.url&&await wS(e,{url:r.url,host:OS(r.url)})}await AT(e);let r=(await yC()).find(t=>t.id===e);!r||DC(r.turns,r.titledAtTurn)===null||await EC(e).catch(()=>void 0)}async function yT(e,t,n,r,i){let a=await bS(t);if(!a.ok){$({op:`event`,runId:Qw,event:{kind:`error`,code:`SESSION_LIMIT`,message:a.message}});return}if(kC(e)){let{sessionId:e}=a.session,t=await zT(a.session,await DT(e));await OT(e,{kind:`user`,id:Gw(),text:OC}),await OT(e,{kind:`context`,id:Gw(),breakdown:t});return}await bT(a.session,e,{agentSkillId:n,focus:r,liveTools:i,fastPath:!0})===`busy`&&await OT(a.session.sessionId,Yw(`error`,`RUN_IN_PROGRESS: This conversation is still running — stop it before sending another instruction.`))}async function bT(e,t,n){let{agentSkillId:r,focus:i,liveTools:a,fastPath:o}=n,{sessionId:s}=e;if(e.runId||iT.has(s))return`busy`;await OT(s,{kind:`user`,id:crypto.randomUUID(),text:t,focus:i&&NT(i)}),await wS(s,{turns:e.turns+1}),iT.add(s);try{if(o&&!r&&!i&&await xT(t,e))return await AT(s),`local`;let n=d_(t,{url:e.url,tabId:e.currentTabId,sessionId:s,agent:e.agent,agentSessionId:e.agentSessionId,agentSkillId:r,focus:i,liveTools:a,files:await IT(),recordings:await RT()});return n?(await wS(s,{runId:n}),await Pw(),`started`):(await OT(s,Yw(`error`,`EXTENSION_OFFLINE: No Browsentic daemon is attached, so only quick browser commands work. Pair the browser to do more.`)),await AT(s),`offline`)}finally{iT.delete(s)}}async function xT(e,t){try{return await iw(e,e=>{Z.set(t.sessionId,Kw(Z.get(t.sessionId)??[],e)),$({op:`event`,sessionId:t.sessionId,runId:Qw,event:e})},t.currentTabId)}catch(e){return console.warn(`[browsentic] fast path threw, escalating:`,e),!1}}async function ST(e){let t=(await X())[e]?.runId;if(t){if(!H_(t)){await CT(e,`The daemon is not connected, so there was nothing left to stop.`);return}clearTimeout(oT.get(e)),oT.set(e,setTimeout(()=>{Q(async()=>{(await X())[e]?.runId===t&&await CT(e,`Stopped. The daemon never confirmed it, so check for a run still finishing there.`)})},$w))}}async function CT(e,t){await OT(e,Yw(`error`,`CANCELLED: ${t}`)),await vT(e)}function wT(e){for(let t of cT.values())t.sessionId===e&&(t.sessionId=void 0,$({op:`mapDraft`,draft:t.draft}))}async function TT(e){let t=(await X())[e];t?.runId&&H_(t.runId),await eb(e),await jx(e),clearTimeout(oT.get(e)),oT.delete(e),await AT(e),await TS(e),Z.delete(e),iT.delete(e),wT(e),W_(e),await Pw()}async function ET(e,t){if(Object.values(await X()).find(t=>t.sessionId===e))return;let n=await vS(t.tabId);if(n?.runId){await OT(n.sessionId,Yw(`error`,`RUN_IN_PROGRESS: This tab is still running — stop it before opening another conversation here.`));return}n&&(await AT(n.sessionId),await TS(n.sessionId),Z.delete(n.sessionId),wT(n.sessionId));let r=(await yC()).find(t=>t.id===e);if(!r)return;let i=await CC(e);Z.set(e,i?.items??[Yw(`error`,`That conversation’s messages are no longer stored.`)]);let a=await xS({sessionId:e,turns:r.turns,agent:r.agent,agentSessionId:r.agentSessionId,usage:r.usage,url:r.url,title:VT(r)??t.title},t);$({op:`items`,sessionId:e,items:Z.get(e)??[]}),r.url&&/^https?:$/.test(HT(r.url))&&await kS(Bu.name,{url:r.url},a.currentTabId).catch(()=>void 0)}async function DT(e){let t=Z.get(e);if(t)return t;let n=(await CC(e))?.items??[];return Z.set(e,n),n}async function OT(e,t){Z.set(e,[...await DT(e),t]),$({op:`item`,sessionId:e,item:t}),kT(e)}function kT(e){clearTimeout(aT.get(e)),aT.set(e,setTimeout(()=>void Q(()=>AT(e)),eT))}async function AT(e){clearTimeout(aT.get(e)),aT.delete(e);let t=Z.get(e);if(!t?.length)return;let n=(await X())[e],r=n?null:(await yC()).find(t=>t.id===e),i=Date.now();await xC({id:e,turns:n?.turns??r?.turns??0,url:n?.url??r?.url,host:n?.host??r?.host,agent:n?.agent??r?.agent,agentSessionId:n?.agentSessionId??r?.agentSessionId,usage:n?.usage??r?.usage,createdAt:n?.createdAt??r?.createdAt??i,updatedAt:i},t)}function jT(){t.tabs.onRemoved.addListener(e=>{Fw(e),Q(async()=>{let{closed:t}=await ES(e);if(!t)return await Pw();t.runId&&(H_(t.runId),await OT(t.sessionId,Yw(`error`,`CANCELLED: The tab was closed, so that run is over.`))),clearTimeout(oT.get(t.sessionId)),oT.delete(t.sessionId),await jx(t.sessionId),await AT(t.sessionId),Z.delete(t.sessionId),iT.delete(t.sessionId),wT(t.sessionId),t.runId&&W_(t.sessionId),await Pw()})}),t.tabs.onReplaced.addListener((e,t)=>{Q(()=>DS(t,e))}),t.tabs.onUpdated.addListener((e,t,n)=>{t.title===void 0&&t.url===void 0||Q(async()=>{let r=await vS(e);if(!r)return;let i={};e===r.mainTabId&&n.title&&n.title!==r.title&&(i.title=n.title),e===r.currentTabId&&t.url&&(i.url=t.url,i.host=OS(t.url)),Object.keys(i).length&&await wS(r.sessionId,i)})})}async function MT(e){let t=await $v(e);t.ok||$({op:`event`,runId:Qw,event:{kind:`error`,code:t.error.code,message:t.error.message}})}var NT=e=>[e.role??e.tag,e.label].filter(Boolean).join(` · `),PT=6,FT=2e3;async function IT(){try{return(await dv()).slice(0,PT).map(e=>({id:e.id,name:e.name,mime:e.mime,size:e.size,status:e.status,summary:e.summary,digest:e.digest?.slice(0,FT)}))}catch{return[]}}var LT=8;async function RT(){try{return(await Nv()).filter(e=>e.status===`ready`).slice(0,LT).map(Hv)}catch{return[]}}async function zT(e,t){let n={user:0,assistant:0,tools:0,notices:0,chars:0};for(let e of t)e.kind===`user`?(n.user+=1,n.chars+=e.text.length):e.kind===`assistant`?(n.assistant+=1,n.chars+=e.text.length):e.kind===`tool`?n.tools+=1:e.kind===`notice`&&(n.notices+=1);let r=await dv().catch(()=>[]),i=(await Nv().catch(()=>[])).filter(e=>e.status===`ready`);return{agent:e.agent,resumes:e.agentSessionId!==void 0,usage:e.usage,turns:e.turns,tabCount:e.tabIds.length,host:e.host,messages:n,files:r.slice(0,PT).map(e=>({name:e.name,size:e.size,status:e.status})),filesOmitted:Math.max(0,r.length-PT),recordings:i.slice(0,LT).map(e=>({name:e.name,steps:e.steps})),recordingsOmitted:Math.max(0,i.length-LT),capturedAt:Date.now()}}var BT=e=>{let{tone:t,text:n}=Xw(e);return[t,n]},VT=e=>e.title??void 0;function HT(e){try{return new URL(e).protocol}catch{return``}}function $(e){for(let t of tT)UT(t,e)}function UT(e,t){try{e.postMessage(t)}catch{tT.delete(e)}}var WT=[`claude`,`codex`,`antigravity`],GT={claude:{kind:`claude`,label:`Claude Code`,vendor:`Anthropic`,bin:`claude`,install:`npm i -g @anthropic-ai/claude-code`,docs:`https://claude.com/claude-code`,models:[`claude-fable-5`,`claude-opus-5`,`claude-sonnet-5`,`claude-haiku-4-5`]},codex:{kind:`codex`,label:`Codex`,vendor:`OpenAI`,bin:`codex`,install:`npm i -g @openai/codex`,docs:`https://developers.openai.com/codex/cli`,models:[`gpt-5.6-terra`,`gpt-5.1-codex-max`,`gpt-5.1-codex`,`gpt-5.1-codex-mini`]},antigravity:{kind:`antigravity`,label:`Antigravity`,vendor:`Google`,bin:`agy`,install:`https://antigravity.google/docs/cli/install`,docs:`https://antigravity.google/docs/cli`,models:[`gemini-3-pro`,`gemini-3-flash`]}};WT.map(e=>GT[e]);function KT(e){return typeof e==`string`&&WT.includes(e)}var qT=`open-side-panel`,JT=e(()=>{zm(),t.runtime.onMessage.addListener((e,t,n)=>{if(c(e)){if(e.op===`describe`){n(o(Vf()));return}if(e.op===`invoke`&&typeof e.action==`string`)return kS(e.action,e.input).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`analyzeFile`&&typeof e.fileId==`string`){hv(e.fileId),n(o(!0));return}if(e.op===`saveSkill`&&typeof e.skillId==`string`){dC(e.skillId),n(o(!0));return}if(e.op===`removeSkill`&&typeof e.skillId==`string`){fC(e.skillId),n(o(!0));return}if(e.op===`nameSession`&&typeof e.sessionId==`string`){EC(e.sessionId),n(o(!0));return}if(e.op===`recordEvents`&&Array.isArray(e.events)){ty(t.tab?.id,e.events),n(o(!0));return}if(e.op===`recordingState`)return Qv(t.tab?.id).then(e=>n(o(e))).catch(()=>n(o({recording:!1,captureValues:!1}))),!0;if(e.op===`analyzeRecording`&&typeof e.recordingId==`string`){Rv(e.recordingId),n(o(!0));return}if(e.op===`monitorSample`&&typeof e.monitorId==`string`){Kb(t.tab?.id,e.monitorId,e.sample),n(o(!0));return}if(e.op===`monitorState`)return $b(t.tab?.id).then(n).catch(()=>n(o({monitors:[]}))),!0;if(e.op===`listSkills`)return L_(e.refresh===!0).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`agentState`)return j_(e.refresh===!0).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`setAgent`&&KT(e.agent))return M_(e.agent).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`setAgentModel`&&KT(e.agent))return N_(e.agent,typeof e.model==`string`&&e.model.trim()?e.model:null).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`grantAgent`&&KT(e.agent))return P_(e.agent).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`guardrails`)return z_().then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`setGuardrail`&&typeof e.setting==`string`)return B_(e.setting,e.value).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`pair`&&typeof e.token==`string`)return K_(e.token).then(e=>n(e.ok?o(!0):s(`PAIRING_FAILED`,e.error??`Pairing failed`))).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`panelOpened`){_w(!1),n(o(!0));return}if(e.op===`disconnect`)return q_().then(()=>n(o(!0))).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;n(s(`INVALID_REQUEST`,`Expected {op:"describe"|"invoke"|"analyzeFile"|"saveSkill"|"removeSkill"|"nameSession"|"recordEvents"|"recordingState"|"analyzeRecording"|"monitorSample"|"monitorState"|"listSkills"|"agentState"|"setAgent"|"setAgentModel"|"grantAgent"|"guardrails"|"setGuardrail"|"pair"|"panelOpened"|"disconnect"}`))}}),t.runtime.onInstalled.addListener(()=>{t.tabs.query({}).then(e=>{for(let t of e)t.id!=null&&!t.discarded&&up(t.id)})});let e=t.contextMenus.removeAll().then(()=>t.contextMenus.create({id:qT,title:`Open Browsentic`,contexts:[`all`]})),n=!1;fT(r=>{n=r,e.then(()=>t.contextMenus.update(qT,{title:r?`Close Browsentic`:`Open Browsentic`})),r||Sw()}),t.contextMenus.onClicked.addListener((e,t)=>{if(!(e.menuItemId!==qT||t?.windowId==null)){if(n){pT();return}hw(t.windowId)}}),nb(),Qf(),ig(),ry(),rx(),Mx(),dT(),jT(),Aw(),Db(),xw(),u_(()=>{mC(),zv()}),G_(),t.runtime.onStartup.addListener(()=>void G_()),t.alarms.create(Zg,{periodInMinutes:1}),t.alarms.onAlarm.addListener(e=>{e.name===`browsentic/reconnect`&&G_()})}),YT={debug:(...e)=>([...e],void 0),log:(...e)=>([...e],void 0),warn:(...e)=>([...e],void 0),error:(...e)=>([...e],void 0)},XT;try{XT=JT.main(),XT instanceof Promise&&console.warn(`The background's main() function return a promise, but it must be synchronous`)}catch(e){throw YT.error(`The background crashed on startup!`),e}return XT})();
183
+ `?`Enter`:t);e.dispatchEvent(new KeyboardEvent(`keydown`,n))&&(e.dispatchEvent(new KeyboardEvent(`keypress`,n)),Lf(e,t)),e.dispatchEvent(new KeyboardEvent(`keyup`,n))}var zf=F({name:`page.waitForElement`,description:`Wait until an element reaches a state: attached, visible, hidden, or detached.`,input:N({target:z.describe(`Element to wait for`),state:P([`attached`,`visible`,`hidden`,`detached`]).default(`visible`).describe(`State to wait for: present in the DOM, present and visible, invisible or absent, or absent`),timeoutMs:j().int().positive().max(3e4).default(5e3).describe(`Give up after this many milliseconds`)}),async execute({target:e,state:t,timeoutMs:n}){let r=()=>{try{return B(e,{includeHidden:!0})}catch(e){if(e instanceof I&&e.code===`INVALID_TARGET`)throw e;return null}},i=e=>({attached:!!e,visible:!!e&&sc(e),hidden:!e||!sc(e),detached:!e})[t],a=performance.now(),o=r();return i(o)?{state:t,elapsedMs:0,element:o?H(o):void 0}:(await new Promise((e,a)=>{let s=()=>{o=r(),i(o)&&(d(),e())},c=new MutationObserver(s);c.observe(document.documentElement,{subtree:!0,childList:!0,attributes:!0});let l=setInterval(s,250),u=setTimeout(()=>{d(),a(new I(`Timed out after ${n}ms waiting for element to be ${t}`,`TIMEOUT`))},n),d=()=>{c.disconnect(),clearInterval(l),clearTimeout(u)}}),{state:t,elapsedMs:Math.round(performance.now()-a),element:o?H(o):void 0})}}),Bf=new Map([vu,Yd,Lc,Ef,El,sf,ju,cl,du,Cl,Nf,nf,rf,yl,td,nd,Cf,zf,Mu,qd,Iu,Pc,Al,uu,Cd,hc,Hs,cf,vd,yd,bf,lf,Lu,Nc,xf,yf,Tf,Sf,Au,Zd,Bu,Vu,wf,fu,Rc,Jd,Pu,pc,Fc,Nu,Fu,bd].map(e=>[e.name,e]));function Vf(){return[...Bf.values()].map(({name:e,description:t,input:n})=>({name:e,description:t,inputSchema:ea(n,{io:`input`})}))}var Hf=`data-browsentic-frame`,Uf=`browsentic/frameFocus`,Wf=null;async function Gf(){return Wf||(Wf=(await t.storage.session.get(`browsentic/frameFocus`))[`browsentic/frameFocus`]??{},Wf)}async function Kf(e){Wf=e,await t.storage.session.set({[Uf]:e})}async function qf(e){return(await Gf())[String(e)]??[]}async function Jf(e){return(await qf(e)).at(-1)?.frameId??0}async function Yf(e,t){return(await qf(e)).at(-1)?.url??t}async function Xf(e,t){let{[String(e)]:n,...r}=await Gf();await Kf(t.length?{...r,[String(e)]:t}:r)}function Zf(e){return Xf(e,[])}function Qf(){t.tabs.onRemoved.addListener(e=>void Zf(e)),t.tabs.onUpdated.addListener((e,t)=>{t.status===`loading`&&Zf(e)})}async function $f(e,n,r){try{return await t.tabs.sendMessage(e,{channel:`browsentic/frame`,...r},{frameId:n})??null}catch{return null}}var ep=(e,t)=>$f(e,t,{op:`describe`}),tp=(e,t,n)=>$f(e,t,{op:`mark`,token:n}),np=(e,t)=>$f(e,t,{op:`unmark`}),rp=(e,t,n)=>$f(e,t,{op:`locate`,frameId:n});async function ip(e){let t=await qf(e),n={x:0,y:0},r=0;for(let{frameId:i}of t){let t=await rp(e,r,i);if(!t)return null;n={x:n.x+t.x,y:n.y+t.y},r=i}return n}var ap=`the frame in focus is gone or blocks scripts — call page.switchFrame with no arguments to return to the top document`,op=`Receiving end does not exist`,sp=new Set([`page.getPageInfo`,`page.extractText`,`page.waitForElement`,`page.navigate`]);async function U(e,t,...[n]){return cp(e,await Jf(e),t,n)}async function cp(e,r,i,...[a]){let o=typeof i==`string`?i:i.name,c=async()=>await t.tabs.sendMessage(e,{channel:n,action:o,input:a},{frameId:r}),l=e=>s(`TAB_UNREACHABLE`,r===0?`${e} — the page may not allow content scripts`:`${e} — ${ap}`);try{return await c()}catch(t){let n=t instanceof Error?t.message:String(t);if(!n.includes(op)||!await up(e,r))return l(n);if(!sp.has(o))return s(`TAB_UNREACHABLE`,`This tab had no content script; one has just been injected and the tab is reachable now. Take a fresh page.getPageInfo snapshot — the page may have changed — then retry the action.`);try{return await c()}catch(e){return s(`TAB_UNREACHABLE`,`${e instanceof Error?e.message:String(e)} — the content script was injected but the page still did not answer`)}}}var lp=5e3;async function up(e,n=0){let r=(t.runtime.getManifest().content_scripts??[]).flatMap(e=>e.js??[]);if(!r.length)return!1;try{return await dp(t.scripting.executeScript({target:{tabId:e,frameIds:[n]},files:r,injectImmediately:!0})),!0}catch{return!1}}function dp(e){return Promise.race([e,new Promise((e,t)=>setTimeout(()=>t(Error(`injection timed out`)),lp))])}var fp=`browsentic.`;`${fp}`;var pp=`${fp}startRecording`,mp=`${fp}stopRecording`;`${fp}`,`${fp}`;var hp=`browsentic/record`,gp=2e3,_p=15*6e4,vp=13*6e4,yp=/pass|ssn|card|cvv|cvc|otp|secret|token|pin\b/i,bp=/cc-|new-password|current-password|one-time-code/i;function xp(e){let t=(e.type??``).toLowerCase();return t===`password`||t===`hidden`||bp.test(e.autocomplete??``)||yp.test(e.name??``)||yp.test(e.id??``)?!0:Sp(e.value??``)}function Sp(e){let t=e.replace(/[\s-]/g,``);if(!/^\d{13,19}$/.test(t))return!1;let n=0,r=!1;for(let e=t.length-1;e>=0;--e){let i=t.charCodeAt(e)-48;r&&(i*=2,i>9&&(i-=9)),n+=i,r=!r}return n%10==0}function Cp(e){try{return new URL(e).hostname.toLowerCase()}catch{return``}}function wp(e){try{return new URL(e).origin}catch{return``}}var Tp={head:0,tail:0},Ep=[[`pass`,`word`],[`pass`,`wd`],[`pass`,`phrase`],[`pass`,`code`],[`pwd`],[`otp`],[`one`,`time`,`code`]],Dp=[[`secret`],[`token`],[`api`,`key`],[`access`,`key`],[`access`,`token`],[`secret`,`key`],[`client`,`secret`],[`refresh`,`token`],[`auth`,`token`],[`authorization`],[`bearer`],[`credential`],[`credentials`],[`signing`,`key`],[`private`,`key`],[`connection`,`string`]],Op=[[`cookie`],[`session`,`id`],[`session`,`key`],[`session`,`token`],[`csrf`,`token`],[`xsrf`,`token`]],kp=e=>e.map(e=>e.join(String.raw`[_\-\s]?`)).join(`|`),Ap=kp(Ep),jp=kp(Dp),Mp=kp(Op),Np=[[`password`,Ep],[`token`,Dp],[`cookie`,Op]];function Pp(e){let t=e.toLowerCase().replace(/[^a-z0-9]/g,``);if(!t)return null;let n=t.endsWith(`s`)?[t,t.slice(0,-1)]:[t];for(let[e,t]of Np)if(t.some(e=>n.some(t=>t.endsWith(e.join(``)))))return e;return null}[...Ep,...Dp,...Op].map(e=>e.join(`_`));var Fp=String.raw`(?:Bearer\s+|Basic\s+|Token\s+)?(?:"([^"\r\n]{4,400})"|'([^'\r\n]{4,400})'|([^\s,;&"'<>{}\[\]]{4,400}))`,Ip=e=>new RegExp(String.raw`(?<![A-Za-z0-9])(?:${e})["']?\s*[:=]\s*${Fp}`,`gi`),Lp=String.raw`(?:"([^"\r\n]{4,400})"|'([^'\r\n]{4,400})'|([^\s"'<>]{3,399}[^\s"'<>.,;:!?]))`,Rp=e=>new RegExp(String.raw`(?<![A-Za-z0-9])(?:${e})\s+(?:is|are|was|will\s+be)\s*:?\s+${Lp}`,`gi`),zp=/\d|[!@#$%^&*()_+=\[\]{}|\\<>~/&]|[a-z][A-Z]/;function Bp(e){return e.length>=6&&Hp(e)&&zp.test(e)}var Vp=/^(?:null|nil|none|true|false|undefined|n\/?a|empty|blank|test|demo|example|sample|changeme|hidden|redacted|your[-_\s].*|my[-_\s].*|x{3,}|\*+|•+|\.{3,}|…+|-+|_+|\[[^\]]*\]|<[^>]*>|\{\{.*\}\}|\$\{.*\})$/i;function Hp(e){return Vp.test(e)||/^(.)\1*$/.test(e)?!1:!e.includes(`…`)}var Up=[{id:`private-key`,kind:`private-key`,guard:`-----begin`,pattern:/-----BEGIN(?:[A-Z ]{0,32})PRIVATE KEY-----[A-Za-z0-9+/=\s]{0,8000}-----END(?:[A-Z ]{0,32})PRIVATE KEY-----/g},{id:`jwt`,kind:`jwt`,guard:`eyj`,pattern:/\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}/g},{id:`anthropic-key`,kind:`api-key`,guard:`sk-ant-`,pattern:/\bsk-ant-[A-Za-z0-9_-]{16,}/g,reveal:{head:7,tail:0}},{id:`openai-key`,kind:`api-key`,guard:`sk-`,pattern:/\bsk-(?:proj-|svcacct-|admin-)?[A-Za-z0-9_-]{20,}/g,reveal:{head:3,tail:0}},{id:`google-key`,kind:`api-key`,guard:`aiza`,pattern:/\bAIza[0-9A-Za-z_-]{35}\b/g,reveal:{head:4,tail:0}},{id:`aws-access-key`,kind:`api-key`,pattern:/\b(?:AKIA|ASIA|AIDA|AROA|AGPA|ANPA)[0-9A-Z]{16}\b/g,reveal:{head:4,tail:0}},{id:`github-pat`,kind:`token`,guard:`github_pat_`,pattern:/\bgithub_pat_[A-Za-z0-9_]{40,}/g,reveal:{head:11,tail:0}},{id:`github-token`,kind:`token`,guard:`gh`,pattern:/\bgh[pousr]_[A-Za-z0-9]{30,}/g,reveal:{head:4,tail:0}},{id:`slack-token`,kind:`token`,guard:`xox`,pattern:/\bxox[abposr]-[A-Za-z0-9-]{10,}/g,reveal:{head:4,tail:0}},{id:`stripe-key`,kind:`api-key`,guard:`k_`,pattern:/\b[rs]k_(?:live|test)_[A-Za-z0-9]{16,}/g,reveal:{head:8,tail:0}},{id:`npm-token`,kind:`token`,guard:`npm_`,pattern:/\bnpm_[A-Za-z0-9]{36}\b/g,reveal:{head:4,tail:0}},{id:`gitlab-token`,kind:`token`,guard:`glpat-`,pattern:/\bglpat-[A-Za-z0-9_-]{20,}/g,reveal:{head:6,tail:0}},{id:`sendgrid-key`,kind:`api-key`,guard:`sg.`,pattern:/\bSG\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}/g,reveal:{head:3,tail:0}},{id:`basic-auth`,kind:`password`,guard:`@`,pattern:/\bhttps?:\/\/[^\s/:@]{1,64}:([^\s/@]{3,128})@/g},{id:`cookie-header`,kind:`cookie`,guard:`cookie`,pattern:/(?:^|\n)[ \t]*(?:set-)?cookie[ \t]*:[ \t]*([^\r\n]{4,4000})/gi},{id:`labelled-password`,kind:`password`,pattern:Ip(Ap),validate:Hp},{id:`labelled-token`,kind:`token`,pattern:Ip(jp),validate:Hp},{id:`labelled-cookie`,kind:`cookie`,pattern:Ip(Mp),validate:Hp},{id:`prose-password`,kind:`password`,pattern:Rp(Ap),validate:Bp},{id:`prose-token`,kind:`token`,pattern:Rp(jp),validate:Bp},{id:`card`,kind:`card`,pattern:/\b\d(?:[ -]?\d){12,18}\b/g,reveal:{head:0,tail:4},validate:Sp}],Wp=/(?<![A-Za-z0-9+/_=-])[A-Za-z0-9+/_-]{32,4096}={0,2}(?![A-Za-z0-9+/_-])/g,Gp=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Kp=4.3,qp=.5,Jp=/\bdata:[^\s;,]{0,80};base64,[A-Za-z0-9+/=]+/g;function Yp(e,t=[]){if(!e)return[];let n=[...t,...tm(e,Jp)].sort((e,t)=>e.start-t.start),r=e.toLowerCase(),i=[],a=e=>{nm(n,e)||(n.push(e),n.sort((e,t)=>e.start-t.start),i.push(e))};for(let t of Up)if(!(t.guard&&!r.includes(t.guard)))for(let n of e.matchAll(t.pattern)){let e=Xp(n);e&&(t.validate&&!t.validate(e.value)||a({...e,kind:t.kind,shape:t.id,reveal:t.reveal??Tp}))}for(let t of e.matchAll(Wp)){let e=t[0];Zp(e)&&a({start:t.index,end:t.index+e.length,value:e,kind:`secret`,shape:`high-entropy`,reveal:Tp})}return i.sort((e,t)=>e.start-t.start)}function Xp(e){if(e.index===void 0)return null;let t=e.slice(1).find(e=>e!==void 0);if(t===void 0)return{start:e.index,end:e.index+e[0].length,value:e[0]};if(!t)return null;let n=e[0].lastIndexOf(t);return n<0?null:{start:e.index+n,end:e.index+n+t.length,value:t}}function Zp(e){return e.length<32||Gp.test(e)||/^[0-9a-f]+$/i.test(e)||!/[a-z]/.test(e)||!/[A-Z]/.test(e)||!/[0-9]/.test(e)?!1:em(e)>=Kp&&Qp(e)>=qp}function Qp(e){let t=e.replace(/[^A-Za-z]/g,``);if(t.length<2)return 0;let n=0;for(let e=1;e<t.length;e+=1)$p(t[e])!==$p(t[e-1])&&(n+=1);return n/(t.length-1)}var $p=e=>e===e.toUpperCase();function em(e){let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=0;for(let r of t.values()){let t=r/e.length;n-=t*Math.log2(t)}return n}function tm(e,t){return[...e.matchAll(t)].map(e=>({start:e.index,end:e.index+e[0].length}))}function nm(e,t){return e.some(e=>t.start<e.end&&e.start<t.end)}var rm=/⟦([a-z-]+):([0-9a-z]+)(?:@([A-Za-z0-9._:\[\]-]{1,255}))?#([0-9a-f]{6,32})⟧/g;function im(e,t){let n=e.origin?`@${e.origin}`:``;return`⟦${e.kind}:${e.id}${n}#${t}⟧`}function am(e,t){return e.includes(`⟦`)?[...e.matchAll(rm)].map(e=>({kind:e[1],id:e[2],origin:e[3],tag:e[4],text:e[0]})).filter(e=>!t||e.tag===t):[]}function om(e,t){if(!e||e.length<4)return{value:e,found:[]};let n=fm(e,t.tag),r=t.tag?pm(e,n):e,i=Yp(r,n);if(!i.length)return{value:r,found:[]};let a=[],o=``,s=0;for(let e of i){let n=t.mint(e.value,e.kind,e.shape);a.push({kind:e.kind,shape:e.shape,handle:n}),o+=r.slice(s,e.start)+dm(e.value,e.reveal,n),s=e.end}return{value:o+r.slice(s),found:a}}var sm=new Set([`selector`]),cm=4;function lm(e,t){let n=[],r=(e,r)=>{let i=Yp(e).find(t=>t.start===0&&t.end===e.length),a=i?{kind:i.kind,shape:i.shape,reveal:i.reveal}:{kind:r,shape:`keyed`,reveal:Tp},o=t.mint(e,a.kind,a.shape);return n.push({kind:a.kind,shape:a.shape,handle:o}),dm(e,a.reveal,o)},i=(e,a,o)=>{if(typeof e==`string`){if(e.startsWith(`data:`))return e;if(o&&e.length>=cm&&Hp(e)&&!am(e).length)return r(e,o);let i=om(e,t);return n.push(...i.found),i.value}if(a>=mm||typeof e!=`object`||!e)return e;if(Array.isArray(e))return e.map(e=>i(e,a+1,o));let s={};for(let[t,n]of Object.entries(e))s[t]=sm.has(t)?n:i(n,a+1,Pp(t));return s};return{value:i(e,0,null),found:n}}function um(e,t,n){let r=[],i=[];return{text:e.replace(rm,(e,a,o,s,c)=>{let l={kind:a,id:o,origin:s,tag:c,text:e};if(c!==t)return i.push(l),e;let u=n(l);return u===null?(i.push(l),e):(r.push(l),u)}),released:r,unresolved:i}}function dm(e,t,n){let r=Math.max(0,e.length-4),i=e.slice(0,Math.min(t.head,r)),a=t.tail&&e.length-t.tail>i.length?e.slice(-t.tail):``;return`${i}${i?`…`:``}${n}${a?`…`:``}${a}`}function fm(e,t){return e.includes(`⟦`)?[...e.matchAll(rm)].filter(e=>!t||e[4]===t).map(e=>({start:e.index,end:e.index+e[0].length})):[]}function pm(e,t){if(!e.includes(`⟦`)&&!e.includes(`⟧`))return e;let n=e=>t.some(t=>e>=t.start&&e<t.end),r=``;for(let t=0;t<e.length;t+=1){let i=e[t];n(t)?r+=i:i===`⟦`?r+=`⟨`:i===`⟧`?r+=`⟩`:r+=i}return r}var mm=12,hm={"page.fillInput":[`value`],"page.typeText":[`text`]},gm=`A sealed secret can only be released into page.fillInput “value” or page.typeText “text”. Browsentic swaps the placeholder for the real value at the moment it reaches the page, so the secret is never yours to move: pass the placeholder through unchanged and let the field it belongs in do it.`,_m=`That sealed secret is no longer held — it expired, or it was read in an earlier browser session. Read the value from the page again, or ask the user for it.`;function vm(e){return hm[e]??[]}function ym(e,t,n,r){let i=vm(e),a=[],o=[],s=[];if(!t||typeof t!=`object`||Array.isArray(t))return{input:t,released:a,refused:bm(t,o),unresolved:s};let c={};for(let[e,l]of Object.entries(t)){if(i.includes(e)&&typeof l==`string`){let t=um(l,n,r);a.push(...t.released),s.push(...t.unresolved),c[e]=t.text;continue}bm(l,o),c[e]=l}return{input:c,released:a,refused:o,unresolved:s}}function bm(e,t,n=0){if(typeof e==`string`)t.push(...am(e));else if(n<12&&e&&typeof e==`object`)for(let r of Object.values(e))bm(r,t,n+1);return t}var xm=`browsentic/secrets`,Sm=120*6e4,Cm=Promise.resolve();function wm(e){let t=Cm.then(e,e);return Cm=t.catch(()=>void 0),t}function Tm(e,t){return wm(async()=>{let n=await Dm(),r=Date.now(),i=n.entries.filter(e=>r-e.at<Sm),a=[],o=lm(e,{mint:(e,o,s)=>{let c=[...i,...a].find(n=>n.value===e&&n.origin===t);if(c)return c.at=r,im(c,n.tag);let l={id:jm(),value:e,kind:o,shape:s,origin:t,at:r};return a.push(l),im(l,n.tag)},tag:n.tag});return(a.length||i.length!==n.entries.length)&&await Om({tag:n.tag,entries:[...i,...a].slice(-64)}),o})}function Em(e,t){return wm(async()=>{let n=await Dm(),r=Date.now(),i=[],a=ym(e,t,n.tag,e=>{let t=n.entries.find(t=>t.id===e.id);return!t||r-t.at>=Sm?null:(t.at=r,i.push(t),t.value)});return i.length&&await Om(n),a})}async function Dm(){let e=(await t.storage.session.get(xm).catch(()=>({})))[xm];if(e?.tag&&Array.isArray(e.entries))return{tag:e.tag,entries:e.entries};let n={tag:Am(),entries:[]};return await Om(n),n}function Om(e){return t.storage.session.set({[xm]:e}).catch(()=>void 0)}var km=e=>[...crypto.getRandomValues(new Uint8Array(e))].map(e=>e.toString(16).padStart(2,`0`)).join(``),Am=()=>km(8),jm=()=>km(4),Mm=[{id:`turnstile`,label:`Cloudflare Turnstile`,kind:`checkbox`,hostMarkers:[`.cf-turnstile`,`#cf-turnstile`,`#challenge-stage`,`#cf-challenge-running`,`#challenge-running`],frame:`challenges.cloudflare.com`,checkbox:`input[type="checkbox"]`,solvedInPage:`!!document.querySelector('input[name="cf-turnstile-response"]')?.value`},{id:`recaptcha-v2`,label:`reCAPTCHA v2`,kind:`checkbox`,hostMarkers:[`.g-recaptcha`,`#g-recaptcha`,`iframe[src*="recaptcha/api2/anchor"]`,`iframe[src*="recaptcha/enterprise/anchor"]`],frame:`recaptcha/api2/anchor`,challengeFrame:`recaptcha/api2/bframe`,checkbox:`#recaptcha-anchor`,solvedInFrame:`!!document.querySelector('#recaptcha-anchor.recaptcha-checkbox-checked')`,solvedInPage:`!!document.querySelector('textarea#g-recaptcha-response')?.value`},{id:`hcaptcha`,label:`hCaptcha`,kind:`checkbox`,hostMarkers:[`.h-captcha`,`[data-hcaptcha-widget-id]`,`iframe[src*="hcaptcha.com/captcha"]`],frame:`frame=checkbox`,challengeFrame:`frame=challenge`,checkbox:`#checkbox`,solvedInPage:`!!document.querySelector('textarea[name="h-captcha-response"]')?.value`},{id:`geetest`,label:`GeeTest`,kind:`checkbox`,hostMarkers:[`.geetest_holder`,`.geetest_radar_tip`,`.geetest_btn`],checkbox:`.geetest_radar_tip`,solvedInPage:`!!document.querySelector('.geetest_success_radar_tip')`},{id:`arkose`,label:`Arkose FunCaptcha`,kind:`interactive`,hostMarkers:[`#funcaptcha`,`#arkose`,`[data-pkey]`,`iframe[src*="arkoselabs.com"]`],frame:`arkoselabs.com`},{id:`aws-waf`,label:`AWS WAF Captcha`,kind:`interactive`,hostMarkers:[`#captcha-container`,`script[src*="captcha.awswaf.com"]`,`iframe[src*="awswaf.com"]`],frame:`awswaf.com`},{id:`recaptcha-v3`,label:`reCAPTCHA v3`,kind:`invisible`,hostMarkers:[`script[src*="recaptcha/api.js?render="]`,`script[src*="recaptcha/enterprise.js?render="]`],solvedInPage:`!!document.querySelector('textarea#g-recaptcha-response')?.value`}],Nm=t.debugger,Pm=`1.3`,Fm=250,Im=150,Lm=4,W=e=>new Promise(t=>setTimeout(t,e)),Rm=new Set;function zm(){Nm.onEvent.addListener((e,t,n)=>{for(let r of Rm)r(e,t,n)})}function Bm(e){return Rm.add(e),()=>Rm.delete(e)}async function Vm(e){try{return await Nm.attach({tabId:e},Pm),{ok:!0}}catch(e){return{ok:!1,message:Jm(e)}}}async function Hm(e){let t={tabId:e};await G(t,`Target.setAutoAttach`,Km).catch(()=>{}),await Nm.detach(t).catch(()=>{})}function Um(e){Nm.onDetach.addListener((t,n)=>{t.tabId!=null&&e(t.tabId,n)})}function G(e,t,n){return Nm.sendCommand(e,t,n)}async function Wm(e,t,n){let r={tabId:e};try{await Nm.attach(r,Pm)}catch(e){return s(`DEBUGGER_UNAVAILABLE`,Jm(e))}try{return await W(Fm),await n(r)}catch(e){return s(`ACTION_FAILED`,e instanceof Error?e.message:String(e))}finally{await G(r,`Target.setAutoAttach`,Km).catch(()=>{}),await Nm.detach(r).catch(()=>{})}}var Gm={autoAttach:!0,flatten:!0,waitForDebuggerOnStart:!1,filter:[{type:`iframe`}]},Km={autoAttach:!1,flatten:!0,waitForDebuggerOnStart:!1};async function qm(e){let t=[],n=Bm((e,n,r)=>{if(n!==`Target.attachedToTarget`)return;let i=r;i?.targetInfo?.type===`iframe`&&t.push({sessionId:i.sessionId,url:i.targetInfo.url,parent:e.sessionId})});try{let n=[e];for(let r=0;r<Lm&&n.length;r+=1){let r=t.length;for(let e of n)await G(e,`Target.setAutoAttach`,Gm).catch(()=>{});await W(Im),n=t.slice(r).map(({sessionId:t})=>({tabId:e.tabId,sessionId:t}))}}finally{n()}return t}function Jm(e){let t=e instanceof Error?e.message:String(e);return/already attached|another debugger/i.test(t)?`${t} — close DevTools for this tab, then retry.`:`${t} — Chrome’s debugger could not attach to this tab.`}var Ym={alt:1,ctrl:2,meta:4,shift:8},Xm={left:1,right:2,middle:4},Zm=12,Qm=`A trusted click needs Chrome’s debugger, which Firefox does not expose — use page.clickElement instead.`,$m=`A trusted drag needs Chrome’s debugger, which Firefox does not expose — drop "trusted" to drag with synthetic events instead.`;function eh(e,t){return Wm(e,Qm,async n=>{let r=await U(e,Ef.name,t);if(!r.ok)return r;let i=await ip(e);if(!i)return s(`TAB_UNREACHABLE`,`The click could not be placed — ${ap}`);let a=r.data;return await rh(n,{...a,point:nh(a.point,i),from:nh(a.from,i)}),o({...r.data,trusted:!0})})}function th(e,t){return Wm(e,$m,async n=>{let r=await U(e,cl.name,t);if(!r.ok)return r;let i=await ip(e);if(!i)return s(`TAB_UNREACHABLE`,`The drag could not be placed — ${ap}`);let a=r.data;return await ih(n,{...a,approach:nh(a.approach,i),grip:nh(a.grip,i),drop:nh(a.drop,i)}),o({...r.data,trusted:!0})})}var nh=(e,t)=>({x:e.x+t.x,y:e.y+t.y});async function rh(e,t){let{point:n,from:r,button:i,clickCount:a,modifiers:o,moveSteps:s,hoverMs:c,holdMs:l}=t,u={modifiers:o.reduce((e,t)=>e|(Ym[t]??0),0),pointerType:`mouse`},d=t=>G(e,`Input.dispatchMouseEvent`,t),f=e=>d({...u,...e,type:`mouseMoved`,button:`none`,buttons:0});await f(r);for(let e of Yc(r,n,s))await W(Zm),await f(e);await W(c);for(let e=1;e<=a;e+=1)await d({...u,...n,type:`mousePressed`,button:i,buttons:Xm[i],clickCount:e}),await W(l),await d({...u,...n,type:`mouseReleased`,button:i,buttons:0,clickCount:e})}async function ih(e,t){let{approach:n,grip:r,drop:i,steps:a,holdMs:o,settleMs:s}=t,c={modifiers:0,pointerType:`mouse`},l=t=>G(e,`Input.dispatchMouseEvent`,t),u=(e,t)=>l({...c,...e,type:`mouseMoved`,button:t?`left`:`none`,buttons:t});for(let e of Yc(n,r,4))await W(Zm),await u(e,0);await l({...c,...r,type:`mousePressed`,button:`left`,buttons:1,clickCount:1}),await W(o);for(let e of Yc(r,i,a))await W(Zm),await u(e,1);await W(s),await l({...c,...i,type:`mouseReleased`,button:`left`,buttons:0,clickCount:1})}var ah=`Reading a captcha needs Chrome’s debugger, which Firefox does not expose — solve the captcha in the page yourself.`,oh=500,sh={button:`left`,clickCount:1,modifiers:[],moveSteps:14,hoverMs:120,holdMs:70};function ch(e){return Wm(e,ah,async e=>{let t=await fh(e);return o(t?dh(t):{found:!1})})}function lh(e,t){let n=sf.input.safeParse(t??{});if(!n.success)return Promise.resolve(s(`INVALID_INPUT`,x(n.error)));let{waitMs:r,timeoutMs:i}=n.data;return Wm(e,ah,async e=>{let t=Date.now()+i,n=await fh(e);return n?!n.point||n.state!==`idle`?o({...dh(n),clicked:!1}):(await rh(e,uh(n.point)),o({...dh(await hh(e,n,Math.min(r,t-Date.now()))),clicked:!0})):s(`CAPTCHA_NOT_FOUND`,`No captcha widget on this page. If the page is still blocked, take a fresh page.getPageInfo — the block may be something else.`)})}function uh(e){return{point:e,from:{x:Math.max(e.x-140,0),y:Math.max(e.y-90,0)},...sh}}function dh(e){return{found:!0,vendor:e.vendor.id,label:e.vendor.label,kind:e.vendor.kind,state:e.state,solved:e.state===`solved`,hasToken:e.hasToken,bounds:e.bounds,point:e.point,note:e.note}}async function fh(e){await Sh(e);for(let t of Mm)if(await ph(e,t))return mh(e,t);return null}async function ph(e,t){for(let n of t.hostMarkers)if((await Ch(e,n)).length)return!0;return!1}async function mh(e,t){let n=t.frame?await qm(e):[],r=t.solvedInPage?await Th(e,t.solvedInPage):!1;if(r||await _h(e,t,n))return{vendor:t,frames:n,state:`solved`,hasToken:r};if(t.kind===`invisible`)return{vendor:t,frames:n,state:`invisible`,hasToken:r,note:`${t.label} scores in the background — there is nothing to click.`};if(t.challengeFrame&&await Th(e,yh(t.challengeFrame)))return{vendor:t,frames:n,state:`needsHuman`,hasToken:r,bounds:await vh(e,t.challengeFrame),note:`${t.label} has escalated to a challenge only a person can answer.`};if(t.kind===`interactive`)return{vendor:t,frames:n,state:`needsHuman`,hasToken:r,bounds:t.frame?await vh(e,t.frame):void 0,note:`${t.label} asks for a puzzle rather than a checkbox.`};let i=await gh(e,t,n);return{vendor:t,frames:n,state:i.point?`idle`:`needsHuman`,hasToken:r,bounds:i.bounds,point:i.point,note:i.note}}async function hh(e,t,n){let{vendor:r,frames:i}=t,a=Date.now()+Math.max(0,n);for(;Date.now()<a;){await W(oh);let n=r.solvedInPage?await Th(e,r.solvedInPage):!1;if(n||await _h(e,r,i))return{...t,state:`solved`,hasToken:n};if(r.challengeFrame&&await Th(e,yh(r.challengeFrame)))return{...t,state:`needsHuman`,hasToken:n,bounds:await vh(e,r.challengeFrame)??t.bounds,note:`${r.label} answered the checkbox with a challenge only a person can answer.`}}return{...t,state:`pending`,note:`${r.label} accepted the click but had not settled within the wait — call page.findCaptcha again to re-check.`}}async function gh(e,t,n){if(!t.checkbox)return{note:`${t.label} exposes no checkbox to click.`};if(!t.frame){let[n]=await Ch(e,t.checkbox),r=n?await wh(e,n):null;return r?{bounds:r,point:bh(r)}:{note:`${t.label}’s checkbox is in the page but has no box on screen — scroll it into view, then retry.`}}let[r]=await Ch(e,`iframe[src*="${t.frame}"]`),i=r?await wh(e,r):null;if(!i)return{note:`${t.label}’s widget iframe is not painted — scroll it into view, then retry.`};let a=n.find(e=>e.url.includes(t.frame));if(!a)return{bounds:i,note:`Chrome did not expose ${t.label}’s widget frame, so its checkbox cannot be located.`};let o={tabId:e.tabId,sessionId:a.sessionId};await Sh(o).catch(()=>{});let[s]=await Ch(o,t.checkbox),c=s?await wh(o,s):null;if(!c)return{bounds:i,note:`${t.label}’s widget is open but its checkbox could not be located inside the frame.`};let l={x:Math.round(i.x+c.x+c.width/2),y:Math.round(i.y+c.y+c.height/2)};return xh(i,l)?{bounds:i,point:l}:{bounds:i,note:`${t.label}’s checkbox resolved outside its own frame — refusing to click a guessed point.`}}async function _h(e,t,n){if(!t.solvedInFrame||!t.frame)return!1;let r=n.find(e=>e.url.includes(t.frame));return r?Th({tabId:e.tabId,sessionId:r.sessionId},t.solvedInFrame):!1}async function vh(e,t){let[n]=await Ch(e,`iframe[src*="${t}"]`);return(n?await wh(e,n):null)??void 0}var yh=e=>`[...document.querySelectorAll('iframe')].some((f) => f.src.includes(${JSON.stringify(e)}) && f.getBoundingClientRect().height > 40 && getComputedStyle(f).visibility !== 'hidden' && getComputedStyle(f.parentElement || f).visibility !== 'hidden')`,bh=e=>({x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}),xh=(e,t)=>t.x>=e.x&&t.x<=e.x+e.width&&t.y>=e.y&&t.y<=e.y+e.height;async function Sh(e){await G(e,`DOM.enable`),await G(e,`DOM.getDocument`,{depth:-1,pierce:!0})}async function Ch(e,t){let n=await G(e,`DOM.performSearch`,{query:t,includeUserAgentShadowDOM:!1}).catch(()=>null);if(!n?.searchId)return[];let r=n.resultCount?await G(e,`DOM.getSearchResults`,{searchId:n.searchId,fromIndex:0,toIndex:n.resultCount}).catch(()=>null):null;return await G(e,`DOM.discardSearchResults`,{searchId:n.searchId}).catch(()=>{}),r?.nodeIds??[]}async function wh(e,t){let n=(await G(e,`DOM.getBoxModel`,{nodeId:t}).catch(()=>null))?.model?.content;if(!n||n.length<8)return null;let r=[n[0],n[2],n[4],n[6]],i=[n[1],n[3],n[5],n[7]],a=Math.min(...r),o=Math.min(...i),s=Math.max(...r)-a,c=Math.max(...i)-o;return s>0&&c>0?{x:Math.round(a),y:Math.round(o),width:Math.round(s),height:Math.round(c)}:null}async function Th(e,t){return(await G(e,`Runtime.evaluate`,{expression:t,returnByValue:!0}).catch(()=>null))?.result?.value===!0}var Eh=/^[a-z0-9][a-z0-9-]{0,47}$/;function Dh(e){let t=0;for(let n=0;n<e.length;n++){let r=e.charCodeAt(n);r<128?t+=1:r<2048?t+=2:r>=55296&&r<=56319?(t+=4,n++):t+=3}return t}var Oh=48;function kh(e){let t;try{t=new URL(e)}catch{return null}if(t.protocol!==`http:`&&t.protocol!==`https:`)return null;let n=t.hostname.toLowerCase().replace(/^www\./,``);if(!n)return null;let[r=``]=t.pathname.split(`/`).filter(Boolean);return{host:n,segment:Mh(r)||`root`}}function Ah(e,t){return`${e.host}:${e.segment}:${t}`}function jh(e,t){let n=kh(t);return!!n&&n.host===e.host&&n.segment===e.segment}function Mh(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,Oh).replace(/-+$/,``)}var Nh=new Set([`a`,`an`,`and`,`for`,`from`,`in`,`of`,`on`,`the`,`this`,`to`,`with`]);function Ph(e,t){return Mh(e.toLowerCase().replace(/[^a-z0-9\s-]+/g,` `).split(/[\s-]+/).filter(e=>e&&!Nh.has(e)).join(`-`))||Mh(t)||`tool`}function Fh(e,t){let n=Mh(`tool-${e.host}-${e.segment}-${t}`).slice(0,48).replace(/-+$/,``);return Eh.test(n)?n:`tool-${Mh(t).slice(0,42)}`}var Ih=50;async function Lh(e){let t=await Jf(e.tabId);if(t===0)return{session:e};let n=crypto.randomUUID();if(!await tp(e.tabId,t,n))return null;try{let t=(await qm(e)).map(({sessionId:t})=>({tabId:e.tabId,sessionId:t}));for(let r of[e,...t])for(let e of await Rh(r))if(await zh(r,e)===n)return{session:r,contextId:e};return null}finally{np(e.tabId,t)}}async function Rh(e){let t=[],n=Bm((n,r,i)=>{if(r!==`Runtime.executionContextCreated`||n.tabId!==e.tabId||n.sessionId!==e.sessionId)return;let a=i.context;a?.auxData?.isDefault&&t.push(a.id)});try{await G(e,`Runtime.enable`),await W(Ih)}catch{return[]}finally{n(),await G(e,`Runtime.disable`).catch(()=>{})}return t}async function zh(e,t){return(await G(e,`Runtime.evaluate`,{expression:`document.documentElement.getAttribute(${JSON.stringify(Hf)})`,returnByValue:!0,contextId:t}).catch(()=>null))?.result?.value}var Bh=`browsentic/savedTools`,Vh=({code:e,...t})=>t;async function Hh(){let e=(await t.storage.local.get(Bh))[Bh];return Array.isArray(e)?e:[]}async function Uh(e){return(await Hh()).find(t=>t.id===e)??null}async function Wh(e){let n=(await Hh()).filter(t=>t.name!==e.name);await t.storage.local.set({[Bh]:[e,...n].slice(0,100)})}async function Gh(e){let n=await Hh(),r=n.find(t=>t.id===e);return r?(await t.storage.local.set({[Bh]:n.filter(t=>t.id!==e)}),Vh(r)):null}async function Kh(e,t){let n=new Set((await Hh()).map(e=>e.name)),r=Ah(e,t);if(!n.has(r))return r;for(let e=2;e<100;e++){let t=`${r}-${e}`;if(!n.has(t))return t}return`${r}-${Date.now()}`}function qh(e,t){if(!t||!kh(t))return!1;let n;try{n=new URL(t).origin}catch{return!1}return n===e.origin&&jh(e.scope,t)}var Jh=`browsentic/codeToolkits`,Yh=`Installing page code needs Chrome’s debugger, which Firefox does not expose — use the ordinary page tools instead.`,Xh=600,Zh=`Chrome’s debugger found no script context for the frame in focus — call page.switchFrame with no arguments and inject from the top document, or enter the frame again once it has loaded.`,Qh=1e3,$h=new Set;function eg(e){$h.add(e)}async function tg(){return(await t.storage.session.get(Jh))[Jh]??{}}async function ng(e,n){let r=await tg();n?r[String(e)]=n:delete r[String(e)],await t.storage.session.set({[Jh]:r})}async function rg(e){await ng(e,null)}function ig(){t.tabs.onRemoved.addListener(e=>void rg(e))}function ag(e){if(e)try{let t=new URL(e).origin;return t===`null`?void 0:t}catch{return}}async function og(e,t,n){let r=Mu.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let i=ag(t);if(!i)return s(`UNSUPPORTED`,`Page code can only be installed on an http(s) page.`);let{purpose:a,code:c,call:l}=r.data,u={id:crypto.randomUUID(),origin:i,purpose:a,code:c,entries:[],installedAt:Date.now()},d=await dg(e,u);if(!d.ok)return d;u.entries=d.data,await ng(e,u);let f={toolkitId:u.id,origin:i,purpose:a,functions:u.entries.map(e=>e.name)},p=l?await ug(e,t,{function:l.function,args:l.args}):null;return sg(u,t,l?.function),p?p.ok?o({...f,called:p.data}):o({...f,callFailed:p.error}):o(f)}function sg(e,t,n){let r=e.entries.filter(e=>e.arity===0),i=r.find(e=>e.name===n)??(r.length===1?r[0]:null),a=t?kh(t):null;!i||!a||setTimeout(()=>{let t={toolkitId:e.id,fn:i.name,purpose:e.purpose,suggestedSlug:Ph(e.purpose,i.name),host:a.host,segment:a.segment,origin:e.origin};for(let e of $h)e(t)},Qh)}async function cg(e,t,n){let r=await Uh(n);if(!r)return s(`UNKNOWN_TOOL`,`That tool is no longer saved.`);if(!qh(r,t))return s(`TOOLKIT_SCOPE`,`“${r.name}” was saved for ${r.origin}/${r.scope.segment}, and this tab is somewhere else.`);let i={id:r.id,origin:r.origin,purpose:r.description,code:r.code,entries:[],installedAt:Date.now()},a=await dg(e,i);return a.ok?(i.entries=a.data,await ng(e,i),U(e,qd.name,{function:r.fn,args:[],timeoutMs:1e4})):a}async function lg(e,t){let n=(await tg())[String(e)];return n&&n.id===t?n.code:null}async function ug(e,t,n){let r=qd.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let i=(await tg())[String(e)];if(!i)return s(Hd,`No toolkit is installed in this tab. Call page.injectCode first, and the user will be asked to approve the code.`);let a=ag(t);if(a!==i.origin)return await rg(e),s(`TOOLKIT_SCOPE`,`That toolkit was approved for ${i.origin}, but this tab is on ${a??`another page`}. Install it again here if the job continues.`);if(!i.entries.some(e=>e.name===r.data.function))return s(`UNKNOWN_FUNCTION`,`This toolkit has no function named “${r.data.function}”. It defines: ${i.entries.map(e=>e.name).join(`, `)}.`);let o=await U(e,qd.name,r.data);if(o.ok||o.error.code!==`TOOLKIT_MISSING`)return o;let c=await dg(e,i);return c.ok?U(e,qd.name,r.data):c}function dg(e,t){return Wm(e,Yh,async e=>{let n=await Lh(e);if(!n)return s(`FRAME_UNREACHABLE`,Zh);let r=await fg(n,Wd(t.id,t.code)),i=r.exceptionDetails;if(i)return s(`CODE_ERROR`,`The code failed while installing: ${pg(i)}`);let a=r.result?.value;return Array.isArray(a)?o(a):s(`CODE_ERROR`,`The code installed but reported no functions.`)})}function fg({session:e,contextId:t},n){return G(e,`Runtime.evaluate`,{expression:n,returnByValue:!0,awaitPromise:!0,...t==null?{}:{contextId:t}})}function pg(e){let t=e.exception?.description??e.text??`unknown error`;return t.length>Xh?`${t.slice(0,Xh)}…`:t}async function mg(e,t,n){let r=fu.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let i=await qf(e);if(!r.data.frame){let n=r.data.to===`top`?[]:i.slice(0,-1);return await Xf(e,n),o(gg(n,t))}let a=await U(e,fu.name,r.data);if(!a.ok)return a;let c=a.data,l=await hg(e,c.frameId);if(!l)return s(`FRAME_UNREACHABLE`,`${c.selector} cannot be entered — ${c.sandbox&&!c.sandbox.includes(`allow-scripts`)?`its sandbox forbids scripts`:`it is a browser-internal frame or has not loaded`}. page.screenshot still shows it and page.trustedClick with a "point" still reaches it.`);let u=[...i,{frameId:c.frameId,url:l.url,selector:c.selector}];return await Xf(e,u),o({entered:a.data,...gg(u,t)})}async function hg(e,t){return await ep(e,t)||(await up(e,t)?ep(e,t):null)}function gg(e,t){let n=e.at(-1);return{frame:{depth:e.length,frameId:n?.frameId??0,url:n?.url??t,path:e.map(({selector:e,url:t})=>({selector:e,url:t}))}}}var _g=`⟪browsentic:site-tool-timeout⟫`;async function vg(e){try{let t=document.modelContext,n=navigator.modelContext,r=t??n;if(!r)return{ok:!0,api:null,tools:[]};let i=t?`document.modelContext`:`navigator.modelContext`,a=r.getTools??r.listTools;if(typeof a!=`function`)return{ok:!0,api:i,tools:[]};let o=await Promise.resolve(a.call(r)),s=Array.isArray(o)?o:Array.isArray(o?.tools)?o.tools:[],c=e=>{try{return e===void 0?void 0:JSON.parse(JSON.stringify(e))}catch{return}};return{ok:!0,api:i,tools:s.filter(e=>!!e&&typeof e.name==`string`).map(t=>({name:String(t.name),description:typeof t.description==`string`?t.description.slice(0,e?500:140):void 0,...e?{inputSchema:c(t.inputSchema??t.input_schema??t.parameters),annotations:c(t.annotations)}:{}}))}}catch(e){return{ok:!1,error:String(e?.message??e)}}}async function yg(e,t,n,r){try{let i=document.modelContext,a=navigator.modelContext,o=i??a;if(!o)return{ok:!1,code:`NO_SITE_TOOLS`,error:`This site registers no WebMCP tools.`};let s=o.getTools??o.listTools;if(typeof s==`function`){let t=await Promise.resolve(s.call(o)),n=(Array.isArray(t)?t:Array.isArray(t?.tools)?t.tools:[]).map(e=>e?.name).filter(e=>typeof e==`string`);if(n.length&&!n.includes(e))return{ok:!1,code:`SITE_TOOL_NOT_FOUND`,error:`This site registers no tool named “${e}”.`,tools:n}}let c=o.executeTool??o.callTool;if(typeof c!=`function`)return{ok:!1,code:`NO_SITE_TOOLS`,error:`This site’s model context offers no way to execute a tool.`};let l=await Promise.race([Promise.resolve(c.call(o,e,t)),new Promise(e=>setTimeout(()=>e(r),n))]);if(l===r)return{ok:!1,code:`TIMEOUT`,error:`“${e}” did not finish within ${n}ms.`};try{return{ok:!0,value:l===void 0?null:JSON.parse(JSON.stringify(l))}}catch{return{ok:!1,code:`SITE_TOOL_FAILED`,error:`The tool returned something that is not JSON.`}}}catch(e){return{ok:!1,code:`SITE_TOOL_FAILED`,error:String(e?.message??e)}}}async function bg(e,n,r){try{return(await t.scripting.executeScript({target:{tabId:e,frameIds:[await Jf(e)]},world:`MAIN`,func:n,args:r}))[0]?.result??null}catch{return null}}async function xg(e){let t=await bg(e,vg,[!1]);return!t?.ok||!t.tools.length?null:{api:t.api,count:t.tools.length,tools:t.tools}}async function Sg(e,t,n){let[r,i,a]=await Promise.all([U(e,vu.name,n),xg(e),qf(e)]);return r.ok?o({...r.data,...i?{siteTools:i}:{},...a.length?gg(a,t):{}}):r}async function Cg(e,t){if(!ag(t))return s(`UNSUPPORTED`,`Site tools can only be read on an http(s) page.`);let n=await bg(e,vg,[!0]);return n?n.ok?n.tools.length?o({api:n.api,count:n.tools.length,tools:n.tools}):s(`NO_SITE_TOOLS`,`This site registers no WebMCP tools — the ordinary page tools are the way to work here.`):s(`ACTION_FAILED`,`The site’s model context failed while listing its tools: ${n.error}`):s(`UNSUPPORTED`,`Reading site tools needs main-world scripting, which this browser does not allow here.`)}async function wg(e,t,n){let r=Pc.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));if(!ag(t))return s(`UNSUPPORTED`,`Site tools can only be called on an http(s) page.`);let{tool:i,args:a,timeoutMs:c}=r.data,l=await bg(e,yg,[i,a,c,_g]);if(!l)return s(`UNSUPPORTED`,`Calling site tools needs main-world scripting, which this browser does not allow here.`);if(!l.ok){let e=l.tools?.length?` It defines: ${l.tools.join(`, `)}.`:``;return s(l.code,`${l.error}${e}`)}return o({tool:i,returned:l.value})}var Tg=15e3;async function Eg(e,n){let r=Fc.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let{target:i,url:a,timeoutMs:c}=r.data;try{Ic(r.data)}catch(e){return e instanceof I?s(e.code,e.message):s(`INVALID_INPUT`,String(e))}if(!t.downloads)return s(`DOWNLOADS_UNAVAILABLE`,`This browser build has no downloads permission — reload the Browsentic extension and accept the new permission prompt.`);let l=jg(c),u=null;try{a?l.expect(await t.downloads.download({url:a})):u=await U(e,Lc.name,{target:i})}catch(e){return l.cancel(),s(`DOWNLOAD_FAILED`,e instanceof Error?e.message:String(e))}if(u&&!u.ok)return l.cancel(),u;let d=await l.settled;if(!d.ok)return d;let f=d.data;try{await t.downloads.erase({id:f.id})}catch{}return o({triggeredBy:a?`url`:`click`,...u?.ok?{clicked:u.data}:{},item:Og(f)})}async function Dg(e){let[n]=await t.downloads.search({id:e});return n??null}function Og(e){let t=e.filename;return{browserPath:t,name:kg(t),mime:e.mime??``,size:typeof e.fileSize==`number`&&e.fileSize>0?e.fileSize:e.totalBytes??0,url:e.finalUrl||e.url,host:Ag(e.finalUrl||e.url)}}function kg(e){return e.split(/[\\/]/).pop()||`download`}function Ag(e){try{return new URL(e).hostname.toLowerCase()||void 0}catch{return}}function jg(e){let n=null,r=()=>{},i=new Promise(e=>{r=e}),a=setTimeout(()=>{n===null&&m(s(`NO_DOWNLOAD_STARTED`,`Nothing downloaded. The click may have opened a page instead — check where the tab landed, or pass the file’s url directly.`))},Math.min(Tg,e)),c=setTimeout(()=>m(s(`TIMEOUT`,`The download did not finish within ${e}ms.`)),e),l=e=>{n===null&&d(e.id)},u=e=>{e.id===n&&(e.state?.current===`complete`?p(e.id):e.state?.current===`interrupted`&&m(s(`DOWNLOAD_FAILED`,`The browser stopped the download: ${e.error?.current??`interrupted`}.`)))};function d(e){n=e,clearTimeout(a),f(e)}async function f(e){let t=await Dg(e);t?.state===`complete`?p(e):t?.state===`interrupted`&&m(s(`DOWNLOAD_FAILED`,`The browser stopped the download: ${t.error??`interrupted`}.`))}async function p(e){let t=await Dg(e);if(!t?.filename){m(s(`DOWNLOAD_FAILED`,`The download finished but the browser reported no file.`));return}m(o(t))}function m(e){clearTimeout(a),clearTimeout(c),t.downloads.onCreated.removeListener(l),t.downloads.onChanged.removeListener(u),r(e)}return t.downloads.onCreated.addListener(l),t.downloads.onChanged.addListener(u),{settled:i,expect:d,cancel:()=>m(s(`CANCELLED`,`The capture was abandoned before a download started.`))}}function Mg(e){let t=2166136261,n=JSON.stringify([...e].sort((e,t)=>e.name<t.name?-1:+(e.name>t.name)).map(({name:e,description:t,inputSchema:n})=>[e,t,n]));for(let e=0;e<n.length;e++)t^=n.charCodeAt(e),t=Math.imul(t,16777619);return(t>>>0).toString(16).padStart(8,`0`)}var Ng=16,Pg=`|`,Fg=25e4,Ig=new TextEncoder,Lg=new TextDecoder;function Rg(){return Jg(crypto.getRandomValues(new Uint8Array(Ng)))}function zg(e){return typeof e==`string`&&e.length>=16}async function Bg(e,t){let n=await crypto.subtle.importKey(`raw`,Ig.encode(e),`PBKDF2`,!1,[`deriveBits`]),r=Ig.encode(qg(`browsentic/pair`,t.clientNonce,t.serverNonce)),i=await crypto.subtle.deriveBits({name:`PBKDF2`,salt:r,iterations:Fg,hash:`SHA-256`},n,256);return Jg(new Uint8Array(i))}async function Vg(e,t){return Jg(await Gg(e,`browsentic/client`,t))}async function Hg(e,t,n){return Jg(await Gg(e,`browsentic/server`,t,qg(n.daemonVersion,n.manifestHash,String(n.manifestInSync),n.sealedSessionKey??``)))}async function Ug(e,t,n){let r=Yg(n);if(!r)return null;let i=await Kg(e,t,r.length);return Lg.decode(r.map((e,t)=>e^i[t]))}function Wg(e,t){if(typeof e!=`string`||e.length!==t.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=e.charCodeAt(r)^t.charCodeAt(r);return n===0}async function Gg(e,t,n,r=``){let i=await crypto.subtle.importKey(`raw`,Ig.encode(e),{name:`HMAC`,hash:`SHA-256`},!1,[`sign`]),a=qg(t,String(n.protocolVersion),n.extensionVersion,n.manifestHash,n.clientNonce,n.serverNonce,r);return new Uint8Array(await crypto.subtle.sign(`HMAC`,i,Ig.encode(a)))}async function Kg(e,t,n){let r=new Uint8Array(n);for(let i=0,a=0;i<n;i+=32,a++){let o=await Gg(e,`browsentic/seal`,t,String(a));r.set(o.subarray(0,Math.min(32,n-i)),i)}return r}function qg(...e){return e.join(Pg)}function Jg(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function Yg(e){try{return Uint8Array.from(atob(e.replace(/-/g,`+`).replace(/_/g,`/`)),e=>e.charCodeAt(0))}catch{return null}}var Xg=`browsentic/daemon`,Zg=`browsentic/reconnect`,Qg=`browsentic/sessionKey`,$g=1e3,e_=3e4,t_=5e3,n_=2e4,K=null,r_=0,i_,a_=null,o_=new Set,s_=null;function c_(e){s_=e}function l_(e){a_=e}function u_(e){o_.add(e)}function d_(e,t){let n=crypto.randomUUID();return q({t:`instruct`,id:n,text:e,context:t})?n:null}var f_=9e4,p_=new Map;function m_(e){let t=crypto.randomUUID();return q({t:`analyzeFile`,id:t,...e})?new Promise(e=>{let n=setTimeout(()=>{p_.delete(t),e(s(`TIMEOUT`,`The daemon did not return a summary in time.`))},f_);p_.set(t,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var h_=12e4,g_=new Map;function __(e){let t=crypto.randomUUID();return q({t:`analyzeRecording`,id:t,recording:e})?new Promise(e=>{let n=setTimeout(()=>{g_.delete(t),e(s(`TIMEOUT`,`The daemon did not return a workflow in time.`))},h_);g_.set(t,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var v_=2e4,y_=new Map;function b_(e){let t=crypto.randomUUID();return q({t:`nameSession`,id:t,...e})?new Promise(e=>{let n=setTimeout(()=>{y_.delete(t),e(s(`TIMEOUT`,`The daemon did not return a name in time.`))},v_);y_.set(t,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var x_=15e3,S_=new Map;function C_(e){return O_({t:`saveSkill`,id:crypto.randomUUID(),skill:e})}function w_(e){return O_({t:`deleteSkill`,id:crypto.randomUUID(),name:e})}function T_(e){return O_({t:`deleteSiteMap`,id:crypto.randomUUID(),name:e})}function E_(e,t=!1){return O_({t:`activateSiteMap`,id:crypto.randomUUID(),stagingId:e,exactHost:t})}function D_(e){return O_({t:`discardSiteMap`,id:crypto.randomUUID(),stagingId:e})}function O_(e){return q(e)?new Promise(t=>{let n=setTimeout(()=>{S_.delete(e.id),t(s(`TIMEOUT`,`The daemon did not answer in time.`))},x_);S_.set(e.id,e=>{clearTimeout(n),t(e)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var k_=2e4,A_=new Map;function j_(e=!1){return F_({t:`agentState`,id:crypto.randomUUID(),refresh:e})}function M_(e){return F_({t:`setAgent`,id:crypto.randomUUID(),agent:e})}function N_(e,t){return F_({t:`setAgentModel`,id:crypto.randomUUID(),agent:e,model:t})}function P_(e){return F_({t:`grantAgent`,id:crypto.randomUUID(),agent:e})}function F_(e){return q(e)?new Promise(t=>{let n=setTimeout(()=>{A_.delete(e.id),t(s(`TIMEOUT`,`The daemon did not answer in time.`))},k_);A_.set(e.id,e=>{clearTimeout(n),t(e)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var I_=new Map;function L_(e=!1){let t={t:`listSkills`,id:crypto.randomUUID(),refresh:e};return q(t)?new Promise(e=>{let n=setTimeout(()=>{I_.delete(t.id),e(s(`TIMEOUT`,`The daemon did not answer in time.`))},k_);I_.set(t.id,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var R_=new Map;function z_(){return V_({t:`guardrails`,id:crypto.randomUUID()})}function B_(e,t){return V_({t:`setGuardrail`,id:crypto.randomUUID(),setting:e,value:t})}function V_(e){return q(e)?new Promise(t=>{let n=setTimeout(()=>{R_.delete(e.id),t(s(`TIMEOUT`,`The daemon did not answer in time.`))},k_);R_.set(e.id,e=>{clearTimeout(n),t(e)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}function H_(e){return q({t:`cancel`,id:e})}function U_(e,t,n,r){q({t:`decision`,id:e,toolId:t,allow:n,remember:r})}function W_(e){q({t:`reset`,sessionId:e})}function q(e){return!K||K.readyState!==WebSocket.OPEN?!1:(iv(K,e),!0)}async function G_(){if(X_())return;let e=await cv();if(!e){await sv({connected:!1,paired:!1,error:void 0,lastChangeAt:Date.now()});return}let t=await ov();t&&!t.paired&&t.error||(clearTimeout(i_),Q_({kind:`session`,secret:e},0))}async function K_(e){let t=e.replace(/[\s-]/g,``).toUpperCase();return t?(Z_(),clearTimeout(i_),r_=0,new Promise(e=>{J_=e,Q_({kind:`pair`,secret:t},0),setTimeout(()=>Y_({ok:!1,error:`No Browsentic daemon is running. Start one with "browsentic pair".`}),n_)})):{ok:!1,error:`Enter the pairing code from "browsentic pair".`}}async function q_(){clearTimeout(i_),Z_(),await t.storage.local.remove(Qg),await sv({connected:!1,paired:!1,error:void 0,agent:void 0,lastChangeAt:Date.now()})}var J_=null;function Y_(e){J_?.(e),J_=null}function X_(){return!!K&&(K.readyState===WebSocket.OPEN||K.readyState===WebSocket.CONNECTING)}function Z_(){let e=K;if(K=null,e){e.onopen=null,e.onmessage=null,e.onclose=null;try{e.close(1e3,`client disconnecting`)}catch{}}}function Q_(e,n,r){if(n>=i.length)return tv(e,r);let a=i[n],o=new WebSocket(`ws://127.0.0.1:${a}/extension`);K=o;let s=!1,c=!1,l=r,u={credential:e,port:a,hello:{extensionVersion:t.runtime.getManifest().version,manifestHash:Mg(Vf()),nonce:Rg()},done(){s=!0,c=!0,clearTimeout(d)},walk(e){if(!s){s=!0,l=e??r,clearTimeout(d);try{o.close(1e3,`unproven daemon`)}catch{}}}},d=setTimeout(()=>u.walk(),t_);o.onopen=()=>{iv(o,{t:`hello`,protocolVersion:16,extensionVersion:u.hello.extensionVersion,manifestHash:u.hello.manifestHash,auth:{kind:e.kind},nonce:u.hello.nonce})},o.onmessage=e=>{rv(o,String(e.data),u)},o.onclose=t=>{if(clearTimeout(d),K===o&&(K=null),l??=ev(t),!c)return Q_(e,n+1,l);sv({connected:!1,paired:!0,error:void 0,lastChangeAt:Date.now()}),e.kind===`session`&&av(e)}}var $_=new Set([`unproven daemon`,``]);function ev(e){let t=e.reason?.trim();if(!(!t||$_.has(t)))return/protocol version mismatch/i.test(t)?{reason:`${t}. Rebuild and reload the extension — “yarn build”, then Reload at chrome://extensions.`,retryable:!1}:{reason:t,retryable:!0}}function tv(e,t){if(t&&!t.retryable){Y_({ok:!1,error:t.reason}),sv({connected:!1,paired:!1,error:t.reason,lastChangeAt:Date.now()});return}Y_({ok:!1,error:t?.reason??`No Browsentic daemon is running.`}),e.kind===`session`&&av(e)}function nv(e){return{protocolVersion:16,extensionVersion:e.hello.extensionVersion,manifestHash:e.hello.manifestHash,clientNonce:e.hello.nonce,serverNonce:e.serverNonce??``}}async function rv(e,n,r){let i=a(n);if(i)switch(i.t){case`ping`:return iv(e,{t:`pong`,id:i.id});case`challenge`:{if(!zg(i.nonce)||r.serverNonce)return r.walk();r.serverNonce=i.nonce;let t=nv(r);return r.secret=r.credential.kind===`pair`?await Bg(r.credential.secret,t):r.credential.secret,iv(e,{t:`prove`,proof:await Vg(r.secret,t)})}case`unauthorized`:return r.walk({reason:i.reason,retryable:i.retryable!==!1});case`welcome`:{let e=r.secret;if(!e)return r.walk();let n=nv(r),a=i.sealedSessionKey??``;if(!Wg(i.proof,await Hg(e,n,i)))return r.walk({reason:`Whatever is listening on port ${r.port} could not prove it is the Browsentic daemon.`,retryable:!0});let o=a?await Ug(e,n,a):null;if(!o&&(a||r.credential.kind===`pair`))return r.walk();r.done(),r_=0,o&&await t.storage.local.set({[Qg]:o}),Y_({ok:!0}),await sv({connected:!0,paired:!0,port:r.port,daemonVersion:i.daemonVersion,manifestInSync:i.manifestInSync,error:void 0,lastChangeAt:Date.now()});for(let e of o_)e();return}case`describe`:return iv(e,{t:`manifest`,id:i.id,tools:Vf()});case`invoke`:return iv(e,{t:`result`,id:i.id,result:await RS(i.action,i.input,i.tabId,i.runId)});case`run`:return a_?.(i.id,i.event);case`fileSummary`:p_.get(i.id)?.(i.result),p_.delete(i.id);return;case`skillResult`:S_.get(i.id)?.(i.result),S_.delete(i.id);return;case`sessionName`:y_.get(i.id)?.(i.result),y_.delete(i.id);return;case`recordingWorkflow`:g_.get(i.id)?.(i.result),g_.delete(i.id);return;case`agentInfo`:A_.get(i.id)?.(i.result),A_.delete(i.id),i.result.ok&&await sv({agent:i.result.data,lastChangeAt:Date.now()});return;case`guardrailInfo`:R_.get(i.id)?.(i.result),R_.delete(i.id);return;case`skillCatalog`:I_.get(i.id)?.(i.result),I_.delete(i.id),i.result.ok&&await sv({skillCatalog:i.result.data,lastChangeAt:Date.now()});return;case`siteMapDraft`:return s_?.(i.id,i.draft);default:return}}function iv(e,t){e.readyState===WebSocket.OPEN&&e.send(JSON.stringify(t))}function av(e){let t=Math.min(e_,$g*2**r_++)*(.5+Math.random()/2);clearTimeout(i_),i_=setTimeout(()=>Q_(e,0),t)}async function ov(){return(await t.storage.session.get(Xg))[Xg]}async function sv(e){let n=await ov()??{connected:!1,paired:!1,lastChangeAt:0};await t.storage.session.set({[Xg]:{...n,...e}})}async function cv(){let e=(await t.storage.local.get(Qg))[Qg];return typeof e==`string`&&e?e:null}var lv=`browsentic:files`,uv=e=>`browsentic:file:${e}`;async function dv(){let e=(await t.storage.local.get(lv))[lv];return Array.isArray(e)?e:[]}async function fv(e){await t.storage.local.set({[lv]:e})}async function pv(e){let n=uv(e),r=(await t.storage.local.get(n))[n];return r&&typeof r.content==`string`?r:null}async function mv(e,t){await fv((await dv()).map(n=>n.id===e?{...n,...t}:n))}async function hv(e){let t=await pv(e);if(!t){await mv(e,{status:`error`,error:`File bytes are missing from storage.`});return}let n=(await dv()).find(t=>t.id===e),r=await m_({name:t.name,mime:t.mime,size:n?.size??0,content:t.content});r.ok?await mv(e,{status:`ready`,summary:r.data.summary,digest:r.data.digest,error:void 0}):await mv(e,{status:`error`,error:`${r.error.code}: ${r.error.message}`})}var gv=RegExp(`[\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f\\u200b-\\u200f\\u202a-\\u202e\\u2066-\\u2069\\ufeff]`,`g`),_v=/^[a-zA-Z0-9 .#>+~*,_:[\]="'()-]{1,120}$/;function J(e,t){return typeof e==`string`?e.replace(/[\r\n\t]+/g,` `).replace(gv,``).replace(/^[\s#>*\-+|`~=]+/,``).replace(/[`|]/g,``).replace(/\s+/g,` `).trim().slice(0,t):``}function vv(e){return/\b(?:ignore (?:all |any )?previous|disregard (?:the |all )?(?:above|previous)|you (?:must|should|will) (?:now|always|never)|instead(?:,)? (?:navigate|go|send|email|transfer|click)|do not tell|without asking|system prompt|new instructions?)\b/i.test(e)}function yv(e){return _v.test(e)&&e.trim().split(/\s+/).length<=8}function bv(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}var xv={goal:160,summary:400,intent:120,note:160,value:200,text:80,variable:40,field:80,kind:24,caveat:200},Sv=[`page.navigate`,`page.clickElement`,`page.fillInput`,`page.selectOption`,`page.pressKey`,`page.submitForm`,`page.scrollTo`,`page.hoverElement`,`page.focusInput`,`page.selectText`,`page.waitForElement`,`page.extractText`,`page.getPageInfo`];function Cv(e,t){if(!e||typeof e!=`object`)return{ok:!1,message:`The workflow must be an object.`};let n=e,r=[],i=J(n.goal??``,xv.goal);if(!i)return{ok:!1,message:`The workflow needs a one-line goal.`};let a=J(n.summary??``,xv.summary),o=[];for(let e of Array.isArray(n.steps)?n.steps.slice(0,80):[]){let n=wv(e,t.origin,r);n&&o.push({...n,ordinal:o.length+1})}if(!o.length)return{ok:!1,message:`The workflow lists no replayable steps.`};let s=new Set,c=[];for(let e of Array.isArray(n.variables)?n.variables.slice(0,20):[]){let t=J(e?.name??``,xv.variable).replace(/[{}]/g,``);!t||s.has(t)||(s.add(t),c.push({name:t,field:J(e?.field??``,xv.field)||t,kind:J(e?.kind??``,xv.kind)||`text`}))}let l={goal:i,summary:a,steps:o,variables:c,caveats:(Array.isArray(n.caveats)?n.caveats:[]).slice(0,8).map(e=>J(e,xv.caveat)).filter(Boolean)};kv(l,r);for(let e of Dv(l))vv(e)&&r.push(`Reads like an instruction rather than an observation: “${bv(e,80)}”`);return{ok:!0,workflow:l,warnings:r}}function wv(e,t,n){let r=typeof e?.action==`string`?e.action.trim():``;if(!Sv.includes(r))return r&&n.push(`Dropped a step naming an action that cannot be replayed: ${bv(r,40)}`),null;let i=J(e?.intent??``,xv.intent);if(!i)return null;let a=Tv(e?.target,n),o=Ev(e?.url,t);return r===`page.navigate`&&!o||r!==`page.navigate`&&r!==`page.getPageInfo`&&!a?null:{ordinal:0,intent:i,action:r,target:a,value:J(e?.value??``,xv.value)||void 0,url:o||void 0,note:J(e?.note??``,xv.note)||void 0}}function Tv(e,t){if(!e||typeof e!=`object`)return;let n=typeof e.selector==`string`?e.selector.trim():``;n&&!yv(n)&&(t.push(`Dropped a step selector that did not look like a selector: ${bv(n,40)}`),n=``);let r=J(e.text??``,xv.text),i=J(e.role??``,xv.kind);if(!(!n&&!r))return{selector:n||void 0,text:r||void 0,role:i||void 0}}function Ev(e,t){if(typeof e!=`string`||!e.trim())return``;try{let n=new URL(t),r=new URL(e.trim(),t);return r.origin!==n.origin||r.protocol!==`http:`&&r.protocol!==`https:`?``:bv(r.href,300)}catch{return``}}function Dv(e){return[e.goal,e.summary,...e.steps.flatMap(e=>[e.intent,e.note??``,e.target?.text??``]),...e.variables.map(e=>e.field),...e.caveats].filter(Boolean)}function Ov(e){return Dv(e).reduce((e,t)=>e+Dh(t),0)}function kv(e,t){if(Ov(e)<=12288)return;let n=(n,r)=>{Ov(e)<=12288||(r(),t.push(`The workflow was over its size budget, so ${n} was left out.`))};for(n(`the per-step notes`,()=>{for(let t of e.steps)t.note=void 0}),n(`some of the caveats`,()=>{e.caveats=e.caveats.slice(0,3)}),n(`the longer step descriptions`,()=>{for(let t of e.steps)t.intent=bv(t.intent,60)});Ov(e)>12288&&e.steps.length>1;)e.steps.pop();e.steps.length===1&&t.push(`Only the first step fitted in the workflow.`)}var Av=`browsentic:recordings`,jv=e=>`browsentic:recording:${e}`,Mv=20;async function Nv(){let e=(await t.storage.local.get(Av))[Av];return Array.isArray(e)?e:[]}async function Pv(e){await t.storage.local.set({[Av]:e})}async function Fv(e,n){await t.storage.local.set({[jv(e.id)]:n});let r=await Nv(),i=[{...r.find(t=>t.id===e.id),...e},...r.filter(t=>t.id!==e.id)],a=i.slice(Mv);a.length&&await t.storage.local.remove(a.map(e=>jv(e.id))),await Pv(i.slice(0,Mv))}async function Iv(e){let n=jv(e),r=(await t.storage.local.get(n))[n];return r&&Array.isArray(r.events)?r:null}async function Lv(e,t){let n=await Nv();n.some(t=>t.id===e)&&await Pv(n.map(n=>n.id===e?{...n,...t,updatedAt:Date.now()}:n))}async function Rv(e){let n=(await Nv()).find(t=>t.id===e);if(!n)return;let r=await Iv(e);if(!r||!r.events.length){await Lv(e,{status:`error`,error:`The recorded steps are missing from storage.`});return}await Lv(e,{status:`analyzing`,error:void 0});let i=await __({id:n.id,name:n.name,host:n.host,startUrl:n.startUrl,captureValues:n.capturedValues,durationMs:n.durationMs,events:r.events});if(!i.ok){await Lv(e,{status:`error`,error:`${i.error.code}: ${i.error.message}`});return}let a=Cv(i.data.workflow,{origin:wp(n.startUrl)});if(!a.ok){await Lv(e,{status:`error`,error:a.message});return}await t.storage.local.set({[jv(e)]:{...r,workflow:a.workflow}}),await Lv(e,{status:`ready`,goal:a.workflow.goal,summary:a.workflow.summary,steps:a.workflow.steps.length,warnings:[...i.data.warnings,...a.warnings].slice(0,8),name:n.name===Bv(n.host,n.createdAt)?a.workflow.goal:n.name,error:void 0})}async function zv(){let e=await Nv();for(let t of e)(t.status===`analyzing`||t.error?.startsWith(`EXTENSION_OFFLINE`))&&await Rv(t.id)}function Bv(e,t){let n=new Date(t),r=`${n.getFullYear()}-${Vv(n.getMonth()+1)}-${Vv(n.getDate())} ${Vv(n.getHours())}:${Vv(n.getMinutes())}`;return`${e||`Browsing`} — ${r}`}function Vv(e){return String(e).padStart(2,`0`)}function Hv(e){return{id:e.id,name:e.name,host:e.host||Cp(e.startUrl),goal:e.goal,steps:e.steps,capturedValues:e.capturedValues,durationMs:e.durationMs}}var Uv=`browsentic/recording`,Wv=`browsentic/recording-warn`,Gv=`browsentic/recording-stop`,Kv=null;function qv(e){Kv=e}async function Jv(){let e=(await t.storage.session.get(Uv))[Uv];return e&&Array.isArray(e.events)?e:null}async function Yv(e){e?await t.storage.session.set({[Uv]:e}):await t.storage.session.remove(Uv)}function Xv(e,t){return{id:e.id,startedAt:e.startedAt,elapsedMs:Date.now()-e.startedAt,events:e.events.length,captureValues:e.captureValues,host:e.host,warning:t}}async function Zv(){let e=await Jv();return e?Xv(e):null}async function Qv(e){let t=await Jv(),n=!!t&&t.tabId===e;return{recording:n,captureValues:n?t.captureValues:!1}}async function $v(e){let n=(await t.tabs.query({active:!0,currentWindow:!0}))[0];return n?.id==null||!n.url?s(`NO_ACTIVE_TAB`,`No active tab to record.`):ey({tabId:n.id,url:n.url,captureValues:e})}async function ey(e){if(await Jv())return s(`RECORDING_IN_PROGRESS`,`A recording is already running — stop it before starting another.`);if(!/^https?:/.test(e.url))return s(`UNSUPPORTED`,`Only http(s) pages can be recorded.`);let n={id:crypto.randomUUID(),tabId:e.tabId,host:Cp(e.url),startUrl:e.url,startedAt:Date.now(),captureValues:e.captureValues,events:[{t:Date.now(),kind:`navigate`,url:e.url}],warned:!1};await Yv(n),await t.alarms.create(Wv,{when:n.startedAt+vp}),await t.alarms.create(Gv,{when:n.startedAt+_p}),await t.tabs.sendMessage(e.tabId,{channel:hp,op:`begin`}).catch(()=>void 0);let r=Xv(n);return Kv?.(r),o(r)}async function ty(e,t){if(!t.length)return;let n=await Jv();if(!(!n||n.tabId!==e)){if(n.events.length>=2e3){await ny(`timeout`);return}n.events.push(...t.slice(0,gp-n.events.length)),await Yv(n),Kv?.(Xv(n))}}async function ny(e){let n=await Jv();if(await t.alarms.clear(Wv),await t.alarms.clear(Gv),!n)return Kv?.(null),o(null);await Yv(null),e!==`tab-closed`&&await t.tabs.sendMessage(n.tabId,{channel:hp,op:`end`}).catch(()=>void 0),Kv?.(null);let r=n.startedAt;return await Fv({id:n.id,name:Bv(n.host,r),host:n.host,startUrl:n.startUrl,status:`analyzing`,capturedValues:n.captureValues,events:n.events.length,durationMs:Date.now()-n.startedAt,createdAt:r,updatedAt:Date.now()},{id:n.id,events:n.events}),Rv(n.id),o({id:n.id})}function ry(){t.tabs.onUpdated.addListener((e,t)=>{t.url&&(async()=>{let n=await Jv();if(!n||n.tabId!==e)return;let r=n.events[n.events.length-1];r?.kind===`navigate`&&r.url===t.url||await ty(e,[{t:Date.now(),kind:`navigate`,url:t.url}])})()}),t.tabs.onRemoved.addListener(e=>{(async()=>{(await Jv())?.tabId===e&&await ny(`tab-closed`)})()}),t.alarms.onAlarm.addListener(e=>{if(e.name===`browsentic/recording-stop`){ny(`timeout`);return}e.name===`browsentic/recording-warn`&&(async()=>{let e=await Jv();if(!e||e.warned)return;e.warned=!0,await Yv(e);let t=Math.max(0,_p-(Date.now()-e.startedAt));Kv?.(Xv(e,`Recording stops automatically in ${iy(t)}.`))})()})}function iy(e){let t=Math.round(e/1e3);return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}var ay=1e4,oy=120,sy=20,cy=50,ly=10;async function uy(e,n){let r=Vu.input.safeParse(e??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let{url:i,active:a}=r.data;if(!i.trim())return s(`INVALID_INPUT`,`page.openTab needs a "url" — a blank new tab is a browser page that no page action can reach.`);let c=n?await t.tabs.get(n.id).catch(()=>void 0):(await t.tabs.query({active:!0,currentWindow:!0}))[0],l=c?.url&&Ty(c.url)?c.url:void 0,u;try{let e=zu({url:i},l);if(e.kind!==`url`)return s(`INVALID_INPUT`,`page.openTab opens a URL — it has no history to walk.`);u=e.href}catch(e){return e instanceof I?s(e.code,e.message):s(`ACTION_FAILED`,String(e))}let d=c?.id!=null&&c.windowId!=null?{windowId:c.windowId,openerTabId:c.id}:{},f;try{f=await t.tabs.create({url:u,active:a,...d})}catch(e){return s(`ACTION_FAILED`,e instanceof Error?e.message:String(e))}if(f.id==null)return s(`ACTION_FAILED`,`The browser opened a tab but reported no id for it.`);let p=await my(f.id),m=a?f.id:c?.id;return o({performed:`opened ${Ey(u)} in a new ${a?`tab`:`background tab`}`,openedUrl:u,tabId:f.id,index:f.index,loaded:p,...m==null?{}:{activeTabId:m},...a&&c?.id!=null?{previousTabId:c.id}:{}})}async function dy(e,n){let r=wf.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let{tabId:i,match:a}=r.data;if(i!=null&&a!=null)return s(`INVALID_INPUT`,`Give either "tabId" or "match", not both.`);let c=await yy(e);if(i==null&&a==null)return o(_y(c,e));let l=await gy(c,{tabId:i,match:a},`switch to`);if(!l.ok)return l.result;let u=l.tab;if(!Ty(u.url))return s(`UNSUPPORTED`,`Tab ${u.id} is a browser page, not a web page — page actions cannot read or act on it, so there is nothing to switch to.`);try{await t.tabs.update(u.id,{active:!0})}catch(e){return s(`ACTION_FAILED`,e instanceof Error?e.message:String(e))}return o({performed:`switched to ${xy(u)}`,activeTabId:u.id,previousTabId:e.id,tab:by({...u,active:!0})})}async function fy(e,n){let r=Rc.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let{tabId:i,match:a}=r.data;if(i!=null&&a!=null)return s(`INVALID_INPUT`,`Give either "tabId" or "match", not both.`);let c=await yy(e),l=i==null&&a==null?hy(c,e):await gy(c,{tabId:i,match:a},`close`);if(!l.ok)return l.result;let u=l.tab;if(c.length<=1)return s(`INVALID_TARGET`,`${xy(u)} is the only tab in this window — closing it would close the window and the Browsentic panel with it. Open another tab first, or leave this one alone.`);if(u.pinned)return s(`INVALID_TARGET`,`${xy(u)} is pinned, which means the user wants to keep it. Ask them to unpin it if it really should close.`);if(!Ty(u.url))return s(`UNSUPPORTED`,`Tab ${u.id} is a browser page, not a web page — Browsentic cannot see what it is, so it will not close it.`);if((await Qv(u.id)).recording)return s(`INVALID_TARGET`,`A recording is in progress in ${xy(u)} — closing it would cut the recording short. Stop the recording first.`);try{await t.tabs.remove(u.id)}catch(e){return s(`ACTION_FAILED`,e instanceof Error?e.message:String(e))}let d=await vy(e,u.id),f=d.active?.url?Ey(d.active.url):void 0;return o({performed:f?`closed ${xy(u)} — now on ${f}`:`closed ${xy(u)}`,closed:by(u),...f?{nowOn:f}:{},...d.active?.id==null?{}:{activeTabId:d.active.id},remaining:d.remaining})}function py(e){let n,r=new Promise(e=>{n=e}),i=e=>{t.tabs.onUpdated.removeListener(a),clearTimeout(o),n(e)},a=(t,n)=>{t===e&&n.status===`complete`&&i(!0)},o=setTimeout(()=>i(!1),ay);return t.tabs.onUpdated.addListener(a),{settled:r,cancel:()=>i(!1)}}async function my(e){let n=py(e),r=(await t.tabs.get(e).catch(()=>null))?.status;return r==null||r===`complete`?(n.cancel(),r===`complete`):n.settled}function hy(e,t){let n=e.find(e=>e.id===t.id);return n?{ok:!0,tab:n}:{ok:!1,result:s(`TARGET_NOT_FOUND`,`The tab page actions were targeting is already gone.`)}}async function gy(e,n,r){if(n.tabId!=null){let r=e.find(e=>e.id===n.tabId);return r?{ok:!0,tab:r}:{ok:!1,result:await t.tabs.get(n.tabId).catch(()=>null)?s(`INVALID_TARGET`,`Tab ${n.tabId} is in a different browser window. Browsentic only acts within the window it was opened in — ${Cy(e)}`):s(`TARGET_NOT_FOUND`,`No tab with id ${n.tabId} — it has probably been closed. ${Cy(e)}`)}}let i=n.match.trim().toLowerCase();if(!i)return{ok:!1,result:s(`INVALID_INPUT`,`"match" cannot be empty.`)};let a=e.filter(wy).filter(e=>`${e.title??``} ${e.url??``}`.toLowerCase().includes(i));return a.length?a.length>1?{ok:!1,result:s(`INVALID_TARGET`,`"${Ey(n.match)}" matches ${a.length} tabs, so nothing was touched — ${r} one of them by id: ${Sy(a)}`)}:{ok:!0,tab:a[0]}:{ok:!1,result:s(`TARGET_NOT_FOUND`,`No open tab matches "${Ey(n.match)}". ${Cy(e)}`)}}function _y(e,t){let n=e.filter(wy),r=e.length-n.length,i=n.slice(0,sy);return{performed:`${n.length} open tab${n.length===1?``:`s`} in this window`,activeTabId:t.id,tabs:i.map(by),...r?{hidden:r}:{},...i.length<n.length?{truncated:!0}:{}}}async function vy(e,t){let n=[];for(let r=0;r<ly;r++){n=await yy(e);let r=n.find(e=>e.active);if(r&&!n.some(e=>e.id===t))return{active:r,remaining:n.length};await Dy(cy)}let r=n.filter(e=>e.id!==t);return{active:r.find(e=>e.active),remaining:r.length}}async function yy(e){return await t.tabs.query(e.windowId==null?{currentWindow:!0}:{windowId:e.windowId})}function by(e){return{tabId:e.id,title:Ey(e.title??``),url:Ey(e.url??``),...e.active?{active:!0}:{}}}function xy(e){let t=Ey(e.title??``),n=Ey(e.url??``);return t&&n?`“${t}” — ${n}`:t||n||`tab ${e.id}`}function Sy(e){let t=e.slice(0,sy),n=t.map(e=>`#${e.id} ${xy(e)}`).join(`; `);return t.length<e.length?`${n}; …and ${e.length-t.length} more`:n}function Cy(e){let t=e.filter(wy);return t.length?`Open tabs: ${Sy(t)}`:`No other web page is open in this window.`}var wy=e=>Ty(e.url),Ty=e=>!!e&&/^https?:/i.test(e);function Ey(e){let t=e.replace(/\s+/g,` `).trim();return t.length>oy?`${t.slice(0,oy-1)}…`:t}var Dy=e=>new Promise(t=>setTimeout(t,e)),Oy=`browsentic/diagnostics`,ky=30,Ay=400,jy=null,My=[],Ny;async function Py(){return jy||(jy=(await t.storage.session.get(Oy).catch(()=>({})))[Oy]??{},jy)}function Fy(){return clearTimeout(Ny),Ny=void 0,jy?t.storage.session.set({[Oy]:jy}).catch(()=>void 0):Promise.resolve()}function Iy(){Ny||=setTimeout(()=>void Fy(),200)}var Ly=e=>Object.values(e).filter(e=>e.phase===`watching`);function Ry(e,t){return Ly(e).find(e=>e.tabId===t)}async function zy(e,n,r){let i=e.tabId??n,a=i==null?(await t.tabs.query({active:!0,currentWindow:!0}))[0]:await t.tabs.get(i).catch(()=>void 0);if(a?.id==null||!a.url)return i==null?s(`NO_ACTIVE_TAB`,`No active tab to record.`):s(`TARGET_NOT_FOUND`,`No tab with id ${i} — it has probably been closed.`);if(!/^https?:/i.test(a.url))return s(`UNSUPPORTED`,`Only http(s) pages report a console and network activity — browser pages do not.`);if(!e.capture.length)return s(`INVALID_INPUT`,`Give "capture" at least one of "console" or "network" — there is nothing to record otherwise.`);let c=await Py();await Qy(c);let l=Ry(c,a.id);if(l)return s(`DIAGNOSTICS_IN_PROGRESS`,`This tab is already being recorded by ${l.diagnosticsId} — read it with page.readConsole, or stop it first.`);if(Ly(c).length>=2)return s(`DIAGNOSTICS_LIMIT`,`2 tabs are already being recorded — stop one with page.stopDiagnostics first.`);let u=await Vm(a.id);if(!u.ok)return s(`DEBUGGER_UNAVAILABLE`,u.message);let d=await Vy(a.id,e.capture);if(d)return await Hm(a.id),s(`DEBUGGER_UNAVAILABLE`,d);let f=Date.now(),p={diagnosticsId:crypto.randomUUID(),tabId:a.id,url:a.url,host:Cp(a.url),owner:r,capture:e.capture,phase:`watching`,startedAt:f,expiresAt:f+e.timeoutMs,console:[],network:[],droppedConsole:0,droppedNetwork:0};c[p.diagnosticsId]=p,await Fy(),await t.alarms.create(id(p.diagnosticsId),{when:p.expiresAt}),await W(150);let m=e.reload?await By(a.id):void 0;return o({..._d(p),reloaded:m,notice:dd})}async function By(e){let n=py(e);try{await t.tabs.reload(e)}catch{return n.cancel(),!1}return n.settled}async function Vy(e,t){let n={tabId:e};try{return t.includes(`console`)&&(await G(n,`Runtime.enable`),await G(n,`Log.enable`)),t.includes(`network`)&&await G(n,`Network.enable`),null}catch(e){return`Chrome attached but refused to start reporting: ${e instanceof Error?e.message:String(e)}`}}async function Hy(e){let t=await Jy(e.diagnosticsId);if(!t.ok)return t;let n=t.data,r=e.contains?.toLowerCase(),i=n.console.filter(t=>(e.level===`all`||hd(t.level,e.level))&&(!r||t.text.toLowerCase().includes(r))),a=i.slice(-e.limit),s=n.droppedConsole;if(e.drain){let e=new Set(a);n.console=n.console.filter(t=>!e.has(t)),n.droppedConsole=0,await Fy()}return o({..._d(n),messages:a,matched:i.length,returned:a.length,droppedConsole:s,truncated:i.length>a.length?`${i.length-a.length} older messages not shown — raise "limit" or narrow with "contains".`:void 0})}async function Uy(e){let t=await Jy(e.diagnosticsId);if(!t.ok)return t;let n=t.data,r=e.urlContains?.toLowerCase(),i=e.method?.toUpperCase(),a=n.network.filter(t=>Wy(t,e.status)&&(!r||t.url.toLowerCase().includes(r))&&(!i||t.method===i)),s=a.slice(-e.limit),c=e.includeBodies?await Ky(n,s):void 0,l=n.droppedNetwork;if(e.drain){let e=new Set(s);n.network=n.network.filter(t=>!e.has(t)),n.droppedNetwork=0,await Fy()}return o({..._d(n),requests:s.map(t=>Gy(t,e.includeHeaders,c)),matched:a.length,returned:s.length,droppedNetwork:l,truncated:a.length>s.length?`${a.length-s.length} older requests not shown — raise "limit" or narrow with "urlContains".`:void 0})}function Wy(e,t){return t===`all`?!0:t===`failed`?e.failed!=null:t===`pending`?e.failed==null&&e.status==null:e.failed!=null||e.status!=null&&e.status>=400}function Gy(e,t,n){let{mono:r,requestHeaders:i,responseHeaders:a,...o}=e;return{...o,requestHeaders:t?i:void 0,responseHeaders:t?a:void 0,body:n?.get(e.requestId)}}async function Ky(e,t){let n=new Map;if(e.phase!==`watching`){for(let e of t.slice(-5))n.set(e.requestId,`Not available — this recording has stopped, and Chrome keeps response bodies only while attached.`);return n}for(let r of t.slice(-5))if(r.status!=null)try{let t=await G({tabId:e.tabId},`Network.getResponseBody`,{requestId:r.requestId});n.set(r.requestId,t.base64Encoded?`[${t.body.length} bytes of binary]`:gd(t.body,ud))}catch{n.set(r.requestId,`Not available — Chrome has already discarded this body.`)}return n}async function qy(e){let t=await Py();await Qy(t);let n=Ly(t);if(e!=null){let n=await Yy(e,`stopped`);if(n)return o(_d(n));let r=t[e];return r?s(`DIAGNOSTICS_NOT_FOUND`,`Recording ${e} already ended (${r.phase}) — there is nothing to stop.`):s(`DIAGNOSTICS_NOT_FOUND`,`No recording with id “${e}”.`)}if(!n.length)return s(`DIAGNOSTICS_NOT_FOUND`,`Nothing is being recorded.`);if(n.length>1){let e=n.map(e=>`${e.diagnosticsId} · ${e.host} (tab ${e.tabId})`).join(`; `);return s(`INVALID_TARGET`,`${n.length} recordings are running, so nothing was stopped — stop one by id: ${e}`)}let r=await Yy(n[0].diagnosticsId,`stopped`);return r?o(_d(r)):s(`DIAGNOSTICS_NOT_FOUND`,`That recording just ended on its own.`)}async function Jy(e){let t=await Py();if(await Qy(t),e!=null){let n=t[e];return n?o(n):s(`DIAGNOSTICS_NOT_FOUND`,`No recording with id “${e}”. Start one with page.startDiagnostics.`)}let n=Object.values(t),r=Ly(t),i=r.length?r:n;if(!i.length)return s(`DIAGNOSTICS_NOT_FOUND`,`Nothing has been recorded. Call page.startDiagnostics first — a page’s console and network activity only exist while Browsentic is attached to it.`);if(i.length>1){let e=i.map(e=>`${e.diagnosticsId} · ${e.host} (tab ${e.tabId})`).join(`; `);return s(`INVALID_TARGET`,`${i.length} recordings to choose from — name one with "diagnosticsId": ${e}`)}return o(i[0])}async function Yy(e,n,r){let i=await Py(),a=i[e];return!a||a.phase!==`watching`?null:(a.phase=n,a.message=r??Xy(n),await t.alarms.clear(id(e)).catch(()=>void 0),n!==`detached`&&n!==`tab-closed`&&await Hm(a.tabId),Zy(i),await Fy(),a)}function Xy(e){return{stopped:`Stopped. What was collected is still readable; response bodies are not.`,timeout:`Detached on its own after its timeout, so Chrome’s debugger bar did not stay up. What was collected is still readable.`,detached:`Chrome took the debugger away — DevTools was opened on this tab, or the debugging bar was dismissed.`,"tab-closed":`The tab was closed.`}[e]}function Zy(e){let t=Object.values(e).filter(e=>e.phase!==`watching`).sort((e,t)=>e.startedAt-t.startedAt);for(let n of t.slice(0,Math.max(0,t.length-2)))delete e[n.diagnosticsId]}async function Qy(e){let t=Date.now();for(let n of Ly(e))n.expiresAt<=t&&await Yy(n.diagnosticsId,`timeout`)}async function $y(e,t){if(!e.length)return;let n=await Py();for(let r of e)await Yy(r.diagnosticsId,t),delete n[r.diagnosticsId];await Fy()}async function eb(e){let t=await Py();await $y(Object.values(t).filter(t=>t.owner===e),`stopped`)}async function tb(e){let t=await Py();await $y(Object.values(t).filter(t=>t.tabId===e),`tab-closed`)}function nb(){Bm((e,t,n)=>{e.sessionId||e.tabId==null||rb(e.tabId,t,n??{})}),Um(e=>{Py().then(t=>{let n=Ry(t,e);n&&Yy(n.diagnosticsId,`detached`)})}),t.alarms.onAlarm.addListener(e=>{e.name.startsWith(`browsentic/diagnostics-timeout:`)&&Yy(e.name.slice(rd.length),`timeout`)}),t.tabs.onRemoved.addListener(e=>void tb(e))}function rb(e,t,n){if(!jy){My.push({tabId:e,method:t,params:n}),Py().then(()=>{let e=My;My=[];for(let t of e)ib(t.tabId,t.method,t.params);Iy()});return}ib(e,t,n)}function ib(e,t,n){let r=jy?Ry(jy,e):void 0;if(!r)return;let i=ab[t]??ob[t];i&&(i(r,n),Iy())}var ab={"Runtime.consoleAPICalled":(e,t)=>{let n=t.args??[],r=fb(t.stackTrace);lb(e,{t:Date.now(),level:pd(t.type),kind:`console`,text:gd(n.slice(0,6).map(db).filter(Boolean).join(` `)),url:r[0]?.url,line:r[0]?.line,column:r[0]?.column,stack:r.length>1?r.map(pb):void 0})},"Runtime.exceptionThrown":(e,t)=>{let n=t.exceptionDetails??{},r=fb(n.stackTrace);lb(e,{t:Date.now(),level:`error`,kind:`exception`,text:gd(n.exception?.description??n.text??`Uncaught exception`),url:n.url??r[0]?.url,line:n.lineNumber==null?r[0]?.line:n.lineNumber+1,column:n.columnNumber==null?r[0]?.column:n.columnNumber+1,stack:r.length?r.map(pb):void 0})},"Log.entryAdded":(e,t)=>{let n=t.entry??{};lb(e,{t:Date.now(),level:pd(n.level),kind:`browser`,text:gd(n.source?`[${n.source}] ${n.text??``}`:n.text??``),url:n.url,line:n.lineNumber==null?void 0:n.lineNumber+1})}},ob={"Network.requestWillBeSent":(e,t)=>{let n=t.requestId,r=t.request??{},i=t.redirectResponse;if(i){let t=sb(e,n);t&&(t.status=i.status,t.statusText=i.statusText||void 0,t.responseHeaders=mb(i.headers),t.requestId=`${n}:${t.t}`)}ub(e,{t:t.wallTime?t.wallTime*1e3:Date.now(),mono:t.timestamp??0,requestId:n,method:(r.method??`GET`).toUpperCase(),url:gd(r.url??``),type:t.type,requestHeaders:mb(r.headers)})},"Network.responseReceived":(e,t)=>{let n=sb(e,t.requestId);if(!n)return;let r=t.response??{};n.status=r.status,n.statusText=r.statusText||void 0,n.mimeType=r.mimeType,n.fromCache=r.fromDiskCache===!0||r.fromPrefetchCache===!0||void 0,n.responseHeaders=mb(r.headers),n.type=t.type??n.type,n.durationMs=cb(n,t.timestamp)},"Network.loadingFinished":(e,t)=>{let n=sb(e,t.requestId);n&&(n.sizeBytes=t.encodedDataLength,n.durationMs=cb(n,t.timestamp)??n.durationMs)},"Network.loadingFailed":(e,t)=>{let n=sb(e,t.requestId);if(!n)return;let r=t.blockedReason,i=t.errorText??`Request failed`;n.failed=t.canceled===!0&&!r?`${i} (cancelled)`:r?`${i} (blocked: ${r})`:i,n.durationMs=cb(n,t.timestamp)??n.durationMs}};function sb(e,t){for(let n=e.network.length-1;n>=0;--n)if(e.network[n].requestId===t)return e.network[n]}var cb=(e,t)=>t!=null&&e.mono?Math.max(0,Math.round((t-e.mono)*1e3)):void 0;function lb(e,t){e.console.push(t);let n=e.console.length-500;n>0&&(e.droppedConsole+=n,e.console.splice(0,n))}function ub(e,t){e.network.push(t);let n=e.network.length-cd;n>0&&(e.droppedNetwork+=n,e.network.splice(0,n))}function db(e){if(e.value!==void 0)return typeof e.value==`string`?e.value:JSON.stringify(e.value);if(e.preview?.properties?.length){let t=e.preview.properties.map(e=>`${e.name}: ${e.value??`…`}`).join(`, `);return`${e.preview.description??e.type??``} {${t}${e.preview.overflow?`, …`:``}}`.trim()}return e.description??e.type??``}function fb(e){return(e?.callFrames??[]).slice(0,8).map(e=>({url:e.url||void 0,line:e.lineNumber==null?void 0:e.lineNumber+1,column:e.columnNumber==null?void 0:e.columnNumber+1,fn:e.functionName||`(anonymous)`}))}var pb=e=>`${e.fn} (${e.url??`<unknown>`}:${e.line??0}:${e.column??0})`;function mb(e){if(!e)return;let t={};for(let[n,r]of Object.entries(e).slice(0,ky))t[n.toLowerCase()]=gd(String(r),Ay);return t}var hb=`browsentic/toast`,gb=1e4;function _b(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.channel===`browsentic/toast`&&t.op===`activate`&&typeof t.tabId==`number`}var vb=[{id:`ember`,name:`Ember`,note:`Warm near-black, cyan brand.`},{id:`midnight`,name:`Midnight`,note:`Cool blue-black, violet brand.`},{id:`phosphor`,name:`Phosphor`,note:`A green CRT, grain turned up.`},{id:`daylight`,name:`Daylight`,note:`Ink on paper, for a bright room.`}],yb=`ember`,bb=`browsentic/theme`;function xb(e){return vb.some(t=>t.id===e)?e:yb}async function Sb(){return xb((await t.storage.local.get(bb))[bb])}var Cb=`Receiving end does not exist`;async function wb(e,t){let n={channel:hb,op:`show`,view:{...e,theme:await Sb(),durationMs:gb}};for(let e of await Tb(t))if(await Eb(e,n))return!0;return!1}async function Tb(e){let n=[],r=e=>{e!=null&&!n.includes(e)&&n.push(e)},[i]=await t.tabs.query({active:!0,lastFocusedWindow:!0}).catch(()=>[]);if(r(i?.id),e==null)return n;let a=await t.tabs.get(e).catch(()=>null);if(a?.windowId==null)return n;let[o]=await t.tabs.query({active:!0,windowId:a.windowId}).catch(()=>[]);return r(o?.id),n}async function Eb(e,n){let r=async()=>(await t.tabs.sendMessage(e,n))?.ok===!0;try{return await r()}catch(t){return!(t instanceof Error?t.message:String(t)).includes(Cb)||!await up(e)?!1:r().catch(()=>!1)}}function Db(){t.runtime.onMessage.addListener((e,t,n)=>{_b(e)&&(Ob(e.tabId),n({ok:!0}))})}async function Ob(e){let n=await t.tabs.update(e,{active:!0}).catch(()=>null);n?.windowId!=null&&await t.windows.update(n.windowId,{focused:!0}).catch(()=>void 0)}var kb=`browsentic/monitors`,Ab=`browsentic/monitorsDone`,jb=`Receiving end does not exist`,Mb=new Set,Nb=new Map,Pb=Promise.resolve();function Fb(e){Mb.add(e)}function Ib(e){for(let t of Mb)t(e)}function Lb(e){let t=Pb.then(e,e);return Pb=t.catch(()=>void 0),t}async function Y(){return(await t.storage.session.get(kb))[kb]??{}}function Rb(e){return t.storage.session.set({[kb]:e})}async function zb(){let e=(await t.storage.session.get(Ab))[Ab];return Array.isArray(e)?e:[]}function Bb(e){return t.storage.session.set({[Ab]:e})}function Vb(e,t=`watching`,n){let r=Date.now(),{percent:i,etaMs:a}=jc(e.samples,e.until.threshold),o=r-e.lastProgressAt;return{monitorId:e.id,tabId:e.tabId,host:e.host,label:e.label,until:e.until,startedAt:e.startedAt,elapsedMs:r-e.startedAt,timeoutMs:e.timeoutMs,phase:t,percent:i,etaMs:t===`watching`?a:void 0,stalledForMs:t===`watching`&&o>=12e4?o:void 0,logs:e.logs,message:n}}function Hb(e){return{...e,logs:e.logs.slice(-5)}}function Ub(e,t){e.logs.push({t:Date.now(),text:t}),e.logs.length>50&&e.logs.splice(0,e.logs.length-50)}async function Wb(e,n){let r=kc(e.until);if(r)return s(`INVALID_INPUT`,r);let i=e.tabId??n,a=i==null?(await t.tabs.query({active:!0,currentWindow:!0}))[0]:await t.tabs.get(i).catch(()=>void 0);if(a?.id==null||!a.url)return i==null?s(`NO_ACTIVE_TAB`,`No active tab to watch.`):s(`TARGET_NOT_FOUND`,`No tab with id ${i} — it has probably been closed.`);if(!/^https?:/i.test(a.url))return s(`UNSUPPORTED`,`Only http(s) pages can be watched — browser pages expose nothing to observe.`);let c=await Lb(async()=>{let t=await Y(),n=Object.values(t).find(e=>e.tabId===a.id);if(n)return s(`MONITOR_IN_PROGRESS`,`This tab is already being watched by monitor ${n.id}${n.label?` (“${n.label}”)`:``} — stop it first, or watch a different tab.`);if(Object.keys(t).length>=3)return s(`MONITOR_LIMIT`,`3 monitors are already running — stop one with page.stopMonitor first. page.monitorStatus lists them.`);let r=Date.now(),i={id:crypto.randomUUID(),tabId:a.id,host:Cp(a.url),startUrl:a.url,origin:wp(a.url),label:e.label,until:e.until,startedAt:r,timeoutMs:e.timeoutMs,restorePinned:a.pinned===!0,samples:[],logs:[],lastProgressAt:r,lastLogAt:r,warnedStall:!1};return Ub(i,`Watching ${i.host} ${Ac(i.until)}.`),t[i.id]=i,await Rb(t),o(i)});if(!c.ok)return c;let l=c.data;l.restorePinned||await t.tabs.update(l.tabId,{pinned:!0}).catch(()=>void 0),await t.alarms.create(Tc(l.id),{when:l.startedAt+l.timeoutMs}),await t.alarms.create(Cc,{periodInMinutes:1}),await Gb(l);let u=Vb(l);return Ib(u),o(Hb(u))}async function Gb(e){let n={channel:vc,op:`watch`,monitorId:e.id,until:e.until};try{await t.tabs.sendMessage(e.tabId,n)}catch(r){if(!(r instanceof Error?r.message:String(r)).includes(jb))return;await up(e.tabId)&&await t.tabs.sendMessage(e.tabId,n).catch(()=>void 0)}}async function Kb(e,t,n){let r=await Lb(async()=>{let r=await Y(),i=r[t];if(!i||i.tabId!==e)return null;let a=i.samples.at(-1);i.samples.push(n),i.samples.length>24&&i.samples.splice(0,i.samples.length-24),(n.percent!=null&&(a?.percent==null||n.percent>a.percent)||n.text!==void 0&&n.text!==a?.text||n.matched!==a?.matched)&&(i.lastProgressAt=n.t,i.warnedStall=!1);let{percent:o,etaMs:s}=jc(i.samples,i.until.threshold);return o!=null&&(i.lastLogPercent==null||o-i.lastLogPercent>=5||n.t-i.lastLogAt>=3e4)?(Ub(i,`Progress ${Math.round(o)}%${s==null?``:`, ETA ${Mc(s)}`}.`),i.lastLogAt=n.t,i.lastLogPercent=o):o==null&&n.text&&n.t-i.lastLogAt>=3e4&&(Ub(i,`“${n.text}”`),i.lastLogAt=n.t),await Rb(r),{monitor:{...i},complete:n.matched===!0}});if(r){if(r.complete){await qb(t,`done`);return}Ib(Vb(r.monitor))}}async function qb(e,n,r){let i=await Lb(async()=>{let t=await Y(),i=t[e];if(!i)return null;delete t[e],await Rb(t),Ub(i,r??Jb(n));let a=Vb(i,n,r),o=await zb();return o.push(a),await Bb(o.slice(-6)),{monitor:i,state:a,remaining:Object.keys(t).length}});if(!i)return null;let{monitor:a,state:o,remaining:s}=i;await t.alarms.clear(Tc(e)),s===0&&await t.alarms.clear(Cc),await Yb(a),n!==`tab-closed`&&await t.tabs.sendMessage(a.tabId,{channel:vc,op:`unwatch`,monitorId:e}).catch(()=>void 0);for(let t of Nb.get(e)??[])t(o);return Nb.delete(e),n!==`stopped`&&await ax(o),Ib(o),o}function Jb(e){return{done:`The watched condition completed.`,timeout:`Gave up: the time limit passed without completing.`,stopped:`Stopped by the user.`,"tab-closed":`The tab was closed.`,"tab-navigated":`The tab left the watched site.`}[e]}async function Yb(e){e.restorePinned||(await t.tabs.get(e.tabId).catch(()=>null))?.pinned&&await t.tabs.update(e.tabId,{pinned:!1}).catch(()=>void 0)}async function Xb(e){let t=await Y(),n=Object.values(t);if(e!=null){if(!t[e]){let t=(await zb()).find(t=>t.monitorId===e);return t?s(`MONITOR_NOT_FOUND`,`Monitor ${e} already finished (${t.phase}) — there is nothing to stop.`):s(`MONITOR_NOT_FOUND`,`No monitor with id “${e}”. page.monitorStatus lists what is running.`)}let n=await qb(e,`stopped`);return n?o(Hb(n)):s(`MONITOR_NOT_FOUND`,`Monitor ${e} just finished on its own.`)}if(n.length===0)return s(`MONITOR_NOT_FOUND`,`No monitor is running.`);if(n.length>1){let e=n.map(e=>`${e.id} · ${e.label??e.host}`).join(`; `);return s(`INVALID_TARGET`,`${n.length} monitors are running, so nothing was stopped — stop one by id: ${e}`)}let r=await qb(n[0].id,`stopped`);return r?o(Hb(r)):s(`MONITOR_NOT_FOUND`,`That monitor just finished on its own.`)}async function Zb(e){let t=await Y(),n=await zb();if(e!=null){let r=t[e];if(r)return o(Hb(Vb(r)));let i=n.find(t=>t.monitorId===e);return i?o(Hb(i)):s(`MONITOR_NOT_FOUND`,`No monitor with id “${e}” is running or recently finished.`)}return o({monitors:[...Object.values(t).map(e=>Hb(Vb(e))),...n.map(Hb)]})}async function Qb(e,t){if(!(await Y())[e]){let t=(await zb()).find(t=>t.monitorId===e);return t?o({settled:!0,state:t}):s(`MONITOR_NOT_FOUND`,`No monitor with id “${e}” is running or recently finished.`)}return new Promise(n=>{let r=Nb.get(e)??new Set,i=e=>{clearTimeout(a),r.delete(i),n(o({settled:!0,state:e}))};r.add(i),Nb.set(e,r);let a=setTimeout(()=>{(async()=>{r.delete(i);let t=(await Y())[e];if(t)return n(o({settled:!1,state:Hb(Vb(t))}));let a=(await zb()).find(t=>t.monitorId===e);n(a?o({settled:!0,state:a}):s(`MONITOR_NOT_FOUND`,`Monitor ${e} disappeared while waiting.`))})()},Math.min(t,Sc))})}async function $b(e){if(e==null)return o({monitors:[]});let t=await Y();return o({monitors:Object.values(t).filter(t=>t.tabId===e).map(e=>({monitorId:e.id,until:e.until}))})}async function ex(){let e=await Y();return Object.values(e).map(e=>Vb(e))}async function tx(){return zb()}async function nx(e){if(e==null)return Bb([]);await Bb((await zb()).filter(t=>t.monitorId!==e))}function rx(){t.tabs.onRemoved.addListener(e=>{(async()=>{for(let t of Object.values(await Y()))t.tabId===e&&await qb(t.id,`tab-closed`,`The tab was closed.`)})()}),t.tabs.onUpdated.addListener((e,t)=>{t.url&&(async()=>{for(let n of Object.values(await Y()))if(n.tabId===e)if(wp(t.url)===n.origin){let e=await Lb(async()=>{let e=await Y(),r=e[n.id];return r?(Ub(r,`Navigated to ${ix(t.url)} — still watching.`),await Rb(e),{...r}):null});e&&Ib(Vb(e))}else await qb(n.id,`tab-navigated`,`The tab left ${n.host} for ${Cp(t.url)||`another page`}.`)})()}),t.alarms.onAlarm.addListener(e=>{if(e.name.startsWith(`browsentic/monitor-timeout:`)){qb(e.name.slice(wc.length),`timeout`);return}e.name===`browsentic/monitor-watch`&&(async()=>{let e=Date.now();for(let t of Object.values(await Y())){if(await Gb(t),e-t.lastProgressAt<12e4||t.warnedStall)continue;let n=await Lb(async()=>{let n=await Y(),r=n[t.id];return!r||r.warnedStall?null:(r.warnedStall=!0,Ub(r,`No change for ${Math.round((e-r.lastProgressAt)/6e4)} minutes.`),await Rb(n),{...r})});n&&Ib(Vb(n))}})()}),t.notifications?.onClicked.addListener(e=>{if(!e.startsWith(`browsentic-monitor:`))return;let n=e.slice(Ec.length);(async()=>{let r=(await zb()).find(e=>e.monitorId===n)?.tabId??(await Y())[n]?.tabId;if(r==null)return;let i=await t.tabs.update(r,{active:!0}).catch(()=>null);i?.windowId!=null&&await t.windows.update(i.windowId,{focused:!0}).catch(()=>void 0),await t.notifications.clear(e).catch(()=>void 0)})()})}function ix(e){try{let t=new URL(e);return t.pathname+t.search}catch{return e}}async function ax(e){let n=ox(e);n&&(await wb({toastId:e.monitorId,tone:e.phase===`done`?`live`:`warn`,title:n.title,body:n.message,tabId:e.phase===`tab-closed`?void 0:e.tabId},e.tabId)||await t.notifications?.create(`${Ec}${e.monitorId}`,{type:`basic`,iconUrl:sx(),title:n.title,message:n.message}).catch(()=>void 0))}function ox(e){let t=e.label??e.host;return{done:{title:`Done: ${t}`,message:`Finished after ${cx(e.elapsedMs)}.`},timeout:{title:`Still going: ${t}`,message:`Watched for ${cx(e.elapsedMs)} without completing.`},"tab-closed":{title:`Monitor ended — tab closed`,message:`${t} was closed before finishing.`},"tab-navigated":{title:`Monitor ended — tab moved on`,message:e.message??`The tab left ${e.host}.`}}[e.phase]}function sx(){let e=t.runtime.getManifest().icons??{};return e[Object.keys(e).map(Number).sort((e,t)=>t-e)[0]]??``}function cx(e){let t=Math.round(e/1e3);return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}var lx=`browsentic/timers`,ux=`browsentic/timersDone`,dx=null,fx=Promise.resolve();function px(e){dx=e}function mx(e){let t=fx.then(e,e);return fx=t.catch(()=>void 0),t}async function hx(){return(await t.storage.session.get(lx))[lx]??{}}function gx(e){return t.storage.session.set({[lx]:e})}async function _x(){let e=(await t.storage.session.get(ux))[ux];return Array.isArray(e)?e:[]}function vx(e){return t.storage.session.set({[ux]:e})}function yx(e,t=`scheduled`,n){return{timerId:e.id,label:e.label,prompt:e.prompt,deliver:e.deliver,sessionId:e.sessionId,afterMs:e.afterMs,repeat:e.repeat,maxRuns:e.maxRuns,runs:e.runs,skipped:e.skipped,createdAt:e.createdAt,nextFireAt:t===`scheduled`?e.nextFireAt:void 0,lastFiredAt:e.lastFiredAt,phase:t,logs:e.logs,message:n}}function bx(e){return{...e,logs:e.logs.slice(-5)}}function xx(e,t){e.logs.push({t:Date.now(),text:t}),e.logs.length>20&&e.logs.splice(0,e.logs.length-20)}var Sx=e=>e.label??`timer`;async function Cx(e,t){if(e.deliver===`agent`&&!t)return s(`NO_CONVERSATION`,`Nothing here can be woken with a prompt — a timer only hands work back inside a Browsentic side-panel conversation. Pass deliver: "notify" to remind the user at that time instead, or schedule the job with your own client’s scheduler.`);let n=await mx(async()=>{let n=await hx();if(Object.keys(n).length>=5)return s(`TIMER_LIMIT`,`5 timers are already scheduled — cancel one with page.stopTimer first. page.timerStatus lists them.`);let r=Date.now(),i={id:crypto.randomUUID(),sessionId:t,label:e.label,prompt:e.prompt,deliver:e.deliver,afterMs:e.afterMs,repeat:e.repeat,maxRuns:e.repeat?e.maxRuns:1,runs:0,skipped:0,createdAt:r,nextFireAt:r+e.afterMs,logs:[]};return xx(i,`Scheduled to fire ${vf(i)}.`),n[i.id]=i,await gx(n),o(i)});if(!n.ok)return n;let r=n.data;return await wx(r),o(bx(yx(r)))}function wx(e){return t.alarms.create(hf(e.id),{when:e.nextFireAt,...e.repeat?{periodInMinutes:e.afterMs/6e4}:{}})}async function Tx(e){let n=(await hx())[e];if(!n){await t.alarms.clear(hf(e));return}let r=await Ex(n);if(r===`gone`){await Dx(e,`orphaned`,`The conversation this timer belonged to is gone.`);return}let i=await mx(async()=>{let t=await hx(),n=t[e];if(!n)return null;let i=Date.now();return r===`busy`?(n.skipped+=1,xx(n,`Skipped — the conversation was still working on the previous turn.`)):(n.runs+=1,n.lastFiredAt=i,xx(n,`Fired — run ${n.runs}${n.repeat?` of ${n.maxRuns}`:``}.`)),n.nextFireAt=i+(n.repeat||r===`delivered`?n.afterMs:pf),await gx(t),{...n}});if(i){if(i.skipped>=20){await Dx(e,`finished`,`Gave up after ${i.skipped} fires found the conversation still busy — the job takes longer than the interval it was given.`);return}if(!i.repeat){r===`delivered`?await Dx(e,`finished`):await wx(i);return}i.runs>=i.maxRuns&&await Dx(e,`finished`,`Fired ${i.runs} times, which is the limit that was set.`)}}async function Ex(e){return e.deliver===`notify`?(await Nx(e.id,e.label??`Browsentic timer`,e.prompt),`delivered`):!e.sessionId||!dx?`gone`:dx(e.sessionId,e.prompt,Sx(e))}async function Dx(e,n,r){let i=await mx(async()=>{let t=await hx(),i=t[e];if(!i)return null;delete t[e],await gx(t),xx(i,r??Ox(n));let a=yx(i,n,r);return await vx([...await _x(),a].slice(-6)),a});return i?(await t.alarms.clear(hf(e)),n===`orphaned`&&await Nx(e,`Timer ended: ${i.label??`scheduled job`}`,`The conversation it was set in has closed, so it was cancelled.`),i):null}function Ox(e){return{finished:`The schedule ran out.`,stopped:`Cancelled.`,orphaned:`The conversation this timer belonged to is gone.`}[e]}async function kx(e){let t=Object.values(await hx());if(e!=null){let t=await Dx(e,`stopped`);if(t)return o(bx(t));let n=(await _x()).find(t=>t.timerId===e);return n?s(`TIMER_NOT_FOUND`,`Timer ${e} already ended (${n.phase}) — there is nothing to cancel.`):s(`TIMER_NOT_FOUND`,`No timer with id “${e}”. page.timerStatus lists what is scheduled.`)}if(t.length===0)return s(`TIMER_NOT_FOUND`,`No timer is scheduled.`);if(t.length>1){let e=t.map(e=>`${e.id} · ${Sx(e)} (${vf(e)})`).join(`; `);return s(`INVALID_TARGET`,`${t.length} timers are scheduled, so nothing was cancelled — cancel one by id: ${e}`)}let n=await Dx(t[0].id,`stopped`);return n?o(bx(n)):s(`TIMER_NOT_FOUND`,`That timer just ended on its own.`)}async function Ax(e){let t=await hx(),n=await _x();if(e!=null){let r=t[e];if(r)return o(bx(yx(r)));let i=n.find(t=>t.timerId===e);return i?o(bx(i)):s(`TIMER_NOT_FOUND`,`No timer with id “${e}” is scheduled or recently finished.`)}return o({timers:[...Object.values(t).map(e=>bx(yx(e))),...n.map(bx)]})}async function jx(e){for(let t of Object.values(await hx()))t.sessionId===e&&await Dx(t.id,`orphaned`,`The conversation was ended.`)}function Mx(){t.alarms.onAlarm.addListener(e=>{e.name.startsWith(`browsentic/timer:`)&&Tx(e.name.slice(mf.length))}),t.notifications?.onClicked.addListener(e=>{e.startsWith(`browsentic-timer:`)&&t.notifications.clear(e).catch(()=>void 0)})}async function Nx(e,n,r){await t.notifications?.create(`${gf}${e}`,{type:`basic`,iconUrl:Px(),title:n,message:r}).catch(()=>void 0)}function Px(){let e=t.runtime.getManifest().icons??{};return e[Object.keys(e).map(Number).sort((e,t)=>t-e)[0]]??``}var Fx=`browsentic:shots`,Ix=e=>`browsentic:shot:${e}`,Lx=2,Rx=4e6,zx=new Set;function Bx(e){zx.add(e)}async function Vx(e,t){if(!e.thumbnail)return;let n=crypto.randomUUID(),r=await Hx(n,e.dataUrl),i={previewId:n,thumbnail:e.thumbnail,width:e.width,height:e.height,full:r};for(let e of zx)e(i,t)}async function Hx(e,n){if(n.length>Rx)return!1;try{let r=await t.storage.session.get(Fx),i=[e,...(Array.isArray(r[Fx])?r[Fx]:[]).filter(t=>t!==e)],a=i.slice(Lx);return await t.storage.session.set({[Ix(e)]:n,[Fx]:i.slice(0,Lx)}),a.length&&await t.storage.session.remove(a.map(Ix)),!0}catch{return!1}}var Ux=500,Wx=48,Gx=16384,Kx=Gx*Gx,qx=`TAB_LEFT_THE_FRONT`,Jx=1e4,Yx=`Capturing a background tab through the debugger is Chrome-only — Firefox captures it directly.`;async function Xx(e,t,n){if(await Zx(e.id)){let r=await nS(e.id,t,n,Qx(e));if(r.ok||r.error.code!==qx)return r}return Wm(e.id,Yx,r=>nS(e.id,t,n,$x(r)))}async function Zx(e){return(await t.tabs.get(e).catch(()=>null))?.active===!0}function Qx(e){return async(t,n)=>{let r=await dS(e.windowId,t,n);if(await Zx(e.id))return r;throw r.bitmap.close(),new I(`The tab went behind another one mid-capture`,qx)}}function $x(e){return async(t,n)=>{let r=G(e,`Page.captureScreenshot`,{format:t,...t===`jpeg`?{quality:n??cS}:{}}),i,a=new Promise((e,t)=>{i=setTimeout(()=>t(new I(`Chrome did not render the background tab in time — bring the tab to the front and retry`,`CAPTURE_FAILED`)),Jx)}),{data:o}=await Promise.race([r,a]).finally(()=>clearTimeout(i));return eS(`data:image/${t};base64,${o}`)}}async function eS(e){return{dataUrl:e,bitmap:await createImageBitmap(await(await fetch(e)).blob())}}var tS=e=>`Cannot capture this tab (${e instanceof Error?e.message:String(e)}) — it may be a chrome:// page, the Web Store, or a PDF, which browsers refuse to screenshot`;async function nS(e,t,n,r){let i=await cp(e,0,`page.screenshot`,t);if(!i.ok)return i;let a=i.data;try{let t=await iS(e,a,r);return rS(t,n),o(t)}catch(e){return e instanceof I?s(e.code,e.message):s(`CAPTURE_FAILED`,e instanceof Error?e.message:String(e))}finally{cp(e,0,`page.scrollTo`,{position:{x:a.scroll.x,y:a.scroll.y},behavior:`instant`})}}async function rS(e,t){try{await Vx({...e,thumbnail:await sS(e.dataUrl)},t)}catch{}}async function iS(e,t,n){let{viewport:r,format:i,quality:a,maxLongSide:o}=t,s={...t.region},c=Math.max(1,Math.ceil(s.w/r.w)),l=Math.max(1,Math.floor(Wx/Math.min(c,Wx))),u=!1;c>Wx&&(s.w=Wx*r.w,u=!0),Math.ceil(s.h/r.h)>l&&(s.h=l*r.h,u=!0);let d=fS(s.x,s.w,r.w),f=fS(s.y,s.h,r.h),p=d.length===1&&f.length===1&&t.mode===`viewport`,m=null,h=null,g=1,_=1,v=0;for(let c of f)for(let l of d){let d=await cp(e,0,`page.scrollTo`,{position:{x:l,y:c},behavior:`instant`});if(!d.ok)throw new I(d.error.message,d.error.code);let f=d.data,ee=Date.now()-v;v&&ee<Ux&&await pS(Ux-ee);let te=await n(i,a);v=Date.now();let ne=te.bitmap;if(!h){let e=ne.width/r.w||t.dpr||1;if(_=uS(s.w*e,s.h*e,o),g=e*_,p&&_===1){let{width:e,height:t}=ne;return ne.close(),{format:i,width:e,height:t,dataUrl:te.dataUrl,...u?{truncated:u}:{}}}if(h=new OffscreenCanvas(Math.max(1,Math.round(s.w*g)),Math.max(1,Math.round(s.h*g))),m=h.getContext(`2d`),!m)throw ne.close(),new I(`OffscreenCanvas 2D context unavailable`,`CAPTURE_FAILED`)}m.drawImage(ne,(f.scrollX-s.x)*g,(f.scrollY-s.y)*g,ne.width*_,ne.height*_),ne.close()}if(!h)throw new I(`Nothing was captured`,`CAPTURE_FAILED`);return lS(h,i,a,u)}var aS=640,oS=.6;async function sS(e){let t=await createImageBitmap(await(await fetch(e)).blob()),n=Math.min(1,aS/Math.max(t.width,t.height,1)),r=new OffscreenCanvas(Math.max(1,Math.round(t.width*n)),Math.max(1,Math.round(t.height*n))),i=r.getContext(`2d`);return i?(i.drawImage(t,0,0,r.width,r.height),t.close(),mS(await r.convertToBlob({type:`image/jpeg`,quality:oS}),`image/jpeg`)):(t.close(),``)}var cS=80;async function lS(e,t,n,r){let i=t===`jpeg`?`image/jpeg`:`image/png`,a=await mS(await e.convertToBlob(t===`jpeg`?{type:i,quality:(n??cS)/100}:{type:i}),i);return{format:t,width:e.width,height:e.height,dataUrl:a,...r?{truncated:r}:{}}}function uS(e,t,n){let r=Math.min(n,Gx)/Math.max(e,t,1),i=Math.sqrt(Kx/Math.max(e*t,1));return Math.min(1,r,i)}async function dS(e,n,r){let i=n===`jpeg`?r??cS:void 0;for(let r=0;;r++)try{return await eS(e==null?await t.tabs.captureVisibleTab({format:n,quality:i}):await t.tabs.captureVisibleTab(e,{format:n,quality:i}))}catch(e){let t=e instanceof Error?e.message:String(e);if(r<2&&/MAX_CAPTURE_VISIBLE_TAB_CALLS_PER_SECOND/i.test(t)){await pS(Ux);continue}throw new I(tS(e),`CAPTURE_UNSUPPORTED`)}}function fS(e,t,n){let r=[];for(let i=e;i<e+t;i+=n)r.push(i);return r.length?r:[e]}var pS=e=>new Promise(t=>setTimeout(t,e));function mS(e,t){return e.arrayBuffer().then(e=>{let n=new Uint8Array(e),r=``,i=32768;for(let e=0;e<n.length;e+=i)r+=String.fromCharCode(...n.subarray(e,e+i));return`data:${t};base64,${btoa(r)}`})}var hS=16,gS=1200,_S=.85,vS=120;async function yS(e,t){let n=await U(e.id,td.name,t);if(!n.ok)return n;let{capture:r,...i}=n.data,a=r?await bS(e.id,r):null,s=a?await xS(e.windowId,a).catch(()=>null):null;return o(s?{...i,shot:s}:i)}async function bS(e,t){if(await Jf(e)===0)return t;let[n,r]=await Promise.all([ip(e),ep(e,0)]);return!n||!r?null:{...t,region:{...t.region,x:t.region.x+n.x,y:t.region.y+n.y},viewport:r.viewport}}async function xS(e,t){let{viewport:n,dpr:r}=t,i=Math.max(0,t.region.x-hS),a=Math.max(0,t.region.y-hS),o=Math.min(n.w,t.region.x+t.region.w+hS)-i,s=Math.min(n.h,t.region.y+t.region.h+hS)-a;if(o<1||s<1)return null;await new Promise(e=>setTimeout(e,vS));let{bitmap:c}=await dS(e,`jpeg`,Math.round(_S*100)),l=c.width/n.w||r,u=Math.min(1,gS/Math.max(o*l,s*l,1)),d=new OffscreenCanvas(Math.max(1,Math.round(o*l*u)),Math.max(1,Math.round(s*l*u))),f=d.getContext(`2d`);return f?(f.drawImage(c,i*l,a*l,o*l,s*l,0,0,d.width,d.height),c.close(),{dataUrl:await mS(await d.convertToBlob({type:`image/jpeg`,quality:_S}),`image/jpeg`),width:d.width,height:d.height}):(c.close(),null)}var SS=`browsentic/tabSessions`,CS=null,wS=Promise.resolve();function TS(e){let t=wS.then(e,e);return wS=t.catch(()=>void 0),t}async function X(){return CS||(CS=(await t.storage.session.get(`browsentic/tabSessions`))[`browsentic/tabSessions`]??{},CS)}function ES(e){return TS(async()=>{let n={...await X()},r=await e(n);return CS=n,await t.storage.session.set({[SS]:n}),r})}async function DS(e){let t=await X();return Object.values(t).find(t=>t.tabIds.includes(e))??null}async function OS(e){let t=await X();return Object.values(t).find(t=>t.runId===e)??null}async function kS(e){return ES(t=>{let n=Object.values(t).find(t=>t.tabIds.includes(e.tabId));if(n)return n.lastActivityAt=Date.now(),e.url&&(n.url=e.url,n.host=LS(e.url)??n.host),e.title&&(n.title=e.title),{ok:!0,session:n};if(Object.keys(t).length>=8)return{ok:!1,message:`8 tab sessions are already open — close one of those tabs, or end a session, before starting another.`};let r=Date.now(),i={sessionId:crypto.randomUUID(),mainTabId:e.tabId,tabIds:[e.tabId],currentTabId:e.tabId,windowId:e.windowId??-1,title:e.title??LS(e.url)??`This tab`,url:e.url,host:LS(e.url),runId:null,turns:0,createdAt:r,lastActivityAt:r};return t[i.sessionId]=i,{ok:!0,session:i}})}function AS(e,t){return ES(n=>{for(let[e,r]of Object.entries(n))r.tabIds.includes(t.tabId)&&!r.runId&&delete n[e];let r=Date.now(),i={sessionId:e.sessionId,mainTabId:t.tabId,tabIds:[t.tabId],currentTabId:t.tabId,windowId:t.windowId??-1,title:e.title??t.title??LS(e.url)??`This tab`,url:e.url??t.url,host:LS(e.url??t.url),runId:null,agent:e.agent,agentSessionId:e.agentSessionId,usage:e.usage,turns:e.turns,createdAt:r,lastActivityAt:r};return n[i.sessionId]=i,i})}function jS(e,t,n){return ES(r=>{let i=r[e];if(i){for(let n of Object.values(r))n.sessionId!==e&&(n.tabIds=n.tabIds.filter(e=>e!==t));i.tabIds.includes(t)||i.tabIds.push(t),n&&(i.currentTabId=t),i.lastActivityAt=Date.now()}})}function MS(e,t){return ES(n=>{let r=n[e];!r||!r.tabIds.includes(t)||(r.currentTabId=t,r.lastActivityAt=Date.now())})}function NS(e,t){return ES(n=>{let r=n[e];r&&Object.assign(r,t,{lastActivityAt:Date.now()})})}function PS(e){return ES(t=>{let n=t[e]??null;return delete t[e],n})}function FS(e){return ES(t=>{for(let n of Object.values(t))if(n.tabIds.includes(e))return n.mainTabId===e?(delete t[n.sessionId],{closed:n,shrunk:null}):(n.tabIds=n.tabIds.filter(t=>t!==e),n.currentTabId===e&&(n.currentTabId=n.mainTabId),{closed:null,shrunk:n});return{closed:null,shrunk:null}})}function IS(e,t){return ES(n=>{for(let r of Object.values(n))r.tabIds.includes(e)&&(r.tabIds=r.tabIds.map(n=>n===e?t:n),r.mainTabId===e&&(r.mainTabId=t),r.currentTabId===e&&(r.currentTabId=t))})}function LS(e){if(e)try{return new URL(e).host||void 0}catch{return}}async function RS(e,t,n,r){let i=await Em(e,t);if(i.refused.length)return s(`SECRET_NOT_RELEASABLE`,gm);if(i.unresolved.length)return s(`SECRET_EXPIRED`,_m);let{value:a}=await Tm(await VS(e,i.input,n,r),await zS(n,r));return a}async function zS(e,t){let n=await WS(e,t?await OS(t):null),r=n?.id==null?n?.url:await Yf(n.id,n.url);return r?BS(r):void 0}function BS(e){try{return new URL(e).hostname.toLowerCase()||void 0}catch{return}}async function VS(e,t,n,r){if(e===Pu.name)return iC(t);if(e===Fu.name)return aC(t);if(e===bd.name)return oC(t);let i=r?await OS(r):null;if(e===Vu.name)return GS(t,i);if(e===cf.name)return qS(t,n??i?.currentTabId,i?.sessionId);if(e===vd.name)return JS(t);if(e===yd.name)return YS(t);if(e===bf.name)return XS(t);if(e===lf.name)return ZS(t,n??i?.currentTabId);if(e===Lu.name)return QS(t);if(e===xf.name)return $S(t);if(e===Nc.name)return eC(t);if(e===yf.name)return tC(t,i?.sessionId);if(e===Tf.name)return nC(t);if(e===Sf.name)return rC(t);let a=await WS(n,i);return a?.id==null?i?s(`SESSION_TAB_CLOSED`,`The tab this conversation was working in has been closed.`):n==null?s(`NO_ACTIVE_TAB`,`No active tab to control`):s(`MAPPING_TAB_CHANGED`,`The tab this run started in has been closed.`):e===Bu.name?lC(a.id,t):e===Zd.name?fC(a.id,t):e===wf.name?KS({id:a.id,windowId:a.windowId},t,i):e===fu.name?mg(a.id,a.url,t):e===Rc.name?fy({id:a.id,windowId:a.windowId},t):e===Jd.name?Xx({id:a.id,windowId:a.windowId},t,r):e===td.name?yS({id:a.id,windowId:a.windowId},t):e===pc.name?sC(a.id,t):e===Fc.name?Eg(a.id,t):e===Mu.name?og(a.id,await Yf(a.id,a.url),t):e===qd.name?ug(a.id,await Yf(a.id,a.url),t):e===vu.name?Sg(a.id,a.url,t):e===Iu.name?Cg(a.id,await Yf(a.id,a.url)):e===Pc.name?wg(a.id,await Yf(a.id,a.url),t):e===Ef.name?eh(a.id,t):e===cl.name&&HS(t)?th(a.id,t):e===El.name?ch(a.id):e===sf.name?lh(a.id,t):U(a.id,e,t)}function HS(e){return e?.trusted===!0}async function US(e){try{return await t.tabs.get(e)}catch{return}}async function WS(e,n){return n?await US(n.currentTabId)??await US(n.mainTabId):e==null?(await t.tabs.query({active:!0,currentWindow:!0}))[0]:US(e)}async function GS(e,t){if(!t)return uy(e);let n=await US(t.currentTabId)??await US(t.mainTabId),r=await uy(e,n?.id==null?void 0:{id:n.id,windowId:n.windowId});if(!r.ok)return r;let i=r.data.tabId;return typeof i==`number`&&await jS(t.sessionId,i,r.data.activeTabId===i),r}async function KS(e,t,n){if(!n)return dy(e,t);let r=t??{};if(typeof r.tabId==`number`&&!n.tabIds.includes(r.tabId)&&await DS(r.tabId))return s(`TAB_IN_USE`,`Another Browsentic conversation is working in tab ${r.tabId}. Leave it alone, or ask the user to end that session first.`);let i=await dy(e,t);if(!i.ok)return i;let a=i.data.activeTabId;return typeof a!=`number`||a===e.id||(n.tabIds.includes(a)?await MS(n.sessionId,a):await DS(a)||await jS(n.sessionId,a,!0)),i}async function qS(e,t,n){let r=cf.input.safeParse(e??{});return r.success?zy(r.data,t,n):s(`INVALID_INPUT`,x(r.error))}async function JS(e){let t=vd.input.safeParse(e??{});return t.success?Hy(t.data):s(`INVALID_INPUT`,x(t.error))}async function YS(e){let t=yd.input.safeParse(e??{});return t.success?Uy(t.data):s(`INVALID_INPUT`,x(t.error))}async function XS(e){let t=bf.input.safeParse(e??{});return t.success?qy(t.data.diagnosticsId):s(`INVALID_INPUT`,x(t.error))}async function ZS(e,t){let n=lf.input.safeParse(e??{});return n.success?Wb(n.data,t):s(`INVALID_INPUT`,x(n.error))}async function QS(e){let t=Lu.input.safeParse(e??{});return t.success?Zb(t.data.monitorId):s(`INVALID_INPUT`,x(t.error))}async function $S(e){let t=xf.input.safeParse(e??{});return t.success?Xb(t.data.monitorId):s(`INVALID_INPUT`,x(t.error))}async function eC(e){let t=Nc.input.safeParse(e??{});return t.success?Qb(t.data.monitorId,t.data.timeoutMs):s(`INVALID_INPUT`,x(t.error))}async function tC(e,t){let n=yf.input.safeParse(e??{});return n.success?Cx(n.data,t):s(`INVALID_INPUT`,x(n.error))}async function nC(e){let t=Tf.input.safeParse(e??{});return t.success?Ax(t.data.timerId):s(`INVALID_INPUT`,x(t.error))}async function rC(e){let t=Sf.input.safeParse(e??{});return t.success?kx(t.data.timerId):s(`INVALID_INPUT`,x(t.error))}async function iC(e){let t=e?.nameContains,n=typeof t==`string`?t.toLowerCase():null;return o({files:(await dv()).filter(e=>!n||e.name.toLowerCase().includes(n)).map(({id:e,name:t,mime:n,size:r,status:i,summary:a,addedAt:o})=>({id:e,name:t,mime:n,size:r,status:i,summary:a,addedAt:o}))})}async function aC(e){let t=e,n=typeof t?.host==`string`?t.host.toLowerCase():null,r=typeof t?.nameContains==`string`?t.nameContains.toLowerCase():null;return o({recordings:(await Nv()).filter(e=>!n||e.host.toLowerCase()===n).filter(e=>!r||`${e.name} ${e.goal??``}`.toLowerCase().includes(r)).map(({id:e,name:t,host:n,status:r,goal:i,summary:a,steps:o,capturedValues:s,durationMs:c,createdAt:l})=>({id:e,name:t,host:n,status:r,goal:i,summary:a,steps:o,capturedValues:s,durationMs:c,createdAt:l}))})}async function oC(e){let t=e?.recordingId;if(typeof t!=`string`||!t)return s(`INVALID_INPUT`,`Provide the "recordingId" of a recording from page.listRecordings.`);let n=(await Nv()).find(e=>e.id===t);if(!n)return s(`RECORDING_NOT_FOUND`,`No recording with id "${t}".`);let r=await Iv(t);return r?.workflow?o({id:n.id,name:n.name,host:n.host,startUrl:n.startUrl,capturedValues:n.capturedValues,durationMs:n.durationMs,goal:r.workflow.goal,summary:r.workflow.summary,variables:r.workflow.variables,caveats:r.workflow.caveats,steps:r.workflow.steps}):s(`RECORDING_NOT_READY`,n.status===`error`?`That recording could not be turned into steps: ${n.error??`unknown error`}`:`That recording is still being turned into steps — try again shortly.`)}async function sC(e,t){let n=t??{};if(typeof n.content==`string`&&n.content)return U(e,pc.name,t);let{fileId:r,target:i}=n;if(typeof r!=`string`||!r)return s(`INVALID_INPUT`,`attachFile needs a "fileId" from page.listFiles or a "downloadId" from page.captureDownload.`);let a=await pv(r);return a?U(e,pc.name,{fileId:r,target:i,name:a.name,mime:a.mime,content:a.content}):s(`FILE_NOT_FOUND`,`No stored file with id "${r}". Call page.listFiles to see stored files.`)}var cC=`Receiving end does not exist`;async function lC(e,t){await Zf(e);let n=await cp(e,0,Bu.name,t);return n.ok?o({...n.data,loaded:await py(e).settled}):n.error.code===`TAB_UNREACHABLE`?n.error.message.includes(cC)?uC(e,t):o({navigating:!0,loaded:await py(e).settled}):n}async function uC(e,n){let r=Bu.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,x(r.error));let i;try{i=zu(r.data)}catch(e){return e instanceof I?s(e.code,e.message):s(`ACTION_FAILED`,String(e))}let a=py(e);try{i.kind===`url`?await t.tabs.update(e,{url:i.href}):i.action===`reload`?await t.tabs.reload(e):i.action===`back`?await t.tabs.goBack(e):await t.tabs.goForward(e)}catch(e){a.cancel();let t=e instanceof Error?e.message:String(e);return s(`ACTION_FAILED`,i.kind===`history`&&i.action!==`reload`?`Cannot go ${i.action}: this tab has no ${i.action===`back`?`previous`:`next`} page in its history (${t})`:t)}let c=await a.settled;return o(i.kind===`url`?{navigatedTo:i.href,loaded:c}:{performed:i.action,loaded:c})}var dC=2e3;async function fC(e,t){let n=await U(e,Zd.name,t);if(!n.ok)return n;let r=n.data,i=await pC(e,r.via===`url`||r.submitted===!0);return o({...n.data,loaded:i,landedOn:(await US(e))?.url})}async function pC(e,t){let n=py(e);if(t)return n.settled;let r=await Promise.race([n.settled,new Promise(e=>setTimeout(()=>e(null),dC))]);return r===null&&n.cancel(),r??!1}var mC=`browsentic:skills`,hC=e=>`browsentic:skill:${e}`;async function gC(){let e=(await t.storage.local.get(mC))[mC];return Array.isArray(e)?e:[]}async function _C(e){await t.storage.local.set({[mC]:e})}async function vC(e){let n=hC(e),r=(await t.storage.local.get(n))[n];return r&&typeof r.body==`string`?r:null}async function yC(e,t){await _C((await gC()).map(n=>n.id===e?{...n,...t}:n))}async function bC(e){let t=(await gC()).find(t=>t.id===e);if(t?.origin===`generated`)return;let n=await vC(e);if(!t||!n){await yC(e,{status:`error`,error:`The skill is missing from storage.`});return}let r=await C_({name:t.name,description:t.description,category:t.category,domains:t.domains,triggers:n.triggers,body:n.body});r.ok?await yC(e,{status:`saved`,path:r.data.path,error:void 0}):await yC(e,{status:`error`,error:`${r.error.code}: ${r.error.message}`})}async function xC(e){let n=(await gC()).find(t=>t.id===e);n&&await(n.origin===`generated`?T_(n.name):w_(n.name)),await t.storage.local.remove(hC(e)),await _C((await gC()).filter(t=>t.id!==e))}async function SC(e){let t=await gC();await _C([{id:crypto.randomUUID(),name:e.name,description:`Mapped ${e.domain} — ${e.pages} pages.`,category:`site-exploration`,domains:[e.domain],status:`saved`,path:e.directory,addedAt:Date.parse(e.generatedAt)||Date.now(),origin:`generated`,pages:e.pages},...t.filter(t=>t.name!==e.name)])}async function CC(){for(let e of await gC())e.status!==`saved`&&e.origin!==`generated`&&await bC(e.id)}var wC=`browsentic:sessions`,TC=e=>`browsentic:session:${e}`,EC=50,DC=[1,5,15];async function OC(){let e=(await t.storage.local.get(wC))[wC];return Array.isArray(e)?e:[]}async function kC(e){await t.storage.local.set({[wC]:e})}async function AC(e,n){if(!n.length)return;let r={id:e.id,items:n.slice(-500).map(jC)};await t.storage.local.set({[TC(e.id)]:r});let i=await OC(),a=[{...i.find(t=>t.id===e.id),...e},...i.filter(t=>t.id!==e.id)],o=a.slice(EC);o.length&&await t.storage.local.remove(o.map(e=>TC(e.id))),await kC(a.slice(0,EC))}function jC(e){if(e.kind!==`tool`||!e.preview)return e;let{preview:t,...n}=e;return n}async function MC(e){let n=TC(e),r=(await t.storage.local.get(n))[n];return r&&Array.isArray(r.items)?r:null}async function NC(e,t){let n=await OC();n.some(t=>t.id===e)&&await kC(n.map(n=>n.id===e?{...n,...t}:n))}var PC=60;async function FC(e){let t=(await OC()).find(t=>t.id===e);if(!t)return;let n=((await MC(e))?.items??[]).filter(e=>e.kind===`user`).map(e=>e.text).slice(-12);if(!n.length)return;let r=t.turns;await NC(e,{namingAt:Date.now()});let i=await b_({host:t.host,messages:n});if(i.ok&&i.data.title.trim()){await NC(e,{title:i.data.title.replace(/\s+/g,` `).trim().slice(0,PC),titledAtTurn:r,namingAt:void 0});return}await NC(e,{titledAtTurn:r,namingAt:void 0})}function IC(e,t=0){let n=DC.filter(t=>e>=t).at(-1);return n!==void 0&&n>t?n:null}var LC=`/context`,RC=e=>e.trim().toLowerCase()===LC;async function zC(e){let{offer:t,code:n}=e,r={host:t.host,segment:t.segment},i=Mh(e.slug??``)||t.suggestedSlug,a=await Kh(r,i),o={id:crypto.randomUUID(),name:a,skillName:Fh(r,i),description:t.purpose,scope:r,origin:t.origin,code:n,fn:t.fn,createdAt:Date.now()};return await Wh(o),await C_(VC(o)).catch(()=>void 0),Vh(o)}async function BC(e){let t=await Gh(e);return t&&await w_(t.skillName).catch(()=>void 0),t}function VC(e){let t=e.scope.segment===`root`?e.scope.host:`${e.scope.host}/${e.scope.segment}`;return{name:e.skillName,description:`Saved tool on ${t}: ${e.description}`,category:`site-exploration`,domains:[e.scope.host],triggers:[e.name,e.scope.host],body:[`# ${e.name}`,``,`The user saved a tool for **${t}**, out of page code they read and approved:`,``,`> ${e.description}`,``,`## How it runs`,``,`It runs from the side panel, by typing \`/${e.name}\`. It is already approved, so it`,`needs no further permission and costs no round trip.`,``,`## What you should do`,``,`You cannot call it yourself: it is not a page action, and its code lives in the extension`,`rather than here. If the user asks for this on this page, tell them the tool exists and to`,`run \`/${e.name}\`, rather than writing the same thing again with page.injectCode.`,``,`If they want it changed, write fresh code with page.injectCode as usual and let them save`,`that over the old one.`].join(`
184
+ `)}}var HC=/\b([a-z0-9][a-z0-9-]*)\s+dot\s+(com|net|org|io|dev|co|ai|app|edu|gov|me|uk|xyz)\b/g,UC=/^(?:hey|hi|ok|okay|yo|um|uh|please|browsentic|assistant|can you|could you|would you|will you|i want you to|i would like you to|id like you to|lets|just|now|go ahead and)\s+/,WC=/\s+(?:please|thanks|thank you|for me|now|a bit|a little|a lot|some more|more|slightly|real quick|quickly)$/,GC=/[^a-z0-9\s./:&=@_+#-]/g;function KC(e){let t=e.trim(),n=t.toLowerCase().replace(/['‘’]/g,``);n=n.replace(HC,`$1.$2`),n=n.replace(GC,` `).replace(/\s+/g,` `).trim();let r=!1,i;do i=n,n=n.replace(UC,``).replace(WC,``).trim(),r||=n!==i;while(n!==i);return{text:n.replace(/\.$/,``),raw:t,question:/\?\s*$/.test(t)&&!r}}var qC={google:`google.com`,"google maps":`maps.google.com`,maps:`maps.google.com`,"google drive":`drive.google.com`,drive:`drive.google.com`,"google calendar":`calendar.google.com`,calendar:`calendar.google.com`,gmail:`mail.google.com`,youtube:`youtube.com`,github:`github.com`,reddit:`reddit.com`,wikipedia:`wikipedia.org`,twitter:`twitter.com`,linkedin:`linkedin.com`,facebook:`facebook.com`,instagram:`instagram.com`,amazon:`amazon.com`,netflix:`netflix.com`,"stack overflow":`stackoverflow.com`,stackoverflow:`stackoverflow.com`,"hacker news":`news.ycombinator.com`,chatgpt:`chatgpt.com`,claude:`claude.ai`},JC=new Set([`enter`,`return`]),YC={escape:`Escape`,esc:`Escape`,tab:`Tab`,space:` `,spacebar:` `,backspace:`Backspace`,delete:`Delete`,"page up":`PageUp`,"page down":`PageDown`,home:`Home`,end:`End`,"up arrow":`ArrowUp`,"down arrow":`ArrowDown`,"left arrow":`ArrowLeft`,"right arrow":`ArrowRight`,"arrow up":`ArrowUp`,"arrow down":`ArrowDown`,"arrow left":`ArrowLeft`,"arrow right":`ArrowRight`},XC=Object.keys(YC).join(`|`),ZC=/\b(?:buy|buy now|purchase|pay|payment|checkout|place order|order now|delete|remove|send|submit|transfer|withdraw|deposit|unsubscribe|subscribe|donate|book now|confirm)\b/,QC=/^(?:it|that|this|there|them|those|these|him|her|thing|one)$/,$C=8,ew=[{id:`history.back`,action:Bu.name,certainty:.97,pattern:/^(?:go\s+)?back(?:\s+(?:a|one)\s+page)?$/,build:()=>nw({action:`back`},`Go back`)},{id:`history.forward`,action:Bu.name,certainty:.97,pattern:/^(?:go\s+)?forwards?(?:\s+(?:a|one)\s+page)?$/,build:()=>nw({action:`forward`},`Go forward`)},{id:`history.reload`,action:Bu.name,certainty:.97,pattern:/^(?:reload|refresh)(?:\s+(?:the|this)\s+page)?$/,build:()=>nw({action:`reload`},`Reload the page`)},{id:`tab.open`,action:Vu.name,certainty:.95,pattern:/^(?:go\s+to|goto|open|visit|navigate\s+to|take\s+me\s+to|load|pull\s+up)\s+(?:the\s+)?(?<dest>\S+(?:\s+\S+)?)\s+in\s+(?:an?\s+)?(?:new|another|separate)\s+tab$/,build:({dest:e})=>{let t=qC[e];if(t)return rw({url:`https://${t}`},`Open ${t} in a new tab`,1);let n=ow(e);return n?rw({url:n},`Open ${e} in a new tab`,/^https?:\/\//.test(e)?1:.97):null}},{id:`navigate.url`,action:Bu.name,certainty:.95,pattern:/^(?:go\s+to|goto|open|visit|navigate\s+to|take\s+me\s+to|load|pull\s+up)\s+(?:the\s+)?(?<dest>\S+(?:\s+\S+)?)$/,build:({dest:e})=>{let t=qC[e];if(t)return nw({url:`https://${t}`},`Open ${t}`,1);let n=ow(e);return n?nw({url:n},`Open ${e}`,/^https?:\/\//.test(e)?1:.97):null}},{id:`navigate.search`,action:Bu.name,certainty:.9,pattern:/^(?<verb>google|search\s+(?:the\s+web|google)\s+for|web\s+search\s+for)\s+(?<q>.+)$/,build:({verb:e,q:t})=>{let n=t.trim();return e===`google`&&n.split(` `).length<2?null:nw({url:`https://www.google.com/search?q=${encodeURIComponent(n)}`},`Search the web for "${n}"`,e===`google`?.95:1)}},{id:`site.search`,action:Zd.name,certainty:.95,pattern:/^search\s+(?:(?:on|in)\s+)?(?:(?:this|the)\s+(?:site|website)|here)\s+for\s+(?<q>.+)$/,build:({q:e})=>{let t=e.trim();return t?tw({query:t},`Search this site for "${t}"`):null}},{id:`scroll.direction`,action:Yd.name,certainty:.95,pattern:/^(?:scroll|jump|move|go)(?:\s+(?:to|down\s+to|back\s+to|all\s+the\s+way\s+to))?\s+(?:the\s+)?(?<dir>up|down|top|bottom)(?:\s+of\s+(?:the\s+)?page)?$/,build:({dir:e})=>iw({direction:e},`Scroll ${e}`)},{id:`scroll.page`,action:Yd.name,certainty:.95,pattern:/^page\s+(?<dir>up|down)$/,build:({dir:e})=>iw({direction:e},`Scroll ${e}`)},{id:`scroll.element`,action:Yd.name,certainty:.85,pattern:/^scroll\s+(?:down\s+)?to\s+(?:the\s+)?(?<label>.+)$/,build:({label:e})=>{let t=aw(e);return t&&iw({target:{text:t.value}},`Scroll to ${t.value}`,t.confidence)}},{id:`key.press`,action:nd.name,certainty:.97,pattern:RegExp(`^(?:press|hit|tap|push)(?:\\s+the)?\\s+(?<key>${XC})(?:\\s+key)?$`),build:({key:e})=>{let t=YC[e];return t?tw({key:t},`Press ${e}`):null}},{id:`recording.start`,action:pp,certainty:.95,pattern:/^(?:start\s+record(?:ing)?(?:\s+(?:my|this|the))?(?:\s+(?:browsing|browser))?(?:\s+session)?|record(?:ing)?(?:\s+(?:my|this|the))?(?:\s+(?:browsing|browser))?\s+session)$/,build:()=>tw({captureValues:!1},`Start recording this session`)},{id:`recording.stop`,action:mp,certainty:.95,pattern:/^(?:stop|end|finish)\s+(?:the\s+)?recording$/,build:()=>tw({},`Stop recording`)},{id:`monitor.stop`,action:xf.name,certainty:.95,pattern:/^(?:stop|end|quit|cancel)\s+(?:the\s+)?(?:monitor(?:ing)?|watching)(?:\s+(?:the|this|that)\s+\S{1,20})?$/,build:()=>tw({},`Stop monitoring`)},{id:`click.text`,action:Lc.name,certainty:.9,pattern:/^(?:click|tap|press|hit|push)(?:\s+on)?(?:\s+the)?\s+(?<label>.+?)(?:\s+(?<role>button|link|tab|checkbox))?$/,build:({label:e,role:t})=>{let n=aw(e);return!n||!t&&JC.has(n.value.toLowerCase())?null:{input:{target:t?{text:n.value,role:t}:{text:n.value}},label:`Click ${n.value}`,confidence:n.confidence,risky:ZC.test(n.value)}}}],tw=(e,t,n=1)=>({input:e,label:t,confidence:n}),nw=(e,t,n=1)=>tw(e,t,n),rw=(e,t,n=1)=>tw(e,t,n),iw=(e,t,n=1)=>tw(e,t,n);function aw(e){let t=e.trim();if(!t)return null;let n=t.split(/\s+/);if(n.length>$C)return null;if(QC.test(t))return{value:t,confidence:.55};let r=1;return n.length>4&&(r-=.12*(n.length-4)),t.length<2&&(r-=.4),{value:t,confidence:Math.max(0,r)}}function ow(e){return/^https?:\/\/\S+$/.test(e)?e:/^localhost(?::\d+)?(?:\/\S*)?$/.test(e)?`http://${e}`:/^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z]{2,}(?::\d+)?(?:\/\S*)?$/.test(e)?`https://${e}`:null}var sw=/^(?:what|whats|why|how|who|when|where|which|is|are|was|were|do|does|did|can|could|should|would|tell|explain|describe|summarize|summarise|read|find|show|check|look|see|list|compare|help|write|draft|fill)\b/,cw=/\b(?:and then|then|after that|and also|followed by)\b/,lw=/\b(?:if|unless|whenever|maybe|might|try to|see if|as soon as|in case|otherwise)\b/;function uw(e){let t=KC(e);if(t.raw.startsWith(`@`))return dw(`skill-prefix`,0);if(!t.text)return dw(`no-match`,0);if(t.question||sw.test(t.text))return dw(`question`,0);if(cw.test(t.text))return dw(`multi-step`,0);if(lw.test(t.text))return dw(`conditional`,0);let n=null;for(let e of ew){let r=e.pattern.exec(t.text);if(!r)continue;let i=e.build(r.groups??{});if(!i)continue;let a=fw(e.certainty*i.confidence);(!n||a>n.score)&&(n={rule:e,score:a,label:i.label,input:i.input,risky:i.risky===!0})}return n?n.risky?dw(`consequential`,n.score,n.rule.id):n.score<.75?dw(`below-threshold`,n.score,n.rule.id):{decision:`act`,intent:{ruleId:n.rule.id,action:n.rule.action,input:n.input,label:n.label,score:n.score}}:dw(`no-match`,0)}var dw=(e,t,n)=>({decision:`escalate`,reason:e,score:t,ruleId:n}),fw=e=>Math.round(e*1e3)/1e3;async function pw(e,t,n){let r=uw(e);if(r.decision!==`act`)return!1;let{action:i,input:a,label:o,ruleId:s,score:c}=r.intent,l=`local-${crypto.randomUUID()}`;t({kind:`tool`,toolId:l,action:i,input:a,source:`local`});let u=Date.now(),d=await mw(i,a,n),f=Date.now()-u;return t({kind:`toolResult`,toolId:l,ok:d.ok,summary:d.ok?`${o} · ${f} ms`:`${d.error.code}: ${d.error.message}`}),d.ok||hw(i)?!0:(console.debug(`[browsentic] fast path ${s} (${c}) failed, escalating:`,d.error.code),!1)}async function mw(e,t,n){return e===pp?$v(t?.captureValues===!0):e===mp?ny(`user`):RS(e,t,n)}function hw(e){return e===pp||e===mp}var gw=`browsentic/indicator`,_w=`#ff7a3d`,vw=`browsentic/rail`;function yw(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.channel===`browsentic/rail`&&(t.op===`open`||t.op===`sync`)}var bw=`browsentic/panelCollapsed`,xw=`browsentic/panelTab`;async function Sw(){return(await t.storage.local.get(bw))[bw]===!0}async function Cw(){let e=(await t.storage.local.get(xw))[xw];return typeof e==`string`?e:`chat`}function ww(e){return t.sidePanel.open({windowId:e})}var Tw=`browsentic/daemon`;async function Ew(e){await t.storage.local.set({[bw]:e}),await Aw()}var Dw=null,Ow=!1,kw=null;function Aw(){return Dw?(Ow=!0,Dw):(Dw=(async()=>{do Ow=!1,await Mw();while(Ow);Dw=null})(),Dw)}async function jw(){await Sw()||(kw=null,await Aw())}async function Mw(){let e=await Sw();if(!e&&kw===!1)return;let n=e?{channel:vw,op:`show`,view:await Fw()}:{channel:vw,op:`hide`},r=await t.tabs.query({});await Promise.all(r.map(e=>Pw(e.id,e.discarded,n))),kw=e}async function Nw(e){await Sw()&&await Pw(e,!1,{channel:vw,op:`show`,view:await Fw()})}function Pw(e,n,r){if(!(e==null||n))return t.tabs.sendMessage(e,r).catch(()=>void 0)}async function Fw(){let[e,t,n,r,i,a,o,s]=await Promise.all([Lw(),OC(),gC(),Nv(),X(),Cw(),Rw(),Sb()]),c=Object.values(i).filter(e=>e.runId).length,l=Iw(e,c>0);return{tab:a,theme:s,side:o,running:c,tone:l.tone,status:l.label,counts:{history:t.length,skills:n.length,recordings:r.length}}}function Iw(e,t){return e?.paired?e.connected?t?{tone:`busy`,label:`Working`}:{tone:`live`,label:`Online`}:{tone:`pending`,label:`Reconnecting`}:{tone:`off`,label:`Not paired`}}async function Lw(){return(await t.storage.session.get(Tw))[Tw]??null}async function Rw(){let e=t.sidePanel;if(!e.getLayout)return`right`;try{return(await e.getLayout()).side===`left`?`left`:`right`}catch{return`right`}}function zw(){t.runtime.onMessage.addListener((e,n)=>{if(!yw(e))return;let{id:r,windowId:i}=n.tab??{};if(!(r==null||i==null))return e.op===`sync`?(Nw(r),Promise.resolve({ok:!0})):(ww(i).catch(()=>void 0),t.storage.local.set({[xw]:e.tab}),Promise.resolve({ok:!0}))}),t.tabs.onUpdated.addListener((e,t)=>{t.status===`complete`&&Nw(e)}),t.storage.local.onChanged.addListener(e=>{(`browsentic/panelCollapsed`in e||`browsentic/panelTab`in e||`browsentic/theme`in e)&&Aw()}),t.storage.session.onChanged.addListener(e=>{Tw in e&&Aw()})}var Bw=`●`,Vw=new Set;function Hw(){return t.action??null}async function Uw(){let e=new Set;for(let t of Object.values(await X()))if(t.runId)for(let n of t.tabIds)e.add(n);for(let t of e)Vw.has(t)||await Gw(t,!0);for(let t of[...Vw])e.has(t)||await Gw(t,!1);await Aw()}function Ww(e){Vw.delete(e)}async function Gw(e,n){n?Vw.add(e):Vw.delete(e);let r=Hw();if(r)try{await r.setBadgeBackgroundColor({tabId:e,color:_w}),await r.setBadgeText({tabId:e,text:n?Bw:``})}catch{Vw.delete(e)}await t.tabs.sendMessage(e,{channel:gw,op:n?`busy`:`idle`}).catch(()=>void 0)}var Kw=`[redacted]`,qw=200,Jw=20,Yw=4;function Xw(e,t,n){if(typeof t==`string`)return xp({name:e,id:e,value:t})?Kw:t.length>qw?`${t.slice(0,qw)}…`:t;if(typeof t==`number`||typeof t==`boolean`||t===null)return t;if(n>=Yw)return`[…]`;if(Array.isArray(t)){let r=t.slice(0,Jw).map(t=>Xw(e,t,n+1));return t.length>Jw?[...r,`…`]:r}if(typeof t==`object`){let e={};for(let[r,i]of Object.entries(t))e[r]=xp({name:r,id:r})?Kw:Xw(r,i,n+1);return e}return null}var Zw={"page.fillInput":`value`,"page.typeText":`text`},Qw={"page.injectCode":[`purpose`,`code`]};function $w(e,t){if(!t||typeof t!=`object`)return Xw(``,t,0);let n=Xw(``,t,0);for(let r of Qw[e]??[]){let e=t[r];typeof e==`string`&&(n[r]=e)}let r=Zw[e];if(r&&r in n){let e=t[r],i=typeof e==`string`?am(e):[];n[r]=i.length?i.map(e=>e.text).join(` `):Kw}return n}var eT=()=>crypto.randomUUID();function tT(e,t){switch(t.kind){case`started`:{let n=t.attached?` + attached: ${t.attached}`:``,r=t.overlays?.length?` + site notes: ${t.overlays.join(`, `)}`:``;return[...e,{kind:`notice`,id:eT(),tone:`info`,text:`Loaded skill: ${t.skill}${n}${r}`}]}case`text`:{let n=e.at(-1);return n?.kind===`assistant`?[...e.slice(0,-1),{...n,text:n.text+t.delta}]:[...e,{kind:`assistant`,id:eT(),text:t.delta}]}case`tool`:return[...e,{kind:`tool`,id:t.toolId,action:t.action,input:$w(t.action,t.input),source:t.source}];case`approval`:return nT(e,t.toolId,{awaiting:!0,site:t.site});case`toolResult`:return nT(e,t.toolId,{ok:t.ok,summary:t.summary,awaiting:!1});case`session`:case`usage`:return e;case`done`:return t.stopReason===`end_turn`?e:[...e,{kind:`notice`,id:eT(),tone:`info`,text:`Stopped: ${t.stopReason}`}];case`error`:return[...e,{kind:`notice`,id:eT(),tone:`error`,text:`${t.code}: ${t.message}`}]}}function nT(e,t,n){return e.map(e=>e.kind===`tool`&&e.id===t?{...e,...n}:e)}function rT(e,t){for(let n=e.length-1;n>=0;n--){let r=e[n];if(r.kind===`tool`&&r.action===Jd.name&&!r.preview){let i=[...e];return i[n]={...r,preview:t},i}}return e}function iT(e,t){return{kind:`notice`,id:eT(),tone:e,text:t}}function aT(e){let t=e.label??e.host,n=oT(e.elapsedMs);switch(e.phase){case`done`:return{tone:`info`,text:`Monitor “${t}” finished after ${n}.`};case`stopped`:return{tone:`info`,text:`Monitor “${t}” stopped.`};case`timeout`:return{tone:`error`,text:`Monitor “${t}” gave up after ${n} without completing.`};case`tab-closed`:return{tone:`error`,text:`Monitor “${t}” ended — the tab was closed.`};default:return{tone:`error`,text:`Monitor “${t}” ended — ${e.message??`the tab left the watched site.`}`}}}function oT(e){let t=Math.floor(e/1e3);return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}var sT=`local`,cT=4e3,lT=800,uT=new Set,dT=new Set,fT=new Set,Z=new Map,pT=new Set,mT=new Map,hT=new Map,gT=[],_T=new Map,vT=new Map,yT=Promise.resolve();function Q(e){let t=yT.then(e,e);return yT=t.catch(()=>void 0),t}function bT(){l_((e,t)=>{Q(()=>ET(e,t))}),Bx((e,t)=>{Q(async()=>{let n=t?await OS(t):null;if(n){let t=rT(await IT(n.sessionId),e);Z.set(n.sessionId,t)}$({op:`preview`,sessionId:n?.sessionId,preview:e})})}),eg(e=>{vT.set(e.toolkitId,e),$({op:`toolOffer`,offer:e})}),Fb(e=>{$({op:`monitor`,state:e}),e.phase!==`watching`&&(Q(async()=>{let t=e.tabId==null?null:await DS(e.tabId);t&&await LT(t.sessionId,iT(...YT(e)))}),uT.size>0&&nx(e.monitorId))}),px((e,t,n)=>Q(async()=>{let r=(await X())[e];return r?r.runId||pT.has(e)?`busy`:(await LT(e,iT(`info`,`Timer “${n}” fired.`)),await kT(r,t,{fastPath:!1}),`delivered`):`gone`})),c_((e,t)=>{Q(async()=>{let n=await OS(e);if(n)for(let[e,t]of _T)t.sessionId===n.sessionId&&_T.delete(e);_T.set(t.stagingId,{sessionId:n?.sessionId,draft:t}),$({op:`mapDraft`,sessionId:n?.sessionId,draft:t})})}),u_(()=>{Q(async()=>{for(let e of Object.values(await X()))e.runId&&await MT(e.sessionId,`The connection to the daemon dropped, so that run is over.`)})}),qv(e=>{e?.warning&&$({op:`event`,runId:sT,event:{kind:`error`,code:`RECORDING_LIMIT`,message:e.warning}}),$({op:`recording`,state:e})}),t.runtime.onConnect.addListener(e=>{if(e.name===`browsentic/run`){if(uT.add(e),e.sender?.url?.includes(`sidepanel.html`)&&(dT.add(e),dT.size===1))for(let e of fT)e(!0);for(let t of _T.values())QT(e,{op:`mapDraft`,sessionId:t.sessionId,draft:t.draft});Zv().then(t=>QT(e,{op:`recording`,state:t})),Hh().then(t=>QT(e,{op:`tools`,tools:t.map(Vh)})),ex().then(t=>{for(let n of t)QT(e,{op:`monitor`,state:n})}),tx().then(t=>{if(t.length){for(let n of t)QT(e,{op:`monitor`,state:n});nx()}}),e.onMessage.addListener(e=>CT(e)),e.onDisconnect.addListener(()=>{if(uT.delete(e),dT.delete(e)&&dT.size===0)for(let e of fT)e(!1)})}})}function xT(e){fT.add(e)}function ST(){for(let e of dT)QT(e,{op:`close`})}function CT(e){switch(e.op){case`instruct`:Q(()=>OT(e.text,e.tab,e.agentSkillId,e.focus,e.liveTools));return;case`cancel`:Q(()=>jT(e.sessionId));return;case`decision`:Q(async()=>{let t=(await X())[e.sessionId];t?.runId&&(Z.set(e.sessionId,nT(await IT(e.sessionId),e.toolId,{awaiting:!1})),await NS(e.sessionId,{pendingApproval:void 0}),U_(t.runId,e.toolId,e.allow,e.remember))});return;case`endSession`:Q(()=>PT(e.sessionId));return;case`replay`:Q(async()=>{$({op:`items`,sessionId:e.sessionId,items:await IT(e.sessionId)})});return;case`restore`:Q(()=>FT(e.sessionId,e.tab));return;case`activateMap`:case`discardMap`:{let t=_T.get(e.stagingId);(e.op===`activateMap`?E_(e.stagingId,e.exactHost):D_(e.stagingId)).then(n=>{if(n.ok&&e.op===`activateMap`&&t){let{draft:n}=t;SC({name:n.name,domain:e.exactHost?n.host:n.domain,directory:n.directory,pages:n.pages,generatedAt:n.generatedAt})}_T.delete(e.stagingId),$({op:`mapSettled`,sessionId:t?.sessionId,stagingId:e.stagingId,ok:n.ok,message:n.ok?void 0:`${n.error.code}: ${n.error.message}`})});return}case`startRecording`:VT(e.captureValues);return;case`stopRecording`:ny(`user`);return;case`stopMonitor`:Xb(e.monitorId);return;case`keepTool`:Q(async()=>{let t=vT.get(e.toolkitId),n=t?await lg(e.tabId,e.toolkitId):null;t&&n&&await zC({offer:t,code:n,slug:e.slug}).catch(()=>void 0),vT.delete(e.toolkitId),$({op:`toolOfferSettled`,toolkitId:e.toolkitId}),await TT()});return;case`dismissTool`:vT.delete(e.toolkitId),$({op:`toolOfferSettled`,toolkitId:e.toolkitId});return;case`forgetTool`:Q(async()=>{await BC(e.id),await TT()});return;case`runTool`:Q(async()=>{let t=await cg(e.tab.tabId,e.tab.url,e.id);$({op:`item`,item:wT(e.id,t)})});return;case`listTools`:TT();return}}function wT(e,t){return t.ok?{kind:`tool`,id:eT(),action:`savedTool`,input:{tool:e},ok:!0,source:`local`}:iT(`error`,`${t.error?.code}: ${t.error?.message}`)}async function TT(){$({op:`tools`,tools:(await Hh()).map(Vh)})}async function ET(e,t){if(e===`external`){gT=tT(gT,t).slice(-100),$({op:`event`,runId:e,event:t});return}let n=await OS(e);if(!n)return;let{sessionId:r}=n;Z.set(r,tT(await IT(r),t)),$({op:`event`,sessionId:r,runId:e,event:t}),t.kind===`session`?await NS(r,{agent:t.agent,agentSessionId:t.agentSessionId??void 0}):t.kind===`approval`?await NS(r,{pendingApproval:{toolId:t.toolId,action:t.action,input:t.input,site:t.site}}):t.kind===`toolResult`?await NS(r,{pendingApproval:void 0}):t.kind===`usage`&&await NS(r,{usage:t.usage}),t.kind===`done`||t.kind===`error`?await DT(r):RT(r)}async function DT(e){clearTimeout(hT.get(e)),hT.delete(e),await eb(e),await NS(e,{runId:null,pendingApproval:void 0}),await Uw();let n=(await X())[e];if(n){let r=await t.tabs.get(n.currentTabId).catch(()=>null);r?.url&&await NS(e,{url:r.url,host:LS(r.url)})}await zT(e);let r=(await OC()).find(t=>t.id===e);!r||IC(r.turns,r.titledAtTurn)===null||await FC(e).catch(()=>void 0)}async function OT(e,t,n,r,i){let a=await kS(t);if(!a.ok){$({op:`event`,runId:sT,event:{kind:`error`,code:`SESSION_LIMIT`,message:a.message}});return}if(RC(e)){let{sessionId:e}=a.session,t=await JT(a.session,await IT(e));await LT(e,{kind:`user`,id:eT(),text:LC}),await LT(e,{kind:`context`,id:eT(),breakdown:t});return}await kT(a.session,e,{agentSkillId:n,focus:r,liveTools:i,fastPath:!0})===`busy`&&await LT(a.session.sessionId,iT(`error`,`RUN_IN_PROGRESS: This conversation is still running — stop it before sending another instruction.`))}async function kT(e,t,n){let{agentSkillId:r,focus:i,liveTools:a,fastPath:o}=n,{sessionId:s}=e;if(e.runId||pT.has(s))return`busy`;await LT(s,{kind:`user`,id:crypto.randomUUID(),text:t,focus:i&&HT(i)}),await NS(s,{turns:e.turns+1}),pT.add(s);try{if(o&&!r&&!i&&await AT(t,e))return await zT(s),`local`;let n=d_(t,{url:e.url,tabId:e.currentTabId,sessionId:s,agent:e.agent,agentSessionId:e.agentSessionId,agentSkillId:r,focus:i,liveTools:a,files:await GT(),recordings:await qT()});return n?(await NS(s,{runId:n}),await Uw(),`started`):(await LT(s,iT(`error`,`EXTENSION_OFFLINE: No Browsentic daemon is attached, so only quick browser commands work. Pair the browser to do more.`)),await zT(s),`offline`)}finally{pT.delete(s)}}async function AT(e,t){try{return await pw(e,e=>{Z.set(t.sessionId,tT(Z.get(t.sessionId)??[],e)),$({op:`event`,sessionId:t.sessionId,runId:sT,event:e})},t.currentTabId)}catch(e){return console.warn(`[browsentic] fast path threw, escalating:`,e),!1}}async function jT(e){let t=(await X())[e]?.runId;if(t){if(!H_(t)){await MT(e,`The daemon is not connected, so there was nothing left to stop.`);return}clearTimeout(hT.get(e)),hT.set(e,setTimeout(()=>{Q(async()=>{(await X())[e]?.runId===t&&await MT(e,`Stopped. The daemon never confirmed it, so check for a run still finishing there.`)})},cT))}}async function MT(e,t){await LT(e,iT(`error`,`CANCELLED: ${t}`)),await DT(e)}function NT(e){for(let t of _T.values())t.sessionId===e&&(t.sessionId=void 0,$({op:`mapDraft`,draft:t.draft}))}async function PT(e){let t=(await X())[e];t?.runId&&H_(t.runId),await eb(e),await jx(e),clearTimeout(hT.get(e)),hT.delete(e),await zT(e),await PS(e),Z.delete(e),pT.delete(e),NT(e),W_(e),await Uw()}async function FT(e,t){if(Object.values(await X()).find(t=>t.sessionId===e))return;let n=await DS(t.tabId);if(n?.runId){await LT(n.sessionId,iT(`error`,`RUN_IN_PROGRESS: This tab is still running — stop it before opening another conversation here.`));return}n&&(await zT(n.sessionId),await PS(n.sessionId),Z.delete(n.sessionId),NT(n.sessionId));let r=(await OC()).find(t=>t.id===e);if(!r)return;let i=await MC(e);Z.set(e,i?.items??[iT(`error`,`That conversation’s messages are no longer stored.`)]);let a=await AS({sessionId:e,turns:r.turns,agent:r.agent,agentSessionId:r.agentSessionId,usage:r.usage,url:r.url,title:XT(r)??t.title},t);$({op:`items`,sessionId:e,items:Z.get(e)??[]}),r.url&&/^https?:$/.test(ZT(r.url))&&await RS(Bu.name,{url:r.url},a.currentTabId).catch(()=>void 0)}async function IT(e){let t=Z.get(e);if(t)return t;let n=(await MC(e))?.items??[];return Z.set(e,n),n}async function LT(e,t){Z.set(e,[...await IT(e),t]),$({op:`item`,sessionId:e,item:t}),RT(e)}function RT(e){clearTimeout(mT.get(e)),mT.set(e,setTimeout(()=>void Q(()=>zT(e)),lT))}async function zT(e){clearTimeout(mT.get(e)),mT.delete(e);let t=Z.get(e);if(!t?.length)return;let n=(await X())[e],r=n?null:(await OC()).find(t=>t.id===e),i=Date.now();await AC({id:e,turns:n?.turns??r?.turns??0,url:n?.url??r?.url,host:n?.host??r?.host,agent:n?.agent??r?.agent,agentSessionId:n?.agentSessionId??r?.agentSessionId,usage:n?.usage??r?.usage,createdAt:n?.createdAt??r?.createdAt??i,updatedAt:i},t)}function BT(){t.tabs.onRemoved.addListener(e=>{Ww(e),Q(async()=>{let{closed:t}=await FS(e);if(!t)return await Uw();t.runId&&(H_(t.runId),await LT(t.sessionId,iT(`error`,`CANCELLED: The tab was closed, so that run is over.`))),clearTimeout(hT.get(t.sessionId)),hT.delete(t.sessionId),await jx(t.sessionId),await zT(t.sessionId),Z.delete(t.sessionId),pT.delete(t.sessionId),NT(t.sessionId),t.runId&&W_(t.sessionId),await Uw()})}),t.tabs.onReplaced.addListener((e,t)=>{Q(()=>IS(t,e))}),t.tabs.onUpdated.addListener((e,t,n)=>{t.title===void 0&&t.url===void 0||Q(async()=>{let r=await DS(e);if(!r)return;let i={};e===r.mainTabId&&n.title&&n.title!==r.title&&(i.title=n.title),e===r.currentTabId&&t.url&&(i.url=t.url,i.host=LS(t.url)),Object.keys(i).length&&await NS(r.sessionId,i)})})}async function VT(e){let t=await $v(e);t.ok||$({op:`event`,runId:sT,event:{kind:`error`,code:t.error.code,message:t.error.message}})}var HT=e=>[e.role??e.tag,e.label].filter(Boolean).join(` · `),UT=6,WT=2e3;async function GT(){try{return(await dv()).slice(0,UT).map(e=>({id:e.id,name:e.name,mime:e.mime,size:e.size,status:e.status,summary:e.summary,digest:e.digest?.slice(0,WT)}))}catch{return[]}}var KT=8;async function qT(){try{return(await Nv()).filter(e=>e.status===`ready`).slice(0,KT).map(Hv)}catch{return[]}}async function JT(e,t){let n={user:0,assistant:0,tools:0,notices:0,chars:0};for(let e of t)e.kind===`user`?(n.user+=1,n.chars+=e.text.length):e.kind===`assistant`?(n.assistant+=1,n.chars+=e.text.length):e.kind===`tool`?n.tools+=1:e.kind===`notice`&&(n.notices+=1);let r=await dv().catch(()=>[]),i=(await Nv().catch(()=>[])).filter(e=>e.status===`ready`);return{agent:e.agent,resumes:e.agentSessionId!==void 0,usage:e.usage,turns:e.turns,tabCount:e.tabIds.length,host:e.host,messages:n,files:r.slice(0,UT).map(e=>({name:e.name,size:e.size,status:e.status})),filesOmitted:Math.max(0,r.length-UT),recordings:i.slice(0,KT).map(e=>({name:e.name,steps:e.steps})),recordingsOmitted:Math.max(0,i.length-KT),capturedAt:Date.now()}}var YT=e=>{let{tone:t,text:n}=aT(e);return[t,n]},XT=e=>e.title??void 0;function ZT(e){try{return new URL(e).protocol}catch{return``}}function $(e){for(let t of uT)QT(t,e)}function QT(e,t){try{e.postMessage(t)}catch{uT.delete(e)}}var $T=[`claude`,`codex`,`antigravity`],eE={claude:{kind:`claude`,label:`Claude Code`,vendor:`Anthropic`,bin:`claude`,install:`npm i -g @anthropic-ai/claude-code`,docs:`https://claude.com/claude-code`,models:[`claude-fable-5`,`claude-opus-5`,`claude-sonnet-5`,`claude-haiku-4-5`]},codex:{kind:`codex`,label:`Codex`,vendor:`OpenAI`,bin:`codex`,install:`npm i -g @openai/codex`,docs:`https://developers.openai.com/codex/cli`,models:[`gpt-5.6-terra`,`gpt-5.6-luna`,`gpt-5.5`]},antigravity:{kind:`antigravity`,label:`Antigravity`,vendor:`Google`,bin:`agy`,install:`https://antigravity.google/docs/cli/install`,docs:`https://antigravity.google/docs/cli`,models:[`gemini-3-pro`,`gemini-3-flash`]}};$T.map(e=>eE[e]);function tE(e){return typeof e==`string`&&$T.includes(e)}var nE=`open-side-panel`,rE=e(()=>{zm(),t.runtime.onMessage.addListener((e,t,n)=>{if(c(e)){if(e.op===`describe`){n(o(Vf()));return}if(e.op===`invoke`&&typeof e.action==`string`)return RS(e.action,e.input).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`analyzeFile`&&typeof e.fileId==`string`){hv(e.fileId),n(o(!0));return}if(e.op===`saveSkill`&&typeof e.skillId==`string`){bC(e.skillId),n(o(!0));return}if(e.op===`removeSkill`&&typeof e.skillId==`string`){xC(e.skillId),n(o(!0));return}if(e.op===`nameSession`&&typeof e.sessionId==`string`){FC(e.sessionId),n(o(!0));return}if(e.op===`recordEvents`&&Array.isArray(e.events)){ty(t.tab?.id,e.events),n(o(!0));return}if(e.op===`recordingState`)return Qv(t.tab?.id).then(e=>n(o(e))).catch(()=>n(o({recording:!1,captureValues:!1}))),!0;if(e.op===`analyzeRecording`&&typeof e.recordingId==`string`){Rv(e.recordingId),n(o(!0));return}if(e.op===`monitorSample`&&typeof e.monitorId==`string`){Kb(t.tab?.id,e.monitorId,e.sample),n(o(!0));return}if(e.op===`monitorState`)return $b(t.tab?.id).then(n).catch(()=>n(o({monitors:[]}))),!0;if(e.op===`listSkills`)return L_(e.refresh===!0).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`agentState`)return j_(e.refresh===!0).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`setAgent`&&tE(e.agent))return M_(e.agent).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`setAgentModel`&&tE(e.agent))return N_(e.agent,typeof e.model==`string`&&e.model.trim()?e.model:null).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`grantAgent`&&tE(e.agent))return P_(e.agent).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`guardrails`)return z_().then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`setGuardrail`&&typeof e.setting==`string`)return B_(e.setting,e.value).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`pair`&&typeof e.token==`string`)return K_(e.token).then(e=>n(e.ok?o(!0):s(`PAIRING_FAILED`,e.error??`Pairing failed`))).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`panelOpened`){Ew(!1),n(o(!0));return}if(e.op===`disconnect`)return q_().then(()=>n(o(!0))).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;n(s(`INVALID_REQUEST`,`Expected {op:"describe"|"invoke"|"analyzeFile"|"saveSkill"|"removeSkill"|"nameSession"|"recordEvents"|"recordingState"|"analyzeRecording"|"monitorSample"|"monitorState"|"listSkills"|"agentState"|"setAgent"|"setAgentModel"|"grantAgent"|"guardrails"|"setGuardrail"|"pair"|"panelOpened"|"disconnect"}`))}}),t.runtime.onInstalled.addListener(()=>{t.tabs.query({}).then(e=>{for(let t of e)t.id!=null&&!t.discarded&&up(t.id)})});let e=t.contextMenus.removeAll().then(()=>t.contextMenus.create({id:nE,title:`Open Browsentic`,contexts:[`all`]})),n=!1;xT(r=>{n=r,e.then(()=>t.contextMenus.update(nE,{title:r?`Close Browsentic`:`Open Browsentic`})),r||jw()}),t.contextMenus.onClicked.addListener((e,t)=>{if(!(e.menuItemId!==nE||t?.windowId==null)){if(n){ST();return}ww(t.windowId)}}),nb(),Qf(),ig(),ry(),rx(),Mx(),bT(),BT(),zw(),Db(),Aw(),u_(()=>{CC(),zv()}),G_(),t.runtime.onStartup.addListener(()=>void G_()),t.alarms.create(Zg,{periodInMinutes:1}),t.alarms.onAlarm.addListener(e=>{e.name===`browsentic/reconnect`&&G_()})}),iE={debug:(...e)=>([...e],void 0),log:(...e)=>([...e],void 0),warn:(...e)=>([...e],void 0),error:(...e)=>([...e],void 0)},aE;try{aE=rE.main(),aE instanceof Promise&&console.warn(`The background's main() function return a promise, but it must be synchronous`)}catch(e){throw iE.error(`The background crashed on startup!`),e}return aE})();