agent-device 0.11.12 → 0.11.14
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/src/32.js +2 -0
- package/dist/src/320.js +1 -1
- package/dist/src/974.js +2 -2
- package/dist/src/bin.js +67 -67
- package/dist/src/daemon.js +46 -47
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +2 -2
- package/dist/src/metro-companion.js +1 -1
- package/dist/src/metro.d.ts +1 -0
- package/package.json +1 -1
- package/dist/src/995.js +0 -1
package/dist/src/32.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"node:fs";import t from"node:path";import{fileURLToPath as n}from"node:url";import r from"node:os";import i from"node:crypto";import{PNG as a}from"pngjs";import{runCmdSync as s,emitDiagnostic as o,AppError as l}from"./818.js";let u="<wifi|airplane|location> <on|off>",c="appearance <light|dark|toggle>",d="faceid <match|nonmatch|enroll|unenroll>",p="touchid <match|nonmatch|enroll|unenroll>",m="fingerprint <match|nonmatch>",f="permission <grant|deny|reset> <camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri> [full|limited]",h="permission <grant|reset> <accessibility|screen-recording|input-monitoring>",g=`macOS supports only settings ${c} and settings ${h}. wifi|airplane|location remain unsupported on macOS.`,w=`settings ${u} | settings ${c} | settings ${d} | settings ${p} | settings ${m} | settings ${f} | settings ${h}`,x=`settings requires ${u}, ${c}, ${d}, ${p}, ${m}, ${f}, or ${h}`;function b(e){let t=e.trim().toLowerCase();return"appearance"===t||"permission"===t}function y(e){return`Unsupported macOS setting: ${e}. ${g}`}let v=["app","frontmost-app","desktop","menubar"];function S(e){let t=e?.trim().toLowerCase();if("app"===t||"frontmost-app"===t||"desktop"===t||"menubar"===t)return t;throw new l("INVALID_ARGS",`Invalid surface: ${e}. Use ${v.join("|")}.`)}function I(e){var t;let n,r=M(e.label),i=M(e.value),a=M(e.identifier),s=(t=a)&&!/^[\w.]+:id\/[\w.-]+$/i.test(t)&&!/^_?NS:\d+$/i.test(t)?a:"";return(n=A(e.type??"")).includes("textfield")||n.includes("securetextfield")||n.includes("searchfield")||n.includes("edittext")||n.includes("textview")||n.includes("textarea")?i||r||s:r||i||s}function M(e){return"string"==typeof e?e.trim():""}function A(e){let t=e.trim().replace(/XCUIElementType/gi,"").replace(/^AX/,"").toLowerCase(),n=Math.max(t.lastIndexOf("."),t.lastIndexOf("/"));return -1!==n&&(t=t.slice(n+1)),t}function $(e,t={}){let n=[],r=[];for(let i of e){let e=i.depth??0,a=i.label?.trim()||i.value?.trim()||i.identifier?.trim()||"",s=R(i.type??"Element");if("group"===s&&!a)continue;for(;n.length>0&&e<=n[n.length-1];)n.pop();let o=n.length;n.push(e),r.push({node:i,depth:o,type:s,text:N(i,o,!1,s,t)})}return r}function N(e,t,n,r,i={}){var a,s,o,l,u;let c,d,p=r??R(e.type??"Element"),m=(c=I(e),{text:c,isLargeSurface:d=function(e,t){if("text-view"===t||"text-field"===t||"search"===t)return!0;let n=A(e.type??""),r=`${e.role??""} ${e.subrole??""}`.toLowerCase();return n.includes("textview")||n.includes("textarea")||n.includes("textfield")||n.includes("securetextfield")||n.includes("searchfield")||n.includes("edittext")||r.includes("text area")||r.includes("text field")}(e,p),shouldSummarize:d&&!!(a=c)&&(a.length>80||/[\r\n]/.test(a))}),f=(s=e,o=p,l=i,u=m,l.summarizeTextSurfaces&&u.shouldSummarize&&function(e,t,n){let r=M(e.label);if(r&&r!==n)return r;let i=M(e.identifier);if(i&&!L(i)&&i!==n)return i;switch(t){case"text":case"text-view":return"Text view";case"text-field":return"Text field";case"search":return"Search field";default:return""}}(s,o,u.text)||D(s,o)),h=" ".repeat(t),g=e.ref?`@${e.ref}`:"",w=(function(e,t,n,r){let i,a=[];if(!1===e.enabled&&a.push("disabled"),!n.summarizeTextSurfaces||(!0===e.selected&&a.push("selected"),E(t)&&a.push("editable"),function(e,t){if("scroll-area"===t)return!0;let n=(e.type??"").toLowerCase(),r=`${e.role??""} ${e.subrole??""}`.toLowerCase();return n.includes("scroll")||r.includes("scroll")}(e,t)&&a.push("scrollable"),!r.shouldSummarize))return a;return a.push(`preview:"${((i=r.text.replace(/\s+/g," ").trim()).length<=48?i:`${i.slice(0,45)}...`).replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`),a.push("truncated"),[...new Set(a)]})(e,p,i,m).map(e=>` [${e}]`).join(""),x=f?` "${f}"`:"";return n?`${h}${g} [${p}]${w}`.trimEnd():`${h}${g} [${p}]${x}${w}`.trimEnd()}function D(e,t){var n,r;let i,a=e.label?.trim();if(a&&(n=t,r=a,("scroll-area"===n||"list"===n||"collection"===n||"table"===n)&&(i=r.trim().toLowerCase())&&/^(vertical|horizontal)\s+scroll\s+bar(?:,?\s*\d+\s+pages?)?$/.test(i)))return"";let s=e.value?.trim();if(E(t)){if(s)return s;if(a)return a}else if(a)return a;if(s)return s;let o=e.identifier?.trim();return!o||L(o)&&("group"===t||"image"===t||"list"===t||"collection"===t)?"":o}function R(e){let t=e.replace(/XCUIElementType/gi,"").toLowerCase(),n=e.includes(".")&&(e.startsWith("android.")||e.startsWith("androidx.")||e.startsWith("com."));switch(t.includes(".")&&(t=t.replace(/^android\.widget\./,"").replace(/^android\.view\./,"").replace(/^android\.webkit\./,"").replace(/^androidx\./,"").replace(/^com\.google\.android\./,"").replace(/^com\.android\./,""),n&&t.includes(".")&&(t=t.slice(t.lastIndexOf(".")+1))),t){case"application":return"application";case"navigationbar":return"navigation-bar";case"tabbar":return"tab-bar";case"button":case"imagebutton":return"button";case"link":return"link";case"cell":return"cell";case"statictext":case"checkedtextview":return"text";case"textfield":case"edittext":return"text-field";case"textview":return n?"text":"text-view";case"textarea":return"text-view";case"switch":return"switch";case"slider":return"slider";case"image":case"imageview":return"image";case"webview":return"webview";case"framelayout":case"linearlayout":case"relativelayout":case"constraintlayout":case"viewgroup":case"view":case"group":return"group";case"listview":case"recyclerview":return"list";case"collectionview":return"collection";case"searchfield":return"search";case"segmentedcontrol":return"segmented-control";case"window":return"window";case"checkbox":return"checkbox";case"radio":return"radio";case"menuitem":return"menu-item";case"toolbar":return"toolbar";case"scrollarea":case"scrollview":case"nestedscrollview":return"scroll-area";case"table":return"table";default:return t||"element"}}function E(e){return"text-field"===e||"text-view"===e||"search"===e}function L(e){return/^[\w.]+:id\/[\w.-]+$/i.test(e)}function _(e){let t=new Map;for(let[n,r]of e.entries())t.set(r.index,n);let n=[],r=[];for(let[i,a]of e.entries()){let e=Math.max(0,a.depth??0);for(;r.length>0&&e<=r[r.length-1].depth;)r.pop();let s="number"==typeof a.parentIndex?t.get(a.parentIndex):void 0,o="number"==typeof s&&s<i?s:r[r.length-1]?.index;n.push({...a,index:i,depth:e,parentIndex:o}),r.push({depth:e,index:i})}return n}function C(e){return new Map(e.map(e=>[e.index,e]))}function k(e){return e.label?.trim()||e.value?.trim()||e.identifier?.trim()||""}function T(e){return e.map((e,t)=>({...e,ref:`e${t+1}`}))}function j(e){let t=e.trim();return t.startsWith("@")?t.slice(1)||null:t.startsWith("e")?t:null}function P(e,t){return e.find(e=>e.ref===t)??null}function z(e){return{x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}}function O(e,t){let n=z(t),r=e.filter(e=>{var t;return!!(t=e.rect)&&Number.isFinite(t.x)&&Number.isFinite(t.y)&&Number.isFinite(t.width)&&Number.isFinite(t.height)}),i=r.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}),a=G(i.map(e=>e.rect).filter(e=>F(e,n.x,n.y)));if(a)return a;let s=G(i.map(e=>e.rect));if(s)return s;let o=G(r.map(e=>e.rect).filter(e=>F(e,n.x,n.y)));return o||null}function B(e,t){let n=Math.max(1,t.height),r=t.y,i=t.y+n,a=r+.25*n,s=i-.25*n,o=e.y+e.height/2;return o<a?Math.ceil(a-o):o>s?Math.ceil(o-s):0}function F(e,t,n){return t>=e.x&&t<=e.x+e.width&&n>=e.y&&n<=e.y+e.height}function G(e){let t=null,n=-1;for(let r of e){let e=r.width*r.height;e>n&&(t=r,n=e)}return t}function V(e,t,n,r){return Math.max(e,n)<=Math.min(t,r)}function U(e){let t=`${e??""}`.toLowerCase();return t.includes("scroll")||t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")||t.includes("collectionview")||"table"===t}function W(e){return!!U(e.type)||`${e.role??""} ${e.subrole??""}`.toLowerCase().includes("scroll")}function H(e){if(0===e.length)return{nodes:e,hiddenCount:0,summaryLines:[]};let t=C(e),n=new Set,r=[];for(let i of e){if(J(i,e,t)){!function(e,t,n){let r=e,i=new Set;for(;r&&!i.has(r.index);)i.add(r.index),t.add(r.index),r="number"==typeof r.parentIndex?n.get(r.parentIndex):void 0}(i,n,t);continue}r.push(i)}let i=function(e,t,n,r){let i=new Map,a=new Set;for(let e of t){if(!e.rect)continue;let t=K(e,n,r);if(!t?.rect)continue;let s=X(e.rect,t.rect);if(!s)continue;let o=i.get(t.index)??new Set;o.add(s),i.set(t.index,o),a.add(e.index)}return function(e,t,n,r){for(let i of e){let e=function(e){let t=function(e,t){if(!(e?.trim().toLowerCase()??"").includes("vertical scroll bar"))return null;let n=function(e){if(!e)return null;let t=/^(\d{1,3})%$/.exec(e.trim());if(!t)return null;let n=Number(t[1]);return Number.isFinite(n)?Math.max(0,Math.min(100,n)):null}(t);return null===n?null:n<=1?{above:!1,below:!0}:n>=99?{above:!0,below:!1}:{above:!0,below:!0}}(e.label,e.value);if(!t)return null;let n=new Set;return t.above&&n.add("above"),t.below&&n.add("below"),n.size>0?n:null}(i);if(!e||0===e.size)continue;let a=K(i,t,n);if(!a)continue;let s=r.get(a.index)??new Set;for(let t of e)s.add(t);r.set(a.index,s)}}(e,n,r,i),{directionsByContainer:i,coveredNodeIndexes:a}}(e,r,n,t),a=0===n.size?e:e.filter(e=>n.has(e.index));return{nodes:a.map(e=>(function(e,t){let n=t.get(e.index);if(!n||0===n.size)return e;let r=!!(!0===e.hiddenContentAbove||n.has("above"))||void 0,i=!!(!0===e.hiddenContentBelow||n.has("below"))||void 0;return{...e,hiddenContentAbove:r,hiddenContentBelow:i}})(e,i.directionsByContainer)),hiddenCount:0===n.size?0:e.length-a.length,summaryLines:function(e,t,n){let r=new Map;for(let i of e){let e=function(e,t,n){if(!e.rect)return null;let r=q(e,t,n);return r?X(e.rect,r):null}(i,t,n);if(!e)continue;let a=r.get(e)??[];a.push(i),r.set(e,a)}return["above","below"].flatMap(e=>{let t=r.get(e);if(!t||0===t.length)return[];let n=(function(e){let t=new Set,n=[];for(let r of e){let e=k(r);!e||t.has(e)||(t.add(e),n.push(e))}return n})(t).slice(0,3).map(e=>`"${e}"`),i=1===t.length?"interactive item":"interactive items",a=n.length>0?`: ${n.join(", ")}`:"";return[`[off-screen ${e}] ${t.length} ${i}${a}`]})}(r.filter(e=>!i.coveredNodeIndexes.has(e.index)&&function(e){if(!0===e.hittable)return!0;let t=(e.type??"").toLowerCase();return t.includes("button")||t.includes("link")||t.includes("textfield")||t.includes("edittext")||t.includes("searchfield")||t.includes("checkbox")||t.includes("radio")||t.includes("switch")||t.includes("menuitem")||!!k(e)}(e)),e,t)}}function J(e,t,n=C(t)){var r;if(!e.rect)return!0;let i=q(e,t,n);return!i||(r=e.rect,V(r.x,r.x+r.width,i.x,i.x+i.width)&&V(r.y,r.y+r.height,i.y,i.y+i.height))}function q(e,t,n=C(t)){let r=function(e,t){let n="number"==typeof e.parentIndex?t.get(e.parentIndex):void 0,r=new Set;for(;n&&!r.has(n.index);){if(r.add(n.index),n.rect&&W(n))return n.rect;n="number"==typeof n.parentIndex?t.get(n.parentIndex):void 0}return null}(e,n);return r||O(t,e.rect??{x:0,y:0,width:0,height:0})}function X(e,t){return e.y+e.height<=t.y?"above":e.y>=t.y+t.height?"below":null}function K(e,t,n){let r="number"==typeof e.parentIndex?n.get(e.parentIndex):void 0,i=new Set;for(;r&&!i.has(r.index);){if(i.add(r.index),t.has(r.index)&&W(r))return r;r="number"==typeof r.parentIndex?n.get(r.parentIndex):void 0}return null}function Y(){try{let n=Z();return JSON.parse(e.readFileSync(t.join(n,"package.json"),"utf8")).version??"0.0.0"}catch{return"0.0.0"}}function Z(){let r=t.dirname(n(import.meta.url)),i=r;for(let n=0;n<6;n+=1){let n=t.join(i,"package.json");if(e.existsSync(n))return i;i=t.dirname(i)}return r}function Q(e){return e?{message:e}:{}}function ee(e,t){return t?{...e,message:t}:e}function et(e){return"string"==typeof e?.message&&e.message.length>0?e.message:null}let en=[/(^|[/\s"'=])dist\/src\/daemon\.js($|[\s"'])/,/(^|[/\s"'=])src\/daemon\.ts($|[\s"'])/];function er(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return"EPERM"===e.code}}function ei(e){if(!Number.isInteger(e)||e<=0)return null;try{let t=s("ps",["-p",String(e),"-o","lstart="],{allowFailure:!0,timeoutMs:1e3});if(0!==t.exitCode)return null;let n=t.stdout.trim();return n.length>0?n:null}catch{return null}}function ea(e){if(!Number.isInteger(e)||e<=0)return null;try{let t=s("ps",["-p",String(e),"-o","command="],{allowFailure:!0,timeoutMs:1e3});if(0!==t.exitCode)return null;let n=t.stdout.trim();return n.length>0?n:null}catch{return null}}function es(e,t){let n;if(!er(e))return!1;if(t){let n=ei(e);if(!n||n!==t)return!1}let r=ea(e);return!!r&&!!(n=r.toLowerCase().replaceAll("\\","/")).includes("agent-device")&&en.some(e=>e.test(n))}function eo(e,t){try{return process.kill(e,t),!0}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return!1;throw t}}async function el(e,t){if(!er(e))return!0;let n=Date.now();for(;Date.now()-n<t;)if(await new Promise(e=>setTimeout(e,50)),!er(e))return!0;return!er(e)}async function eu(e,t){!es(e,t.expectedStartTime)||!eo(e,"SIGTERM")||await el(e,t.termTimeoutMs)||eo(e,"SIGKILL")&&await el(e,t.killTimeoutMs)}function ec(e){return e?.HOME?.trim()||r.homedir()}function ed(e,n={}){return"~"===e?ec(n.env):e.startsWith("~/")?t.join(ec(n.env),e.slice(2)):e}function ep(e,n={}){let r=ed(e,n);return t.isAbsolute(r)?r:t.resolve(n.cwd??process.cwd(),r)}function em(e){let n,r=(n=(e??"").trim())?ep(n):t.join(ed("~"),".agent-device");return{baseDir:r,infoPath:t.join(r,"daemon.json"),lockPath:t.join(r,"daemon.lock"),logPath:t.join(r,"daemon.log"),sessionsDir:t.join(r,"sessions")}}function ef(e){let t=(e??"").trim().toLowerCase();return"http"===t?"http":"dual"===t?"dual":"socket"}function eh(e){let t=(e??"").trim().toLowerCase();return"auto"===t?"auto":"socket"===t?"socket":"http"===t?"http":"auto"}function eg(e){return"tenant"===(e??"").trim().toLowerCase()?"tenant":"none"}function ew(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}let ex=/(?:^|[^\w$.])(?:import|export)\s+(?:type\s+)?(?:[^'"`]*?\s+from\s+)?['"]([^'"]+)['"]/gm,eb=/import\(\s*['"]([^'"]+)['"]\s*\)/gm,ey=[".ts",".tsx",".js",".jsx",".mjs",".cjs"];function ev(){let e=process.argv[1];return e?eS(e):"unknown"}function eS(n,r=Z()){try{let a=t.resolve(r),s=[t.resolve(n)],o=new Set,l=[];for(;s.length>0;){let n=s.pop();if(!n||o.has(n))continue;o.add(n);let r=e.statSync(n);if(!r.isFile())continue;let i=t.relative(a,n)||n;l.push(`${i}:${r.size}:${Math.trunc(r.mtimeMs)}`);let u=e.readFileSync(n,"utf8");for(let e of function(e){let t=new Set;return eI(e,ex,t),eI(e,eb,t),[...t]}(u)){let r=function(e,n){let r=t.resolve(t.dirname(e),n),i=eM(r);if(i)return i;for(let e of ey){let t=eM(`${r}${e}`);if(t)return t}for(let e of ey){let n=eM(t.join(r,`index${e}`));if(n)return n}return null}(n,e);r&&s.push(r)}}let u=l.sort().join("|"),c=i.createHash("sha1").update(u).digest("hex");return`graph:${l.length}:${c}`}catch{return"unknown"}}function eI(e,t,n){t.lastIndex=0;let r=null;for(;null!==(r=t.exec(e));){let e=r[1]?.trim();e?.startsWith(".")&&n.add(e)}}function eM(t){try{return e.statSync(t).isFile()?t:null}catch{return null}}let eA=100,e$=new Set(["batch","replay"]),eN=new Set(["command","positionals","flags","runtime"]);function eD(e){let t;try{t=JSON.parse(e)}catch{throw new l("INVALID_ARGS","Batch steps must be valid JSON.")}if(!Array.isArray(t)||0===t.length)throw new l("INVALID_ARGS","Batch steps must be a non-empty JSON array.");return t}function eR(e,t){if(!Array.isArray(e)||0===e.length)throw new l("INVALID_ARGS","batch requires a non-empty batchSteps array.");if(e.length>t)throw new l("INVALID_ARGS",`batch has ${e.length} steps; max allowed is ${t}.`);let n=[];for(let t=0;t<e.length;t+=1){let r=e[t];if(!r||"object"!=typeof r)throw new l("INVALID_ARGS",`Invalid batch step at index ${t}.`);let i=Object.keys(r).filter(e=>!eN.has(e));if(i.length>0){let e=i.map(e=>`"${e}"`).join(", ");throw new l("INVALID_ARGS",`Batch step ${t+1} has unknown field(s): ${e}. Allowed fields: command, positionals, flags, runtime.`)}let a="string"==typeof r.command?r.command.trim().toLowerCase():"";if(!a)throw new l("INVALID_ARGS",`Batch step ${t+1} requires command.`);if(e$.has(a))throw new l("INVALID_ARGS",`Batch step ${t+1} cannot run ${a}.`);if(void 0!==r.positionals&&!Array.isArray(r.positionals))throw new l("INVALID_ARGS",`Batch step ${t+1} positionals must be an array.`);let s=r.positionals??[];if(s.some(e=>"string"!=typeof e))throw new l("INVALID_ARGS",`Batch step ${t+1} positionals must contain only strings.`);if(void 0!==r.flags&&("object"!=typeof r.flags||Array.isArray(r.flags)||!r.flags))throw new l("INVALID_ARGS",`Batch step ${t+1} flags must be an object.`);if(void 0!==r.runtime&&("object"!=typeof r.runtime||Array.isArray(r.runtime)||!r.runtime))throw new l("INVALID_ARGS",`Batch step ${t+1} runtime must be an object.`);n.push({command:a,positionals:s,flags:r.flags??{},runtime:r.runtime})}return n}function eE(e){let t=e.appId??e.bundleId??e.packageName;return{session:e.session,appId:t,appBundleId:e.bundleId,package:e.packageName}}function eL(e,t,n){return{deviceId:t,deviceName:n,..."android"===e?{serial:t}:"ios"===e?{udid:t}:{}}}function e_(e,t={}){let n=t.includeAndroidSerial??!0;return{platform:e.platform,target:e.target,device:e.name,id:e.id,..."ios"===e.platform?{device_udid:e.ios?.udid??e.id,ios_simulator_device_set:e.ios?.simulatorSetPath??null}:{},..."android"===e.platform&&n?{serial:e.android?.serial??e.id}:{}}}function eC(e){return{name:e.name,...e_(e.device,{includeAndroidSerial:!1}),createdAt:e.createdAt}}function ek(e){return{platform:e.platform,id:e.id,name:e.name,kind:e.kind,target:e.target,..."boolean"==typeof e.booted?{booted:e.booted}:{}}}function eT(e){let t=e.created?"Created":"Reused",n=e.booted?" (booted)":"";return ee({udid:e.udid,device:e.device,runtime:e.runtime,ios_simulator_device_set:e.iosSimulatorDeviceSet??null,created:e.created,booted:e.booted},`${t}: ${e.device} ${e.udid}${n}`)}function ej(e){return e.bundleId??e.package??e.app}function eP(e){return ee({app:e.app,appPath:e.appPath,platform:e.platform,...e.appId?{appId:e.appId}:{},...e.bundleId?{bundleId:e.bundleId}:{},...e.package?{package:e.package}:{}},`Installed: ${ej(e)}`)}function ez(e){return e.appName??e.bundleId??e.packageName??e.launchTarget}function eO(e){return ee({launchTarget:e.launchTarget,...e.appName?{appName:e.appName}:{},...e.appId?{appId:e.appId}:{},...e.bundleId?{bundleId:e.bundleId}:{},...e.packageName?{package:e.packageName}:{},...e.installablePath?{installablePath:e.installablePath}:{},...e.archivePath?{archivePath:e.archivePath}:{},...e.materializationId?{materializationId:e.materializationId}:{},...e.materializationExpiresAt?{materializationExpiresAt:e.materializationExpiresAt}:{}},`Installed: ${ez(e)}`)}function eB(e){let t=e.appName??e.appBundleId??e.session;return ee({session:e.session,...e.appName?{appName:e.appName}:{},...e.appBundleId?{appBundleId:e.appBundleId}:{},...e.startup?{startup:e.startup}:{},...e.runtime?{runtime:e.runtime}:{},...e.device?e_(e.device):{}},t?`Opened: ${t}`:"Opened")}function eF(e){return{session:e.session,...e.shutdown?{shutdown:e.shutdown}:{},...Q(e.session?`Closed: ${e.session}`:"Closed")}}function eG(e){return{nodes:e.nodes,truncated:e.truncated,...e.appName?{appName:e.appName}:{},...e.appBundleId?{appBundleId:e.appBundleId}:{},...e.visibility?{visibility:e.visibility}:{},...e.warnings&&e.warnings.length>0?{warnings:e.warnings}:{}}}function eV(e,t){try{return a.sync.read(e)}catch(e){throw new l("COMMAND_FAILED",`Failed to decode ${t} as PNG`,{label:t,reason:e instanceof Error?e.message:String(e)})}}let eU=eW(process.env.AGENT_DEVICE_RETRY_LOGS);function eW(e){return["1","true","yes","on"].includes((e??"").trim().toLowerCase())}let eH={ios_boot:{startupMs:12e4,operationMs:2e4,totalMs:12e4},ios_runner_connect:{startupMs:12e4,operationMs:15e3,totalMs:12e4},android_boot:{startupMs:6e4,operationMs:1e4,totalMs:6e4}};class eJ{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new eJ(t,e)}remainingMs(e=Date.now()){return Math.max(0,this.expiresAtMs-e)}elapsedMs(e=Date.now()){return Math.max(0,e-this.startedAtMs)}isExpired(e=Date.now()){return 0>=this.remainingMs(e)}}async function eq(e,t={},n={}){let r,i={maxAttempts:t.maxAttempts??3,baseDelayMs:t.baseDelayMs??200,maxDelayMs:t.maxDelayMs??2e3,jitter:t.jitter??.2,shouldRetry:t.shouldRetry};for(let t=1;t<=i.maxAttempts;t+=1){if(n.signal?.aborted)throw new l("COMMAND_FAILED","request canceled",{reason:"request_canceled"});if(n.deadline?.isExpired()&&t>1)break;try{let r=await e({attempt:t,maxAttempts:i.maxAttempts,deadline:n.deadline});return n.onEvent?.({phase:n.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs()}),eK({phase:n.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs()}),r}catch(u){r=u;let e=n.classifyReason?.(u),a={phase:n.phase,event:"attempt_failed",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs(),reason:e};if(n.onEvent?.(a),eK(a),t>=i.maxAttempts||i.shouldRetry&&!i.shouldRetry(u,t))break;let s=function(e,t,n,r){let i=Math.min(t,e*2**(r-1));return Math.max(0,i+i*n*(2*Math.random()-1))}(i.baseDelayMs,i.maxDelayMs,i.jitter,t),o=n.deadline?Math.min(s,n.deadline.remainingMs()):s;if(o<=0)break;let l={phase:n.phase,event:"retry_scheduled",attempt:t,maxAttempts:i.maxAttempts,delayMs:o,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs(),reason:e};n.onEvent?.(l),eK(l),await function(e,t){return new Promise(n=>{if(t?.aborted)return void n();let r=!1,i=()=>{r||(r=!0,t&&t.removeEventListener("abort",s),n())},a=setTimeout(i,e);function s(){clearTimeout(a),i()}t&&t.addEventListener("abort",s,{once:!0})})}(o,n.signal)}}let a={phase:n.phase,event:"exhausted",attempt:i.maxAttempts,maxAttempts:i.maxAttempts,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs(),reason:n.classifyReason?.(r)};if(n.onEvent?.(a),eK(a),r)throw r;throw new l("COMMAND_FAILED","retry failed")}async function eX(e,t={}){return eq(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function eK(e){o({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),eU&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
|
|
2
|
+
`)}export{eA as DEFAULT_BATCH_MAX_STEPS,eJ as Deadline,v as SESSION_SURFACES,x as SETTINGS_INVALID_ARGS_MESSAGE,w as SETTINGS_USAGE_OVERRIDE,eH as TIMEOUT_PROFILES,T as attachRefs,eE as buildAppIdentifiers,eL as buildDeviceIdentifiers,H as buildMobileSnapshotPresentation,$ as buildSnapshotDisplayLines,z as centerOfRect,eS as computeDaemonCodeSignature,F as containsPoint,eV as decodePng,D as displayLabel,k as displayNodeLabel,B as distanceFromSafeViewportBand,ed as expandUserHomePath,I as extractReadableText,P as findNodeByRef,Z as findProjectRoot,R as formatRole,N as formatSnapshotLine,y as getUnsupportedMacOsSettingMessage,es as isAgentDeviceDaemonProcess,eW as isEnvTruthy,b as isMacOsSettingSupported,J as isNodeVisibleInEffectiveViewport,er as isProcessAlive,U as isScrollableType,j as normalizeRef,_ as normalizeSnapshotTree,ew as normalizeTenantId,eD as parseBatchStepsJson,S as parseSessionSurface,G as pickLargestRect,et as readCommandMessage,ea as readProcessCommand,ei as readProcessStartTime,Y as readVersion,ev as resolveDaemonCodeSignature,em as resolveDaemonPaths,ef as resolveDaemonServerMode,eh as resolveDaemonTransportPreference,ej as resolveDeployResultTarget,q as resolveEffectiveViewportRect,ez as resolveInstallFromSourceResultTarget,eg as resolveSessionIsolationMode,ep as resolveUserPath,O as resolveViewportRect,eq as retryWithPolicy,eF as serializeCloseResult,eP as serializeDeployResult,ek as serializeDevice,eT as serializeEnsureSimulatorResult,eO as serializeInstallFromSourceResult,eB as serializeOpenResult,eC as serializeSessionListEntry,eG as serializeSnapshotResult,eu as stopProcessForTakeover,Q as successText,eR as validateAndNormalizeBatchSteps,el as waitForProcessExit,eX as withRetry,ee as withSuccessText};
|
package/dist/src/320.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
let E="--agent-device-run-metro-companion",_="AGENT_DEVICE_METRO_COMPANION_SERVER_BASE_URL",e="AGENT_DEVICE_METRO_COMPANION_BEARER_TOKEN",
|
|
1
|
+
let E="--agent-device-run-metro-companion",_="AGENT_DEVICE_METRO_COMPANION_SERVER_BASE_URL",e="AGENT_DEVICE_METRO_COMPANION_BEARER_TOKEN",A="AGENT_DEVICE_METRO_COMPANION_LOCAL_BASE_URL",N="AGENT_DEVICE_METRO_COMPANION_LAUNCH_URL",R="AGENT_DEVICE_METRO_COMPANION_STATE_PATH";function O(E){let _=E.length;for(;_>0&&47===E.charCodeAt(_-1);)_-=1;return _===E.length?E:E.slice(0,_)}function r(E,_){let e=new URL(`${O(E)}/index.bundle`);return e.searchParams.set("platform",_),e.searchParams.set("dev","true"),e.searchParams.set("minify","false"),e.toString()}export{e as ENV_BEARER_TOKEN,N as ENV_LAUNCH_URL,A as ENV_LOCAL_BASE_URL,_ as ENV_SERVER_BASE_URL,R as ENV_STATE_PATH,E as METRO_COMPANION_RUN_ARG,r as buildBundleUrl,O as normalizeBaseUrl};
|
package/dist/src/974.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"node:fs";import"node:fs/promises";import t from"node:path";import{spawn as r,spawnSync as n}from"node:child_process";import{createHash as o}from"node:crypto";import{fileURLToPath as i}from"node:url";import{resolveUserPath as a,AppError as s}from"./957.js";let l=/^[A-Za-z0-9][A-Za-z0-9._+-]*$/;function u(e,t,r={}){let o=m(e),i=n(o,t,{cwd:r.cwd,env:r.env,stdio:["pipe","pipe","pipe"],encoding:r.binaryStdout?void 0:"utf8",input:r.stdin,timeout:d(r.timeoutMs),shell:!1});if(i.error){let n=i.error.code;if("ETIMEDOUT"===n)throw new s("COMMAND_FAILED",`${o} timed out after ${d(r.timeoutMs)}ms`,{cmd:e,args:t,timeoutMs:d(r.timeoutMs)},i.error);if("ENOENT"===n)throw new s("TOOL_MISSING",`${o} not found in PATH`,{cmd:e},i.error);throw new s("COMMAND_FAILED",`Failed to run ${o}`,{cmd:e,args:t},i.error)}let a=r.binaryStdout?Buffer.isBuffer(i.stdout)?i.stdout:Buffer.from(i.stdout??""):void 0,l=r.binaryStdout?"":"string"==typeof i.stdout?i.stdout:(i.stdout??"").toString(),c="string"==typeof i.stderr?i.stderr:(i.stderr??"").toString(),p=i.status??1;if(0!==p&&!r.allowFailure)throw new s("COMMAND_FAILED",`${o} exited with code ${p}`,{cmd:e,args:t,stdout:l,stderr:c,exitCode:p,processExitError:!0});return{stdout:l,stderr:c,exitCode:p,stdoutBuffer:a}}function c(e,t,n={}){let o=r(m(e),t,{cwd:n.cwd,env:n.env,stdio:n.stdio??"ignore",detached:!0,shell:!1});return o.unref(),o.pid??0}function m(e){var r;let n,o=(r={allowRelativePath:!0},!(n=e.trim())||n.includes("\0")?null:t.isAbsolute(n)?n:n.includes("/")||n.includes("\\")?r.allowRelativePath?n:null:l.test(n)?n:null);if(!o)throw new s("INVALID_ARGS",`Invalid executable command: ${JSON.stringify(e)}`,{cmd:e});return o}function d(e){if(!Number.isFinite(e))return;let t=Math.floor(e);if(!(t<=0))return t}let p=[/(^|[/\s"'=])dist\/src\/daemon\.js($|[\s"'])/,/(^|[/\s"'=])src\/daemon\.ts($|[\s"'])/];function f(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return"EPERM"===e.code}}function h(e){if(!Number.isInteger(e)||e<=0)return null;try{let t=u("ps",["-p",String(e),"-o","lstart="],{allowFailure:!0,timeoutMs:1e3});if(0!==t.exitCode)return null;let r=t.stdout.trim();return r.length>0?r:null}catch{return null}}function g(e){if(!Number.isInteger(e)||e<=0)return null;try{let t=u("ps",["-p",String(e),"-o","command="],{allowFailure:!0,timeoutMs:1e3});if(0!==t.exitCode)return null;let r=t.stdout.trim();return r.length>0?r:null}catch{return null}}function y(e,t){let r;if(!f(e))return!1;if(t){let r=h(e);if(!r||r!==t)return!1}let n=g(e);return!!n&&!!(r=n.toLowerCase().replaceAll("\\","/")).includes("agent-device")&&p.some(e=>e.test(r))}function b(e,t){try{return process.kill(e,t),!0}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return!1;throw t}}async function w(e,t){if(!f(e))return!0;let r=Date.now();for(;Date.now()-r<t;)if(await new Promise(e=>setTimeout(e,50)),!f(e))return!0;return!f(e)}async function E(e,t){!y(e,t.expectedStartTime)||!b(e,"SIGTERM")||await w(e,t.termTimeoutMs)||b(e,"SIGKILL")&&await w(e,t.killTimeoutMs)}let S="--agent-device-run-metro-companion",_="AGENT_DEVICE_METRO_COMPANION_LAUNCH_URL";function M(e){let t=e.length;for(;t>0&&47===e.charCodeAt(t-1);)t-=1;return t===e.length?e:e.slice(0,t)}function P(e,t){let r=new URL(`${M(e)}/index.bundle`);return r.searchParams.set("platform",t),r.searchParams.set("dev","true"),r.searchParams.set("minify","false"),r.toString()}function
|
|
2
|
-
`,"utf8")}function k(t){try{e.unlinkSync(t)}catch{}}function I(e){return e.includes(S)}function R(e){return v(e.consumerKey)??v(e.profileKey)??null}function $(e,t){return!t||e.consumers.includes(t)?e:{...e,consumers:[...e.consumers,t]}}async function x(e){if(!f(e.pid))return;let t=g(e.pid);if(t&&I(t)){try{process.kill(e.pid,"SIGTERM")}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return;throw t}if(!await w(e.pid,1e3)){try{process.kill(e.pid,"SIGKILL")}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return;throw t}await w(e.pid,1e3)}}}async function D(r){let n=R(r),o=A(r.projectRoot,r.profileKey),a=N(o.statePath);if(a&&function(e,t){if(!f(e.pid))return!1;if(e.startTime){let t=h(e.pid);if(!t||t!==e.startTime)return!1}let r=g(e.pid);return!!r&&!!I(r)&&e.serverBaseUrl===M(t.serverBaseUrl)&&e.localBaseUrl===M(t.localBaseUrl)&&e.launchUrl===v(t.launchUrl)&&e.tokenHash===U(t.bearerToken)}(a,r)){let e=$(a,n);return e!==a&&T(o.statePath,e),{pid:a.pid,spawned:!1,statePath:o.statePath,logPath:o.logPath}}a&&(await x(a),k(o.statePath));let s=function(r,n){let o=function(){let r=i(import.meta.url),n=t.extname(r)||".js",o=t.join(t.dirname(r),`metro-companion${n}`);if(!e.existsSync(o))throw Error(`Metro companion entrypoint not found at ${o}. Rebuild the package to include the companion worker entry.`);return o}(),a=o.endsWith(".ts")?["--experimental-strip-types"]:[];e.mkdirSync(t.dirname(n),{recursive:!0});let s=e.openSync(n,"a"),l=0;try{let e;l=c(process.execPath,[...a,o,S],{env:(e={...r.env??process.env,AGENT_DEVICE_METRO_COMPANION_SERVER_BASE_URL:M(r.serverBaseUrl),AGENT_DEVICE_METRO_COMPANION_BEARER_TOKEN:r.bearerToken,AGENT_DEVICE_METRO_COMPANION_LOCAL_BASE_URL:M(r.localBaseUrl)},r.launchUrl?.trim()?e[_]=r.launchUrl.trim():delete e[_],e),stdio:["ignore",s,s]})}finally{e.closeSync(s)}if(!Number.isInteger(l)||l<=0)throw Error("Failed to start Metro companion process.");return{pid:l,startTime:h(l)??void 0,command:g(l)??void 0,serverBaseUrl:M(r.serverBaseUrl),localBaseUrl:M(r.localBaseUrl),launchUrl:v(r.launchUrl),tokenHash:U(r.bearerToken),consumers:[]}}(r,o.logPath);return T(o.statePath,$(s,n)),{pid:s.pid,spawned:!0,statePath:o.statePath,logPath:o.logPath}}async function O(e){let t=R(e),r=A(e.projectRoot,e.profileKey),n=N(r.statePath);if(!n)return k(r.statePath),{stopped:!1,statePath:r.statePath};let o=t?{...n,consumers:n.consumers.filter(e=>e!==t)}:{...n,consumers:[]};return o.consumers.length>0?(T(r.statePath,o),{stopped:!1,statePath:r.statePath}):(await x(n),k(r.statePath),{stopped:!0,statePath:r.statePath})}function C(e){return"string"==typeof e&&e.trim()?M(e.trim()):""}function B(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function j(e,t,r){return a(e,{env:t,cwd:r})}function L(t){try{return e.accessSync(t,e.constants.F_OK),!0}catch{return!1}}function F(e,t,r){if(null==e||""===e)return t;let n=Number.parseInt(String(e),10);return Number.isInteger(n)?Math.max(n,r):t}function G(e,t){return{platform:t,bundleUrl:P(e,t)}}function H(e,t){return{platform:t,metroHost:B(e?.metro_host),metroPort:e?.metro_port,bundleUrl:B(e?.metro_bundle_url),launchUrl:B(e?.launch_url)}}async function K(e){await new Promise(t=>setTimeout(t,e))}async function V(e,t,r={}){try{let n=await fetch(e,{headers:r,signal:AbortSignal.timeout(t)});return{ok:n.ok,status:n.status,body:await n.text()}}catch(r){if(r instanceof Error&&"TimeoutError"===r.name)throw Error(`Timed out fetching ${e} after ${t}ms`);throw r}}async function J(e,t){try{let r=await V(e,t);return r.ok&&r.body.includes("packager-status:running")}catch{return!1}}function q(e,t){let r=Error(e);return r.retryable=t,r}async function z(e){var t,r,n,o;let i;try{i=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:"POST",headers:(t=e.baseUrl,r=e.bearerToken,{Authorization:`Bearer ${r}`,"Content-Type":"application/json",...t.includes("ngrok")?{"ngrok-skip-browser-warning":"1"}:{}}),body:JSON.stringify({ios_runtime:e.runtime,timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(t){if(t instanceof Error&&"TimeoutError"===t.name)throw q(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0);throw q(t instanceof Error?t.message:String(t),!0)}let a=await i.text(),s=a?JSON.parse(a):{};if(!i.ok)throw q(`/api/metro/bridge failed (${i.status}): ${JSON.stringify(s)}`,(n=i.status,!!(n>=500||408===n||425===n||429===n||JSON.stringify(s).includes("Metro companion is not connected"))));return{enabled:(o=s.data??s).enabled,baseUrl:o.base_url,statusUrl:o.status_url??"",bundleUrl:o.bundle_url??"",iosRuntime:H(o.ios_runtime,"ios"),androidRuntime:H(o.android_runtime,"android"),upstream:{bundleUrl:o.upstream.bundle_url??"",host:o.upstream.host??"",port:o.upstream.port??0,statusUrl:o.upstream.status_url??""},probe:{reachable:o.probe.reachable,statusCode:o.probe.status_code,latencyMs:o.probe.latency_ms,detail:o.probe.detail}}}function Z(e,t,r,n,o){let i=[`Metro bridge is required for this run but could not be configured via ${e}/api/metro/bridge.`];return t&&i.push(`bridgeError=${t}`),r?.probe.reachable===!1&&i.push(`bridgeProbe=${r.probe.detail||`unreachable (status ${r.probe.statusCode||0})`}`),n&&n!==t&&i.push(`initialBridgeError=${n}`),o&&i.push(`metroCompanionLog=${o}`),i.join(" ")}async function W(e,t,r){let n=Date.now()+t;for(;Date.now()<n;){let t=Math.min(r,Math.max(n-Date.now(),1));if(await J(e,t))return!0;let o=Math.min(500,Math.max(n-Date.now(),0));o>0&&await K(o)}return!1}async function X(e){let t=Date.now()+e.startupTimeoutMs,r=null,n=null;for(;Date.now()<t;){try{let t=await z({baseUrl:e.baseUrl,bearerToken:e.bearerToken,runtime:e.runtime,timeoutMs:e.probeTimeoutMs});if(!1!==t.probe.reachable)return t;r=t,n=null}catch(e){if(n=e instanceof Error?e.message:String(e),!(e&&"object"==typeof e&&"retryable"in e&&!0===e.retryable))break}let o=Math.min(1e3,Math.max(t-Date.now(),0));o>0&&await K(o)}throw Error(Z(e.baseUrl,n,r,e.initialBridgeError,e.companionLogPath))}async function Y(r={}){let n=r.env??process.env,o=process.cwd(),i=j(r.projectRoot??o,n,o),a=function(r,n){if("auto"!==n)return n;let o=function(r){let n=t.join(r,"package.json");if(!L(n))throw new s("INVALID_ARGS",`package.json not found at ${n}`);return JSON.parse(e.readFileSync(n,"utf8"))}(r);return"string"==typeof({...o.dependencies??{},...o.devDependencies??{}}).expo?"expo":"react-native"}(i,r.kind??"auto"),l=function(e){if(null==e||""===e)return 8081;let t=Number.parseInt(String(e),10);if(!Number.isInteger(t)||t<1||t>65535)throw new s("INVALID_ARGS",`Invalid Metro port: ${String(e)}. Use 1-65535.`);return t}(r.metroPort??8081),m=B(r.listenHost)??"0.0.0.0",d=B(r.statusHost)??"127.0.0.1",p=C(r.publicBaseUrl),f=F(r.startupTimeoutMs,18e4,3e4),h=F(r.probeTimeoutMs,1e4,1e3),g=r.reuseExisting??!0,y=r.installDependenciesIfNeeded??!0,b=r.runtimeFilePath?j(r.runtimeFilePath,n,o):null,w=j(r.logPath??t.join(i,".agent-device","metro.log"),n,o);if(!p)throw new s("INVALID_ARGS","metro prepare requires --public-base-url <url>.");let{proxyEnabled:E,proxyBaseUrl:S,proxyBearerToken:_}=function(e,t){if(e&&!t)throw new s("INVALID_ARGS","metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_PROXY_TOKEN.");if(!e&&t)throw new s("INVALID_ARGS","metro prepare requires --proxy-base-url when proxy auth is provided.");return{proxyEnabled:!!(e&&t),proxyBaseUrl:e,proxyBearerToken:t}}(C(r.proxyBaseUrl),B(r.proxyBearerToken)??""),M=y?function(r,n){if(function(t){try{return e.statSync(t).isDirectory()}catch{return!1}}(t.join(r,"node_modules")))return{installed:!1};let o=L(t.join(r,"pnpm-lock.yaml"))?{command:"pnpm",installArgs:["install"]}:L(t.join(r,"yarn.lock"))?{command:"yarn",installArgs:["install"]}:{command:"npm",installArgs:["install"]};return u(o.command,o.installArgs,{cwd:r,env:n}),{installed:!0,packageManager:o.command}}(i,n):{installed:!1},P=`http://${d}:${l}/status`,U=!1,v=!1,A=0;if(g&&await J(P,h))v=!0;else if(U=!0,A=function(r,n,o,i,a,s){let l="expo"===n?{command:"npx",installArgs:["expo","start","--host","lan","--port",String(o)]}:{command:"npx",installArgs:["react-native","start","--host",i,"--port",String(o)]};e.mkdirSync(t.dirname(a),{recursive:!0});let u=e.openSync(a,"a"),m=0;try{m=c(l.command,l.installArgs,{cwd:r,env:s,stdio:["ignore",u,u]})}finally{e.closeSync(u)}if(!Number.isInteger(m)||m<=0)throw Error("Failed to start Metro. Expected a detached child PID.");return{pid:m}}(i,a,l,m,w,n).pid,!await W(P,f,h))throw Error(`Metro did not become ready at ${P} within ${f}ms. Check ${w}.`);let N=G(p,"ios"),T=G(p,"android"),k=null,I=null;if(E)try{k=await z({baseUrl:S,bearerToken:_,runtime:{metro_bundle_url:N.bundleUrl},timeoutMs:h})}catch(e){I=e instanceof Error?e.message:String(e)}if(E&&(!k||!1===k.probe.reachable)){let e;try{e=(await D({projectRoot:i,serverBaseUrl:S,bearerToken:_,localBaseUrl:`http://${d}:${l}`,launchUrl:B(r.launchUrl),profileKey:B(r.companionProfileKey),consumerKey:B(r.companionConsumerKey),env:n})).logPath}catch(e){throw Error(Z(S,e instanceof Error?e.message:String(e),k,I))}try{k=await X({baseUrl:S,bearerToken:_,runtime:{metro_bundle_url:N.bundleUrl},probeTimeoutMs:h,startupTimeoutMs:f,initialBridgeError:I,companionLogPath:e})}catch(e){throw e instanceof Error?e:Error(String(e))}}let R=k?.iosRuntime??N,$=k?.androidRuntime??T,x={projectRoot:i,kind:a,dependenciesInstalled:M.installed,packageManager:M.packageManager??null,started:U,reused:v,pid:A,logPath:w,statusUrl:P,runtimeFilePath:b,iosRuntime:R,androidRuntime:$,bridge:k};return b&&(e.mkdirSync(t.dirname(b),{recursive:!0}),e.writeFileSync(b,JSON.stringify(x,null,2))),x}export{P as buildBundleUrl,G as buildMetroRuntimeHints,D as ensureMetroCompanion,y as isAgentDeviceDaemonProcess,M as normalizeBaseUrl,Y as prepareMetroRuntime,c as runCmdDetached,u as runCmdSync,O as stopMetroCompanion,E as stopProcessForTakeover};
|
|
1
|
+
import e from"node:fs";import"node:fs/promises";import t from"node:path";import{spawn as r,spawnSync as n}from"node:child_process";import{createHash as o}from"node:crypto";import{fileURLToPath as i}from"node:url";import{resolveUserPath as a,AppError as s}from"./957.js";let l=/^[A-Za-z0-9][A-Za-z0-9._+-]*$/;function u(e,t,r={}){let o=m(e),i=n(o,t,{cwd:r.cwd,env:r.env,stdio:["pipe","pipe","pipe"],encoding:r.binaryStdout?void 0:"utf8",input:r.stdin,timeout:d(r.timeoutMs),shell:!1});if(i.error){let n=i.error.code;if("ETIMEDOUT"===n)throw new s("COMMAND_FAILED",`${o} timed out after ${d(r.timeoutMs)}ms`,{cmd:e,args:t,timeoutMs:d(r.timeoutMs)},i.error);if("ENOENT"===n)throw new s("TOOL_MISSING",`${o} not found in PATH`,{cmd:e},i.error);throw new s("COMMAND_FAILED",`Failed to run ${o}`,{cmd:e,args:t},i.error)}let a=r.binaryStdout?Buffer.isBuffer(i.stdout)?i.stdout:Buffer.from(i.stdout??""):void 0,l=r.binaryStdout?"":"string"==typeof i.stdout?i.stdout:(i.stdout??"").toString(),c="string"==typeof i.stderr?i.stderr:(i.stderr??"").toString(),p=i.status??1;if(0!==p&&!r.allowFailure)throw new s("COMMAND_FAILED",`${o} exited with code ${p}`,{cmd:e,args:t,stdout:l,stderr:c,exitCode:p,processExitError:!0});return{stdout:l,stderr:c,exitCode:p,stdoutBuffer:a}}function c(e,t,n={}){let o=r(m(e),t,{cwd:n.cwd,env:n.env,stdio:n.stdio??"ignore",detached:!0,shell:!1});return o.unref(),o.pid??0}function m(e){var r;let n,o=(r={allowRelativePath:!0},!(n=e.trim())||n.includes("\0")?null:t.isAbsolute(n)?n:n.includes("/")||n.includes("\\")?r.allowRelativePath?n:null:l.test(n)?n:null);if(!o)throw new s("INVALID_ARGS",`Invalid executable command: ${JSON.stringify(e)}`,{cmd:e});return o}function d(e){if(!Number.isFinite(e))return;let t=Math.floor(e);if(!(t<=0))return t}let p=[/(^|[/\s"'=])dist\/src\/daemon\.js($|[\s"'])/,/(^|[/\s"'=])src\/daemon\.ts($|[\s"'])/];function f(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return"EPERM"===e.code}}function h(e){if(!Number.isInteger(e)||e<=0)return null;try{let t=u("ps",["-p",String(e),"-o","lstart="],{allowFailure:!0,timeoutMs:1e3});if(0!==t.exitCode)return null;let r=t.stdout.trim();return r.length>0?r:null}catch{return null}}function g(e){if(!Number.isInteger(e)||e<=0)return null;try{let t=u("ps",["-p",String(e),"-o","command="],{allowFailure:!0,timeoutMs:1e3});if(0!==t.exitCode)return null;let r=t.stdout.trim();return r.length>0?r:null}catch{return null}}function y(e,t){let r;if(!f(e))return!1;if(t){let r=h(e);if(!r||r!==t)return!1}let n=g(e);return!!n&&!!(r=n.toLowerCase().replaceAll("\\","/")).includes("agent-device")&&p.some(e=>e.test(r))}function b(e,t){try{return process.kill(e,t),!0}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return!1;throw t}}async function w(e,t){if(!f(e))return!0;let r=Date.now();for(;Date.now()-r<t;)if(await new Promise(e=>setTimeout(e,50)),!f(e))return!0;return!f(e)}async function E(e,t){!y(e,t.expectedStartTime)||!b(e,"SIGTERM")||await w(e,t.termTimeoutMs)||b(e,"SIGKILL")&&await w(e,t.killTimeoutMs)}let S="--agent-device-run-metro-companion",_="AGENT_DEVICE_METRO_COMPANION_LAUNCH_URL";function M(e){let t=e.length;for(;t>0&&47===e.charCodeAt(t-1);)t-=1;return t===e.length?e:e.slice(0,t)}function P(e,t){let r=new URL(`${M(e)}/index.bundle`);return r.searchParams.set("platform",t),r.searchParams.set("dev","true"),r.searchParams.set("minify","false"),r.toString()}let U="metro-companion";function A(e){return o("sha256").update(e).digest("hex")}function v(e){return e?.trim()?e.trim():void 0}function N(e,r){let n=t.join(e,".agent-device");if(!r)return{statePath:t.join(n,"metro-companion.json"),logPath:t.join(n,"metro-companion.log")};let o=A(r).slice(0,12),i=t.join(n,U);return{statePath:t.join(i,`metro-companion-${o}.json`),logPath:t.join(i,`metro-companion-${o}.log`)}}function T(t){try{let r=JSON.parse(e.readFileSync(t,"utf8"));if(!Number.isInteger(r.pid)||0>=Number(r.pid)||"string"!=typeof r.serverBaseUrl||"string"!=typeof r.localBaseUrl||"string"!=typeof r.tokenHash||0===r.tokenHash.length)return null;let n=Array.isArray(r.consumers)?r.consumers.filter(e=>"string"==typeof e&&e.length>0):[];return{pid:Number(r.pid),startTime:"string"==typeof r.startTime?r.startTime:void 0,command:"string"==typeof r.command?r.command:void 0,serverBaseUrl:r.serverBaseUrl,localBaseUrl:r.localBaseUrl,launchUrl:v("string"==typeof r.launchUrl?r.launchUrl:void 0),tokenHash:r.tokenHash,consumers:n}}catch{return null}}function I(r,n){e.mkdirSync(t.dirname(r),{recursive:!0}),e.writeFileSync(r,`${JSON.stringify(n,null,2)}
|
|
2
|
+
`,"utf8")}function k(t){try{let r=e.readdirSync(t);0===r.length&&e.rmdirSync(t)}catch{}}function R(r){let n=t.dirname(r.statePath),o=t.dirname(r.logPath);var i=r.statePath;try{e.unlinkSync(i)}catch{}var a=r.logPath;try{e.unlinkSync(a)}catch{}k(n),o!==n&&k(o),t.basename(n)===U&&k(t.dirname(n))}function $(e){return e.includes(S)}function O(e){return v(e.consumerKey)??v(e.profileKey)??null}function C(e,t){return!t||e.consumers.includes(t)?e:{...e,consumers:[...e.consumers,t]}}async function D(e){if(!f(e.pid))return;let t=g(e.pid);if(t&&$(t)){try{process.kill(e.pid,"SIGTERM")}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return;throw t}if(!await w(e.pid,1e3)){try{process.kill(e.pid,"SIGKILL")}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return;throw t}await w(e.pid,1e3)}}}async function x(r){let n=O(r),o=N(r.projectRoot,r.profileKey),a=T(o.statePath);if(a&&function(e,t){if(!f(e.pid))return!1;if(e.startTime){let t=h(e.pid);if(!t||t!==e.startTime)return!1}let r=g(e.pid);return!!r&&!!$(r)&&e.serverBaseUrl===M(t.serverBaseUrl)&&e.localBaseUrl===M(t.localBaseUrl)&&e.launchUrl===v(t.launchUrl)&&e.tokenHash===A(t.bearerToken)}(a,r)){let e=C(a,n);return e!==a&&I(o.statePath,e),{pid:a.pid,spawned:!1,statePath:o.statePath,logPath:o.logPath}}a&&(await D(a),R(o));let s=function(r,n){let o=function(){let r=i(import.meta.url),n=t.extname(r)||".js",o=t.join(t.dirname(r),`metro-companion${n}`);if(!e.existsSync(o))throw Error(`Metro companion entrypoint not found at ${o}. Rebuild the package to include the companion worker entry.`);return o}(),a=o.endsWith(".ts")?["--experimental-strip-types"]:[];e.mkdirSync(t.dirname(n),{recursive:!0});let s=e.openSync(n,"a"),l=0;try{let e;l=c(process.execPath,[...a,o,S],{env:(e={...r.env??process.env,AGENT_DEVICE_METRO_COMPANION_SERVER_BASE_URL:M(r.serverBaseUrl),AGENT_DEVICE_METRO_COMPANION_BEARER_TOKEN:r.bearerToken,AGENT_DEVICE_METRO_COMPANION_LOCAL_BASE_URL:M(r.localBaseUrl),AGENT_DEVICE_METRO_COMPANION_STATE_PATH:N(r.projectRoot,r.profileKey).statePath},r.launchUrl?.trim()?e[_]=r.launchUrl.trim():delete e[_],e),stdio:["ignore",s,s]})}finally{e.closeSync(s)}if(!Number.isInteger(l)||l<=0)throw Error("Failed to start Metro companion process.");return{pid:l,startTime:h(l)??void 0,command:g(l)??void 0,serverBaseUrl:M(r.serverBaseUrl),localBaseUrl:M(r.localBaseUrl),launchUrl:v(r.launchUrl),tokenHash:A(r.bearerToken),consumers:[]}}(r,o.logPath);return I(o.statePath,C(s,n)),{pid:s.pid,spawned:!0,statePath:o.statePath,logPath:o.logPath}}async function B(e){let t=O(e),r=N(e.projectRoot,e.profileKey),n=T(r.statePath);if(!n)return R(r),{stopped:!1,statePath:r.statePath};let o=t?{...n,consumers:n.consumers.filter(e=>e!==t)}:{...n,consumers:[]};return o.consumers.length>0?(I(r.statePath,o),{stopped:!1,statePath:r.statePath}):(await D(n),R(r),{stopped:!0,statePath:r.statePath})}function j(e){return"string"==typeof e&&e.trim()?M(e.trim()):""}function L(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function F(e,t,r){return a(e,{env:t,cwd:r})}function G(t){try{return e.accessSync(t,e.constants.F_OK),!0}catch{return!1}}function H(e,t,r){if(null==e||""===e)return t;let n=Number.parseInt(String(e),10);return Number.isInteger(n)?Math.max(n,r):t}function K(e,t){return{platform:t,bundleUrl:P(e,t)}}function V(e,t){return{platform:t,metroHost:L(e?.metro_host),metroPort:e?.metro_port,bundleUrl:L(e?.metro_bundle_url),launchUrl:L(e?.launch_url)}}async function J(e){await new Promise(t=>setTimeout(t,e))}async function q(e,t,r={}){try{let n=await fetch(e,{headers:r,signal:AbortSignal.timeout(t)});return{ok:n.ok,status:n.status,body:await n.text()}}catch(r){if(r instanceof Error&&"TimeoutError"===r.name)throw Error(`Timed out fetching ${e} after ${t}ms`);throw r}}async function z(e,t){try{let r=await q(e,t);return r.ok&&r.body.includes("packager-status:running")}catch{return!1}}function Z(e,t){let r=Error(e);return r.retryable=t,r}async function W(e){var t,r,n,o;let i;try{i=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:"POST",headers:(t=e.baseUrl,r=e.bearerToken,{Authorization:`Bearer ${r}`,"Content-Type":"application/json",...t.includes("ngrok")?{"ngrok-skip-browser-warning":"1"}:{}}),body:JSON.stringify({ios_runtime:e.runtime,timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(t){if(t instanceof Error&&"TimeoutError"===t.name)throw Z(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0);throw Z(t instanceof Error?t.message:String(t),!0)}let a=await i.text(),s=a?JSON.parse(a):{};if(!i.ok)throw Z(`/api/metro/bridge failed (${i.status}): ${JSON.stringify(s)}`,(n=i.status,!!(n>=500||408===n||425===n||429===n||JSON.stringify(s).includes("Metro companion is not connected"))));return{enabled:(o=s.data??s).enabled,baseUrl:o.base_url,statusUrl:o.status_url??"",bundleUrl:o.bundle_url??"",iosRuntime:V(o.ios_runtime,"ios"),androidRuntime:V(o.android_runtime,"android"),upstream:{bundleUrl:o.upstream.bundle_url??"",host:o.upstream.host??"",port:o.upstream.port??0,statusUrl:o.upstream.status_url??""},probe:{reachable:o.probe.reachable,statusCode:o.probe.status_code,latencyMs:o.probe.latency_ms,detail:o.probe.detail}}}function X(e,t,r,n,o){let i=[`Metro bridge is required for this run but could not be configured via ${e}/api/metro/bridge.`];return t&&i.push(`bridgeError=${t}`),r?.probe.reachable===!1&&i.push(`bridgeProbe=${r.probe.detail||`unreachable (status ${r.probe.statusCode||0})`}`),n&&n!==t&&i.push(`initialBridgeError=${n}`),o&&i.push(`metroCompanionLog=${o}`),i.join(" ")}async function Y(e,t,r){let n=Date.now()+t;for(;Date.now()<n;){let t=Math.min(r,Math.max(n-Date.now(),1));if(await z(e,t))return!0;let o=Math.min(500,Math.max(n-Date.now(),0));o>0&&await J(o)}return!1}async function Q(e){let t=Date.now()+e.startupTimeoutMs,r=null,n=null;for(;Date.now()<t;){try{let t=await W({baseUrl:e.baseUrl,bearerToken:e.bearerToken,runtime:e.runtime,timeoutMs:e.probeTimeoutMs});if(!1!==t.probe.reachable)return t;r=t,n=null}catch(e){if(n=e instanceof Error?e.message:String(e),!(e&&"object"==typeof e&&"retryable"in e&&!0===e.retryable))break}let o=Math.min(1e3,Math.max(t-Date.now(),0));o>0&&await J(o)}throw Error(X(e.baseUrl,n,r,e.initialBridgeError,e.companionLogPath))}async function ee(r={}){let n=r.env??process.env,o=process.cwd(),i=F(r.projectRoot??o,n,o),a=function(r,n){if("auto"!==n)return n;let o=function(r){let n=t.join(r,"package.json");if(!G(n))throw new s("INVALID_ARGS",`package.json not found at ${n}`);return JSON.parse(e.readFileSync(n,"utf8"))}(r);return"string"==typeof({...o.dependencies??{},...o.devDependencies??{}}).expo?"expo":"react-native"}(i,r.kind??"auto"),l=function(e){if(null==e||""===e)return 8081;let t=Number.parseInt(String(e),10);if(!Number.isInteger(t)||t<1||t>65535)throw new s("INVALID_ARGS",`Invalid Metro port: ${String(e)}. Use 1-65535.`);return t}(r.metroPort??8081),m=L(r.listenHost)??"0.0.0.0",d=L(r.statusHost)??"127.0.0.1",p=j(r.publicBaseUrl),f=H(r.startupTimeoutMs,18e4,3e4),h=H(r.probeTimeoutMs,1e4,1e3),g=r.reuseExisting??!0,y=r.installDependenciesIfNeeded??!0,b=r.runtimeFilePath?F(r.runtimeFilePath,n,o):null,w=F(r.logPath??t.join(i,".agent-device","metro.log"),n,o);if(!p)throw new s("INVALID_ARGS","metro prepare requires --public-base-url <url>.");let{proxyEnabled:E,proxyBaseUrl:S,proxyBearerToken:_}=function(e,t){if(e&&!t)throw new s("INVALID_ARGS","metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_PROXY_TOKEN.");if(!e&&t)throw new s("INVALID_ARGS","metro prepare requires --proxy-base-url when proxy auth is provided.");return{proxyEnabled:!!(e&&t),proxyBaseUrl:e,proxyBearerToken:t}}(j(r.proxyBaseUrl),L(r.proxyBearerToken)??""),M=y?function(r,n){if(function(t){try{return e.statSync(t).isDirectory()}catch{return!1}}(t.join(r,"node_modules")))return{installed:!1};let o=G(t.join(r,"pnpm-lock.yaml"))?{command:"pnpm",installArgs:["install"]}:G(t.join(r,"yarn.lock"))?{command:"yarn",installArgs:["install"]}:{command:"npm",installArgs:["install"]};return u(o.command,o.installArgs,{cwd:r,env:n}),{installed:!0,packageManager:o.command}}(i,n):{installed:!1},P=`http://${d}:${l}/status`,U=!1,A=!1,v=0;if(g&&await z(P,h))A=!0;else if(U=!0,v=function(r,n,o,i,a,s){let l="expo"===n?{command:"npx",installArgs:["expo","start","--host","lan","--port",String(o)]}:{command:"npx",installArgs:["react-native","start","--host",i,"--port",String(o)]};e.mkdirSync(t.dirname(a),{recursive:!0});let u=e.openSync(a,"a"),m=0;try{m=c(l.command,l.installArgs,{cwd:r,env:s,stdio:["ignore",u,u]})}finally{e.closeSync(u)}if(!Number.isInteger(m)||m<=0)throw Error("Failed to start Metro. Expected a detached child PID.");return{pid:m}}(i,a,l,m,w,n).pid,!await Y(P,f,h))throw Error(`Metro did not become ready at ${P} within ${f}ms. Check ${w}.`);let N=K(p,"ios"),T=K(p,"android"),I=null,k=null;if(E)try{I=await W({baseUrl:S,bearerToken:_,runtime:{metro_bundle_url:N.bundleUrl},timeoutMs:h})}catch(e){k=e instanceof Error?e.message:String(e)}if(E&&(!I||!1===I.probe.reachable)){let e;try{e=(await x({projectRoot:i,serverBaseUrl:S,bearerToken:_,localBaseUrl:`http://${d}:${l}`,launchUrl:L(r.launchUrl),profileKey:L(r.companionProfileKey),consumerKey:L(r.companionConsumerKey),env:n})).logPath}catch(e){throw Error(X(S,e instanceof Error?e.message:String(e),I,k))}try{I=await Q({baseUrl:S,bearerToken:_,runtime:{metro_bundle_url:N.bundleUrl},probeTimeoutMs:h,startupTimeoutMs:f,initialBridgeError:k,companionLogPath:e})}catch(e){throw e instanceof Error?e:Error(String(e))}}let R=I?.iosRuntime??N,$=I?.androidRuntime??T,O={projectRoot:i,kind:a,dependenciesInstalled:M.installed,packageManager:M.packageManager??null,started:U,reused:A,pid:v,logPath:w,statusUrl:P,runtimeFilePath:b,iosRuntime:R,androidRuntime:$,bridge:I};return b&&(e.mkdirSync(t.dirname(b),{recursive:!0}),e.writeFileSync(b,JSON.stringify(O,null,2))),O}export{P as buildBundleUrl,K as buildMetroRuntimeHints,x as ensureMetroCompanion,y as isAgentDeviceDaemonProcess,M as normalizeBaseUrl,ee as prepareMetroRuntime,c as runCmdDetached,u as runCmdSync,B as stopMetroCompanion,E as stopProcessForTakeover};
|