@vpxa/aikit 0.1.173 → 0.1.175
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.
- package/package.json +3 -3
- package/packages/blocks-core/dist/index.d.ts +4 -3
- package/packages/blocks-core/dist/index.js +90 -25
- package/packages/browser/dist/index.d.ts +6 -1
- package/packages/browser/dist/index.js +14 -6
- package/packages/cli/dist/index.js +16 -16
- package/packages/cli/dist/{init-BVU1RVy5.js → init-BDZpaO7q.js} +1 -1
- package/packages/cli/dist/{scaffold-BB6OrTuA.js → scaffold-BdUnq1xy.js} +1 -1
- package/packages/core/dist/index.d.ts +29 -1
- package/packages/dashboard/dist/assets/{index-ehoWAjDs.js → index-4HQiq-qo.js} +2 -2
- package/packages/dashboard/dist/index.html +1 -1
- package/packages/present/dist/index.html +119 -54
- package/packages/server/dist/auth-BfqgawfR.js +1 -0
- package/packages/server/dist/config-DAnAxrUW.js +1 -0
- package/packages/server/dist/{curated-manager-BkSgtNC2.js → curated-manager-BnP6VqvL.js} +4 -4
- package/packages/server/dist/index.js +1 -1
- package/packages/server/dist/proxy.d.ts +32 -0
- package/packages/server/dist/proxy.js +4 -0
- package/packages/server/dist/server-B0gtRiNa.js +2909 -0
- package/packages/server/dist/supersession-DJQGXMWm.js +2 -0
- package/packages/server/viewers/canvas.html +127 -62
- package/packages/server/viewers/report-template.html +92 -27
- package/packages/server/viewers/tour-viewer.html +91 -26
- package/packages/settings-ui/dist/assets/{index-DSTxXokO.js → index-DLcLvASh.js} +2 -2
- package/packages/store/dist/index.d.ts +135 -1
- package/packages/store/dist/index.js +447 -12
- package/packages/tools/dist/index.d.ts +72 -30
- package/packages/tools/dist/index.js +72 -73
- package/{scaffold/general → packages}/viewers/README.md +1 -1
- package/scaffold/dist/definitions/bodies.mjs +28 -3
- package/scaffold/dist/definitions/prompts.mjs +1 -1
- package/scaffold/dist/definitions/protocols.mjs +25 -0
- package/scaffold/dist/definitions/skills/aikit.mjs +1 -1
- package/scaffold/dist/definitions/skills/browser-use.mjs +1 -1
- package/scaffold/dist/definitions/skills/c4-architecture.mjs +1 -1
- package/scaffold/dist/definitions/skills/docs.mjs +1 -1
- package/scaffold/dist/definitions/tools.mjs +1 -1
- package/packages/server/dist/config-Dsu2Kd3U.js +0 -1
- package/packages/server/dist/server-CqEB0MaC.js +0 -2901
- /package/packages/cli/dist/{templates-D-eA4QVK.js → templates-Do9eni2d.js} +0 -0
- /package/packages/server/dist/{dashboard-static-BfIe0Si1.js → dashboard-static-CnXafYTs.js} +0 -0
- /package/packages/server/dist/{routes-gbC5Wmr9.js → routes-CR3fI-HJ.js} +0 -0
- /package/packages/server/dist/{settings-static-BosGZSPf.js → settings-static-BkVLqWOr.js} +0 -0
- /package/packages/server/dist/{version-check-Bj07vc5x.js → version-check-BgHzxxCW.js} +0 -0
- /package/packages/store/dist/{lance-store-BIP1LEiS.js → lance-store-BRKcJXVO.js} +0 -0
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import{createRequire as e}from"node:module";import{createHash as t,randomUUID as n}from"node:crypto";import{homedir as r}from"node:os";import{join as i}from"node:path";import{execFileSync as a}from"node:child_process";import{existsSync as o,readdirSync as s}from"node:fs";import{Buffer as c}from"node:buffer";import{z as l}from"zod";var u=class{#e;#t;#n=0;#r=0;constructor(e=200){if(!Number.isInteger(e)||e<1)throw RangeError(`CircularBuffer capacity must be a positive integer.`);this.#e=e,this.#t=Array(e)}push(e){this.#t[this.#n]=e,this.#n=(this.#n+1)%this.#e,this.#r<this.#e&&(this.#r+=1)}toArray(){if(this.#r===0)return[];let e=(this.#n-this.#r+this.#e)%this.#e,t=[];for(let n=0;n<this.#r;n+=1)t.push(this.#t[(e+n)%this.#e]);return t}clear(){this.#t=Array(this.#e),this.#n=0,this.#r=0}get size(){return this.#r}get capacity(){return this.#e}isEmpty(){return this.#r===0}};const d=[`xhr`,`fetch`,`websocket`,`document`],f=[/^authorization$/i,/^cookie$/i,/^set-cookie$/i,/^x-api-key$/i,/^x-access-token$/i,/^x-auth-token$/i,/^x-session$/i,/^x-secret$/i,/^x-password$/i,/^proxy-authorization$/i,/^www-authenticate$/i,/^x-csrf-token$/i,/^x-xsrf-token$/i];function p(e,t){if(t?.showSensitive)return{...e};let n=[...f,...t?.additionalPatterns??[]],r={};for(let[t,i]of Object.entries(e))r[t]=n.some(e=>e.test(t))?`[REDACTED]`:i;return r}function m(e,t=512){if(e)return e.length<=t?e:`${e.slice(0,t)}...[truncated]`}function ee(){return{networkBuffer:new u(200),consoleBuffer:new u(1e3),networkEnabled:!1,consoleEnabled:!1,networkFilter:{},nextRequestSequence:0,pendingRequests:new Map}}function te(e,t){if(e.capacity===t)return e;let n=new u(t),r=e.toArray(),i=Math.max(0,r.length-t);for(let e of r.slice(i))n.push(e);return n}function ne(e){switch(e){case`error`:case`info`:case`log`:case`debug`:return e;case`warning`:return`warn`;default:return`log`}}function re(e){if(e)return Buffer.byteLength(e)<=5242880?m(e):void 0}function ie(e){if(!e)return{};let t=Buffer.byteLength(e);return{bodySize:t,bodyPreview:t<=5242880?m(e):void 0}}function ae(e,t){return!t.resourceTypes.has(e.resourceType)||t.urlPattern&&!t.urlPattern.test(e.url)?!1:!t.excludeUrls.some(t=>t.test(e.url))}function h(e){if(e.length>200)throw Error(`Network filter regex patterns must be 200 characters or fewer`);try{let t=new RegExp(e);return t.test(`a`.repeat(100)),t}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`Invalid network filter regex pattern: ${t}`)}}function g(e={}){return{resourceTypes:new Set(e.resourceTypes??d),urlPattern:e.urlPattern?h(e.urlPattern):void 0,excludeUrls:(e.excludeUrls??[]).map(e=>h(e))}}function oe(e){return e.nextRequestSequence+=1,`req-${e.nextRequestSequence}`}function se(e,t,n){let r={request:t,previous:e.pendingRequestTail};e.pendingRequestTail?e.pendingRequestTail.next=r:e.pendingRequestHead=r,e.pendingRequestTail=r,e.pendingRequests.set(t,{entry:n,node:r})}function _(e,t){t.previous?t.previous.next=t.next:e.pendingRequestHead=t.next,t.next?t.next.previous=t.previous:e.pendingRequestTail=t.previous,delete t.previous,delete t.next}function ce(e){for(;e.pendingRequests.size>e.networkBuffer.capacity;){let t=e.pendingRequestHead;if(!t)return;_(e,t),e.pendingRequests.delete(t.request)}}function v(e){e.pendingRequests.clear(),e.pendingRequestHead=void 0,e.pendingRequestTail=void 0}var le=class{states=new Map;getOrCreate(e){let t=this.states.get(e);if(t)return t;let n=ee();return this.states.set(e,n),n}get(e){return this.states.get(e)}remove(e){let t=this.states.get(e);t&&(t.networkEnabled=!1,t.consoleEnabled=!1,this.detachNetworkListeners(t),this.detachConsoleListeners(t),v(t),this.states.delete(e))}clear(){for(let e of this.states.values())e.networkEnabled=!1,e.consoleEnabled=!1,this.detachNetworkListeners(e),this.detachConsoleListeners(e),v(e);this.states.clear()}enableNetwork(e,t,n,r){let i=this.getOrCreate(e);i.networkEnabled&&this.disableNetwork(e,t),i.page=t,i.networkEnabled=!0,i.networkFilter=n?{...n}:{},i.compiledNetworkFilter=g(i.networkFilter),r?.bufferSize&&(i.networkBuffer=te(i.networkBuffer,r.bufferSize));let a=e=>{let t=i.compiledNetworkFilter??g(i.networkFilter),n={resourceType:e.resourceType(),url:e.url()};if(!ae(n,t))return;let a={...e.headers()},o=Date.now(),s={id:oe(i),url:n.url,method:e.method(),resourceType:n.resourceType,headers:r?.showSensitive?a:p(a),postData:r?.includeBody?re(e.postData()??void 0):void 0,timestamp:o};i.networkBuffer.push(s),se(i,e,s),ce(i)},o=async e=>{let t=e.request(),n=i.pendingRequests.get(t);if(!n)return;i.pendingRequests.delete(t),_(i,n.node);let a;if(r?.includeBody)try{a=ie(await e.text())}catch{a=void 0}let o={...e.headers()};n.entry.response={status:e.status(),statusText:e.statusText(),headers:r?.showSensitive?o:p(o),bodySize:a?.bodySize,bodyPreview:a?.bodyPreview,timing:Date.now()-n.entry.timestamp}};i.listenerRefs={...i.listenerRefs,requestHandler:a,responseHandler:o},this.ensurePageCloseHandler(e,i,t),t.on(`request`,a),t.on(`response`,o)}disableNetwork(e,t){let n=this.states.get(e);n&&(n.page=n.page??t,n.networkEnabled=!1,this.detachNetworkListeners(n),v(n))}enableConsole(e,t,n){let r=this.getOrCreate(e);r.consoleEnabled&&this.disableConsole(e,t),r.page=t,r.consoleEnabled=!0,n?.bufferSize&&(r.consoleBuffer=te(r.consoleBuffer,n.bufferSize));let i=e=>{let t=e.location();r.consoleBuffer.push({level:ne(e.type()),text:e.text(),timestamp:Date.now(),location:t.url?{url:t.url,line:t.lineNumber,column:t.columnNumber}:void 0,args:e.args().map(e=>e.toString())})};r.listenerRefs={...r.listenerRefs,consoleHandler:i},this.ensurePageCloseHandler(e,r,t),t.on(`console`,i)}disableConsole(e,t){let n=this.states.get(e);n&&(n.page=n.page??t,n.consoleEnabled=!1,this.detachConsoleListeners(n))}detachNetworkListeners(e){let t=e.page,n=e.listenerRefs?.requestHandler,r=e.listenerRefs?.responseHandler;t&&n&&t.off(`request`,n),t&&r&&t.off(`response`,r),e.listenerRefs&&(delete e.listenerRefs.requestHandler,delete e.listenerRefs.responseHandler),this.detachPageCloseHandlerIfUnused(e)}detachConsoleListeners(e){let t=e.page,n=e.listenerRefs?.consoleHandler;t&&n&&t.off(`console`,n),e.listenerRefs&&delete e.listenerRefs.consoleHandler,this.detachPageCloseHandlerIfUnused(e)}ensurePageCloseHandler(e,t,n){if(t.listenerRefs?.pageCloseHandler)return;let r=()=>{this.remove(e)};t.listenerRefs={...t.listenerRefs,pageCloseHandler:r},n.on(`close`,r)}detachPageCloseHandlerIfUnused(e){if(e.networkEnabled||e.consoleEnabled)return;let t=e.page,n=e.listenerRefs?.pageCloseHandler;t&&n&&t.off(`close`,n),e.listenerRefs&&delete e.listenerRefs.pageCloseHandler,e.listenerRefs&&!e.listenerRefs.requestHandler&&!e.listenerRefs.responseHandler&&!e.listenerRefs.consoleHandler&&!e.listenerRefs.pageCloseHandler&&delete e.listenerRefs}};let ue=null;function y(){return ue||=new le,ue}const de=e(import.meta.url);function fe(e){return typeof e==`string`?e.trim():e instanceof Buffer?e.toString(`utf8`).trim():``}function pe(e){process.env.PLAYWRIGHT_BROWSERS_PATH=e}async function b(e){pe(e);let{chromium:t}=await import(`playwright-core`),n=t.executablePath();if(!n)throw Error(`Chromium executable not found in ${e}`);return n}function x(){return i(r(),`.aikit`,`browsers`)}function S(e){return e.browsersPath??process.env.PLAYWRIGHT_BROWSERS_PATH??x()}function C(e){return o(e)?s(e,{withFileTypes:!0}).some(e=>e.isDirectory()&&e.name.toLowerCase().startsWith(`chromium-`)):!1}async function w(e,t){let n=S(e);if(pe(n),t?.(`Using Chromium cache at ${n}`),C(n))return t?.(`Chromium already installed`),b(n);let r=i(de.resolve(`playwright-core`),`..`,`cli.js`);t?.(`Installing Chromium via playwright-core`);try{a(process.execPath,[r,`install`,`chromium`],{env:{...process.env,PLAYWRIGHT_BROWSERS_PATH:n},encoding:`utf8`,stdio:`pipe`})}catch(e){let t=e,n=fe(t.stderr),r=fe(t.stdout),i=n||r||t.message||`Unknown playwright install failure`;throw Error(`Failed to install Chromium: ${i}`)}return t?.(`Chromium install complete`),b(n)}function me(){return process.platform===`win32`||process.platform===`darwin`?!0:!!(process.env.DISPLAY||process.env.WAYLAND_DISPLAY)}function T(e){return e===`headless`||!me()?`headless`:e}function E(e){switch(e){case`headless`:return{headless:!0,args:[]};default:return{headless:!1,args:[]}}}var D=class{pages=new Map;registerPage(e,t,r){let i=n();return this.pages.set(i,{page:e,url:t,title:r,createdAt:new Date}),i}getPage(e){let t=this.pages.get(e);if(!t)throw Error(`Page not found: ${e}`);return t.page}getPageInfo(e){let t=this.pages.get(e);if(!t)throw Error(`Page not found: ${e}`);return{pageId:e,url:t.url,title:t.title,createdAt:t.createdAt}}updatePageInfo(e,t,n){let r=this.pages.get(e);if(!r)throw Error(`Page not found: ${e}`);this.pages.set(e,{...r,url:t,title:n})}async removePage(e){let t=this.pages.get(e);t&&(await t.page.close(),this.pages.delete(e))}listPages(){return[...this.pages.entries()].map(([e,t])=>({pageId:e,url:t.url,title:t.title,createdAt:t.createdAt}))}async closeAll(){await Promise.allSettled([...this.pages.keys()].map(async e=>this.removePage(e)))}get size(){return this.pages.size}};const O={defaultMode:`ui`,browsersPath:null,userDataDirRoot:null,idleShutdownMinutes:10,allowInternalSchemes:!1,evalTimeoutMs:1e4,evalMaxResultBytes:262144,redactPasswordFieldsInScreenshots:!0};var k=class{browser=null;context=null;idleTimer=null;launchPromise=null;currentMode=null;session=new D;config;constructor(e={}){this.config={...O,...e}}async launch(e,t){let n=T(e??this.config.defaultMode);if(this.context&&this.currentMode!==n&&await this.close(),!this.context){if(this.launchPromise)return this.launchPromise;this.launchPromise=this.doLaunch(n,t);try{await this.launchPromise}finally{this.launchPromise=null}}}async doLaunch(e,n){if(this.browser&&this.context)return;let a=S(this.config);process.env.PLAYWRIGHT_BROWSERS_PATH=a;let{chromium:o}=await import(`playwright-core`),s=await w(this.config,n),c=E(e),l=t(`sha256`).update(process.cwd()).digest(`hex`).slice(0,12),u=i(this.config.userDataDirRoot??i(r(),`.aikit`,`profiles`),l);if(n?.(`Launching Chromium in ${e} mode`),this.context=await o.launchPersistentContext(u,{headless:c.headless,args:c.args,executablePath:s}),this.browser=this.context.browser(),!this.browser)throw await this.context.close(),this.context=null,Error(`Failed to acquire Chromium browser instance`);this.currentMode=e,this.browser.on(`disconnected`,()=>{this.browser=null,this.context=null,this.currentMode=null,y().clear(),this.session.closeAll().catch(()=>{}),this.stopIdleTimer()}),this.resetIdleTimer()}stopIdleTimer(){this.idleTimer&&=(clearTimeout(this.idleTimer),null)}resetIdleTimer(){this.stopIdleTimer();let e=setTimeout(()=>{this.close()},this.config.idleShutdownMinutes*6e4);e.unref?.(),this.idleTimer=e}async close(){this.stopIdleTimer(),this.launchPromise=null;let e=this.context,t=this.browser;this.context=null,this.browser=null,this.currentMode=null;let n;try{y().clear()}catch(e){n=e}try{await this.session.closeAll()}catch(e){n??=e}try{e&&await e.close()}catch(e){n??=e}finally{try{t&&await t.close()}catch(e){n??=e}}if(n)throw n}getContext(){if(!this.context)throw Error(`Browser not launched. Call launch() first.`);return this.context}getConfig(){return this.config}isLaunched(){return this.browser!==null}};let A=null;function j(e){return A||=new k(e),A}async function he(){A&&=(await A.close(),null)}const ge=[`file:`,`chrome:`,`chrome-extension:`,`data:`,`javascript:`],_e=[`169.254.169.254`,`metadata.google.internal`,`metadata.google.com`],M=[`localhost`,`127.0.0.1`,`::1`,`[::1]`];function ve(e){return e.replace(/^\[(.*)\]$/,`$1`).toLowerCase()}function ye(e){let t=new WeakSet,n=JSON.stringify(e,(e,n)=>{if(typeof n==`bigint`)return n.toString();if(typeof n==`function`)return`[Function ${n.name||`anonymous`}]`;if(typeof n==`symbol`)return n.toString();if(n instanceof Error)return{name:n.name,message:n.message,stack:n.stack};if(typeof n==`object`&&n){if(t.has(n))return`[Circular]`;t.add(n)}return n});return n===void 0?e===void 0?`undefined`:String(e):n}function be(e,t){let n=c.from(e,`utf8`);return n.byteLength<=t?e:n.subarray(0,t).toString(`utf8`)}function N(e,t){let n;try{n=new URL(e)}catch{return{allowed:!1,reason:`Invalid URL: ${e}`}}let r=n.protocol.toLowerCase();if(ge.includes(r)&&!t.allowInternalSchemes)return{allowed:!1,reason:`Blocked URL scheme: ${r}`};let i=ve(n.hostname);return _e.includes(i)?{allowed:!1,reason:`Blocked host: ${n.hostname}`}:(M.includes(i)||M.includes(n.hostname),{allowed:!0})}function P(e){return e?{allowed:!0}:{allowed:!1,reason:`Cookie access requires explicit confirmation (confirm: true)`}}function F(e,t){if(t<=0)return{valid:!1,reason:`maxBytes must be greater than 0`};try{let n=ye(e);return c.byteLength(n,`utf8`)<=t?{valid:!0,result:n,truncated:!1}:{valid:!0,result:`${be(n,Math.max(t-3,0))}...`,truncated:!0,reason:`Result exceeded ${t} bytes and was truncated`}}catch(e){return{valid:!1,reason:`Unable to serialize eval result: ${e instanceof Error?e.message:String(e)}`}}}function xe(e){return e.replace(/<input\b[^>]*>/gi,e=>/\btype\s*=\s*(["'])password\1/i.test(e)?/\bvalue\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/i.test(e)?e.replace(/\bvalue\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/i,`value="***"`):e.replace(/\s*\/?>$/,e=>` value="***"${e}`):e)}const Se=[`ui`,`headless`];function Ce(e){return typeof e==`object`&&e?e:null}function I(e){return typeof e==`string`&&e.length>0?e:void 0}function L(e){return typeof e==`boolean`?e:void 0}function R(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function z(e){return typeof e==`string`&&Se.includes(e)?e:void 0}function B(e){let t=process.env[e];if(!t)return;let n=Number(t);return Number.isFinite(n)?n:void 0}function we(e){let t=Ce(e.browser)??{};return{...O,defaultMode:z(process.env.AIKIT_BROWSER_DEFAULT_MODE)??z(t.defaultMode)??O.defaultMode,browsersPath:I(process.env.AIKIT_BROWSER_PATH)??I(process.env.AIKIT_BROWSER_BROWSERS_PATH)??I(t.browsersPath)??O.browsersPath,userDataDirRoot:I(t.userDataDirRoot)??O.userDataDirRoot,idleShutdownMinutes:B(`AIKIT_BROWSER_IDLE_MINUTES`)??R(t.idleShutdownMinutes)??O.idleShutdownMinutes,allowInternalSchemes:L(t.allowInternalSchemes)??O.allowInternalSchemes,evalTimeoutMs:B(`AIKIT_BROWSER_EVAL_TIMEOUT_MS`)??R(t.evalTimeoutMs)??O.evalTimeoutMs,evalMaxResultBytes:R(t.evalMaxResultBytes)??O.evalMaxResultBytes,redactPasswordFieldsInScreenshots:L(t.redactPasswordFieldsInScreenshots)??O.redactPasswordFieldsInScreenshots}}function V(e,t){return{content:[{type:`text`,text:e}],structuredContent:t}}function H(e,t){let n=e.selector??e.ref??(e.element?`text=${e.element}`:void 0);if(!n)throw Error(`${t} requires selector, ref, or element`);return n}async function Te(e,t,n){let r=null;try{return await Promise.race([e,new Promise((e,i)=>{r=setTimeout(()=>{i(Error(`${n} timed out after ${t}ms`))},t)})])}finally{r&&clearTimeout(r)}}l.string().describe(`Tracked browser page identifier`),l.enum([`click`,`type`,`press`,`hover`,`drag`,`select`,`scroll`,`upload`]).describe(`Interaction kind: click, type, press, hover, drag, select, scroll, upload`),l.string().optional().describe(`Target ref alias`),l.string().optional().describe(`Playwright selector`),l.string().optional().describe(`Human-readable element label`),l.string().optional().describe(`Text to type`),l.string().optional().describe(`Key to press`),l.string().optional().describe(`Option value, drag target, scroll spec, or file path(s)`),l.string().optional().describe(`Drag source ref`),l.string().optional().describe(`Drag source selector`),l.string().optional().describe(`Drag target ref`),l.string().optional().describe(`Drag target selector`);function Ee(e){return async({pageId:t,kind:n,ref:r,selector:i,element:a,text:o,key:s,value:c,fromRef:l,fromSelector:u,toRef:d,toSelector:f})=>{let p=j(e),m=p.session.getPage(t);switch(n){case`click`:{let e=H({ref:r,selector:i,element:a},`browser_act(click)`);await m.click(e);break}case`type`:{let e=H({ref:r,selector:i,element:a},`browser_act(type)`);await m.fill(e,o??``);break}case`press`:{let e=H({ref:r,selector:i,element:a},`browser_act(press)`);if(!s)throw Error(`browser_act(press) requires key`);await m.press(e,s);break}case`hover`:{let e=H({ref:r,selector:i,element:a},`browser_act(hover)`);await m.hover(e);break}case`drag`:{let e=H({ref:l??r,selector:u??i,element:a},`browser_act(drag) source`),t=H({ref:d,selector:f??c,element:a},`browser_act(drag) target`);await m.dragAndDrop(e,t);break}case`select`:{let e=H({ref:r,selector:i,element:a},`browser_act(select)`);if(c===void 0)throw Error(`browser_act(select) requires value`);await m.selectOption(e,c);break}case`scroll`:{if(i||r||a){let e=H({ref:r,selector:i,element:a},`browser_act(scroll)`);await m.locator(e).scrollIntoViewIfNeeded();break}let e=c??`down 500`;await m.evaluate(e=>{if(e===`bottom`){window.scrollTo(0,document.body.scrollHeight);return}if(e===`top`){window.scrollTo(0,0);return}let t=e.split(` `),n=t[0]||`down`,r=Number.parseInt(t[1]||`500`,10),i=n===`left`?-r:n===`right`?r:0,a=n===`up`?-r:n===`down`?r:0;window.scrollBy(i,a)},e);break}case`upload`:{let e=H({ref:r,selector:i,element:a},`browser_act(upload)`);if(!c)throw Error(`value (file path or JSON array of paths) required for upload`);let t;try{let e=JSON.parse(c);t=Array.isArray(e)?e:[c]}catch{t=[c]}await m.locator(e).setInputFiles(t);break}}return p.resetIdleTimer(),V(`ok`,{ok:!0})}}function De(e,t){return t?e.filter(e=>e.level===t):e}function Oe(e){return e.map(e=>{let t=e.location?` (${e.location.url}:${e.location.line})`:``;return`[${e.level.toUpperCase()}] ${e.text}${t}`}).join(`
|
|
2
|
-
`)}async function
|
|
3
|
-
`)
|
|
4
|
-
`)
|
|
1
|
+
import{createRequire as e}from"node:module";import{createHash as t,randomUUID as n}from"node:crypto";import{homedir as r}from"node:os";import{join as i}from"node:path";import{execFileSync as a}from"node:child_process";import{existsSync as o,readdirSync as s}from"node:fs";import{Buffer as c}from"node:buffer";import{z as l}from"zod";var u=class{#e;#t;#n=0;#r=0;constructor(e=200){if(!Number.isInteger(e)||e<1)throw RangeError(`CircularBuffer capacity must be a positive integer.`);this.#e=e,this.#t=Array(e)}push(e){this.#t[this.#n]=e,this.#n=(this.#n+1)%this.#e,this.#r<this.#e&&(this.#r+=1)}toArray(){if(this.#r===0)return[];let e=(this.#n-this.#r+this.#e)%this.#e,t=[];for(let n=0;n<this.#r;n+=1)t.push(this.#t[(e+n)%this.#e]);return t}clear(){this.#t=Array(this.#e),this.#n=0,this.#r=0}get size(){return this.#r}get capacity(){return this.#e}isEmpty(){return this.#r===0}};const d=[`xhr`,`fetch`,`websocket`,`document`],f=[/^authorization$/i,/^cookie$/i,/^set-cookie$/i,/^x-api-key$/i,/^x-access-token$/i,/^x-auth-token$/i,/^x-session$/i,/^x-secret$/i,/^x-password$/i,/^proxy-authorization$/i,/^www-authenticate$/i,/^x-csrf-token$/i,/^x-xsrf-token$/i];function p(e,t){if(t?.showSensitive)return{...e};let n=[...f,...t?.additionalPatterns??[]],r={};for(let[t,i]of Object.entries(e))r[t]=n.some(e=>e.test(t))?`[REDACTED]`:i;return r}function m(e,t=512){if(e)return e.length<=t?e:`${e.slice(0,t)}...[truncated]`}function ee(){return{networkBuffer:new u(200),consoleBuffer:new u(1e3),networkEnabled:!1,consoleEnabled:!1,networkFilter:{},nextRequestSequence:0,pendingRequests:new Map}}function te(e,t){if(e.capacity===t)return e;let n=new u(t),r=e.toArray(),i=Math.max(0,r.length-t);for(let e of r.slice(i))n.push(e);return n}function ne(e){switch(e){case`error`:case`info`:case`log`:case`debug`:return e;case`warning`:return`warn`;default:return`log`}}function re(e){if(e)return Buffer.byteLength(e)<=5242880?m(e):void 0}function ie(e){if(!e)return{};let t=Buffer.byteLength(e);return{bodySize:t,bodyPreview:t<=5242880?m(e):void 0}}function ae(e,t){return!t.resourceTypes.has(e.resourceType)||t.urlPattern&&!t.urlPattern.test(e.url)?!1:!t.excludeUrls.some(t=>t.test(e.url))}function h(e){if(e.length>200)throw Error(`Network filter regex patterns must be 200 characters or fewer`);try{let t=new RegExp(e);return t.test(`a`.repeat(100)),t}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`Invalid network filter regex pattern: ${t}`)}}function g(e={}){return{resourceTypes:new Set(e.resourceTypes??d),urlPattern:e.urlPattern?h(e.urlPattern):void 0,excludeUrls:(e.excludeUrls??[]).map(e=>h(e))}}function oe(e){return e.nextRequestSequence+=1,`req-${e.nextRequestSequence}`}function se(e,t,n){let r={request:t,previous:e.pendingRequestTail};e.pendingRequestTail?e.pendingRequestTail.next=r:e.pendingRequestHead=r,e.pendingRequestTail=r,e.pendingRequests.set(t,{entry:n,node:r})}function _(e,t){t.previous?t.previous.next=t.next:e.pendingRequestHead=t.next,t.next?t.next.previous=t.previous:e.pendingRequestTail=t.previous,delete t.previous,delete t.next}function ce(e){for(;e.pendingRequests.size>e.networkBuffer.capacity;){let t=e.pendingRequestHead;if(!t)return;_(e,t),e.pendingRequests.delete(t.request)}}function v(e){e.pendingRequests.clear(),e.pendingRequestHead=void 0,e.pendingRequestTail=void 0}var le=class{states=new Map;getOrCreate(e){let t=this.states.get(e);if(t)return t;let n=ee();return this.states.set(e,n),n}get(e){return this.states.get(e)}remove(e){let t=this.states.get(e);t&&(t.networkEnabled=!1,t.consoleEnabled=!1,this.detachNetworkListeners(t),this.detachConsoleListeners(t),v(t),this.states.delete(e))}clear(){for(let e of this.states.values())e.networkEnabled=!1,e.consoleEnabled=!1,this.detachNetworkListeners(e),this.detachConsoleListeners(e),v(e);this.states.clear()}enableNetwork(e,t,n,r){let i=this.getOrCreate(e);i.networkEnabled&&this.disableNetwork(e,t),i.page=t,i.networkEnabled=!0,i.networkFilter=n?{...n}:{},i.compiledNetworkFilter=g(i.networkFilter),r?.bufferSize&&(i.networkBuffer=te(i.networkBuffer,r.bufferSize));let a=e=>{let t=i.compiledNetworkFilter??g(i.networkFilter),n={resourceType:e.resourceType(),url:e.url()};if(!ae(n,t))return;let a={...e.headers()},o=Date.now(),s={id:oe(i),url:n.url,method:e.method(),resourceType:n.resourceType,headers:r?.showSensitive?a:p(a),postData:r?.includeBody?re(e.postData()??void 0):void 0,timestamp:o};i.networkBuffer.push(s),se(i,e,s),ce(i)},o=async e=>{let t=e.request(),n=i.pendingRequests.get(t);if(!n)return;i.pendingRequests.delete(t),_(i,n.node);let a;if(r?.includeBody)try{a=ie(await e.text())}catch{a=void 0}let o={...e.headers()};n.entry.response={status:e.status(),statusText:e.statusText(),headers:r?.showSensitive?o:p(o),bodySize:a?.bodySize,bodyPreview:a?.bodyPreview,timing:Date.now()-n.entry.timestamp}};i.listenerRefs={...i.listenerRefs,requestHandler:a,responseHandler:o},this.ensurePageCloseHandler(e,i,t),t.on(`request`,a),t.on(`response`,o)}disableNetwork(e,t){let n=this.states.get(e);n&&(n.page=n.page??t,n.networkEnabled=!1,this.detachNetworkListeners(n),v(n))}enableConsole(e,t,n){let r=this.getOrCreate(e);r.consoleEnabled&&this.disableConsole(e,t),r.page=t,r.consoleEnabled=!0,n?.bufferSize&&(r.consoleBuffer=te(r.consoleBuffer,n.bufferSize));let i=e=>{let t=e.location();r.consoleBuffer.push({level:ne(e.type()),text:e.text(),timestamp:Date.now(),location:t.url?{url:t.url,line:t.lineNumber,column:t.columnNumber}:void 0,args:e.args().map(e=>e.toString())})};r.listenerRefs={...r.listenerRefs,consoleHandler:i},this.ensurePageCloseHandler(e,r,t),t.on(`console`,i)}disableConsole(e,t){let n=this.states.get(e);n&&(n.page=n.page??t,n.consoleEnabled=!1,this.detachConsoleListeners(n))}detachNetworkListeners(e){let t=e.page,n=e.listenerRefs?.requestHandler,r=e.listenerRefs?.responseHandler;t&&n&&t.off(`request`,n),t&&r&&t.off(`response`,r),e.listenerRefs&&(delete e.listenerRefs.requestHandler,delete e.listenerRefs.responseHandler),this.detachPageCloseHandlerIfUnused(e)}detachConsoleListeners(e){let t=e.page,n=e.listenerRefs?.consoleHandler;t&&n&&t.off(`console`,n),e.listenerRefs&&delete e.listenerRefs.consoleHandler,this.detachPageCloseHandlerIfUnused(e)}ensurePageCloseHandler(e,t,n){if(t.listenerRefs?.pageCloseHandler)return;let r=()=>{this.remove(e)};t.listenerRefs={...t.listenerRefs,pageCloseHandler:r},n.on(`close`,r)}detachPageCloseHandlerIfUnused(e){if(e.networkEnabled||e.consoleEnabled)return;let t=e.page,n=e.listenerRefs?.pageCloseHandler;t&&n&&t.off(`close`,n),e.listenerRefs&&delete e.listenerRefs.pageCloseHandler,e.listenerRefs&&!e.listenerRefs.requestHandler&&!e.listenerRefs.responseHandler&&!e.listenerRefs.consoleHandler&&!e.listenerRefs.pageCloseHandler&&delete e.listenerRefs}};let ue=null;function y(){return ue||=new le,ue}const de=e(import.meta.url);function fe(e){return typeof e==`string`?e.trim():e instanceof Buffer?e.toString(`utf8`).trim():``}function pe(e){process.env.PLAYWRIGHT_BROWSERS_PATH=e}async function me(e){pe(e);let{chromium:t}=await import(`playwright-core`),n=t.executablePath();if(!n)throw Error(`Chromium executable not found in ${e}`);return n}function he(){return i(r(),`.aikit`,`browsers`)}function b(e){return e.browsersPath??process.env.PLAYWRIGHT_BROWSERS_PATH??he()}function x(e){return o(e)?s(e,{withFileTypes:!0}).some(e=>e.isDirectory()&&e.name.toLowerCase().startsWith(`chromium-`)):!1}async function S(e,t){let n=b(e);if(pe(n),t?.(`Using Chromium cache at ${n}`),x(n))return t?.(`Chromium already installed`),me(n);let r=i(de.resolve(`playwright-core`),`..`,`cli.js`);t?.(`Installing Chromium via playwright-core`);try{a(process.execPath,[r,`install`,`chromium`],{env:{...process.env,PLAYWRIGHT_BROWSERS_PATH:n},encoding:`utf8`,stdio:`pipe`})}catch(e){let t=e,n=fe(t.stderr),r=fe(t.stdout),i=n||r||t.message||`Unknown playwright install failure`;throw Error(`Failed to install Chromium: ${i}`)}return t?.(`Chromium install complete`),me(n)}function C(){return process.platform===`win32`||process.platform===`darwin`?!0:!!(process.env.DISPLAY||process.env.WAYLAND_DISPLAY)}function w(e){return e===`headless`||!C()?`headless`:e}function T(e){switch(e){case`headless`:return{headless:!0,args:[]};default:return{headless:!1,args:[]}}}var E=class{pages=new Map;registerPage(e,t,r,i){let a=n();return this.pages.set(a,{page:e,url:t,title:r,label:i,createdAt:new Date}),a}getPageByLabel(e){for(let t of this.pages.values())if(t.label===e)return t.page;throw Error(`Page not found: ${e}`)}resolvePageId(e){if(this.pages.has(e))return e;for(let[t,n]of this.pages.entries())if(n.label===e)return t;throw Error(`Page not found: ${e}`)}getPage(e){let t=this.pages.get(e);if(!t)throw Error(`Page not found: ${e}`);return t.page}getPageInfo(e){let t=this.pages.get(e);if(!t)throw Error(`Page not found: ${e}`);return{pageId:e,url:t.url,title:t.title,label:t.label,createdAt:t.createdAt}}setSnapshot(e,t){let n=this.pages.get(e);if(!n)throw Error(`Page not found: ${e}`);this.pages.set(e,{...n,lastSnapshot:t})}getSnapshot(e){let t=this.pages.get(e);if(!t)throw Error(`Page not found: ${e}`);return t.lastSnapshot}updatePageInfo(e,t,n){let r=this.pages.get(e);if(!r)throw Error(`Page not found: ${e}`);this.pages.set(e,{...r,url:t,title:n})}async removePage(e){let t=this.pages.get(e);t&&(await t.page.close(),this.pages.delete(e))}listPages(){return[...this.pages.entries()].map(([e,t])=>({pageId:e,url:t.url,title:t.title,label:t.label,createdAt:t.createdAt}))}async closeAll(){await Promise.allSettled([...this.pages.keys()].map(async e=>this.removePage(e)))}get size(){return this.pages.size}};const D={defaultMode:`ui`,browsersPath:null,userDataDirRoot:null,idleShutdownMinutes:10,allowInternalSchemes:!1,evalTimeoutMs:1e4,evalMaxResultBytes:262144,redactPasswordFieldsInScreenshots:!0};var O=class{browser=null;context=null;idleTimer=null;launchPromise=null;currentMode=null;session=new E;config;constructor(e={}){this.config={...D,...e}}async launch(e,t){let n=w(e??this.config.defaultMode);if(this.context&&this.currentMode!==n&&await this.close(),!this.context){if(this.launchPromise)return this.launchPromise;this.launchPromise=this.doLaunch(n,t);try{await this.launchPromise}finally{this.launchPromise=null}}}async doLaunch(e,n){if(this.browser&&this.context)return;let a=b(this.config);process.env.PLAYWRIGHT_BROWSERS_PATH=a;let{chromium:o}=await import(`playwright-core`),s=await S(this.config,n),c=T(e),l=t(`sha256`).update(process.cwd()).digest(`hex`).slice(0,12),u=i(this.config.userDataDirRoot??i(r(),`.aikit`,`profiles`),l);if(n?.(`Launching Chromium in ${e} mode`),this.context=await o.launchPersistentContext(u,{headless:c.headless,args:c.args,executablePath:s}),this.browser=this.context.browser(),!this.browser)throw await this.context.close(),this.context=null,Error(`Failed to acquire Chromium browser instance`);this.currentMode=e,this.browser.on(`disconnected`,()=>{this.browser=null,this.context=null,this.currentMode=null,y().clear(),this.session.closeAll().catch(()=>{}),this.stopIdleTimer()}),this.resetIdleTimer()}stopIdleTimer(){this.idleTimer&&=(clearTimeout(this.idleTimer),null)}resetIdleTimer(){this.stopIdleTimer();let e=setTimeout(()=>{this.close()},this.config.idleShutdownMinutes*6e4);e.unref?.(),this.idleTimer=e}async close(){this.stopIdleTimer(),this.launchPromise=null;let e=this.context,t=this.browser;this.context=null,this.browser=null,this.currentMode=null;let n;try{y().clear()}catch(e){n=e}try{await this.session.closeAll()}catch(e){n??=e}try{e&&await e.close()}catch(e){n??=e}finally{try{t&&await t.close()}catch(e){n??=e}}if(n)throw n}getContext(){if(!this.context)throw Error(`Browser not launched. Call launch() first.`);return this.context}getConfig(){return this.config}isLaunched(){return this.browser!==null}};let k=null;function A(e){return k||=new O(e),k}async function ge(){k&&=(await k.close(),null)}const _e=[`file:`,`chrome:`,`chrome-extension:`,`data:`,`javascript:`],ve=[`169.254.169.254`,`metadata.google.internal`,`metadata.google.com`],j=[`localhost`,`127.0.0.1`,`::1`,`[::1]`];function ye(e){return e.replace(/^\[(.*)\]$/,`$1`).toLowerCase()}function be(e){let t=new WeakSet,n=JSON.stringify(e,(e,n)=>{if(typeof n==`bigint`)return n.toString();if(typeof n==`function`)return`[Function ${n.name||`anonymous`}]`;if(typeof n==`symbol`)return n.toString();if(n instanceof Error)return{name:n.name,message:n.message,stack:n.stack};if(typeof n==`object`&&n){if(t.has(n))return`[Circular]`;t.add(n)}return n});return n===void 0?e===void 0?`undefined`:String(e):n}function xe(e,t){let n=c.from(e,`utf8`);return n.byteLength<=t?e:n.subarray(0,t).toString(`utf8`)}function M(e,t){let n;try{n=new URL(e)}catch{return{allowed:!1,reason:`Invalid URL: ${e}`}}let r=n.protocol.toLowerCase();if(_e.includes(r)&&!t.allowInternalSchemes)return{allowed:!1,reason:`Blocked URL scheme: ${r}`};let i=ye(n.hostname);return ve.includes(i)?{allowed:!1,reason:`Blocked host: ${n.hostname}`}:(j.includes(i)||j.includes(n.hostname),{allowed:!0})}function N(e){return e?{allowed:!0}:{allowed:!1,reason:`Cookie access requires explicit confirmation (confirm: true)`}}function P(e,t){if(t<=0)return{valid:!1,reason:`maxBytes must be greater than 0`};try{let n=be(e);return c.byteLength(n,`utf8`)<=t?{valid:!0,result:n,truncated:!1}:{valid:!0,result:`${xe(n,Math.max(t-3,0))}...`,truncated:!0,reason:`Result exceeded ${t} bytes and was truncated`}}catch(e){return{valid:!1,reason:`Unable to serialize eval result: ${e instanceof Error?e.message:String(e)}`}}}function Se(e){return e.replace(/<input\b[^>]*>/gi,e=>/\btype\s*=\s*(["'])password\1/i.test(e)?/\bvalue\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/i.test(e)?e.replace(/\bvalue\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/i,`value="***"`):e.replace(/\s*\/?>$/,e=>` value="***"${e}`):e)}const Ce=[`ui`,`headless`];function we(e){return typeof e==`object`&&e?e:null}function F(e){return typeof e==`string`&&e.length>0?e:void 0}function I(e){return typeof e==`boolean`?e:void 0}function L(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function R(e){return typeof e==`string`&&Ce.includes(e)?e:void 0}function z(e){let t=process.env[e];if(!t)return;let n=Number(t);return Number.isFinite(n)?n:void 0}function Te(e){let t=we(e.browser)??{};return{...D,defaultMode:R(process.env.AIKIT_BROWSER_DEFAULT_MODE)??R(t.defaultMode)??D.defaultMode,browsersPath:F(process.env.AIKIT_BROWSER_PATH)??F(process.env.AIKIT_BROWSER_BROWSERS_PATH)??F(t.browsersPath)??D.browsersPath,userDataDirRoot:F(t.userDataDirRoot)??D.userDataDirRoot,idleShutdownMinutes:z(`AIKIT_BROWSER_IDLE_MINUTES`)??L(t.idleShutdownMinutes)??D.idleShutdownMinutes,allowInternalSchemes:I(t.allowInternalSchemes)??D.allowInternalSchemes,evalTimeoutMs:z(`AIKIT_BROWSER_EVAL_TIMEOUT_MS`)??L(t.evalTimeoutMs)??D.evalTimeoutMs,evalMaxResultBytes:L(t.evalMaxResultBytes)??D.evalMaxResultBytes,redactPasswordFieldsInScreenshots:I(t.redactPasswordFieldsInScreenshots)??D.redactPasswordFieldsInScreenshots}}function B(e,t){return{content:[{type:`text`,text:e}],structuredContent:t}}function V(e,t){let n=e.selector??e.ref??(e.element?`text=${e.element}`:void 0);if(!n)throw Error(`${t} requires selector, ref, or element`);return n}async function Ee(e,t,n){let r=null;try{return await Promise.race([e,new Promise((e,i)=>{r=setTimeout(()=>{i(Error(`${n} timed out after ${t}ms`))},t)})])}finally{r&&clearTimeout(r)}}l.string().describe(`Tracked browser page identifier`),l.enum([`click`,`type`,`press`,`hover`,`drag`,`select`,`scroll`,`upload`]).describe(`Interaction kind: click, type, press, hover, drag, select, scroll, upload`),l.string().optional().describe(`Target ref alias`),l.string().optional().describe(`Playwright selector`),l.string().optional().describe(`Human-readable element label`),l.string().optional().describe(`Text to type`),l.string().optional().describe(`Key to press`),l.string().optional().describe(`Option value, drag target, scroll spec, or file path(s)`),l.string().optional().describe(`Drag source ref`),l.string().optional().describe(`Drag source selector`),l.string().optional().describe(`Drag target ref`),l.string().optional().describe(`Drag target selector`);function De(e){return async({pageId:t,kind:n,ref:r,selector:i,element:a,text:o,key:s,value:c,fromRef:l,fromSelector:u,toRef:d,toSelector:f})=>{let p=A(e),m=p.session.getPage(t);switch(n){case`click`:{let e=V({ref:r,selector:i,element:a},`browser_act(click)`);await m.click(e);break}case`type`:{let e=V({ref:r,selector:i,element:a},`browser_act(type)`);await m.fill(e,o??``);break}case`press`:{let e=V({ref:r,selector:i,element:a},`browser_act(press)`);if(!s)throw Error(`browser_act(press) requires key`);await m.press(e,s);break}case`hover`:{let e=V({ref:r,selector:i,element:a},`browser_act(hover)`);await m.hover(e);break}case`drag`:{let e=V({ref:l??r,selector:u??i,element:a},`browser_act(drag) source`),t=V({ref:d,selector:f??c,element:a},`browser_act(drag) target`);await m.dragAndDrop(e,t);break}case`select`:{let e=V({ref:r,selector:i,element:a},`browser_act(select)`);if(c===void 0)throw Error(`browser_act(select) requires value`);await m.selectOption(e,c);break}case`scroll`:{if(i||r||a){let e=V({ref:r,selector:i,element:a},`browser_act(scroll)`);await m.locator(e).scrollIntoViewIfNeeded();break}let e=c??`down 500`;await m.evaluate(e=>{if(e===`bottom`){window.scrollTo(0,document.body.scrollHeight);return}if(e===`top`){window.scrollTo(0,0);return}let t=e.split(` `),n=t[0]||`down`,r=Number.parseInt(t[1]||`500`,10),i=n===`left`?-r:n===`right`?r:0,a=n===`up`?-r:n===`down`?r:0;window.scrollBy(i,a)},e);break}case`upload`:{let e=V({ref:r,selector:i,element:a},`browser_act(upload)`);if(!c)throw Error(`value (file path or JSON array of paths) required for upload`);let t;try{let e=JSON.parse(c);t=Array.isArray(e)?e:[c]}catch{t=[c]}await m.locator(e).setInputFiles(t);break}}return p.resetIdleTimer(),B(`ok`,{ok:!0})}}function Oe(e,t){return t?e.filter(e=>e.level===t):e}function ke(e){return e.map(e=>{let t=e.location?` (${e.location.url}:${e.location.line})`:``;return`[${e.level.toUpperCase()}] ${e.text}${t}`}).join(`
|
|
2
|
+
`)}async function Ae(e,t){let n=y();switch(t.subAction){case`enable`:return n.enableConsole(t.pageId,e,{bufferSize:t.bufferSize}),B(`Console capture enabled for page ${t.pageId}`,{enabled:!0,bufferSize:t.bufferSize??1e3});case`get`:{let e=n.get(t.pageId);if(!e?.consoleEnabled)return B(`Console capture not enabled. Call with subAction: "enable" first.`,{enabled:!1,entries:[]});let r=Oe(e.consoleBuffer.toArray(),t.level);return B(ke(r)||`No console messages captured yet.`,{enabled:!0,count:r.length,entries:r})}case`clear`:{let e=n.get(t.pageId);return e&&e.consoleBuffer.clear(),B(`Console buffer cleared.`,{cleared:!0})}}}function je(e){return async t=>{let n=A(e),r=await Ae(n.session.getPage(t.pageId),t);return n.resetIdleTimer(),r}}l.string().describe(`Tracked browser page identifier`),l.boolean().describe(`Whether to accept the next dialog`),l.string().optional().describe(`Text to provide when accepting a prompt dialog`);function Me(e){return async({pageId:t,accept:n,promptText:r})=>{let i=A(e);return i.session.getPage(t).once(`dialog`,async e=>{n?await e.accept(r):await e.dismiss()}),i.resetIdleTimer(),B(`ok`,{ok:!0})}}function Ne(e){return async({pageId:t})=>{let n=A(e),r=await n.session.getPage(t).accessibility.snapshot()??{},i=JSON.stringify(r,null,2),a=n.session.getSnapshot(t);if(n.session.setSnapshot(t,i),n.resetIdleTimer(),!a)return B(`First snapshot captured (no previous to diff against).\n${i}`,{pageId:t,hasChanges:!1,isFirst:!0,snapshot:r});if(a===i)return B(`No changes detected.`,{pageId:t,hasChanges:!1});let o=a.split(`
|
|
3
|
+
`),s=i.split(`
|
|
4
|
+
`),c=new Set(o),l=new Set(s),u=s.filter(e=>!c.has(e)),d=o.filter(e=>!l.has(e)),f=u.length>0||d.length>0;return B([u.length>0?`Added:\n${u.join(`
|
|
5
|
+
`)}`:``,d.length>0?`Removed:\n${d.join(`
|
|
6
|
+
`)}`:``].filter(Boolean).join(`
|
|
7
|
+
|
|
8
|
+
`)||`No meaningful changes.`,{pageId:t,hasChanges:f,added:u,removed:d})}}l.string().describe(`Tracked browser page identifier`),l.string().describe(`JavaScript expression or IIFE evaluated in page context. Code is wrapped in Function("return (<code>)"). For multi-statement code, use an IIFE: (() => { stmt1; return result; })(). Do NOT use bare return or semicolons at the top level.`),l.number().min(1).max(6e4).optional().describe(`Optional evaluation timeout`);function Pe(e){return async({pageId:t,code:n,timeoutMs:r})=>{let i=A(e),a=i.session.getPage(t),o=Math.min(r??e.evalTimeoutMs,6e4),s=P(await Ee(a.evaluate(e=>{let t=Function(`return (${e});`)();return typeof t==`function`?t():t},n),o,`browser_eval`),e.evalMaxResultBytes);if(!s.valid||s.result===void 0)throw Error(s.reason??`browser_eval result validation failed`);return i.resetIdleTimer(),B(s.result,{pageId:t,result:s.result,truncated:s.truncated??!1,reason:s.reason})}}const Fe=new Set([`localhost`,`metadata.google.internal`]),Ie=[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`,`HEAD`,`OPTIONS`];function H(e){return e.replace(/^\[(.*)\]$/,`$1`).toLowerCase()}function Le(e){if(!/^(?:\d{1,3}\.){3}\d{1,3}$/.test(e))return;let t=e.split(`.`).map(e=>Number(e));if(!t.some(e=>!Number.isInteger(e)||e<0||e>255))return t}function Re(e){let t=H(e).split(`::`);if(t.length>2)return;let n=e=>{if(e.length===0)return e;let t=e[e.length-1];if(!t?.includes(`.`))return e;let n=Le(t);if(n)return[...e.slice(0,-1),(n[0]<<8|n[1]).toString(16),(n[2]<<8|n[3]).toString(16)]},r=n(t[0]?t[0].split(`:`):[]),i=n(t[1]?t[1].split(`:`):[]);if(!r||!i)return;let a=t.length===2,o=r.length+i.length;if(!a&&o!==8||o>8)return;let s=a?Array(8-o).fill(`0`):[],c=[...r,...s,...i];if(c.length!==8)return;let l=0n;for(let e of c){if(!/^[0-9a-f]{1,4}$/i.test(e))return;l=(l<<16n)+BigInt(`0x${e}`)}return l}function ze(e){let[t,n,r,i]=e;return t===127||t===10||t===172&&n>=16&&n<=31||t===192&&n===168||t===169&&n===254||t===0&&n===0&&r===0&&i===0}function Be(e){return e===1n||(e&339950059921992234495148655666698125312n)==338288524927261089654018896841347694592n||(e&337623910929368631717566993311207522304n)==334965454937798799971759379190646833152n}function Ve(e){let t;try{t=new URL(e)}catch{return!1}let n=H(t.hostname);if(Fe.has(n))return!0;let r=Le(n);if(r)return ze(r);let i=Re(n);return i===void 0?!1:Be(i)}function U(e){let t;try{t=new URL(e)}catch{throw Error(`Invalid fetch URL: ${e}`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`Fetch URL must use http:// or https://`);if(Ve(e))throw Error(`Fetch URL must not target private or local hosts`)}function He(e,t=262144){return e.length<=t?{body:e,truncated:!1}:{body:`${e.slice(0,t)}\n\n[truncated after ${t} chars]`,truncated:!0}}function Ue(e){let t=[`HTTP ${e.status} ${e.statusText}`,`URL: ${e.url}`,`Redirected: ${e.redirected?`yes`:`no`}`,`JSON: ${e.isJson?`yes`:`no`}`],n=Object.entries(e.headers);if(n.length>0){t.push(``,`Headers:`);for(let[e,r]of n)t.push(`${e}: ${r}`)}return t.push(``,`Body:`,e.body||`<empty>`),t.join(`
|
|
9
|
+
`)}function We(e){let t=(e??`GET`).toUpperCase();if(!Ie.includes(t))throw Error(`Unsupported fetch method: ${t}`);return t}function Ge(e){if(e===void 0)return 3e4;if(!Number.isFinite(e)||e<=0)throw Error(`Fetch timeoutMs must be a positive number`);return e}function Ke(e){return Object.entries(e).find(([e])=>e.toLowerCase()===`content-type`)?.[1]}function qe(e,t){if(!t||e.length===0)return e;try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}async function Je(e,t){U(t.url);let n=We(t.method),r=Ge(t.timeoutMs),i=t.headers??{},a=n===`GET`||n===`HEAD`?void 0:t.body,o;try{o=await e.evaluate(async e=>{let t=new AbortController,n=setTimeout(()=>t.abort(),e.timeoutMs);try{let n=await fetch(e.url,{method:e.method,headers:e.headers,body:e.body,signal:t.signal,redirect:`follow`});return{status:n.status,statusText:n.statusText,headers:Object.fromEntries(n.headers.entries()),body:await n.text(),url:n.url,redirected:n.redirected}}catch(t){if(t instanceof Error&&t.name===`AbortError`)throw Error(`Fetch timed out after ${e.timeoutMs}ms`);let n=t instanceof Error?t.message:String(t);throw Error(`Fetch failed: ${n}`,{cause:t})}finally{clearTimeout(n)}},{url:t.url,method:n,headers:i,body:a,timeoutMs:r})}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(t,{cause:e})}U(o.url);let s=Ke(o.headers)?.toLowerCase().includes(`json`)??!1,c=He(qe(o.body,s)),l=t.includeHeaders===!1?{}:o.headers,u={status:o.status,statusText:o.statusText,headers:l,body:c.body,isJson:s,url:o.url,redirected:o.redirected};return B(Ue(u),{...u,truncated:c.truncated})}function Ye(e){return async t=>{let n=A(e),r=await Je(n.session.getPage(t.pageId),t);return n.resetIdleTimer(),r}}l.string().describe(`Tracked browser page identifier`),l.string().url().optional().describe(`Optional URL to navigate to`),l.enum([`back`,`forward`,`reload`,`waitFor`]).optional().describe(`Navigation helper action`),l.string().optional().describe(`Selector to wait for when type="waitFor"`),l.number().min(1).max(6e4).optional().describe(`Optional wait timeout`);function Xe(e){return async({pageId:t,url:n,type:r,selector:i,timeoutMs:a})=>{let o=A(e),s=o.session.getPage(t);if(n){let r=M(n,e);if(!r.allowed)return B(`Navigation blocked: ${r.reason}`,{blocked:!0,pageId:t,reason:r.reason});await s.goto(n)}else if(!r)return B(`Navigation requires url or type`,{error:`Navigation requires url or type`,pageId:t});else if(r===`back`)await s.goBack();else if(r===`forward`)await s.goForward();else if(r===`reload`)await s.reload();else if(r===`waitFor`){if(!i)throw Error(`browser_navigate(waitFor) requires selector`);await s.waitForSelector(i,a?{timeout:a}:void 0)}let c=s.url(),l=await s.title();return o.session.updatePageInfo(t,c,l),o.resetIdleTimer(),B(`${l||c}\n${c}`,{pageId:t,url:c,title:l})}}function W(e){return Object.entries(e).map(([e,t])=>({name:e,value:t}))}function Ze(e){try{return Array.from(new URL(e).searchParams.entries()).map(([e,t])=>({name:e,value:t}))}catch{return[]}}function Qe(e,t){let n=t.toLowerCase();for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}function $e(e){let t=Qe(e,`content-type`);return t&&t.split(`;`,1)[0]?.trim()||`application/octet-stream`}function et(e){return e===void 0?0:Buffer.byteLength(e,`utf8`)}function tt(e,t=!1){return t?{...e}:p(e)}function nt(e,t){return{...e,headers:tt(e.headers,t.showSensitive),postData:t.includeBody?e.postData:void 0,response:e.response?{...e.response,headers:tt(e.response.headers,t.showSensitive),bodyPreview:t.includeBody?e.response.bodyPreview:void 0}:void 0}}function rt(e){return B(`Network capture not enabled. Call with subAction: "enable" first.`,{pageId:e,enabled:!1,count:0,entries:[]})}async function it(e,t){let n=y();switch(t.subAction){case`enable`:return n.enableNetwork(t.pageId,e,t.filter,{bufferSize:t.bufferSize,showSensitive:t.showSensitive,includeBody:t.includeBody}),B(`Network capture enabled for page ${t.pageId}`,{pageId:t.pageId,enabled:!0,filter:t.filter??{resourceTypes:[...d]}});case`get`:{let e=n.get(t.pageId);if(!e?.networkEnabled)return rt(t.pageId);let r=e.networkBuffer.toArray().map(e=>nt(e,t));return B(r.map(e=>`${e.method} ${e.url} -> ${e.response?.status??`pending`} (${e.response?.timing?`${e.response.timing}ms`:`no response`})`).join(`
|
|
10
|
+
`)||`No requests captured yet.`,{pageId:t.pageId,enabled:!0,count:r.length,entries:r})}case`clear`:{let e=n.get(t.pageId);return e?.networkEnabled?(e.networkBuffer.clear(),e.pendingRequests.clear(),e.pendingRequestHead=void 0,e.pendingRequestTail=void 0,B(`Network capture buffer cleared.`,{pageId:t.pageId,cleared:!0})):B(`Network capture not enabled. Call with subAction: "enable" first.`,{pageId:t.pageId,enabled:!1,cleared:!1})}case`export-har`:{let e=n.get(t.pageId);if(!e?.networkEnabled)return rt(t.pageId);let r=e.networkBuffer.toArray().map(e=>{let n=nt(e,t);return{startedDateTime:new Date(n.timestamp).toISOString(),time:n.response?.timing??-1,request:{method:n.method,url:n.url,httpVersion:`HTTP/1.1`,cookies:[],headers:W(n.headers),queryString:Ze(n.url),headersSize:-1,bodySize:et(e.postData),postData:n.postData?{text:n.postData}:void 0},response:n.response?{status:n.response.status,statusText:n.response.statusText,httpVersion:`HTTP/1.1`,cookies:[],headers:W(n.response.headers),content:{size:n.response.bodySize??0,mimeType:$e(n.response.headers),text:n.response.bodyPreview},redirectURL:``,headersSize:-1,bodySize:n.response.bodySize??-1}:{status:0,statusText:`pending`,httpVersion:`HTTP/1.1`,cookies:[],headers:[],content:{size:0,mimeType:`application/octet-stream`},redirectURL:``,headersSize:-1,bodySize:-1},cache:{},timings:{send:-1,wait:-1,receive:-1}}});return B(`Exported ${r.length} entries in HAR 1.2 format.`,{pageId:t.pageId,har:{log:{version:`1.2`,creator:{name:`aikit-browser`,version:`1.0.0`},entries:r}}})}default:{let e=`Unknown network subAction: ${String(t.subAction)}`;return B(e,{pageId:t.pageId,error:e})}}}function at(e){return async t=>{let n=A(e),r=await it(n.session.getPage(t.pageId),t);return n.resetIdleTimer(),r}}l.string().url().describe(`Absolute URL to open`),l.enum([`ui`,`headless`]).optional().describe(`Browser launch mode`),l.boolean().optional().describe(`Reserved for future tab reuse control`),l.string().optional().describe(`Human-readable label for the page`),l.boolean().optional().describe(`Auto-accept alert/beforeunload dialogs (default: true)`),l.enum([`load`,`domcontentloaded`,`networkidle`]).optional().describe(`Navigation readiness event`);function ot(e){return async({url:t,mode:n,label:r,autoDialog:i,waitUntil:a})=>{let o=M(t,e);if(!o.allowed)throw Error(o.reason??`Blocked URL: ${t}`);let s=A(e);s.isLaunched()||await s.launch(n??e.defaultMode);let c=await s.getContext().newPage();a?await c.goto(t,{waitUntil:a}):await c.goto(t);let l=await c.title(),u=s.session.registerPage(c,t,l,r);return i!==!1&&c.on(`dialog`,async e=>{let t=e.type();(t===`alert`||t===`beforeunload`)&&await e.accept()}),s.resetIdleTimer(),B(`Opened ${l||t}\npageId: ${u}`,{pageId:u,url:t,title:l,label:r})}}l.string().describe(`Tracked browser page identifier`),l.enum([`snapshot`,`dom`,`markdown`,`text`]).optional().describe(`Extraction mode: snapshot (ARIA tree), dom (HTML), markdown (clean MD), text (plain text)`),l.string().optional().describe(`CSS selector to scope extraction to a specific element`);function st(e){return async({pageId:t,mode:n,selector:r})=>{let i=A(e).session.getPage(t),a=r??`body`,o=n??`snapshot`;switch(o){case`dom`:{let e=r?await i.locator(r).innerHTML():await i.content();return B(e||`empty page`,{pageId:t,mode:o,selector:r,dom:e})}case`markdown`:{let e=await i.evaluate(e=>{let t=globalThis,n=e?t.document?.querySelector(e):t.document?.body;if(!n)return``;function r(e){if(e.nodeType===t.Node?.TEXT_NODE)return e.textContent?.replace(/\s+/g,` `)||``;if(e.nodeType!==t.Node?.ELEMENT_NODE)return``;let n=e,a=n.tagName.toLowerCase(),o=t.window?.getComputedStyle(n);if(o?.display===`none`||o?.visibility===`hidden`)return``;let s=Array.from(n.childNodes).map(r).filter(Boolean).join(``);switch(a){case`h1`:return`# ${s.trim()}\n\n`;case`h2`:return`## ${s.trim()}\n\n`;case`h3`:return`### ${s.trim()}\n\n`;case`h4`:return`#### ${s.trim()}\n\n`;case`h5`:return`##### ${s.trim()}\n\n`;case`h6`:return`###### ${s.trim()}\n\n`;case`p`:return`${s.trim()}\n\n`;case`br`:return`
|
|
5
11
|
`;case`hr`:return`
|
|
6
12
|
---
|
|
7
13
|
|
|
@@ -9,8 +15,9 @@ import{createRequire as e}from"node:module";import{createHash as t,randomUUID as
|
|
|
9
15
|
> `)}\n\n`;case`a`:return`[${s.trim()}](${n.getAttribute(`href`)||``})`;case`img`:return`||``})`;case`ul`:case`ol`:return`${s}\n`;case`li`:return`${n.parentElement?.tagName===`OL`?`${Array.from(n.parentElement.children).indexOf(n)+1}. `:`- `}${s.trim()}\n`;case`table`:return`${i(n)}\n\n`;case`script`:case`style`:case`noscript`:case`nav`:case`footer`:case`header`:return``;case`div`:case`section`:case`article`:case`main`:case`span`:return s;default:return s}}function i(e){let t=Array.from(e.querySelectorAll(`tr`));if(!t.length)return``;let n=[];return t.forEach((e,t)=>{let r=Array.from(e.querySelectorAll(`th, td`)).map(e=>e.textContent?.trim()||``);n.push(`| ${r.join(` | `)} |`),t===0&&n.push(`| ${r.map(()=>`---`).join(` | `)} |`)}),n.join(`
|
|
10
16
|
`)}return r(n).replace(/\n{3,}/g,`
|
|
11
17
|
|
|
12
|
-
`).trim()},r);return V(e||`empty page`,{pageId:t,mode:o,selector:r,markdown:e})}case`text`:{let e=await i.locator(a).innerText();return V(e||`empty page`,{pageId:t,mode:o,selector:r,text:e})}default:{let e=await i.locator(a).ariaSnapshot();return V(e||`empty page`,{pageId:t,mode:o,selector:r,snapshot:e})}}}}l.string().describe(`Tracked browser page identifier`),l.string().optional().describe(`Optional target ref alias`),l.string().optional().describe(`Optional target selector`),l.boolean().optional().describe(`Capture the full page when no selector is provided`),l.boolean().optional().describe(`Mask password fields before capture`),l.object({x:l.number(),y:l.number(),width:l.number(),height:l.number()}).optional().describe(`Capture a specific page region { x, y, width, height }`),l.enum([`png`,`jpeg`]).optional().describe(`Image format (default: png)`),l.number().min(0).max(100).optional().describe(`JPEG quality 0-100 (only for jpeg format)`);function ot(e){return async({pageId:t,ref:n,selector:r,fullPage:i,redactPasswords:a,clip:o,format:s,quality:c})=>{let l=j(e),u=l.session.getPage(t),d=a??e.redactPasswordFieldsInScreenshots,f=[];d&&(f=await u.evaluate(()=>{let e=globalThis.document;return Array.from(e.querySelectorAll(`input[type="password"]`)).map((e,t)=>{let n=e,r=`data-aikit-password-mask-${t}`;return n.setAttribute(r,n.value),n.value=`***`,r})}));try{let e={};s&&(e.type=s),s===`jpeg`&&c!==void 0&&(e.quality=c);let a=r??n?await u.locator(H({ref:n,selector:r},`browser_screenshot`)).screenshot(e):await u.screenshot({...e,...o?{clip:o}:{fullPage:i??!1}});return l.resetIdleTimer(),V(`Screenshot captured`,{pageId:t,base64:a.toString(`base64`)})}finally{d&&f.length>0&&await u.evaluate(e=>{let t=globalThis.document;for(let n of e){let e=t.querySelector(`input[${n}]`);e&&(e.value=e.getAttribute(n)??``,e.removeAttribute(n))}},f)}}}const st=l.enum([`Lax`,`None`,`Strict`]),ct=l.enum([`localStorage`,`sessionStorage`]);l.enum([`list`,`close`,`cookies`,`set-cookie`,`delete-cookie`,`clear-cookies`,`get-storage`,`set-storage`,`clear-storage`]).describe(`Session sub-action`),l.string().optional().describe(`Page ID (required for close, storage actions)`),l.boolean().optional().describe(`Explicit confirmation for cookie operations`),l.array(l.object({name:l.string(),value:l.string(),url:l.string().optional(),domain:l.string().optional(),path:l.string().optional(),expires:l.number().optional(),httpOnly:l.boolean().optional(),secure:l.boolean().optional(),sameSite:st.optional()})).optional().describe(`Cookies to set (for set-cookie action)`),l.string().optional().describe(`Cookie name (for delete-cookie action)`),ct.optional().describe(`Storage type for storage actions`),l.string().optional().describe(`Storage key to get/set`),l.string().optional().describe(`Storage value to set`);function lt(e){return async({action:t,pageId:n,confirm:r,cookies:i,name:a,storageType:o,storageKey:s,storageValue:c})=>{let l=j(e);if(t===`list`){let e=l.session.listPages();return V(JSON.stringify(e,null,2),{pages:e})}if(t===`close`){if(!n)throw Error(`browser_session(close) requires pageId`);return await l.session.removePage(n),l.resetIdleTimer(),V(`ok`,{ok:!0,pageId:n})}if(t===`set-cookie`){let e=P(!!r);if(!e.allowed)throw Error(e.reason??`Cookie access denied`);if(!i?.length)throw Error(`cookies array required for set-cookie`);return await l.getContext().addCookies(i),l.resetIdleTimer(),V(`Set ${i.length} cookie(s)`,{ok:!0,count:i.length})}if(t===`delete-cookie`){let e=P(!!r);if(!e.allowed)throw Error(e.reason??`Cookie access denied`);if(!a)throw Error(`name required for delete-cookie`);return await l.getContext().clearCookies({name:a}),l.resetIdleTimer(),V(`Deleted cookie: ${a}`,{ok:!0,name:a})}if(t===`clear-cookies`){let e=P(!!r);if(!e.allowed)throw Error(e.reason??`Cookie access denied`);return await l.getContext().clearCookies(),l.resetIdleTimer(),V(`All cookies cleared`,{ok:!0})}if(t===`get-storage`){if(!n)throw Error(`pageId required for get-storage`);if(!o)throw Error(`storageType required for get-storage`);let e=await l.session.getPage(n).evaluate(({type:e,key:t})=>{let n=e===`localStorage`?localStorage:sessionStorage;if(t)return n.getItem(t);let r={};for(let e=0;e<n.length;e+=1){let t=n.key(e);t&&(r[t]=n.getItem(t)||``)}return r},{type:o,key:s});return l.resetIdleTimer(),V(s?`${o}.${s} = ${String(e)}`:`${o}: ${JSON.stringify(e)}`,{storageType:o,key:s,data:e})}if(t===`set-storage`){if(!n)throw Error(`pageId required for set-storage`);if(!o)throw Error(`storageType required for set-storage`);if(!s)throw Error(`storageKey required for set-storage`);if(c===void 0)throw Error(`storageValue required for set-storage`);return await l.session.getPage(n).evaluate(({type:e,key:t,value:n})=>{(e===`localStorage`?localStorage:sessionStorage).setItem(t,n)},{type:o,key:s,value:c}),l.resetIdleTimer(),V(`Set ${o}.${s}`,{ok:!0,storageType:o,key:s})}if(t===`clear-storage`){if(!n)throw Error(`pageId required for clear-storage`);if(!o)throw Error(`storageType required for clear-storage`);return await l.session.getPage(n).evaluate(e=>{(e===`localStorage`?localStorage:sessionStorage).clear()},o),l.resetIdleTimer(),V(`Cleared ${o}`,{ok:!0,storageType:o})}let u=P(!!r);if(!u.allowed)throw Error(u.reason??`Cookie access denied`);let d=await l.getContext().cookies();return l.resetIdleTimer(),V(JSON.stringify(d,null,2),{cookies:d})}}const ut=[`open`,`read`,`act`,`navigate`,`network`,`console`,`fetch`,`eval`,`screenshot`,`dialog`,`session`],dt=[`ui`,`headless`],ft=[`load`,`domcontentloaded`,`networkidle`],pt=[`click`,`type`,`press`,`hover`,`drag`,`select`,`scroll`,`upload`],mt=[`back`,`forward`,`reload`,`waitFor`],ht=[`enable`,`get`,`clear`,`export-har`],gt=[`enable`,`get`,`clear`],_t=[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`,`HEAD`,`OPTIONS`],vt=[`list`,`close`,`cookies`,`set-cookie`,`delete-cookie`,`clear-cookies`,`get-storage`,`set-storage`,`clear-storage`],yt={action:l.enum(ut).describe(`Browser action to perform`),pageId:l.string().optional().describe(`Tracked browser page identifier`),url:l.string().url().optional().describe(`URL to open or navigate to`),mode:l.enum(dt).optional().describe(`Browser launch mode (open only)`),forceNew:l.boolean().optional().describe(`Reserved for future tab reuse`),waitUntil:l.enum(ft).optional().describe(`Navigation readiness event`),kind:l.enum(pt).optional().describe(`Interaction kind (act only)`),ref:l.string().optional().describe(`Target ref alias`),selector:l.string().optional().describe(`Playwright selector`),element:l.string().optional().describe(`Human-readable element label (resolved via Playwright text selector). Prefer selector for precision.`),text:l.string().optional().describe(`Text to type`),key:l.string().optional().describe(`Key to press`),value:l.string().optional().describe(`Option value or drag target`),fromRef:l.string().optional().describe(`Drag source ref`),fromSelector:l.string().optional().describe(`Drag source selector`),toRef:l.string().optional().describe(`Drag target ref`),toSelector:l.string().optional().describe(`Drag target selector`),type:l.enum(mt).optional().describe(`Navigation type`),subAction:l.enum(ht).optional().describe(`Network sub-action: enable, get, clear, or export-har`),code:l.string().optional().describe(`JavaScript expression or IIFE evaluated in page context. Wrapped in Function("return (<code>)"). Multi-statement: use (() => { ...; return result; })(). No bare return or top-level semicolons.`),timeoutMs:l.number().min(1).max(6e4).optional().describe(`Timeout in milliseconds`),filter:l.object({resourceTypes:l.array(l.string()).optional(),urlPattern:l.string().optional(),excludeUrls:l.array(l.string()).optional()}).optional().describe(`Network capture filter for resource types and URL patterns`),showSensitive:l.boolean().optional().describe(`Include sensitive headers instead of redacting them`),includeBody:l.boolean().optional().describe(`Include truncated request bodies in captured entries`),bufferSize:l.number().int().min(1).max(1e4).optional().describe(`Buffer capacity (1-10000, default varies by action)`),consoleSubAction:l.enum(gt).optional().describe(`Console sub-action: enable, get, or clear`),level:l.string().optional().describe(`Filter console entries by level (log/info/warn/error/debug)`),fetchUrl:l.string().optional().describe(`URL for fetch action (http/https only). Uses page cookies/session.`),fetchMethod:l.enum(_t).optional().describe(`HTTP method for fetch action (default: GET)`),fetchHeaders:l.record(l.string(),l.string()).optional().describe(`Custom headers for fetch action`),fetchBody:l.string().optional().describe(`Request body for fetch action (POST/PUT/PATCH)`),includeResponseHeaders:l.boolean().optional().describe(`Include response headers in fetch output (default: true)`),fullPage:l.boolean().optional().describe(`Capture full page`),redactPasswords:l.boolean().optional().describe(`Mask password fields`),readMode:l.enum([`snapshot`,`dom`,`markdown`,`text`]).optional().describe(`Extraction mode for read action: snapshot (ARIA tree), dom (HTML), markdown (clean MD), text (plain text)`),clip:l.object({x:l.number(),y:l.number(),width:l.number(),height:l.number()}).optional().describe(`Capture a specific page region { x, y, width, height }`),format:l.enum([`png`,`jpeg`]).optional().describe(`Screenshot image format (default: png)`),quality:l.number().min(0).max(100).optional().describe(`JPEG quality 0-100 (only for jpeg format)`),cookies:l.array(l.object({name:l.string(),value:l.string(),url:l.string().optional(),domain:l.string().optional(),path:l.string().optional(),expires:l.number().optional(),httpOnly:l.boolean().optional(),secure:l.boolean().optional(),sameSite:l.enum([`Lax`,`None`,`Strict`]).optional()})).optional().describe(`Cookies to set (for session set-cookie action)`),name:l.string().optional().describe(`Cookie name for delete-cookie action`),storageType:l.enum([`localStorage`,`sessionStorage`]).optional().describe(`Storage type for get/set/clear-storage actions`),storageKey:l.string().optional().describe(`Storage key to get or set`),storageValue:l.string().optional().describe(`Value to set in storage`),accept:l.boolean().optional().describe(`Accept or dismiss dialog`),promptText:l.string().optional().describe(`Text for prompt dialog`),sessionAction:l.enum(vt).optional().describe(`Session sub-action (session only)`),confirm:l.boolean().optional().describe(`Explicit confirmation for cookie export`)};function K(e,t){return typeof e==`string`&&t.includes(e)}function q(e,t,n){let r=e[t];if(typeof r!=`string`)throw Error(`${n} requires ${t}`);return r}function bt(e,t,n){let r=e[t];if(typeof r!=`boolean`)throw Error(`${n} requires ${t}`);return r}function J(e,t){let n=e[t];return typeof n==`string`?n:void 0}function Y(e,t){let n=e[t];return typeof n==`boolean`?n:void 0}function X(e,t){let n=e[t];return typeof n==`number`?n:void 0}function Z(e,t){let n=e[t];return typeof n==`object`&&n?n:void 0}function Q(e,t,n,r){let i=e[t];if(!K(i,n))throw Error(`${r} requires ${t}`);return i}function $(e,t,n,r){let i=e[t];if(i!==void 0){if(!K(i,n))throw Error(`${r} received invalid ${t}`);return i}}function xt(e,t){let n=we(t),r=it(n),i=at(n),a=Ee(n),o=qe(n),s=rt(n),c=Ae(n),l=Ke(n),u=Me(n),d=ot(n),f=je(n),p=lt(n);e.registerTool(`browser`,{title:`Browser Automation`,description:`Unified browser automation tool. Actions:
|
|
18
|
+
`).trim()},r);return B(e||`empty page`,{pageId:t,mode:o,selector:r,markdown:e})}case`text`:{let e=await i.locator(a).innerText();return B(e||`empty page`,{pageId:t,mode:o,selector:r,text:e})}default:{let e=await i.locator(a).ariaSnapshot();return B(e||`empty page`,{pageId:t,mode:o,selector:r,snapshot:e})}}}}l.string().describe(`Tracked browser page identifier`),l.string().optional().describe(`Optional target ref alias`),l.string().optional().describe(`Optional target selector`),l.boolean().optional().describe(`Capture the full page when no selector is provided`),l.boolean().optional().describe(`Mask password fields before capture`),l.object({x:l.number(),y:l.number(),width:l.number(),height:l.number()}).optional().describe(`Capture a specific page region { x, y, width, height }`),l.enum([`png`,`jpeg`]).optional().describe(`Image format (default: png)`),l.number().min(0).max(100).optional().describe(`JPEG quality 0-100 (only for jpeg format)`);function ct(e){return async({pageId:t,ref:n,selector:r,fullPage:i,redactPasswords:a,clip:o,format:s,quality:c})=>{let l=A(e),u=l.session.getPage(t),d=a??e.redactPasswordFieldsInScreenshots,f=[];d&&(f=await u.evaluate(()=>{let e=globalThis.document;return Array.from(e.querySelectorAll(`input[type="password"]`)).map((e,t)=>{let n=e,r=`data-aikit-password-mask-${t}`;return n.setAttribute(r,n.value),n.value=`***`,r})}));try{let e={};s&&(e.type=s),s===`jpeg`&&c!==void 0&&(e.quality=c);let a=r??n?await u.locator(V({ref:n,selector:r},`browser_screenshot`)).screenshot(e):await u.screenshot({...e,...o?{clip:o}:{fullPage:i??!1}});return l.resetIdleTimer(),B(`Screenshot captured`,{pageId:t,base64:a.toString(`base64`)})}finally{d&&f.length>0&&await u.evaluate(e=>{let t=globalThis.document;for(let n of e){let e=t.querySelector(`input[${n}]`);e&&(e.value=e.getAttribute(n)??``,e.removeAttribute(n))}},f)}}}const lt=l.enum([`Lax`,`None`,`Strict`]),ut=l.enum([`localStorage`,`sessionStorage`]);l.enum([`list`,`close`,`cookies`,`set-cookie`,`delete-cookie`,`clear-cookies`,`get-storage`,`set-storage`,`clear-storage`]).describe(`Session sub-action`),l.string().optional().describe(`Page ID (required for close, storage actions)`),l.boolean().optional().describe(`Explicit confirmation for cookie operations`),l.array(l.object({name:l.string(),value:l.string(),url:l.string().optional(),domain:l.string().optional(),path:l.string().optional(),expires:l.number().optional(),httpOnly:l.boolean().optional(),secure:l.boolean().optional(),sameSite:lt.optional()})).optional().describe(`Cookies to set (for set-cookie action)`),l.string().optional().describe(`Cookie name (for delete-cookie action)`),ut.optional().describe(`Storage type for storage actions`),l.string().optional().describe(`Storage key to get/set`),l.string().optional().describe(`Storage value to set`);function dt(e){return async({action:t,pageId:n,confirm:r,cookies:i,name:a,storageType:o,storageKey:s,storageValue:c})=>{let l=A(e);if(t===`list`){let e=l.session.listPages();return B(JSON.stringify(e,null,2),{pages:e})}if(t===`close`){if(!n)throw Error(`browser_session(close) requires pageId`);return await l.session.removePage(n),l.resetIdleTimer(),B(`ok`,{ok:!0,pageId:n})}if(t===`set-cookie`){let e=N(!!r);if(!e.allowed)throw Error(e.reason??`Cookie access denied`);if(!i?.length)throw Error(`cookies array required for set-cookie`);return await l.getContext().addCookies(i),l.resetIdleTimer(),B(`Set ${i.length} cookie(s)`,{ok:!0,count:i.length})}if(t===`delete-cookie`){let e=N(!!r);if(!e.allowed)throw Error(e.reason??`Cookie access denied`);if(!a)throw Error(`name required for delete-cookie`);return await l.getContext().clearCookies({name:a}),l.resetIdleTimer(),B(`Deleted cookie: ${a}`,{ok:!0,name:a})}if(t===`clear-cookies`){let e=N(!!r);if(!e.allowed)throw Error(e.reason??`Cookie access denied`);return await l.getContext().clearCookies(),l.resetIdleTimer(),B(`All cookies cleared`,{ok:!0})}if(t===`get-storage`){if(!n)throw Error(`pageId required for get-storage`);if(!o)throw Error(`storageType required for get-storage`);let e=await l.session.getPage(n).evaluate(({type:e,key:t})=>{let n=e===`localStorage`?localStorage:sessionStorage;if(t)return n.getItem(t);let r={};for(let e=0;e<n.length;e+=1){let t=n.key(e);t&&(r[t]=n.getItem(t)||``)}return r},{type:o,key:s});return l.resetIdleTimer(),B(s?`${o}.${s} = ${String(e)}`:`${o}: ${JSON.stringify(e)}`,{storageType:o,key:s,data:e})}if(t===`set-storage`){if(!n)throw Error(`pageId required for set-storage`);if(!o)throw Error(`storageType required for set-storage`);if(!s)throw Error(`storageKey required for set-storage`);if(c===void 0)throw Error(`storageValue required for set-storage`);return await l.session.getPage(n).evaluate(({type:e,key:t,value:n})=>{(e===`localStorage`?localStorage:sessionStorage).setItem(t,n)},{type:o,key:s,value:c}),l.resetIdleTimer(),B(`Set ${o}.${s}`,{ok:!0,storageType:o,key:s})}if(t===`clear-storage`){if(!n)throw Error(`pageId required for clear-storage`);if(!o)throw Error(`storageType required for clear-storage`);return await l.session.getPage(n).evaluate(e=>{(e===`localStorage`?localStorage:sessionStorage).clear()},o),l.resetIdleTimer(),B(`Cleared ${o}`,{ok:!0,storageType:o})}let u=N(!!r);if(!u.allowed)throw Error(u.reason??`Cookie access denied`);let d=await l.getContext().cookies();return l.resetIdleTimer(),B(JSON.stringify(d,null,2),{cookies:d})}}const ft=[`open`,`batch`,`read`,`act`,`navigate`,`network`,`console`,`fetch`,`eval`,`diff`,`screenshot`,`dialog`,`session`],G=[`ui`,`headless`],pt=[`load`,`domcontentloaded`,`networkidle`],mt=[`click`,`type`,`press`,`hover`,`drag`,`select`,`scroll`,`upload`],ht=[`back`,`forward`,`reload`,`waitFor`],gt=[`enable`,`get`,`clear`,`export-har`],_t=[`enable`,`get`,`clear`],vt=[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`,`HEAD`,`OPTIONS`],yt=[`list`,`close`,`cookies`,`set-cookie`,`delete-cookie`,`clear-cookies`,`get-storage`,`set-storage`,`clear-storage`],bt={action:l.enum(ft).describe(`Browser action to perform`),pageId:l.string().optional().describe(`Tracked browser page identifier`),label:l.string().optional().describe(`Human-readable label for the page (used as alternative to pageId)`),url:l.string().url().optional().describe(`URL to open or navigate to`),mode:l.enum(G).optional().describe(`Browser launch mode (open only)`),forceNew:l.boolean().optional().describe(`Reserved for future tab reuse`),autoDialog:l.boolean().optional().describe(`Auto-accept alert/beforeunload dialogs (default: true). Set false to handle all dialogs manually.`),waitUntil:l.enum(pt).optional().describe(`Navigation readiness event`),kind:l.enum(mt).optional().describe(`Interaction kind (act only)`),ref:l.string().optional().describe(`Target ref alias`),selector:l.string().optional().describe(`Playwright selector`),element:l.string().optional().describe(`Human-readable element label (resolved via Playwright text selector). Prefer selector for precision.`),text:l.string().optional().describe(`Text to type`),key:l.string().optional().describe(`Key to press`),value:l.string().optional().describe(`Option value or drag target`),fromRef:l.string().optional().describe(`Drag source ref`),fromSelector:l.string().optional().describe(`Drag source selector`),toRef:l.string().optional().describe(`Drag target ref`),toSelector:l.string().optional().describe(`Drag target selector`),type:l.enum(ht).optional().describe(`Navigation type`),subAction:l.enum(gt).optional().describe(`Network sub-action: enable, get, clear, or export-har`),code:l.string().optional().describe(`JavaScript expression or IIFE evaluated in page context. Wrapped in Function("return (<code>)"). Multi-statement: use (() => { ...; return result; })(). No bare return or top-level semicolons.`),timeoutMs:l.number().min(1).max(6e4).optional().describe(`Timeout in milliseconds`),filter:l.object({resourceTypes:l.array(l.string()).optional(),urlPattern:l.string().optional(),excludeUrls:l.array(l.string()).optional()}).optional().describe(`Network capture filter for resource types and URL patterns`),showSensitive:l.boolean().optional().describe(`Include sensitive headers instead of redacting them`),includeBody:l.boolean().optional().describe(`Include truncated request bodies in captured entries`),bufferSize:l.number().int().min(1).max(1e4).optional().describe(`Buffer capacity (1-10000, default varies by action)`),consoleSubAction:l.enum(_t).optional().describe(`Console sub-action: enable, get, or clear`),level:l.string().optional().describe(`Filter console entries by level (log/info/warn/error/debug)`),fetchUrl:l.string().optional().describe(`URL for fetch action (http/https only). Uses page cookies/session.`),fetchMethod:l.enum(vt).optional().describe(`HTTP method for fetch action (default: GET)`),fetchHeaders:l.record(l.string(),l.string()).optional().describe(`Custom headers for fetch action`),fetchBody:l.string().optional().describe(`Request body for fetch action (POST/PUT/PATCH)`),includeResponseHeaders:l.boolean().optional().describe(`Include response headers in fetch output (default: true)`),fullPage:l.boolean().optional().describe(`Capture full page`),redactPasswords:l.boolean().optional().describe(`Mask password fields`),readMode:l.enum([`snapshot`,`dom`,`markdown`,`text`]).optional().describe(`Extraction mode for read action: snapshot (ARIA tree), dom (HTML), markdown (clean MD), text (plain text)`),clip:l.object({x:l.number(),y:l.number(),width:l.number(),height:l.number()}).optional().describe(`Capture a specific page region { x, y, width, height }`),format:l.enum([`png`,`jpeg`]).optional().describe(`Screenshot image format (default: png)`),quality:l.number().min(0).max(100).optional().describe(`JPEG quality 0-100 (only for jpeg format)`),cookies:l.array(l.object({name:l.string(),value:l.string(),url:l.string().optional(),domain:l.string().optional(),path:l.string().optional(),expires:l.number().optional(),httpOnly:l.boolean().optional(),secure:l.boolean().optional(),sameSite:l.enum([`Lax`,`None`,`Strict`]).optional()})).optional().describe(`Cookies to set (for session set-cookie action)`),name:l.string().optional().describe(`Cookie name for delete-cookie action`),storageType:l.enum([`localStorage`,`sessionStorage`]).optional().describe(`Storage type for get/set/clear-storage actions`),storageKey:l.string().optional().describe(`Storage key to get or set`),storageValue:l.string().optional().describe(`Value to set in storage`),accept:l.boolean().optional().describe(`Accept or dismiss dialog`),promptText:l.string().optional().describe(`Text for prompt dialog`),sessionAction:l.enum(yt).optional().describe(`Session sub-action (session only)`),confirm:l.boolean().optional().describe(`Explicit confirmation for cookie export`),steps:l.array(l.record(l.string(),l.unknown())).optional().describe(`Array of action steps for batch execution. Each step is an object with action + action-specific params.`)};function xt(e,t){return typeof e==`string`&&t.includes(e)}function K(e,t,n){let r=e[t];if(typeof r!=`string`)throw Error(`${n} requires ${t}`);return r}function St(e,t,n){let r=e[t];if(typeof r!=`boolean`)throw Error(`${n} requires ${t}`);return r}function q(e,t){let n=e[t];return typeof n==`string`?n:void 0}function J(e,t){let n=e[t];return typeof n==`boolean`?n:void 0}function Y(e,t){let n=e[t];return typeof n==`number`?n:void 0}function X(e,t){let n=e[t];return typeof n==`object`&&n?n:void 0}function Ct(e,t){let n=e.steps;if(!Array.isArray(n)||n.length===0)throw Error(`${t} requires non-empty steps`);return n.map((e,n)=>{if(typeof e!=`object`||!e||Array.isArray(e))throw Error(`${t} step ${n+1} must be an object`);return e})}function Z(e,t,n,r){let i=e[t];if(!xt(i,n))throw Error(`${r} requires ${t}`);return i}function Q(e,t,n,r){let i=e[t];if(i!==void 0){if(!xt(i,n))throw Error(`${r} received invalid ${t}`);return i}}function wt(e,t){let n=q(e,`pageId`);if(n)return A(t).session.resolvePageId(n)}function $(e,t,n){let r=q(e,`pageId`);if(!r)throw Error(`${n} requires pageId`);return A(t).session.resolvePageId(r)}async function Tt(e,t,n){switch(Z(e,`action`,ft,`browser`)){case`open`:return t.openHandler({url:K(e,`url`,`browser(open)`),mode:Q(e,`mode`,G,`browser(open)`),forceNew:J(e,`forceNew`),label:q(e,`label`),autoDialog:J(e,`autoDialog`),waitUntil:Q(e,`waitUntil`,pt,`browser(open)`)});case`batch`:{let r=Ct(e,`browser(batch)`),i=[],a=0;for(let e=0;e<r.length;e+=1){let o=r[e],s=q(o,`action`)??`unknown`;try{let r=await Tt(o,t,n);a+=1,i.push({index:e,action:s,ok:!0,result:r})}catch(t){i.push({index:e,action:s,ok:!1,error:t instanceof Error?t.message:String(t)})}}return B(`Batch completed: ${a}/${r.length} steps succeeded`,{total:r.length,succeeded:a,steps:i})}case`read`:return t.readHandler({pageId:$(e,n,`browser(read)`),mode:Q(e,`readMode`,[`snapshot`,`dom`,`markdown`,`text`],`browser(read)`),selector:q(e,`selector`)});case`act`:return t.actHandler({pageId:$(e,n,`browser(act)`),kind:Z(e,`kind`,mt,`browser(act)`),ref:q(e,`ref`),selector:q(e,`selector`),element:q(e,`element`),text:q(e,`text`),key:q(e,`key`),value:q(e,`value`),fromRef:q(e,`fromRef`),fromSelector:q(e,`fromSelector`),toRef:q(e,`toRef`),toSelector:q(e,`toSelector`)});case`navigate`:return t.navigateHandler({pageId:$(e,n,`browser(navigate)`),url:q(e,`url`),type:Q(e,`type`,ht,`browser(navigate)`),selector:q(e,`selector`),timeoutMs:Y(e,`timeoutMs`)});case`network`:return t.networkHandler({pageId:$(e,n,`browser(network)`),subAction:Z(e,`subAction`,gt,`browser(network)`),filter:X(e,`filter`),showSensitive:J(e,`showSensitive`),includeBody:J(e,`includeBody`),bufferSize:Y(e,`bufferSize`)});case`console`:return t.consoleHandler({pageId:$(e,n,`browser(console)`),subAction:Z(e,`consoleSubAction`,_t,`browser(console)`),level:q(e,`level`),bufferSize:Y(e,`bufferSize`)});case`fetch`:return t.fetchHandler({pageId:$(e,n,`browser(fetch)`),url:K(e,`fetchUrl`,`browser(fetch)`),method:Q(e,`fetchMethod`,vt,`browser(fetch)`),headers:X(e,`fetchHeaders`),body:q(e,`fetchBody`),timeoutMs:Y(e,`timeoutMs`),includeHeaders:J(e,`includeResponseHeaders`)});case`eval`:return t.evalHandler({pageId:$(e,n,`browser(eval)`),code:K(e,`code`,`browser(eval)`),timeoutMs:Y(e,`timeoutMs`)});case`diff`:return t.diffHandler({pageId:$(e,n,`browser(diff)`)});case`screenshot`:{let r=X(e,`clip`);return t.screenshotHandler({pageId:$(e,n,`browser(screenshot)`),ref:q(e,`ref`),selector:q(e,`selector`),fullPage:J(e,`fullPage`),redactPasswords:J(e,`redactPasswords`),clip:r,format:Q(e,`format`,[`png`,`jpeg`],`browser(screenshot)`),quality:Y(e,`quality`)})}case`dialog`:return t.dialogHandler({pageId:$(e,n,`browser(dialog)`),accept:St(e,`accept`,`browser(dialog)`),promptText:q(e,`promptText`)});case`session`:{let r=e.cookies;return t.sessionHandler({action:Z(e,`sessionAction`,yt,`browser(session)`),pageId:wt(e,n),confirm:J(e,`confirm`),cookies:r,name:q(e,`name`),storageType:Q(e,`storageType`,[`localStorage`,`sessionStorage`],`browser(session)`),storageKey:q(e,`storageKey`),storageValue:q(e,`storageValue`)})}}}function Et(e,t){let n=Te(t),r={openHandler:ot(n),readHandler:st(n),actHandler:De(n),navigateHandler:Xe(n),networkHandler:at(n),consoleHandler:je(n),fetchHandler:Ye(n),evalHandler:Pe(n),diffHandler:Ne(n),screenshotHandler:ct(n),dialogHandler:Me(n),sessionHandler:dt(n)};e.registerTool(`browser`,{title:`Browser Automation`,description:`Unified browser automation tool. Actions:
|
|
13
19
|
- open: Launch a browser page (url required, mode/waitUntil optional)
|
|
20
|
+
- batch: Execute multiple browser actions sequentially (steps required)
|
|
14
21
|
- read: Get accessibility snapshot of a page (pageId required)
|
|
15
22
|
- act: Interact with elements — click/type/press/hover/drag/select/scroll/upload (pageId + kind required)
|
|
16
23
|
- navigate: Go to URL, back/forward/reload, or waitFor selector (pageId required)
|
|
@@ -18,6 +25,7 @@ import{createRequire as e}from"node:module";import{createHash as t,randomUUID as
|
|
|
18
25
|
- console: Capture browser console messages — log/warn/error (pageId + consoleSubAction required)
|
|
19
26
|
- fetch: Execute HTTP request using page cookies/session (pageId + fetchUrl required)
|
|
20
27
|
- eval: Evaluate JavaScript in page context (pageId + code required)
|
|
28
|
+
- diff: Compare the current accessibility snapshot to the previous one (pageId required)
|
|
21
29
|
- screenshot: Capture page or element screenshot (pageId required)
|
|
22
30
|
- dialog: Accept or dismiss next browser dialog (pageId + accept required)
|
|
23
|
-
- session: List pages, close a page, or export cookies (sessionAction required)`,inputSchema:
|
|
31
|
+
- session: List pages, close a page, or export cookies (sessionAction required)`,inputSchema:bt,annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},async e=>Tt(e,r,n))}export{O as BrowserEngine,D as DEFAULT_BROWSER_CONFIG,E as SessionRegistry,w as autoSelectMode,ge as closeEngine,C as detectDisplayAvailable,S as ensureBrowserInstalled,he as getDefaultBrowsersPath,A as getEngine,T as getLaunchArgs,x as isBrowserInstalled,N as isCookieAccessAllowed,M as isUrlAllowed,Se as redactPasswordFields,Et as registerBrowserTools,b as resolveBrowsersPath,P as validateEvalResult};
|