@mearl/native-host 3.0.0-beta.0 → 3.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/skill-manager.d.ts +3 -1
- package/dist/index.js +51 -51
- package/dist/install.js +1 -1
- package/dist/plugin-task-host.js +1 -1
- package/dist/plugin-worker.js +1 -1
- package/package.json +14 -9
package/dist/install.js
CHANGED
|
@@ -3,7 +3,7 @@ import fs4 from"node:fs";import path4 from"node:path";import{execFileSync as exe
|
|
|
3
3
|
rem ${metadataLine}\r
|
|
4
4
|
"${nodePaths[0]}" "${hostPath}" %*\r
|
|
5
5
|
`;return fs.writeFileSync(launcherPath2,content2,"utf-8"),launcherPath2}let launcherPath=path.join(hostDir,`${hostName}-launcher.sh`),content=["#!/bin/sh",`# ${metadataLine}`,`HOST_SCRIPT=${shellQuote(hostPath)}`,'if [ ! -f "$HOST_SCRIPT" ] || [ ! -r "$HOST_SCRIPT" ]; then',` printf '%s\\n' "Mearl native host: runtime script is missing or unreadable: $HOST_SCRIPT" >&2`," printf '%s\\n' 'Run npx @mearl/setup update --local to repair the installation.' >&2"," exit 1","fi",`for NODE_BIN in ${nodePaths.map(shellQuote).join(" ")}; do`,' if [ -f "$NODE_BIN" ] && [ -x "$NODE_BIN" ]; then',' PATH="${NODE_BIN%/*}${PATH:+:$PATH}"'," export PATH",' exec "$NODE_BIN" "$HOST_SCRIPT" "$@"'," fi","done",`printf '%s\\n' ${shellQuote(`Mearl native host: no executable Node.js found. Tried: ${nodePaths.join(", ")}`)} >&2`,"printf '%s\\n' 'Run mearl-native-host init with a working Node.js, then reopen the extension.' >&2","exit 127",""].join(`
|
|
6
|
-
`);return fs.writeFileSync(launcherPath,content,"utf-8"),fs.chmodSync(launcherPath,493),launcherPath}import fs3 from"node:fs";import path3 from"node:path";import{execFileSync}from"node:child_process";import fs2 from"node:fs";import os from"node:os";import path2 from"node:path";var MEARL_NATIVE_HOST_NAMES={skills:"com.alibaba.mearl.skills",mcp:"com.alibaba.mearl.mcp"};function resolveNativeHostDirectory(options={}){let env=options.env??process.env,home=(options.homedir??os.homedir)();switch(options.platform??process.platform){case"darwin":return path2.join(home,"Library/Application Support/Google/Chrome/NativeMessagingHosts");case"linux":return path2.join(home,".config/google-chrome/NativeMessagingHosts");case"win32":return path2.join(env.PROGRAMDATA||"C:\\ProgramData","Google\\Chrome\\NativeMessagingHosts");default:throw new Error(`Unsupported platform: ${String(options.platform??process.platform)}`)}}function unregisterWindowsNativeHost(hostName){let registryKey=`HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\${hostName}`;try{execFileSync("reg",["delete",registryKey,"/f"],{stdio:"pipe"})}catch{}}function uninstallNativeHostArtifacts(options={},dependencies={}){let{mode="both",silent=!1}=options;if(mode==="both")return["skills","mcp"].map(integrationMode=>uninstallNativeHostArtifacts({...options,mode:integrationMode},dependencies)).every(Boolean);let writeLine=dependencies.writeLine??(line=>console.error(line)),log=line=>{silent||writeLine(line)};try{let existsSync=dependencies.existsSync??fs3.existsSync,platform=dependencies.platform??process.platform,hostDir=dependencies.hostDir??resolveNativeHostDirectory({env:dependencies.env,homedir:dependencies.homedir,platform}),unlinkSync=dependencies.unlinkSync??fs3.unlinkSync,unregister=dependencies.unregisterWindowsNativeHost??unregisterWindowsNativeHost,hostName=MEARL_NATIVE_HOST_NAMES[mode],launcherExtension=platform==="win32"?"cmd":"sh",artifacts=[path3.join(hostDir,`${hostName}.json`),path3.join(hostDir,`${hostName}-launcher.${launcherExtension}`)];for(let artifact of artifacts)existsSync(artifact)&&(unlinkSync(artifact),log(`✅ Removed: ${artifact}`));return platform==="win32"&&unregister(hostName),!0}catch(error){return log(`❌ Uninstall failed: ${error instanceof Error?error.message:String(error)}`),!1}}var DEFAULT_EXTENSION_ID="aoehhjnofngknnjefamjbplchbolghkm",__filename=fileURLToPath(import.meta.url),__dirname=path4.dirname(__filename),ALL_MODES=["skills","mcp"];function resolveHostDir(){return resolveNativeHostDirectory()}function resolveNativeHostPath(){let siblingPath=path4.join(__dirname,"index.js");if(fs4.existsSync(siblingPath))return siblingPath;try{return createRequire(import.meta.url).resolve("@mearl/native-host/runtime")}catch{throw new Error("Cannot locate native-host runtime entry point. Ensure @mearl/native-host is installed correctly.")}}function registerWindowsNativeHost(hostName,manifestPath){let regKey=`HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\${hostName}`;execFileSync2("reg",["add",regKey,"/ve","/t","REG_SZ","/d",manifestPath,"/f"],{stdio:"pipe"})}async function installNativeHost(options={}){let{mode="both",extensionId=DEFAULT_EXTENSION_ID,silent=!1,skipIfExists=!1}=options;if(mode==="both")return(await Promise.all(ALL_MODES.map(m=>installNativeHost({...options,mode:m})))).every(Boolean);let hostName=MEARL_NATIVE_HOST_NAMES[mode];if(!hostName)throw new Error(`Unknown mode: ${mode}. Expected 'skills' or 'mcp'.`);let log=(...args)=>{silent||console.error(...args)};try{let hostDir=resolveHostDir();if(skipIfExists){let manifestPath2=path4.join(hostDir,`${hostName}.json`);if(fs4.existsSync(manifestPath2))return log(`✅ Already installed: ${manifestPath2}`),!0}fs4.existsSync(hostDir)||(fs4.mkdirSync(hostDir,{recursive:!0}),log(`✅ Created directory: ${hostDir}`));let resolvedHostPath=resolveNativeHostPath();log(`✅ Native host path: ${resolvedHostPath}`);let launcherPath=createLauncherScript(hostDir,resolvedHostPath,hostName);log(`✅ Launcher script: ${launcherPath}`);let manifest={name:hostName,description:"Mearl Native Messaging Bridge",path:launcherPath,type:"stdio",allowed_origins:[`chrome-extension://${extensionId}/`]},manifestPath=path4.join(hostDir,`${hostName}.json`);return fs4.writeFileSync(manifestPath,JSON.stringify(manifest,null,2)),process.platform==="win32"?(registerWindowsNativeHost(hostName,manifestPath),log(`✅ Windows registry key created for: ${hostName}`)):fs4.chmodSync(manifestPath,420),log(`✅ Manifest installed: ${manifestPath}`),log(`✅ Extension ID: ${extensionId}`),log(`✅ Host name: ${hostName}`),!0}catch(error){return log(`❌ Installation failed: ${error instanceof Error?error.message:String(error)}`),error instanceof Error&&"code"in error&&error.code==="EACCES"&&log(`
|
|
6
|
+
`);return fs.writeFileSync(launcherPath,content,"utf-8"),fs.chmodSync(launcherPath,493),launcherPath}import fs3 from"node:fs";import path3 from"node:path";import{execFileSync}from"node:child_process";import fs2 from"node:fs";import os from"node:os";import path2 from"node:path";var APP_BRIDGE_BEHAVIORS=["navigate","closeAll","closeBackData","postMessage","notifySubscribe","notifyUnsubscribe","notifyPost","sharedFileRead","sharedFileWrite","sharedDataGet","sharedDataSet","legacyBroadcastCreate","legacyBroadcastPost","legacyBroadcastClose","memoryGet","memorySet","memoryDelete","availabilityMap","userInfo","authCode","networkInfo","geolocation","permission","imagePicker","prefetch","fptTrack","mtopStream","previewFile","toast","unsupportedNativeInput","payment","userTrack","calendar","networkQualityMonitor","beaconRequest","voiceRecognition"],BEHAVIORS=new Set(APP_BRIDGE_BEHAVIORS);var textEncoder=new TextEncoder;var ALLOWED_ORIGINS=["*://localhost/*","*://127.0.0.1/*"],ALLOWED_ORIGINS_LIST=[...ALLOWED_ORIGINS];function scrollElementInPage(direction,distance,targetLabel,containerPolicy="self"){let element=this?.nodeType===3?this.parentElement:this,targetDocument=element?.nodeType===9?element:null;if(targetDocument&&(element=targetDocument.scrollingElement),!element||element.isConnected===!1)return{error:"Cannot resolve scroll container: "+targetLabel};let startingElement=element,ancestorDistance=0;function scrollMetrics(candidate){let scrollTop=Number(candidate?.scrollTop),scrollHeight=Number(candidate?.scrollHeight),clientHeight=Number(candidate?.clientHeight);if(!Number.isFinite(scrollTop)||!Number.isFinite(scrollHeight)||!Number.isFinite(clientHeight))return null;let ownerDocument=candidate.ownerDocument,isRootScroller=!!ownerDocument&&candidate===ownerDocument.scrollingElement,maxScrollTop=Math.max(0,scrollHeight-clientHeight),overflowAllowsScroll=!0;try{let overflowY=ownerDocument?.defaultView?.getComputedStyle(candidate).overflowY;!isRootScroller&&(overflowY==="visible"||overflowY==="clip")&&(overflowAllowsScroll=!1)}catch{}return{scrollTop,scrollHeight,clientHeight,maxScrollTop,isRootScroller,usable:isRootScroller||maxScrollTop>0&&overflowAllowsScroll}}function documentFallback(documentRef){let windowRef=documentRef.defaultView,visited=new Set,viewportWidth=Number(windowRef?.innerWidth)||Number(element?.clientWidth)||0,viewportHeight=Number(windowRef?.innerHeight)||Number(element?.clientHeight)||0,points=[[viewportWidth/2,viewportHeight/2],[viewportWidth/2,viewportHeight*.75],[viewportWidth/2,viewportHeight*.25]];function containerDepth(candidate){if(candidate===documentRef.body||candidate===documentRef.documentElement)return 0;let depth=0,cursor=candidate;for(;cursor&&cursor!==documentRef.body&&cursor!==documentRef.documentElement;)depth+=1,cursor=cursor.parentElement;return depth}function canMove(metrics2){return direction==="up"||direction==="top"?metrics2.scrollTop>0:metrics2.scrollTop<metrics2.maxScrollTop}let sampledPageContainer;for(let[x,y]of points){let candidate=null;try{candidate=documentRef.elementFromPoint?.(x,y)??null}catch{}for(;candidate&&candidate.nodeType===1;){if(!visited.has(candidate)){visited.add(candidate);let candidateMetrics=scrollMetrics(candidate);if(candidateMetrics?.usable&&candidateMetrics.maxScrollTop>0&&canMove(candidateMetrics)){let resolved={element:candidate,metrics:candidateMetrics,distance:containerDepth(candidate)};if(candidate===documentRef.body||candidate===documentRef.documentElement)sampledPageContainer??=resolved;else return resolved}}candidate=candidate.parentElement}}if(sampledPageContainer)return sampledPageContainer;let best,candidates=Array.from(documentRef.querySelectorAll?.("*")??[]).slice(0,1e4);for(let candidate of candidates){let candidateMetrics=scrollMetrics(candidate);if(!candidateMetrics?.usable||candidateMetrics.maxScrollTop<=0||!canMove(candidateMetrics))continue;let rect,style;try{rect=candidate.getBoundingClientRect(),style=windowRef?.getComputedStyle(candidate)}catch{continue}if(!rect||rect.width<=0||rect.height<=0||style?.display==="none"||style?.visibility==="hidden"||style?.visibility==="collapse")continue;let visibleWidth=Math.max(0,Math.min(rect.right,viewportWidth)-Math.max(rect.left,0)),visibleHeight=Math.max(0,Math.min(rect.bottom,viewportHeight)-Math.max(rect.top,0)),area=visibleWidth*visibleHeight;if(area<=0)continue;let depth=containerDepth(candidate);(!best||depth<best.distance||depth===best.distance&&area>best.area)&&(best={element:candidate,metrics:candidateMetrics,distance:depth,area})}return best?{element:best.element,metrics:best.metrics,distance:best.distance}:null}function selectorFor(candidate){let documentRef=candidate?.ownerDocument;if(!documentRef||candidate.nodeType!==1)return"";if(candidate===documentRef.documentElement)return"html";if(candidate===documentRef.body)return"body";let escapeCss=value=>documentRef.defaultView?.CSS?.escape?documentRef.defaultView.CSS.escape(value):value.replace(/[^a-zA-Z0-9_-]/g,character=>"\\"+character);if(candidate.id){let idSelector="#"+escapeCss(String(candidate.id));try{if(documentRef.querySelectorAll(idSelector).length===1)return idSelector}catch{}}let path5=[],cursor=candidate;for(;cursor&&cursor.nodeType===1&&path5.length<8;){let tag=String(cursor.tagName||"").toLowerCase();if(!tag)break;let parent=cursor.parentElement;if(!parent){path5.unshift(tag);break}let siblings=Array.from(parent.children).filter(sibling=>sibling.tagName===cursor.tagName),index=siblings.indexOf(cursor)+1;if(path5.unshift(siblings.length>1?tag+":nth-of-type("+index+")":tag),cursor=parent,cursor===documentRef.documentElement){path5.unshift("html");break}}return path5.join(" > ")}let metrics=scrollMetrics(element);if(!metrics)return{error:"Element is not scrollable: "+targetLabel};if(targetDocument){let fallback=documentFallback(targetDocument);fallback&&(element=fallback.element,metrics=fallback.metrics,ancestorDistance=fallback.distance)}if(!metrics.usable&&containerPolicy==="nearest"){let candidate=element.parentElement;for(;candidate;){ancestorDistance+=1;let candidateMetrics=scrollMetrics(candidate);if(candidateMetrics?.usable){element=candidate,metrics=candidateMetrics;break}candidate=candidate.parentElement}}if(!metrics.usable&&!metrics.isRootScroller)return{error:"Element is not scrollable: "+targetLabel+(containerPolicy==="nearest"?" (no scrollable ancestor found)":"")};let targetTop;switch(direction){case"top":targetTop=0;break;case"bottom":targetTop=metrics.maxScrollTop;break;case"up":targetTop=Math.max(0,metrics.scrollTop-Math.abs(distance));break;default:targetTop=Math.min(metrics.maxScrollTop,metrics.scrollTop+Math.abs(distance));break}if(typeof element.scrollTo=="function")try{element.scrollTo({top:targetTop,left:Number(element.scrollLeft)||0,behavior:"instant"})}catch{element.scrollTop=targetTop}else element.scrollTop=targetTop;let actualScrollTop=Number(element.scrollTop);return!metrics.isRootScroller&&targetTop!==metrics.scrollTop&&actualScrollTop===metrics.scrollTop?{error:"Element is not scrollable: "+targetLabel}:{scrollY:Math.round(actualScrollTop),scrollHeight:metrics.scrollHeight,clientHeight:metrics.clientHeight,maxScrollY:Math.round(metrics.maxScrollTop),scrollYBefore:Math.round(metrics.scrollTop),scrollYAfter:Math.round(actualScrollTop),moved:actualScrollTop!==metrics.scrollTop,atTop:actualScrollTop<=0,atBottom:actualScrollTop>=metrics.maxScrollTop,target:targetLabel,resolvedContainer:targetDocument&&element===targetDocument.body&&element!==startingElement?"document-body":targetDocument&&element!==startingElement?"document-descendant":element===startingElement?"self":"nearest-scrollable-ancestor",ancestorDistance,...targetDocument&&element!==startingElement?{containerSelector:selectorFor(element)}:{}}}var SCROLL_ELEMENT_IN_PAGE_SOURCE=scrollElementInPage.toString();function inspectElementsInPage(selector,filter,styles,maxResults,invalidSelectorHint,includeOuterHTML=!1){let context=this?.nodeType===3?this.parentElement:this,documentRef=context?.nodeType===9?context:context?.ownerDocument;if(!documentRef)return{error:"page_inspect cannot resolve the target document"};let scanLimit=1e4,candidates;if(context?.nodeType===9){let effectiveSelector=selector??"*";try{candidates=Array.from(documentRef.querySelectorAll(effectiveSelector))}catch(error){return{error:'Invalid CSS selector "'+effectiveSelector+'": '+(error instanceof Error?error.message:String(error))+". "+invalidSelectorHint}}}else if(context?.nodeType===1&&context.isConnected!==!1)candidates=[context];else return{error:"page_inspect target is detached from the document"};let candidateCount=candidates.length,scanTruncated=filter!=="all"&&candidateCount>scanLimit;candidates=filter==="all"?candidates.slice(0,maxResults):scanTruncated?candidates.slice(0,scanLimit):candidates;let windowRef=documentRef.defaultView,viewportWidth=Number(windowRef?.innerWidth)||0,viewportHeight=Number(windowRef?.innerHeight)||0;function round(value){return Math.round(value*1e3)/1e3}function controlState(element){let state={};for(let name of["checked","selected","pressed","expanded","disabled","readonly"]){let value=element.getAttribute?.("aria-"+name);(value==="true"||value==="false"||value==="mixed"&&(name==="checked"||name==="pressed"))&&(state[name]={value:value==="mixed"?"mixed":value==="true",source:"aria"})}let tag=String(element.tagName||"").toLowerCase(),type=String(element.type||"").toLowerCase();if(tag==="input"&&(type==="checkbox"||type==="radio")&&(state.checked={value:type==="checkbox"&&element.indeterminate?"mixed":!!element.checked,source:"native"}),tag==="option"&&(state.selected={value:!!element.selected,source:"native"}),["button","input","select","textarea","option","optgroup","fieldset"].includes(tag)){let disabled=element.matches?.(":disabled")??!!element.disabled;(disabled||!state.disabled)&&(state.disabled={value:disabled,source:"native"})}return(tag==="textarea"||tag==="input"&&["text","search","tel","url","email","password","date","month","week","time","datetime-local","number"].includes(type))&&(element.readOnly||!state.readonly)&&(state.readonly={value:!!element.readOnly,source:"native"}),state}function escapeCss(value){return windowRef?.CSS&&typeof windowRef.CSS.escape=="function"?windowRef.CSS.escape(value):value.replace(/[^a-zA-Z0-9_-]/g,character=>"\\"+character)}function selectorFor(element){if(element.id){let idSelector="#"+escapeCss(String(element.id));try{if(documentRef.querySelectorAll(idSelector).length===1)return idSelector}catch{}}let path5=[],cursor=element;for(;cursor&&cursor.nodeType===1&&path5.length<8;){let tag=String(cursor.tagName||"").toLowerCase();if(!tag)break;let parent=cursor.parentElement;if(!parent){path5.unshift(tag);break}let siblings=Array.from(parent.children).filter(sibling=>sibling.tagName===cursor.tagName),index=siblings.indexOf(cursor)+1;if(path5.unshift(siblings.length>1?tag+":nth-of-type("+index+")":tag),cursor=parent,cursor===documentRef.documentElement){path5.unshift("html");break}}return path5.join(" > ")}function readStyle(style,property){let cssValue=style.getPropertyValue?.(property);if(cssValue)return String(cssValue);let camelName=property.replace(/-([a-z])/g,(_match,letter)=>letter.toUpperCase());return String(style[camelName]??"")}function isScrollable(element,style){let canScrollX=Number(element.scrollWidth)>Number(element.clientWidth)&&!["visible","clip"].includes(String(style.overflowX)),canScrollY=Number(element.scrollHeight)>Number(element.clientHeight)&&!["visible","clip"].includes(String(style.overflowY));return canScrollX||canScrollY}function nearestScrollContainer(element){let candidate=element,ancestorDistance=0;for(;candidate&&candidate.nodeType===1;){let style=windowRef.getComputedStyle(candidate);if(isScrollable(candidate,style))return{selector:selectorFor(candidate),tag:String(candidate.tagName||"").toLowerCase(),ancestorDistance,scrollWidth:Number(candidate.scrollWidth)||0,scrollHeight:Number(candidate.scrollHeight)||0,clientWidth:Number(candidate.clientWidth)||0,clientHeight:Number(candidate.clientHeight)||0,scrollLeft:Number(candidate.scrollLeft)||0,scrollTop:Number(candidate.scrollTop)||0,overflowX:String(style.overflowX||""),overflowY:String(style.overflowY||"")};candidate=candidate.parentElement,ancestorDistance+=1}}function hitTargetInfo(element,rect,visible,style){let left=Math.max(0,Number(rect.left)||0),right=Math.min(viewportWidth,Number(rect.right)||0),top=Math.max(0,Number(rect.top)||0),bottom=Math.min(viewportHeight,Number(rect.bottom)||0),x=round(left+Math.max(0,right-left)/2),y=round(top+Math.max(0,bottom-top)/2),hit=null;try{hit=visible?documentRef.elementFromPoint?.(x,y)??null:null}catch{}let topmost=!!hit&&(hit===element||element.contains?.(hit)),target=hit?{selector:selectorFor(hit),tag:String(hit.tagName||"").toLowerCase(),text:String(hit.innerText??hit.textContent??"").trim().replace(/\s+/g," ").slice(0,120)}:void 0;return{point:{x,y},topmost,receivesPointerEvents:visible&&style.pointerEvents!=="none"&&topmost,...target?{target}:{},...!topmost&&target?{occludedBy:target}:{}}}let matches=[],count=filter==="all"?candidateCount:0;for(let element of candidates){let style=windowRef.getComputedStyle(element),scrollWidth=Number(element.scrollWidth)||0,scrollHeight=Number(element.scrollHeight)||0,clientWidth=Number(element.clientWidth)||0,clientHeight=Number(element.clientHeight)||0,horizontalOverflow=Math.max(0,scrollWidth-clientWidth),verticalOverflow=Math.max(0,scrollHeight-clientHeight),scrollable=isScrollable(element,style);if(!(filter==="all"||filter==="overflowing"&&(horizontalOverflow>0||verticalOverflow>0)||filter==="horizontal-overflow"&&horizontalOverflow>0||filter==="vertical-overflow"&&verticalOverflow>0||filter==="scrollable"&&scrollable)||(filter!=="all"&&(count+=1),matches.length>=maxResults))continue;let rect=element.getBoundingClientRect(),opacity=Number(style.opacity),visible=rect.width>0&&rect.height>0&&style.display!=="none"&&style.visibility!=="hidden"&&style.visibility!=="collapse"&&(!Number.isFinite(opacity)||opacity>0)&&rect.right>0&&rect.bottom>0&&rect.left<viewportWidth&&rect.top<viewportHeight,computedStyle={};for(let property of styles)computedStyle[property]=readStyle(style,property);let scrollContainer=nearestScrollContainer(element),hitTest=hitTargetInfo(element,rect,visible,style),state=controlState(element);matches.push({selector:selectorFor(element),tag:String(element.tagName||"").toLowerCase(),text:String(element.innerText??element.textContent??"").trim().replace(/\s+/g," ").slice(0,240),visible,hitTest,...Object.keys(state).length?{state}:{},boundingBox:{x:round(rect.x),y:round(rect.y),width:round(rect.width),height:round(rect.height),top:round(rect.top),right:round(rect.right),bottom:round(rect.bottom),left:round(rect.left)},computedStyle,scroll:{scrollWidth,scrollHeight,clientWidth,clientHeight,overflowX:String(style.overflowX||""),overflowY:String(style.overflowY||""),horizontalOverflow,verticalOverflow},...scrollContainer?{scrollContainer}:{},...includeOuterHTML?{outerHTML:String(element.outerHTML??"").slice(0,3e3)}:{}})}return{...selector!==void 0?{selector}:{},filter,candidateCount,count,matches,truncated:scanTruncated||count>matches.length,...scanTruncated?{scanTruncated:!0}:{}}}var INSPECT_ELEMENTS_IN_PAGE_SOURCE=inspectElementsInPage.toString();var SHELL_BODY=btoa('<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"></head><body></body></html>');var MAX_DOCUMENT_BYTES=16*1024*1024;function dragBetweenPointsInPage(from,points,pointerType){let target=document.elementFromPoint(from.x,from.y);if(!target)return{dragged:!1,steps:0,error:`No element found at drag start point (${from.x}, ${from.y})`};if(points.length===0)return{dragged:!1,steps:0,error:"Drag path must contain at least one point"};let view=target.ownerDocument.defaultView??window,realm=view,pointerId=1,pointerInit=(point,buttons,pressure)=>({bubbles:!0,cancelable:!0,composed:!0,view,clientX:point.x,clientY:point.y,screenX:point.x,screenY:point.y,button:0,buttons,pointerId,pointerType,isPrimary:!0,pressure,width:1,height:1}),dispatchPointer=(type,point,buttons,pressure)=>typeof realm.PointerEvent!="function"?!1:(target.dispatchEvent(new realm.PointerEvent(type,pointerInit(point,buttons,pressure))),!0),dispatchMouse=(type,point,buttons)=>typeof realm.MouseEvent!="function"?!1:(target.dispatchEvent(new realm.MouseEvent(type,{bubbles:!0,cancelable:!0,composed:!0,view,clientX:point.x,clientY:point.y,screenX:point.x,screenY:point.y,button:0,buttons})),!0),createTouch=point=>{let init={identifier:pointerId,target,clientX:point.x,clientY:point.y,screenX:point.x,screenY:point.y,pageX:point.x+view.scrollX,pageY:point.y+view.scrollY,radiusX:1,radiusY:1,rotationAngle:0,force:.5};return typeof realm.Touch=="function"?new realm.Touch(init):init},dispatchTouch=(type,point)=>{if(typeof realm.TouchEvent!="function")return!1;let touch=createTouch(point),activeTouches=type==="touchend"?[]:[touch];return target.dispatchEvent(new realm.TouchEvent(type,{bubbles:!0,cancelable:!0,composed:!0,touches:activeTouches,targetTouches:activeTouches,changedTouches:[touch]})),!0},dispatched=dispatchPointer("pointerdown",from,1,.5);dispatched=pointerType==="touch"?dispatchTouch("touchstart",from)||dispatched:dispatchMouse("mousedown",from,1)||dispatched;for(let point of points)dispatched=dispatchPointer("pointermove",point,1,.5)||dispatched,dispatched=pointerType==="touch"?dispatchTouch("touchmove",point)||dispatched:dispatchMouse("mousemove",point,1)||dispatched;let end=points[points.length-1];return dispatched=pointerType==="touch"?dispatchTouch("touchend",end)||dispatched:dispatchMouse("mouseup",end,0)||dispatched,dispatched=dispatchPointer("pointerup",end,0,0)||dispatched,dispatched?{dragged:!0,steps:points.length}:{dragged:!1,steps:0,error:"This page does not support synthetic drag events"}}var DRAG_BETWEEN_POINTS_IN_PAGE_SOURCE=dragBetweenPointsInPage.toString();var PAGE_PRESS_KEY_DESCRIPTORS=Object.freeze({Enter:{key:"Enter",code:"Enter",keyCode:13,text:"\r"},Tab:{key:"Tab",code:"Tab",keyCode:9},Escape:{key:"Escape",code:"Escape",keyCode:27},Backspace:{key:"Backspace",code:"Backspace",keyCode:8},Delete:{key:"Delete",code:"Delete",keyCode:46},ArrowUp:{key:"ArrowUp",code:"ArrowUp",keyCode:38},ArrowDown:{key:"ArrowDown",code:"ArrowDown",keyCode:40},ArrowLeft:{key:"ArrowLeft",code:"ArrowLeft",keyCode:37},ArrowRight:{key:"ArrowRight",code:"ArrowRight",keyCode:39},Home:{key:"Home",code:"Home",keyCode:36},End:{key:"End",code:"End",keyCode:35},PageUp:{key:"PageUp",code:"PageUp",keyCode:33},PageDown:{key:"PageDown",code:"PageDown",keyCode:34},Space:{key:" ",code:"Space",keyCode:32,text:" "}});var TAB_ID_REQUIRED_ACTIONS=["tab_checkpoint","capture_checkpoint","get_requests","get_logs","get_events","set_mock","get_mocks","page_screenshot","tab_close","page_click","page_drag","page_type","page_scroll","page_hover","page_eval","page_inspect","page_snapshot","page_press","page_wait","page_navigate","page_upload","page_download","page_frames","set_device_emulation","set_app_profile","set_timezone","run_actions"],TAB_ID_REQUIRED_ACTION_SET=new Set(TAB_ID_REQUIRED_ACTIONS);var EXTENSION_BROWSER_ACTIONS={tab_checkpoint:!0,capture_checkpoint:!0,get_requests:!0,get_logs:!0,get_events:!0,set_mock:!0,get_mocks:!0,set_rule:!0,get_rules:!0,send_request:!0,send_mtop_request:!0,browser_release:!0,page_screenshot:!0,tab_open:!0,tab_close:!0,tab_list:!0,tab_group:!0,page_click:!0,page_drag:!0,page_type:!0,page_scroll:!0,page_hover:!0,page_eval:!0,page_runtime:!0,page_inspect:!0,page_snapshot:!0,page_press:!0,page_wait:!0,page_navigate:!0,page_upload:!0,page_frames:!0,set_device_emulation:!0,set_app_profile:!0,set_timezone:!0,get_cookie:!0,set_cookie:!0,request_domain_permission:!0,run_actions:!0},BROWSER_CAPABILITY_ACTIONS={...EXTENSION_BROWSER_ACTIONS,page_download:!0};var AGENT_CHAT_MAX_IMAGE_BYTES=10*1024*1024,AGENT_CHAT_MAX_TOTAL_IMAGE_BYTES=20*1024*1024;var MEARL_NATIVE_HOST_NAMES={skills:"ai.mearl.skills",mcp:"ai.mearl.mcp"};function resolveNativeHostDirectory(options={}){let env=options.env??process.env,home=(options.homedir??os.homedir)();switch(options.platform??process.platform){case"darwin":return path2.join(home,"Library/Application Support/Google/Chrome/NativeMessagingHosts");case"linux":return path2.join(home,".config/google-chrome/NativeMessagingHosts");case"win32":return path2.join(env.PROGRAMDATA||"C:\\ProgramData","Google\\Chrome\\NativeMessagingHosts");default:throw new Error(`Unsupported platform: ${String(options.platform??process.platform)}`)}}function unregisterWindowsNativeHost(hostName){let registryKey=`HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\${hostName}`;try{execFileSync("reg",["delete",registryKey,"/f"],{stdio:"pipe"})}catch{}}function uninstallNativeHostArtifacts(options={},dependencies={}){let{mode="both",silent=!1}=options;if(mode==="both")return["skills","mcp"].map(integrationMode=>uninstallNativeHostArtifacts({...options,mode:integrationMode},dependencies)).every(Boolean);let writeLine=dependencies.writeLine??(line=>console.error(line)),log=line=>{silent||writeLine(line)};try{let existsSync=dependencies.existsSync??fs3.existsSync,platform=dependencies.platform??process.platform,hostDir=dependencies.hostDir??resolveNativeHostDirectory({env:dependencies.env,homedir:dependencies.homedir,platform}),unlinkSync=dependencies.unlinkSync??fs3.unlinkSync,unregister=dependencies.unregisterWindowsNativeHost??unregisterWindowsNativeHost,hostName=MEARL_NATIVE_HOST_NAMES[mode],launcherExtension=platform==="win32"?"cmd":"sh",artifacts=[path3.join(hostDir,`${hostName}.json`),path3.join(hostDir,`${hostName}-launcher.${launcherExtension}`)];for(let artifact of artifacts)existsSync(artifact)&&(unlinkSync(artifact),log(`✅ Removed: ${artifact}`));return platform==="win32"&&unregister(hostName),!0}catch(error){return log(`❌ Uninstall failed: ${error instanceof Error?error.message:String(error)}`),!1}}var DEFAULT_EXTENSION_ID="aoehhjnofngknnjefamjbplchbolghkm",__filename=fileURLToPath(import.meta.url),__dirname=path4.dirname(__filename),ALL_MODES=["skills","mcp"];function resolveHostDir(){return resolveNativeHostDirectory()}function resolveNativeHostPath(){let siblingPath=path4.join(__dirname,"index.js");if(fs4.existsSync(siblingPath))return siblingPath;try{return createRequire(import.meta.url).resolve("@mearl/native-host/runtime")}catch{throw new Error("Cannot locate native-host runtime entry point. Ensure @mearl/native-host is installed correctly.")}}function registerWindowsNativeHost(hostName,manifestPath){let regKey=`HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\${hostName}`;execFileSync2("reg",["add",regKey,"/ve","/t","REG_SZ","/d",manifestPath,"/f"],{stdio:"pipe"})}async function installNativeHost(options={}){let{mode="both",extensionId=DEFAULT_EXTENSION_ID,silent=!1,skipIfExists=!1}=options;if(mode==="both")return(await Promise.all(ALL_MODES.map(m=>installNativeHost({...options,mode:m})))).every(Boolean);let hostName=MEARL_NATIVE_HOST_NAMES[mode];if(!hostName)throw new Error(`Unknown mode: ${mode}. Expected 'skills' or 'mcp'.`);let log=(...args)=>{silent||console.error(...args)};try{let hostDir=resolveHostDir();if(skipIfExists){let manifestPath2=path4.join(hostDir,`${hostName}.json`);if(fs4.existsSync(manifestPath2))return log(`✅ Already installed: ${manifestPath2}`),!0}fs4.existsSync(hostDir)||(fs4.mkdirSync(hostDir,{recursive:!0}),log(`✅ Created directory: ${hostDir}`));let resolvedHostPath=resolveNativeHostPath();log(`✅ Native host path: ${resolvedHostPath}`);let launcherPath=createLauncherScript(hostDir,resolvedHostPath,hostName);log(`✅ Launcher script: ${launcherPath}`);let manifest={name:hostName,description:"Mearl Native Messaging Bridge",path:launcherPath,type:"stdio",allowed_origins:[`chrome-extension://${extensionId}/`]},manifestPath=path4.join(hostDir,`${hostName}.json`);return fs4.writeFileSync(manifestPath,JSON.stringify(manifest,null,2)),process.platform==="win32"?(registerWindowsNativeHost(hostName,manifestPath),log(`✅ Windows registry key created for: ${hostName}`)):fs4.chmodSync(manifestPath,420),log(`✅ Manifest installed: ${manifestPath}`),log(`✅ Extension ID: ${extensionId}`),log(`✅ Host name: ${hostName}`),!0}catch(error){return log(`❌ Installation failed: ${error instanceof Error?error.message:String(error)}`),error instanceof Error&&"code"in error&&error.code==="EACCES"&&log(`
|
|
7
7
|
Permission denied. Try running with sudo.`),!1}}async function uninstallNativeHost(options={},dependencies={}){return uninstallNativeHostArtifacts(options,dependencies)}async function parseNativeHostInstallArgs(argv){let normalizedArgv=argv[0]==="--init"?["init",...argv.slice(1)]:argv[0]==="--uninstall"?["uninstall",...argv.slice(1)]:argv,operation="init",mode="both",extensionId,showHelp=!1,skipIfExists=!1,index=0;if(normalizedArgv[0]==="init"||normalizedArgv[0]==="uninstall")operation=normalizedArgv[0],index=1;else if(normalizedArgv[0]&&!normalizedArgv[0].startsWith("-"))throw new Error(`Unknown command: ${normalizedArgv[0]}`);let readValue=name=>{let argument=normalizedArgv[index];if(argument===name){let value=normalizedArgv[index+1];if(value===void 0||value.startsWith("-"))throw new Error(`argument missing for option '${name}'`);return index+=1,value}return argument?.startsWith(`${name}=`)?argument.slice(name.length+1):null};for(;index<normalizedArgv.length;index+=1){let argument=normalizedArgv[index];if(argument==="--help"||argument==="-h"){showHelp=!0;continue}if(argument==="--skip-if-exists"){skipIfExists=!0;continue}let parsedMode=readValue("--mode");if(parsedMode!==null){if(parsedMode!=="skills"&&parsedMode!=="mcp"&&parsedMode!=="both")throw new Error(`Invalid --mode: ${parsedMode}. Allowed choices are skills, mcp, and both`);mode=parsedMode;continue}let parsedExtensionId=readValue("--extension-id");if(parsedExtensionId!==null){extensionId=parsedExtensionId;continue}throw new Error(argument?.startsWith("-")?`unknown option '${argument}'`:`unexpected argument '${argument}'`)}if(operation==="uninstall"&&extensionId)throw new Error("--extension-id is only available for init");if(operation==="uninstall"&&skipIfExists)throw new Error("--skip-if-exists is only available for init");return{showHelp,uninstall:operation==="uninstall",mode,...extensionId?{extensionId}:{},skipIfExists}}function printHelp(){console.error(`Usage:
|
|
8
8
|
mearl-native-host init [options]
|
|
9
9
|
mearl-native-host uninstall [options]
|