browsentic 0.4.14 → 0.4.15

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 Rd(e,t,n){if(!document.documentElement.hasAttribute(`data-browsentic-toolkit`))throw new L(`No toolkit is installed in this page.`,Fd);let r=crypto.randomUUID();return new Promise((i,a)=>{let o=e=>{let t=zd(e.detail);t?.id===r&&(c(),t.ok?i(t.value??null):a(new L(t.error??`The function threw.`,Id)))},s=setTimeout(()=>{c(),a(new L(`“${e}” did not finish within ${n}ms.`,`TIMEOUT`))},n);function c(){clearTimeout(s),window.removeEventListener(Nd,o)}window.addEventListener(Nd,o),window.dispatchEvent(new CustomEvent(Md,{detail:JSON.stringify({id:r,fn:e,args:t})}))})}function zd(e){if(typeof e!=`string`)return null;try{return JSON.parse(e)}catch{return null}}var Bd=I({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:P({function:A().min(1).describe("Name of a function the installed toolkit assigned onto `tools`."),args:Qa(Ja()).default([]).describe(`Arguments passed to the function, in order. JSON values only — this is where per-call data like a tag name belongs.`),timeoutMs:M().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 Rd(e,t,n)}}}),Vd=I({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:P({target:B.optional().describe(`Capture only this element’s box (a specific block). When set, fullPage is ignored.`),fullPage:N().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:F([`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:M().int().min(1).max(100).optional().describe(`JPEG quality, 1–100, defaulting to 80. Only valid when format is "jpeg".`),maxLongSide:M().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:N().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:A().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 L(`"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=uc(V(e));if(t.width===0||t.height===0)throw new L(`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}}}),Hd=I({name:`page.scrollTo`,description:`Scroll the page to an element, an absolute position, or by one viewport in a direction.`,input:P({target:B.optional().describe(`Element to bring into view`),position:P({x:M().default(0).describe(`Document x coordinate`),y:M().describe(`Document y coordinate`)}).optional().describe(`Absolute document coordinates to scroll to`),direction:F([`up`,`down`,`top`,`bottom`]).optional().describe(`Scroll one viewport up or down, or jump to an edge`),behavior:F([`smooth`,`instant`]).default(`smooth`).describe(`Animation of the scroll`)}),async execute({target:e,position:t,direction:n,behavior:r}){if(e)V(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 Ud(),{scrollX:Math.round(window.scrollX),scrollY:Math.round(window.scrollY)}}});function Ud(){return new Promise(e=>{let t=()=>{window.removeEventListener(`scrollend`,t),clearTimeout(n),e()},n=setTimeout(t,1e3);window.addEventListener(`scrollend`,t)})}var Wd=I({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:P({query:A().min(1).max(200).describe(`What to look for on this site`),strategy:F([`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:B.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=Gd(n),i=t===`field`?null:Ql(r,e);if(i){if(i.url.origin!==location.origin)throw Jd(i.url.href);return location.assign(i.url.href),{searchedFor:e,via:`url`,templateFrom:i.from,navigatingTo:i.url.href,field:r?eu(r):void 0}}if(t===`url`)throw new L(`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 Kd(r,e)}});function Gd(e){return e?Jl(V(e,{includeHidden:!0})):ql(Kl())}function Kd(e,t){if(!e)throw new L(`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 L(`The search box on this page is hidden${qd()}.`,`TARGET_NOT_FOUND`);let n=e.form?.getAttribute(`action`),r=n&&new URL(n,location.href);if(r&&r.origin!==location.origin)throw Jd(r.href);e.element.focus();let{submitted:i}=Cl(e.element,t,{clear:!0,pressEnter:!0});return{searchedFor:t,via:`field`,submitted:i,field:eu(e)}}function qd(){let e=Yl(Kl())[0];return e?` — click ${H(e)} to reveal it, then search again`:`, and nothing on the page reveals it`}function Jd(e){return new L(`This site hands its search to another host. Open ${e} with page.navigate instead, so it goes through the usual checks.`,`UNSUPPORTED`)}var Yd=I({name:`page.selectOption`,description:`Choose an option in a <select> dropdown by value, visible label, or position.`,input:P({target:B.describe(`The select element`),value:A().optional().describe(`Match by option value`),label:A().optional().describe(`Match by visible option text, case-insensitive`),index:M().int().nonnegative().optional().describe(`Match by option position`)}),execute({target:e,value:t,label:n,index:r}){let i=V(e);if(!(i instanceof HTMLSelectElement))throw new L(`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 L(`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 L(`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}}}}),Xd=I({name:`page.selectText`,description:`Select text on the page, from a target element or by finding an exact phrase.`,input:P({target:B.optional().describe(`Element whose entire text content to select`),search:A().optional().describe(`Exact text to find and select, case-insensitive`),occurrence:M().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 L(`Provide either "target" or "search"`,`INVALID_INPUT`);let r=document.createRange();if(e)r.selectNodeContents(V(e));else if(t){let e=Zd(),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 L(`Text "${t}" not found on the page`,`TARGET_NOT_FOUND`);r.setStart(...Qd(e,o)),r.setEnd(...Qd(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 Zd(){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`)||!oc(e)||(t.push({node:r,start:n}),n+=r.data.length)}return t}function Qd(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 $d=I({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:P({waitMs:M().int().min(0).max(12e4).default(2e4).describe(`How long to wait after clicking for the widget to report a verdict.`),timeoutMs:M().int().min(1e3).max(18e4).default(6e4).describe(`Overall budget for the whole attempt, including finding the widget.`)}),execute(){throw new L(`page.solveCaptcha is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),ef=I({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:P({capture:Qa(F([`console`,`network`])).default([`console`,`network`]).describe(`What to record. Narrow it to one when the other would only add noise.`),reload:N().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:M().int().optional().describe(`Tab to record, from page.openTab or page.switchTab. Defaults to the active tab.`),timeoutMs:M().int().min(Qu).max(ed).default($u).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 L(`page.startDiagnostics is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),tf=I({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:P({until:P({kind:F([`element-appears`,`element-vanishes`,`text-matches`,`progress-reaches`,`title-matches`]).describe(`What ends the watch`),target:B.optional().describe(`Element to watch — required for element-appears, element-vanishes and progress-reaches; optional scope for text-matches`),pattern:A().max(200).optional().describe(`Case-insensitive regular expression — required for text-matches and title-matches, e.g. "upload complete|processing finished"`),threshold:M().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:A().max(80).optional().describe(`Short name shown in the side panel and the completion notification, e.g. "YouTube upload"`),tabId:M().int().optional().describe(`Tab to watch, from page.openTab or page.switchTab. Defaults to the active tab.`),timeoutMs:M().int().positive().max(yc).default(vc).describe(`Give up and report a timeout after this long`)}),execute(){throw new L(`page.startMonitor is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),nf=3e4,rf=1440*6e4,af=2e3,of=6e4,sf=`browsentic/timer:`,cf=e=>`${sf}${e}`,lf=`browsentic-timer:`;function uf(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 df(e){return e.repeat?`every ${uf(e.afterMs)}, up to ${e.maxRuns} times`:`once in ${uf(e.afterMs)}`}var ff=I({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:P({prompt:A().min(1).max(af).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:M().int().min(nf).max(rf).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:N().default(!1).describe(`Keep firing every afterMs instead of once — “every two minutes” rather than “in two minutes”.`),maxRuns:M().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:A().max(80).optional().describe(`Short name shown in the side panel and in notifications, e.g. “deploy check”.`),deliver:F([`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 L(`page.startTimer is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),pf=I({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:P({diagnosticsId:A().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 L(`page.stopDiagnostics is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),mf=I({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:P({monitorId:A().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 L(`page.stopMonitor is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),hf=I({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:P({timerId:A().optional().describe(`Omit when only one timer is scheduled; with several an omitted id stops nothing and the candidates are listed.`)}),execute(){throw new L(`page.stopTimer is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),gf=I({name:`page.submitForm`,description:`Submit a form, firing its submit event and validation as if the user pressed Enter.`,input:P({target:B.optional().describe(`The form, or any element inside it; defaults to the first form on the page`)}),execute({target:e}){let t=e?V(e).closest(`form`):document.querySelector(`form`);if(!t)throw new L(`No form found to submit`,`TARGET_NOT_FOUND`);return typeof t.requestSubmit==`function`?t.requestSubmit():t.submit(),{form:H(t),action:t.getAttribute(`action`)||void 0,method:(t.getAttribute(`method`)||`get`).toLowerCase()}}}),_f=I({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:P({tabId:M().int().optional().describe(`Id of the tab to switch to, as reported by page.openTab or a no-argument page.switchTab.`),match:A().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 L(`page.switchTab is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),vf=I({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:P({timerId:A().optional().describe(`One timer to report. Omit to list every scheduled and recently finished timer.`)}),execute(){throw new L(`page.timerStatus is resolved by the Browsentic extension, not in the page`,`UNSUPPORTED`)}}),yf=I({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:P({target:B.optional().describe(`Element to click. Give this or "point", never both.`),point:Bc.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:F([`left`,`right`,`middle`]).default(`left`).describe(`Mouse button to press`),clickCount:M().int().min(1).max(3).default(1).describe(`1 for a single click, 2 for a double click, 3 for a triple click`),modifiers:Qa(F([`ctrl`,`shift`,`alt`,`meta`])).default([]).describe(`Modifier keys held during the click, e.g. ["meta"] to open a link in a new tab`),scrollIntoView:N().default(!0).describe(`Bring the element into view before clicking. Ignored with "point".`),moveSteps:M().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:M().int().min(0).max(2e3).default(60).describe(`Pause on the target after arriving, before pressing.`),holdMs:M().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 L(`Give either a "target" to click or a "point" to click at — not both, not neither`,`INVALID_INPUT`);let l=e?V(e):null;l&&a&&l.scrollIntoView({block:`center`,behavior:`instant`});let u=l?Hc(l):Uc(t);l&&Kc(l,u);let d=Gc(u);return{...l?U(l):{over:d?H(d):void 0},point:u,from:Wc(u),button:n,clickCount:r,modifiers:i,moveSteps:o,hoverMs:s,holdMs:c,submits:l?dc(l):!1}}}),bf={slow:400,natural:220,fast:110,instant:0},xf={".":3,"?":3,"!":3,"\n":2.5,",":2,";":2,":":2},Sf=12e4,Cf=(e,t)=>[...e].map(e=>t*(xf[e]??1)),wf=(e,t)=>Math.round(e.reduce((e,t)=>e+t,0)*(1+t)),Tf=e=>new Promise(t=>setTimeout(t,e)),Ef=I({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:P({target:B.optional().describe(`Element to type into; defaults to the currently focused element`),text:A().min(1).max(2e3).describe(`Text to type, character by character`),speed:F([`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:M().int().min(0).max(2e3).optional().describe(`Average milliseconds between keystrokes; overrides "speed" when given`),jitter:M().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:N().default(!0).describe(`Replace existing content instead of appending`),pressEnter:N().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?V(e):document.activeElement??document.body;if(!(s instanceof HTMLInputElement||s instanceof HTMLTextAreaElement)&&!s.isContentEditable)throw new L(`<${s.tagName.toLowerCase()}> is not an editable element`,`INVALID_TARGET`);if(t.includes(`
182
182
  `)&&s instanceof HTMLInputElement)throw new L(`A single-line <input> cannot take newlines — drop them from "text", or set pressEnter to submit`,`INVALID_INPUT`);let c=r??bf[n],l=Cf(t,c),u=wf(l,i);if(u>Sf)throw new L(`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&&Of(s),kf(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 Tf(n),jf(s,t)}let p=!1;if(o){let e=xl(`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:U(s),typed:f.length,charDelayMs:c,elapsedMs:Math.round(performance.now()-d),appended:!a,submitted:p}}});function Df(e,t){let n=e instanceof HTMLInputElement?HTMLInputElement.prototype:HTMLTextAreaElement.prototype;Object.getOwnPropertyDescriptor(n,`value`)?.set?.call(e,t)}function Of(e){e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement?Df(e,``):e.textContent=``,e.dispatchEvent(new InputEvent(`input`,{bubbles:!0,inputType:`deleteContentBackward`}))}function kf(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 Af(e,t){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){let n=e.selectionStart??e.value.length,r=e.selectionEnd??e.value.length;Df(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 jf(e,t){let n=xl(t===`
183
- `?`Enter`:t);e.dispatchEvent(new KeyboardEvent(`keydown`,n))&&(e.dispatchEvent(new KeyboardEvent(`keypress`,n)),Af(e,t)),e.dispatchEvent(new KeyboardEvent(`keyup`,n))}var Mf=I({name:`page.waitForElement`,description:`Wait until an element reaches a state: attached, visible, hidden, or detached.`,input:P({target:B.describe(`Element to wait for`),state:F([`attached`,`visible`,`hidden`,`detached`]).default(`visible`).describe(`State to wait for: present in the DOM, present and visible, invisible or absent, or absent`),timeoutMs:M().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 V(e,{includeHidden:!0})}catch(e){if(e instanceof L&&e.code===`INVALID_TARGET`)throw e;return null}},i=e=>({attached:!!e,visible:!!e&&oc(e),hidden:!e||!oc(e),detached:!e})[t],a=performance.now(),o=r();return i(o)?{state:t,elapsedMs:0,element:o?U(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 L(`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?U(o):void 0})}}),Nf=new Map([pu,Hd,Ic,yf,Tl,$d,wu,sl,uu,Sl,Ef,Yd,Xd,vl,Ju,Yu,gf,Mf,Tu,Bd,ku,Nc,kl,lu,gd,mc,Vs,ef,dd,fd,pf,tf,Au,Mc,mf,ff,vf,hf,Cu,Wd,Nu,Pu,_f,Lc,Vd,Du,fc,Pc,Eu,Ou,pd].map(e=>[e.name,e]));function Pf(){return[...Nf.values()].map(({name:e,description:t,input:n})=>({name:e,description:t,inputSchema:$i(n,{io:`input`})}))}var Ff=`Receiving end does not exist`,If=new Set([`page.getPageInfo`,`page.extractText`,`page.waitForElement`,`page.navigate`]);async function W(e,r,...[i]){let a=typeof r==`string`?r:r.name,o=async()=>await t.tabs.sendMessage(e,{channel:n,action:a,input:i});try{return await o()}catch(t){let n=t instanceof Error?t.message:String(t);if(!n.includes(Ff)||!await Rf(e))return Bf(n);if(!If.has(a))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 o()}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 Lf=5e3;async function Rf(e){let n=(t.runtime.getManifest().content_scripts??[]).flatMap(e=>e.js??[]);if(!n.length)return!1;try{return await zf(t.scripting.executeScript({target:{tabId:e},files:n,injectImmediately:!0})),!0}catch{return!1}}function zf(e){return Promise.race([e,new Promise((e,t)=>setTimeout(()=>t(Error(`injection timed out`)),Lf))])}var Bf=e=>s(`TAB_UNREACHABLE`,`${e} — the page may not allow content scripts`),Vf=`browsentic.`;`${Vf}`;var Hf=`${Vf}startRecording`,Uf=`${Vf}stopRecording`;`${Vf}`,`${Vf}`;var Wf=`browsentic/record`,Gf=2e3,Kf=15*6e4,qf=13*6e4,Jf=/pass|ssn|card|cvv|cvc|otp|secret|token|pin\b/i,Yf=/cc-|new-password|current-password|one-time-code/i;function Xf(e){let t=(e.type??``).toLowerCase();return t===`password`||t===`hidden`||Yf.test(e.autocomplete??``)||Jf.test(e.name??``)||Jf.test(e.id??``)?!0:Zf(e.value??``)}function Zf(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 Qf(e){try{return new URL(e).hostname.toLowerCase()}catch{return``}}function $f(e){try{return new URL(e).origin}catch{return``}}var ep={head:0,tail:0},tp=[[`pass`,`word`],[`pass`,`wd`],[`pass`,`phrase`],[`pass`,`code`],[`pwd`],[`otp`],[`one`,`time`,`code`]],np=[[`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`]],rp=[[`cookie`],[`session`,`id`],[`session`,`key`],[`session`,`token`],[`csrf`,`token`],[`xsrf`,`token`]],ip=e=>e.map(e=>e.join(String.raw`[_\-\s]?`)).join(`|`),ap=ip(tp),op=ip(np),sp=ip(rp),cp=[[`password`,tp],[`token`,np],[`cookie`,rp]];function lp(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 cp)if(t.some(e=>n.some(t=>t.endsWith(e.join(``)))))return e;return null}[...tp,...np,...rp].map(e=>e.join(`_`));var up=String.raw`(?:Bearer\s+|Basic\s+|Token\s+)?(?:"([^"\r\n]{4,400})"|'([^'\r\n]{4,400})'|([^\s,;&"'<>{}\[\]]{4,400}))`,dp=e=>new RegExp(String.raw`(?<![A-Za-z0-9])(?:${e})["']?\s*[:=]\s*${up}`,`gi`),fp=String.raw`(?:"([^"\r\n]{4,400})"|'([^'\r\n]{4,400})'|([^\s"'<>]{3,399}[^\s"'<>.,;:!?]))`,pp=e=>new RegExp(String.raw`(?<![A-Za-z0-9])(?:${e})\s+(?:is|are|was|will\s+be)\s*:?\s+${fp}`,`gi`),mp=/\d|[!@#$%^&*()_+=\[\]{}|\\<>~/&]|[a-z][A-Z]/;function hp(e){return e.length>=6&&_p(e)&&mp.test(e)}var gp=/^(?: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 _p(e){return gp.test(e)||/^(.)\1*$/.test(e)?!1:!e.includes(`…`)}var vp=[{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:dp(ap),validate:_p},{id:`labelled-token`,kind:`token`,pattern:dp(op),validate:_p},{id:`labelled-cookie`,kind:`cookie`,pattern:dp(sp),validate:_p},{id:`prose-password`,kind:`password`,pattern:pp(ap),validate:hp},{id:`prose-token`,kind:`token`,pattern:pp(op),validate:hp},{id:`card`,kind:`card`,pattern:/\b\d(?:[ -]?\d){12,18}\b/g,reveal:{head:0,tail:4},validate:Zf}],yp=/(?<![A-Za-z0-9+/_=-])[A-Za-z0-9+/_-]{32,4096}={0,2}(?![A-Za-z0-9+/_-])/g,bp=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,xp=4.3,Sp=.5,Cp=/\bdata:[^\s;,]{0,80};base64,[A-Za-z0-9+/=]+/g;function wp(e,t=[]){if(!e)return[];let n=[...t,...Ap(e,Cp)].sort((e,t)=>e.start-t.start),r=e.toLowerCase(),i=[],a=e=>{jp(n,e)||(n.push(e),n.sort((e,t)=>e.start-t.start),i.push(e))};for(let t of vp)if(!(t.guard&&!r.includes(t.guard)))for(let n of e.matchAll(t.pattern)){let e=Tp(n);e&&(t.validate&&!t.validate(e.value)||a({...e,kind:t.kind,shape:t.id,reveal:t.reveal??ep}))}for(let t of e.matchAll(yp)){let e=t[0];Ep(e)&&a({start:t.index,end:t.index+e.length,value:e,kind:`secret`,shape:`high-entropy`,reveal:ep})}return i.sort((e,t)=>e.start-t.start)}function Tp(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 Ep(e){return e.length<32||bp.test(e)||/^[0-9a-f]+$/i.test(e)||!/[a-z]/.test(e)||!/[A-Z]/.test(e)||!/[0-9]/.test(e)?!1:kp(e)>=xp&&Dp(e)>=Sp}function Dp(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)Op(t[e])!==Op(t[e-1])&&(n+=1);return n/(t.length-1)}var Op=e=>e===e.toUpperCase();function kp(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 Ap(e,t){return[...e.matchAll(t)].map(e=>({start:e.index,end:e.index+e[0].length}))}function jp(e,t){return e.some(e=>t.start<e.end&&e.start<t.end)}var Mp=/⟦([a-z-]+):([0-9a-z]+)(?:@([A-Za-z0-9._:\[\]-]{1,255}))?#([0-9a-f]{6,32})⟧/g;function Np(e,t){let n=e.origin?`@${e.origin}`:``;return`⟦${e.kind}:${e.id}${n}#${t}⟧`}function Pp(e,t){return e.includes(`⟦`)?[...e.matchAll(Mp)].map(e=>({kind:e[1],id:e[2],origin:e[3],tag:e[4],text:e[0]})).filter(e=>!t||e.tag===t):[]}function Fp(e,t){if(!e||e.length<4)return{value:e,found:[]};let n=Vp(e,t.tag),r=t.tag?Hp(e,n):e,i=wp(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)+Bp(e.value,e.reveal,n),s=e.end}return{value:o+r.slice(s),found:a}}var Ip=new Set([`selector`]),Lp=4;function Rp(e,t){let n=[],r=(e,r)=>{let i=wp(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:ep},o=t.mint(e,a.kind,a.shape);return n.push({kind:a.kind,shape:a.shape,handle:o}),Bp(e,a.reveal,o)},i=(e,a,o)=>{if(typeof e==`string`){if(e.startsWith(`data:`))return e;if(o&&e.length>=Lp&&_p(e)&&!Pp(e).length)return r(e,o);let i=Fp(e,t);return n.push(...i.found),i.value}if(a>=Up||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]=Ip.has(t)?n:i(n,a+1,lp(t));return s};return{value:i(e,0,null),found:n}}function zp(e,t,n){let r=[],i=[];return{text:e.replace(Mp,(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 Bp(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 Vp(e,t){return e.includes(`⟦`)?[...e.matchAll(Mp)].filter(e=>!t||e[4]===t).map(e=>({start:e.index,end:e.index+e[0].length})):[]}function Hp(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 Up=12,Wp={"page.fillInput":[`value`],"page.typeText":[`text`]},Gp=`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.`,Kp=`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 qp(e){return Wp[e]??[]}function Jp(e,t,n,r){let i=qp(e),a=[],o=[],s=[];if(!t||typeof t!=`object`||Array.isArray(t))return{input:t,released:a,refused:Yp(t,o),unresolved:s};let c={};for(let[e,l]of Object.entries(t)){if(i.includes(e)&&typeof l==`string`){let t=zp(l,n,r);a.push(...t.released),s.push(...t.unresolved),c[e]=t.text;continue}Yp(l,o),c[e]=l}return{input:c,released:a,refused:o,unresolved:s}}function Yp(e,t,n=0){if(typeof e==`string`)t.push(...Pp(e));else if(n<12&&e&&typeof e==`object`)for(let r of Object.values(e))Yp(r,t,n+1);return t}var Xp=`browsentic/secrets`,Zp=120*6e4,Qp=Promise.resolve();function $p(e){let t=Qp.then(e,e);return Qp=t.catch(()=>void 0),t}function em(e,t){return $p(async()=>{let n=await nm(),r=Date.now(),i=n.entries.filter(e=>r-e.at<Zp),a=[],o=Rp(e,{mint:(e,o,s)=>{let c=[...i,...a].find(n=>n.value===e&&n.origin===t);if(c)return c.at=r,Np(c,n.tag);let l={id:om(),value:e,kind:o,shape:s,origin:t,at:r};return a.push(l),Np(l,n.tag)},tag:n.tag});return(a.length||i.length!==n.entries.length)&&await rm({tag:n.tag,entries:[...i,...a].slice(-64)}),o})}function tm(e,t){return $p(async()=>{let n=await nm(),r=Date.now(),i=[],a=Jp(e,t,n.tag,e=>{let t=n.entries.find(t=>t.id===e.id);return!t||r-t.at>=Zp?null:(t.at=r,i.push(t),t.value)});return i.length&&await rm(n),a})}async function nm(){let e=(await t.storage.session.get(Xp).catch(()=>({})))[Xp];if(e?.tag&&Array.isArray(e.entries))return{tag:e.tag,entries:e.entries};let n={tag:am(),entries:[]};return await rm(n),n}function rm(e){return t.storage.session.set({[Xp]:e}).catch(()=>void 0)}var im=e=>[...crypto.getRandomValues(new Uint8Array(e))].map(e=>e.toString(16).padStart(2,`0`)).join(``),am=()=>im(8),om=()=>im(4),sm=[{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`}],cm=t.debugger,lm=`1.3`,um=250,dm=150,fm=4,G=e=>new Promise(t=>setTimeout(t,e)),pm=new Set;function mm(){cm.onEvent.addListener((e,t,n)=>{for(let r of pm)r(e,t,n)})}function hm(e){return pm.add(e),()=>pm.delete(e)}async function gm(e){try{return await cm.attach({tabId:e},lm),{ok:!0}}catch(e){return{ok:!1,message:Cm(e)}}}async function _m(e){let t={tabId:e};await K(t,`Target.setAutoAttach`,xm).catch(()=>{}),await cm.detach(t).catch(()=>{})}function vm(e){cm.onDetach.addListener((t,n)=>{t.tabId!=null&&e(t.tabId,n)})}function K(e,t,n){return cm.sendCommand(e,t,n)}async function ym(e,t,n){let r={tabId:e};try{await cm.attach(r,lm)}catch(e){return s(`DEBUGGER_UNAVAILABLE`,Cm(e))}try{return await G(um),await n(r)}catch(e){return s(`ACTION_FAILED`,e instanceof Error?e.message:String(e))}finally{await K(r,`Target.setAutoAttach`,xm).catch(()=>{}),await cm.detach(r).catch(()=>{})}}var bm={autoAttach:!0,flatten:!0,waitForDebuggerOnStart:!1,filter:[{type:`iframe`}]},xm={autoAttach:!1,flatten:!0,waitForDebuggerOnStart:!1};async function Sm(e){let t=[],n=hm((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<fm&&n.length;r+=1){let r=t.length;for(let e of n)await K(e,`Target.setAutoAttach`,bm).catch(()=>{});await G(dm),n=t.slice(r).map(({sessionId:t})=>({tabId:e.tabId,sessionId:t}))}}finally{n()}return t}function Cm(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 wm={alt:1,ctrl:2,meta:4,shift:8},Tm={left:1,right:2,middle:4},Em=12,Dm=`A trusted click needs Chrome’s debugger, which Firefox does not expose — use page.clickElement instead.`,Om=`A trusted drag needs Chrome’s debugger, which Firefox does not expose — drop "trusted" to drag with synthetic events instead.`;function km(e,t){return ym(e,Dm,async n=>{let r=await W(e,yf.name,t);return r.ok?(await jm(n,r.data),o({...r.data,trusted:!0})):r})}function Am(e,t){return ym(e,Om,async n=>{let r=await W(e,sl.name,t);return r.ok?(await Mm(n,r.data),o({...r.data,trusted:!0})):r})}async function jm(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|(wm[t]??0),0),pointerType:`mouse`},d=t=>K(e,`Input.dispatchMouseEvent`,t),f=e=>d({...u,...e,type:`mouseMoved`,button:`none`,buttons:0});await f(r);for(let e of Jc(r,n,s))await G(Em),await f(e);await G(c);for(let e=1;e<=a;e+=1)await d({...u,...n,type:`mousePressed`,button:i,buttons:Tm[i],clickCount:e}),await G(l),await d({...u,...n,type:`mouseReleased`,button:i,buttons:0,clickCount:e})}async function Mm(e,t){let{approach:n,grip:r,drop:i,steps:a,holdMs:o,settleMs:s}=t,c={modifiers:0,pointerType:`mouse`},l=t=>K(e,`Input.dispatchMouseEvent`,t),u=(e,t)=>l({...c,...e,type:`mouseMoved`,button:t?`left`:`none`,buttons:t});for(let e of Jc(n,r,4))await G(Em),await u(e,0);await l({...c,...r,type:`mousePressed`,button:`left`,buttons:1,clickCount:1}),await G(o);for(let e of Jc(r,i,a))await G(Em),await u(e,1);await G(s),await l({...c,...i,type:`mouseReleased`,button:`left`,buttons:0,clickCount:1})}var Nm=`Reading a captcha needs Chrome’s debugger, which Firefox does not expose — solve the captcha in the page yourself.`,Pm=500,Fm={button:`left`,clickCount:1,modifiers:[],moveSteps:14,hoverMs:120,holdMs:70};function Im(e){return ym(e,Nm,async e=>{let t=await Bm(e);return o(t?zm(t):{found:!1})})}function Lm(e,t){let n=$d.input.safeParse(t??{});if(!n.success)return Promise.resolve(s(`INVALID_INPUT`,S(n.error)));let{waitMs:r,timeoutMs:i}=n.data;return ym(e,Nm,async e=>{let t=Date.now()+i,n=await Bm(e);return n?!n.point||n.state!==`idle`?o({...zm(n),clicked:!1}):(await jm(e,Rm(n.point)),o({...zm(await Um(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 Rm(e){return{point:e,from:{x:Math.max(e.x-140,0),y:Math.max(e.y-90,0)},...Fm}}function zm(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 Bm(e){await Xm(e);for(let t of sm)if(await Vm(e,t))return Hm(e,t);return null}async function Vm(e,t){for(let n of t.hostMarkers)if((await Zm(e,n)).length)return!0;return!1}async function Hm(e,t){let n=t.frame?await Sm(e):[],r=t.solvedInPage?await $m(e,t.solvedInPage):!1;if(r||await Gm(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 $m(e,qm(t.challengeFrame)))return{vendor:t,frames:n,state:`needsHuman`,hasToken:r,bounds:await Km(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 Km(e,t.frame):void 0,note:`${t.label} asks for a puzzle rather than a checkbox.`};let i=await Wm(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 Um(e,t,n){let{vendor:r,frames:i}=t,a=Date.now()+Math.max(0,n);for(;Date.now()<a;){await G(Pm);let n=r.solvedInPage?await $m(e,r.solvedInPage):!1;if(n||await Gm(e,r,i))return{...t,state:`solved`,hasToken:n};if(r.challengeFrame&&await $m(e,qm(r.challengeFrame)))return{...t,state:`needsHuman`,hasToken:n,bounds:await Km(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 Wm(e,t,n){if(!t.checkbox)return{note:`${t.label} exposes no checkbox to click.`};if(!t.frame){let[n]=await Zm(e,t.checkbox),r=n?await Qm(e,n):null;return r?{bounds:r,point:Jm(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 Zm(e,`iframe[src*="${t.frame}"]`),i=r?await Qm(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 Xm(o).catch(()=>{});let[s]=await Zm(o,t.checkbox),c=s?await Qm(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 Ym(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 Gm(e,t,n){if(!t.solvedInFrame||!t.frame)return!1;let r=n.find(e=>e.url.includes(t.frame));return r?$m({tabId:e.tabId,sessionId:r.sessionId},t.solvedInFrame):!1}async function Km(e,t){let[n]=await Zm(e,`iframe[src*="${t}"]`);return(n?await Qm(e,n):null)??void 0}var qm=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')`,Jm=e=>({x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}),Ym=(e,t)=>t.x>=e.x&&t.x<=e.x+e.width&&t.y>=e.y&&t.y<=e.y+e.height;async function Xm(e){await K(e,`DOM.enable`),await K(e,`DOM.getDocument`,{depth:-1,pierce:!0})}async function Zm(e,t){let n=await K(e,`DOM.performSearch`,{query:t,includeUserAgentShadowDOM:!1}).catch(()=>null);if(!n?.searchId)return[];let r=n.resultCount?await K(e,`DOM.getSearchResults`,{searchId:n.searchId,fromIndex:0,toIndex:n.resultCount}).catch(()=>null):null;return await K(e,`DOM.discardSearchResults`,{searchId:n.searchId}).catch(()=>{}),r?.nodeIds??[]}async function Qm(e,t){let n=(await K(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 $m(e,t){return(await K(e,`Runtime.evaluate`,{expression:t,returnByValue:!0}).catch(()=>null))?.result?.value===!0}var eh=/^[a-z0-9][a-z0-9-]{0,47}$/;function th(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 nh=48;function rh(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:oh(r)||`root`}}function ih(e,t){return`${e.host}:${e.segment}:${t}`}function ah(e,t){let n=rh(t);return!!n&&n.host===e.host&&n.segment===e.segment}function oh(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,nh).replace(/-+$/,``)}var sh=new Set([`a`,`an`,`and`,`for`,`from`,`in`,`of`,`on`,`the`,`this`,`to`,`with`]);function ch(e,t){return oh(e.toLowerCase().replace(/[^a-z0-9\s-]+/g,` `).split(/[\s-]+/).filter(e=>e&&!sh.has(e)).join(`-`))||oh(t)||`tool`}function lh(e,t){let n=oh(`tool-${e.host}-${e.segment}-${t}`).slice(0,48).replace(/-+$/,``);return eh.test(n)?n:`tool-${oh(t).slice(0,42)}`}var uh=`browsentic/savedTools`,dh=({code:e,...t})=>t;async function fh(){let e=(await t.storage.local.get(uh))[uh];return Array.isArray(e)?e:[]}async function ph(e){return(await fh()).find(t=>t.id===e)??null}async function mh(e){let n=(await fh()).filter(t=>t.name!==e.name);await t.storage.local.set({[uh]:[e,...n].slice(0,100)})}async function hh(e){let n=await fh(),r=n.find(t=>t.id===e);return r?(await t.storage.local.set({[uh]:n.filter(t=>t.id!==e)}),dh(r)):null}async function gh(e,t){let n=new Set((await fh()).map(e=>e.name)),r=ih(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 _h(e,t){if(!t||!rh(t))return!1;let n;try{n=new URL(t).origin}catch{return!1}return n===e.origin&&ah(e.scope,t)}var vh=`browsentic/codeToolkits`,yh=`Installing page code needs Chrome’s debugger, which Firefox does not expose — use the ordinary page tools instead.`,bh=600,xh=1e3,Sh=new Set;function Ch(e){Sh.add(e)}async function wh(){return(await t.storage.session.get(vh))[vh]??{}}async function Th(e,n){let r=await wh();n?r[String(e)]=n:delete r[String(e)],await t.storage.session.set({[vh]:r})}async function Eh(e){await Th(e,null)}function Dh(){t.tabs.onRemoved.addListener(e=>void Eh(e))}function Oh(e){if(e)try{let t=new URL(e).origin;return t===`null`?void 0:t}catch{return}}async function kh(e,t,n){let r=Tu.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(r.error));let i=Oh(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 Ph(e,u);if(!d.ok)return d;u.entries=d.data,await Th(e,u);let f={toolkitId:u.id,origin:i,purpose:a,functions:u.entries.map(e=>e.name)},p=l?await Nh(e,t,{function:l.function,args:l.args}):null;return Ah(u,t,l?.function),p?p.ok?o({...f,called:p.data}):o({...f,callFailed:p.error}):o(f)}function Ah(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?rh(t):null;!i||!a||setTimeout(()=>{let t={toolkitId:e.id,fn:i.name,purpose:e.purpose,suggestedSlug:ch(e.purpose,i.name),host:a.host,segment:a.segment,origin:e.origin};for(let e of Sh)e(t)},xh)}async function jh(e,t,n){let r=await ph(n);if(!r)return s(`UNKNOWN_TOOL`,`That tool is no longer saved.`);if(!_h(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 Ph(e,i);return a.ok?(i.entries=a.data,await Th(e,i),W(e,Bd.name,{function:r.fn,args:[],timeoutMs:1e4})):a}async function Mh(e,t){let n=(await wh())[String(e)];return n&&n.id===t?n.code:null}async function Nh(e,t,n){let r=Bd.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(r.error));let i=(await wh())[String(e)];if(!i)return s(Fd,`No toolkit is installed in this tab. Call page.injectCode first, and the user will be asked to approve the code.`);let a=Oh(t);if(a!==i.origin)return await Eh(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 W(e,Bd.name,r.data);if(o.ok||o.error.code!==`TOOLKIT_MISSING`)return o;let c=await Ph(e,i);return c.ok?W(e,Bd.name,r.data):c}function Ph(e,t){return ym(e,yh,async e=>{let n=await Fh(e,Ld(t.id,t.code)),r=n.exceptionDetails;if(r)return s(`CODE_ERROR`,`The code failed while installing: ${Ih(r)}`);let i=n.result?.value;return Array.isArray(i)?o(i):s(`CODE_ERROR`,`The code installed but reported no functions.`)})}function Fh(e,t){return K(e,`Runtime.evaluate`,{expression:t,returnByValue:!0,awaitPromise:!0})}function Ih(e){let t=e.exception?.description??e.text??`unknown error`;return t.length>bh?`${t.slice(0,bh)}…`:t}var Lh=`⟪browsentic:site-tool-timeout⟫`;async function Rh(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 zh(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 Bh(e,n,r){try{return(await t.scripting.executeScript({target:{tabId:e},world:`MAIN`,func:n,args:r}))[0]?.result??null}catch{return null}}async function Vh(e){let t=await Bh(e,Rh,[!1]);return!t?.ok||!t.tools.length?null:{api:t.api,count:t.tools.length,tools:t.tools}}async function Hh(e,t){let[n,r]=await Promise.all([W(e,pu.name,t),Vh(e)]);return!n.ok||!r?n:o({...n.data,siteTools:r})}async function Uh(e,t){if(!Oh(t))return s(`UNSUPPORTED`,`Site tools can only be read on an http(s) page.`);let n=await Bh(e,Rh,[!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 Wh(e,t,n){let r=Nc.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(r.error));if(!Oh(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 Bh(e,zh,[i,a,c,Lh]);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 Gh=15e3;async function Kh(e,n){let r=Pc.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(r.error));let{target:i,url:a,timeoutMs:c}=r.data;try{Fc(r.data)}catch(e){return e instanceof L?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=Zh(c),u=null;try{a?l.expect(await t.downloads.download({url:a})):u=await W(e,Ic.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:Jh(f)})}async function qh(e){let[n]=await t.downloads.search({id:e});return n??null}function Jh(e){let t=e.filename;return{browserPath:t,name:Yh(t),mime:e.mime??``,size:typeof e.fileSize==`number`&&e.fileSize>0?e.fileSize:e.totalBytes??0,url:e.finalUrl||e.url,host:Xh(e.finalUrl||e.url)}}function Yh(e){return e.split(/[\\/]/).pop()||`download`}function Xh(e){try{return new URL(e).hostname.toLowerCase()||void 0}catch{return}}function Zh(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(Gh,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 qh(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 qh(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 Qh(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 $h=16,eg=`|`,tg=25e4,ng=new TextEncoder,rg=new TextDecoder;function ig(){return mg(crypto.getRandomValues(new Uint8Array($h)))}function ag(e){return typeof e==`string`&&e.length>=16}async function og(e,t){let n=await crypto.subtle.importKey(`raw`,ng.encode(e),`PBKDF2`,!1,[`deriveBits`]),r=ng.encode(pg(`browsentic/pair`,t.clientNonce,t.serverNonce)),i=await crypto.subtle.deriveBits({name:`PBKDF2`,salt:r,iterations:tg,hash:`SHA-256`},n,256);return mg(new Uint8Array(i))}async function sg(e,t){return mg(await dg(e,`browsentic/client`,t))}async function cg(e,t,n){return mg(await dg(e,`browsentic/server`,t,pg(n.daemonVersion,n.manifestHash,String(n.manifestInSync),n.sealedSessionKey??``)))}async function lg(e,t,n){let r=hg(n);if(!r)return null;let i=await fg(e,t,r.length);return rg.decode(r.map((e,t)=>e^i[t]))}function ug(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 dg(e,t,n,r=``){let i=await crypto.subtle.importKey(`raw`,ng.encode(e),{name:`HMAC`,hash:`SHA-256`},!1,[`sign`]),a=pg(t,String(n.protocolVersion),n.extensionVersion,n.manifestHash,n.clientNonce,n.serverNonce,r);return new Uint8Array(await crypto.subtle.sign(`HMAC`,i,ng.encode(a)))}async function fg(e,t,n){let r=new Uint8Array(n);for(let i=0,a=0;i<n;i+=32,a++){let o=await dg(e,`browsentic/seal`,t,String(a));r.set(o.subarray(0,Math.min(32,n-i)),i)}return r}function pg(...e){return e.join(eg)}function mg(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function hg(e){try{return Uint8Array.from(atob(e.replace(/-/g,`+`).replace(/_/g,`/`)),e=>e.charCodeAt(0))}catch{return null}}var gg=`browsentic/daemon`,_g=`browsentic/reconnect`,vg=`browsentic/sessionKey`,yg=1e3,bg=3e4,xg=5e3,Sg=2e4,q=null,Cg=0,wg,Tg=null,Eg=new Set,Dg=null;function Og(e){Dg=e}function kg(e){Tg=e}function Ag(e){Eg.add(e)}function jg(e,t){let n=crypto.randomUUID();return J({t:`instruct`,id:n,text:e,context:t})?n:null}var Mg=9e4,Ng=new Map;function Pg(e){let t=crypto.randomUUID();return J({t:`analyzeFile`,id:t,...e})?new Promise(e=>{let n=setTimeout(()=>{Ng.delete(t),e(s(`TIMEOUT`,`The daemon did not return a summary in time.`))},Mg);Ng.set(t,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var Fg=12e4,Ig=new Map;function Lg(e){let t=crypto.randomUUID();return J({t:`analyzeRecording`,id:t,recording:e})?new Promise(e=>{let n=setTimeout(()=>{Ig.delete(t),e(s(`TIMEOUT`,`The daemon did not return a workflow in time.`))},Fg);Ig.set(t,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var Rg=2e4,zg=new Map;function Bg(e){let t=crypto.randomUUID();return J({t:`nameSession`,id:t,...e})?new Promise(e=>{let n=setTimeout(()=>{zg.delete(t),e(s(`TIMEOUT`,`The daemon did not return a name in time.`))},Rg);zg.set(t,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var Vg=15e3,Hg=new Map;function Ug(e){return Jg({t:`saveSkill`,id:crypto.randomUUID(),skill:e})}function Wg(e){return Jg({t:`deleteSkill`,id:crypto.randomUUID(),name:e})}function Gg(e){return Jg({t:`deleteSiteMap`,id:crypto.randomUUID(),name:e})}function Kg(e,t=!1){return Jg({t:`activateSiteMap`,id:crypto.randomUUID(),stagingId:e,exactHost:t})}function qg(e){return Jg({t:`discardSiteMap`,id:crypto.randomUUID(),stagingId:e})}function Jg(e){return J(e)?new Promise(t=>{let n=setTimeout(()=>{Hg.delete(e.id),t(s(`TIMEOUT`,`The daemon did not answer in time.`))},Vg);Hg.set(e.id,e=>{clearTimeout(n),t(e)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var Yg=2e4,Xg=new Map;function Zg(e=!1){return t_({t:`agentState`,id:crypto.randomUUID(),refresh:e})}function Qg(e){return t_({t:`setAgent`,id:crypto.randomUUID(),agent:e})}function $g(e,t){return t_({t:`setAgentModel`,id:crypto.randomUUID(),agent:e,model:t})}function e_(e){return t_({t:`grantAgent`,id:crypto.randomUUID(),agent:e})}function t_(e){return J(e)?new Promise(t=>{let n=setTimeout(()=>{Xg.delete(e.id),t(s(`TIMEOUT`,`The daemon did not answer in time.`))},Yg);Xg.set(e.id,e=>{clearTimeout(n),t(e)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var n_=new Map;function r_(e=!1){let t={t:`listSkills`,id:crypto.randomUUID(),refresh:e};return J(t)?new Promise(e=>{let n=setTimeout(()=>{n_.delete(t.id),e(s(`TIMEOUT`,`The daemon did not answer in time.`))},Yg);n_.set(t.id,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var i_=new Map;function a_(){return s_({t:`guardrails`,id:crypto.randomUUID()})}function o_(e,t){return s_({t:`setGuardrail`,id:crypto.randomUUID(),setting:e,value:t})}function s_(e){return J(e)?new Promise(t=>{let n=setTimeout(()=>{i_.delete(e.id),t(s(`TIMEOUT`,`The daemon did not answer in time.`))},Yg);i_.set(e.id,e=>{clearTimeout(n),t(e)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}function c_(e){return J({t:`cancel`,id:e})}function l_(e,t,n,r){J({t:`decision`,id:e,toolId:t,allow:n,remember:r})}function u_(e){J({t:`reset`,sessionId:e})}function J(e){return!q||q.readyState!==WebSocket.OPEN?!1:(w_(q,e),!0)}async function d_(){if(g_())return;let e=await O_();if(!e){await D_({connected:!1,paired:!1,error:void 0,lastChangeAt:Date.now()});return}let t=await E_();t&&!t.paired&&t.error||(clearTimeout(wg),v_({kind:`session`,secret:e},0))}async function f_(e){let t=e.replace(/[\s-]/g,``).toUpperCase();return t?(__(),clearTimeout(wg),Cg=0,new Promise(e=>{m_=e,v_({kind:`pair`,secret:t},0),setTimeout(()=>h_({ok:!1,error:`No Browsentic daemon is running. Start one with "browsentic pair".`}),Sg)})):{ok:!1,error:`Enter the pairing code from "browsentic pair".`}}async function p_(){clearTimeout(wg),__(),await t.storage.local.remove(vg),await D_({connected:!1,paired:!1,error:void 0,agent:void 0,lastChangeAt:Date.now()})}var m_=null;function h_(e){m_?.(e),m_=null}function g_(){return!!q&&(q.readyState===WebSocket.OPEN||q.readyState===WebSocket.CONNECTING)}function __(){let e=q;if(q=null,e){e.onopen=null,e.onmessage=null,e.onclose=null;try{e.close(1e3,`client disconnecting`)}catch{}}}function v_(e,n,r){if(n>=i.length)return x_(e,r);let a=i[n],o=new WebSocket(`ws://127.0.0.1:${a}/extension`);q=o;let s=!1,c=!1,l=r,u={credential:e,port:a,hello:{extensionVersion:t.runtime.getManifest().version,manifestHash:Qh(Pf()),nonce:ig()},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(),xg);o.onopen=()=>{w_(o,{t:`hello`,protocolVersion:16,extensionVersion:u.hello.extensionVersion,manifestHash:u.hello.manifestHash,auth:{kind:e.kind},nonce:u.hello.nonce})},o.onmessage=e=>{C_(o,String(e.data),u)},o.onclose=t=>{if(clearTimeout(d),q===o&&(q=null),l??=b_(t),!c)return v_(e,n+1,l);D_({connected:!1,paired:!0,error:void 0,lastChangeAt:Date.now()}),e.kind===`session`&&T_(e)}}var y_=new Set([`unproven daemon`,``]);function b_(e){let t=e.reason?.trim();if(!(!t||y_.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 x_(e,t){if(t&&!t.retryable){h_({ok:!1,error:t.reason}),D_({connected:!1,paired:!1,error:t.reason,lastChangeAt:Date.now()});return}h_({ok:!1,error:t?.reason??`No Browsentic daemon is running.`}),e.kind===`session`&&T_(e)}function S_(e){return{protocolVersion:16,extensionVersion:e.hello.extensionVersion,manifestHash:e.hello.manifestHash,clientNonce:e.hello.nonce,serverNonce:e.serverNonce??``}}async function C_(e,n,r){let i=a(n);if(i)switch(i.t){case`ping`:return w_(e,{t:`pong`,id:i.id});case`challenge`:{if(!ag(i.nonce)||r.serverNonce)return r.walk();r.serverNonce=i.nonce;let t=S_(r);return r.secret=r.credential.kind===`pair`?await og(r.credential.secret,t):r.credential.secret,w_(e,{t:`prove`,proof:await sg(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=S_(r),a=i.sealedSessionKey??``;if(!ug(i.proof,await cg(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 lg(e,n,a):null;if(!o&&(a||r.credential.kind===`pair`))return r.walk();r.done(),Cg=0,o&&await t.storage.local.set({[vg]:o}),h_({ok:!0}),await D_({connected:!0,paired:!0,port:r.port,daemonVersion:i.daemonVersion,manifestInSync:i.manifestInSync,error:void 0,lastChangeAt:Date.now()});for(let e of Eg)e();return}case`describe`:return w_(e,{t:`manifest`,id:i.id,tools:Pf()});case`invoke`:return w_(e,{t:`result`,id:i.id,result:await Px(i.action,i.input,i.tabId,i.runId)});case`run`:return Tg?.(i.id,i.event);case`fileSummary`:Ng.get(i.id)?.(i.result),Ng.delete(i.id);return;case`skillResult`:Hg.get(i.id)?.(i.result),Hg.delete(i.id);return;case`sessionName`:zg.get(i.id)?.(i.result),zg.delete(i.id);return;case`recordingWorkflow`:Ig.get(i.id)?.(i.result),Ig.delete(i.id);return;case`agentInfo`:Xg.get(i.id)?.(i.result),Xg.delete(i.id),i.result.ok&&await D_({agent:i.result.data,lastChangeAt:Date.now()});return;case`guardrailInfo`:i_.get(i.id)?.(i.result),i_.delete(i.id);return;case`skillCatalog`:n_.get(i.id)?.(i.result),n_.delete(i.id),i.result.ok&&await D_({skillCatalog:i.result.data,lastChangeAt:Date.now()});return;case`siteMapDraft`:return Dg?.(i.id,i.draft);default:return}}function w_(e,t){e.readyState===WebSocket.OPEN&&e.send(JSON.stringify(t))}function T_(e){let t=Math.min(bg,yg*2**Cg++)*(.5+Math.random()/2);clearTimeout(wg),wg=setTimeout(()=>v_(e,0),t)}async function E_(){return(await t.storage.session.get(gg))[gg]}async function D_(e){let n=await E_()??{connected:!1,paired:!1,lastChangeAt:0};await t.storage.session.set({[gg]:{...n,...e}})}async function O_(){let e=(await t.storage.local.get(vg))[vg];return typeof e==`string`&&e?e:null}var k_=`browsentic:files`,A_=e=>`browsentic:file:${e}`;async function j_(){let e=(await t.storage.local.get(k_))[k_];return Array.isArray(e)?e:[]}async function M_(e){await t.storage.local.set({[k_]:e})}async function N_(e){let n=A_(e),r=(await t.storage.local.get(n))[n];return r&&typeof r.content==`string`?r:null}async function P_(e,t){await M_((await j_()).map(n=>n.id===e?{...n,...t}:n))}async function F_(e){let t=await N_(e);if(!t){await P_(e,{status:`error`,error:`File bytes are missing from storage.`});return}let n=(await j_()).find(t=>t.id===e),r=await Pg({name:t.name,mime:t.mime,size:n?.size??0,content:t.content});r.ok?await P_(e,{status:`ready`,summary:r.data.summary,digest:r.data.digest,error:void 0}):await P_(e,{status:`error`,error:`${r.error.code}: ${r.error.message}`})}var I_=RegExp(`[\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f\\u200b-\\u200f\\u202a-\\u202e\\u2066-\\u2069\\ufeff]`,`g`),L_=/^[a-zA-Z0-9 .#>+~*,_:[\]="'()-]{1,120}$/;function R_(e,t){return typeof e==`string`?e.replace(/[\r\n\t]+/g,` `).replace(I_,``).replace(/^[\s#>*\-+|`~=]+/,``).replace(/[`|]/g,``).replace(/\s+/g,` `).trim().slice(0,t):``}function z_(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 B_(e){return L_.test(e)&&e.trim().split(/\s+/).length<=8}function V_(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}var H_={goal:160,summary:400,intent:120,note:160,value:200,text:80,variable:40,field:80,kind:24,caveat:200},U_=[`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 W_(e,t){if(!e||typeof e!=`object`)return{ok:!1,message:`The workflow must be an object.`};let n=e,r=[],i=R_(n.goal??``,H_.goal);if(!i)return{ok:!1,message:`The workflow needs a one-line goal.`};let a=R_(n.summary??``,H_.summary),o=[];for(let e of Array.isArray(n.steps)?n.steps.slice(0,80):[]){let n=G_(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=R_(e?.name??``,H_.variable).replace(/[{}]/g,``);!t||s.has(t)||(s.add(t),c.push({name:t,field:R_(e?.field??``,H_.field)||t,kind:R_(e?.kind??``,H_.kind)||`text`}))}let l={goal:i,summary:a,steps:o,variables:c,caveats:(Array.isArray(n.caveats)?n.caveats:[]).slice(0,8).map(e=>R_(e,H_.caveat)).filter(Boolean)};X_(l,r);for(let e of J_(l))z_(e)&&r.push(`Reads like an instruction rather than an observation: “${V_(e,80)}”`);return{ok:!0,workflow:l,warnings:r}}function G_(e,t,n){let r=typeof e?.action==`string`?e.action.trim():``;if(!U_.includes(r))return r&&n.push(`Dropped a step naming an action that cannot be replayed: ${V_(r,40)}`),null;let i=R_(e?.intent??``,H_.intent);if(!i)return null;let a=K_(e?.target,n),o=q_(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:R_(e?.value??``,H_.value)||void 0,url:o||void 0,note:R_(e?.note??``,H_.note)||void 0}}function K_(e,t){if(!e||typeof e!=`object`)return;let n=typeof e.selector==`string`?e.selector.trim():``;n&&!B_(n)&&(t.push(`Dropped a step selector that did not look like a selector: ${V_(n,40)}`),n=``);let r=R_(e.text??``,H_.text),i=R_(e.role??``,H_.kind);if(!(!n&&!r))return{selector:n||void 0,text:r||void 0,role:i||void 0}}function q_(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:`?``:V_(r.href,300)}catch{return``}}function J_(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 Y_(e){return J_(e).reduce((e,t)=>e+th(t),0)}function X_(e,t){if(Y_(e)<=12288)return;let n=(n,r)=>{Y_(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=V_(t.intent,60)});Y_(e)>12288&&e.steps.length>1;)e.steps.pop();e.steps.length===1&&t.push(`Only the first step fitted in the workflow.`)}var Z_=`browsentic:recordings`,Q_=e=>`browsentic:recording:${e}`,$_=20;async function ev(){let e=(await t.storage.local.get(Z_))[Z_];return Array.isArray(e)?e:[]}async function tv(e){await t.storage.local.set({[Z_]:e})}async function nv(e,n){await t.storage.local.set({[Q_(e.id)]:n});let r=await ev(),i=[{...r.find(t=>t.id===e.id),...e},...r.filter(t=>t.id!==e.id)],a=i.slice($_);a.length&&await t.storage.local.remove(a.map(e=>Q_(e.id))),await tv(i.slice(0,$_))}async function rv(e){let n=Q_(e),r=(await t.storage.local.get(n))[n];return r&&Array.isArray(r.events)?r:null}async function iv(e,t){let n=await ev();n.some(t=>t.id===e)&&await tv(n.map(n=>n.id===e?{...n,...t,updatedAt:Date.now()}:n))}async function av(e){let n=(await ev()).find(t=>t.id===e);if(!n)return;let r=await rv(e);if(!r||!r.events.length){await iv(e,{status:`error`,error:`The recorded steps are missing from storage.`});return}await iv(e,{status:`analyzing`,error:void 0});let i=await Lg({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 iv(e,{status:`error`,error:`${i.error.code}: ${i.error.message}`});return}let a=W_(i.data.workflow,{origin:$f(n.startUrl)});if(!a.ok){await iv(e,{status:`error`,error:a.message});return}await t.storage.local.set({[Q_(e)]:{...r,workflow:a.workflow}}),await iv(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===sv(n.host,n.createdAt)?a.workflow.goal:n.name,error:void 0})}async function ov(){let e=await ev();for(let t of e)(t.status===`analyzing`||t.error?.startsWith(`EXTENSION_OFFLINE`))&&await av(t.id)}function sv(e,t){let n=new Date(t),r=`${n.getFullYear()}-${cv(n.getMonth()+1)}-${cv(n.getDate())} ${cv(n.getHours())}:${cv(n.getMinutes())}`;return`${e||`Browsing`} — ${r}`}function cv(e){return String(e).padStart(2,`0`)}function lv(e){return{id:e.id,name:e.name,host:e.host||Qf(e.startUrl),goal:e.goal,steps:e.steps,capturedValues:e.capturedValues,durationMs:e.durationMs}}var uv=`browsentic/recording`,dv=`browsentic/recording-warn`,fv=`browsentic/recording-stop`,pv=null;function mv(e){pv=e}async function hv(){let e=(await t.storage.session.get(uv))[uv];return e&&Array.isArray(e.events)?e:null}async function gv(e){e?await t.storage.session.set({[uv]:e}):await t.storage.session.remove(uv)}function _v(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 vv(){let e=await hv();return e?_v(e):null}async function yv(e){let t=await hv(),n=!!t&&t.tabId===e;return{recording:n,captureValues:n?t.captureValues:!1}}async function bv(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.`):xv({tabId:n.id,url:n.url,captureValues:e})}async function xv(e){if(await hv())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:Qf(e.url),startUrl:e.url,startedAt:Date.now(),captureValues:e.captureValues,events:[{t:Date.now(),kind:`navigate`,url:e.url}],warned:!1};await gv(n),await t.alarms.create(dv,{when:n.startedAt+qf}),await t.alarms.create(fv,{when:n.startedAt+Kf}),await t.tabs.sendMessage(e.tabId,{channel:Wf,op:`begin`}).catch(()=>void 0);let r=_v(n);return pv?.(r),o(r)}async function Sv(e,t){if(!t.length)return;let n=await hv();if(!(!n||n.tabId!==e)){if(n.events.length>=2e3){await Cv(`timeout`);return}n.events.push(...t.slice(0,Gf-n.events.length)),await gv(n),pv?.(_v(n))}}async function Cv(e){let n=await hv();if(await t.alarms.clear(dv),await t.alarms.clear(fv),!n)return pv?.(null),o(null);await gv(null),e!==`tab-closed`&&await t.tabs.sendMessage(n.tabId,{channel:Wf,op:`end`}).catch(()=>void 0),pv?.(null);let r=n.startedAt;return await nv({id:n.id,name:sv(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}),av(n.id),o({id:n.id})}function wv(){t.tabs.onUpdated.addListener((e,t)=>{t.url&&(async()=>{let n=await hv();if(!n||n.tabId!==e)return;let r=n.events[n.events.length-1];r?.kind===`navigate`&&r.url===t.url||await Sv(e,[{t:Date.now(),kind:`navigate`,url:t.url}])})()}),t.tabs.onRemoved.addListener(e=>{(async()=>{(await hv())?.tabId===e&&await Cv(`tab-closed`)})()}),t.alarms.onAlarm.addListener(e=>{if(e.name===`browsentic/recording-stop`){Cv(`timeout`);return}e.name===`browsentic/recording-warn`&&(async()=>{let e=await hv();if(!e||e.warned)return;e.warned=!0,await gv(e);let t=Math.max(0,Kf-(Date.now()-e.startedAt));pv?.(_v(e,`Recording stops automatically in ${Tv(t)}.`))})()})}function Tv(e){let t=Math.round(e/1e3);return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}var Ev=1e4,Dv=120,Ov=20,kv=50,Av=10;async function jv(e,n){let r=Pu.input.safeParse(e??{});if(!r.success)return s(`INVALID_INPUT`,S(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&&Kv(c.url)?c.url:void 0,u;try{let e=Mu({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 L?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 Fv(f.id),m=a?f.id:c?.id;return o({performed:`opened ${qv(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 Mv(e,n){let r=_f.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(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 Bv(e);if(i==null&&a==null)return o(Rv(c,e));let l=await Lv(c,{tabId:i,match:a},`switch to`);if(!l.ok)return l.result;let u=l.tab;if(!Kv(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 ${Hv(u)}`,activeTabId:u.id,previousTabId:e.id,tab:Vv({...u,active:!0})})}async function Nv(e,n){let r=Lc.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(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 Bv(e),l=i==null&&a==null?Iv(c,e):await Lv(c,{tabId:i,match:a},`close`);if(!l.ok)return l.result;let u=l.tab;if(c.length<=1)return s(`INVALID_TARGET`,`${Hv(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`,`${Hv(u)} is pinned, which means the user wants to keep it. Ask them to unpin it if it really should close.`);if(!Kv(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 yv(u.id)).recording)return s(`INVALID_TARGET`,`A recording is in progress in ${Hv(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 zv(e,u.id),f=d.active?.url?qv(d.active.url):void 0;return o({performed:f?`closed ${Hv(u)} — now on ${f}`:`closed ${Hv(u)}`,closed:Vv(u),...f?{nowOn:f}:{},...d.active?.id==null?{}:{activeTabId:d.active.id},remaining:d.remaining})}function Pv(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),Ev);return t.tabs.onUpdated.addListener(a),{settled:r,cancel:()=>i(!1)}}async function Fv(e){let n=Pv(e),r=(await t.tabs.get(e).catch(()=>null))?.status;return r==null||r===`complete`?(n.cancel(),r===`complete`):n.settled}function Iv(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 Lv(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 — ${Wv(e)}`):s(`TARGET_NOT_FOUND`,`No tab with id ${n.tabId} — it has probably been closed. ${Wv(e)}`)}}let i=n.match.trim().toLowerCase();if(!i)return{ok:!1,result:s(`INVALID_INPUT`,`"match" cannot be empty.`)};let a=e.filter(Gv).filter(e=>`${e.title??``} ${e.url??``}`.toLowerCase().includes(i));return a.length?a.length>1?{ok:!1,result:s(`INVALID_TARGET`,`"${qv(n.match)}" matches ${a.length} tabs, so nothing was touched — ${r} one of them by id: ${Uv(a)}`)}:{ok:!0,tab:a[0]}:{ok:!1,result:s(`TARGET_NOT_FOUND`,`No open tab matches "${qv(n.match)}". ${Wv(e)}`)}}function Rv(e,t){let n=e.filter(Gv),r=e.length-n.length,i=n.slice(0,Ov);return{performed:`${n.length} open tab${n.length===1?``:`s`} in this window`,activeTabId:t.id,tabs:i.map(Vv),...r?{hidden:r}:{},...i.length<n.length?{truncated:!0}:{}}}async function zv(e,t){let n=[];for(let r=0;r<Av;r++){n=await Bv(e);let r=n.find(e=>e.active);if(r&&!n.some(e=>e.id===t))return{active:r,remaining:n.length};await Jv(kv)}let r=n.filter(e=>e.id!==t);return{active:r.find(e=>e.active),remaining:r.length}}async function Bv(e){return await t.tabs.query(e.windowId==null?{currentWindow:!0}:{windowId:e.windowId})}function Vv(e){return{tabId:e.id,title:qv(e.title??``),url:qv(e.url??``),...e.active?{active:!0}:{}}}function Hv(e){let t=qv(e.title??``),n=qv(e.url??``);return t&&n?`“${t}” — ${n}`:t||n||`tab ${e.id}`}function Uv(e){let t=e.slice(0,Ov),n=t.map(e=>`#${e.id} ${Hv(e)}`).join(`; `);return t.length<e.length?`${n}; …and ${e.length-t.length} more`:n}function Wv(e){let t=e.filter(Gv);return t.length?`Open tabs: ${Uv(t)}`:`No other web page is open in this window.`}var Gv=e=>Kv(e.url),Kv=e=>!!e&&/^https?:/i.test(e);function qv(e){let t=e.replace(/\s+/g,` `).trim();return t.length>Dv?`${t.slice(0,Dv-1)}…`:t}var Jv=e=>new Promise(t=>setTimeout(t,e)),Yv=`browsentic/diagnostics`,Xv=30,Zv=400,Qv=null,$v=[],ey;async function ty(){return Qv||(Qv=(await t.storage.session.get(Yv).catch(()=>({})))[Yv]??{},Qv)}function ny(){return clearTimeout(ey),ey=void 0,Qv?t.storage.session.set({[Yv]:Qv}).catch(()=>void 0):Promise.resolve()}function ry(){ey||=setTimeout(()=>void ny(),200)}var iy=e=>Object.values(e).filter(e=>e.phase===`watching`);function ay(e,t){return iy(e).find(e=>e.tabId===t)}async function oy(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 ty();await yy(c);let l=ay(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(iy(c).length>=2)return s(`DIAGNOSTICS_LIMIT`,`2 tabs are already being recorded — stop one with page.stopDiagnostics first.`);let u=await gm(a.id);if(!u.ok)return s(`DEBUGGER_UNAVAILABLE`,u.message);let d=await cy(a.id,e.capture);if(d)return await _m(a.id),s(`DEBUGGER_UNAVAILABLE`,d);let f=Date.now(),p={diagnosticsId:crypto.randomUUID(),tabId:a.id,url:a.url,host:Qf(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 ny(),await t.alarms.create(Zu(p.diagnosticsId),{when:p.expiresAt}),await G(150);let m=e.reload?await sy(a.id):void 0;return o({...ud(p),reloaded:m,notice:id})}async function sy(e){let n=Pv(e);try{await t.tabs.reload(e)}catch{return n.cancel(),!1}return n.settled}async function cy(e,t){let n={tabId:e};try{return t.includes(`console`)&&(await K(n,`Runtime.enable`),await K(n,`Log.enable`)),t.includes(`network`)&&await K(n,`Network.enable`),null}catch(e){return`Chrome attached but refused to start reporting: ${e instanceof Error?e.message:String(e)}`}}async function ly(e){let t=await hy(e.diagnosticsId);if(!t.ok)return t;let n=t.data,r=e.contains?.toLowerCase(),i=n.console.filter(t=>(e.level===`all`||cd(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 ny()}return o({...ud(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 hy(e.diagnosticsId);if(!t.ok)return t;let n=t.data,r=e.urlContains?.toLowerCase(),i=e.method?.toUpperCase(),a=n.network.filter(t=>dy(t,e.status)&&(!r||t.url.toLowerCase().includes(r))&&(!i||t.method===i)),s=a.slice(-e.limit),c=e.includeBodies?await py(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 ny()}return o({...ud(n),requests:s.map(t=>fy(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 dy(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 fy(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 py(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 K({tabId:e.tabId},`Network.getResponseBody`,{requestId:r.requestId});n.set(r.requestId,t.base64Encoded?`[${t.body.length} bytes of binary]`:ld(t.body,rd))}catch{n.set(r.requestId,`Not available — Chrome has already discarded this body.`)}return n}async function my(e){let t=await ty();await yy(t);let n=iy(t);if(e!=null){let n=await gy(e,`stopped`);if(n)return o(ud(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 gy(n[0].diagnosticsId,`stopped`);return r?o(ud(r)):s(`DIAGNOSTICS_NOT_FOUND`,`That recording just ended on its own.`)}async function hy(e){let t=await ty();if(await yy(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=iy(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 gy(e,n,r){let i=await ty(),a=i[e];return!a||a.phase!==`watching`?null:(a.phase=n,a.message=r??_y(n),await t.alarms.clear(Zu(e)).catch(()=>void 0),n!==`detached`&&n!==`tab-closed`&&await _m(a.tabId),vy(i),await ny(),a)}function _y(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 vy(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 yy(e){let t=Date.now();for(let n of iy(e))n.expiresAt<=t&&await gy(n.diagnosticsId,`timeout`)}async function by(e,t){if(!e.length)return;let n=await ty();for(let r of e)await gy(r.diagnosticsId,t),delete n[r.diagnosticsId];await ny()}async function xy(e){let t=await ty();await by(Object.values(t).filter(t=>t.owner===e),`stopped`)}async function Sy(e){let t=await ty();await by(Object.values(t).filter(t=>t.tabId===e),`tab-closed`)}function Cy(){hm((e,t,n)=>{e.sessionId||e.tabId==null||wy(e.tabId,t,n??{})}),vm(e=>{ty().then(t=>{let n=ay(t,e);n&&gy(n.diagnosticsId,`detached`)})}),t.alarms.onAlarm.addListener(e=>{e.name.startsWith(`browsentic/diagnostics-timeout:`)&&gy(e.name.slice(Xu.length),`timeout`)}),t.tabs.onRemoved.addListener(e=>void Sy(e))}function wy(e,t,n){if(!Qv){$v.push({tabId:e,method:t,params:n}),ty().then(()=>{let e=$v;$v=[];for(let t of e)Ty(t.tabId,t.method,t.params);ry()});return}Ty(e,t,n)}function Ty(e,t,n){let r=Qv?ay(Qv,e):void 0;if(!r)return;let i=Ey[t]??Dy[t];i&&(i(r,n),ry())}var Ey={"Runtime.consoleAPICalled":(e,t)=>{let n=t.args??[],r=Ny(t.stackTrace);Ay(e,{t:Date.now(),level:od(t.type),kind:`console`,text:ld(n.slice(0,6).map(My).filter(Boolean).join(` `)),url:r[0]?.url,line:r[0]?.line,column:r[0]?.column,stack:r.length>1?r.map(Py):void 0})},"Runtime.exceptionThrown":(e,t)=>{let n=t.exceptionDetails??{},r=Ny(n.stackTrace);Ay(e,{t:Date.now(),level:`error`,kind:`exception`,text:ld(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(Py):void 0})},"Log.entryAdded":(e,t)=>{let n=t.entry??{};Ay(e,{t:Date.now(),level:od(n.level),kind:`browser`,text:ld(n.source?`[${n.source}] ${n.text??``}`:n.text??``),url:n.url,line:n.lineNumber==null?void 0:n.lineNumber+1})}},Dy={"Network.requestWillBeSent":(e,t)=>{let n=t.requestId,r=t.request??{},i=t.redirectResponse;if(i){let t=Oy(e,n);t&&(t.status=i.status,t.statusText=i.statusText||void 0,t.responseHeaders=Fy(i.headers),t.requestId=`${n}:${t.t}`)}jy(e,{t:t.wallTime?t.wallTime*1e3:Date.now(),mono:t.timestamp??0,requestId:n,method:(r.method??`GET`).toUpperCase(),url:ld(r.url??``),type:t.type,requestHeaders:Fy(r.headers)})},"Network.responseReceived":(e,t)=>{let n=Oy(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=Fy(r.headers),n.type=t.type??n.type,n.durationMs=ky(n,t.timestamp)},"Network.loadingFinished":(e,t)=>{let n=Oy(e,t.requestId);n&&(n.sizeBytes=t.encodedDataLength,n.durationMs=ky(n,t.timestamp)??n.durationMs)},"Network.loadingFailed":(e,t)=>{let n=Oy(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=ky(n,t.timestamp)??n.durationMs}};function Oy(e,t){for(let n=e.network.length-1;n>=0;--n)if(e.network[n].requestId===t)return e.network[n]}var ky=(e,t)=>t!=null&&e.mono?Math.max(0,Math.round((t-e.mono)*1e3)):void 0;function Ay(e,t){e.console.push(t);let n=e.console.length-500;n>0&&(e.droppedConsole+=n,e.console.splice(0,n))}function jy(e,t){e.network.push(t);let n=e.network.length-td;n>0&&(e.droppedNetwork+=n,e.network.splice(0,n))}function My(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 Ny(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 Py=e=>`${e.fn} (${e.url??`<unknown>`}:${e.line??0}:${e.column??0})`;function Fy(e){if(!e)return;let t={};for(let[n,r]of Object.entries(e).slice(0,Xv))t[n.toLowerCase()]=ld(String(r),Zv);return t}var Iy=`browsentic/monitors`,Ly=`browsentic/monitorsDone`,Ry=`Receiving end does not exist`,zy=new Set,By=new Map,Vy=Promise.resolve();function Hy(e){zy.add(e)}function Uy(e){for(let t of zy)t(e)}function Wy(e){let t=Vy.then(e,e);return Vy=t.catch(()=>void 0),t}async function Y(){return(await t.storage.session.get(Iy))[Iy]??{}}function Gy(e){return t.storage.session.set({[Iy]:e})}async function Ky(){let e=(await t.storage.session.get(Ly))[Ly];return Array.isArray(e)?e:[]}function qy(e){return t.storage.session.set({[Ly]:e})}function Jy(e,t=`watching`,n){let r=Date.now(),{percent:i,etaMs:a}=Ac(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 Yy(e){return{...e,logs:e.logs.slice(-5)}}function Xy(e,t){e.logs.push({t:Date.now(),text:t}),e.logs.length>50&&e.logs.splice(0,e.logs.length-50)}async function Zy(e,n){let r=Oc(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 Wy(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:Qf(a.url),startUrl:a.url,origin:$f(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 Xy(i,`Watching ${i.host} ${kc(i.until)}.`),t[i.id]=i,await Gy(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(wc(l.id),{when:l.startedAt+l.timeoutMs}),await t.alarms.create(Sc,{periodInMinutes:1}),await Qy(l);let u=Jy(l);return Uy(u),o(Yy(u))}async function Qy(e){let n={channel:_c,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(Ry))return;await Rf(e.tabId)&&await t.tabs.sendMessage(e.tabId,n).catch(()=>void 0)}}async function $y(e,t,n){let r=await Wy(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}=Ac(i.samples,i.until.threshold);return o!=null&&(i.lastLogPercent==null||o-i.lastLogPercent>=5||n.t-i.lastLogAt>=3e4)?(Xy(i,`Progress ${Math.round(o)}%${s==null?``:`, ETA ${jc(s)}`}.`),i.lastLogAt=n.t,i.lastLogPercent=o):o==null&&n.text&&n.t-i.lastLogAt>=3e4&&(Xy(i,`“${n.text}”`),i.lastLogAt=n.t),await Gy(r),{monitor:{...i},complete:n.matched===!0}});if(r){if(r.complete){await eb(t,`done`);return}Uy(Jy(r.monitor))}}async function eb(e,n,r){let i=await Wy(async()=>{let t=await Y(),i=t[e];if(!i)return null;delete t[e],await Gy(t),Xy(i,r??tb(n));let a=Jy(i,n,r),o=await Ky();return o.push(a),await qy(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(wc(e)),s===0&&await t.alarms.clear(Sc),await nb(a),n!==`tab-closed`&&await t.tabs.sendMessage(a.tabId,{channel:_c,op:`unwatch`,monitorId:e}).catch(()=>void 0);for(let t of By.get(e)??[])t(o);return By.delete(e),n!==`stopped`&&await fb(o),Uy(o),o}function tb(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 nb(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 rb(e){let t=await Y(),n=Object.values(t);if(e!=null){if(!t[e]){let t=(await Ky()).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 eb(e,`stopped`);return n?o(Yy(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 eb(n[0].id,`stopped`);return r?o(Yy(r)):s(`MONITOR_NOT_FOUND`,`That monitor just finished on its own.`)}async function ib(e){let t=await Y(),n=await Ky();if(e!=null){let r=t[e];if(r)return o(Yy(Jy(r)));let i=n.find(t=>t.monitorId===e);return i?o(Yy(i)):s(`MONITOR_NOT_FOUND`,`No monitor with id “${e}” is running or recently finished.`)}return o({monitors:[...Object.values(t).map(e=>Yy(Jy(e))),...n.map(Yy)]})}async function ab(e,t){if(!(await Y())[e]){let t=(await Ky()).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=By.get(e)??new Set,i=e=>{clearTimeout(a),r.delete(i),n(o({settled:!0,state:e}))};r.add(i),By.set(e,r);let a=setTimeout(()=>{(async()=>{r.delete(i);let t=(await Y())[e];if(t)return n(o({settled:!1,state:Yy(Jy(t))}));let a=(await Ky()).find(t=>t.monitorId===e);n(a?o({settled:!0,state:a}):s(`MONITOR_NOT_FOUND`,`Monitor ${e} disappeared while waiting.`))})()},Math.min(t,xc))})}async function ob(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 sb(){let e=await Y();return Object.values(e).map(e=>Jy(e))}async function cb(){return Ky()}async function lb(e){if(e==null)return qy([]);await qy((await Ky()).filter(t=>t.monitorId!==e))}function ub(){t.tabs.onRemoved.addListener(e=>{(async()=>{for(let t of Object.values(await Y()))t.tabId===e&&await eb(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($f(t.url)===n.origin){let e=await Wy(async()=>{let e=await Y(),r=e[n.id];return r?(Xy(r,`Navigated to ${db(t.url)} — still watching.`),await Gy(e),{...r}):null});e&&Uy(Jy(e))}else await eb(n.id,`tab-navigated`,`The tab left ${n.host} for ${Qf(t.url)||`another page`}.`)})()}),t.alarms.onAlarm.addListener(e=>{if(e.name.startsWith(`browsentic/monitor-timeout:`)){eb(e.name.slice(Cc.length),`timeout`);return}e.name===`browsentic/monitor-watch`&&(async()=>{let e=Date.now();for(let t of Object.values(await Y())){if(await Qy(t),e-t.lastProgressAt<12e4||t.warnedStall)continue;let n=await Wy(async()=>{let n=await Y(),r=n[t.id];return!r||r.warnedStall?null:(r.warnedStall=!0,Xy(r,`No change for ${Math.round((e-r.lastProgressAt)/6e4)} minutes.`),await Gy(n),{...r})});n&&Uy(Jy(n))}})()}),t.notifications?.onClicked.addListener(e=>{if(!e.startsWith(`browsentic-monitor:`))return;let n=e.slice(Tc.length);(async()=>{let r=(await Ky()).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 db(e){try{let t=new URL(e);return t.pathname+t.search}catch{return e}}async function fb(e){let n=e.label??e.host,r={done:{title:`Done: ${n}`,message:`Finished after ${mb(e.elapsedMs)}.`},timeout:{title:`Still going: ${n}`,message:`Watched for ${mb(e.elapsedMs)} without completing.`},"tab-closed":{title:`Monitor ended — tab closed`,message:`${n} was closed before finishing.`},"tab-navigated":{title:`Monitor ended — tab moved on`,message:e.message??`The tab left ${e.host}.`}}[e.phase];r&&await t.notifications?.create(`${Tc}${e.monitorId}`,{type:`basic`,iconUrl:pb(),title:r.title,message:r.message}).catch(()=>void 0)}function pb(){let e=t.runtime.getManifest().icons??{};return e[Object.keys(e).map(Number).sort((e,t)=>t-e)[0]]??``}function mb(e){let t=Math.round(e/1e3);return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}var hb=`browsentic/timers`,gb=`browsentic/timersDone`,_b=null,vb=Promise.resolve();function yb(e){_b=e}function bb(e){let t=vb.then(e,e);return vb=t.catch(()=>void 0),t}async function xb(){return(await t.storage.session.get(hb))[hb]??{}}function Sb(e){return t.storage.session.set({[hb]:e})}async function Cb(){let e=(await t.storage.session.get(gb))[gb];return Array.isArray(e)?e:[]}function wb(e){return t.storage.session.set({[gb]:e})}function Tb(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 Eb(e){return{...e,logs:e.logs.slice(-5)}}function Db(e,t){e.logs.push({t:Date.now(),text:t}),e.logs.length>20&&e.logs.splice(0,e.logs.length-20)}var Ob=e=>e.label??`timer`;async function kb(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 bb(async()=>{let n=await xb();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 Db(i,`Scheduled to fire ${df(i)}.`),n[i.id]=i,await Sb(n),o(i)});if(!n.ok)return n;let r=n.data;return await Ab(r),o(Eb(Tb(r)))}function Ab(e){return t.alarms.create(cf(e.id),{when:e.nextFireAt,...e.repeat?{periodInMinutes:e.afterMs/6e4}:{}})}async function jb(e){let n=(await xb())[e];if(!n){await t.alarms.clear(cf(e));return}let r=await Mb(n);if(r===`gone`){await Nb(e,`orphaned`,`The conversation this timer belonged to is gone.`);return}let i=await bb(async()=>{let t=await xb(),n=t[e];if(!n)return null;let i=Date.now();return r===`busy`?(n.skipped+=1,Db(n,`Skipped — the conversation was still working on the previous turn.`)):(n.runs+=1,n.lastFiredAt=i,Db(n,`Fired — run ${n.runs}${n.repeat?` of ${n.maxRuns}`:``}.`)),n.nextFireAt=i+(n.repeat||r===`delivered`?n.afterMs:of),await Sb(t),{...n}});if(i){if(i.skipped>=20){await Nb(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 Nb(e,`finished`):await Ab(i);return}i.runs>=i.maxRuns&&await Nb(e,`finished`,`Fired ${i.runs} times, which is the limit that was set.`)}}async function Mb(e){return e.deliver===`notify`?(await zb(e.id,e.label??`Browsentic timer`,e.prompt),`delivered`):!e.sessionId||!_b?`gone`:_b(e.sessionId,e.prompt,Ob(e))}async function Nb(e,n,r){let i=await bb(async()=>{let t=await xb(),i=t[e];if(!i)return null;delete t[e],await Sb(t),Db(i,r??Pb(n));let a=Tb(i,n,r);return await wb([...await Cb(),a].slice(-6)),a});return i?(await t.alarms.clear(cf(e)),n===`orphaned`&&await zb(e,`Timer ended: ${i.label??`scheduled job`}`,`The conversation it was set in has closed, so it was cancelled.`),i):null}function Pb(e){return{finished:`The schedule ran out.`,stopped:`Cancelled.`,orphaned:`The conversation this timer belonged to is gone.`}[e]}async function Fb(e){let t=Object.values(await xb());if(e!=null){let t=await Nb(e,`stopped`);if(t)return o(Eb(t));let n=(await Cb()).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} · ${Ob(e)} (${df(e)})`).join(`; `);return s(`INVALID_TARGET`,`${t.length} timers are scheduled, so nothing was cancelled — cancel one by id: ${e}`)}let n=await Nb(t[0].id,`stopped`);return n?o(Eb(n)):s(`TIMER_NOT_FOUND`,`That timer just ended on its own.`)}async function Ib(e){let t=await xb(),n=await Cb();if(e!=null){let r=t[e];if(r)return o(Eb(Tb(r)));let i=n.find(t=>t.timerId===e);return i?o(Eb(i)):s(`TIMER_NOT_FOUND`,`No timer with id “${e}” is scheduled or recently finished.`)}return o({timers:[...Object.values(t).map(e=>Eb(Tb(e))),...n.map(Eb)]})}async function Lb(e){for(let t of Object.values(await xb()))t.sessionId===e&&await Nb(t.id,`orphaned`,`The conversation was ended.`)}function Rb(){t.alarms.onAlarm.addListener(e=>{e.name.startsWith(`browsentic/timer:`)&&jb(e.name.slice(sf.length))}),t.notifications?.onClicked.addListener(e=>{e.startsWith(`browsentic-timer:`)&&t.notifications.clear(e).catch(()=>void 0)})}async function zb(e,n,r){await t.notifications?.create(`${lf}${e}`,{type:`basic`,iconUrl:Bb(),title:n,message:r}).catch(()=>void 0)}function Bb(){let e=t.runtime.getManifest().icons??{};return e[Object.keys(e).map(Number).sort((e,t)=>t-e)[0]]??``}var Vb=`browsentic:shots`,Hb=e=>`browsentic:shot:${e}`,Ub=2,Wb=4e6,Gb=new Set;function Kb(e){Gb.add(e)}async function qb(e,t){if(!e.thumbnail)return;let n=crypto.randomUUID(),r=await Jb(n,e.dataUrl),i={previewId:n,thumbnail:e.thumbnail,width:e.width,height:e.height,full:r};for(let e of Gb)e(i,t)}async function Jb(e,n){if(n.length>Wb)return!1;try{let r=await t.storage.session.get(Vb),i=[e,...(Array.isArray(r[Vb])?r[Vb]:[]).filter(t=>t!==e)],a=i.slice(Ub);return await t.storage.session.set({[Hb(e)]:n,[Vb]:i.slice(0,Ub)}),a.length&&await t.storage.session.remove(a.map(Hb)),!0}catch{return!1}}var Yb=500,Xb=48,Zb=16384,Qb=Zb*Zb;async function $b(e,t,n){let r=await W(e.id,`page.screenshot`,t);if(!r.ok)return r;let i=r.data;try{let t=await tx(e,i);return ex(t,n),o(t)}catch(e){return e instanceof L?s(e.code,e.message):s(`CAPTURE_FAILED`,e instanceof Error?e.message:String(e))}finally{W(e.id,`page.scrollTo`,{position:{x:i.scroll.x,y:i.scroll.y},behavior:`instant`})}}async function ex(e,t){try{await qb({...e,thumbnail:await ix(e.dataUrl)},t)}catch{}}async function tx(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(Xb/Math.min(s,Xb))),l=!1;s>Xb&&(o.w=Xb*n.w,l=!0),Math.ceil(o.h/n.h)>c&&(o.h=c*n.h,l=!0);let u=lx(o.x,o.w,n.w),d=lx(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 W(e.id,`page.scrollTo`,{position:{x:c,y:s},behavior:`instant`});if(!u.ok)throw new L(u.error.message,u.error.code);let d=u.data,v=Date.now()-_;_&&v<Yb&&await ux(Yb-v);let ee=await cx(e.windowId,r,i);_=Date.now();let y=ee.bitmap;if(!m){let e=y.width/n.w||t.dpr||1;if(g=sx(o.w*e,o.h*e,a),h=e*g,f&&g===1){let{width:e,height:t}=y;return y.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 y.close(),new L(`OffscreenCanvas 2D context unavailable`,`CAPTURE_FAILED`)}p.drawImage(y,(d.scrollX-o.x)*h,(d.scrollY-o.y)*h,y.width*g,y.height*g),y.close()}if(!m)throw new L(`Nothing was captured`,`CAPTURE_FAILED`);return ox(m,r,i,l)}var nx=640,rx=.6;async function ix(e){let t=await createImageBitmap(await(await fetch(e)).blob()),n=Math.min(1,nx/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(),dx(await r.convertToBlob({type:`image/jpeg`,quality:rx}),`image/jpeg`)):(t.close(),``)}var ax=80;async function ox(e,t,n,r){let i=t===`jpeg`?`image/jpeg`:`image/png`,a=await dx(await e.convertToBlob(t===`jpeg`?{type:i,quality:(n??ax)/100}:{type:i}),i);return{format:t,width:e.width,height:e.height,dataUrl:a,...r?{truncated:r}:{}}}function sx(e,t,n){let r=Math.min(n,Zb)/Math.max(e,t,1),i=Math.sqrt(Qb/Math.max(e*t,1));return Math.min(1,r,i)}async function cx(e,n,r){let i=n===`jpeg`?r??ax: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 ux(Yb);continue}throw new L(`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 lx(e,t,n){let r=[];for(let i=e;i<e+t;i+=n)r.push(i);return r.length?r:[e]}var ux=e=>new Promise(t=>setTimeout(t,e));function dx(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 fx=16,px=1200,mx=.85,hx=120;async function gx(e,t){let n=await W(e.id,Ju.name,t);if(!n.ok)return n;let{capture:r,...i}=n.data,a=r?await _x(e.windowId,r).catch(()=>null):null;return o(a?{...i,shot:a}:i)}async function _x(e,t){let{viewport:n,dpr:r}=t,i=Math.max(0,t.region.x-fx),a=Math.max(0,t.region.y-fx),o=Math.min(n.w,t.region.x+t.region.w+fx)-i,s=Math.min(n.h,t.region.y+t.region.h+fx)-a;if(o<1||s<1)return null;await new Promise(e=>setTimeout(e,hx));let{bitmap:c}=await cx(e,`jpeg`,Math.round(mx*100)),l=c.width/n.w||r,u=Math.min(1,px/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 dx(await d.convertToBlob({type:`image/jpeg`,quality:mx}),`image/jpeg`),width:d.width,height:d.height}):(c.close(),null)}var vx=`browsentic/tabSessions`,yx=null,bx=Promise.resolve();function xx(e){let t=bx.then(e,e);return bx=t.catch(()=>void 0),t}async function X(){return yx||(yx=(await t.storage.session.get(`browsentic/tabSessions`))[`browsentic/tabSessions`]??{},yx)}function Sx(e){return xx(async()=>{let n={...await X()},r=await e(n);return yx=n,await t.storage.session.set({[vx]:n}),r})}async function Cx(e){let t=await X();return Object.values(t).find(t=>t.tabIds.includes(e))??null}async function wx(e){let t=await X();return Object.values(t).find(t=>t.runId===e)??null}async function Tx(e){return Sx(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=Nx(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??Nx(e.url)??`This tab`,url:e.url,host:Nx(e.url),runId:null,turns:0,createdAt:r,lastActivityAt:r};return t[i.sessionId]=i,{ok:!0,session:i}})}function Ex(e,t){return Sx(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??Nx(e.url)??`This tab`,url:e.url??t.url,host:Nx(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 Dx(e,t,n){return Sx(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 Ox(e,t){return Sx(n=>{let r=n[e];!r||!r.tabIds.includes(t)||(r.currentTabId=t,r.lastActivityAt=Date.now())})}function kx(e,t){return Sx(n=>{let r=n[e];r&&Object.assign(r,t,{lastActivityAt:Date.now()})})}function Ax(e){return Sx(t=>{let n=t[e]??null;return delete t[e],n})}function jx(e){return Sx(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 Mx(e,t){return Sx(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 Nx(e){if(e)try{return new URL(e).host||void 0}catch{return}}async function Px(e,t,n,r){let i=await tm(e,t);if(i.refused.length)return s(`SECRET_NOT_RELEASABLE`,Gp);if(i.unresolved.length)return s(`SECRET_EXPIRED`,Kp);let{value:a}=await em(await Lx(e,i.input,n,r),await Fx(n,r));return a}async function Fx(e,t){let n=await Bx(e,t?await wx(t):null);return n?.url?Ix(n.url):void 0}function Ix(e){try{return new URL(e).hostname.toLowerCase()||void 0}catch{return}}async function Lx(e,t,n,r){if(e===Du.name)return eS(t);if(e===Ou.name)return tS(t);if(e===pd.name)return nS(t);let i=r?await wx(r):null;if(e===Pu.name)return Vx(t,i);if(e===ef.name)return Ux(t,n??i?.currentTabId,i?.sessionId);if(e===dd.name)return Wx(t);if(e===fd.name)return Gx(t);if(e===pf.name)return Kx(t);if(e===tf.name)return qx(t,n??i?.currentTabId);if(e===Au.name)return Jx(t);if(e===mf.name)return Yx(t);if(e===Mc.name)return Xx(t);if(e===ff.name)return Zx(t,i?.sessionId);if(e===vf.name)return Qx(t);if(e===hf.name)return $x(t);let a=await Bx(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===Nu.name?aS(a.id,t):e===Wd.name?cS(a.id,t):e===_f.name?Hx({id:a.id,windowId:a.windowId},t,i):e===Lc.name?Nv({id:a.id,windowId:a.windowId},t):e===Vd.name?$b({id:a.id,windowId:a.windowId},t,r):e===Ju.name?gx({id:a.id,windowId:a.windowId},t):e===fc.name?rS(a.id,t):e===Pc.name?Kh(a.id,t):e===Tu.name?kh(a.id,a.url,t):e===Bd.name?Nh(a.id,a.url,t):e===pu.name?Hh(a.id,t):e===ku.name?Uh(a.id,a.url):e===Nc.name?Wh(a.id,a.url,t):e===yf.name?km(a.id,t):e===sl.name&&Rx(t)?Am(a.id,t):e===Tl.name?Im(a.id):e===$d.name?Lm(a.id,t):W(a.id,e,t)}function Rx(e){return e?.trusted===!0}async function zx(e){try{return await t.tabs.get(e)}catch{return}}async function Bx(e,n){return n?await zx(n.currentTabId)??await zx(n.mainTabId):e==null?(await t.tabs.query({active:!0,currentWindow:!0}))[0]:zx(e)}async function Vx(e,t){if(!t)return jv(e);let n=await zx(t.currentTabId)??await zx(t.mainTabId),r=await jv(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 Dx(t.sessionId,i,r.data.activeTabId===i),r}async function Hx(e,t,n){if(!n)return Mv(e,t);let r=t??{};if(typeof r.tabId==`number`&&!n.tabIds.includes(r.tabId)&&await Cx(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 Mv(e,t);if(!i.ok)return i;let a=i.data.activeTabId;return typeof a!=`number`||a===e.id||(n.tabIds.includes(a)?await Ox(n.sessionId,a):await Cx(a)||await Dx(n.sessionId,a,!0)),i}async function Ux(e,t,n){let r=ef.input.safeParse(e??{});return r.success?oy(r.data,t,n):s(`INVALID_INPUT`,S(r.error))}async function Wx(e){let t=dd.input.safeParse(e??{});return t.success?ly(t.data):s(`INVALID_INPUT`,S(t.error))}async function Gx(e){let t=fd.input.safeParse(e??{});return t.success?uy(t.data):s(`INVALID_INPUT`,S(t.error))}async function Kx(e){let t=pf.input.safeParse(e??{});return t.success?my(t.data.diagnosticsId):s(`INVALID_INPUT`,S(t.error))}async function qx(e,t){let n=tf.input.safeParse(e??{});return n.success?Zy(n.data,t):s(`INVALID_INPUT`,S(n.error))}async function Jx(e){let t=Au.input.safeParse(e??{});return t.success?ib(t.data.monitorId):s(`INVALID_INPUT`,S(t.error))}async function Yx(e){let t=mf.input.safeParse(e??{});return t.success?rb(t.data.monitorId):s(`INVALID_INPUT`,S(t.error))}async function Xx(e){let t=Mc.input.safeParse(e??{});return t.success?ab(t.data.monitorId,t.data.timeoutMs):s(`INVALID_INPUT`,S(t.error))}async function Zx(e,t){let n=ff.input.safeParse(e??{});return n.success?kb(n.data,t):s(`INVALID_INPUT`,S(n.error))}async function Qx(e){let t=vf.input.safeParse(e??{});return t.success?Ib(t.data.timerId):s(`INVALID_INPUT`,S(t.error))}async function $x(e){let t=hf.input.safeParse(e??{});return t.success?Fb(t.data.timerId):s(`INVALID_INPUT`,S(t.error))}async function eS(e){let t=e?.nameContains,n=typeof t==`string`?t.toLowerCase():null;return o({files:(await j_()).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 tS(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 ev()).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 nS(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 ev()).find(e=>e.id===t);if(!n)return s(`RECORDING_NOT_FOUND`,`No recording with id "${t}".`);let r=await rv(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 rS(e,t){let n=t??{};if(typeof n.content==`string`&&n.content)return W(e,fc.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 N_(r);return a?W(e,fc.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 iS=`Receiving end does not exist`;async function aS(e,t){let n=await W(e,Nu.name,t);return n.ok?o({...n.data,loaded:await Pv(e).settled}):n.error.code===`TAB_UNREACHABLE`?n.error.message.includes(iS)?oS(e,t):o({navigating:!0,loaded:await Pv(e).settled}):n}async function oS(e,n){let r=Nu.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(r.error));let i;try{i=Mu(r.data)}catch(e){return e instanceof L?s(e.code,e.message):s(`ACTION_FAILED`,String(e))}let a=Pv(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 sS=2e3;async function cS(e,t){let n=await W(e,Wd.name,t);if(!n.ok)return n;let r=n.data,i=await lS(e,r.via===`url`||r.submitted===!0);return o({...n.data,loaded:i,landedOn:(await zx(e))?.url})}async function lS(e,t){let n=Pv(e);if(t)return n.settled;let r=await Promise.race([n.settled,new Promise(e=>setTimeout(()=>e(null),sS))]);return r===null&&n.cancel(),r??!1}var uS=`browsentic:skills`,dS=e=>`browsentic:skill:${e}`;async function fS(){let e=(await t.storage.local.get(uS))[uS];return Array.isArray(e)?e:[]}async function pS(e){await t.storage.local.set({[uS]:e})}async function mS(e){let n=dS(e),r=(await t.storage.local.get(n))[n];return r&&typeof r.body==`string`?r:null}async function hS(e,t){await pS((await fS()).map(n=>n.id===e?{...n,...t}:n))}async function gS(e){let t=(await fS()).find(t=>t.id===e);if(t?.origin===`generated`)return;let n=await mS(e);if(!t||!n){await hS(e,{status:`error`,error:`The skill is missing from storage.`});return}let r=await Ug({name:t.name,description:t.description,category:t.category,domains:t.domains,triggers:n.triggers,body:n.body});r.ok?await hS(e,{status:`saved`,path:r.data.path,error:void 0}):await hS(e,{status:`error`,error:`${r.error.code}: ${r.error.message}`})}async function _S(e){let n=(await fS()).find(t=>t.id===e);n&&await(n.origin===`generated`?Gg(n.name):Wg(n.name)),await t.storage.local.remove(dS(e)),await pS((await fS()).filter(t=>t.id!==e))}async function vS(e){let t=await fS();await pS([{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 yS(){for(let e of await fS())e.status!==`saved`&&e.origin!==`generated`&&await gS(e.id)}var bS=`browsentic:sessions`,xS=e=>`browsentic:session:${e}`,SS=50,CS=[1,5,15];async function wS(){let e=(await t.storage.local.get(bS))[bS];return Array.isArray(e)?e:[]}async function TS(e){await t.storage.local.set({[bS]:e})}async function ES(e,n){if(!n.length)return;let r={id:e.id,items:n.slice(-500).map(DS)};await t.storage.local.set({[xS(e.id)]:r});let i=await wS(),a=[{...i.find(t=>t.id===e.id),...e},...i.filter(t=>t.id!==e.id)],o=a.slice(SS);o.length&&await t.storage.local.remove(o.map(e=>xS(e.id))),await TS(a.slice(0,SS))}function DS(e){if(e.kind!==`tool`||!e.preview)return e;let{preview:t,...n}=e;return n}async function OS(e){let n=xS(e),r=(await t.storage.local.get(n))[n];return r&&Array.isArray(r.items)?r:null}async function kS(e,t){let n=await wS();n.some(t=>t.id===e)&&await TS(n.map(n=>n.id===e?{...n,...t}:n))}var AS=60;async function jS(e){let t=(await wS()).find(t=>t.id===e);if(!t)return;let n=((await OS(e))?.items??[]).filter(e=>e.kind===`user`).map(e=>e.text).slice(-12);if(!n.length)return;let r=t.turns;await kS(e,{namingAt:Date.now()});let i=await Bg({host:t.host,messages:n});if(i.ok&&i.data.title.trim()){await kS(e,{title:i.data.title.replace(/\s+/g,` `).trim().slice(0,AS),titledAtTurn:r,namingAt:void 0});return}await kS(e,{titledAtTurn:r,namingAt:void 0})}function MS(e,t=0){let n=CS.filter(t=>e>=t).at(-1);return n!==void 0&&n>t?n:null}var NS=`/context`,PS=e=>e.trim().toLowerCase()===NS;async function FS(e){let{offer:t,code:n}=e,r={host:t.host,segment:t.segment},i=oh(e.slug??``)||t.suggestedSlug,a=await gh(r,i),o={id:crypto.randomUUID(),name:a,skillName:lh(r,i),description:t.purpose,scope:r,origin:t.origin,code:n,fn:t.fn,createdAt:Date.now()};return await mh(o),await Ug(LS(o)).catch(()=>void 0),dh(o)}async function IS(e){let t=await hh(e);return t&&await Wg(t.skillName).catch(()=>void 0),t}function LS(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 RS=/\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,zS=/^(?: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+/,BS=/\s+(?:please|thanks|thank you|for me|now|a bit|a little|a lot|some more|more|slightly|real quick|quickly)$/,VS=/[^a-z0-9\s./:&=@_+#-]/g;function HS(e){let t=e.trim(),n=t.toLowerCase().replace(/['‘’]/g,``);n=n.replace(RS,`$1.$2`),n=n.replace(VS,` `).replace(/\s+/g,` `).trim();let r=!1,i;do i=n,n=n.replace(zS,``).replace(BS,``).trim(),r||=n!==i;while(n!==i);return{text:n.replace(/\.$/,``),raw:t,question:/\?\s*$/.test(t)&&!r}}var US={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`},WS=new Set([`enter`,`return`]),GS={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`},KS=Object.keys(GS).join(`|`),qS=/\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/,JS=/^(?:it|that|this|there|them|those|these|him|her|thing|one)$/,YS=8,XS=[{id:`history.back`,action:Nu.name,certainty:.97,pattern:/^(?:go\s+)?back(?:\s+(?:a|one)\s+page)?$/,build:()=>QS({action:`back`},`Go back`)},{id:`history.forward`,action:Nu.name,certainty:.97,pattern:/^(?:go\s+)?forwards?(?:\s+(?:a|one)\s+page)?$/,build:()=>QS({action:`forward`},`Go forward`)},{id:`history.reload`,action:Nu.name,certainty:.97,pattern:/^(?:reload|refresh)(?:\s+(?:the|this)\s+page)?$/,build:()=>QS({action:`reload`},`Reload the page`)},{id:`tab.open`,action:Pu.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=US[e];if(t)return $S({url:`https://${t}`},`Open ${t} in a new tab`,1);let n=nC(e);return n?$S({url:n},`Open ${e} in a new tab`,/^https?:\/\//.test(e)?1:.97):null}},{id:`navigate.url`,action:Nu.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=US[e];if(t)return QS({url:`https://${t}`},`Open ${t}`,1);let n=nC(e);return n?QS({url:n},`Open ${e}`,/^https?:\/\//.test(e)?1:.97):null}},{id:`navigate.search`,action:Nu.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:QS({url:`https://www.google.com/search?q=${encodeURIComponent(n)}`},`Search the web for "${n}"`,e===`google`?.95:1)}},{id:`site.search`,action:Wd.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?ZS({query:t},`Search this site for "${t}"`):null}},{id:`scroll.direction`,action:Hd.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})=>eC({direction:e},`Scroll ${e}`)},{id:`scroll.page`,action:Hd.name,certainty:.95,pattern:/^page\s+(?<dir>up|down)$/,build:({dir:e})=>eC({direction:e},`Scroll ${e}`)},{id:`scroll.element`,action:Hd.name,certainty:.85,pattern:/^scroll\s+(?:down\s+)?to\s+(?:the\s+)?(?<label>.+)$/,build:({label:e})=>{let t=tC(e);return t&&eC({target:{text:t.value}},`Scroll to ${t.value}`,t.confidence)}},{id:`key.press`,action:Yu.name,certainty:.97,pattern:RegExp(`^(?:press|hit|tap|push)(?:\\s+the)?\\s+(?<key>${KS})(?:\\s+key)?$`),build:({key:e})=>{let t=GS[e];return t?ZS({key:t},`Press ${e}`):null}},{id:`recording.start`,action:Hf,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:()=>ZS({captureValues:!1},`Start recording this session`)},{id:`recording.stop`,action:Uf,certainty:.95,pattern:/^(?:stop|end|finish)\s+(?:the\s+)?recording$/,build:()=>ZS({},`Stop recording`)},{id:`monitor.stop`,action:mf.name,certainty:.95,pattern:/^(?:stop|end|quit|cancel)\s+(?:the\s+)?(?:monitor(?:ing)?|watching)(?:\s+(?:the|this|that)\s+\S{1,20})?$/,build:()=>ZS({},`Stop monitoring`)},{id:`click.text`,action:Ic.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=tC(e);return!n||!t&&WS.has(n.value.toLowerCase())?null:{input:{target:t?{text:n.value,role:t}:{text:n.value}},label:`Click ${n.value}`,confidence:n.confidence,risky:qS.test(n.value)}}}],ZS=(e,t,n=1)=>({input:e,label:t,confidence:n}),QS=(e,t,n=1)=>ZS(e,t,n),$S=(e,t,n=1)=>ZS(e,t,n),eC=(e,t,n=1)=>ZS(e,t,n);function tC(e){let t=e.trim();if(!t)return null;let n=t.split(/\s+/);if(n.length>YS)return null;if(JS.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 nC(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 rC=/^(?: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/,iC=/\b(?:and then|then|after that|and also|followed by)\b/,aC=/\b(?:if|unless|whenever|maybe|might|try to|see if|as soon as|in case|otherwise)\b/;function oC(e){let t=HS(e);if(t.raw.startsWith(`@`))return sC(`skill-prefix`,0);if(!t.text)return sC(`no-match`,0);if(t.question||rC.test(t.text))return sC(`question`,0);if(iC.test(t.text))return sC(`multi-step`,0);if(aC.test(t.text))return sC(`conditional`,0);let n=null;for(let e of XS){let r=e.pattern.exec(t.text);if(!r)continue;let i=e.build(r.groups??{});if(!i)continue;let a=cC(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?sC(`consequential`,n.score,n.rule.id):n.score<.75?sC(`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}}:sC(`no-match`,0)}var sC=(e,t,n)=>({decision:`escalate`,reason:e,score:t,ruleId:n}),cC=e=>Math.round(e*1e3)/1e3;async function lC(e,t,n){let r=oC(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 uC(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||dC(i)?!0:(console.debug(`[browsentic] fast path ${s} (${c}) failed, escalating:`,d.error.code),!1)}async function uC(e,t,n){return e===Hf?bv(t?.captureValues===!0):e===Uf?Cv(`user`):Px(e,t,n)}function dC(e){return e===Hf||e===Uf}var fC=`browsentic/indicator`,pC=`#ff7a3d`,mC=`browsentic/rail`;function hC(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.channel===`browsentic/rail`&&(t.op===`open`||t.op===`sync`)}var gC=`browsentic/panelCollapsed`,_C=`browsentic/panelTab`;async function vC(){return(await t.storage.local.get(gC))[gC]===!0}async function yC(){let e=(await t.storage.local.get(_C))[_C];return typeof e==`string`?e:`chat`}var bC=[{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.`}],xC=`ember`,SC=`browsentic/theme`;function CC(e){return bC.some(t=>t.id===e)?e:xC}async function wC(){return CC((await t.storage.local.get(SC))[SC])}function TC(e){return t.sidePanel.open({windowId:e})}var EC=`browsentic/daemon`;async function DC(e){await t.storage.local.set({[gC]:e}),await jC()}var OC=null,kC=!1,AC=null;function jC(){return OC?(kC=!0,OC):(OC=(async()=>{do kC=!1,await NC();while(kC);OC=null})(),OC)}async function MC(){await vC()||(AC=null,await jC())}async function NC(){let e=await vC();if(!e&&AC===!1)return;let n=e?{channel:mC,op:`show`,view:await IC()}:{channel:mC,op:`hide`},r=await t.tabs.query({});await Promise.all(r.map(e=>FC(e.id,e.discarded,n))),AC=e}async function PC(e){await vC()&&await FC(e,!1,{channel:mC,op:`show`,view:await IC()})}function FC(e,n,r){if(!(e==null||n))return t.tabs.sendMessage(e,r).catch(()=>void 0)}async function IC(){let[e,t,n,r,i,a,o,s]=await Promise.all([RC(),wS(),fS(),ev(),X(),yC(),zC(),wC()]),c=Object.values(i).filter(e=>e.runId).length,l=LC(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 LC(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 RC(){return(await t.storage.session.get(EC))[EC]??null}async function zC(){let e=t.sidePanel;if(!e.getLayout)return`right`;try{return(await e.getLayout()).side===`left`?`left`:`right`}catch{return`right`}}function BC(){t.runtime.onMessage.addListener((e,n)=>{if(!hC(e))return;let{id:r,windowId:i}=n.tab??{};if(!(r==null||i==null))return e.op===`sync`?(PC(r),Promise.resolve({ok:!0})):(TC(i).catch(()=>void 0),t.storage.local.set({[_C]:e.tab}),Promise.resolve({ok:!0}))}),t.tabs.onUpdated.addListener((e,t)=>{t.status===`complete`&&PC(e)}),t.storage.local.onChanged.addListener(e=>{(`browsentic/panelCollapsed`in e||`browsentic/panelTab`in e||`browsentic/theme`in e)&&jC()}),t.storage.session.onChanged.addListener(e=>{EC in e&&jC()})}var VC=`●`,HC=new Set;function UC(){return t.action??null}async function WC(){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)HC.has(t)||await KC(t,!0);for(let t of[...HC])e.has(t)||await KC(t,!1);await jC()}function GC(e){HC.delete(e)}async function KC(e,n){n?HC.add(e):HC.delete(e);let r=UC();if(r)try{await r.setBadgeBackgroundColor({tabId:e,color:pC}),await r.setBadgeText({tabId:e,text:n?VC:``})}catch{HC.delete(e)}await t.tabs.sendMessage(e,{channel:fC,op:n?`busy`:`idle`}).catch(()=>void 0)}var qC=`[redacted]`,JC=200,YC=20,XC=4;function ZC(e,t,n){if(typeof t==`string`)return Xf({name:e,id:e,value:t})?qC:t.length>JC?`${t.slice(0,JC)}…`:t;if(typeof t==`number`||typeof t==`boolean`||t===null)return t;if(n>=XC)return`[…]`;if(Array.isArray(t)){let r=t.slice(0,YC).map(t=>ZC(e,t,n+1));return t.length>YC?[...r,`…`]:r}if(typeof t==`object`){let e={};for(let[r,i]of Object.entries(t))e[r]=Xf({name:r,id:r})?qC:ZC(r,i,n+1);return e}return null}var QC={"page.fillInput":`value`,"page.typeText":`text`},$C={"page.injectCode":[`purpose`,`code`]};function ew(e,t){if(!t||typeof t!=`object`)return ZC(``,t,0);let n=ZC(``,t,0);for(let r of $C[e]??[]){let e=t[r];typeof e==`string`&&(n[r]=e)}let r=QC[e];if(r&&r in n){let e=t[r],i=typeof e==`string`?Pp(e):[];n[r]=i.length?i.map(e=>e.text).join(` `):qC}return n}var tw=()=>crypto.randomUUID();function nw(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:tw(),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:tw(),text:t.delta}]}case`tool`:return[...e,{kind:`tool`,id:t.toolId,action:t.action,input:ew(t.action,t.input),source:t.source}];case`approval`:return rw(e,t.toolId,{awaiting:!0,site:t.site});case`toolResult`:return rw(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:tw(),tone:`info`,text:`Stopped: ${t.stopReason}`}];case`error`:return[...e,{kind:`notice`,id:tw(),tone:`error`,text:`${t.code}: ${t.message}`}]}}function rw(e,t,n){return e.map(e=>e.kind===`tool`&&e.id===t?{...e,...n}:e)}function iw(e,t){for(let n=e.length-1;n>=0;n--){let r=e[n];if(r.kind===`tool`&&r.action===Vd.name&&!r.preview){let i=[...e];return i[n]={...r,preview:t},i}}return e}function aw(e,t){return{kind:`notice`,id:tw(),tone:e,text:t}}function ow(e){let t=e.label??e.host,n=sw(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 sw(e){let t=Math.floor(e/1e3);return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}var cw=`local`,lw=4e3,uw=800,dw=new Set,fw=new Set,pw=new Set,Z=new Map,mw=new Set,hw=new Map,gw=new Map,_w=[],vw=new Map,yw=new Map,bw=Promise.resolve();function Q(e){let t=bw.then(e,e);return bw=t.catch(()=>void 0),t}function xw(){kg((e,t)=>{Q(()=>Dw(e,t))}),Kb((e,t)=>{Q(async()=>{let n=t?await wx(t):null;if(n){let t=iw(await Lw(n.sessionId),e);Z.set(n.sessionId,t)}$({op:`preview`,sessionId:n?.sessionId,preview:e})})}),Ch(e=>{yw.set(e.toolkitId,e),$({op:`toolOffer`,offer:e})}),Hy(e=>{$({op:`monitor`,state:e}),e.phase!==`watching`&&(Q(async()=>{let t=e.tabId==null?null:await Cx(e.tabId);t&&await Rw(t.sessionId,aw(...Xw(e)))}),dw.size>0&&lb(e.monitorId))}),yb((e,t,n)=>Q(async()=>{let r=(await X())[e];return r?r.runId||mw.has(e)?`busy`:(await Rw(e,aw(`info`,`Timer “${n}” fired.`)),await Aw(r,t,{fastPath:!1}),`delivered`):`gone`})),Og((e,t)=>{Q(async()=>{let n=await wx(e);if(n)for(let[e,t]of vw)t.sessionId===n.sessionId&&vw.delete(e);vw.set(t.stagingId,{sessionId:n?.sessionId,draft:t}),$({op:`mapDraft`,sessionId:n?.sessionId,draft:t})})}),Ag(()=>{Q(async()=>{for(let e of Object.values(await X()))e.runId&&await Nw(e.sessionId,`The connection to the daemon dropped, so that run is over.`)})}),mv(e=>{e?.warning&&$({op:`event`,runId:cw,event:{kind:`error`,code:`RECORDING_LIMIT`,message:e.warning}}),$({op:`recording`,state:e})}),t.runtime.onConnect.addListener(e=>{if(e.name===`browsentic/run`){if(dw.add(e),e.sender?.url?.includes(`sidepanel.html`)&&(fw.add(e),fw.size===1))for(let e of pw)e(!0);for(let t of vw.values())$w(e,{op:`mapDraft`,sessionId:t.sessionId,draft:t.draft});vv().then(t=>$w(e,{op:`recording`,state:t})),fh().then(t=>$w(e,{op:`tools`,tools:t.map(dh)})),sb().then(t=>{for(let n of t)$w(e,{op:`monitor`,state:n})}),cb().then(t=>{if(t.length){for(let n of t)$w(e,{op:`monitor`,state:n});lb()}}),e.onMessage.addListener(e=>ww(e)),e.onDisconnect.addListener(()=>{if(dw.delete(e),fw.delete(e)&&fw.size===0)for(let e of pw)e(!1)})}})}function Sw(e){pw.add(e)}function Cw(){for(let e of fw)$w(e,{op:`close`})}function ww(e){switch(e.op){case`instruct`:Q(()=>kw(e.text,e.tab,e.agentSkillId,e.focus,e.liveTools));return;case`cancel`:Q(()=>Mw(e.sessionId));return;case`decision`:Q(async()=>{let t=(await X())[e.sessionId];t?.runId&&(Z.set(e.sessionId,rw(await Lw(e.sessionId),e.toolId,{awaiting:!1})),await kx(e.sessionId,{pendingApproval:void 0}),l_(t.runId,e.toolId,e.allow,e.remember))});return;case`endSession`:Q(()=>Fw(e.sessionId));return;case`replay`:Q(async()=>{$({op:`items`,sessionId:e.sessionId,items:await Lw(e.sessionId)})});return;case`restore`:Q(()=>Iw(e.sessionId,e.tab));return;case`activateMap`:case`discardMap`:{let t=vw.get(e.stagingId);(e.op===`activateMap`?Kg(e.stagingId,e.exactHost):qg(e.stagingId)).then(n=>{if(n.ok&&e.op===`activateMap`&&t){let{draft:n}=t;vS({name:n.name,domain:e.exactHost?n.host:n.domain,directory:n.directory,pages:n.pages,generatedAt:n.generatedAt})}vw.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`:Hw(e.captureValues);return;case`stopRecording`:Cv(`user`);return;case`stopMonitor`:rb(e.monitorId);return;case`keepTool`:Q(async()=>{let t=yw.get(e.toolkitId),n=t?await Mh(e.tabId,e.toolkitId):null;t&&n&&await FS({offer:t,code:n,slug:e.slug}).catch(()=>void 0),yw.delete(e.toolkitId),$({op:`toolOfferSettled`,toolkitId:e.toolkitId}),await Ew()});return;case`dismissTool`:yw.delete(e.toolkitId),$({op:`toolOfferSettled`,toolkitId:e.toolkitId});return;case`forgetTool`:Q(async()=>{await IS(e.id),await Ew()});return;case`runTool`:Q(async()=>{let t=await jh(e.tab.tabId,e.tab.url,e.id);$({op:`item`,item:Tw(e.id,t)})});return;case`listTools`:Ew();return}}function Tw(e,t){return t.ok?{kind:`tool`,id:tw(),action:`savedTool`,input:{tool:e},ok:!0,source:`local`}:aw(`error`,`${t.error?.code}: ${t.error?.message}`)}async function Ew(){$({op:`tools`,tools:(await fh()).map(dh)})}async function Dw(e,t){if(e===`external`){_w=nw(_w,t).slice(-100),$({op:`event`,runId:e,event:t});return}let n=await wx(e);if(!n)return;let{sessionId:r}=n;Z.set(r,nw(await Lw(r),t)),$({op:`event`,sessionId:r,runId:e,event:t}),t.kind===`session`?await kx(r,{agent:t.agent,agentSessionId:t.agentSessionId??void 0}):t.kind===`approval`?await kx(r,{pendingApproval:{toolId:t.toolId,action:t.action,input:t.input,site:t.site}}):t.kind===`toolResult`?await kx(r,{pendingApproval:void 0}):t.kind===`usage`&&await kx(r,{usage:t.usage}),t.kind===`done`||t.kind===`error`?await Ow(r):zw(r)}async function Ow(e){clearTimeout(gw.get(e)),gw.delete(e),await xy(e),await kx(e,{runId:null,pendingApproval:void 0}),await WC();let n=(await X())[e];if(n){let r=await t.tabs.get(n.currentTabId).catch(()=>null);r?.url&&await kx(e,{url:r.url,host:Nx(r.url)})}await Bw(e);let r=(await wS()).find(t=>t.id===e);!r||MS(r.turns,r.titledAtTurn)===null||await jS(e).catch(()=>void 0)}async function kw(e,t,n,r,i){let a=await Tx(t);if(!a.ok){$({op:`event`,runId:cw,event:{kind:`error`,code:`SESSION_LIMIT`,message:a.message}});return}if(PS(e)){let{sessionId:e}=a.session,t=await Yw(a.session,await Lw(e));await Rw(e,{kind:`user`,id:tw(),text:NS}),await Rw(e,{kind:`context`,id:tw(),breakdown:t});return}await Aw(a.session,e,{agentSkillId:n,focus:r,liveTools:i,fastPath:!0})===`busy`&&await Rw(a.session.sessionId,aw(`error`,`RUN_IN_PROGRESS: This conversation is still running — stop it before sending another instruction.`))}async function Aw(e,t,n){let{agentSkillId:r,focus:i,liveTools:a,fastPath:o}=n,{sessionId:s}=e;if(e.runId||mw.has(s))return`busy`;await Rw(s,{kind:`user`,id:crypto.randomUUID(),text:t,focus:i&&Uw(i)}),await kx(s,{turns:e.turns+1}),mw.add(s);try{if(o&&!r&&!i&&await jw(t,e))return await Bw(s),`local`;let n=jg(t,{url:e.url,tabId:e.currentTabId,sessionId:s,agent:e.agent,agentSessionId:e.agentSessionId,agentSkillId:r,focus:i,liveTools:a,files:await Kw(),recordings:await Jw()});return n?(await kx(s,{runId:n}),await WC(),`started`):(await Rw(s,aw(`error`,`EXTENSION_OFFLINE: No Browsentic daemon is attached, so only quick browser commands work. Pair the browser to do more.`)),await Bw(s),`offline`)}finally{mw.delete(s)}}async function jw(e,t){try{return await lC(e,e=>{Z.set(t.sessionId,nw(Z.get(t.sessionId)??[],e)),$({op:`event`,sessionId:t.sessionId,runId:cw,event:e})},t.currentTabId)}catch(e){return console.warn(`[browsentic] fast path threw, escalating:`,e),!1}}async function Mw(e){let t=(await X())[e]?.runId;if(t){if(!c_(t)){await Nw(e,`The daemon is not connected, so there was nothing left to stop.`);return}clearTimeout(gw.get(e)),gw.set(e,setTimeout(()=>{Q(async()=>{(await X())[e]?.runId===t&&await Nw(e,`Stopped. The daemon never confirmed it, so check for a run still finishing there.`)})},lw))}}async function Nw(e,t){await Rw(e,aw(`error`,`CANCELLED: ${t}`)),await Ow(e)}function Pw(e){for(let t of vw.values())t.sessionId===e&&(t.sessionId=void 0,$({op:`mapDraft`,draft:t.draft}))}async function Fw(e){let t=(await X())[e];t?.runId&&c_(t.runId),await xy(e),await Lb(e),clearTimeout(gw.get(e)),gw.delete(e),await Bw(e),await Ax(e),Z.delete(e),mw.delete(e),Pw(e),u_(e),await WC()}async function Iw(e,t){if(Object.values(await X()).find(t=>t.sessionId===e))return;let n=await Cx(t.tabId);if(n?.runId){await Rw(n.sessionId,aw(`error`,`RUN_IN_PROGRESS: This tab is still running — stop it before opening another conversation here.`));return}n&&(await Bw(n.sessionId),await Ax(n.sessionId),Z.delete(n.sessionId),Pw(n.sessionId));let r=(await wS()).find(t=>t.id===e);if(!r)return;let i=await OS(e);Z.set(e,i?.items??[aw(`error`,`That conversation’s messages are no longer stored.`)]);let a=await Ex({sessionId:e,turns:r.turns,agent:r.agent,agentSessionId:r.agentSessionId,usage:r.usage,url:r.url,title:Zw(r)??t.title},t);$({op:`items`,sessionId:e,items:Z.get(e)??[]}),r.url&&/^https?:$/.test(Qw(r.url))&&await Px(Nu.name,{url:r.url},a.currentTabId).catch(()=>void 0)}async function Lw(e){let t=Z.get(e);if(t)return t;let n=(await OS(e))?.items??[];return Z.set(e,n),n}async function Rw(e,t){Z.set(e,[...await Lw(e),t]),$({op:`item`,sessionId:e,item:t}),zw(e)}function zw(e){clearTimeout(hw.get(e)),hw.set(e,setTimeout(()=>void Q(()=>Bw(e)),uw))}async function Bw(e){clearTimeout(hw.get(e)),hw.delete(e);let t=Z.get(e);if(!t?.length)return;let n=(await X())[e],r=n?null:(await wS()).find(t=>t.id===e),i=Date.now();await ES({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 Vw(){t.tabs.onRemoved.addListener(e=>{GC(e),Q(async()=>{let{closed:t}=await jx(e);if(!t)return await WC();t.runId&&(c_(t.runId),await Rw(t.sessionId,aw(`error`,`CANCELLED: The tab was closed, so that run is over.`))),clearTimeout(gw.get(t.sessionId)),gw.delete(t.sessionId),await Lb(t.sessionId),await Bw(t.sessionId),Z.delete(t.sessionId),mw.delete(t.sessionId),Pw(t.sessionId),t.runId&&u_(t.sessionId),await WC()})}),t.tabs.onReplaced.addListener((e,t)=>{Q(()=>Mx(t,e))}),t.tabs.onUpdated.addListener((e,t,n)=>{t.title===void 0&&t.url===void 0||Q(async()=>{let r=await Cx(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=Nx(t.url)),Object.keys(i).length&&await kx(r.sessionId,i)})})}async function Hw(e){let t=await bv(e);t.ok||$({op:`event`,runId:cw,event:{kind:`error`,code:t.error.code,message:t.error.message}})}var Uw=e=>[e.role??e.tag,e.label].filter(Boolean).join(` · `),Ww=6,Gw=2e3;async function Kw(){try{return(await j_()).slice(0,Ww).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,Gw)}))}catch{return[]}}var qw=8;async function Jw(){try{return(await ev()).filter(e=>e.status===`ready`).slice(0,qw).map(lv)}catch{return[]}}async function Yw(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 j_().catch(()=>[]),i=(await ev().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,Ww).map(e=>({name:e.name,size:e.size,status:e.status})),filesOmitted:Math.max(0,r.length-Ww),recordings:i.slice(0,qw).map(e=>({name:e.name,steps:e.steps})),recordingsOmitted:Math.max(0,i.length-qw),capturedAt:Date.now()}}var Xw=e=>{let{tone:t,text:n}=ow(e);return[t,n]},Zw=e=>e.title??void 0;function Qw(e){try{return new URL(e).protocol}catch{return``}}function $(e){for(let t of dw)$w(t,e)}function $w(e,t){try{e.postMessage(t)}catch{dw.delete(e)}}var eT=[`claude`,`codex`,`antigravity`],tT={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`]}};eT.map(e=>tT[e]);function nT(e){return typeof e==`string`&&eT.includes(e)}var rT=`open-side-panel`,iT=e(()=>{mm(),t.runtime.onMessage.addListener((e,t,n)=>{if(c(e)){if(e.op===`describe`){n(o(Pf()));return}if(e.op===`invoke`&&typeof e.action==`string`)return Px(e.action,e.input).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`analyzeFile`&&typeof e.fileId==`string`){F_(e.fileId),n(o(!0));return}if(e.op===`saveSkill`&&typeof e.skillId==`string`){gS(e.skillId),n(o(!0));return}if(e.op===`removeSkill`&&typeof e.skillId==`string`){_S(e.skillId),n(o(!0));return}if(e.op===`nameSession`&&typeof e.sessionId==`string`){jS(e.sessionId),n(o(!0));return}if(e.op===`recordEvents`&&Array.isArray(e.events)){Sv(t.tab?.id,e.events),n(o(!0));return}if(e.op===`recordingState`)return yv(t.tab?.id).then(e=>n(o(e))).catch(()=>n(o({recording:!1,captureValues:!1}))),!0;if(e.op===`analyzeRecording`&&typeof e.recordingId==`string`){av(e.recordingId),n(o(!0));return}if(e.op===`monitorSample`&&typeof e.monitorId==`string`){$y(t.tab?.id,e.monitorId,e.sample),n(o(!0));return}if(e.op===`monitorState`)return ob(t.tab?.id).then(n).catch(()=>n(o({monitors:[]}))),!0;if(e.op===`listSkills`)return r_(e.refresh===!0).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`agentState`)return Zg(e.refresh===!0).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`setAgent`&&nT(e.agent))return Qg(e.agent).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`setAgentModel`&&nT(e.agent))return $g(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`&&nT(e.agent))return e_(e.agent).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`guardrails`)return a_().then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`setGuardrail`&&typeof e.setting==`string`)return o_(e.setting,e.value).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`pair`&&typeof e.token==`string`)return f_(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`){DC(!1),n(o(!0));return}if(e.op===`disconnect`)return p_().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&&Rf(t.id)})});let e=t.contextMenus.removeAll().then(()=>t.contextMenus.create({id:rT,title:`Open Browsentic`,contexts:[`all`]})),n=!1;Sw(r=>{n=r,e.then(()=>t.contextMenus.update(rT,{title:r?`Close Browsentic`:`Open Browsentic`})),r||MC()}),t.contextMenus.onClicked.addListener((e,t)=>{if(!(e.menuItemId!==rT||t?.windowId==null)){if(n){Cw();return}TC(t.windowId)}}),Cy(),Dh(),wv(),ub(),Rb(),xw(),Vw(),BC(),jC(),Ag(()=>{yS(),ov()}),d_(),t.runtime.onStartup.addListener(()=>void d_()),t.alarms.create(_g,{periodInMinutes:1}),t.alarms.onAlarm.addListener(e=>{e.name===`browsentic/reconnect`&&d_()})}),aT={debug:(...e)=>([...e],void 0),log:(...e)=>([...e],void 0),warn:(...e)=>([...e],void 0),error:(...e)=>([...e],void 0)},oT;try{oT=iT.main(),oT instanceof Promise&&console.warn(`The background's main() function return a promise, but it must be synchronous`)}catch(e){throw aT.error(`The background crashed on startup!`),e}return oT})();
183
+ `?`Enter`:t);e.dispatchEvent(new KeyboardEvent(`keydown`,n))&&(e.dispatchEvent(new KeyboardEvent(`keypress`,n)),Af(e,t)),e.dispatchEvent(new KeyboardEvent(`keyup`,n))}var Mf=I({name:`page.waitForElement`,description:`Wait until an element reaches a state: attached, visible, hidden, or detached.`,input:P({target:B.describe(`Element to wait for`),state:F([`attached`,`visible`,`hidden`,`detached`]).default(`visible`).describe(`State to wait for: present in the DOM, present and visible, invisible or absent, or absent`),timeoutMs:M().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 V(e,{includeHidden:!0})}catch(e){if(e instanceof L&&e.code===`INVALID_TARGET`)throw e;return null}},i=e=>({attached:!!e,visible:!!e&&oc(e),hidden:!e||!oc(e),detached:!e})[t],a=performance.now(),o=r();return i(o)?{state:t,elapsedMs:0,element:o?U(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 L(`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?U(o):void 0})}}),Nf=new Map([pu,Hd,Ic,yf,Tl,$d,wu,sl,uu,Sl,Ef,Yd,Xd,vl,Ju,Yu,gf,Mf,Tu,Bd,ku,Nc,kl,lu,gd,mc,Vs,ef,dd,fd,pf,tf,Au,Mc,mf,ff,vf,hf,Cu,Wd,Nu,Pu,_f,Lc,Vd,Du,fc,Pc,Eu,Ou,pd].map(e=>[e.name,e]));function Pf(){return[...Nf.values()].map(({name:e,description:t,input:n})=>({name:e,description:t,inputSchema:$i(n,{io:`input`})}))}var Ff=`Receiving end does not exist`,If=new Set([`page.getPageInfo`,`page.extractText`,`page.waitForElement`,`page.navigate`]);async function W(e,r,...[i]){let a=typeof r==`string`?r:r.name,o=async()=>await t.tabs.sendMessage(e,{channel:n,action:a,input:i});try{return await o()}catch(t){let n=t instanceof Error?t.message:String(t);if(!n.includes(Ff)||!await Rf(e))return Bf(n);if(!If.has(a))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 o()}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 Lf=5e3;async function Rf(e){let n=(t.runtime.getManifest().content_scripts??[]).flatMap(e=>e.js??[]);if(!n.length)return!1;try{return await zf(t.scripting.executeScript({target:{tabId:e},files:n,injectImmediately:!0})),!0}catch{return!1}}function zf(e){return Promise.race([e,new Promise((e,t)=>setTimeout(()=>t(Error(`injection timed out`)),Lf))])}var Bf=e=>s(`TAB_UNREACHABLE`,`${e} — the page may not allow content scripts`),Vf=`browsentic.`;`${Vf}`;var Hf=`${Vf}startRecording`,Uf=`${Vf}stopRecording`;`${Vf}`,`${Vf}`;var Wf=`browsentic/record`,Gf=2e3,Kf=15*6e4,qf=13*6e4,Jf=/pass|ssn|card|cvv|cvc|otp|secret|token|pin\b/i,Yf=/cc-|new-password|current-password|one-time-code/i;function Xf(e){let t=(e.type??``).toLowerCase();return t===`password`||t===`hidden`||Yf.test(e.autocomplete??``)||Jf.test(e.name??``)||Jf.test(e.id??``)?!0:Zf(e.value??``)}function Zf(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 Qf(e){try{return new URL(e).hostname.toLowerCase()}catch{return``}}function $f(e){try{return new URL(e).origin}catch{return``}}var ep={head:0,tail:0},tp=[[`pass`,`word`],[`pass`,`wd`],[`pass`,`phrase`],[`pass`,`code`],[`pwd`],[`otp`],[`one`,`time`,`code`]],np=[[`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`]],rp=[[`cookie`],[`session`,`id`],[`session`,`key`],[`session`,`token`],[`csrf`,`token`],[`xsrf`,`token`]],ip=e=>e.map(e=>e.join(String.raw`[_\-\s]?`)).join(`|`),ap=ip(tp),op=ip(np),sp=ip(rp),cp=[[`password`,tp],[`token`,np],[`cookie`,rp]];function lp(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 cp)if(t.some(e=>n.some(t=>t.endsWith(e.join(``)))))return e;return null}[...tp,...np,...rp].map(e=>e.join(`_`));var up=String.raw`(?:Bearer\s+|Basic\s+|Token\s+)?(?:"([^"\r\n]{4,400})"|'([^'\r\n]{4,400})'|([^\s,;&"'<>{}\[\]]{4,400}))`,dp=e=>new RegExp(String.raw`(?<![A-Za-z0-9])(?:${e})["']?\s*[:=]\s*${up}`,`gi`),fp=String.raw`(?:"([^"\r\n]{4,400})"|'([^'\r\n]{4,400})'|([^\s"'<>]{3,399}[^\s"'<>.,;:!?]))`,pp=e=>new RegExp(String.raw`(?<![A-Za-z0-9])(?:${e})\s+(?:is|are|was|will\s+be)\s*:?\s+${fp}`,`gi`),mp=/\d|[!@#$%^&*()_+=\[\]{}|\\<>~/&]|[a-z][A-Z]/;function hp(e){return e.length>=6&&_p(e)&&mp.test(e)}var gp=/^(?: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 _p(e){return gp.test(e)||/^(.)\1*$/.test(e)?!1:!e.includes(`…`)}var vp=[{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:dp(ap),validate:_p},{id:`labelled-token`,kind:`token`,pattern:dp(op),validate:_p},{id:`labelled-cookie`,kind:`cookie`,pattern:dp(sp),validate:_p},{id:`prose-password`,kind:`password`,pattern:pp(ap),validate:hp},{id:`prose-token`,kind:`token`,pattern:pp(op),validate:hp},{id:`card`,kind:`card`,pattern:/\b\d(?:[ -]?\d){12,18}\b/g,reveal:{head:0,tail:4},validate:Zf}],yp=/(?<![A-Za-z0-9+/_=-])[A-Za-z0-9+/_-]{32,4096}={0,2}(?![A-Za-z0-9+/_-])/g,bp=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,xp=4.3,Sp=.5,Cp=/\bdata:[^\s;,]{0,80};base64,[A-Za-z0-9+/=]+/g;function wp(e,t=[]){if(!e)return[];let n=[...t,...Ap(e,Cp)].sort((e,t)=>e.start-t.start),r=e.toLowerCase(),i=[],a=e=>{jp(n,e)||(n.push(e),n.sort((e,t)=>e.start-t.start),i.push(e))};for(let t of vp)if(!(t.guard&&!r.includes(t.guard)))for(let n of e.matchAll(t.pattern)){let e=Tp(n);e&&(t.validate&&!t.validate(e.value)||a({...e,kind:t.kind,shape:t.id,reveal:t.reveal??ep}))}for(let t of e.matchAll(yp)){let e=t[0];Ep(e)&&a({start:t.index,end:t.index+e.length,value:e,kind:`secret`,shape:`high-entropy`,reveal:ep})}return i.sort((e,t)=>e.start-t.start)}function Tp(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 Ep(e){return e.length<32||bp.test(e)||/^[0-9a-f]+$/i.test(e)||!/[a-z]/.test(e)||!/[A-Z]/.test(e)||!/[0-9]/.test(e)?!1:kp(e)>=xp&&Dp(e)>=Sp}function Dp(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)Op(t[e])!==Op(t[e-1])&&(n+=1);return n/(t.length-1)}var Op=e=>e===e.toUpperCase();function kp(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 Ap(e,t){return[...e.matchAll(t)].map(e=>({start:e.index,end:e.index+e[0].length}))}function jp(e,t){return e.some(e=>t.start<e.end&&e.start<t.end)}var Mp=/⟦([a-z-]+):([0-9a-z]+)(?:@([A-Za-z0-9._:\[\]-]{1,255}))?#([0-9a-f]{6,32})⟧/g;function Np(e,t){let n=e.origin?`@${e.origin}`:``;return`⟦${e.kind}:${e.id}${n}#${t}⟧`}function Pp(e,t){return e.includes(`⟦`)?[...e.matchAll(Mp)].map(e=>({kind:e[1],id:e[2],origin:e[3],tag:e[4],text:e[0]})).filter(e=>!t||e.tag===t):[]}function Fp(e,t){if(!e||e.length<4)return{value:e,found:[]};let n=Vp(e,t.tag),r=t.tag?Hp(e,n):e,i=wp(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)+Bp(e.value,e.reveal,n),s=e.end}return{value:o+r.slice(s),found:a}}var Ip=new Set([`selector`]),Lp=4;function Rp(e,t){let n=[],r=(e,r)=>{let i=wp(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:ep},o=t.mint(e,a.kind,a.shape);return n.push({kind:a.kind,shape:a.shape,handle:o}),Bp(e,a.reveal,o)},i=(e,a,o)=>{if(typeof e==`string`){if(e.startsWith(`data:`))return e;if(o&&e.length>=Lp&&_p(e)&&!Pp(e).length)return r(e,o);let i=Fp(e,t);return n.push(...i.found),i.value}if(a>=Up||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]=Ip.has(t)?n:i(n,a+1,lp(t));return s};return{value:i(e,0,null),found:n}}function zp(e,t,n){let r=[],i=[];return{text:e.replace(Mp,(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 Bp(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 Vp(e,t){return e.includes(`⟦`)?[...e.matchAll(Mp)].filter(e=>!t||e[4]===t).map(e=>({start:e.index,end:e.index+e[0].length})):[]}function Hp(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 Up=12,Wp={"page.fillInput":[`value`],"page.typeText":[`text`]},Gp=`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.`,Kp=`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 qp(e){return Wp[e]??[]}function Jp(e,t,n,r){let i=qp(e),a=[],o=[],s=[];if(!t||typeof t!=`object`||Array.isArray(t))return{input:t,released:a,refused:Yp(t,o),unresolved:s};let c={};for(let[e,l]of Object.entries(t)){if(i.includes(e)&&typeof l==`string`){let t=zp(l,n,r);a.push(...t.released),s.push(...t.unresolved),c[e]=t.text;continue}Yp(l,o),c[e]=l}return{input:c,released:a,refused:o,unresolved:s}}function Yp(e,t,n=0){if(typeof e==`string`)t.push(...Pp(e));else if(n<12&&e&&typeof e==`object`)for(let r of Object.values(e))Yp(r,t,n+1);return t}var Xp=`browsentic/secrets`,Zp=120*6e4,Qp=Promise.resolve();function $p(e){let t=Qp.then(e,e);return Qp=t.catch(()=>void 0),t}function em(e,t){return $p(async()=>{let n=await nm(),r=Date.now(),i=n.entries.filter(e=>r-e.at<Zp),a=[],o=Rp(e,{mint:(e,o,s)=>{let c=[...i,...a].find(n=>n.value===e&&n.origin===t);if(c)return c.at=r,Np(c,n.tag);let l={id:om(),value:e,kind:o,shape:s,origin:t,at:r};return a.push(l),Np(l,n.tag)},tag:n.tag});return(a.length||i.length!==n.entries.length)&&await rm({tag:n.tag,entries:[...i,...a].slice(-64)}),o})}function tm(e,t){return $p(async()=>{let n=await nm(),r=Date.now(),i=[],a=Jp(e,t,n.tag,e=>{let t=n.entries.find(t=>t.id===e.id);return!t||r-t.at>=Zp?null:(t.at=r,i.push(t),t.value)});return i.length&&await rm(n),a})}async function nm(){let e=(await t.storage.session.get(Xp).catch(()=>({})))[Xp];if(e?.tag&&Array.isArray(e.entries))return{tag:e.tag,entries:e.entries};let n={tag:am(),entries:[]};return await rm(n),n}function rm(e){return t.storage.session.set({[Xp]:e}).catch(()=>void 0)}var im=e=>[...crypto.getRandomValues(new Uint8Array(e))].map(e=>e.toString(16).padStart(2,`0`)).join(``),am=()=>im(8),om=()=>im(4),sm=[{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`}],cm=t.debugger,lm=`1.3`,um=250,dm=150,fm=4,G=e=>new Promise(t=>setTimeout(t,e)),pm=new Set;function mm(){cm.onEvent.addListener((e,t,n)=>{for(let r of pm)r(e,t,n)})}function hm(e){return pm.add(e),()=>pm.delete(e)}async function gm(e){try{return await cm.attach({tabId:e},lm),{ok:!0}}catch(e){return{ok:!1,message:Cm(e)}}}async function _m(e){let t={tabId:e};await K(t,`Target.setAutoAttach`,xm).catch(()=>{}),await cm.detach(t).catch(()=>{})}function vm(e){cm.onDetach.addListener((t,n)=>{t.tabId!=null&&e(t.tabId,n)})}function K(e,t,n){return cm.sendCommand(e,t,n)}async function ym(e,t,n){let r={tabId:e};try{await cm.attach(r,lm)}catch(e){return s(`DEBUGGER_UNAVAILABLE`,Cm(e))}try{return await G(um),await n(r)}catch(e){return s(`ACTION_FAILED`,e instanceof Error?e.message:String(e))}finally{await K(r,`Target.setAutoAttach`,xm).catch(()=>{}),await cm.detach(r).catch(()=>{})}}var bm={autoAttach:!0,flatten:!0,waitForDebuggerOnStart:!1,filter:[{type:`iframe`}]},xm={autoAttach:!1,flatten:!0,waitForDebuggerOnStart:!1};async function Sm(e){let t=[],n=hm((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<fm&&n.length;r+=1){let r=t.length;for(let e of n)await K(e,`Target.setAutoAttach`,bm).catch(()=>{});await G(dm),n=t.slice(r).map(({sessionId:t})=>({tabId:e.tabId,sessionId:t}))}}finally{n()}return t}function Cm(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 wm={alt:1,ctrl:2,meta:4,shift:8},Tm={left:1,right:2,middle:4},Em=12,Dm=`A trusted click needs Chrome’s debugger, which Firefox does not expose — use page.clickElement instead.`,Om=`A trusted drag needs Chrome’s debugger, which Firefox does not expose — drop "trusted" to drag with synthetic events instead.`;function km(e,t){return ym(e,Dm,async n=>{let r=await W(e,yf.name,t);return r.ok?(await jm(n,r.data),o({...r.data,trusted:!0})):r})}function Am(e,t){return ym(e,Om,async n=>{let r=await W(e,sl.name,t);return r.ok?(await Mm(n,r.data),o({...r.data,trusted:!0})):r})}async function jm(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|(wm[t]??0),0),pointerType:`mouse`},d=t=>K(e,`Input.dispatchMouseEvent`,t),f=e=>d({...u,...e,type:`mouseMoved`,button:`none`,buttons:0});await f(r);for(let e of Jc(r,n,s))await G(Em),await f(e);await G(c);for(let e=1;e<=a;e+=1)await d({...u,...n,type:`mousePressed`,button:i,buttons:Tm[i],clickCount:e}),await G(l),await d({...u,...n,type:`mouseReleased`,button:i,buttons:0,clickCount:e})}async function Mm(e,t){let{approach:n,grip:r,drop:i,steps:a,holdMs:o,settleMs:s}=t,c={modifiers:0,pointerType:`mouse`},l=t=>K(e,`Input.dispatchMouseEvent`,t),u=(e,t)=>l({...c,...e,type:`mouseMoved`,button:t?`left`:`none`,buttons:t});for(let e of Jc(n,r,4))await G(Em),await u(e,0);await l({...c,...r,type:`mousePressed`,button:`left`,buttons:1,clickCount:1}),await G(o);for(let e of Jc(r,i,a))await G(Em),await u(e,1);await G(s),await l({...c,...i,type:`mouseReleased`,button:`left`,buttons:0,clickCount:1})}var Nm=`Reading a captcha needs Chrome’s debugger, which Firefox does not expose — solve the captcha in the page yourself.`,Pm=500,Fm={button:`left`,clickCount:1,modifiers:[],moveSteps:14,hoverMs:120,holdMs:70};function Im(e){return ym(e,Nm,async e=>{let t=await Bm(e);return o(t?zm(t):{found:!1})})}function Lm(e,t){let n=$d.input.safeParse(t??{});if(!n.success)return Promise.resolve(s(`INVALID_INPUT`,S(n.error)));let{waitMs:r,timeoutMs:i}=n.data;return ym(e,Nm,async e=>{let t=Date.now()+i,n=await Bm(e);return n?!n.point||n.state!==`idle`?o({...zm(n),clicked:!1}):(await jm(e,Rm(n.point)),o({...zm(await Um(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 Rm(e){return{point:e,from:{x:Math.max(e.x-140,0),y:Math.max(e.y-90,0)},...Fm}}function zm(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 Bm(e){await Xm(e);for(let t of sm)if(await Vm(e,t))return Hm(e,t);return null}async function Vm(e,t){for(let n of t.hostMarkers)if((await Zm(e,n)).length)return!0;return!1}async function Hm(e,t){let n=t.frame?await Sm(e):[],r=t.solvedInPage?await $m(e,t.solvedInPage):!1;if(r||await Gm(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 $m(e,qm(t.challengeFrame)))return{vendor:t,frames:n,state:`needsHuman`,hasToken:r,bounds:await Km(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 Km(e,t.frame):void 0,note:`${t.label} asks for a puzzle rather than a checkbox.`};let i=await Wm(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 Um(e,t,n){let{vendor:r,frames:i}=t,a=Date.now()+Math.max(0,n);for(;Date.now()<a;){await G(Pm);let n=r.solvedInPage?await $m(e,r.solvedInPage):!1;if(n||await Gm(e,r,i))return{...t,state:`solved`,hasToken:n};if(r.challengeFrame&&await $m(e,qm(r.challengeFrame)))return{...t,state:`needsHuman`,hasToken:n,bounds:await Km(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 Wm(e,t,n){if(!t.checkbox)return{note:`${t.label} exposes no checkbox to click.`};if(!t.frame){let[n]=await Zm(e,t.checkbox),r=n?await Qm(e,n):null;return r?{bounds:r,point:Jm(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 Zm(e,`iframe[src*="${t.frame}"]`),i=r?await Qm(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 Xm(o).catch(()=>{});let[s]=await Zm(o,t.checkbox),c=s?await Qm(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 Ym(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 Gm(e,t,n){if(!t.solvedInFrame||!t.frame)return!1;let r=n.find(e=>e.url.includes(t.frame));return r?$m({tabId:e.tabId,sessionId:r.sessionId},t.solvedInFrame):!1}async function Km(e,t){let[n]=await Zm(e,`iframe[src*="${t}"]`);return(n?await Qm(e,n):null)??void 0}var qm=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')`,Jm=e=>({x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}),Ym=(e,t)=>t.x>=e.x&&t.x<=e.x+e.width&&t.y>=e.y&&t.y<=e.y+e.height;async function Xm(e){await K(e,`DOM.enable`),await K(e,`DOM.getDocument`,{depth:-1,pierce:!0})}async function Zm(e,t){let n=await K(e,`DOM.performSearch`,{query:t,includeUserAgentShadowDOM:!1}).catch(()=>null);if(!n?.searchId)return[];let r=n.resultCount?await K(e,`DOM.getSearchResults`,{searchId:n.searchId,fromIndex:0,toIndex:n.resultCount}).catch(()=>null):null;return await K(e,`DOM.discardSearchResults`,{searchId:n.searchId}).catch(()=>{}),r?.nodeIds??[]}async function Qm(e,t){let n=(await K(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 $m(e,t){return(await K(e,`Runtime.evaluate`,{expression:t,returnByValue:!0}).catch(()=>null))?.result?.value===!0}var eh=/^[a-z0-9][a-z0-9-]{0,47}$/;function th(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 nh=48;function rh(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:oh(r)||`root`}}function ih(e,t){return`${e.host}:${e.segment}:${t}`}function ah(e,t){let n=rh(t);return!!n&&n.host===e.host&&n.segment===e.segment}function oh(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,nh).replace(/-+$/,``)}var sh=new Set([`a`,`an`,`and`,`for`,`from`,`in`,`of`,`on`,`the`,`this`,`to`,`with`]);function ch(e,t){return oh(e.toLowerCase().replace(/[^a-z0-9\s-]+/g,` `).split(/[\s-]+/).filter(e=>e&&!sh.has(e)).join(`-`))||oh(t)||`tool`}function lh(e,t){let n=oh(`tool-${e.host}-${e.segment}-${t}`).slice(0,48).replace(/-+$/,``);return eh.test(n)?n:`tool-${oh(t).slice(0,42)}`}var uh=`browsentic/savedTools`,dh=({code:e,...t})=>t;async function fh(){let e=(await t.storage.local.get(uh))[uh];return Array.isArray(e)?e:[]}async function ph(e){return(await fh()).find(t=>t.id===e)??null}async function mh(e){let n=(await fh()).filter(t=>t.name!==e.name);await t.storage.local.set({[uh]:[e,...n].slice(0,100)})}async function hh(e){let n=await fh(),r=n.find(t=>t.id===e);return r?(await t.storage.local.set({[uh]:n.filter(t=>t.id!==e)}),dh(r)):null}async function gh(e,t){let n=new Set((await fh()).map(e=>e.name)),r=ih(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 _h(e,t){if(!t||!rh(t))return!1;let n;try{n=new URL(t).origin}catch{return!1}return n===e.origin&&ah(e.scope,t)}var vh=`browsentic/codeToolkits`,yh=`Installing page code needs Chrome’s debugger, which Firefox does not expose — use the ordinary page tools instead.`,bh=600,xh=1e3,Sh=new Set;function Ch(e){Sh.add(e)}async function wh(){return(await t.storage.session.get(vh))[vh]??{}}async function Th(e,n){let r=await wh();n?r[String(e)]=n:delete r[String(e)],await t.storage.session.set({[vh]:r})}async function Eh(e){await Th(e,null)}function Dh(){t.tabs.onRemoved.addListener(e=>void Eh(e))}function Oh(e){if(e)try{let t=new URL(e).origin;return t===`null`?void 0:t}catch{return}}async function kh(e,t,n){let r=Tu.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(r.error));let i=Oh(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 Ph(e,u);if(!d.ok)return d;u.entries=d.data,await Th(e,u);let f={toolkitId:u.id,origin:i,purpose:a,functions:u.entries.map(e=>e.name)},p=l?await Nh(e,t,{function:l.function,args:l.args}):null;return Ah(u,t,l?.function),p?p.ok?o({...f,called:p.data}):o({...f,callFailed:p.error}):o(f)}function Ah(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?rh(t):null;!i||!a||setTimeout(()=>{let t={toolkitId:e.id,fn:i.name,purpose:e.purpose,suggestedSlug:ch(e.purpose,i.name),host:a.host,segment:a.segment,origin:e.origin};for(let e of Sh)e(t)},xh)}async function jh(e,t,n){let r=await ph(n);if(!r)return s(`UNKNOWN_TOOL`,`That tool is no longer saved.`);if(!_h(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 Ph(e,i);return a.ok?(i.entries=a.data,await Th(e,i),W(e,Bd.name,{function:r.fn,args:[],timeoutMs:1e4})):a}async function Mh(e,t){let n=(await wh())[String(e)];return n&&n.id===t?n.code:null}async function Nh(e,t,n){let r=Bd.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(r.error));let i=(await wh())[String(e)];if(!i)return s(Fd,`No toolkit is installed in this tab. Call page.injectCode first, and the user will be asked to approve the code.`);let a=Oh(t);if(a!==i.origin)return await Eh(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 W(e,Bd.name,r.data);if(o.ok||o.error.code!==`TOOLKIT_MISSING`)return o;let c=await Ph(e,i);return c.ok?W(e,Bd.name,r.data):c}function Ph(e,t){return ym(e,yh,async e=>{let n=await Fh(e,Ld(t.id,t.code)),r=n.exceptionDetails;if(r)return s(`CODE_ERROR`,`The code failed while installing: ${Ih(r)}`);let i=n.result?.value;return Array.isArray(i)?o(i):s(`CODE_ERROR`,`The code installed but reported no functions.`)})}function Fh(e,t){return K(e,`Runtime.evaluate`,{expression:t,returnByValue:!0,awaitPromise:!0})}function Ih(e){let t=e.exception?.description??e.text??`unknown error`;return t.length>bh?`${t.slice(0,bh)}…`:t}var Lh=`⟪browsentic:site-tool-timeout⟫`;async function Rh(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 zh(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 Bh(e,n,r){try{return(await t.scripting.executeScript({target:{tabId:e},world:`MAIN`,func:n,args:r}))[0]?.result??null}catch{return null}}async function Vh(e){let t=await Bh(e,Rh,[!1]);return!t?.ok||!t.tools.length?null:{api:t.api,count:t.tools.length,tools:t.tools}}async function Hh(e,t){let[n,r]=await Promise.all([W(e,pu.name,t),Vh(e)]);return!n.ok||!r?n:o({...n.data,siteTools:r})}async function Uh(e,t){if(!Oh(t))return s(`UNSUPPORTED`,`Site tools can only be read on an http(s) page.`);let n=await Bh(e,Rh,[!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 Wh(e,t,n){let r=Nc.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(r.error));if(!Oh(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 Bh(e,zh,[i,a,c,Lh]);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 Gh=15e3;async function Kh(e,n){let r=Pc.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(r.error));let{target:i,url:a,timeoutMs:c}=r.data;try{Fc(r.data)}catch(e){return e instanceof L?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=Zh(c),u=null;try{a?l.expect(await t.downloads.download({url:a})):u=await W(e,Ic.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:Jh(f)})}async function qh(e){let[n]=await t.downloads.search({id:e});return n??null}function Jh(e){let t=e.filename;return{browserPath:t,name:Yh(t),mime:e.mime??``,size:typeof e.fileSize==`number`&&e.fileSize>0?e.fileSize:e.totalBytes??0,url:e.finalUrl||e.url,host:Xh(e.finalUrl||e.url)}}function Yh(e){return e.split(/[\\/]/).pop()||`download`}function Xh(e){try{return new URL(e).hostname.toLowerCase()||void 0}catch{return}}function Zh(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(Gh,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 qh(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 qh(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 Qh(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 $h=16,eg=`|`,tg=25e4,ng=new TextEncoder,rg=new TextDecoder;function ig(){return mg(crypto.getRandomValues(new Uint8Array($h)))}function ag(e){return typeof e==`string`&&e.length>=16}async function og(e,t){let n=await crypto.subtle.importKey(`raw`,ng.encode(e),`PBKDF2`,!1,[`deriveBits`]),r=ng.encode(pg(`browsentic/pair`,t.clientNonce,t.serverNonce)),i=await crypto.subtle.deriveBits({name:`PBKDF2`,salt:r,iterations:tg,hash:`SHA-256`},n,256);return mg(new Uint8Array(i))}async function sg(e,t){return mg(await dg(e,`browsentic/client`,t))}async function cg(e,t,n){return mg(await dg(e,`browsentic/server`,t,pg(n.daemonVersion,n.manifestHash,String(n.manifestInSync),n.sealedSessionKey??``)))}async function lg(e,t,n){let r=hg(n);if(!r)return null;let i=await fg(e,t,r.length);return rg.decode(r.map((e,t)=>e^i[t]))}function ug(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 dg(e,t,n,r=``){let i=await crypto.subtle.importKey(`raw`,ng.encode(e),{name:`HMAC`,hash:`SHA-256`},!1,[`sign`]),a=pg(t,String(n.protocolVersion),n.extensionVersion,n.manifestHash,n.clientNonce,n.serverNonce,r);return new Uint8Array(await crypto.subtle.sign(`HMAC`,i,ng.encode(a)))}async function fg(e,t,n){let r=new Uint8Array(n);for(let i=0,a=0;i<n;i+=32,a++){let o=await dg(e,`browsentic/seal`,t,String(a));r.set(o.subarray(0,Math.min(32,n-i)),i)}return r}function pg(...e){return e.join(eg)}function mg(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function hg(e){try{return Uint8Array.from(atob(e.replace(/-/g,`+`).replace(/_/g,`/`)),e=>e.charCodeAt(0))}catch{return null}}var gg=`browsentic/daemon`,_g=`browsentic/reconnect`,vg=`browsentic/sessionKey`,yg=1e3,bg=3e4,xg=5e3,Sg=2e4,q=null,Cg=0,wg,Tg=null,Eg=new Set,Dg=null;function Og(e){Dg=e}function kg(e){Tg=e}function Ag(e){Eg.add(e)}function jg(e,t){let n=crypto.randomUUID();return J({t:`instruct`,id:n,text:e,context:t})?n:null}var Mg=9e4,Ng=new Map;function Pg(e){let t=crypto.randomUUID();return J({t:`analyzeFile`,id:t,...e})?new Promise(e=>{let n=setTimeout(()=>{Ng.delete(t),e(s(`TIMEOUT`,`The daemon did not return a summary in time.`))},Mg);Ng.set(t,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var Fg=12e4,Ig=new Map;function Lg(e){let t=crypto.randomUUID();return J({t:`analyzeRecording`,id:t,recording:e})?new Promise(e=>{let n=setTimeout(()=>{Ig.delete(t),e(s(`TIMEOUT`,`The daemon did not return a workflow in time.`))},Fg);Ig.set(t,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var Rg=2e4,zg=new Map;function Bg(e){let t=crypto.randomUUID();return J({t:`nameSession`,id:t,...e})?new Promise(e=>{let n=setTimeout(()=>{zg.delete(t),e(s(`TIMEOUT`,`The daemon did not return a name in time.`))},Rg);zg.set(t,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var Vg=15e3,Hg=new Map;function Ug(e){return Jg({t:`saveSkill`,id:crypto.randomUUID(),skill:e})}function Wg(e){return Jg({t:`deleteSkill`,id:crypto.randomUUID(),name:e})}function Gg(e){return Jg({t:`deleteSiteMap`,id:crypto.randomUUID(),name:e})}function Kg(e,t=!1){return Jg({t:`activateSiteMap`,id:crypto.randomUUID(),stagingId:e,exactHost:t})}function qg(e){return Jg({t:`discardSiteMap`,id:crypto.randomUUID(),stagingId:e})}function Jg(e){return J(e)?new Promise(t=>{let n=setTimeout(()=>{Hg.delete(e.id),t(s(`TIMEOUT`,`The daemon did not answer in time.`))},Vg);Hg.set(e.id,e=>{clearTimeout(n),t(e)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var Yg=2e4,Xg=new Map;function Zg(e=!1){return t_({t:`agentState`,id:crypto.randomUUID(),refresh:e})}function Qg(e){return t_({t:`setAgent`,id:crypto.randomUUID(),agent:e})}function $g(e,t){return t_({t:`setAgentModel`,id:crypto.randomUUID(),agent:e,model:t})}function e_(e){return t_({t:`grantAgent`,id:crypto.randomUUID(),agent:e})}function t_(e){return J(e)?new Promise(t=>{let n=setTimeout(()=>{Xg.delete(e.id),t(s(`TIMEOUT`,`The daemon did not answer in time.`))},Yg);Xg.set(e.id,e=>{clearTimeout(n),t(e)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var n_=new Map;function r_(e=!1){let t={t:`listSkills`,id:crypto.randomUUID(),refresh:e};return J(t)?new Promise(e=>{let n=setTimeout(()=>{n_.delete(t.id),e(s(`TIMEOUT`,`The daemon did not answer in time.`))},Yg);n_.set(t.id,t=>{clearTimeout(n),e(t)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}var i_=new Map;function a_(){return s_({t:`guardrails`,id:crypto.randomUUID()})}function o_(e,t){return s_({t:`setGuardrail`,id:crypto.randomUUID(),setting:e,value:t})}function s_(e){return J(e)?new Promise(t=>{let n=setTimeout(()=>{i_.delete(e.id),t(s(`TIMEOUT`,`The daemon did not answer in time.`))},Yg);i_.set(e.id,e=>{clearTimeout(n),t(e)})}):Promise.resolve(s(`EXTENSION_OFFLINE`,`No Browsentic daemon is attached — pair the browser first.`))}function c_(e){return J({t:`cancel`,id:e})}function l_(e,t,n,r){J({t:`decision`,id:e,toolId:t,allow:n,remember:r})}function u_(e){J({t:`reset`,sessionId:e})}function J(e){return!q||q.readyState!==WebSocket.OPEN?!1:(w_(q,e),!0)}async function d_(){if(g_())return;let e=await O_();if(!e){await D_({connected:!1,paired:!1,error:void 0,lastChangeAt:Date.now()});return}let t=await E_();t&&!t.paired&&t.error||(clearTimeout(wg),v_({kind:`session`,secret:e},0))}async function f_(e){let t=e.replace(/[\s-]/g,``).toUpperCase();return t?(__(),clearTimeout(wg),Cg=0,new Promise(e=>{m_=e,v_({kind:`pair`,secret:t},0),setTimeout(()=>h_({ok:!1,error:`No Browsentic daemon is running. Start one with "browsentic pair".`}),Sg)})):{ok:!1,error:`Enter the pairing code from "browsentic pair".`}}async function p_(){clearTimeout(wg),__(),await t.storage.local.remove(vg),await D_({connected:!1,paired:!1,error:void 0,agent:void 0,lastChangeAt:Date.now()})}var m_=null;function h_(e){m_?.(e),m_=null}function g_(){return!!q&&(q.readyState===WebSocket.OPEN||q.readyState===WebSocket.CONNECTING)}function __(){let e=q;if(q=null,e){e.onopen=null,e.onmessage=null,e.onclose=null;try{e.close(1e3,`client disconnecting`)}catch{}}}function v_(e,n,r){if(n>=i.length)return x_(e,r);let a=i[n],o=new WebSocket(`ws://127.0.0.1:${a}/extension`);q=o;let s=!1,c=!1,l=r,u={credential:e,port:a,hello:{extensionVersion:t.runtime.getManifest().version,manifestHash:Qh(Pf()),nonce:ig()},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(),xg);o.onopen=()=>{w_(o,{t:`hello`,protocolVersion:16,extensionVersion:u.hello.extensionVersion,manifestHash:u.hello.manifestHash,auth:{kind:e.kind},nonce:u.hello.nonce})},o.onmessage=e=>{C_(o,String(e.data),u)},o.onclose=t=>{if(clearTimeout(d),q===o&&(q=null),l??=b_(t),!c)return v_(e,n+1,l);D_({connected:!1,paired:!0,error:void 0,lastChangeAt:Date.now()}),e.kind===`session`&&T_(e)}}var y_=new Set([`unproven daemon`,``]);function b_(e){let t=e.reason?.trim();if(!(!t||y_.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 x_(e,t){if(t&&!t.retryable){h_({ok:!1,error:t.reason}),D_({connected:!1,paired:!1,error:t.reason,lastChangeAt:Date.now()});return}h_({ok:!1,error:t?.reason??`No Browsentic daemon is running.`}),e.kind===`session`&&T_(e)}function S_(e){return{protocolVersion:16,extensionVersion:e.hello.extensionVersion,manifestHash:e.hello.manifestHash,clientNonce:e.hello.nonce,serverNonce:e.serverNonce??``}}async function C_(e,n,r){let i=a(n);if(i)switch(i.t){case`ping`:return w_(e,{t:`pong`,id:i.id});case`challenge`:{if(!ag(i.nonce)||r.serverNonce)return r.walk();r.serverNonce=i.nonce;let t=S_(r);return r.secret=r.credential.kind===`pair`?await og(r.credential.secret,t):r.credential.secret,w_(e,{t:`prove`,proof:await sg(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=S_(r),a=i.sealedSessionKey??``;if(!ug(i.proof,await cg(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 lg(e,n,a):null;if(!o&&(a||r.credential.kind===`pair`))return r.walk();r.done(),Cg=0,o&&await t.storage.local.set({[vg]:o}),h_({ok:!0}),await D_({connected:!0,paired:!0,port:r.port,daemonVersion:i.daemonVersion,manifestInSync:i.manifestInSync,error:void 0,lastChangeAt:Date.now()});for(let e of Eg)e();return}case`describe`:return w_(e,{t:`manifest`,id:i.id,tools:Pf()});case`invoke`:return w_(e,{t:`result`,id:i.id,result:await Yx(i.action,i.input,i.tabId,i.runId)});case`run`:return Tg?.(i.id,i.event);case`fileSummary`:Ng.get(i.id)?.(i.result),Ng.delete(i.id);return;case`skillResult`:Hg.get(i.id)?.(i.result),Hg.delete(i.id);return;case`sessionName`:zg.get(i.id)?.(i.result),zg.delete(i.id);return;case`recordingWorkflow`:Ig.get(i.id)?.(i.result),Ig.delete(i.id);return;case`agentInfo`:Xg.get(i.id)?.(i.result),Xg.delete(i.id),i.result.ok&&await D_({agent:i.result.data,lastChangeAt:Date.now()});return;case`guardrailInfo`:i_.get(i.id)?.(i.result),i_.delete(i.id);return;case`skillCatalog`:n_.get(i.id)?.(i.result),n_.delete(i.id),i.result.ok&&await D_({skillCatalog:i.result.data,lastChangeAt:Date.now()});return;case`siteMapDraft`:return Dg?.(i.id,i.draft);default:return}}function w_(e,t){e.readyState===WebSocket.OPEN&&e.send(JSON.stringify(t))}function T_(e){let t=Math.min(bg,yg*2**Cg++)*(.5+Math.random()/2);clearTimeout(wg),wg=setTimeout(()=>v_(e,0),t)}async function E_(){return(await t.storage.session.get(gg))[gg]}async function D_(e){let n=await E_()??{connected:!1,paired:!1,lastChangeAt:0};await t.storage.session.set({[gg]:{...n,...e}})}async function O_(){let e=(await t.storage.local.get(vg))[vg];return typeof e==`string`&&e?e:null}var k_=`browsentic:files`,A_=e=>`browsentic:file:${e}`;async function j_(){let e=(await t.storage.local.get(k_))[k_];return Array.isArray(e)?e:[]}async function M_(e){await t.storage.local.set({[k_]:e})}async function N_(e){let n=A_(e),r=(await t.storage.local.get(n))[n];return r&&typeof r.content==`string`?r:null}async function P_(e,t){await M_((await j_()).map(n=>n.id===e?{...n,...t}:n))}async function F_(e){let t=await N_(e);if(!t){await P_(e,{status:`error`,error:`File bytes are missing from storage.`});return}let n=(await j_()).find(t=>t.id===e),r=await Pg({name:t.name,mime:t.mime,size:n?.size??0,content:t.content});r.ok?await P_(e,{status:`ready`,summary:r.data.summary,digest:r.data.digest,error:void 0}):await P_(e,{status:`error`,error:`${r.error.code}: ${r.error.message}`})}var I_=RegExp(`[\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f\\u200b-\\u200f\\u202a-\\u202e\\u2066-\\u2069\\ufeff]`,`g`),L_=/^[a-zA-Z0-9 .#>+~*,_:[\]="'()-]{1,120}$/;function R_(e,t){return typeof e==`string`?e.replace(/[\r\n\t]+/g,` `).replace(I_,``).replace(/^[\s#>*\-+|`~=]+/,``).replace(/[`|]/g,``).replace(/\s+/g,` `).trim().slice(0,t):``}function z_(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 B_(e){return L_.test(e)&&e.trim().split(/\s+/).length<=8}function V_(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}var H_={goal:160,summary:400,intent:120,note:160,value:200,text:80,variable:40,field:80,kind:24,caveat:200},U_=[`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 W_(e,t){if(!e||typeof e!=`object`)return{ok:!1,message:`The workflow must be an object.`};let n=e,r=[],i=R_(n.goal??``,H_.goal);if(!i)return{ok:!1,message:`The workflow needs a one-line goal.`};let a=R_(n.summary??``,H_.summary),o=[];for(let e of Array.isArray(n.steps)?n.steps.slice(0,80):[]){let n=G_(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=R_(e?.name??``,H_.variable).replace(/[{}]/g,``);!t||s.has(t)||(s.add(t),c.push({name:t,field:R_(e?.field??``,H_.field)||t,kind:R_(e?.kind??``,H_.kind)||`text`}))}let l={goal:i,summary:a,steps:o,variables:c,caveats:(Array.isArray(n.caveats)?n.caveats:[]).slice(0,8).map(e=>R_(e,H_.caveat)).filter(Boolean)};X_(l,r);for(let e of J_(l))z_(e)&&r.push(`Reads like an instruction rather than an observation: “${V_(e,80)}”`);return{ok:!0,workflow:l,warnings:r}}function G_(e,t,n){let r=typeof e?.action==`string`?e.action.trim():``;if(!U_.includes(r))return r&&n.push(`Dropped a step naming an action that cannot be replayed: ${V_(r,40)}`),null;let i=R_(e?.intent??``,H_.intent);if(!i)return null;let a=K_(e?.target,n),o=q_(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:R_(e?.value??``,H_.value)||void 0,url:o||void 0,note:R_(e?.note??``,H_.note)||void 0}}function K_(e,t){if(!e||typeof e!=`object`)return;let n=typeof e.selector==`string`?e.selector.trim():``;n&&!B_(n)&&(t.push(`Dropped a step selector that did not look like a selector: ${V_(n,40)}`),n=``);let r=R_(e.text??``,H_.text),i=R_(e.role??``,H_.kind);if(!(!n&&!r))return{selector:n||void 0,text:r||void 0,role:i||void 0}}function q_(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:`?``:V_(r.href,300)}catch{return``}}function J_(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 Y_(e){return J_(e).reduce((e,t)=>e+th(t),0)}function X_(e,t){if(Y_(e)<=12288)return;let n=(n,r)=>{Y_(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=V_(t.intent,60)});Y_(e)>12288&&e.steps.length>1;)e.steps.pop();e.steps.length===1&&t.push(`Only the first step fitted in the workflow.`)}var Z_=`browsentic:recordings`,Q_=e=>`browsentic:recording:${e}`,$_=20;async function ev(){let e=(await t.storage.local.get(Z_))[Z_];return Array.isArray(e)?e:[]}async function tv(e){await t.storage.local.set({[Z_]:e})}async function nv(e,n){await t.storage.local.set({[Q_(e.id)]:n});let r=await ev(),i=[{...r.find(t=>t.id===e.id),...e},...r.filter(t=>t.id!==e.id)],a=i.slice($_);a.length&&await t.storage.local.remove(a.map(e=>Q_(e.id))),await tv(i.slice(0,$_))}async function rv(e){let n=Q_(e),r=(await t.storage.local.get(n))[n];return r&&Array.isArray(r.events)?r:null}async function iv(e,t){let n=await ev();n.some(t=>t.id===e)&&await tv(n.map(n=>n.id===e?{...n,...t,updatedAt:Date.now()}:n))}async function av(e){let n=(await ev()).find(t=>t.id===e);if(!n)return;let r=await rv(e);if(!r||!r.events.length){await iv(e,{status:`error`,error:`The recorded steps are missing from storage.`});return}await iv(e,{status:`analyzing`,error:void 0});let i=await Lg({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 iv(e,{status:`error`,error:`${i.error.code}: ${i.error.message}`});return}let a=W_(i.data.workflow,{origin:$f(n.startUrl)});if(!a.ok){await iv(e,{status:`error`,error:a.message});return}await t.storage.local.set({[Q_(e)]:{...r,workflow:a.workflow}}),await iv(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===sv(n.host,n.createdAt)?a.workflow.goal:n.name,error:void 0})}async function ov(){let e=await ev();for(let t of e)(t.status===`analyzing`||t.error?.startsWith(`EXTENSION_OFFLINE`))&&await av(t.id)}function sv(e,t){let n=new Date(t),r=`${n.getFullYear()}-${cv(n.getMonth()+1)}-${cv(n.getDate())} ${cv(n.getHours())}:${cv(n.getMinutes())}`;return`${e||`Browsing`} — ${r}`}function cv(e){return String(e).padStart(2,`0`)}function lv(e){return{id:e.id,name:e.name,host:e.host||Qf(e.startUrl),goal:e.goal,steps:e.steps,capturedValues:e.capturedValues,durationMs:e.durationMs}}var uv=`browsentic/recording`,dv=`browsentic/recording-warn`,fv=`browsentic/recording-stop`,pv=null;function mv(e){pv=e}async function hv(){let e=(await t.storage.session.get(uv))[uv];return e&&Array.isArray(e.events)?e:null}async function gv(e){e?await t.storage.session.set({[uv]:e}):await t.storage.session.remove(uv)}function _v(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 vv(){let e=await hv();return e?_v(e):null}async function yv(e){let t=await hv(),n=!!t&&t.tabId===e;return{recording:n,captureValues:n?t.captureValues:!1}}async function bv(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.`):xv({tabId:n.id,url:n.url,captureValues:e})}async function xv(e){if(await hv())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:Qf(e.url),startUrl:e.url,startedAt:Date.now(),captureValues:e.captureValues,events:[{t:Date.now(),kind:`navigate`,url:e.url}],warned:!1};await gv(n),await t.alarms.create(dv,{when:n.startedAt+qf}),await t.alarms.create(fv,{when:n.startedAt+Kf}),await t.tabs.sendMessage(e.tabId,{channel:Wf,op:`begin`}).catch(()=>void 0);let r=_v(n);return pv?.(r),o(r)}async function Sv(e,t){if(!t.length)return;let n=await hv();if(!(!n||n.tabId!==e)){if(n.events.length>=2e3){await Cv(`timeout`);return}n.events.push(...t.slice(0,Gf-n.events.length)),await gv(n),pv?.(_v(n))}}async function Cv(e){let n=await hv();if(await t.alarms.clear(dv),await t.alarms.clear(fv),!n)return pv?.(null),o(null);await gv(null),e!==`tab-closed`&&await t.tabs.sendMessage(n.tabId,{channel:Wf,op:`end`}).catch(()=>void 0),pv?.(null);let r=n.startedAt;return await nv({id:n.id,name:sv(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}),av(n.id),o({id:n.id})}function wv(){t.tabs.onUpdated.addListener((e,t)=>{t.url&&(async()=>{let n=await hv();if(!n||n.tabId!==e)return;let r=n.events[n.events.length-1];r?.kind===`navigate`&&r.url===t.url||await Sv(e,[{t:Date.now(),kind:`navigate`,url:t.url}])})()}),t.tabs.onRemoved.addListener(e=>{(async()=>{(await hv())?.tabId===e&&await Cv(`tab-closed`)})()}),t.alarms.onAlarm.addListener(e=>{if(e.name===`browsentic/recording-stop`){Cv(`timeout`);return}e.name===`browsentic/recording-warn`&&(async()=>{let e=await hv();if(!e||e.warned)return;e.warned=!0,await gv(e);let t=Math.max(0,Kf-(Date.now()-e.startedAt));pv?.(_v(e,`Recording stops automatically in ${Tv(t)}.`))})()})}function Tv(e){let t=Math.round(e/1e3);return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}var Ev=1e4,Dv=120,Ov=20,kv=50,Av=10;async function jv(e,n){let r=Pu.input.safeParse(e??{});if(!r.success)return s(`INVALID_INPUT`,S(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&&Kv(c.url)?c.url:void 0,u;try{let e=Mu({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 L?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 Fv(f.id),m=a?f.id:c?.id;return o({performed:`opened ${qv(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 Mv(e,n){let r=_f.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(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 Bv(e);if(i==null&&a==null)return o(Rv(c,e));let l=await Lv(c,{tabId:i,match:a},`switch to`);if(!l.ok)return l.result;let u=l.tab;if(!Kv(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 ${Hv(u)}`,activeTabId:u.id,previousTabId:e.id,tab:Vv({...u,active:!0})})}async function Nv(e,n){let r=Lc.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(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 Bv(e),l=i==null&&a==null?Iv(c,e):await Lv(c,{tabId:i,match:a},`close`);if(!l.ok)return l.result;let u=l.tab;if(c.length<=1)return s(`INVALID_TARGET`,`${Hv(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`,`${Hv(u)} is pinned, which means the user wants to keep it. Ask them to unpin it if it really should close.`);if(!Kv(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 yv(u.id)).recording)return s(`INVALID_TARGET`,`A recording is in progress in ${Hv(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 zv(e,u.id),f=d.active?.url?qv(d.active.url):void 0;return o({performed:f?`closed ${Hv(u)} — now on ${f}`:`closed ${Hv(u)}`,closed:Vv(u),...f?{nowOn:f}:{},...d.active?.id==null?{}:{activeTabId:d.active.id},remaining:d.remaining})}function Pv(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),Ev);return t.tabs.onUpdated.addListener(a),{settled:r,cancel:()=>i(!1)}}async function Fv(e){let n=Pv(e),r=(await t.tabs.get(e).catch(()=>null))?.status;return r==null||r===`complete`?(n.cancel(),r===`complete`):n.settled}function Iv(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 Lv(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 — ${Wv(e)}`):s(`TARGET_NOT_FOUND`,`No tab with id ${n.tabId} — it has probably been closed. ${Wv(e)}`)}}let i=n.match.trim().toLowerCase();if(!i)return{ok:!1,result:s(`INVALID_INPUT`,`"match" cannot be empty.`)};let a=e.filter(Gv).filter(e=>`${e.title??``} ${e.url??``}`.toLowerCase().includes(i));return a.length?a.length>1?{ok:!1,result:s(`INVALID_TARGET`,`"${qv(n.match)}" matches ${a.length} tabs, so nothing was touched — ${r} one of them by id: ${Uv(a)}`)}:{ok:!0,tab:a[0]}:{ok:!1,result:s(`TARGET_NOT_FOUND`,`No open tab matches "${qv(n.match)}". ${Wv(e)}`)}}function Rv(e,t){let n=e.filter(Gv),r=e.length-n.length,i=n.slice(0,Ov);return{performed:`${n.length} open tab${n.length===1?``:`s`} in this window`,activeTabId:t.id,tabs:i.map(Vv),...r?{hidden:r}:{},...i.length<n.length?{truncated:!0}:{}}}async function zv(e,t){let n=[];for(let r=0;r<Av;r++){n=await Bv(e);let r=n.find(e=>e.active);if(r&&!n.some(e=>e.id===t))return{active:r,remaining:n.length};await Jv(kv)}let r=n.filter(e=>e.id!==t);return{active:r.find(e=>e.active),remaining:r.length}}async function Bv(e){return await t.tabs.query(e.windowId==null?{currentWindow:!0}:{windowId:e.windowId})}function Vv(e){return{tabId:e.id,title:qv(e.title??``),url:qv(e.url??``),...e.active?{active:!0}:{}}}function Hv(e){let t=qv(e.title??``),n=qv(e.url??``);return t&&n?`“${t}” — ${n}`:t||n||`tab ${e.id}`}function Uv(e){let t=e.slice(0,Ov),n=t.map(e=>`#${e.id} ${Hv(e)}`).join(`; `);return t.length<e.length?`${n}; …and ${e.length-t.length} more`:n}function Wv(e){let t=e.filter(Gv);return t.length?`Open tabs: ${Uv(t)}`:`No other web page is open in this window.`}var Gv=e=>Kv(e.url),Kv=e=>!!e&&/^https?:/i.test(e);function qv(e){let t=e.replace(/\s+/g,` `).trim();return t.length>Dv?`${t.slice(0,Dv-1)}…`:t}var Jv=e=>new Promise(t=>setTimeout(t,e)),Yv=`browsentic/diagnostics`,Xv=30,Zv=400,Qv=null,$v=[],ey;async function ty(){return Qv||(Qv=(await t.storage.session.get(Yv).catch(()=>({})))[Yv]??{},Qv)}function ny(){return clearTimeout(ey),ey=void 0,Qv?t.storage.session.set({[Yv]:Qv}).catch(()=>void 0):Promise.resolve()}function ry(){ey||=setTimeout(()=>void ny(),200)}var iy=e=>Object.values(e).filter(e=>e.phase===`watching`);function ay(e,t){return iy(e).find(e=>e.tabId===t)}async function oy(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 ty();await yy(c);let l=ay(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(iy(c).length>=2)return s(`DIAGNOSTICS_LIMIT`,`2 tabs are already being recorded — stop one with page.stopDiagnostics first.`);let u=await gm(a.id);if(!u.ok)return s(`DEBUGGER_UNAVAILABLE`,u.message);let d=await cy(a.id,e.capture);if(d)return await _m(a.id),s(`DEBUGGER_UNAVAILABLE`,d);let f=Date.now(),p={diagnosticsId:crypto.randomUUID(),tabId:a.id,url:a.url,host:Qf(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 ny(),await t.alarms.create(Zu(p.diagnosticsId),{when:p.expiresAt}),await G(150);let m=e.reload?await sy(a.id):void 0;return o({...ud(p),reloaded:m,notice:id})}async function sy(e){let n=Pv(e);try{await t.tabs.reload(e)}catch{return n.cancel(),!1}return n.settled}async function cy(e,t){let n={tabId:e};try{return t.includes(`console`)&&(await K(n,`Runtime.enable`),await K(n,`Log.enable`)),t.includes(`network`)&&await K(n,`Network.enable`),null}catch(e){return`Chrome attached but refused to start reporting: ${e instanceof Error?e.message:String(e)}`}}async function ly(e){let t=await hy(e.diagnosticsId);if(!t.ok)return t;let n=t.data,r=e.contains?.toLowerCase(),i=n.console.filter(t=>(e.level===`all`||cd(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 ny()}return o({...ud(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 hy(e.diagnosticsId);if(!t.ok)return t;let n=t.data,r=e.urlContains?.toLowerCase(),i=e.method?.toUpperCase(),a=n.network.filter(t=>dy(t,e.status)&&(!r||t.url.toLowerCase().includes(r))&&(!i||t.method===i)),s=a.slice(-e.limit),c=e.includeBodies?await py(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 ny()}return o({...ud(n),requests:s.map(t=>fy(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 dy(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 fy(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 py(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 K({tabId:e.tabId},`Network.getResponseBody`,{requestId:r.requestId});n.set(r.requestId,t.base64Encoded?`[${t.body.length} bytes of binary]`:ld(t.body,rd))}catch{n.set(r.requestId,`Not available — Chrome has already discarded this body.`)}return n}async function my(e){let t=await ty();await yy(t);let n=iy(t);if(e!=null){let n=await gy(e,`stopped`);if(n)return o(ud(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 gy(n[0].diagnosticsId,`stopped`);return r?o(ud(r)):s(`DIAGNOSTICS_NOT_FOUND`,`That recording just ended on its own.`)}async function hy(e){let t=await ty();if(await yy(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=iy(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 gy(e,n,r){let i=await ty(),a=i[e];return!a||a.phase!==`watching`?null:(a.phase=n,a.message=r??_y(n),await t.alarms.clear(Zu(e)).catch(()=>void 0),n!==`detached`&&n!==`tab-closed`&&await _m(a.tabId),vy(i),await ny(),a)}function _y(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 vy(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 yy(e){let t=Date.now();for(let n of iy(e))n.expiresAt<=t&&await gy(n.diagnosticsId,`timeout`)}async function by(e,t){if(!e.length)return;let n=await ty();for(let r of e)await gy(r.diagnosticsId,t),delete n[r.diagnosticsId];await ny()}async function xy(e){let t=await ty();await by(Object.values(t).filter(t=>t.owner===e),`stopped`)}async function Sy(e){let t=await ty();await by(Object.values(t).filter(t=>t.tabId===e),`tab-closed`)}function Cy(){hm((e,t,n)=>{e.sessionId||e.tabId==null||wy(e.tabId,t,n??{})}),vm(e=>{ty().then(t=>{let n=ay(t,e);n&&gy(n.diagnosticsId,`detached`)})}),t.alarms.onAlarm.addListener(e=>{e.name.startsWith(`browsentic/diagnostics-timeout:`)&&gy(e.name.slice(Xu.length),`timeout`)}),t.tabs.onRemoved.addListener(e=>void Sy(e))}function wy(e,t,n){if(!Qv){$v.push({tabId:e,method:t,params:n}),ty().then(()=>{let e=$v;$v=[];for(let t of e)Ty(t.tabId,t.method,t.params);ry()});return}Ty(e,t,n)}function Ty(e,t,n){let r=Qv?ay(Qv,e):void 0;if(!r)return;let i=Ey[t]??Dy[t];i&&(i(r,n),ry())}var Ey={"Runtime.consoleAPICalled":(e,t)=>{let n=t.args??[],r=Ny(t.stackTrace);Ay(e,{t:Date.now(),level:od(t.type),kind:`console`,text:ld(n.slice(0,6).map(My).filter(Boolean).join(` `)),url:r[0]?.url,line:r[0]?.line,column:r[0]?.column,stack:r.length>1?r.map(Py):void 0})},"Runtime.exceptionThrown":(e,t)=>{let n=t.exceptionDetails??{},r=Ny(n.stackTrace);Ay(e,{t:Date.now(),level:`error`,kind:`exception`,text:ld(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(Py):void 0})},"Log.entryAdded":(e,t)=>{let n=t.entry??{};Ay(e,{t:Date.now(),level:od(n.level),kind:`browser`,text:ld(n.source?`[${n.source}] ${n.text??``}`:n.text??``),url:n.url,line:n.lineNumber==null?void 0:n.lineNumber+1})}},Dy={"Network.requestWillBeSent":(e,t)=>{let n=t.requestId,r=t.request??{},i=t.redirectResponse;if(i){let t=Oy(e,n);t&&(t.status=i.status,t.statusText=i.statusText||void 0,t.responseHeaders=Fy(i.headers),t.requestId=`${n}:${t.t}`)}jy(e,{t:t.wallTime?t.wallTime*1e3:Date.now(),mono:t.timestamp??0,requestId:n,method:(r.method??`GET`).toUpperCase(),url:ld(r.url??``),type:t.type,requestHeaders:Fy(r.headers)})},"Network.responseReceived":(e,t)=>{let n=Oy(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=Fy(r.headers),n.type=t.type??n.type,n.durationMs=ky(n,t.timestamp)},"Network.loadingFinished":(e,t)=>{let n=Oy(e,t.requestId);n&&(n.sizeBytes=t.encodedDataLength,n.durationMs=ky(n,t.timestamp)??n.durationMs)},"Network.loadingFailed":(e,t)=>{let n=Oy(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=ky(n,t.timestamp)??n.durationMs}};function Oy(e,t){for(let n=e.network.length-1;n>=0;--n)if(e.network[n].requestId===t)return e.network[n]}var ky=(e,t)=>t!=null&&e.mono?Math.max(0,Math.round((t-e.mono)*1e3)):void 0;function Ay(e,t){e.console.push(t);let n=e.console.length-500;n>0&&(e.droppedConsole+=n,e.console.splice(0,n))}function jy(e,t){e.network.push(t);let n=e.network.length-td;n>0&&(e.droppedNetwork+=n,e.network.splice(0,n))}function My(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 Ny(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 Py=e=>`${e.fn} (${e.url??`<unknown>`}:${e.line??0}:${e.column??0})`;function Fy(e){if(!e)return;let t={};for(let[n,r]of Object.entries(e).slice(0,Xv))t[n.toLowerCase()]=ld(String(r),Zv);return t}var Iy=`browsentic/toast`,Ly=1e4;function Ry(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.channel===`browsentic/toast`&&t.op===`activate`&&typeof t.tabId==`number`}var zy=[{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.`}],By=`ember`,Vy=`browsentic/theme`;function Hy(e){return zy.some(t=>t.id===e)?e:By}async function Uy(){return Hy((await t.storage.local.get(Vy))[Vy])}var Wy=`Receiving end does not exist`;async function Gy(e,t){let n={channel:Iy,op:`show`,view:{...e,theme:await Uy(),durationMs:Ly}};for(let e of await Ky(t))if(await qy(e,n))return!0;return!1}async function Ky(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 qy(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(Wy)||!await Rf(e)?!1:r().catch(()=>!1)}}function Jy(){t.runtime.onMessage.addListener((e,t,n)=>{Ry(e)&&(Yy(e.tabId),n({ok:!0}))})}async function Yy(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 Xy=`browsentic/monitors`,Zy=`browsentic/monitorsDone`,Qy=`Receiving end does not exist`,$y=new Set,eb=new Map,tb=Promise.resolve();function nb(e){$y.add(e)}function rb(e){for(let t of $y)t(e)}function ib(e){let t=tb.then(e,e);return tb=t.catch(()=>void 0),t}async function Y(){return(await t.storage.session.get(Xy))[Xy]??{}}function ab(e){return t.storage.session.set({[Xy]:e})}async function ob(){let e=(await t.storage.session.get(Zy))[Zy];return Array.isArray(e)?e:[]}function sb(e){return t.storage.session.set({[Zy]:e})}function cb(e,t=`watching`,n){let r=Date.now(),{percent:i,etaMs:a}=Ac(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 lb(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 db(e,n){let r=Oc(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 ib(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:Qf(a.url),startUrl:a.url,origin:$f(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} ${kc(i.until)}.`),t[i.id]=i,await ab(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(wc(l.id),{when:l.startedAt+l.timeoutMs}),await t.alarms.create(Sc,{periodInMinutes:1}),await fb(l);let u=cb(l);return rb(u),o(lb(u))}async function fb(e){let n={channel:_c,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(Qy))return;await Rf(e.tabId)&&await t.tabs.sendMessage(e.tabId,n).catch(()=>void 0)}}async function pb(e,t,n){let r=await ib(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}=Ac(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 ${jc(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 ab(r),{monitor:{...i},complete:n.matched===!0}});if(r){if(r.complete){await mb(t,`done`);return}rb(cb(r.monitor))}}async function mb(e,n,r){let i=await ib(async()=>{let t=await Y(),i=t[e];if(!i)return null;delete t[e],await ab(t),ub(i,r??hb(n));let a=cb(i,n,r),o=await ob();return o.push(a),await sb(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(wc(e)),s===0&&await t.alarms.clear(Sc),await gb(a),n!==`tab-closed`&&await t.tabs.sendMessage(a.tabId,{channel:_c,op:`unwatch`,monitorId:e}).catch(()=>void 0);for(let t of eb.get(e)??[])t(o);return eb.delete(e),n!==`stopped`&&await Eb(o),rb(o),o}function hb(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 gb(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 _b(e){let t=await Y(),n=Object.values(t);if(e!=null){if(!t[e]){let t=(await ob()).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 mb(e,`stopped`);return n?o(lb(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 mb(n[0].id,`stopped`);return r?o(lb(r)):s(`MONITOR_NOT_FOUND`,`That monitor just finished on its own.`)}async function vb(e){let t=await Y(),n=await ob();if(e!=null){let r=t[e];if(r)return o(lb(cb(r)));let i=n.find(t=>t.monitorId===e);return i?o(lb(i)):s(`MONITOR_NOT_FOUND`,`No monitor with id “${e}” is running or recently finished.`)}return o({monitors:[...Object.values(t).map(e=>lb(cb(e))),...n.map(lb)]})}async function yb(e,t){if(!(await Y())[e]){let t=(await ob()).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=eb.get(e)??new Set,i=e=>{clearTimeout(a),r.delete(i),n(o({settled:!0,state:e}))};r.add(i),eb.set(e,r);let a=setTimeout(()=>{(async()=>{r.delete(i);let t=(await Y())[e];if(t)return n(o({settled:!1,state:lb(cb(t))}));let a=(await ob()).find(t=>t.monitorId===e);n(a?o({settled:!0,state:a}):s(`MONITOR_NOT_FOUND`,`Monitor ${e} disappeared while waiting.`))})()},Math.min(t,xc))})}async function bb(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 xb(){let e=await Y();return Object.values(e).map(e=>cb(e))}async function Sb(){return ob()}async function Cb(e){if(e==null)return sb([]);await sb((await ob()).filter(t=>t.monitorId!==e))}function wb(){t.tabs.onRemoved.addListener(e=>{(async()=>{for(let t of Object.values(await Y()))t.tabId===e&&await mb(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($f(t.url)===n.origin){let e=await ib(async()=>{let e=await Y(),r=e[n.id];return r?(ub(r,`Navigated to ${Tb(t.url)} — still watching.`),await ab(e),{...r}):null});e&&rb(cb(e))}else await mb(n.id,`tab-navigated`,`The tab left ${n.host} for ${Qf(t.url)||`another page`}.`)})()}),t.alarms.onAlarm.addListener(e=>{if(e.name.startsWith(`browsentic/monitor-timeout:`)){mb(e.name.slice(Cc.length),`timeout`);return}e.name===`browsentic/monitor-watch`&&(async()=>{let e=Date.now();for(let t of Object.values(await Y())){if(await fb(t),e-t.lastProgressAt<12e4||t.warnedStall)continue;let n=await ib(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 ab(n),{...r})});n&&rb(cb(n))}})()}),t.notifications?.onClicked.addListener(e=>{if(!e.startsWith(`browsentic-monitor:`))return;let n=e.slice(Tc.length);(async()=>{let r=(await ob()).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 Tb(e){try{let t=new URL(e);return t.pathname+t.search}catch{return e}}async function Eb(e){let n=Db(e);n&&(await Gy({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(`${Tc}${e.monitorId}`,{type:`basic`,iconUrl:Ob(),title:n.title,message:n.message}).catch(()=>void 0))}function Db(e){let t=e.label??e.host;return{done:{title:`Done: ${t}`,message:`Finished after ${kb(e.elapsedMs)}.`},timeout:{title:`Still going: ${t}`,message:`Watched for ${kb(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 Ob(){let e=t.runtime.getManifest().icons??{};return e[Object.keys(e).map(Number).sort((e,t)=>t-e)[0]]??``}function kb(e){let t=Math.round(e/1e3);return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}var Ab=`browsentic/timers`,jb=`browsentic/timersDone`,Mb=null,Nb=Promise.resolve();function Pb(e){Mb=e}function Fb(e){let t=Nb.then(e,e);return Nb=t.catch(()=>void 0),t}async function Ib(){return(await t.storage.session.get(Ab))[Ab]??{}}function Lb(e){return t.storage.session.set({[Ab]:e})}async function Rb(){let e=(await t.storage.session.get(jb))[jb];return Array.isArray(e)?e:[]}function zb(e){return t.storage.session.set({[jb]:e})}function Bb(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 Vb(e){return{...e,logs:e.logs.slice(-5)}}function Hb(e,t){e.logs.push({t:Date.now(),text:t}),e.logs.length>20&&e.logs.splice(0,e.logs.length-20)}var Ub=e=>e.label??`timer`;async function Wb(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 Fb(async()=>{let n=await Ib();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 Hb(i,`Scheduled to fire ${df(i)}.`),n[i.id]=i,await Lb(n),o(i)});if(!n.ok)return n;let r=n.data;return await Gb(r),o(Vb(Bb(r)))}function Gb(e){return t.alarms.create(cf(e.id),{when:e.nextFireAt,...e.repeat?{periodInMinutes:e.afterMs/6e4}:{}})}async function Kb(e){let n=(await Ib())[e];if(!n){await t.alarms.clear(cf(e));return}let r=await qb(n);if(r===`gone`){await Jb(e,`orphaned`,`The conversation this timer belonged to is gone.`);return}let i=await Fb(async()=>{let t=await Ib(),n=t[e];if(!n)return null;let i=Date.now();return r===`busy`?(n.skipped+=1,Hb(n,`Skipped — the conversation was still working on the previous turn.`)):(n.runs+=1,n.lastFiredAt=i,Hb(n,`Fired — run ${n.runs}${n.repeat?` of ${n.maxRuns}`:``}.`)),n.nextFireAt=i+(n.repeat||r===`delivered`?n.afterMs:of),await Lb(t),{...n}});if(i){if(i.skipped>=20){await Jb(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 Jb(e,`finished`):await Gb(i);return}i.runs>=i.maxRuns&&await Jb(e,`finished`,`Fired ${i.runs} times, which is the limit that was set.`)}}async function qb(e){return e.deliver===`notify`?(await ex(e.id,e.label??`Browsentic timer`,e.prompt),`delivered`):!e.sessionId||!Mb?`gone`:Mb(e.sessionId,e.prompt,Ub(e))}async function Jb(e,n,r){let i=await Fb(async()=>{let t=await Ib(),i=t[e];if(!i)return null;delete t[e],await Lb(t),Hb(i,r??Yb(n));let a=Bb(i,n,r);return await zb([...await Rb(),a].slice(-6)),a});return i?(await t.alarms.clear(cf(e)),n===`orphaned`&&await ex(e,`Timer ended: ${i.label??`scheduled job`}`,`The conversation it was set in has closed, so it was cancelled.`),i):null}function Yb(e){return{finished:`The schedule ran out.`,stopped:`Cancelled.`,orphaned:`The conversation this timer belonged to is gone.`}[e]}async function Xb(e){let t=Object.values(await Ib());if(e!=null){let t=await Jb(e,`stopped`);if(t)return o(Vb(t));let n=(await Rb()).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} · ${Ub(e)} (${df(e)})`).join(`; `);return s(`INVALID_TARGET`,`${t.length} timers are scheduled, so nothing was cancelled — cancel one by id: ${e}`)}let n=await Jb(t[0].id,`stopped`);return n?o(Vb(n)):s(`TIMER_NOT_FOUND`,`That timer just ended on its own.`)}async function Zb(e){let t=await Ib(),n=await Rb();if(e!=null){let r=t[e];if(r)return o(Vb(Bb(r)));let i=n.find(t=>t.timerId===e);return i?o(Vb(i)):s(`TIMER_NOT_FOUND`,`No timer with id “${e}” is scheduled or recently finished.`)}return o({timers:[...Object.values(t).map(e=>Vb(Bb(e))),...n.map(Vb)]})}async function Qb(e){for(let t of Object.values(await Ib()))t.sessionId===e&&await Jb(t.id,`orphaned`,`The conversation was ended.`)}function $b(){t.alarms.onAlarm.addListener(e=>{e.name.startsWith(`browsentic/timer:`)&&Kb(e.name.slice(sf.length))}),t.notifications?.onClicked.addListener(e=>{e.startsWith(`browsentic-timer:`)&&t.notifications.clear(e).catch(()=>void 0)})}async function ex(e,n,r){await t.notifications?.create(`${lf}${e}`,{type:`basic`,iconUrl:tx(),title:n,message:r}).catch(()=>void 0)}function tx(){let e=t.runtime.getManifest().icons??{};return e[Object.keys(e).map(Number).sort((e,t)=>t-e)[0]]??``}var nx=`browsentic:shots`,rx=e=>`browsentic:shot:${e}`,ix=2,ax=4e6,ox=new Set;function sx(e){ox.add(e)}async function cx(e,t){if(!e.thumbnail)return;let n=crypto.randomUUID(),r=await lx(n,e.dataUrl),i={previewId:n,thumbnail:e.thumbnail,width:e.width,height:e.height,full:r};for(let e of ox)e(i,t)}async function lx(e,n){if(n.length>ax)return!1;try{let r=await t.storage.session.get(nx),i=[e,...(Array.isArray(r[nx])?r[nx]:[]).filter(t=>t!==e)],a=i.slice(ix);return await t.storage.session.set({[rx(e)]:n,[nx]:i.slice(0,ix)}),a.length&&await t.storage.session.remove(a.map(rx)),!0}catch{return!1}}var ux=500,dx=48,fx=16384,px=fx*fx;async function mx(e,t,n){let r=await W(e.id,`page.screenshot`,t);if(!r.ok)return r;let i=r.data;try{let t=await gx(e,i);return hx(t,n),o(t)}catch(e){return e instanceof L?s(e.code,e.message):s(`CAPTURE_FAILED`,e instanceof Error?e.message:String(e))}finally{W(e.id,`page.scrollTo`,{position:{x:i.scroll.x,y:i.scroll.y},behavior:`instant`})}}async function hx(e,t){try{await cx({...e,thumbnail:await yx(e.dataUrl)},t)}catch{}}async function gx(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(dx/Math.min(s,dx))),l=!1;s>dx&&(o.w=dx*n.w,l=!0),Math.ceil(o.h/n.h)>c&&(o.h=c*n.h,l=!0);let u=wx(o.x,o.w,n.w),d=wx(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 W(e.id,`page.scrollTo`,{position:{x:c,y:s},behavior:`instant`});if(!u.ok)throw new L(u.error.message,u.error.code);let d=u.data,v=Date.now()-_;_&&v<ux&&await Tx(ux-v);let ee=await Cx(e.windowId,r,i);_=Date.now();let y=ee.bitmap;if(!m){let e=y.width/n.w||t.dpr||1;if(g=Sx(o.w*e,o.h*e,a),h=e*g,f&&g===1){let{width:e,height:t}=y;return y.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 y.close(),new L(`OffscreenCanvas 2D context unavailable`,`CAPTURE_FAILED`)}p.drawImage(y,(d.scrollX-o.x)*h,(d.scrollY-o.y)*h,y.width*g,y.height*g),y.close()}if(!m)throw new L(`Nothing was captured`,`CAPTURE_FAILED`);return xx(m,r,i,l)}var _x=640,vx=.6;async function yx(e){let t=await createImageBitmap(await(await fetch(e)).blob()),n=Math.min(1,_x/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(),Ex(await r.convertToBlob({type:`image/jpeg`,quality:vx}),`image/jpeg`)):(t.close(),``)}var bx=80;async function xx(e,t,n,r){let i=t===`jpeg`?`image/jpeg`:`image/png`,a=await Ex(await e.convertToBlob(t===`jpeg`?{type:i,quality:(n??bx)/100}:{type:i}),i);return{format:t,width:e.width,height:e.height,dataUrl:a,...r?{truncated:r}:{}}}function Sx(e,t,n){let r=Math.min(n,fx)/Math.max(e,t,1),i=Math.sqrt(px/Math.max(e*t,1));return Math.min(1,r,i)}async function Cx(e,n,r){let i=n===`jpeg`?r??bx: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 Tx(ux);continue}throw new L(`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 wx(e,t,n){let r=[];for(let i=e;i<e+t;i+=n)r.push(i);return r.length?r:[e]}var Tx=e=>new Promise(t=>setTimeout(t,e));function Ex(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 Dx=16,Ox=1200,kx=.85,Ax=120;async function jx(e,t){let n=await W(e.id,Ju.name,t);if(!n.ok)return n;let{capture:r,...i}=n.data,a=r?await Mx(e.windowId,r).catch(()=>null):null;return o(a?{...i,shot:a}:i)}async function Mx(e,t){let{viewport:n,dpr:r}=t,i=Math.max(0,t.region.x-Dx),a=Math.max(0,t.region.y-Dx),o=Math.min(n.w,t.region.x+t.region.w+Dx)-i,s=Math.min(n.h,t.region.y+t.region.h+Dx)-a;if(o<1||s<1)return null;await new Promise(e=>setTimeout(e,Ax));let{bitmap:c}=await Cx(e,`jpeg`,Math.round(kx*100)),l=c.width/n.w||r,u=Math.min(1,Ox/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 Ex(await d.convertToBlob({type:`image/jpeg`,quality:kx}),`image/jpeg`),width:d.width,height:d.height}):(c.close(),null)}var Nx=`browsentic/tabSessions`,Px=null,Fx=Promise.resolve();function Ix(e){let t=Fx.then(e,e);return Fx=t.catch(()=>void 0),t}async function X(){return Px||(Px=(await t.storage.session.get(`browsentic/tabSessions`))[`browsentic/tabSessions`]??{},Px)}function Lx(e){return Ix(async()=>{let n={...await X()},r=await e(n);return Px=n,await t.storage.session.set({[Nx]:n}),r})}async function Rx(e){let t=await X();return Object.values(t).find(t=>t.tabIds.includes(e))??null}async function zx(e){let t=await X();return Object.values(t).find(t=>t.runId===e)??null}async function Bx(e){return Lx(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=Jx(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??Jx(e.url)??`This tab`,url:e.url,host:Jx(e.url),runId:null,turns:0,createdAt:r,lastActivityAt:r};return t[i.sessionId]=i,{ok:!0,session:i}})}function Vx(e,t){return Lx(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??Jx(e.url)??`This tab`,url:e.url??t.url,host:Jx(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 Hx(e,t,n){return Lx(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 Ux(e,t){return Lx(n=>{let r=n[e];!r||!r.tabIds.includes(t)||(r.currentTabId=t,r.lastActivityAt=Date.now())})}function Wx(e,t){return Lx(n=>{let r=n[e];r&&Object.assign(r,t,{lastActivityAt:Date.now()})})}function Gx(e){return Lx(t=>{let n=t[e]??null;return delete t[e],n})}function Kx(e){return Lx(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 qx(e,t){return Lx(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 Jx(e){if(e)try{return new URL(e).host||void 0}catch{return}}async function Yx(e,t,n,r){let i=await tm(e,t);if(i.refused.length)return s(`SECRET_NOT_RELEASABLE`,Gp);if(i.unresolved.length)return s(`SECRET_EXPIRED`,Kp);let{value:a}=await em(await Qx(e,i.input,n,r),await Xx(n,r));return a}async function Xx(e,t){let n=await tS(e,t?await zx(t):null);return n?.url?Zx(n.url):void 0}function Zx(e){try{return new URL(e).hostname.toLowerCase()||void 0}catch{return}}async function Qx(e,t,n,r){if(e===Du.name)return hS(t);if(e===Ou.name)return gS(t);if(e===pd.name)return _S(t);let i=r?await zx(r):null;if(e===Pu.name)return nS(t,i);if(e===ef.name)return iS(t,n??i?.currentTabId,i?.sessionId);if(e===dd.name)return aS(t);if(e===fd.name)return oS(t);if(e===pf.name)return sS(t);if(e===tf.name)return cS(t,n??i?.currentTabId);if(e===Au.name)return lS(t);if(e===mf.name)return uS(t);if(e===Mc.name)return dS(t);if(e===ff.name)return fS(t,i?.sessionId);if(e===vf.name)return pS(t);if(e===hf.name)return mS(t);let a=await tS(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===Nu.name?bS(a.id,t):e===Wd.name?CS(a.id,t):e===_f.name?rS({id:a.id,windowId:a.windowId},t,i):e===Lc.name?Nv({id:a.id,windowId:a.windowId},t):e===Vd.name?mx({id:a.id,windowId:a.windowId},t,r):e===Ju.name?jx({id:a.id,windowId:a.windowId},t):e===fc.name?vS(a.id,t):e===Pc.name?Kh(a.id,t):e===Tu.name?kh(a.id,a.url,t):e===Bd.name?Nh(a.id,a.url,t):e===pu.name?Hh(a.id,t):e===ku.name?Uh(a.id,a.url):e===Nc.name?Wh(a.id,a.url,t):e===yf.name?km(a.id,t):e===sl.name&&$x(t)?Am(a.id,t):e===Tl.name?Im(a.id):e===$d.name?Lm(a.id,t):W(a.id,e,t)}function $x(e){return e?.trusted===!0}async function eS(e){try{return await t.tabs.get(e)}catch{return}}async function tS(e,n){return n?await eS(n.currentTabId)??await eS(n.mainTabId):e==null?(await t.tabs.query({active:!0,currentWindow:!0}))[0]:eS(e)}async function nS(e,t){if(!t)return jv(e);let n=await eS(t.currentTabId)??await eS(t.mainTabId),r=await jv(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 Hx(t.sessionId,i,r.data.activeTabId===i),r}async function rS(e,t,n){if(!n)return Mv(e,t);let r=t??{};if(typeof r.tabId==`number`&&!n.tabIds.includes(r.tabId)&&await Rx(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 Mv(e,t);if(!i.ok)return i;let a=i.data.activeTabId;return typeof a!=`number`||a===e.id||(n.tabIds.includes(a)?await Ux(n.sessionId,a):await Rx(a)||await Hx(n.sessionId,a,!0)),i}async function iS(e,t,n){let r=ef.input.safeParse(e??{});return r.success?oy(r.data,t,n):s(`INVALID_INPUT`,S(r.error))}async function aS(e){let t=dd.input.safeParse(e??{});return t.success?ly(t.data):s(`INVALID_INPUT`,S(t.error))}async function oS(e){let t=fd.input.safeParse(e??{});return t.success?uy(t.data):s(`INVALID_INPUT`,S(t.error))}async function sS(e){let t=pf.input.safeParse(e??{});return t.success?my(t.data.diagnosticsId):s(`INVALID_INPUT`,S(t.error))}async function cS(e,t){let n=tf.input.safeParse(e??{});return n.success?db(n.data,t):s(`INVALID_INPUT`,S(n.error))}async function lS(e){let t=Au.input.safeParse(e??{});return t.success?vb(t.data.monitorId):s(`INVALID_INPUT`,S(t.error))}async function uS(e){let t=mf.input.safeParse(e??{});return t.success?_b(t.data.monitorId):s(`INVALID_INPUT`,S(t.error))}async function dS(e){let t=Mc.input.safeParse(e??{});return t.success?yb(t.data.monitorId,t.data.timeoutMs):s(`INVALID_INPUT`,S(t.error))}async function fS(e,t){let n=ff.input.safeParse(e??{});return n.success?Wb(n.data,t):s(`INVALID_INPUT`,S(n.error))}async function pS(e){let t=vf.input.safeParse(e??{});return t.success?Zb(t.data.timerId):s(`INVALID_INPUT`,S(t.error))}async function mS(e){let t=hf.input.safeParse(e??{});return t.success?Xb(t.data.timerId):s(`INVALID_INPUT`,S(t.error))}async function hS(e){let t=e?.nameContains,n=typeof t==`string`?t.toLowerCase():null;return o({files:(await j_()).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 gS(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 ev()).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 _S(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 ev()).find(e=>e.id===t);if(!n)return s(`RECORDING_NOT_FOUND`,`No recording with id "${t}".`);let r=await rv(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 vS(e,t){let n=t??{};if(typeof n.content==`string`&&n.content)return W(e,fc.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 N_(r);return a?W(e,fc.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 yS=`Receiving end does not exist`;async function bS(e,t){let n=await W(e,Nu.name,t);return n.ok?o({...n.data,loaded:await Pv(e).settled}):n.error.code===`TAB_UNREACHABLE`?n.error.message.includes(yS)?xS(e,t):o({navigating:!0,loaded:await Pv(e).settled}):n}async function xS(e,n){let r=Nu.input.safeParse(n??{});if(!r.success)return s(`INVALID_INPUT`,S(r.error));let i;try{i=Mu(r.data)}catch(e){return e instanceof L?s(e.code,e.message):s(`ACTION_FAILED`,String(e))}let a=Pv(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 SS=2e3;async function CS(e,t){let n=await W(e,Wd.name,t);if(!n.ok)return n;let r=n.data,i=await wS(e,r.via===`url`||r.submitted===!0);return o({...n.data,loaded:i,landedOn:(await eS(e))?.url})}async function wS(e,t){let n=Pv(e);if(t)return n.settled;let r=await Promise.race([n.settled,new Promise(e=>setTimeout(()=>e(null),SS))]);return r===null&&n.cancel(),r??!1}var TS=`browsentic:skills`,ES=e=>`browsentic:skill:${e}`;async function DS(){let e=(await t.storage.local.get(TS))[TS];return Array.isArray(e)?e:[]}async function OS(e){await t.storage.local.set({[TS]:e})}async function kS(e){let n=ES(e),r=(await t.storage.local.get(n))[n];return r&&typeof r.body==`string`?r:null}async function AS(e,t){await OS((await DS()).map(n=>n.id===e?{...n,...t}:n))}async function jS(e){let t=(await DS()).find(t=>t.id===e);if(t?.origin===`generated`)return;let n=await kS(e);if(!t||!n){await AS(e,{status:`error`,error:`The skill is missing from storage.`});return}let r=await Ug({name:t.name,description:t.description,category:t.category,domains:t.domains,triggers:n.triggers,body:n.body});r.ok?await AS(e,{status:`saved`,path:r.data.path,error:void 0}):await AS(e,{status:`error`,error:`${r.error.code}: ${r.error.message}`})}async function MS(e){let n=(await DS()).find(t=>t.id===e);n&&await(n.origin===`generated`?Gg(n.name):Wg(n.name)),await t.storage.local.remove(ES(e)),await OS((await DS()).filter(t=>t.id!==e))}async function NS(e){let t=await DS();await OS([{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 PS(){for(let e of await DS())e.status!==`saved`&&e.origin!==`generated`&&await jS(e.id)}var FS=`browsentic:sessions`,IS=e=>`browsentic:session:${e}`,LS=50,RS=[1,5,15];async function zS(){let e=(await t.storage.local.get(FS))[FS];return Array.isArray(e)?e:[]}async function BS(e){await t.storage.local.set({[FS]:e})}async function VS(e,n){if(!n.length)return;let r={id:e.id,items:n.slice(-500).map(HS)};await t.storage.local.set({[IS(e.id)]:r});let i=await zS(),a=[{...i.find(t=>t.id===e.id),...e},...i.filter(t=>t.id!==e.id)],o=a.slice(LS);o.length&&await t.storage.local.remove(o.map(e=>IS(e.id))),await BS(a.slice(0,LS))}function HS(e){if(e.kind!==`tool`||!e.preview)return e;let{preview:t,...n}=e;return n}async function US(e){let n=IS(e),r=(await t.storage.local.get(n))[n];return r&&Array.isArray(r.items)?r:null}async function WS(e,t){let n=await zS();n.some(t=>t.id===e)&&await BS(n.map(n=>n.id===e?{...n,...t}:n))}var GS=60;async function KS(e){let t=(await zS()).find(t=>t.id===e);if(!t)return;let n=((await US(e))?.items??[]).filter(e=>e.kind===`user`).map(e=>e.text).slice(-12);if(!n.length)return;let r=t.turns;await WS(e,{namingAt:Date.now()});let i=await Bg({host:t.host,messages:n});if(i.ok&&i.data.title.trim()){await WS(e,{title:i.data.title.replace(/\s+/g,` `).trim().slice(0,GS),titledAtTurn:r,namingAt:void 0});return}await WS(e,{titledAtTurn:r,namingAt:void 0})}function qS(e,t=0){let n=RS.filter(t=>e>=t).at(-1);return n!==void 0&&n>t?n:null}var JS=`/context`,YS=e=>e.trim().toLowerCase()===JS;async function XS(e){let{offer:t,code:n}=e,r={host:t.host,segment:t.segment},i=oh(e.slug??``)||t.suggestedSlug,a=await gh(r,i),o={id:crypto.randomUUID(),name:a,skillName:lh(r,i),description:t.purpose,scope:r,origin:t.origin,code:n,fn:t.fn,createdAt:Date.now()};return await mh(o),await Ug(QS(o)).catch(()=>void 0),dh(o)}async function ZS(e){let t=await hh(e);return t&&await Wg(t.skillName).catch(()=>void 0),t}function QS(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 $S=/\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,eC=/^(?: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+/,tC=/\s+(?:please|thanks|thank you|for me|now|a bit|a little|a lot|some more|more|slightly|real quick|quickly)$/,nC=/[^a-z0-9\s./:&=@_+#-]/g;function rC(e){let t=e.trim(),n=t.toLowerCase().replace(/['‘’]/g,``);n=n.replace($S,`$1.$2`),n=n.replace(nC,` `).replace(/\s+/g,` `).trim();let r=!1,i;do i=n,n=n.replace(eC,``).replace(tC,``).trim(),r||=n!==i;while(n!==i);return{text:n.replace(/\.$/,``),raw:t,question:/\?\s*$/.test(t)&&!r}}var iC={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`},aC=new Set([`enter`,`return`]),oC={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`},sC=Object.keys(oC).join(`|`),cC=/\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/,lC=/^(?:it|that|this|there|them|those|these|him|her|thing|one)$/,uC=8,dC=[{id:`history.back`,action:Nu.name,certainty:.97,pattern:/^(?:go\s+)?back(?:\s+(?:a|one)\s+page)?$/,build:()=>pC({action:`back`},`Go back`)},{id:`history.forward`,action:Nu.name,certainty:.97,pattern:/^(?:go\s+)?forwards?(?:\s+(?:a|one)\s+page)?$/,build:()=>pC({action:`forward`},`Go forward`)},{id:`history.reload`,action:Nu.name,certainty:.97,pattern:/^(?:reload|refresh)(?:\s+(?:the|this)\s+page)?$/,build:()=>pC({action:`reload`},`Reload the page`)},{id:`tab.open`,action:Pu.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=iC[e];if(t)return mC({url:`https://${t}`},`Open ${t} in a new tab`,1);let n=_C(e);return n?mC({url:n},`Open ${e} in a new tab`,/^https?:\/\//.test(e)?1:.97):null}},{id:`navigate.url`,action:Nu.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=iC[e];if(t)return pC({url:`https://${t}`},`Open ${t}`,1);let n=_C(e);return n?pC({url:n},`Open ${e}`,/^https?:\/\//.test(e)?1:.97):null}},{id:`navigate.search`,action:Nu.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:pC({url:`https://www.google.com/search?q=${encodeURIComponent(n)}`},`Search the web for "${n}"`,e===`google`?.95:1)}},{id:`site.search`,action:Wd.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?fC({query:t},`Search this site for "${t}"`):null}},{id:`scroll.direction`,action:Hd.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})=>hC({direction:e},`Scroll ${e}`)},{id:`scroll.page`,action:Hd.name,certainty:.95,pattern:/^page\s+(?<dir>up|down)$/,build:({dir:e})=>hC({direction:e},`Scroll ${e}`)},{id:`scroll.element`,action:Hd.name,certainty:.85,pattern:/^scroll\s+(?:down\s+)?to\s+(?:the\s+)?(?<label>.+)$/,build:({label:e})=>{let t=gC(e);return t&&hC({target:{text:t.value}},`Scroll to ${t.value}`,t.confidence)}},{id:`key.press`,action:Yu.name,certainty:.97,pattern:RegExp(`^(?:press|hit|tap|push)(?:\\s+the)?\\s+(?<key>${sC})(?:\\s+key)?$`),build:({key:e})=>{let t=oC[e];return t?fC({key:t},`Press ${e}`):null}},{id:`recording.start`,action:Hf,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:()=>fC({captureValues:!1},`Start recording this session`)},{id:`recording.stop`,action:Uf,certainty:.95,pattern:/^(?:stop|end|finish)\s+(?:the\s+)?recording$/,build:()=>fC({},`Stop recording`)},{id:`monitor.stop`,action:mf.name,certainty:.95,pattern:/^(?:stop|end|quit|cancel)\s+(?:the\s+)?(?:monitor(?:ing)?|watching)(?:\s+(?:the|this|that)\s+\S{1,20})?$/,build:()=>fC({},`Stop monitoring`)},{id:`click.text`,action:Ic.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=gC(e);return!n||!t&&aC.has(n.value.toLowerCase())?null:{input:{target:t?{text:n.value,role:t}:{text:n.value}},label:`Click ${n.value}`,confidence:n.confidence,risky:cC.test(n.value)}}}],fC=(e,t,n=1)=>({input:e,label:t,confidence:n}),pC=(e,t,n=1)=>fC(e,t,n),mC=(e,t,n=1)=>fC(e,t,n),hC=(e,t,n=1)=>fC(e,t,n);function gC(e){let t=e.trim();if(!t)return null;let n=t.split(/\s+/);if(n.length>uC)return null;if(lC.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 _C(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 vC=/^(?: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/,yC=/\b(?:and then|then|after that|and also|followed by)\b/,bC=/\b(?:if|unless|whenever|maybe|might|try to|see if|as soon as|in case|otherwise)\b/;function xC(e){let t=rC(e);if(t.raw.startsWith(`@`))return SC(`skill-prefix`,0);if(!t.text)return SC(`no-match`,0);if(t.question||vC.test(t.text))return SC(`question`,0);if(yC.test(t.text))return SC(`multi-step`,0);if(bC.test(t.text))return SC(`conditional`,0);let n=null;for(let e of dC){let r=e.pattern.exec(t.text);if(!r)continue;let i=e.build(r.groups??{});if(!i)continue;let a=CC(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?SC(`consequential`,n.score,n.rule.id):n.score<.75?SC(`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}}:SC(`no-match`,0)}var SC=(e,t,n)=>({decision:`escalate`,reason:e,score:t,ruleId:n}),CC=e=>Math.round(e*1e3)/1e3;async function wC(e,t,n){let r=xC(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 TC(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||EC(i)?!0:(console.debug(`[browsentic] fast path ${s} (${c}) failed, escalating:`,d.error.code),!1)}async function TC(e,t,n){return e===Hf?bv(t?.captureValues===!0):e===Uf?Cv(`user`):Yx(e,t,n)}function EC(e){return e===Hf||e===Uf}var DC=`browsentic/indicator`,OC=`#ff7a3d`,kC=`browsentic/rail`;function AC(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.channel===`browsentic/rail`&&(t.op===`open`||t.op===`sync`)}var jC=`browsentic/panelCollapsed`,MC=`browsentic/panelTab`;async function NC(){return(await t.storage.local.get(jC))[jC]===!0}async function PC(){let e=(await t.storage.local.get(MC))[MC];return typeof e==`string`?e:`chat`}function FC(e){return t.sidePanel.open({windowId:e})}var IC=`browsentic/daemon`;async function LC(e){await t.storage.local.set({[jC]:e}),await VC()}var RC=null,zC=!1,BC=null;function VC(){return RC?(zC=!0,RC):(RC=(async()=>{do zC=!1,await UC();while(zC);RC=null})(),RC)}async function HC(){await NC()||(BC=null,await VC())}async function UC(){let e=await NC();if(!e&&BC===!1)return;let n=e?{channel:kC,op:`show`,view:await KC()}:{channel:kC,op:`hide`},r=await t.tabs.query({});await Promise.all(r.map(e=>GC(e.id,e.discarded,n))),BC=e}async function WC(e){await NC()&&await GC(e,!1,{channel:kC,op:`show`,view:await KC()})}function GC(e,n,r){if(!(e==null||n))return t.tabs.sendMessage(e,r).catch(()=>void 0)}async function KC(){let[e,t,n,r,i,a,o,s]=await Promise.all([JC(),zS(),DS(),ev(),X(),PC(),YC(),Uy()]),c=Object.values(i).filter(e=>e.runId).length,l=qC(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 qC(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 JC(){return(await t.storage.session.get(IC))[IC]??null}async function YC(){let e=t.sidePanel;if(!e.getLayout)return`right`;try{return(await e.getLayout()).side===`left`?`left`:`right`}catch{return`right`}}function XC(){t.runtime.onMessage.addListener((e,n)=>{if(!AC(e))return;let{id:r,windowId:i}=n.tab??{};if(!(r==null||i==null))return e.op===`sync`?(WC(r),Promise.resolve({ok:!0})):(FC(i).catch(()=>void 0),t.storage.local.set({[MC]:e.tab}),Promise.resolve({ok:!0}))}),t.tabs.onUpdated.addListener((e,t)=>{t.status===`complete`&&WC(e)}),t.storage.local.onChanged.addListener(e=>{(`browsentic/panelCollapsed`in e||`browsentic/panelTab`in e||`browsentic/theme`in e)&&VC()}),t.storage.session.onChanged.addListener(e=>{IC in e&&VC()})}var ZC=`●`,QC=new Set;function $C(){return t.action??null}async function ew(){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)QC.has(t)||await nw(t,!0);for(let t of[...QC])e.has(t)||await nw(t,!1);await VC()}function tw(e){QC.delete(e)}async function nw(e,n){n?QC.add(e):QC.delete(e);let r=$C();if(r)try{await r.setBadgeBackgroundColor({tabId:e,color:OC}),await r.setBadgeText({tabId:e,text:n?ZC:``})}catch{QC.delete(e)}await t.tabs.sendMessage(e,{channel:DC,op:n?`busy`:`idle`}).catch(()=>void 0)}var rw=`[redacted]`,iw=200,aw=20,ow=4;function sw(e,t,n){if(typeof t==`string`)return Xf({name:e,id:e,value:t})?rw:t.length>iw?`${t.slice(0,iw)}…`:t;if(typeof t==`number`||typeof t==`boolean`||t===null)return t;if(n>=ow)return`[…]`;if(Array.isArray(t)){let r=t.slice(0,aw).map(t=>sw(e,t,n+1));return t.length>aw?[...r,`…`]:r}if(typeof t==`object`){let e={};for(let[r,i]of Object.entries(t))e[r]=Xf({name:r,id:r})?rw:sw(r,i,n+1);return e}return null}var cw={"page.fillInput":`value`,"page.typeText":`text`},lw={"page.injectCode":[`purpose`,`code`]};function uw(e,t){if(!t||typeof t!=`object`)return sw(``,t,0);let n=sw(``,t,0);for(let r of lw[e]??[]){let e=t[r];typeof e==`string`&&(n[r]=e)}let r=cw[e];if(r&&r in n){let e=t[r],i=typeof e==`string`?Pp(e):[];n[r]=i.length?i.map(e=>e.text).join(` `):rw}return n}var dw=()=>crypto.randomUUID();function fw(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:dw(),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:dw(),text:t.delta}]}case`tool`:return[...e,{kind:`tool`,id:t.toolId,action:t.action,input:uw(t.action,t.input),source:t.source}];case`approval`:return pw(e,t.toolId,{awaiting:!0,site:t.site});case`toolResult`:return pw(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:dw(),tone:`info`,text:`Stopped: ${t.stopReason}`}];case`error`:return[...e,{kind:`notice`,id:dw(),tone:`error`,text:`${t.code}: ${t.message}`}]}}function pw(e,t,n){return e.map(e=>e.kind===`tool`&&e.id===t?{...e,...n}:e)}function mw(e,t){for(let n=e.length-1;n>=0;n--){let r=e[n];if(r.kind===`tool`&&r.action===Vd.name&&!r.preview){let i=[...e];return i[n]={...r,preview:t},i}}return e}function hw(e,t){return{kind:`notice`,id:dw(),tone:e,text:t}}function gw(e){let t=e.label??e.host,n=_w(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 _w(e){let t=Math.floor(e/1e3);return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}var vw=`local`,yw=4e3,bw=800,xw=new Set,Sw=new Set,Cw=new Set,Z=new Map,ww=new Set,Tw=new Map,Ew=new Map,Dw=[],Ow=new Map,kw=new Map,Aw=Promise.resolve();function Q(e){let t=Aw.then(e,e);return Aw=t.catch(()=>void 0),t}function jw(){kg((e,t)=>{Q(()=>Lw(e,t))}),sx((e,t)=>{Q(async()=>{let n=t?await zx(t):null;if(n){let t=mw(await qw(n.sessionId),e);Z.set(n.sessionId,t)}$({op:`preview`,sessionId:n?.sessionId,preview:e})})}),Ch(e=>{kw.set(e.toolkitId,e),$({op:`toolOffer`,offer:e})}),nb(e=>{$({op:`monitor`,state:e}),e.phase!==`watching`&&(Q(async()=>{let t=e.tabId==null?null:await Rx(e.tabId);t&&await Jw(t.sessionId,hw(...oT(e)))}),xw.size>0&&Cb(e.monitorId))}),Pb((e,t,n)=>Q(async()=>{let r=(await X())[e];return r?r.runId||ww.has(e)?`busy`:(await Jw(e,hw(`info`,`Timer “${n}” fired.`)),await Bw(r,t,{fastPath:!1}),`delivered`):`gone`})),Og((e,t)=>{Q(async()=>{let n=await zx(e);if(n)for(let[e,t]of Ow)t.sessionId===n.sessionId&&Ow.delete(e);Ow.set(t.stagingId,{sessionId:n?.sessionId,draft:t}),$({op:`mapDraft`,sessionId:n?.sessionId,draft:t})})}),Ag(()=>{Q(async()=>{for(let e of Object.values(await X()))e.runId&&await Uw(e.sessionId,`The connection to the daemon dropped, so that run is over.`)})}),mv(e=>{e?.warning&&$({op:`event`,runId:vw,event:{kind:`error`,code:`RECORDING_LIMIT`,message:e.warning}}),$({op:`recording`,state:e})}),t.runtime.onConnect.addListener(e=>{if(e.name===`browsentic/run`){if(xw.add(e),e.sender?.url?.includes(`sidepanel.html`)&&(Sw.add(e),Sw.size===1))for(let e of Cw)e(!0);for(let t of Ow.values())lT(e,{op:`mapDraft`,sessionId:t.sessionId,draft:t.draft});vv().then(t=>lT(e,{op:`recording`,state:t})),fh().then(t=>lT(e,{op:`tools`,tools:t.map(dh)})),xb().then(t=>{for(let n of t)lT(e,{op:`monitor`,state:n})}),Sb().then(t=>{if(t.length){for(let n of t)lT(e,{op:`monitor`,state:n});Cb()}}),e.onMessage.addListener(e=>Pw(e)),e.onDisconnect.addListener(()=>{if(xw.delete(e),Sw.delete(e)&&Sw.size===0)for(let e of Cw)e(!1)})}})}function Mw(e){Cw.add(e)}function Nw(){for(let e of Sw)lT(e,{op:`close`})}function Pw(e){switch(e.op){case`instruct`:Q(()=>zw(e.text,e.tab,e.agentSkillId,e.focus,e.liveTools));return;case`cancel`:Q(()=>Hw(e.sessionId));return;case`decision`:Q(async()=>{let t=(await X())[e.sessionId];t?.runId&&(Z.set(e.sessionId,pw(await qw(e.sessionId),e.toolId,{awaiting:!1})),await Wx(e.sessionId,{pendingApproval:void 0}),l_(t.runId,e.toolId,e.allow,e.remember))});return;case`endSession`:Q(()=>Gw(e.sessionId));return;case`replay`:Q(async()=>{$({op:`items`,sessionId:e.sessionId,items:await qw(e.sessionId)})});return;case`restore`:Q(()=>Kw(e.sessionId,e.tab));return;case`activateMap`:case`discardMap`:{let t=Ow.get(e.stagingId);(e.op===`activateMap`?Kg(e.stagingId,e.exactHost):qg(e.stagingId)).then(n=>{if(n.ok&&e.op===`activateMap`&&t){let{draft:n}=t;NS({name:n.name,domain:e.exactHost?n.host:n.domain,directory:n.directory,pages:n.pages,generatedAt:n.generatedAt})}Ow.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`:Qw(e.captureValues);return;case`stopRecording`:Cv(`user`);return;case`stopMonitor`:_b(e.monitorId);return;case`keepTool`:Q(async()=>{let t=kw.get(e.toolkitId),n=t?await Mh(e.tabId,e.toolkitId):null;t&&n&&await XS({offer:t,code:n,slug:e.slug}).catch(()=>void 0),kw.delete(e.toolkitId),$({op:`toolOfferSettled`,toolkitId:e.toolkitId}),await Iw()});return;case`dismissTool`:kw.delete(e.toolkitId),$({op:`toolOfferSettled`,toolkitId:e.toolkitId});return;case`forgetTool`:Q(async()=>{await ZS(e.id),await Iw()});return;case`runTool`:Q(async()=>{let t=await jh(e.tab.tabId,e.tab.url,e.id);$({op:`item`,item:Fw(e.id,t)})});return;case`listTools`:Iw();return}}function Fw(e,t){return t.ok?{kind:`tool`,id:dw(),action:`savedTool`,input:{tool:e},ok:!0,source:`local`}:hw(`error`,`${t.error?.code}: ${t.error?.message}`)}async function Iw(){$({op:`tools`,tools:(await fh()).map(dh)})}async function Lw(e,t){if(e===`external`){Dw=fw(Dw,t).slice(-100),$({op:`event`,runId:e,event:t});return}let n=await zx(e);if(!n)return;let{sessionId:r}=n;Z.set(r,fw(await qw(r),t)),$({op:`event`,sessionId:r,runId:e,event:t}),t.kind===`session`?await Wx(r,{agent:t.agent,agentSessionId:t.agentSessionId??void 0}):t.kind===`approval`?await Wx(r,{pendingApproval:{toolId:t.toolId,action:t.action,input:t.input,site:t.site}}):t.kind===`toolResult`?await Wx(r,{pendingApproval:void 0}):t.kind===`usage`&&await Wx(r,{usage:t.usage}),t.kind===`done`||t.kind===`error`?await Rw(r):Yw(r)}async function Rw(e){clearTimeout(Ew.get(e)),Ew.delete(e),await xy(e),await Wx(e,{runId:null,pendingApproval:void 0}),await ew();let n=(await X())[e];if(n){let r=await t.tabs.get(n.currentTabId).catch(()=>null);r?.url&&await Wx(e,{url:r.url,host:Jx(r.url)})}await Xw(e);let r=(await zS()).find(t=>t.id===e);!r||qS(r.turns,r.titledAtTurn)===null||await KS(e).catch(()=>void 0)}async function zw(e,t,n,r,i){let a=await Bx(t);if(!a.ok){$({op:`event`,runId:vw,event:{kind:`error`,code:`SESSION_LIMIT`,message:a.message}});return}if(YS(e)){let{sessionId:e}=a.session,t=await aT(a.session,await qw(e));await Jw(e,{kind:`user`,id:dw(),text:JS}),await Jw(e,{kind:`context`,id:dw(),breakdown:t});return}await Bw(a.session,e,{agentSkillId:n,focus:r,liveTools:i,fastPath:!0})===`busy`&&await Jw(a.session.sessionId,hw(`error`,`RUN_IN_PROGRESS: This conversation is still running — stop it before sending another instruction.`))}async function Bw(e,t,n){let{agentSkillId:r,focus:i,liveTools:a,fastPath:o}=n,{sessionId:s}=e;if(e.runId||ww.has(s))return`busy`;await Jw(s,{kind:`user`,id:crypto.randomUUID(),text:t,focus:i&&$w(i)}),await Wx(s,{turns:e.turns+1}),ww.add(s);try{if(o&&!r&&!i&&await Vw(t,e))return await Xw(s),`local`;let n=jg(t,{url:e.url,tabId:e.currentTabId,sessionId:s,agent:e.agent,agentSessionId:e.agentSessionId,agentSkillId:r,focus:i,liveTools:a,files:await nT(),recordings:await iT()});return n?(await Wx(s,{runId:n}),await ew(),`started`):(await Jw(s,hw(`error`,`EXTENSION_OFFLINE: No Browsentic daemon is attached, so only quick browser commands work. Pair the browser to do more.`)),await Xw(s),`offline`)}finally{ww.delete(s)}}async function Vw(e,t){try{return await wC(e,e=>{Z.set(t.sessionId,fw(Z.get(t.sessionId)??[],e)),$({op:`event`,sessionId:t.sessionId,runId:vw,event:e})},t.currentTabId)}catch(e){return console.warn(`[browsentic] fast path threw, escalating:`,e),!1}}async function Hw(e){let t=(await X())[e]?.runId;if(t){if(!c_(t)){await Uw(e,`The daemon is not connected, so there was nothing left to stop.`);return}clearTimeout(Ew.get(e)),Ew.set(e,setTimeout(()=>{Q(async()=>{(await X())[e]?.runId===t&&await Uw(e,`Stopped. The daemon never confirmed it, so check for a run still finishing there.`)})},yw))}}async function Uw(e,t){await Jw(e,hw(`error`,`CANCELLED: ${t}`)),await Rw(e)}function Ww(e){for(let t of Ow.values())t.sessionId===e&&(t.sessionId=void 0,$({op:`mapDraft`,draft:t.draft}))}async function Gw(e){let t=(await X())[e];t?.runId&&c_(t.runId),await xy(e),await Qb(e),clearTimeout(Ew.get(e)),Ew.delete(e),await Xw(e),await Gx(e),Z.delete(e),ww.delete(e),Ww(e),u_(e),await ew()}async function Kw(e,t){if(Object.values(await X()).find(t=>t.sessionId===e))return;let n=await Rx(t.tabId);if(n?.runId){await Jw(n.sessionId,hw(`error`,`RUN_IN_PROGRESS: This tab is still running — stop it before opening another conversation here.`));return}n&&(await Xw(n.sessionId),await Gx(n.sessionId),Z.delete(n.sessionId),Ww(n.sessionId));let r=(await zS()).find(t=>t.id===e);if(!r)return;let i=await US(e);Z.set(e,i?.items??[hw(`error`,`That conversation’s messages are no longer stored.`)]);let a=await Vx({sessionId:e,turns:r.turns,agent:r.agent,agentSessionId:r.agentSessionId,usage:r.usage,url:r.url,title:sT(r)??t.title},t);$({op:`items`,sessionId:e,items:Z.get(e)??[]}),r.url&&/^https?:$/.test(cT(r.url))&&await Yx(Nu.name,{url:r.url},a.currentTabId).catch(()=>void 0)}async function qw(e){let t=Z.get(e);if(t)return t;let n=(await US(e))?.items??[];return Z.set(e,n),n}async function Jw(e,t){Z.set(e,[...await qw(e),t]),$({op:`item`,sessionId:e,item:t}),Yw(e)}function Yw(e){clearTimeout(Tw.get(e)),Tw.set(e,setTimeout(()=>void Q(()=>Xw(e)),bw))}async function Xw(e){clearTimeout(Tw.get(e)),Tw.delete(e);let t=Z.get(e);if(!t?.length)return;let n=(await X())[e],r=n?null:(await zS()).find(t=>t.id===e),i=Date.now();await VS({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 Zw(){t.tabs.onRemoved.addListener(e=>{tw(e),Q(async()=>{let{closed:t}=await Kx(e);if(!t)return await ew();t.runId&&(c_(t.runId),await Jw(t.sessionId,hw(`error`,`CANCELLED: The tab was closed, so that run is over.`))),clearTimeout(Ew.get(t.sessionId)),Ew.delete(t.sessionId),await Qb(t.sessionId),await Xw(t.sessionId),Z.delete(t.sessionId),ww.delete(t.sessionId),Ww(t.sessionId),t.runId&&u_(t.sessionId),await ew()})}),t.tabs.onReplaced.addListener((e,t)=>{Q(()=>qx(t,e))}),t.tabs.onUpdated.addListener((e,t,n)=>{t.title===void 0&&t.url===void 0||Q(async()=>{let r=await Rx(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=Jx(t.url)),Object.keys(i).length&&await Wx(r.sessionId,i)})})}async function Qw(e){let t=await bv(e);t.ok||$({op:`event`,runId:vw,event:{kind:`error`,code:t.error.code,message:t.error.message}})}var $w=e=>[e.role??e.tag,e.label].filter(Boolean).join(` · `),eT=6,tT=2e3;async function nT(){try{return(await j_()).slice(0,eT).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,tT)}))}catch{return[]}}var rT=8;async function iT(){try{return(await ev()).filter(e=>e.status===`ready`).slice(0,rT).map(lv)}catch{return[]}}async function aT(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 j_().catch(()=>[]),i=(await ev().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,eT).map(e=>({name:e.name,size:e.size,status:e.status})),filesOmitted:Math.max(0,r.length-eT),recordings:i.slice(0,rT).map(e=>({name:e.name,steps:e.steps})),recordingsOmitted:Math.max(0,i.length-rT),capturedAt:Date.now()}}var oT=e=>{let{tone:t,text:n}=gw(e);return[t,n]},sT=e=>e.title??void 0;function cT(e){try{return new URL(e).protocol}catch{return``}}function $(e){for(let t of xw)lT(t,e)}function lT(e,t){try{e.postMessage(t)}catch{xw.delete(e)}}var uT=[`claude`,`codex`,`antigravity`],dT={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`]}};uT.map(e=>dT[e]);function fT(e){return typeof e==`string`&&uT.includes(e)}var pT=`open-side-panel`,mT=e(()=>{mm(),t.runtime.onMessage.addListener((e,t,n)=>{if(c(e)){if(e.op===`describe`){n(o(Pf()));return}if(e.op===`invoke`&&typeof e.action==`string`)return Yx(e.action,e.input).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`analyzeFile`&&typeof e.fileId==`string`){F_(e.fileId),n(o(!0));return}if(e.op===`saveSkill`&&typeof e.skillId==`string`){jS(e.skillId),n(o(!0));return}if(e.op===`removeSkill`&&typeof e.skillId==`string`){MS(e.skillId),n(o(!0));return}if(e.op===`nameSession`&&typeof e.sessionId==`string`){KS(e.sessionId),n(o(!0));return}if(e.op===`recordEvents`&&Array.isArray(e.events)){Sv(t.tab?.id,e.events),n(o(!0));return}if(e.op===`recordingState`)return yv(t.tab?.id).then(e=>n(o(e))).catch(()=>n(o({recording:!1,captureValues:!1}))),!0;if(e.op===`analyzeRecording`&&typeof e.recordingId==`string`){av(e.recordingId),n(o(!0));return}if(e.op===`monitorSample`&&typeof e.monitorId==`string`){pb(t.tab?.id,e.monitorId,e.sample),n(o(!0));return}if(e.op===`monitorState`)return bb(t.tab?.id).then(n).catch(()=>n(o({monitors:[]}))),!0;if(e.op===`listSkills`)return r_(e.refresh===!0).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`agentState`)return Zg(e.refresh===!0).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`setAgent`&&fT(e.agent))return Qg(e.agent).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`setAgentModel`&&fT(e.agent))return $g(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`&&fT(e.agent))return e_(e.agent).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`guardrails`)return a_().then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`setGuardrail`&&typeof e.setting==`string`)return o_(e.setting,e.value).then(n).catch(e=>n(s(`BRIDGE_ERROR`,String(e)))),!0;if(e.op===`pair`&&typeof e.token==`string`)return f_(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`){LC(!1),n(o(!0));return}if(e.op===`disconnect`)return p_().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&&Rf(t.id)})});let e=t.contextMenus.removeAll().then(()=>t.contextMenus.create({id:pT,title:`Open Browsentic`,contexts:[`all`]})),n=!1;Mw(r=>{n=r,e.then(()=>t.contextMenus.update(pT,{title:r?`Close Browsentic`:`Open Browsentic`})),r||HC()}),t.contextMenus.onClicked.addListener((e,t)=>{if(!(e.menuItemId!==pT||t?.windowId==null)){if(n){Nw();return}FC(t.windowId)}}),Cy(),Dh(),wv(),wb(),$b(),jw(),Zw(),XC(),Jy(),VC(),Ag(()=>{PS(),ov()}),d_(),t.runtime.onStartup.addListener(()=>void d_()),t.alarms.create(_g,{periodInMinutes:1}),t.alarms.onAlarm.addListener(e=>{e.name===`browsentic/reconnect`&&d_()})}),hT={debug:(...e)=>([...e],void 0),log:(...e)=>([...e],void 0),warn:(...e)=>([...e],void 0),error:(...e)=>([...e],void 0)},gT;try{gT=mT.main(),gT instanceof Promise&&console.warn(`The background's main() function return a promise, but it must be synchronous`)}catch(e){throw hT.error(`The background crashed on startup!`),e}return gT})();