agent-device 0.12.2 → 0.12.4

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/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",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};
1
+ let E="--agent-device-run-metro-companion",_="AGENT_DEVICE_METRO_COMPANION_SERVER_BASE_URL",N="AGENT_DEVICE_METRO_COMPANION_BEARER_TOKEN",A="AGENT_DEVICE_METRO_COMPANION_LOCAL_BASE_URL",O="AGENT_DEVICE_METRO_COMPANION_LAUNCH_URL",e="AGENT_DEVICE_METRO_COMPANION_STATE_PATH",T="AGENT_DEVICE_METRO_COMPANION_SCOPE_TENANT_ID",C="AGENT_DEVICE_METRO_COMPANION_SCOPE_RUN_ID",R="AGENT_DEVICE_METRO_COMPANION_SCOPE_LEASE_ID";function I(E){let _=E.length;for(;_>0&&47===E.charCodeAt(_-1);)_-=1;return _===E.length?E:E.slice(0,_)}function r(E,_){let N=new URL(`${I(E)}/index.bundle`);return N.searchParams.set("platform",_),N.searchParams.set("dev","true"),N.searchParams.set("minify","false"),N.toString()}export{N as ENV_BEARER_TOKEN,O as ENV_LAUNCH_URL,A as ENV_LOCAL_BASE_URL,R as ENV_SCOPE_LEASE_ID,C as ENV_SCOPE_RUN_ID,T as ENV_SCOPE_TENANT_ID,_ as ENV_SERVER_BASE_URL,e as ENV_STATE_PATH,E as METRO_COMPANION_RUN_ARG,r as buildBundleUrl,I as normalizeBaseUrl};
package/dist/src/974.js CHANGED
@@ -1,2 +1,2 @@
1
- import e from"node:fs";import r from"node:path";import{createHash as t}from"node:crypto";import{fileURLToPath as n}from"node:url";import{runCmdSync as o,runCmdDetached as a}from"./818.js";import{AppError as i}from"./152.js";import{resolveUserPath as s}from"./267.js";let l=[/(^|[/\s"'=])dist\/src\/daemon\.js($|[\s"'])/,/(^|[/\s"'=])src\/daemon\.ts($|[\s"'])/];function u(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return"EPERM"===e.code}}function c(e){if(!Number.isInteger(e)||e<=0)return null;try{let r=o("ps",["-p",String(e),"-o","lstart="],{allowFailure:!0,timeoutMs:1e3});if(0!==r.exitCode)return null;let t=r.stdout.trim();return t.length>0?t:null}catch{return null}}function m(e){if(!Number.isInteger(e)||e<=0)return null;try{let r=o("ps",["-p",String(e),"-o","command="],{allowFailure:!0,timeoutMs:1e3});if(0!==r.exitCode)return null;let t=r.stdout.trim();return t.length>0?t:null}catch{return null}}function d(e,r){let t;if(!u(e))return!1;if(r){let t=c(e);if(!t||t!==r)return!1}let n=m(e);return!!n&&!!(t=n.toLowerCase().replaceAll("\\","/")).includes("agent-device")&&l.some(e=>e.test(t))}function p(e,r){try{return process.kill(e,r),!0}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return!1;throw r}}async function f(e,r){if(!u(e))return!0;let t=Date.now();for(;Date.now()-t<r;)if(await new Promise(e=>setTimeout(e,50)),!u(e))return!0;return!u(e)}async function h(e,r){!d(e,r.expectedStartTime)||!p(e,"SIGTERM")||await f(e,r.termTimeoutMs)||p(e,"SIGKILL")&&await f(e,r.killTimeoutMs)}let g="--agent-device-run-metro-companion",y="AGENT_DEVICE_METRO_COMPANION_LAUNCH_URL";function b(e){let r=e.length;for(;r>0&&47===e.charCodeAt(r-1);)r-=1;return r===e.length?e:e.slice(0,r)}function w(e,r){let t=new URL(`${b(e)}/index.bundle`);return t.searchParams.set("platform",r),t.searchParams.set("dev","true"),t.searchParams.set("minify","false"),t.toString()}let E="metro-companion";function S(e){return t("sha256").update(e).digest("hex")}function _(e){return e?.trim()?e.trim():void 0}function P(e,t){let n=r.join(e,".agent-device");if(!t)return{statePath:r.join(n,"metro-companion.json"),logPath:r.join(n,"metro-companion.log")};let o=S(t).slice(0,12),a=r.join(n,E);return{statePath:r.join(a,`metro-companion-${o}.json`),logPath:r.join(a,`metro-companion-${o}.log`)}}function U(r){try{let t=JSON.parse(e.readFileSync(r,"utf8"));if(!Number.isInteger(t.pid)||0>=Number(t.pid)||"string"!=typeof t.serverBaseUrl||"string"!=typeof t.localBaseUrl||"string"!=typeof t.tokenHash||0===t.tokenHash.length)return null;let n=Array.isArray(t.consumers)?t.consumers.filter(e=>"string"==typeof e&&e.length>0):[];return{pid:Number(t.pid),startTime:"string"==typeof t.startTime?t.startTime:void 0,command:"string"==typeof t.command?t.command:void 0,serverBaseUrl:t.serverBaseUrl,localBaseUrl:t.localBaseUrl,launchUrl:_("string"==typeof t.launchUrl?t.launchUrl:void 0),tokenHash:t.tokenHash,consumers:n}}catch{return null}}function M(t,n){e.mkdirSync(r.dirname(t),{recursive:!0}),e.writeFileSync(t,`${JSON.stringify(n,null,2)}
2
- `,"utf8")}function N(r){try{let t=e.readdirSync(r);0===t.length&&e.rmdirSync(r)}catch{}}function k(t){let n=r.dirname(t.statePath),o=r.dirname(t.logPath);var a=t.statePath;try{e.unlinkSync(a)}catch{}var i=t.logPath;try{e.unlinkSync(i)}catch{}N(n),o!==n&&N(o),r.basename(n)===E&&N(r.dirname(n))}function A(e){return e.includes(g)}function T(e){return _(e.consumerKey)??_(e.profileKey)??null}function v(e,r){return!r||e.consumers.includes(r)?e:{...e,consumers:[...e.consumers,r]}}async function R(e){if(!u(e.pid))return;let r=m(e.pid);if(r&&A(r)){try{process.kill(e.pid,"SIGTERM")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}if(!await f(e.pid,1e3)){try{process.kill(e.pid,"SIGKILL")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}await f(e.pid,1e3)}}}async function I(t){let o=T(t),i=P(t.projectRoot,t.profileKey),s=U(i.statePath);if(s&&function(e,r){if(!u(e.pid))return!1;if(e.startTime){let r=c(e.pid);if(!r||r!==e.startTime)return!1}let t=m(e.pid);return!!t&&!!A(t)&&e.serverBaseUrl===b(r.serverBaseUrl)&&e.localBaseUrl===b(r.localBaseUrl)&&e.launchUrl===_(r.launchUrl)&&e.tokenHash===S(r.bearerToken)}(s,t)){let e=v(s,o);return e!==s&&M(i.statePath,e),{pid:s.pid,spawned:!1,statePath:i.statePath,logPath:i.logPath}}s&&(await R(s),k(i));let l=function(t,o){let i=function(){let t=n(import.meta.url),o=r.extname(t)||".js",a=r.join(r.dirname(t),`metro-companion${o}`);if(!e.existsSync(a))throw Error(`Metro companion entrypoint not found at ${a}. Rebuild the package to include the companion worker entry.`);return a}(),s=i.endsWith(".ts")?["--experimental-strip-types"]:[];e.mkdirSync(r.dirname(o),{recursive:!0});let l=e.openSync(o,"a"),u=0;try{let e;u=a(process.execPath,[...s,i,g],{env:(e={...t.env??process.env,AGENT_DEVICE_METRO_COMPANION_SERVER_BASE_URL:b(t.serverBaseUrl),AGENT_DEVICE_METRO_COMPANION_BEARER_TOKEN:t.bearerToken,AGENT_DEVICE_METRO_COMPANION_LOCAL_BASE_URL:b(t.localBaseUrl),AGENT_DEVICE_METRO_COMPANION_STATE_PATH:P(t.projectRoot,t.profileKey).statePath},t.launchUrl?.trim()?e[y]=t.launchUrl.trim():delete e[y],e),stdio:["ignore",l,l]})}finally{e.closeSync(l)}if(!Number.isInteger(u)||u<=0)throw Error("Failed to start Metro companion process.");return{pid:u,startTime:c(u)??void 0,command:m(u)??void 0,serverBaseUrl:b(t.serverBaseUrl),localBaseUrl:b(t.localBaseUrl),launchUrl:_(t.launchUrl),tokenHash:S(t.bearerToken),consumers:[]}}(t,i.logPath);return M(i.statePath,v(l,o)),{pid:l.pid,spawned:!0,statePath:i.statePath,logPath:i.logPath}}async function C(e){let r=T(e),t=P(e.projectRoot,e.profileKey),n=U(t.statePath);if(!n)return k(t),{stopped:!1,statePath:t.statePath};let o=r?{...n,consumers:n.consumers.filter(e=>e!==r)}:{...n,consumers:[]};return o.consumers.length>0?(M(t.statePath,o),{stopped:!1,statePath:t.statePath}):(await R(n),k(t),{stopped:!0,statePath:t.statePath})}function $(e){return"string"==typeof e&&e.trim()?b(e.trim()):""}function x(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function O(e,r,t){return s(e,{env:r,cwd:t})}function j(r){try{return e.accessSync(r,e.constants.F_OK),!0}catch{return!1}}function B(e,r,t){if(null==e||""===e)return r;let n=Number.parseInt(String(e),10);return Number.isInteger(n)?Math.max(n,t):r}function D(e,r){return{platform:r,bundleUrl:w(e,r)}}function K(e,r){return{platform:r,metroHost:x(e?.metro_host),metroPort:e?.metro_port,bundleUrl:x(e?.metro_bundle_url),launchUrl:x(e?.launch_url)}}async function L(e){await new Promise(r=>setTimeout(r,e))}async function H(e,r,t={}){try{let n=await fetch(e,{headers:t,signal:AbortSignal.timeout(r)});return{ok:n.ok,status:n.status,body:await n.text()}}catch(t){if(t instanceof Error&&"TimeoutError"===t.name)throw Error(`Timed out fetching ${e} after ${r}ms`);throw t}}async function G(e,r){try{let t=await H(e,r);return t.ok&&t.body.includes("packager-status:running")}catch{return!1}}async function F(e){if(Number.isInteger(e)&&!(e<=0)){try{process.kill(e,"SIGTERM")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}if(!await f(e,1e3)){try{process.kill(e,"SIGKILL")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}await f(e,1e3)}}}function J(e,r){let t=Error(e);return t.retryable=r,t}function V(e,r){return!!(e>=500||408===e||425===e||429===e||JSON.stringify(r).includes("Metro companion is not connected"))}async function q(e){let r;try{var t,n;r=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:"POST",headers:(t=e.baseUrl,n=e.bearerToken,{Authorization:`Bearer ${n}`,"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(r){if(r instanceof Error&&"TimeoutError"===r.name)throw J(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0);throw J(r instanceof Error?r.message:String(r),!0)}let o=function(e,r,t){if(!e)return{};try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw Error("Expected a JSON object");return r}catch(a){let n=e.slice(0,200),o=a instanceof Error?a.message:String(a);throw J(`/api/metro/bridge returned invalid JSON (${r}) from ${t}: ${o}. body=${JSON.stringify(n)}`,V(r,e))}}(await r.text(),r.status,e.baseUrl);if(!r.ok)throw J(`/api/metro/bridge failed (${r.status}): ${JSON.stringify(o)}`,V(r.status,o));var a=o;let i=a.data??a;if(!i||"object"!=typeof i||Array.isArray(i))throw J("/api/metro/bridge returned malformed descriptor: Expected a JSON object.",!1);try{return{enabled:i.enabled,baseUrl:i.base_url,statusUrl:i.status_url??"",bundleUrl:i.bundle_url??"",iosRuntime:K(i.ios_runtime,"ios"),androidRuntime:K(i.android_runtime,"android"),upstream:{bundleUrl:i.upstream.bundle_url??"",host:i.upstream.host??"",port:i.upstream.port??0,statusUrl:i.upstream.status_url??""},probe:{reachable:i.probe.reachable,statusCode:i.probe.status_code,latencyMs:i.probe.latency_ms,detail:i.probe.detail}}}catch(e){throw J(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function z(e,r,t,n,o){let a=[`Metro bridge is required for this run but could not be configured via ${e}/api/metro/bridge.`];return r&&a.push(`bridgeError=${r}`),t?.probe.reachable===!1&&a.push(`bridgeProbe=${t.probe.detail||`unreachable (status ${t.probe.statusCode||0})`}`),n&&n!==r&&a.push(`initialBridgeError=${n}`),o&&a.push(`metroCompanionLog=${o}`),a.join(" ")}async function W(e,r,t){let n=Date.now()+r;for(;Date.now()<n;){let r=Math.min(t,Math.max(n-Date.now(),1));if(await G(e,r))return!0;let o=Math.min(500,Math.max(n-Date.now(),0));o>0&&await L(o)}return!1}async function X(e){let r=Date.now()+e.startupTimeoutMs,t=null,n=null;for(;Date.now()<r;){try{let r=await q({baseUrl:e.baseUrl,bearerToken:e.bearerToken,runtime:e.runtime,timeoutMs:e.probeTimeoutMs});if(!1!==r.probe.reachable)return r;t=r,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(r-Date.now(),0));o>0&&await L(o)}throw Error(z(e.baseUrl,n,t,e.initialBridgeError,e.companionLogPath))}async function Y(t={}){let n=t.env??process.env,s=process.cwd(),l=O(t.projectRoot??s,n,s),u=function(t,n){if("auto"!==n)return n;let o=function(t){let n=r.join(t,"package.json");if(!j(n))throw new i("INVALID_ARGS",`package.json not found at ${n}`);return JSON.parse(e.readFileSync(n,"utf8"))}(t);return"string"==typeof({...o.dependencies??{},...o.devDependencies??{}}).expo?"expo":"react-native"}(l,t.kind??"auto"),c=function(e){if(null==e||""===e)return 8081;let r=Number.parseInt(String(e),10);if(!Number.isInteger(r)||r<1||r>65535)throw new i("INVALID_ARGS",`Invalid Metro port: ${String(e)}. Use 1-65535.`);return r}(t.metroPort??8081),m=x(t.listenHost)??"0.0.0.0",d=x(t.statusHost)??"127.0.0.1",p=$(t.publicBaseUrl),f=B(t.startupTimeoutMs,18e4,3e4),h=B(t.probeTimeoutMs,1e4,1e3),g=t.reuseExisting??!0,y=t.installDependenciesIfNeeded??!0,b=t.runtimeFilePath?O(t.runtimeFilePath,n,s):null,w=O(t.logPath??r.join(l,".agent-device","metro.log"),n,s);if(!p)throw new i("INVALID_ARGS","metro prepare requires --public-base-url <url>.");let{proxyEnabled:E,proxyBaseUrl:S,proxyBearerToken:_}=function(e,r){if(e&&!r)throw new i("INVALID_ARGS","metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_PROXY_TOKEN.");if(!e&&r)throw new i("INVALID_ARGS","metro prepare requires --proxy-base-url when proxy auth is provided.");return{proxyEnabled:!!(e&&r),proxyBaseUrl:e,proxyBearerToken:r}}($(t.proxyBaseUrl),x(t.proxyBearerToken)??""),P=y?function(t,n){if(function(r){try{return e.statSync(r).isDirectory()}catch{return!1}}(r.join(t,"node_modules")))return{installed:!1};let a=j(r.join(t,"pnpm-lock.yaml"))?{command:"pnpm",installArgs:["install"]}:j(r.join(t,"yarn.lock"))?{command:"yarn",installArgs:["install"]}:{command:"npm",installArgs:["install"]};return o(a.command,a.installArgs,{cwd:t,env:n}),{installed:!0,packageManager:a.command}}(l,n):{installed:!1},U=`http://${d}:${c}/status`,M=!1,N=!1,k=0;if(g&&await G(U,h))N=!0;else if(M=!0,k=function(t,n,o,i,s,l){let u="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(r.dirname(s),{recursive:!0});let c=e.openSync(s,"a"),m=0;try{m=a(u.command,u.installArgs,{cwd:t,env:l,stdio:["ignore",c,c]})}finally{e.closeSync(c)}if(!Number.isInteger(m)||m<=0)throw Error("Failed to start Metro. Expected a detached child PID.");return{pid:m}}(l,u,c,m,w,n).pid,!await W(U,f,h))throw await F(k).catch(()=>{}),Error(`Metro did not become ready at ${U} within ${f}ms. Check ${w}.`);let A=D(p,"ios"),T=D(p,"android"),v=null,R=null;if(E)try{v=await q({baseUrl:S,bearerToken:_,runtime:{metro_bundle_url:A.bundleUrl},timeoutMs:h})}catch(e){R=e instanceof Error?e.message:String(e)}if(E&&(!v||!1===v.probe.reachable)){let e;try{e=(await I({projectRoot:l,serverBaseUrl:S,bearerToken:_,localBaseUrl:`http://${d}:${c}`,launchUrl:x(t.launchUrl),profileKey:x(t.companionProfileKey),consumerKey:x(t.companionConsumerKey),env:n})).logPath}catch(e){throw Error(z(S,e instanceof Error?e.message:String(e),v,R))}try{v=await X({baseUrl:S,bearerToken:_,runtime:{metro_bundle_url:A.bundleUrl},probeTimeoutMs:h,startupTimeoutMs:f,initialBridgeError:R,companionLogPath:e})}catch(e){throw e instanceof Error?e:Error(String(e))}}let C=v?.iosRuntime??A,K=v?.androidRuntime??T,L={projectRoot:l,kind:u,dependenciesInstalled:P.installed,packageManager:P.packageManager??null,started:M,reused:N,pid:k,logPath:w,statusUrl:U,runtimeFilePath:b,iosRuntime:C,androidRuntime:K,bridge:v};return b&&(e.mkdirSync(r.dirname(b),{recursive:!0}),e.writeFileSync(b,JSON.stringify(L,null,2))),L}export{w as buildBundleUrl,D as buildMetroRuntimeHints,I as ensureMetroCompanion,d as isAgentDeviceDaemonProcess,b as normalizeBaseUrl,Y as prepareMetroRuntime,C as stopMetroCompanion,h as stopProcessForTakeover};
1
+ import e from"node:fs";import r from"node:path";import{createHash as t}from"node:crypto";import{fileURLToPath as n}from"node:url";import{runCmdSync as o,runCmdDetached as a}from"./818.js";import{AppError as i}from"./152.js";import{resolveUserPath as s}from"./267.js";let l=[/(^|[/\s"'=])dist\/src\/daemon\.js($|[\s"'])/,/(^|[/\s"'=])src\/daemon\.ts($|[\s"'])/];function u(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return"EPERM"===e.code}}function c(e){if(!Number.isInteger(e)||e<=0)return null;try{let r=o("ps",["-p",String(e),"-o","lstart="],{allowFailure:!0,timeoutMs:1e3});if(0!==r.exitCode)return null;let t=r.stdout.trim();return t.length>0?t:null}catch{return null}}function d(e){if(!Number.isInteger(e)||e<=0)return null;try{let r=o("ps",["-p",String(e),"-o","command="],{allowFailure:!0,timeoutMs:1e3});if(0!==r.exitCode)return null;let t=r.stdout.trim();return t.length>0?t:null}catch{return null}}function m(e,r){let t;if(!u(e))return!1;if(r){let t=c(e);if(!t||t!==r)return!1}let n=d(e);return!!n&&!!(t=n.toLowerCase().replaceAll("\\","/")).includes("agent-device")&&l.some(e=>e.test(t))}function p(e,r){try{return process.kill(e,r),!0}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return!1;throw r}}async function f(e,r){if(!u(e))return!0;let t=Date.now();for(;Date.now()-t<r;)if(await new Promise(e=>setTimeout(e,50)),!u(e))return!0;return!u(e)}async function h(e,r){!m(e,r.expectedStartTime)||!p(e,"SIGTERM")||await f(e,r.termTimeoutMs)||p(e,"SIGKILL")&&await f(e,r.killTimeoutMs)}let g="--agent-device-run-metro-companion",y="AGENT_DEVICE_METRO_COMPANION_LAUNCH_URL";function b(e){let r=e.length;for(;r>0&&47===e.charCodeAt(r-1);)r-=1;return r===e.length?e:e.slice(0,r)}function E(e,r){let t=new URL(`${b(e)}/index.bundle`);return t.searchParams.set("platform",r),t.searchParams.set("dev","true"),t.searchParams.set("minify","false"),t.toString()}let S="metro-companion";function _(e){return t("sha256").update(e).digest("hex")}function w(e){return e?.trim()?e.trim():void 0}function I(e,t){let n=r.join(e,".agent-device");if(!t)return{statePath:r.join(n,"metro-companion.json"),logPath:r.join(n,"metro-companion.log")};let o=_(t).slice(0,12),a=r.join(n,S);return{statePath:r.join(a,`metro-companion-${o}.json`),logPath:r.join(a,`metro-companion-${o}.log`)}}function P(r){try{let t=JSON.parse(e.readFileSync(r,"utf8"));if(!Number.isInteger(t.pid)||0>=Number(t.pid)||"string"!=typeof t.serverBaseUrl||"string"!=typeof t.localBaseUrl||"string"!=typeof t.tokenHash||0===t.tokenHash.length)return null;let n=Array.isArray(t.consumers)?t.consumers.filter(e=>"string"==typeof e&&e.length>0):[];return{pid:Number(t.pid),startTime:"string"==typeof t.startTime?t.startTime:void 0,command:"string"==typeof t.command?t.command:void 0,serverBaseUrl:t.serverBaseUrl,localBaseUrl:t.localBaseUrl,launchUrl:w("string"==typeof t.launchUrl?t.launchUrl:void 0),bridgeScope:function(e){if(!(!e||"object"!=typeof e||Array.isArray(e))&&"string"==typeof e.tenantId&&"string"==typeof e.runId&&"string"==typeof e.leaseId)return{tenantId:e.tenantId,runId:e.runId,leaseId:e.leaseId}}(t.bridgeScope),tokenHash:t.tokenHash,consumers:n}}catch{return null}}function N(t,n){e.mkdirSync(r.dirname(t),{recursive:!0}),e.writeFileSync(t,`${JSON.stringify(n,null,2)}
2
+ `,"utf8")}function M(r){try{let t=e.readdirSync(r);0===t.length&&e.rmdirSync(r)}catch{}}function A(t){let n=r.dirname(t.statePath),o=r.dirname(t.logPath);var a=t.statePath;try{e.unlinkSync(a)}catch{}var i=t.logPath;try{e.unlinkSync(i)}catch{}M(n),o!==n&&M(o),r.basename(n)===S&&M(r.dirname(n))}function U(e){return e.includes(g)}function T(e){return w(e.consumerKey)??w(e.profileKey)??null}function R(e,r){return!r||e.consumers.includes(r)?e:{...e,consumers:[...e.consumers,r]}}async function k(e){if(!u(e.pid))return;let r=d(e.pid);if(r&&U(r)){try{process.kill(e.pid,"SIGTERM")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}if(!await f(e.pid,1e3)){try{process.kill(e.pid,"SIGKILL")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}await f(e.pid,1e3)}}}async function v(t){let o=T(t),i=I(t.projectRoot,t.profileKey),s=P(i.statePath);if(s&&function(e,r){var t,n;if(!u(e.pid))return!1;if(e.startTime){let r=c(e.pid);if(!r||r!==e.startTime)return!1}let o=d(e.pid);return!!o&&!!U(o)&&!!e.bridgeScope&&e.serverBaseUrl===b(r.serverBaseUrl)&&e.localBaseUrl===b(r.localBaseUrl)&&e.launchUrl===w(r.launchUrl)&&(t=e.bridgeScope,n=r.bridgeScope,t.tenantId===n.tenantId&&t.runId===n.runId&&t.leaseId===n.leaseId)&&e.tokenHash===_(r.bearerToken)}(s,t)){let e=R(s,o);return e!==s&&N(i.statePath,e),{pid:s.pid,spawned:!1,statePath:i.statePath,logPath:i.logPath}}s&&(await k(s),A(i));let l=function(t,o){let i=function(){let t=n(import.meta.url),o=r.extname(t)||".js",a=r.join(r.dirname(t),`metro-companion${o}`);if(!e.existsSync(a))throw Error(`Metro companion entrypoint not found at ${a}. Rebuild the package to include the companion worker entry.`);return a}(),s=i.endsWith(".ts")?["--experimental-strip-types"]:[];e.mkdirSync(r.dirname(o),{recursive:!0});let l=e.openSync(o,"a"),u=0;try{let e;u=a(process.execPath,[...s,i,g],{env:((e={...t.env??process.env,AGENT_DEVICE_METRO_COMPANION_SERVER_BASE_URL:b(t.serverBaseUrl),AGENT_DEVICE_METRO_COMPANION_BEARER_TOKEN:t.bearerToken,AGENT_DEVICE_METRO_COMPANION_LOCAL_BASE_URL:b(t.localBaseUrl),AGENT_DEVICE_METRO_COMPANION_STATE_PATH:I(t.projectRoot,t.profileKey).statePath}).AGENT_DEVICE_METRO_COMPANION_SCOPE_TENANT_ID=t.bridgeScope.tenantId,e.AGENT_DEVICE_METRO_COMPANION_SCOPE_RUN_ID=t.bridgeScope.runId,e.AGENT_DEVICE_METRO_COMPANION_SCOPE_LEASE_ID=t.bridgeScope.leaseId,t.launchUrl?.trim()?e[y]=t.launchUrl.trim():delete e[y],e),stdio:["ignore",l,l]})}finally{e.closeSync(l)}if(!Number.isInteger(u)||u<=0)throw Error("Failed to start Metro companion process.");return{pid:u,startTime:c(u)??void 0,command:d(u)??void 0,serverBaseUrl:b(t.serverBaseUrl),localBaseUrl:b(t.localBaseUrl),launchUrl:w(t.launchUrl),bridgeScope:t.bridgeScope,tokenHash:_(t.bearerToken),consumers:[]}}(t,i.logPath);return N(i.statePath,R(l,o)),{pid:l.pid,spawned:!0,statePath:i.statePath,logPath:i.logPath}}async function C(e){let r=T(e),t=I(e.projectRoot,e.profileKey),n=P(t.statePath);if(!n)return A(t),{stopped:!1,statePath:t.statePath};let o=r?{...n,consumers:n.consumers.filter(e=>e!==r)}:{...n,consumers:[]};return o.consumers.length>0?(N(t.statePath,o),{stopped:!1,statePath:t.statePath}):(await k(n),A(t),{stopped:!0,statePath:t.statePath})}function O(e){return"string"==typeof e&&e.trim()?b(e.trim()):""}function $(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function x(e,r,t){return s(e,{env:r,cwd:t})}function D(r){try{return e.accessSync(r,e.constants.F_OK),!0}catch{return!1}}function j(e,r,t){if(null==e||""===e)return r;let n=Number.parseInt(String(e),10);return Number.isInteger(n)?Math.max(n,t):r}function B(e,r){return{platform:r,bundleUrl:E(e,r)}}function L(e,r){return{platform:r,metroHost:$(e?.metro_host),metroPort:e?.metro_port,bundleUrl:$(e?.metro_bundle_url),launchUrl:$(e?.launch_url)}}async function G(e){await new Promise(r=>setTimeout(r,e))}async function K(e,r,t={}){try{let n=await fetch(e,{headers:t,signal:AbortSignal.timeout(r)});return{ok:n.ok,status:n.status,body:await n.text()}}catch(t){if(t instanceof Error&&"TimeoutError"===t.name)throw Error(`Timed out fetching ${e} after ${r}ms`);throw t}}async function H(e,r){try{let t=await K(e,r);return t.ok&&t.body.includes("packager-status:running")}catch{return!1}}async function V(e){if(Number.isInteger(e)&&!(e<=0)){try{process.kill(e,"SIGTERM")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}if(!await f(e,1e3)){try{process.kill(e,"SIGKILL")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}await f(e,1e3)}}}function F(e,r){let t=Error(e);return t.retryable=r,t}function J(e,r){return!!(e>=500||408===e||425===e||429===e||JSON.stringify(r).includes("Metro companion is not connected"))}function q(e){return!!(e&&"object"==typeof e&&"retryable"in e&&!0===e.retryable)}async function z(e){let r;try{var t,n;r=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:"POST",headers:(t=e.baseUrl,n=e.bearerToken,{Authorization:`Bearer ${n}`,"Content-Type":"application/json",...t.includes("ngrok")?{"ngrok-skip-browser-warning":"1"}:{}}),body:JSON.stringify({...e.scope,ios_runtime:e.runtime,timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(r){if(r instanceof Error&&"TimeoutError"===r.name)throw F(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0);throw F(r instanceof Error?r.message:String(r),!0)}let o=function(e,r,t){if(!e)return{};try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw Error("Expected a JSON object");return r}catch(a){let n=e.slice(0,200),o=a instanceof Error?a.message:String(a);throw F(`/api/metro/bridge returned invalid JSON (${r}) from ${t}: ${o}. body=${JSON.stringify(n)}`,J(r,e))}}(await r.text(),r.status,e.baseUrl);if(!r.ok)throw F(`/api/metro/bridge failed (${r.status}): ${JSON.stringify(o)}`,J(r.status,o));var a=o;let i=a.data??a;if(!i||"object"!=typeof i||Array.isArray(i))throw F("/api/metro/bridge returned malformed descriptor: Expected a JSON object.",!1);try{return{enabled:i.enabled,baseUrl:i.base_url,statusUrl:i.status_url??"",bundleUrl:i.bundle_url??"",iosRuntime:L(i.ios_runtime,"ios"),androidRuntime:L(i.android_runtime,"android"),upstream:{bundleUrl:i.upstream.bundle_url??"",host:i.upstream.host??"",port:i.upstream.port??0,statusUrl:i.upstream.status_url??""},probe:{reachable:i.probe.reachable,statusCode:i.probe.status_code,latencyMs:i.probe.latency_ms,detail:i.probe.detail}}}catch(e){throw F(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function W(e,r,t,n,o){let a=[`Metro bridge is required for this run but could not be configured via ${e}/api/metro/bridge.`];return r&&a.push(`bridgeError=${r}`),t?.probe.reachable===!1&&a.push(`bridgeProbe=${t.probe.detail||`unreachable (status ${t.probe.statusCode||0})`}`),n&&n!==r&&a.push(`initialBridgeError=${n}`),o&&a.push(`metroCompanionLog=${o}`),a.join(" ")}async function X(e,r,t){let n=Date.now()+r;for(;Date.now()<n;){let r=Math.min(t,Math.max(n-Date.now(),1));if(await H(e,r))return!0;let o=Math.min(500,Math.max(n-Date.now(),0));o>0&&await G(o)}return!1}async function Y(e){let r=Date.now()+e.startupTimeoutMs,t=null,n=null;for(;Date.now()<r;){try{let r=await z({baseUrl:e.baseUrl,bearerToken:e.bearerToken,scope:e.scope,runtime:e.runtime,timeoutMs:e.probeTimeoutMs});if(!1!==r.probe.reachable)return r;t=r,n=null}catch(e){if(n=e instanceof Error?e.message:String(e),!q(e))break}let o=Math.min(1e3,Math.max(r-Date.now(),0));o>0&&await G(o)}throw Error(W(e.baseUrl,n,t,e.initialBridgeError,e.companionLogPath))}async function Q(t={}){let n=t.env??process.env,s=process.cwd(),l=x(t.projectRoot??s,n,s),u=function(t,n){if("auto"!==n)return n;let o=function(t){let n=r.join(t,"package.json");if(!D(n))throw new i("INVALID_ARGS",`package.json not found at ${n}`);return JSON.parse(e.readFileSync(n,"utf8"))}(t);return"string"==typeof({...o.dependencies??{},...o.devDependencies??{}}).expo?"expo":"react-native"}(l,t.kind??"auto"),c=function(e){if(null==e||""===e)return 8081;let r=Number.parseInt(String(e),10);if(!Number.isInteger(r)||r<1||r>65535)throw new i("INVALID_ARGS",`Invalid Metro port: ${String(e)}. Use 1-65535.`);return r}(t.metroPort??8081),d=$(t.listenHost)??"0.0.0.0",m=$(t.statusHost)??"127.0.0.1",p=O(t.publicBaseUrl),f=j(t.startupTimeoutMs,18e4,3e4),h=j(t.probeTimeoutMs,1e4,1e3),g=t.reuseExisting??!0,y=t.installDependenciesIfNeeded??!0,b=t.runtimeFilePath?x(t.runtimeFilePath,n,s):null,E=x(t.logPath??r.join(l,".agent-device","metro.log"),n,s);if(!p)throw new i("INVALID_ARGS","metro prepare requires --public-base-url <url>.");let{proxyEnabled:S,proxyBaseUrl:_,proxyBearerToken:w}=function(e,r){if(e&&!r)throw new i("INVALID_ARGS","metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_PROXY_TOKEN.");if(!e&&r)throw new i("INVALID_ARGS","metro prepare requires --proxy-base-url when proxy auth is provided.");return{proxyEnabled:!!(e&&r),proxyBaseUrl:e,proxyBearerToken:r}}(O(t.proxyBaseUrl),$(t.proxyBearerToken)??""),I=S?function(e){if(!e?.tenantId||!e.runId||!e.leaseId)throw new i("INVALID_ARGS","metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.");return e}(t.bridgeScope):null,P=y?function(t,n){if(function(r){try{return e.statSync(r).isDirectory()}catch{return!1}}(r.join(t,"node_modules")))return{installed:!1};let a=D(r.join(t,"pnpm-lock.yaml"))?{command:"pnpm",installArgs:["install"]}:D(r.join(t,"yarn.lock"))?{command:"yarn",installArgs:["install"]}:{command:"npm",installArgs:["install"]};return o(a.command,a.installArgs,{cwd:t,env:n}),{installed:!0,packageManager:a.command}}(l,n):{installed:!1},N=`http://${m}:${c}/status`,M=!1,A=!1,U=0;if(g&&await H(N,h))A=!0;else if(M=!0,U=function(t,n,o,i,s,l){let u="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(r.dirname(s),{recursive:!0});let c=e.openSync(s,"a"),d=0;try{d=a(u.command,u.installArgs,{cwd:t,env:l,stdio:["ignore",c,c]})}finally{e.closeSync(c)}if(!Number.isInteger(d)||d<=0)throw Error("Failed to start Metro. Expected a detached child PID.");return{pid:d}}(l,u,c,d,E,n).pid,!await X(N,f,h))throw await V(U).catch(()=>{}),Error(`Metro did not become ready at ${N} within ${f}ms. Check ${E}.`);let T=B(p,"ios"),R=B(p,"android"),k=null,C=null;if(I)try{k=await z({baseUrl:_,bearerToken:w,scope:I,runtime:{metro_bundle_url:T.bundleUrl},timeoutMs:h})}catch(e){if(!q(e))throw e;C=e instanceof Error?e.message:String(e)}if(I&&(!k||!1===k.probe.reachable)){let e;try{e=(await v({projectRoot:l,serverBaseUrl:_,bearerToken:w,bridgeScope:I,localBaseUrl:`http://${m}:${c}`,launchUrl:$(t.launchUrl),profileKey:$(t.companionProfileKey),consumerKey:$(t.companionConsumerKey),env:n})).logPath}catch(e){throw Error(W(_,e instanceof Error?e.message:String(e),k,C))}try{k=await Y({baseUrl:_,bearerToken:w,scope:I,runtime:{metro_bundle_url:T.bundleUrl},probeTimeoutMs:h,startupTimeoutMs:f,initialBridgeError:C,companionLogPath:e})}catch(e){throw e instanceof Error?e:Error(String(e))}}let L=k?.iosRuntime??T,G=k?.androidRuntime??R,K={projectRoot:l,kind:u,dependenciesInstalled:P.installed,packageManager:P.packageManager??null,started:M,reused:A,pid:U,logPath:E,statusUrl:N,runtimeFilePath:b,iosRuntime:L,androidRuntime:G,bridge:k};return b&&(e.mkdirSync(r.dirname(b),{recursive:!0}),e.writeFileSync(b,JSON.stringify(K,null,2))),K}export{E as buildBundleUrl,B as buildMetroRuntimeHints,v as ensureMetroCompanion,m as isAgentDeviceDaemonProcess,b as normalizeBaseUrl,Q as prepareMetroRuntime,C as stopMetroCompanion,h as stopProcessForTakeover};
@@ -0,0 +1,12 @@
1
+ export declare type AndroidForegroundApp = {
2
+ package?: string;
3
+ activity?: string;
4
+ };
5
+
6
+ export declare function parseAndroidForegroundApp(text: string): AndroidForegroundApp | null;
7
+
8
+ export declare function parseAndroidLaunchablePackages(stdout: string): string[];
9
+
10
+ export declare function parseAndroidUserInstalledPackages(stdout: string): string[];
11
+
12
+ export { }
@@ -0,0 +1 @@
1
+ function e(e){let t=new Set;for(let n of e.split("\n")){let e=n.trim();if(!e)continue;let r=e.split(/\s+/)[0],i=r.includes("/")?r.split("/")[0]:r;i&&t.add(i)}return Array.from(t)}function t(e){return e.split("\n").map(e=>{let t=e.trim();return t.startsWith("package:")?t.slice(8):t}).filter(Boolean)}function n(e){let t=e.split("\n");for(let e of["mCurrentFocus=Window{","mFocusedApp=AppWindowToken{","mResumedActivity:","ResumedActivity:"])for(let n of t){let t=n.indexOf(e);if(-1===t)continue;let i=function(e){for(let t of e.trim().split(/\s+/)){let e=t.indexOf("/");if(e<=0)continue;let n=r(t.slice(0,e),!1),i=r(t.slice(e+1),!0);if(n&&i&&n.length===e)return{package:n,activity:i}}return null}(n.slice(t+e.length));if(i)return i}return null}function r(e,t){let n=0;for(;n<e.length&&function(e,t){if(!e)return!1;let n=e.charCodeAt(0);return n>=48&&n<=57||n>=65&&n<=90||n>=97&&n<=122||"_"===e||"."===e||t&&"$"===e}(e[n],t);)n+=1;return e.slice(0,n)}export{n as parseAndroidForegroundApp,e as parseAndroidLaunchablePackages,t as parseAndroidUserInstalledPackages};