agent-device 0.17.9 → 0.18.0

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.
Files changed (50) hide show
  1. package/README.md +4 -0
  2. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.9.apk → agent-device-android-multitouch-helper-0.18.0.apk} +0 -0
  3. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.18.0.apk.sha256 +1 -0
  4. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.9.manifest.json → agent-device-android-multitouch-helper-0.18.0.manifest.json} +4 -4
  5. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.9.apk → agent-device-android-snapshot-helper-0.18.0.apk} +0 -0
  6. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.18.0.apk.sha256 +1 -0
  7. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.9.manifest.json → agent-device-android-snapshot-helper-0.18.0.manifest.json} +6 -6
  8. package/dist/src/1848.js +4 -0
  9. package/dist/src/2577.js +1 -1
  10. package/dist/src/2948.js +20 -20
  11. package/dist/src/4291.js +1 -1
  12. package/dist/src/4723.js +1 -1
  13. package/dist/src/5341.js +1 -0
  14. package/dist/src/5643.js +1 -0
  15. package/dist/src/6918.js +1 -1
  16. package/dist/src/8275.js +2 -2
  17. package/dist/src/8936.js +1 -0
  18. package/dist/src/9414.js +1 -0
  19. package/dist/src/9581.js +4 -4
  20. package/dist/src/9722.js +32 -37
  21. package/dist/src/9919.js +5 -5
  22. package/dist/src/apple.js +1 -1
  23. package/dist/src/apps.js +10 -10
  24. package/dist/src/batch.d.ts +20 -3
  25. package/dist/src/batch.js +1 -1
  26. package/dist/src/cli-help.js +111 -35
  27. package/dist/src/cli.js +22 -25
  28. package/dist/src/contracts.d.ts +14 -0
  29. package/dist/src/device-ready.js +2 -0
  30. package/dist/src/find.js +1 -1
  31. package/dist/src/index.d.ts +67 -16
  32. package/dist/src/interaction.js +1 -1
  33. package/dist/src/internal/bin.js +1 -1
  34. package/dist/src/lease.js +1 -1
  35. package/dist/src/metro.js +1 -1
  36. package/dist/src/react-native.js +1 -1
  37. package/dist/src/record-trace-recording.js +3 -3
  38. package/dist/src/remote-config.d.ts +17 -11
  39. package/dist/src/selector-runtime.js +1 -1
  40. package/dist/src/session.js +11 -8
  41. package/dist/src/simulator.js +2 -0
  42. package/dist/src/snapshot.js +1 -1
  43. package/package.json +1 -1
  44. package/server.json +2 -2
  45. package/skills/agent-device/SKILL.md +1 -0
  46. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.9.apk.sha256 +0 -1
  47. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.9.apk.sha256 +0 -1
  48. package/dist/src/2133.js +0 -1
  49. package/dist/src/5628.js +0 -1
  50. package/dist/src/8358.js +0 -4
package/dist/src/4291.js CHANGED
@@ -1 +1 @@
1
- import"./733.js";import{PLATFORM_SELECTORS as t}from"./5910.js";function e(t){return"xctest"===t||"android"===t||"macos-helper"===t||"linux-atspi"===t||"web"===t}function n(t){return void 0===t||"xctest"===t||"android"===t}function a(t){return t.map((t,e)=>({...t,ref:`e${e+1}`}))}function r(t){let e=t.trim();return e.startsWith("@")?e.slice(1)||null:e.startsWith("e")?e:null}function i(t,e){return t.find(t=>t.ref===e)??null}function o(t){return JSON.stringify({interactiveOnly:t?.interactiveOnly===!0,depth:"number"==typeof t?.depth?t.depth:null,scope:t?.scope?.trim()||null,raw:t?.raw===!0})}function s(t){if(t)return{depth:t.snapshotDepth,interactiveOnly:t.snapshotInteractiveOnly,raw:t.snapshotRaw,scope:t.snapshotScope}}function d(t){return{x:Math.round(t.x+t.width/2),y:Math.round(t.y+t.height/2)}}let l=["reject","strip"],c=["ios-simulator","ios-instance","android-instance"],u=["socket","http","dual"],m=["auto","socket","http"],f=["none","tenant"],p=["summary","headers","body","all"];function h(t){return{parse:e=>t(e,"$")}}function $(t,e){throw Error(`${t}: ${e}`)}function I(t,e){return(!t||"object"!=typeof t||Array.isArray(t))&&$(e,"Expected an object"),t}function E(t,e){return"string"!=typeof t&&$(e,"Expected a string"),t}function S(t,e){let n=E(t,e).trim();return n||$(e,"Expected a non-empty string"),n}function v(t,e){return Number.isInteger(t)||$(e,"Expected an integer"),t}function y(t,e,n){let a=t[e];return void 0===a?void 0:E(a,`${n}.${e}`)}function b(t,e,n){let a=t[e];if(void 0!==a)return"boolean"!=typeof a&&$(`${n}.${e}`,"Expected a boolean"),a}function M(t,e,n){let a=t[e];return void 0===a?void 0:v(a,`${n}.${e}`)}function N(t,e,n){let a=t[e];return void 0===a?void 0:I(a,`${n}.${e}`)}function P(t,e,n,a){let r=t[e];if(void 0!==r)return"string"==typeof r&&n.includes(r)||$(`${a}.${e}`,`Expected one of: ${n.join(", ")}`),r}function x(t,e){let n=I(t,e),a={};for(let[t,r]of Object.entries(n))a[t]=E(r,`${e}.${t}`);return a}let O=h((t,e)=>{let n=I(t,e);return{platform:P(n,"platform",["ios","android"],e),metroHost:y(n,"metroHost",e),metroPort:M(n,"metroPort",e),bundleUrl:y(n,"bundleUrl",e),launchUrl:y(n,"launchUrl",e)}}),R=h((e,n)=>{var a,r;let i=I(e,n),o=(a=i.positionals,r=`${n}.positionals`,Array.isArray(a)||$(r,"Expected an array"),a),s=N(i,"meta",n);return{token:y(i,"token",n),session:y(i,"session",n),command:E(i.command,`${n}.command`),positionals:o.map((t,e)=>E(t,`${n}.positionals[${String(e)}]`)),flags:N(i,"flags",n),runtime:void 0===i.runtime?void 0:O.parse(i.runtime),meta:void 0===s?void 0:{requestId:y(s,"requestId",`${n}.meta`),debug:b(s,"debug",`${n}.meta`),cwd:y(s,"cwd",`${n}.meta`),sessionExplicit:b(s,"sessionExplicit",`${n}.meta`),tenantId:y(s,"tenantId",`${n}.meta`),runId:y(s,"runId",`${n}.meta`),leaseId:y(s,"leaseId",`${n}.meta`),leaseTtlMs:M(s,"leaseTtlMs",`${n}.meta`),leaseBackend:P(s,"leaseBackend",c,`${n}.meta`),sessionIsolation:P(s,"sessionIsolation",f,`${n}.meta`),uploadedArtifactId:y(s,"uploadedArtifactId",`${n}.meta`),clientArtifactPaths:void 0===s.clientArtifactPaths?void 0:x(s.clientArtifactPaths,`${n}.meta.clientArtifactPaths`),installSource:void 0===s.installSource?void 0:function(t,e){let n=I(t,e),a=E(n.kind,`${e}.kind`);if("url"===a){let t=E(n.url,`${e}.url`),r=void 0===n.headers?void 0:x(n.headers,`${e}.headers`);return r?{kind:a,url:t,headers:r}:{kind:a,url:t}}if("path"===a)return{kind:a,path:E(n.path,`${e}.path`)};if("github-actions-artifact"===a){let t,a,r,i,o;return t=S(n.owner,`${e}.owner`),a=S(n.repo,`${e}.repo`),r=void 0!==n.artifactId,i=void 0!==n.runId,o=void 0!==n.artifactName,(r&&(i||o)&&$(`${e}`,"Expected either artifactId or artifactName, not both"),r||!i||o||$(`${e}`,"Expected artifactName when runId is specified"),r||o||$(`${e}`,"Expected artifactId or artifactName"),r)?{kind:"github-actions-artifact",owner:t,repo:a,artifactId:v(n.artifactId,`${e}.artifactId`)}:{kind:"github-actions-artifact",owner:t,repo:a,...i?{runId:v(n.runId,`${e}.runId`)}:{},artifactName:S(n.artifactName,`${e}.artifactName`)}}$(`${e}.kind`,'Expected "url", "path", or "github-actions-artifact"')}(s.installSource,`${n}.meta.installSource`),retainMaterializedPaths:b(s,"retainMaterializedPaths",`${n}.meta`),materializedPathRetentionMs:M(s,"materializedPathRetentionMs",`${n}.meta`),materializationId:y(s,"materializationId",`${n}.meta`),lockPolicy:P(s,"lockPolicy",l,`${n}.meta`),lockPlatform:P(s,"lockPlatform",t,`${n}.meta`)}}});function _(t,e){return{token:y(t,"token",e),session:y(t,"session",e),tenantId:y(t,"tenantId",e),tenant:y(t,"tenant",e),runId:y(t,"runId",e)}}let g=h((t,e)=>{let n=I(t,e);return{..._(n,e),ttlMs:M(n,"ttlMs",e),backend:P(n,"backend",c,e)}}),k=h((t,e)=>{let n,a={record:n=I(t,e),leaseId:y(n,"leaseId",e),ttlMs:M(n,"ttlMs",e)};return{..._(a.record,e),leaseId:a.leaseId,ttlMs:a.ttlMs}}),A=h((t,e)=>{let n=I(t,e);return void 0!==n.ttlMs&&$(`${e}.ttlMs`,"Unexpected field"),{..._(n,e),leaseId:y(n,"leaseId",e)}}),w=h((t,e)=>{let n,a=I(t,e);return{jsonrpc:y(a,"jsonrpc",e),id:(null==(n=a.id)||"string"!=typeof n&&"number"!=typeof n&&$(`${e}.id`,"Expected a string, number, or null"),n),method:y(a,"method",e),params:a.params}});export{l as DAEMON_LOCK_POLICIES,u as DAEMON_SERVER_MODES,m as DAEMON_TRANSPORT_PREFERENCES,c as LEASE_BACKENDS,p as NETWORK_INCLUDE_MODES,f as SESSION_ISOLATION_MODES,a as attachRefs,o as buildSnapshotPresentationKey,d as centerOfRect,R as daemonCommandRequestSchema,O as daemonRuntimeSchema,i as findNodeByRef,e as isSnapshotBackend,w as jsonRpcRequestSchema,g as leaseAllocateSchema,k as leaseHeartbeatSchema,A as leaseReleaseSchema,r as normalizeRef,s as snapshotPresentationOptionsFromFlags,n as usesMobileSnapshotPresentation};
1
+ import"./733.js";import{PLATFORM_SELECTORS as t}from"./5910.js";function e(t){return"xctest"===t||"android"===t||"macos-helper"===t||"linux-atspi"===t||"web"===t}function n(t){return void 0===t||"xctest"===t||"android"===t}function a(t){return t.map((t,e)=>({...t,ref:`e${e+1}`}))}function r(t){let e=t.trim();return e.startsWith("@")?e.slice(1)||null:e.startsWith("e")?e:null}function i(t,e){return t.find(t=>t.ref===e)??null}function o(t){return JSON.stringify({interactiveOnly:t?.interactiveOnly===!0,depth:"number"==typeof t?.depth?t.depth:null,scope:t?.scope?.trim()||null,raw:t?.raw===!0})}function s(t){if(t)return{depth:t.snapshotDepth,interactiveOnly:t.snapshotInteractiveOnly,raw:t.snapshotRaw,scope:t.snapshotScope}}function d(t){return{x:Math.round(t.x+t.width/2),y:Math.round(t.y+t.height/2)}}let l=["reject","strip"],c=["ios-simulator","ios-instance","android-instance"],u=["socket","http","dual"],m=["auto","socket","http"],f=["none","tenant"],p=["summary","headers","body","all"];function h(t){return{parse:e=>t(e,"$")}}function $(t,e){throw Error(`${t}: ${e}`)}function I(t,e){return(!t||"object"!=typeof t||Array.isArray(t))&&$(e,"Expected an object"),t}function E(t,e){return"string"!=typeof t&&$(e,"Expected a string"),t}function v(t,e){let n=E(t,e).trim();return n||$(e,"Expected a non-empty string"),n}function S(t,e){return Number.isInteger(t)||$(e,"Expected an integer"),t}function b(t,e,n){let a=t[e];return void 0===a?void 0:E(a,`${n}.${e}`)}function y(t,e,n){let a=b(t,e,n);if(void 0!==a)return a.trim()&&!(a.length>256)&&/^[\x20-\x7E]+$/.test(a)||$(`${n}.${e}`,"Expected 1-256 printable characters"),a}function P(t,e,n,a){let r=b(t,e,n);if(void 0!==r)return(r.length<1||r.length>a||!/^[a-zA-Z0-9._-]+$/.test(r))&&$(`${n}.${e}`,`Expected 1-${String(a)} chars: letters, numbers, dot, underscore, hyphen`),r}function x(t,e,n){let a=t[e];if(void 0!==a)return"boolean"!=typeof a&&$(`${n}.${e}`,"Expected a boolean"),a}function M(t,e,n){let a=t[e];return void 0===a?void 0:S(a,`${n}.${e}`)}function g(t,e,n){let a=t[e];return void 0===a?void 0:I(a,`${n}.${e}`)}function k(t,e,n,a){let r=t[e];if(void 0!==r)return"string"==typeof r&&n.includes(r)||$(`${a}.${e}`,`Expected one of: ${n.join(", ")}`),r}function N(t,e){let n=I(t,e),a={};for(let[t,r]of Object.entries(n))a[t]=E(r,`${e}.${t}`);return a}let _=h((t,e)=>{let n=I(t,e);return{platform:k(n,"platform",["ios","android"],e),metroHost:b(n,"metroHost",e),metroPort:M(n,"metroPort",e),bundleUrl:b(n,"bundleUrl",e),launchUrl:b(n,"launchUrl",e)}}),A=h((e,n)=>{var a,r;let i=I(e,n),o=(a=i.positionals,r=`${n}.positionals`,Array.isArray(a)||$(r,"Expected an array"),a),s=g(i,"meta",n);return{token:b(i,"token",n),session:b(i,"session",n),command:E(i.command,`${n}.command`),positionals:o.map((t,e)=>E(t,`${n}.positionals[${String(e)}]`)),flags:g(i,"flags",n),runtime:void 0===i.runtime?void 0:_.parse(i.runtime),meta:void 0===s?void 0:{requestId:b(s,"requestId",`${n}.meta`),debug:x(s,"debug",`${n}.meta`),cwd:b(s,"cwd",`${n}.meta`),sessionExplicit:x(s,"sessionExplicit",`${n}.meta`),tenantId:b(s,"tenantId",`${n}.meta`),runId:b(s,"runId",`${n}.meta`),leaseId:b(s,"leaseId",`${n}.meta`),leaseTtlMs:M(s,"leaseTtlMs",`${n}.meta`),leaseBackend:k(s,"leaseBackend",c,`${n}.meta`),leaseProvider:P(s,"leaseProvider",`${n}.meta`,64),deviceKey:y(s,"deviceKey",`${n}.meta`),clientId:P(s,"clientId",`${n}.meta`,128),sessionIsolation:k(s,"sessionIsolation",f,`${n}.meta`),uploadedArtifactId:b(s,"uploadedArtifactId",`${n}.meta`),clientArtifactPaths:void 0===s.clientArtifactPaths?void 0:N(s.clientArtifactPaths,`${n}.meta.clientArtifactPaths`),installSource:void 0===s.installSource?void 0:function(t,e){let n=I(t,e),a=E(n.kind,`${e}.kind`);if("url"===a){let t=E(n.url,`${e}.url`),r=void 0===n.headers?void 0:N(n.headers,`${e}.headers`);return r?{kind:a,url:t,headers:r}:{kind:a,url:t}}if("path"===a)return{kind:a,path:E(n.path,`${e}.path`)};if("github-actions-artifact"===a){let t,a,r,i,o;return t=v(n.owner,`${e}.owner`),a=v(n.repo,`${e}.repo`),r=void 0!==n.artifactId,i=void 0!==n.runId,o=void 0!==n.artifactName,(r&&(i||o)&&$(`${e}`,"Expected either artifactId or artifactName, not both"),r||!i||o||$(`${e}`,"Expected artifactName when runId is specified"),r||o||$(`${e}`,"Expected artifactId or artifactName"),r)?{kind:"github-actions-artifact",owner:t,repo:a,artifactId:S(n.artifactId,`${e}.artifactId`)}:{kind:"github-actions-artifact",owner:t,repo:a,...i?{runId:S(n.runId,`${e}.runId`)}:{},artifactName:v(n.artifactName,`${e}.artifactName`)}}$(`${e}.kind`,'Expected "url", "path", or "github-actions-artifact"')}(s.installSource,`${n}.meta.installSource`),retainMaterializedPaths:x(s,"retainMaterializedPaths",`${n}.meta`),materializedPathRetentionMs:M(s,"materializedPathRetentionMs",`${n}.meta`),materializationId:b(s,"materializationId",`${n}.meta`),lockPolicy:k(s,"lockPolicy",l,`${n}.meta`),lockPlatform:k(s,"lockPlatform",t,`${n}.meta`)}}});function O(t,e){return{token:b(t,"token",e),session:b(t,"session",e),tenantId:b(t,"tenantId",e),tenant:b(t,"tenant",e),runId:b(t,"runId",e),leaseProvider:P(t,"leaseProvider",e,64),deviceKey:y(t,"deviceKey",e),clientId:P(t,"clientId",e,128)}}let R=h((t,e)=>{let n=I(t,e);return{...O(n,e),ttlMs:M(n,"ttlMs",e),backend:k(n,"backend",c,e)}}),w=h((t,e)=>{let n,a={record:n=I(t,e),leaseId:b(n,"leaseId",e),ttlMs:M(n,"ttlMs",e)};return{...O(a.record,e),leaseId:a.leaseId,ttlMs:a.ttlMs,backend:k(a.record,"backend",c,e)}}),K=h((t,e)=>{let n=I(t,e);return void 0!==n.ttlMs&&$(`${e}.ttlMs`,"Unexpected field"),{...O(n,e),leaseId:b(n,"leaseId",e),backend:k(n,"backend",c,e)}}),C=h((t,e)=>{let n,a=I(t,e);return{jsonrpc:b(a,"jsonrpc",e),id:(null==(n=a.id)||"string"!=typeof n&&"number"!=typeof n&&$(`${e}.id`,"Expected a string, number, or null"),n),method:b(a,"method",e),params:a.params}});export{l as DAEMON_LOCK_POLICIES,u as DAEMON_SERVER_MODES,m as DAEMON_TRANSPORT_PREFERENCES,c as LEASE_BACKENDS,p as NETWORK_INCLUDE_MODES,f as SESSION_ISOLATION_MODES,a as attachRefs,o as buildSnapshotPresentationKey,d as centerOfRect,A as daemonCommandRequestSchema,_ as daemonRuntimeSchema,i as findNodeByRef,e as isSnapshotBackend,C as jsonRpcRequestSchema,R as leaseAllocateSchema,w as leaseHeartbeatSchema,K as leaseReleaseSchema,r as normalizeRef,s as snapshotPresentationOptionsFromFlags,n as usesMobileSnapshotPresentation};
package/dist/src/4723.js CHANGED
@@ -1 +1 @@
1
- import e from"node:fs";import t from"node:path";import{AppError as n}from"./733.js";import{PLATFORM_SELECTORS as r}from"./5910.js";import{resolveUserPath as o}from"./9612.js";let i=new Set(["1","true","yes","on"]),a=new Set(["0","false","no","off"]);function s(e){return`AGENT_DEVICE_${e.replace(/([A-Z])/g,"_$1").replace(/[^A-Za-z0-9_]/g,"_").toUpperCase()}`}function l(e,t,r,o){if(e.multiple)return(Array.isArray(t)?t:[t]).map(t=>l({...e,multiple:!1},t,r,o));if("boolean"===e.type){var i=t,a=r,s=o;if("boolean"==typeof i)return i;if("string"==typeof i){let e=u(i);if(void 0!==e)return e}throw new n("INVALID_ARGS",`Invalid value for "${s}" in ${a}. Expected boolean.`)}if("booleanOrString"===e.type){if("boolean"==typeof t)return t;if("string"==typeof t&&void 0!==u(t))return u(t);if("string"==typeof t&&t.trim().length>0)return t;throw new n("INVALID_ARGS",`Invalid value for "${o}" in ${r}. Expected boolean or non-empty string.`)}if("string"===e.type){if("string"==typeof t&&t.trim().length>0)return t;throw new n("INVALID_ARGS",`Invalid value for "${o}" in ${r}. Expected non-empty string.`)}if("enum"===e.type){if(void 0!==e.setValue){var f=e,y=t,p=r,m=o;let i=f.setValue;if(y===i)return i;if("string"==typeof y){let e=y.trim();if(""===e||"true"===e||"1"===e)return i;if("false"===e||"0"===e)return}if(!0===y)return i;if(!1!==y)throw new n("INVALID_ARGS",`Invalid value for "${m}" in ${p}. Expected boolean-like value for enum flag.`);return}if("string"!=typeof t||!e.enumValues?.includes(t))throw new n("INVALID_ARGS",`Invalid value for "${o}" in ${r}. Expected one of: ${e.enumValues?.join(", ")}.`);return t}let c="number"==typeof t?t:"string"==typeof t?Number(t):NaN;if(!Number.isFinite(c)||!Number.isInteger(c))throw new n("INVALID_ARGS",`Invalid value for "${o}" in ${r}. Expected integer.`);if("number"==typeof e.min&&c<e.min)throw new n("INVALID_ARGS",`Invalid value for "${o}" in ${r}. Must be >= ${e.min}.`);if("number"==typeof e.max&&c>e.max)throw new n("INVALID_ARGS",`Invalid value for "${o}" in ${r}. Must be <= ${e.max}.`);return c}function u(e){let t=e.trim().toLowerCase();return!!i.has(t)||!a.has(t)&&void 0}let f=[{key:"stateDir",type:"string",path:!0},{key:"daemonBaseUrl",type:"string"},{key:"daemonAuthToken",type:"string"},{key:"daemonTransport",type:"enum",enumValues:["auto","socket","http"]},{key:"daemonServerMode",type:"enum",enumValues:["socket","http","dual"]},{key:"tenant",type:"string"},{key:"sessionIsolation",type:"enum",enumValues:["none","tenant"]},{key:"runId",type:"string"},{key:"leaseId",type:"string"},{key:"leaseBackend",type:"enum",enumValues:["ios-simulator","ios-instance","android-instance"]},{key:"platform",type:"enum",enumValues:r},{key:"target",type:"enum",enumValues:["mobile","tv","desktop"]},{key:"device",type:"string"},{key:"udid",type:"string"},{key:"serial",type:"string"},{key:"iosSimulatorDeviceSet",type:"string",path:!0,env:!1},{key:"androidDeviceAllowlist",type:"string"},{key:"session",type:"string"},{key:"metroProjectRoot",type:"string",path:!0},{key:"metroKind",type:"enum",enumValues:["auto","react-native","expo"]},{key:"metroPublicBaseUrl",type:"string"},{key:"metroProxyBaseUrl",type:"string"},{key:"metroBearerToken",type:"string"},{key:"metroPreparePort",type:"int",min:1,max:65535},{key:"metroListenHost",type:"string"},{key:"metroStatusHost",type:"string"},{key:"metroStartupTimeoutMs",type:"int",min:1},{key:"metroProbeTimeoutMs",type:"int",min:1},{key:"metroRuntimeFile",type:"string",path:!0},{key:"metroNoReuseExisting",type:"boolean"},{key:"metroNoInstallDeps",type:"boolean"}],y=new Map(f.map(e=>[e.key,e]));function p(e){let t=e.env??process.env;return o(e.configPath,{cwd:e.cwd,env:t})}function m(r){let i=function(r){let i,a,s=r.env??process.env,u=p(r);if(!e.existsSync(u))throw new n("INVALID_ARGS",`Remote config file not found: ${u}`);try{i=e.readFileSync(u,"utf8")}catch(e){throw new n("INVALID_ARGS",`Failed to read remote config file: ${u}`,{cause:e instanceof Error?e.message:String(e)})}try{a=JSON.parse(i)}catch(e){throw new n("INVALID_ARGS",`Invalid JSON in remote config file: ${u}`,{cause:e instanceof Error?e.message:String(e)})}if(!a||"object"!=typeof a||Array.isArray(a))throw new n("INVALID_ARGS",`Remote config file must contain a JSON object: ${u}`);let f={},m=a,c=t.dirname(u);for(let[e,t]of Object.entries(m)){let r=y.get(e);if(!r)throw new n("INVALID_ARGS",`Unsupported remote config key "${e}" in remote config file ${u}.`);let i=l(r,t,`remote config file ${u}`,e);f[r.key]="string"==typeof i&&"path"in r&&r.path?o(i,{cwd:c,env:s}):i}return{resolvedPath:u,profile:f}}(r);return{resolvedPath:i.resolvedPath,profile:function(...e){let t={};for(let n of e)if(n)for(let e of f){let r=n[e.key];void 0!==r&&(t[e.key]=r)}return t}(function(e=process.env){let t={};for(let n of f){let r=(function(e){let t=y.get(e);return t?.env===!1?[]:[s(e)]})(n.key).map(t=>({name:t,value:e[t]})).find(e=>"string"==typeof e.value&&e.value.trim().length>0);r&&(t[n.key]=l(n,r.value,`environment variable ${r.name}`,r.name))}return t}(r.env),i.profile)}}export{f as REMOTE_CONFIG_FIELD_SPECS,s as buildPrimaryEnvVarName,l as parseSourceValue,p as resolveRemoteConfigPath,m as resolveRemoteConfigProfile};
1
+ import e from"node:fs";import t from"node:path";import{AppError as n}from"./733.js";import{PLATFORM_SELECTORS as r}from"./5910.js";import{resolveUserPath as o}from"./9612.js";let i=new Set(["1","true","yes","on"]),a=new Set(["0","false","no","off"]);function s(e){return`AGENT_DEVICE_${e.replace(/([A-Z])/g,"_$1").replace(/[^A-Za-z0-9_]/g,"_").toUpperCase()}`}function l(e,t,r,o){if(e.multiple)return(Array.isArray(t)?t:[t]).map(t=>l({...e,multiple:!1},t,r,o));if("boolean"===e.type){var i=t,a=r,s=o;if("boolean"==typeof i)return i;if("string"==typeof i){let e=u(i);if(void 0!==e)return e}throw new n("INVALID_ARGS",`Invalid value for "${s}" in ${a}. Expected boolean.`)}if("booleanOrString"===e.type){if("boolean"==typeof t)return t;if("string"==typeof t&&void 0!==u(t))return u(t);if("string"==typeof t&&t.trim().length>0)return t;throw new n("INVALID_ARGS",`Invalid value for "${o}" in ${r}. Expected boolean or non-empty string.`)}if("string"===e.type){if("string"==typeof t&&t.trim().length>0)return t;throw new n("INVALID_ARGS",`Invalid value for "${o}" in ${r}. Expected non-empty string.`)}if("enum"===e.type){if(void 0!==e.setValue){var y=e,f=t,p=r,m=o;let i=y.setValue;if(f===i)return i;if("string"==typeof f){let e=f.trim();if(""===e||"true"===e||"1"===e)return i;if("false"===e||"0"===e)return}if(!0===f)return i;if(!1!==f)throw new n("INVALID_ARGS",`Invalid value for "${m}" in ${p}. Expected boolean-like value for enum flag.`);return}if("string"!=typeof t||!e.enumValues?.includes(t))throw new n("INVALID_ARGS",`Invalid value for "${o}" in ${r}. Expected one of: ${e.enumValues?.join(", ")}.`);return t}let g="number"==typeof t?t:"string"==typeof t?Number(t):NaN;if(!Number.isFinite(g)||!Number.isInteger(g))throw new n("INVALID_ARGS",`Invalid value for "${o}" in ${r}. Expected integer.`);if("number"==typeof e.min&&g<e.min)throw new n("INVALID_ARGS",`Invalid value for "${o}" in ${r}. Must be >= ${e.min}.`);if("number"==typeof e.max&&g>e.max)throw new n("INVALID_ARGS",`Invalid value for "${o}" in ${r}. Must be <= ${e.max}.`);return g}function u(e){let t=e.trim().toLowerCase();return!!i.has(t)||!a.has(t)&&void 0}let y=[{key:"stateDir",type:"string",path:!0},{key:"daemonBaseUrl",type:"string"},{key:"daemonAuthToken",type:"string"},{key:"daemonTransport",type:"enum",enumValues:["auto","socket","http"]},{key:"daemonServerMode",type:"enum",enumValues:["socket","http","dual"]},{key:"tenant",type:"string"},{key:"sessionIsolation",type:"enum",enumValues:["none","tenant"]},{key:"runId",type:"string"},{key:"leaseId",type:"string"},{key:"leaseBackend",type:"enum",enumValues:["ios-simulator","ios-instance","android-instance"]},{key:"platform",type:"enum",enumValues:r},{key:"target",type:"enum",enumValues:["mobile","tv","desktop"]},{key:"device",type:"string"},{key:"udid",type:"string"},{key:"serial",type:"string"},{key:"iosSimulatorDeviceSet",type:"string",path:!0,env:!1},{key:"androidDeviceAllowlist",type:"string"},{key:"session",type:"string"},{key:"metroProjectRoot",type:"string",path:!0},{key:"metroKind",type:"enum",enumValues:["auto","react-native","expo"]},{key:"metroPublicBaseUrl",type:"string"},{key:"metroProxyBaseUrl",type:"string"},{key:"metroBearerToken",type:"string"},{key:"metroPreparePort",type:"int",min:1,max:65535},{key:"metroListenHost",type:"string"},{key:"metroStatusHost",type:"string"},{key:"metroStartupTimeoutMs",type:"int",min:1},{key:"metroProbeTimeoutMs",type:"int",min:1},{key:"metroRuntimeFile",type:"string",path:!0},{key:"metroNoReuseExisting",type:"boolean"},{key:"metroNoInstallDeps",type:"boolean"}],f=[...y,{key:"leaseProvider",type:"string",env:!1},{key:"deviceKey",type:"string",env:!1},{key:"clientId",type:"string",env:!1}],p=new Map(f.map(e=>[e.key,e]));function m(e){let t=e.env??process.env;return o(e.configPath,{cwd:e.cwd,env:t})}function g(r){let i=function(r){let i,a,s=r.env??process.env,u=m(r);if(!e.existsSync(u))throw new n("INVALID_ARGS",`Remote config file not found: ${u}`);try{i=e.readFileSync(u,"utf8")}catch(e){throw new n("INVALID_ARGS",`Failed to read remote config file: ${u}`,{cause:e instanceof Error?e.message:String(e)})}try{a=JSON.parse(i)}catch(e){throw new n("INVALID_ARGS",`Invalid JSON in remote config file: ${u}`,{cause:e instanceof Error?e.message:String(e)})}if(!a||"object"!=typeof a||Array.isArray(a))throw new n("INVALID_ARGS",`Remote config file must contain a JSON object: ${u}`);let y={},f=a,g=t.dirname(u);for(let[e,t]of Object.entries(f)){let r=p.get(e);if(!r)throw new n("INVALID_ARGS",`Unsupported remote config key "${e}" in remote config file ${u}.`);let i=l(r,t,`remote config file ${u}`,e);y[r.key]="string"==typeof i&&"path"in r&&r.path?o(i,{cwd:g,env:s}):i}return{resolvedPath:u,profile:y}}(r);return{resolvedPath:i.resolvedPath,profile:function(...e){let t={};for(let n of e)if(n)for(let e of f){let r=n[e.key];void 0!==r&&(t[e.key]=r)}return t}(function(e=process.env){let t={};for(let n of f){let r=(function(e){let t=p.get(e);return t?.env===!1?[]:[s(e)]})(n.key).map(t=>({name:t,value:e[t]})).find(e=>"string"==typeof e.value&&e.value.trim().length>0);r&&(t[n.key]=l(n,r.value,`environment variable ${r.name}`,r.name))}return t}(r.env),i.profile)}}export{y as REMOTE_CONFIG_FIELD_SPECS,s as buildPrimaryEnvVarName,l as parseSourceValue,m as resolveRemoteConfigPath,g as resolveRemoteConfigProfile};
@@ -0,0 +1 @@
1
+ import{AppError as e}from"./733.js";let t={alert:"alert",appState:"appstate",appSwitcher:"app-switcher",apps:"apps",back:"back",batch:"batch",boot:"boot",click:"click",close:"close",clipboard:"clipboard",devices:"devices",diff:"diff",fill:"fill",find:"find",focus:"focus",gesture:"gesture",get:"get",home:"home",install:"install",installFromSource:"install-from-source",is:"is",keyboard:"keyboard",logs:"logs",longPress:"longpress",network:"network",open:"open",perf:"perf",prepare:"prepare",press:"press",push:"push",record:"record",reactNative:"react-native",reinstall:"reinstall",replay:"replay",rotate:"rotate",scroll:"scroll",screenshot:"screenshot",settings:"settings",shutdown:"shutdown",snapshot:"snapshot",swipe:"swipe",test:"test",trace:"trace",triggerAppEvent:"trigger-app-event",type:"type",viewport:"viewport",wait:"wait"},r={installSource:"install_source",leaseAllocate:"lease_allocate",leaseHeartbeat:"lease_heartbeat",leaseRelease:"lease_release",releaseMaterializedPaths:"release_materialized_paths",runtime:"runtime",sessionList:"session_list"},n={cdp:"cdp",auth:"auth",connect:"connect",connection:"connection",debug:"debug",disconnect:"disconnect",mcp:"mcp",metro:"metro",proxy:"proxy",reactDevtools:"react-devtools",session:"session",web:"web"},o=["pan","fling","swipe","pinch","rotate","transform"],i=`gesture requires one of: ${o.join(", ")}`,s=a(n.auth,n.cdp,n.connect,n.connection,n.disconnect,n.mcp,n.proxy,n.reactDevtools,n.web,t.prepare);function a(...e){return new Set(e)}function c(){return[...Object.values(t),...Object.values(n)].sort()}function l(e){return Object.values(t).includes(e)||e===n.debug||e===n.metro||e===n.session}function u(){return c().filter(e=>!s.has(e))}function p(t,r,n,o){let i=n(t[r]);if(void 0===i)throw new e("COMMAND_FAILED",o,{response:t});return i}function d(e,t){return p(e,t,A,`Daemon response is missing "${t}".`)}function f(e,t){return A(e[t])}function m(e,t){var r;let n;return r=A,null===(n=e[t])?null:r(n)}function h(e,t){return p(e,t,N,`Daemon response is missing numeric "${t}".`)}function g(e,t){return p(e,t,D,`Daemon response has invalid "${t}".`)}function v(e,t){return p(e,t,C,`Daemon response has invalid "${t}".`)}function b(e,t){return function(e){return"tv"===e||"mobile"===e||"desktop"===e?e:void 0}(e[t])??"mobile"}function w(e){if(!E(e))return;let t=_(e,"x"),r=_(e,"y"),n=_(e,"width"),o=_(e,"height");if(void 0!==t&&void 0!==r&&void 0!==n&&void 0!==o)return{x:t,y:r,width:n,height:o}}function S(e){if(!E(e))return;let t=_(e,"x"),r=_(e,"y");if(void 0!==t&&void 0!==r)return{x:t,y:r}}function _(e,t){let r=e[t];return"number"==typeof r?r:void 0}function A(e){return"string"==typeof e&&e.length>0?e:void 0}function N(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function D(e){return"ios"===e||"macos"===e||"android"===e||"linux"===e||"web"===e?e:void 0}function C(e){return"simulator"===e||"emulator"===e||"device"===e?e:void 0}a(n.auth,n.cdp,n.connect,n.connection,n.debug,n.disconnect,n.mcp,n.metro,n.proxy,n.reactDevtools,n.session,n.web,t.appState,t.prepare,t.batch,t.devices,t.gesture,t.replay,t.test,t.trace);function y(t){if(!E(t))throw new e("COMMAND_FAILED","Daemon returned an unexpected response shape.",{value:t});return t}function E(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}function R(e){let t={};for(let[r,n]of Object.entries(e))void 0!==n&&(t[r]=n);return t}function M(e){return e.split("\n").map(e=>e.trim()).filter(e=>e.length>0)}let O=[t.devices,t.boot,t.shutdown,t.apps,t.open,t.close,t.install,t.reinstall,t.installFromSource,t.push,t.triggerAppEvent,t.snapshot,t.screenshot,t.diff,t.wait,t.alert,t.settings,t.click,t.press,t.longPress,t.swipe,t.focus,t.type,t.fill,t.scroll,t.get,t.gesture,t.is,t.find,t.perf,t.logs,t.network,t.record,t.trace,t.test,t.appState,t.back,t.home,t.rotate,t.appSwitcher,t.keyboard,t.clipboard,t.reactNative],k=new Set(["batch","replay"]),T=["command","positionals","flags","runtime"],B=["platform","target","device","udid","serial","verbose","out"],I=new Set(O);function L(e){return"string"==typeof e?e.trim().toLowerCase():""}function x(t,r){let n=L(t);if(I.has(n))return n;throw new e("INVALID_ARGS",`Batch step ${r} command is not available through command batch: ${String(t)}`)}function P(t,r){if(k.has(t))throw new e("INVALID_ARGS",`Batch step ${r} cannot run ${t}.`)}export{k as BATCH_BLOCKED_COMMANDS,T as BATCH_DAEMON_STEP_KEYS,o as GESTURE_KINDS,i as GESTURE_SUBCOMMAND_ERROR,B as INHERITED_PARENT_FLAG_KEYS,r as INTERNAL_COMMANDS,t as PUBLIC_COMMANDS,O as STRUCTURED_BATCH_COMMAND_NAMES,y as asRecord,P as assertBatchRuntimeCommandAllowed,l as isClientBackedCliCommandName,E as isRecord,c as listCliCommandNames,u as listMcpExposedCommandNames,L as normalizeBatchCommandName,S as parsePoint,w as parseRect,b as readDeviceTarget,m as readNullableString,f as readOptionalString,v as readRequiredDeviceKind,h as readRequiredNumber,g as readRequiredPlatform,d as readRequiredString,x as readStructuredBatchCommandName,M as splitNonEmptyTrimmedLines,R as stripUndefined};
@@ -0,0 +1 @@
1
+ import n from"node:path";function e(n){return"web"===n?".webm":".mp4"}function r(e,r){return n.extname(e)?e:`${e}${r}`}function o(n){return`./recording-${Date.now()}${e(n)}`}export{r as appendRecordingExtensionWhenMissing,o as defaultRecordingPath,e as recordingExtensionForPlatform};
package/dist/src/6918.js CHANGED
@@ -1 +1 @@
1
- import{asAppError as t,AppError as e}from"./733.js";import{normalizeBatchCommandName as r,INHERITED_PARENT_FLAG_KEYS as o,assertBatchRuntimeCommandAllowed as a,BATCH_DAEMON_STEP_KEYS as n}from"./2133.js";let s=new Set(n);async function i(e,r,o){let a=e.flags,n=a?.batchOnError??"stop";if("stop"!==n)return p("INVALID_ARGS",`Unsupported batch on-error mode: ${n}.`);let s=a?.batchMaxSteps??100;if(!Number.isInteger(s)||s<1||s>1e3)return p("INVALID_ARGS",`Invalid batch max-steps: ${String(a?.batchMaxSteps)}`);try{let t=l(a?.batchSteps,s),n=Date.now(),i=[];for(let[a,n]of t.entries()){let s=await h(e,r,n,o,a+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:a,total:t.length,partialResults:i}}};i.push(s.result)}return{ok:!0,data:{total:t.length,executed:t.length,totalDurationMs:Date.now()-n,results:i}}}catch(r){let e=t(r);return p(e.code,e.message,e.details)}}function l(t,o){if(!Array.isArray(t)||0===t.length)throw new e("INVALID_ARGS","batch requires a non-empty batchSteps array.");if(t.length>o)throw new e("INVALID_ARGS",`batch has ${t.length} steps; max allowed is ${o}.`);let n=[];for(let o=0;o<t.length;o+=1){let i=t[o];if(!i||"object"!=typeof i)throw new e("INVALID_ARGS",`Invalid batch step at index ${o}.`);let l=Object.keys(i).filter(t=>!s.has(t));if(l.length>0){let t=l.map(t=>`"${t}"`).join(", ");throw new e("INVALID_ARGS",`Batch step ${o+1} has unknown field(s): ${t}. Allowed fields: command, positionals, flags, runtime.`)}let c=r(i.command);if(!c)throw new e("INVALID_ARGS",`Batch step ${o+1} requires command.`);if(a(c,o+1),void 0!==i.positionals&&!Array.isArray(i.positionals))throw new e("INVALID_ARGS",`Batch step ${o+1} positionals must be an array.`);let m=i.positionals??[];if(m.some(t=>"string"!=typeof t))throw new e("INVALID_ARGS",`Batch step ${o+1} positionals must contain only strings.`);if(void 0!==i.flags&&("object"!=typeof i.flags||Array.isArray(i.flags)||!i.flags))throw new e("INVALID_ARGS",`Batch step ${o+1} flags must be an object.`);if(void 0!==i.runtime&&("object"!=typeof i.runtime||Array.isArray(i.runtime)||!i.runtime))throw new e("INVALID_ARGS",`Batch step ${o+1} runtime must be an object.`);n.push({command:c,positionals:m,flags:i.flags??{},runtime:i.runtime})}return n}function c(t,e){let{batchSteps:r,batchOnError:o,batchMaxSteps:a,...n}=e??{};return m(t,n)}function m(t,e){let r=t??{};for(let t of o)void 0===e[t]&&void 0!==r[t]&&(e[t]=r[t]);return e}async function h(t,e,r,o,a){let n=Date.now(),s=c(t.flags,r.flags);void 0===s.session&&(s.session=e);let i=await o({token:t.token,session:e,command:r.command,positionals:r.positionals,flags:s,runtime:void 0===r.runtime?t.runtime:r.runtime,meta:t.meta}),l=Date.now()-n;return i.ok?{ok:!0,step:a,result:{step:a,command:r.command,ok:!0,data:i.data??{},durationMs:l}}:{ok:!1,step:a,error:i.error}}function p(t,e,r){return{ok:!1,error:{code:t,message:e,...r?{details:r}:{}}}}export{c as buildBatchStepFlags,m as mergeParentFlags,i as runBatch,l as validateAndNormalizeBatchSteps};
1
+ import{daemonRuntimeSchema as t}from"./4291.js";import{asAppError as e,AppError as r}from"./733.js";import{normalizeBatchCommandName as o,isRecord as a,INHERITED_PARENT_FLAG_KEYS as n,assertBatchRuntimeCommandAllowed as s,BATCH_DAEMON_STEP_KEYS as i}from"./5341.js";let l=new Set(i);async function c(t,r,o){let a=t.flags,n=a?.batchOnError??"stop";if("stop"!==n)return u("INVALID_ARGS",`Unsupported batch on-error mode: ${n}.`);let s=a?.batchMaxSteps??100;if(!Number.isInteger(s)||s<1||s>1e3)return u("INVALID_ARGS",`Invalid batch max-steps: ${String(a?.batchMaxSteps)}`);try{let e=m(a?.batchSteps,s),n=Date.now(),i=[];for(let[a,n]of e.entries()){let s=await d(t,r,n,o,a+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:a,total:e.length,partialResults:i}}};i.push(s.result)}let l={total:e.length,executed:e.length,totalDurationMs:Date.now()-n,results:i};return{ok:!0,data:l}}catch(r){let t=e(r);return u(t.code,t.message,t.details)}}function m(e,n){if(!Array.isArray(e)||0===e.length)throw new r("INVALID_ARGS","batch requires a non-empty batchSteps array.");if(e.length>n)throw new r("INVALID_ARGS",`batch has ${e.length} steps; max allowed is ${n}.`);let i=[];for(let n=0;n<e.length;n+=1){let c=e[n];if(!a(c))throw new r("INVALID_ARGS",`Invalid batch step at index ${n}.`);let m=Object.keys(c).filter(t=>!l.has(t));if(m.length>0){let t=m.map(t=>`"${t}"`).join(", ");throw new r("INVALID_ARGS",`Batch step ${n+1} has unknown field(s): ${t}. Allowed fields: command, positionals, flags, runtime.`)}let h=o(c.command);if(!h)throw new r("INVALID_ARGS",`Batch step ${n+1} requires command.`);if(s(h,n+1),void 0!==c.positionals&&!Array.isArray(c.positionals))throw new r("INVALID_ARGS",`Batch step ${n+1} positionals must be an array.`);let p=c.positionals??[];if(p.some(t=>"string"!=typeof t))throw new r("INVALID_ARGS",`Batch step ${n+1} positionals must contain only strings.`);if(void 0!==c.flags&&!a(c.flags))throw new r("INVALID_ARGS",`Batch step ${n+1} flags must be an object.`);i.push({command:h,positionals:p,flags:c.flags??{},runtime:function(e,o){if(void 0!==e)try{return t.parse(e)}catch(t){throw new r("INVALID_ARGS",`Batch step ${o} runtime is invalid: ${t instanceof Error?t.message:String(t)}`)}}(c.runtime,n+1)})}return i}function h(t,e){let{batchSteps:r,batchOnError:o,batchMaxSteps:a,...n}=e??{};return p(t,n)}function p(t,e){let r=t??{};for(let t of n)void 0===e[t]&&void 0!==r[t]&&(e[t]=r[t]);return e}async function d(t,e,r,o,a){let n=Date.now(),s=h(t.flags,r.flags);void 0===s.session&&(s.session=e);let i=await o({token:t.token,session:e,command:r.command,positionals:r.positionals,flags:s,runtime:void 0===r.runtime?t.runtime:r.runtime,meta:t.meta}),l=Date.now()-n;return i.ok?{ok:!0,step:a,result:{step:a,command:r.command,ok:!0,data:i.data??{},durationMs:l}}:{ok:!1,step:a,error:i.error}}function u(t,e,r){return{ok:!1,error:{code:t,message:e,...r?{details:r}:{}}}}export{h as buildBatchStepFlags,p as mergeParentFlags,c as runBatch,m as validateAndNormalizeBatchSteps};
package/dist/src/8275.js CHANGED
@@ -1,2 +1,2 @@
1
- import e from"node:fs";import t from"node:path";import{createHash as r}from"node:crypto";import{fileURLToPath as n}from"node:url";import{runCmdDetached as o,runCmdSync as i}from"./8875.js";import{readProcessCommand as a,waitForProcessExit as s,resolveRuntimeTransportHints as l,isProcessAlive as u,readProcessStartTime as c}from"./5628.js";import{normalizeBaseUrl as d,ENV_COMPANION_TUNNEL_BEARER_TOKEN as p,ENV_COMPANION_TUNNEL_SERVER_BASE_URL as m,ENV_COMPANION_TUNNEL_STATE_PATH as h,ENV_COMPANION_TUNNEL_LAUNCH_URL as f,ENV_COMPANION_TUNNEL_SCOPE_LEASE_ID as g,ENV_COMPANION_TUNNEL_SCOPE_TENANT_ID as y,ENV_COMPANION_TUNNEL_DEVICE_PORT as b,buildBundleUrl as P,METRO_COMPANION_RUN_ARG as S,ENV_COMPANION_TUNNEL_SESSION as w,ENV_COMPANION_TUNNEL_SCOPE_RUN_ID as E,ENV_COMPANION_TUNNEL_REGISTER_PATH as _,ENV_COMPANION_TUNNEL_LOCAL_BASE_URL as v,ENV_COMPANION_TUNNEL_UNREGISTER_PATH as U}from"./4069.js";import{AppError as M}from"./733.js";import{resolveUserPath as I}from"./9612.js";import{sleep as k}from"./5560.js";let T="companion-tunnel";function A(e){return r("sha256").update(e).digest("hex")}function N(e){return e?.trim()?e.trim():void 0}function R(e,r,n,o){let i=o??t.join(e,".agent-device");if(!n)return{statePath:t.join(i,`${r.slug}.json`),logPath:t.join(i,`${r.slug}.log`)};let a=A(n).slice(0,12),s=t.join(i,r.slug);return{statePath:t.join(s,`${r.slug}-${a}.json`),logPath:t.join(s,`${r.slug}-${a}.log`)}}function $(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:N("string"==typeof r.launchUrl?r.launchUrl:void 0),registerPath:N("string"==typeof r.registerPath?r.registerPath:void 0),unregisterPath:N("string"==typeof r.unregisterPath?r.unregisterPath:void 0),devicePort:Number.isInteger(r.devicePort)?Number(r.devicePort):void 0,session:N("string"==typeof r.session?r.session: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}}(r.bridgeScope),tokenHash:r.tokenHash,consumers:n}}catch{return null}}function x(r,n){e.mkdirSync(t.dirname(r),{recursive:!0}),e.writeFileSync(r,`${JSON.stringify(n,null,2)}
2
- `,"utf8")}function j(t){try{let r=e.readdirSync(t);0===r.length&&e.rmdirSync(t)}catch{}}function B(r,n){let o=t.dirname(r.statePath),i=t.dirname(r.logPath);var a=r.statePath;try{e.unlinkSync(a)}catch{}var s=r.logPath;try{e.unlinkSync(s)}catch{}j(o),i!==o&&j(i),t.basename(o)===n.slug&&j(t.dirname(o))}function C(e,t){return e.includes(t.runArg)}function D(e){return N(e.consumerKey)??N(e.profileKey)??null}function H(e,t){return!t||e.consumers.includes(t)?e:{...e,consumers:[...e.consumers,t]}}async function K(e,t){if(!u(e.pid))return;let r=a(e.pid);if(r&&C(r,t)){try{process.kill(e.pid,"SIGTERM")}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return;throw t}if(!await s(e.pid,1e3)){try{process.kill(e.pid,"SIGKILL")}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return;throw t}await s(e.pid,1e3)}}}async function O(r){var i;let s,l=D(r),P=R(r.projectRoot,r.definition,r.profileKey,r.stateDir),S=$(P.statePath);if(S&&function(e,t){var r,n;if(!u(e.pid))return!1;if(e.startTime){let t=c(e.pid);if(!t||t!==e.startTime)return!1}let o=a(e.pid);return!!o&&!!C(o,t.definition)&&!!e.bridgeScope&&e.serverBaseUrl===d(t.serverBaseUrl)&&e.localBaseUrl===d(t.localBaseUrl)&&e.launchUrl===N(t.launchUrl)&&e.registerPath===N(t.registerPath)&&e.unregisterPath===N(t.unregisterPath)&&e.devicePort===t.devicePort&&e.session===N(t.session)&&(r=e.bridgeScope,n=t.bridgeScope,r.tenantId===n.tenantId&&r.runId===n.runId&&r.leaseId===n.leaseId)&&e.tokenHash===A(t.bearerToken)}(S,r)){let e=H(S,l);return e!==S&&x(P.statePath,e),{pid:S.pid,spawned:!1,statePath:P.statePath,logPath:P.logPath}}S&&(await K(S,r.definition),B(P,r.definition)),i=P.statePath,e.mkdirSync(t.dirname(i),{recursive:!0}),e.closeSync(e.openSync(i,"a"));try{s=function(r,i){let s=function(r){let o=n(import.meta.url),i=t.extname(o)||".js",a=[t.join(t.dirname(o),`${T}${i}`),t.join(t.dirname(o),"internal",`${T}${i}`)].find(t=>e.existsSync(t));if(!a)throw Error(`${r.displayName} entrypoint not found. Rebuild the package to include the companion worker entry.`);return a}(r.definition),l=s.endsWith(".ts")?["--experimental-strip-types"]:[];e.mkdirSync(t.dirname(i),{recursive:!0});let u=e.openSync(i,"a"),P=0;try{let e;P=o(process.execPath,[...l,s,r.definition.runArg],{env:((e={...r.env??process.env})[m]=d(r.serverBaseUrl),e[p]=r.bearerToken,e[v]=d(r.localBaseUrl),e[h]=R(r.projectRoot,r.definition,r.profileKey,r.stateDir).statePath,e[y]=r.bridgeScope.tenantId,e[E]=r.bridgeScope.runId,e[g]=r.bridgeScope.leaseId,r.launchUrl?.trim()?e[f]=r.launchUrl.trim():delete e[f],r.registerPath?.trim()?e[_]=r.registerPath.trim():delete e[_],r.unregisterPath?.trim()?e[U]=r.unregisterPath.trim():delete e[U],void 0!==r.devicePort?e[b]=String(r.devicePort):delete e[b],r.session?.trim()?e[w]=r.session.trim():delete e[w],e),stdio:["ignore",u,u]})}finally{e.closeSync(u)}if(!Number.isInteger(P)||P<=0)throw Error(`Failed to start ${r.definition.displayName} process.`);return{pid:P,startTime:c(P)??void 0,command:a(P)??void 0,serverBaseUrl:d(r.serverBaseUrl),localBaseUrl:d(r.localBaseUrl),launchUrl:N(r.launchUrl),registerPath:N(r.registerPath),unregisterPath:N(r.unregisterPath),devicePort:r.devicePort,session:N(r.session),bridgeScope:r.bridgeScope,tokenHash:A(r.bearerToken),consumers:[]}}(r,P.logPath),x(P.statePath,H(s,l))}catch(e){throw s&&await K(s,r.definition).catch(()=>{}),B(P,r.definition),e}return{pid:s.pid,spawned:!0,statePath:P.statePath,logPath:P.logPath}}async function L(e){let t=D(e),r=R(e.projectRoot,e.definition,e.profileKey,e.stateDir),n=$(r.statePath);if(!n)return B(r,e.definition),{stopped:!1,statePath:r.statePath};let o=t?{...n,consumers:n.consumers.filter(e=>e!==t)}:{...n,consumers:[]};return o.consumers.length>0?(x(r.statePath,o),{stopped:!1,statePath:r.statePath}):(await K(n,e.definition),B(r,e.definition),{stopped:!0,statePath:r.statePath})}let G={slug:"metro-companion",runArg:S,displayName:"Metro companion"};async function F(e){return await O({...e,definition:G,registerPath:e.registerPath??"/api/metro/companion/register"})}async function J(e){return await L({...e,definition:G})}function V(e){return"string"==typeof e&&e.trim()?d(e.trim()):""}function q(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function W(e,t,r){return I(e,{env:t,cwd:r})}function z(t){try{return e.accessSync(t,e.constants.F_OK),!0}catch{return!1}}function Q(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 X(e,t){if(null==e||""===e)return t;let r=Number.parseInt(String(e),10);if(!Number.isInteger(r)||r<1||r>65535)throw new M("INVALID_ARGS",`Invalid Metro port: ${String(e)}. Use 1-65535.`);return r}function Y(e,t){return{platform:t,bundleUrl:P(e,t)}}function Z(e,t){return{platform:t,metroHost:q(e?.metro_host),metroPort:e?.metro_port,bundleUrl:q(e?.metro_bundle_url),launchUrl:q(e?.launch_url)}}async function ee(e){await k(e)}async function et(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 er(e,t){try{let r=await et(e,t);return r.ok&&r.body.includes("packager-status:running")}catch{return!1}}async function en(e){if(Number.isInteger(e)&&!(e<=0)){try{process.kill(e,"SIGTERM")}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return;throw t}if(!await s(e,1e3)){try{process.kill(e,"SIGKILL")}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return;throw t}await s(e,1e3)}}}function eo(e,t){let r=Error(e);return r.retryable=t,r}function ei(e,t){return!!(e>=500||408===e||425===e||429===e||JSON.stringify(t).includes("Metro companion is not connected"))}function ea(e){return!!(e&&"object"==typeof e&&"retryable"in e&&!0===e.retryable)}async function es(e){let t;try{var r,n;t=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:"POST",headers:(r=e.baseUrl,n=e.bearerToken,{Authorization:`Bearer ${n}`,"Content-Type":"application/json",...r.includes("ngrok")?{"ngrok-skip-browser-warning":"1"}:{}}),body:JSON.stringify({...e.scope,...e.runtime?{ios_runtime:e.runtime}:{},timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(t){if(t instanceof Error&&"TimeoutError"===t.name)throw eo(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0);throw eo(t instanceof Error?t.message:String(t),!0)}let o=function(e,t,r){if(!e)return{};try{let t=JSON.parse(e);if(!t||"object"!=typeof t||Array.isArray(t))throw Error("Expected a JSON object");return t}catch(i){let n=e.slice(0,200),o=i instanceof Error?i.message:String(i);throw eo(`/api/metro/bridge returned invalid JSON (${t}) from ${r}: ${o}. body=${JSON.stringify(n)}`,ei(t,e))}}(await t.text(),t.status,e.baseUrl);if(!t.ok)throw eo(`/api/metro/bridge failed (${t.status}): ${JSON.stringify(o)}`,ei(t.status,o));var i=o;let a=i.data??i;if(!a||"object"!=typeof a||Array.isArray(a))throw eo("/api/metro/bridge returned malformed descriptor: Expected a JSON object.",!1);try{return{enabled:a.enabled,baseUrl:a.base_url,statusUrl:a.status_url??"",bundleUrl:a.bundle_url??"",iosRuntime:Z(a.ios_runtime,"ios"),androidRuntime:Z(a.android_runtime,"android"),upstream:{bundleUrl:a.upstream.bundle_url??"",host:a.upstream.host??"",port:a.upstream.port??0,statusUrl:a.upstream.status_url??""},probe:{reachable:a.probe.reachable,statusCode:a.probe.status_code,latencyMs:a.probe.latency_ms,detail:a.probe.detail}}}catch(e){throw eo(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function el(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 eu(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 er(e,t))return!0;let o=Math.min(500,Math.max(n-Date.now(),0));o>0&&await ee(o)}return!1}async function ec(e){let t=Date.now()+e.startupTimeoutMs,r=null,n=null;for(;Date.now()<t;){try{let t=await es({baseUrl:e.baseUrl,bearerToken:e.bearerToken,scope:e.scope,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),!ea(e))break}let o=Math.min(1e3,Math.max(t-Date.now(),0));o>0&&await ee(o)}throw Error(el(e.baseUrl,n,r,e.initialBridgeError,e.companionLogPath))}async function ed(r){let n=`http://${r.statusHost}:${r.metroPort}/status`;if(r.reuseExisting&&await er(n,r.probeTimeoutMs))return{started:!1,reused:!0,pid:0,statusUrl:n};let i=function(r,n,i,a,s,l){let u="expo"===n?{command:"npx",installArgs:["expo","start","--host","lan","--port",String(i)]}:{command:"npx",installArgs:["react-native","start","--host",a,"--port",String(i)]};e.mkdirSync(t.dirname(s),{recursive:!0});let c=e.openSync(s,"a"),d=0;try{d=o(u.command,u.installArgs,{cwd:r,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}}(r.projectRoot,r.kind,r.metroPort,r.listenHost,r.logPath,r.env);if(await eu(n,r.startupTimeoutMs,r.probeTimeoutMs))return{started:!0,reused:!1,pid:i.pid,statusUrl:n};throw await en(i.pid).catch(()=>{}),Error(`Metro did not become ready at ${n} within ${r.startupTimeoutMs}ms. Check ${r.logPath}.`)}async function ep(e,t){let r=t.bridgeScope;if(!r)return null;let n=null,o=null;try{n=await es({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:r,timeoutMs:t.probeTimeoutMs})}catch(e){if(!ea(e))throw e;o=e instanceof Error?e.message:String(e)}n&&!1!==n.probe.reachable||(n=await em(e,t,r,n,o));var i=t.proxyBaseUrl,a=n;if(!a?.iosRuntime.bundleUrl)throw Error(el(i,"bridge descriptor is missing ios_runtime.metro_bundle_url",a));return n}async function em(e,t,r,n,o){let i;try{i=(await F({projectRoot:t.projectRoot,serverBaseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,bridgeScope:r,localBaseUrl:`http://${t.statusHost}:${t.metroPort}`,launchUrl:q(e.launchUrl),profileKey:q(e.companionProfileKey),consumerKey:q(e.companionConsumerKey),env:t.env})).logPath}catch(e){throw Error(el(t.proxyBaseUrl,e instanceof Error?e.message:String(e),n,o))}try{return await ec({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:r,probeTimeoutMs:t.probeTimeoutMs,startupTimeoutMs:t.startupTimeoutMs,initialBridgeError:o,companionLogPath:i})}catch(e){throw e instanceof Error?e:Error(String(e))}}async function eh(r={}){var n,o;let a=function(r){let n=r.env??process.env,o=process.cwd(),i=W(r.projectRoot??o,n,o),a=V(r.publicBaseUrl),s=V(r.proxyBaseUrl);if(!a&&!s)throw new M("INVALID_ARGS","metro prepare requires --public-base-url <url> or --proxy-base-url <url>.");let{proxyEnabled:l,proxyBaseUrl:u,proxyBearerToken:c}=function(e,t,r){let n=t||q(r.AGENT_DEVICE_METRO_BEARER_TOKEN)||"",o=n||e&&q(r.AGENT_DEVICE_DAEMON_AUTH_TOKEN)||"";if(e&&!o)throw new M("INVALID_ARGS","metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_METRO_BEARER_TOKEN or AGENT_DEVICE_DAEMON_AUTH_TOKEN.");if(!e&&n)throw new M("INVALID_ARGS","metro prepare requires --proxy-base-url when proxy auth is provided.");return{proxyEnabled:!!(e&&o),proxyBaseUrl:e,proxyBearerToken:o}}(s,q(r.proxyBearerToken)??"",n);return{env:n,projectRoot:i,kind:function(r,n){if("auto"!==n)return n;let o=function(r){let n=t.join(r,"package.json");if(!z(n))throw new M("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"),metroPort:X(r.metroPort??8081,8081),listenHost:q(r.listenHost)??"0.0.0.0",statusHost:q(r.statusHost)??"127.0.0.1",publicBaseUrl:a,proxyBaseUrl:u,proxyBearerToken:c,bridgeScope:l?function(e){if(!e?.tenantId||!e.runId||!e.leaseId)throw new M("INVALID_ARGS","metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.");return e}(r.bridgeScope):null,startupTimeoutMs:Q(r.startupTimeoutMs,18e4,3e4),probeTimeoutMs:Q(r.probeTimeoutMs,1e4,1e3),reuseExisting:r.reuseExisting??!0,installProjectDeps:r.installDependenciesIfNeeded??!0,runtimeFilePath:r.runtimeFilePath?W(r.runtimeFilePath,n,o):null,logPath:W(r.logPath??t.join(i,".agent-device","metro.log"),n,o)}}(r),s=a.installProjectDeps?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=z(t.join(r,"pnpm-lock.yaml"))?{command:"pnpm",installArgs:["install"]}:z(t.join(r,"yarn.lock"))?{command:"yarn",installArgs:["install"]}:{command:"npm",installArgs:["install"]};return i(o.command,o.installArgs,{cwd:r,env:n}),{installed:!0,packageManager:o.command}}(a.projectRoot,a.env):{installed:!1},l=await ed(a),{baseIosRuntime:u,baseAndroidRuntime:c}={baseIosRuntime:(n=a.publicBaseUrl)?Y(n,"ios"):{platform:"ios"},baseAndroidRuntime:n?Y(n,"android"):{platform:"android"}},d=await ep(r,a),p=d?.iosRuntime??u,m=d?.androidRuntime??c,h={projectRoot:a.projectRoot,kind:a.kind,dependenciesInstalled:s.installed,packageManager:s.packageManager??null,started:l.started,reused:l.reused,pid:l.pid,logPath:a.logPath,statusUrl:l.statusUrl,runtimeFilePath:a.runtimeFilePath,iosRuntime:p,androidRuntime:m,bridge:d};return o=a.runtimeFilePath,o&&(e.mkdirSync(t.dirname(o),{recursive:!0}),e.writeFileSync(o,JSON.stringify(h,null,2))),h}async function ef(e={}){let t=Q(e.timeoutMs,1e4,1e3),r=function(e){var t;let r,n=q(e.bundleUrl),o=n??e.runtime?.bundleUrl,i=!!n,a=!!q(o),s=l({metroHost:q(e.metroHost)??(i?void 0:q(e.runtime?.metroHost))??(a?void 0:"localhost"),metroPort:void 0!==e.metroPort?X(e.metroPort,8081):i?void 0:e.runtime?.metroPort??(a?void 0:8081),bundleUrl:o});if(!s)throw new M("INVALID_ARGS","Unable to resolve Metro host and port for reload.");return t=function(e){let t=q(e);if(!t)return"/reload";let r=new URL(t).pathname.replace(/\/+$/,"");return r.endsWith("/index.bundle")?`${r.slice(0,-13)}/reload`:"/reload"}(o),(r=new URL(`${s.scheme}://localhost`)).hostname=s.host,r.port=String(s.port),r.pathname=t,r.toString()}(e),n=await et(r,t);if(!n.ok)throw new M("COMMAND_FAILED",`Metro reload failed (${n.status}).`,{reloadUrl:r,status:n.status,body:n.body,hint:"Verify Metro is running and the target React Native app is connected to this Metro instance."});return{reloaded:!0,reloadUrl:r,status:n.status,body:n.body}}export{Y as buildMetroRuntimeHints,O as ensureCompanionTunnel,F as ensureMetroCompanion,eh as prepareMetroRuntime,ef as reloadMetro,L as stopCompanionTunnel,J as stopMetroCompanion};
1
+ import e from"node:fs";import t from"node:path";import{createHash as r}from"node:crypto";import{fileURLToPath as n}from"node:url";import{runCmdDetached as o,runCmdSync as i}from"./8875.js";import{readProcessCommand as a,waitForProcessExit as s,isProcessAlive as l,readProcessStartTime as u}from"./9414.js";import{normalizeBaseUrl as c,ENV_COMPANION_TUNNEL_BEARER_TOKEN as d,ENV_COMPANION_TUNNEL_SERVER_BASE_URL as p,ENV_COMPANION_TUNNEL_STATE_PATH as m,ENV_COMPANION_TUNNEL_LAUNCH_URL as h,ENV_COMPANION_TUNNEL_SCOPE_LEASE_ID as f,ENV_COMPANION_TUNNEL_SCOPE_TENANT_ID as g,ENV_COMPANION_TUNNEL_DEVICE_PORT as y,buildBundleUrl as b,METRO_COMPANION_RUN_ARG as P,ENV_COMPANION_TUNNEL_SESSION as S,ENV_COMPANION_TUNNEL_SCOPE_RUN_ID as w,ENV_COMPANION_TUNNEL_REGISTER_PATH as _,ENV_COMPANION_TUNNEL_LOCAL_BASE_URL as E,ENV_COMPANION_TUNNEL_UNREGISTER_PATH as v}from"./4069.js";import{AppError as U}from"./733.js";import{resolveUserPath as M}from"./9612.js";import{resolveRuntimeTransportHints as I}from"./8936.js";import{sleep as k}from"./5560.js";let T="companion-tunnel";function A(e){return r("sha256").update(e).digest("hex")}function N(e){return e?.trim()?e.trim():void 0}function R(e,r,n,o){let i=o??t.join(e,".agent-device");if(!n)return{statePath:t.join(i,`${r.slug}.json`),logPath:t.join(i,`${r.slug}.log`)};let a=A(n).slice(0,12),s=t.join(i,r.slug);return{statePath:t.join(s,`${r.slug}-${a}.json`),logPath:t.join(s,`${r.slug}-${a}.log`)}}function $(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:N("string"==typeof r.launchUrl?r.launchUrl:void 0),registerPath:N("string"==typeof r.registerPath?r.registerPath:void 0),unregisterPath:N("string"==typeof r.unregisterPath?r.unregisterPath:void 0),devicePort:Number.isInteger(r.devicePort)?Number(r.devicePort):void 0,session:N("string"==typeof r.session?r.session: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}}(r.bridgeScope),tokenHash:r.tokenHash,consumers:n}}catch{return null}}function x(r,n){e.mkdirSync(t.dirname(r),{recursive:!0}),e.writeFileSync(r,`${JSON.stringify(n,null,2)}
2
+ `,"utf8")}function j(t){try{let r=e.readdirSync(t);0===r.length&&e.rmdirSync(t)}catch{}}function B(r,n){let o=t.dirname(r.statePath),i=t.dirname(r.logPath);var a=r.statePath;try{e.unlinkSync(a)}catch{}var s=r.logPath;try{e.unlinkSync(s)}catch{}j(o),i!==o&&j(i),t.basename(o)===n.slug&&j(t.dirname(o))}function C(e,t){return e.includes(t.runArg)}function D(e){return N(e.consumerKey)??N(e.profileKey)??null}function H(e,t){return!t||e.consumers.includes(t)?e:{...e,consumers:[...e.consumers,t]}}async function K(e,t){if(!l(e.pid))return;let r=a(e.pid);if(r&&C(r,t)){try{process.kill(e.pid,"SIGTERM")}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return;throw t}if(!await s(e.pid,1e3)){try{process.kill(e.pid,"SIGKILL")}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return;throw t}await s(e.pid,1e3)}}}async function O(r){var i;let s,b=D(r),P=R(r.projectRoot,r.definition,r.profileKey,r.stateDir),U=$(P.statePath);if(U&&function(e,t){var r,n;if(!l(e.pid))return!1;if(e.startTime){let t=u(e.pid);if(!t||t!==e.startTime)return!1}let o=a(e.pid);return!!o&&!!C(o,t.definition)&&!!e.bridgeScope&&e.serverBaseUrl===c(t.serverBaseUrl)&&e.localBaseUrl===c(t.localBaseUrl)&&e.launchUrl===N(t.launchUrl)&&e.registerPath===N(t.registerPath)&&e.unregisterPath===N(t.unregisterPath)&&e.devicePort===t.devicePort&&e.session===N(t.session)&&(r=e.bridgeScope,n=t.bridgeScope,r.tenantId===n.tenantId&&r.runId===n.runId&&r.leaseId===n.leaseId)&&e.tokenHash===A(t.bearerToken)}(U,r)){let e=H(U,b);return e!==U&&x(P.statePath,e),{pid:U.pid,spawned:!1,statePath:P.statePath,logPath:P.logPath}}U&&(await K(U,r.definition),B(P,r.definition)),i=P.statePath,e.mkdirSync(t.dirname(i),{recursive:!0}),e.closeSync(e.openSync(i,"a"));try{s=function(r,i){let s=function(r){let o=n(import.meta.url),i=t.extname(o)||".js",a=[t.join(t.dirname(o),`${T}${i}`),t.join(t.dirname(o),"internal",`${T}${i}`)].find(t=>e.existsSync(t));if(!a)throw Error(`${r.displayName} entrypoint not found. Rebuild the package to include the companion worker entry.`);return a}(r.definition),l=s.endsWith(".ts")?["--experimental-strip-types"]:[];e.mkdirSync(t.dirname(i),{recursive:!0});let b=e.openSync(i,"a"),P=0;try{let e;P=o(process.execPath,[...l,s,r.definition.runArg],{env:((e={...r.env??process.env})[p]=c(r.serverBaseUrl),e[d]=r.bearerToken,e[E]=c(r.localBaseUrl),e[m]=R(r.projectRoot,r.definition,r.profileKey,r.stateDir).statePath,e[g]=r.bridgeScope.tenantId,e[w]=r.bridgeScope.runId,e[f]=r.bridgeScope.leaseId,r.launchUrl?.trim()?e[h]=r.launchUrl.trim():delete e[h],r.registerPath?.trim()?e[_]=r.registerPath.trim():delete e[_],r.unregisterPath?.trim()?e[v]=r.unregisterPath.trim():delete e[v],void 0!==r.devicePort?e[y]=String(r.devicePort):delete e[y],r.session?.trim()?e[S]=r.session.trim():delete e[S],e),stdio:["ignore",b,b]})}finally{e.closeSync(b)}if(!Number.isInteger(P)||P<=0)throw Error(`Failed to start ${r.definition.displayName} process.`);return{pid:P,startTime:u(P)??void 0,command:a(P)??void 0,serverBaseUrl:c(r.serverBaseUrl),localBaseUrl:c(r.localBaseUrl),launchUrl:N(r.launchUrl),registerPath:N(r.registerPath),unregisterPath:N(r.unregisterPath),devicePort:r.devicePort,session:N(r.session),bridgeScope:r.bridgeScope,tokenHash:A(r.bearerToken),consumers:[]}}(r,P.logPath),x(P.statePath,H(s,b))}catch(e){throw s&&await K(s,r.definition).catch(()=>{}),B(P,r.definition),e}return{pid:s.pid,spawned:!0,statePath:P.statePath,logPath:P.logPath}}async function L(e){let t=D(e),r=R(e.projectRoot,e.definition,e.profileKey,e.stateDir),n=$(r.statePath);if(!n)return B(r,e.definition),{stopped:!1,statePath:r.statePath};let o=t?{...n,consumers:n.consumers.filter(e=>e!==t)}:{...n,consumers:[]};return o.consumers.length>0?(x(r.statePath,o),{stopped:!1,statePath:r.statePath}):(await K(n,e.definition),B(r,e.definition),{stopped:!0,statePath:r.statePath})}let G={slug:"metro-companion",runArg:P,displayName:"Metro companion"};async function F(e){return await O({...e,definition:G,registerPath:e.registerPath??"/api/metro/companion/register"})}async function J(e){return await L({...e,definition:G})}function V(e){return"string"==typeof e&&e.trim()?c(e.trim()):""}function q(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function W(e,t,r){return M(e,{env:t,cwd:r})}function z(t){try{return e.accessSync(t,e.constants.F_OK),!0}catch{return!1}}function Q(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 X(e,t){if(null==e||""===e)return t;let r=Number.parseInt(String(e),10);if(!Number.isInteger(r)||r<1||r>65535)throw new U("INVALID_ARGS",`Invalid Metro port: ${String(e)}. Use 1-65535.`);return r}function Y(e,t){return{platform:t,bundleUrl:b(e,t)}}function Z(e,t){return{platform:t,metroHost:q(e?.metro_host),metroPort:e?.metro_port,bundleUrl:q(e?.metro_bundle_url),launchUrl:q(e?.launch_url)}}async function ee(e){await k(e)}async function et(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 er(e,t){try{let r=await et(e,t);return r.ok&&r.body.includes("packager-status:running")}catch{return!1}}async function en(e){if(Number.isInteger(e)&&!(e<=0)){try{process.kill(e,"SIGTERM")}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return;throw t}if(!await s(e,1e3)){try{process.kill(e,"SIGKILL")}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return;throw t}await s(e,1e3)}}}function eo(e,t){let r=Error(e);return r.retryable=t,r}function ei(e,t){return!!(e>=500||408===e||425===e||429===e||JSON.stringify(t).includes("Metro companion is not connected"))}function ea(e){return!!(e&&"object"==typeof e&&"retryable"in e&&!0===e.retryable)}async function es(e){let t;try{var r,n;t=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:"POST",headers:(r=e.baseUrl,n=e.bearerToken,{Authorization:`Bearer ${n}`,"Content-Type":"application/json",...r.includes("ngrok")?{"ngrok-skip-browser-warning":"1"}:{}}),body:JSON.stringify({...e.scope,...e.runtime?{ios_runtime:e.runtime}:{},timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(t){if(t instanceof Error&&"TimeoutError"===t.name)throw eo(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0);throw eo(t instanceof Error?t.message:String(t),!0)}let o=function(e,t,r){if(!e)return{};try{let t=JSON.parse(e);if(!t||"object"!=typeof t||Array.isArray(t))throw Error("Expected a JSON object");return t}catch(i){let n=e.slice(0,200),o=i instanceof Error?i.message:String(i);throw eo(`/api/metro/bridge returned invalid JSON (${t}) from ${r}: ${o}. body=${JSON.stringify(n)}`,ei(t,e))}}(await t.text(),t.status,e.baseUrl);if(!t.ok)throw eo(`/api/metro/bridge failed (${t.status}): ${JSON.stringify(o)}`,ei(t.status,o));var i=o;let a=i.data??i;if(!a||"object"!=typeof a||Array.isArray(a))throw eo("/api/metro/bridge returned malformed descriptor: Expected a JSON object.",!1);try{return{enabled:a.enabled,baseUrl:a.base_url,statusUrl:a.status_url??"",bundleUrl:a.bundle_url??"",iosRuntime:Z(a.ios_runtime,"ios"),androidRuntime:Z(a.android_runtime,"android"),upstream:{bundleUrl:a.upstream.bundle_url??"",host:a.upstream.host??"",port:a.upstream.port??0,statusUrl:a.upstream.status_url??""},probe:{reachable:a.probe.reachable,statusCode:a.probe.status_code,latencyMs:a.probe.latency_ms,detail:a.probe.detail}}}catch(e){throw eo(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function el(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 eu(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 er(e,t))return!0;let o=Math.min(500,Math.max(n-Date.now(),0));o>0&&await ee(o)}return!1}async function ec(e){let t=Date.now()+e.startupTimeoutMs,r=null,n=null;for(;Date.now()<t;){try{let t=await es({baseUrl:e.baseUrl,bearerToken:e.bearerToken,scope:e.scope,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),!ea(e))break}let o=Math.min(1e3,Math.max(t-Date.now(),0));o>0&&await ee(o)}throw Error(el(e.baseUrl,n,r,e.initialBridgeError,e.companionLogPath))}async function ed(r){let n=`http://${r.statusHost}:${r.metroPort}/status`;if(r.reuseExisting&&await er(n,r.probeTimeoutMs))return{started:!1,reused:!0,pid:0,statusUrl:n};let i=function(r,n,i,a,s,l){let u="expo"===n?{command:"npx",installArgs:["expo","start","--host","lan","--port",String(i)]}:{command:"npx",installArgs:["react-native","start","--host",a,"--port",String(i)]};e.mkdirSync(t.dirname(s),{recursive:!0});let c=e.openSync(s,"a"),d=0;try{d=o(u.command,u.installArgs,{cwd:r,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}}(r.projectRoot,r.kind,r.metroPort,r.listenHost,r.logPath,r.env);if(await eu(n,r.startupTimeoutMs,r.probeTimeoutMs))return{started:!0,reused:!1,pid:i.pid,statusUrl:n};throw await en(i.pid).catch(()=>{}),Error(`Metro did not become ready at ${n} within ${r.startupTimeoutMs}ms. Check ${r.logPath}.`)}async function ep(e,t){let r=t.bridgeScope;if(!r)return null;let n=null,o=null;try{n=await es({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:r,timeoutMs:t.probeTimeoutMs})}catch(e){if(!ea(e))throw e;o=e instanceof Error?e.message:String(e)}n&&!1!==n.probe.reachable||(n=await em(e,t,r,n,o));var i=t.proxyBaseUrl,a=n;if(!a?.iosRuntime.bundleUrl)throw Error(el(i,"bridge descriptor is missing ios_runtime.metro_bundle_url",a));return n}async function em(e,t,r,n,o){let i;try{i=(await F({projectRoot:t.projectRoot,serverBaseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,bridgeScope:r,localBaseUrl:`http://${t.statusHost}:${t.metroPort}`,launchUrl:q(e.launchUrl),profileKey:q(e.companionProfileKey),consumerKey:q(e.companionConsumerKey),env:t.env})).logPath}catch(e){throw Error(el(t.proxyBaseUrl,e instanceof Error?e.message:String(e),n,o))}try{return await ec({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:r,probeTimeoutMs:t.probeTimeoutMs,startupTimeoutMs:t.startupTimeoutMs,initialBridgeError:o,companionLogPath:i})}catch(e){throw e instanceof Error?e:Error(String(e))}}async function eh(r={}){var n,o;let a=function(r){let n=r.env??process.env,o=process.cwd(),i=W(r.projectRoot??o,n,o),a=V(r.publicBaseUrl),s=V(r.proxyBaseUrl);if(!a&&!s)throw new U("INVALID_ARGS","metro prepare requires --public-base-url <url> or --proxy-base-url <url>.");let{proxyEnabled:l,proxyBaseUrl:u,proxyBearerToken:c}=function(e,t,r){let n=t||q(r.AGENT_DEVICE_METRO_BEARER_TOKEN)||"",o=n||e&&q(r.AGENT_DEVICE_DAEMON_AUTH_TOKEN)||"";if(e&&!o)throw new U("INVALID_ARGS","metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_METRO_BEARER_TOKEN or AGENT_DEVICE_DAEMON_AUTH_TOKEN.");if(!e&&n)throw new U("INVALID_ARGS","metro prepare requires --proxy-base-url when proxy auth is provided.");return{proxyEnabled:!!(e&&o),proxyBaseUrl:e,proxyBearerToken:o}}(s,q(r.proxyBearerToken)??"",n);return{env:n,projectRoot:i,kind:function(r,n){if("auto"!==n)return n;let o=function(r){let n=t.join(r,"package.json");if(!z(n))throw new U("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"),metroPort:X(r.metroPort??8081,8081),listenHost:q(r.listenHost)??"0.0.0.0",statusHost:q(r.statusHost)??"127.0.0.1",publicBaseUrl:a,proxyBaseUrl:u,proxyBearerToken:c,bridgeScope:l?function(e){if(!e?.tenantId||!e.runId||!e.leaseId)throw new U("INVALID_ARGS","metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.");return e}(r.bridgeScope):null,startupTimeoutMs:Q(r.startupTimeoutMs,18e4,3e4),probeTimeoutMs:Q(r.probeTimeoutMs,1e4,1e3),reuseExisting:r.reuseExisting??!0,installProjectDeps:r.installDependenciesIfNeeded??!0,runtimeFilePath:r.runtimeFilePath?W(r.runtimeFilePath,n,o):null,logPath:W(r.logPath??t.join(i,".agent-device","metro.log"),n,o)}}(r),s=a.installProjectDeps?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=z(t.join(r,"pnpm-lock.yaml"))?{command:"pnpm",installArgs:["install"]}:z(t.join(r,"yarn.lock"))?{command:"yarn",installArgs:["install"]}:{command:"npm",installArgs:["install"]};return i(o.command,o.installArgs,{cwd:r,env:n}),{installed:!0,packageManager:o.command}}(a.projectRoot,a.env):{installed:!1},l=await ed(a),{baseIosRuntime:u,baseAndroidRuntime:c}={baseIosRuntime:(n=a.publicBaseUrl)?Y(n,"ios"):{platform:"ios"},baseAndroidRuntime:n?Y(n,"android"):{platform:"android"}},d=await ep(r,a),p=d?.iosRuntime??u,m=d?.androidRuntime??c,h={projectRoot:a.projectRoot,kind:a.kind,dependenciesInstalled:s.installed,packageManager:s.packageManager??null,started:l.started,reused:l.reused,pid:l.pid,logPath:a.logPath,statusUrl:l.statusUrl,runtimeFilePath:a.runtimeFilePath,iosRuntime:p,androidRuntime:m,bridge:d};return o=a.runtimeFilePath,o&&(e.mkdirSync(t.dirname(o),{recursive:!0}),e.writeFileSync(o,JSON.stringify(h,null,2))),h}async function ef(e={}){let t=Q(e.timeoutMs,1e4,1e3),r=function(e){var t;let r,n=q(e.bundleUrl),o=n??e.runtime?.bundleUrl,i=!!n,a=!!q(o),s=I({metroHost:q(e.metroHost)??(i?void 0:q(e.runtime?.metroHost))??(a?void 0:"localhost"),metroPort:void 0!==e.metroPort?X(e.metroPort,8081):i?void 0:e.runtime?.metroPort??(a?void 0:8081),bundleUrl:o});if(!s)throw new U("INVALID_ARGS","Unable to resolve Metro host and port for reload.");return t=function(e){let t=q(e);if(!t)return"/reload";let r=new URL(t).pathname.replace(/\/+$/,"");return r.endsWith("/index.bundle")?`${r.slice(0,-13)}/reload`:"/reload"}(o),(r=new URL(`${s.scheme}://localhost`)).hostname=s.host,r.port=String(s.port),r.pathname=t,r.toString()}(e),n=await et(r,t);if(!n.ok)throw new U("COMMAND_FAILED",`Metro reload failed (${n.status}).`,{reloadUrl:r,status:n.status,body:n.body,hint:"Verify Metro is running and the target React Native app is connected to this Metro instance."});return{reloaded:!0,reloadUrl:r,status:n.status,body:n.body}}export{Y as buildMetroRuntimeHints,O as ensureCompanionTunnel,F as ensureMetroCompanion,eh as prepareMetroRuntime,ef as reloadMetro,L as stopCompanionTunnel,J as stopMetroCompanion};
@@ -0,0 +1 @@
1
+ import{URL as t}from"node:url";import{AppError as r}from"./733.js";function o(o){if(!o)return;let i=e(o.metroHost),p=n(o.metroPort),l="http",u=e(o.bundleUrl);if(u){var m;let o;try{o=new t(u)}catch(t){throw new r("INVALID_ARGS",`Invalid runtime bundle URL: ${u}`,{},t)}("http:"===o.protocol||"https:"===o.protocol)&&(i??=e(o.hostname),p??=n(o.port.length>0?Number(o.port):"https:"===(m=o.protocol)?443:"http:"===m?80:void 0),l="https:"===o.protocol?"https":"http")}if(i&&p)return{host:i,port:p,scheme:l}}function e(t){let r=t?.trim();return r&&r.length>0?r:void 0}function n(t){if(Number.isInteger(t)&&!(t<=0)&&!(t>65535))return t}export{o as resolveRuntimeTransportHints,e as trimRuntimeValue};
@@ -0,0 +1 @@
1
+ import{runCmdSync as e}from"./8875.js";import{sleep as r}from"./5560.js";let t=[/(^|[/\s"'=])dist\/src\/daemon\.js($|[\s"'])/,/(^|[/\s"'=])dist\/src\/internal\/daemon\.js($|[\s"'])/,/(^|[/\s"'=])src\/daemon\.ts($|[\s"'])/];function n(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return"EPERM"===e.code}}function i(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(-e,0),!0}catch(e){return"EPERM"===e.code}}function s(r){if(!Number.isInteger(r)||r<=0)return null;try{let t=e("ps",["-p",String(r),"-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 o(r){if(!Number.isInteger(r)||r<=0)return null;try{let t=e("ps",["-p",String(r),"-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 u(e,r){let i;if(!n(e))return!1;if(r){let t=s(e);if(!t||t!==r)return!1}let u=o(e);return!!u&&!!(i=u.toLowerCase().replaceAll("\\","/")).includes("agent-device")&&t.some(e=>e.test(i))}function l(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 c(e,t){if(!n(e))return!0;let i=Date.now();for(;Date.now()-i<t;)if(await r(50),!n(e))return!0;return!n(e)}async function a(e,r){!u(e,r.expectedStartTime)||!l(e,"SIGTERM")||await c(e,r.termTimeoutMs)||l(e,"SIGKILL")&&await c(e,r.killTimeoutMs)}export{u as isAgentDeviceDaemonProcess,n as isProcessAlive,i as isProcessGroupAlive,o as readProcessCommand,s as readProcessStartTime,a as stopProcessForTakeover,c as waitForProcessExit};
package/dist/src/9581.js CHANGED
@@ -1,6 +1,6 @@
1
- import{COMMON_COMMAND_SUPPORTED_FLAG_KEYS as e,listCommandFamilyCliSchemas as t,METRO_PREPARE_FLAGS as o,listCommandMetadata as a}from"./2948.js";let n={auth:{usageOverride:"auth status|login|logout",listUsageOverride:"auth",helpDescription:"Manage cloud login state used by remote daemon and cloud device workflows.",summary:"Manage cloud login state used by remote daemon and cloud device workflows",positionalArgs:["status|login|logout"],supportedFlags:["remoteConfig","stateDir"]},connect:{usageOverride:"connect [--remote-config <path>] [--daemon-base-url <url>] [--tenant <id>] [--run-id <id>] [--lease-id <id>] [--lease-backend <backend>] [--force] [--no-login]",helpDescription:"Connect to a remote daemon, authenticate when needed, and save remote session state. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.",listUsageOverride:"connect",summary:"Attach CLI commands to a saved remote daemon/cloud lease; inspect for remote runs, tenants, or service-token CI",allowedFlags:["remoteConfig","daemonBaseUrl","tenant","runId","leaseId","leaseBackend","force","noLogin"],supportedFlags:["stateDir","daemonAuthToken","session","platform",...o,"launchUrl"]},connection:{usageOverride:"connection status",listUsageOverride:"connection",helpDescription:"Inspect active remote connection state",summary:"Inspect the active saved remote connection before assuming commands are local",positionalArgs:["status"],supportedFlags:["remoteConfig","stateDir","session"]},disconnect:{helpDescription:"Disconnect remote daemon state, stop owned Metro companion, and release lease",listUsageOverride:"disconnect",summary:"Clear remote connection state, stop owned Metro companions, and release remote leases",allowedFlags:["shutdown"],supportedFlags:["remoteConfig","stateDir","session"]},mcp:{helpDescription:"Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.",summary:"Start MCP server"},proxy:{usageOverride:"proxy [--host <host>] [--port <port>] [--daemon-auth-token <token>] [--state-dir <path>]",listUsageOverride:"proxy",helpDescription:`Expose the local daemon HTTP contract through a tunnel-friendly reverse proxy.
1
+ import{COMMON_COMMAND_SUPPORTED_FLAG_KEYS as e,listCommandFamilyCliSchemas as t,METRO_PREPARE_FLAGS as o,listCommandMetadata as a}from"./2948.js";let n={cdp:{usageOverride:"cdp [...args]",listUsageOverride:"cdp",helpDescription:"Run CDP commands for React Native diagnostics, JS heap usage, heap snapshots, and leak analysis",summary:"Inspect React Native CDP targets, JS heap growth, heap snapshots, retainers, and leak signals",positionalArgs:["args?"],allowsExtraPositionals:!0,supportedFlags:e},auth:{usageOverride:"auth status|login|logout",listUsageOverride:"auth",helpDescription:"Manage cloud login state used by remote daemon and cloud device workflows.",summary:"Manage cloud login state used by remote daemon and cloud device workflows",positionalArgs:["status|login|logout"],supportedFlags:["remoteConfig","stateDir"]},connect:{usageOverride:"connect [--remote-config <path>] [--daemon-base-url <url>] [--tenant <id>] [--run-id <id>] [--lease-id <id>] [--lease-backend <backend>] [--force] [--no-login]",helpDescription:"Connect to a remote daemon, authenticate when needed, and save remote session state. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.",listUsageOverride:"connect",summary:"Attach CLI commands to a saved remote daemon/cloud lease; inspect for remote runs, tenants, or service-token CI",allowedFlags:["remoteConfig","daemonBaseUrl","tenant","runId","leaseId","leaseBackend","force","noLogin"],supportedFlags:["stateDir","daemonAuthToken","session","platform",...o,"launchUrl"]},connection:{usageOverride:"connection status",listUsageOverride:"connection",helpDescription:"Inspect active remote connection state",summary:"Inspect the active saved remote connection before assuming commands are local",positionalArgs:["status"],supportedFlags:["remoteConfig","stateDir","session"]},disconnect:{helpDescription:"Disconnect remote daemon state, stop owned Metro companion, and release lease",listUsageOverride:"disconnect",summary:"Clear remote connection state, stop owned Metro companions, and release remote leases",allowedFlags:["shutdown"],supportedFlags:["remoteConfig","stateDir","session"]},mcp:{helpDescription:"Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.",summary:"Start MCP server"},proxy:{usageOverride:"proxy [--host <host>] [--port <port>] [--daemon-auth-token <token>] [--state-dir <path>]",listUsageOverride:"proxy",helpDescription:`Expose the local daemon HTTP contract through a tunnel-friendly reverse proxy.
2
2
 
3
- Run this on the host that has access to simulators/devices, then point another machine at the printed daemon base URL with --daemon-base-url or AGENT_DEVICE_DAEMON_BASE_URL.
3
+ Run this on the host that has access to simulators/devices, expose the printed local proxy URL through a tunnel, then point another machine at the tunnel URL with connect proxy.
4
4
 
5
5
  The proxy starts or reuses a local HTTP daemon, accepts /health, /rpc, /upload, and /artifacts/*, and also accepts the same routes under /agent-device/*. Health is unauthenticated for reachability probes. Other routes require the generated bearer token printed at startup, or the explicit --daemon-auth-token value when provided. The proxy rewrites authorized client requests to the upstream daemon token instead of exposing the local daemon token.
6
6
 
@@ -9,7 +9,7 @@ Use the /agent-device base path when connecting through cloudflared, ngrok, or a
9
9
  Examples:
10
10
  agent-device proxy --port 4310
11
11
  cloudflared tunnel --url http://127.0.0.1:4310
12
- agent-device devices --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>`,summary:"Expose a local daemon through cloudflared, ngrok, or another HTTP tunnel",allowedFlags:["proxyHost","proxyPort","daemonAuthToken","stateDir"]},"react-devtools":{usageOverride:"react-devtools [...args]",listUsageOverride:"react-devtools",helpDescription:"Run pinned agent-react-devtools commands for React Native performance profiling, component trees, props/state/hooks, and render analysis",summary:"Inspect React Native components, props, hooks, errors, slow renders, and rerender profiles",positionalArgs:["args?"],allowsExtraPositionals:!0,supportedFlags:e},web:{usageOverride:"web setup | web doctor",listUsageOverride:"web setup|doctor",helpDescription:`Install and inspect the managed web automation backend used by --platform web.
12
+ agent-device connect proxy --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>`,summary:"Expose a local daemon through cloudflared, ngrok, or another HTTP tunnel",allowedFlags:["proxyHost","proxyPort","daemonAuthToken","stateDir"]},"react-devtools":{usageOverride:"react-devtools [...args]",listUsageOverride:"react-devtools",helpDescription:"Run pinned agent-react-devtools commands for React Native performance profiling, component trees, props/state/hooks, and render analysis",summary:"Inspect React Native components, props, hooks, errors, slow renders, and rerender profiles",positionalArgs:["args?"],allowsExtraPositionals:!0,supportedFlags:e},web:{usageOverride:"web setup | web doctor",listUsageOverride:"web setup|doctor",helpDescription:`Install and inspect the managed web automation backend used by --platform web.
13
13
 
14
14
  First-run flow:
15
15
  agent-device web setup
@@ -19,4 +19,4 @@ First-run flow:
19
19
 
20
20
  Runtime web commands do not install the backend implicitly. If the managed backend is missing, run agent-device web setup. The backend is resolved only from the managed install in the effective agent-device state dir.
21
21
 
22
- Use web setup to install or reuse the pinned backend. Use web doctor after setup to verify browser backend health.`,summary:"Manage web automation backend",positionalArgs:["setup|doctor"],supportedFlags:["stateDir"]}},r=t(),s=new Map(a().map(t=>[t.name,{helpDescription:t.description,supportedFlags:e}]));function i(e){if(e)return c(e)}function d(e){let t=c(e);if(!t)throw Error(`Missing command schema for ${e}`);return t}function c(e){let t=Object.hasOwn(n,e)?n[e]:void 0;if(t)return t;let o=s.get(e),a=Object.hasOwn(r,e)?r[e]:void 0;if(o)return a?{...o,...a}:o}function l(e,t){let o=i(e);if(!o?.defaults)return!1;let a=!1;for(let[e,n]of Object.entries(o.defaults))void 0===t[e]&&(t[e]=n,a=!0);return a}export{l as applyCommandDefaults,d as getCliCommandSchema,i as getCommandSchema};
22
+ Use web setup to install or reuse the pinned backend. Use web doctor after setup to verify browser backend health.`,summary:"Manage web automation backend",positionalArgs:["setup|doctor"],supportedFlags:["stateDir"]}},s=t(),r=new Map(a().map(t=>[t.name,{helpDescription:t.description,supportedFlags:e}]));function i(e){if(e)return c(e)}function d(e){let t=c(e);if(!t)throw Error(`Missing command schema for ${e}`);return t}function c(e){let t=Object.hasOwn(n,e)?n[e]:void 0;if(t)return t;let o=r.get(e),a=Object.hasOwn(s,e)?s[e]:void 0;if(o)return a?{...o,...a}:o}function l(e,t){let o=i(e);if(!o?.defaults)return!1;let a=!1;for(let[e,n]of Object.entries(o.defaults))void 0===t[e]&&(t[e]=n,a=!0);return a}export{l as applyCommandDefaults,d as getCliCommandSchema,i as getCommandSchema};