@buoy-gg/mcp 7.0.78 → 7.0.80
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/README.md +10 -0
- package/dist/SyncClient-gqMRmB79.d.mts +374 -0
- package/dist/SyncClient-gqMRmB79.d.ts +374 -0
- package/dist/{chunk-LHGIYW7N.mjs → chunk-2324LPBJ.mjs} +1 -1
- package/dist/{chunk-3STZVJQG.mjs → chunk-23AXQYJ4.mjs} +1 -1
- package/dist/{chunk-XA74T4JN.mjs → chunk-5XATNNKY.mjs} +2 -2
- package/dist/chunk-BKCCZNDR.mjs +986 -0
- package/dist/{chunk-ODGXMS2O.mjs → chunk-FYJWWTAC.mjs} +5 -4
- package/dist/chunk-TMN3LXKB.mjs +42 -0
- package/dist/{chunk-2IWYZICF.mjs → chunk-Y3TUCQB7.mjs} +1 -1
- package/dist/cli.js +285 -216
- package/dist/cli.mjs +12 -12
- package/dist/flowRun-DYM3QAEL.mjs +2 -0
- package/dist/index.d.mts +9 -370
- package/dist/index.d.ts +9 -370
- package/dist/index.js +239 -170
- package/dist/index.mjs +1 -1
- package/dist/{init-VCQMVZXB.mjs → init-HT6H7SCW.mjs} +1 -1
- package/dist/{main-6OX5577P.mjs → main-QEH33AS3.mjs} +2 -2
- package/dist/nativeProfiler.d.mts +184 -0
- package/dist/nativeProfiler.d.ts +184 -0
- package/dist/nativeProfiler.js +157 -0
- package/dist/nativeProfiler.mjs +1 -0
- package/dist/{simFarm-R4P6QXRK.mjs → simFarm-AWVHVU6A.mjs} +1 -1
- package/dist/{src-R7ICMP6Q.mjs → src-HRUK7GEE.mjs} +1 -1
- package/package.json +16 -5
- package/dist/chunk-HEPFVYZG.mjs +0 -959
- package/dist/flowRun-XEK65IL7.mjs +0 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{createRequire as So}from"module";const zr=So(import.meta.url);var te=1;var et=1;var Et={parkAfterMinutes:10,maxConcurrentBoots:3,reserveRamGB:24,reserveDiskGB:40,slimSimGB:2,stockSimGB:6,cloneDiskGB:2,freezePilot:false,personLeaseHours:8,runCapMinutes:60,keepRunsHours:24,fairMinFreeShare:.25,fairMaxSwingShare:.12,fairMaxThermalLevel:0,fairMaxSwapGrowthMB:256,phoneProfile:"iphone-se-2nd-gen",phoneOnLimit:"warn",phoneCapMB:0,trimIdleHours:24,keepWarmPerTemplate:2};var p=class extends Error{constructor(e,t,s,i=false){super(t);this.code=e;this.next=s;this.retryable=i;this.name="FarmError"}toJSON(){return{code:this.code,message:this.message,next:this.next,retryable:this.retryable}}};import{createHash as bo}from"crypto";var ks=["com.apple.sharingd"];var Ce=[{"id":"widgets","name":"Widgets & Wallpaper","downside":"Home and Lock Screen widgets, wallpaper posters, and Live Activities stop updating.","approxMemoryMB":675,"labels":["com.apple.PosterBoard","com.apple.chronod","com.apple.liveactivitiesd"]},{"id":"siri","name":"Siri & Intelligence","downside":"Siri, speech features, and Apple Intelligence services are unavailable.","approxMemoryMB":265,"labels":["com.apple.assistantd","com.apple.assistant_cdmd","com.apple.assistant_service","com.apple.siriactionsd","com.apple.siriinferenced","com.apple.siriknowledged","com.apple.sirittsd","com.apple.siri.context.service","com.apple.siri.acousticsignature","com.apple.corespeechd","com.apple.voiced","com.apple.voicebankingd","com.apple.speechmodeltrainingd","com.apple.intelligenceplatformd","com.apple.intelligencecontextd","com.apple.intelligenceflowd","com.apple.intelligencetasksd","com.apple.generativeexperiencesd","com.apple.knowledgeconstructiond","com.apple.naturallanguaged","com.apple.textunderstandingd","com.apple.modelcatalogd","com.apple.modelmanagerd","com.apple.mlhostd","com.apple.mlruntimed","com.apple.suggestd","com.apple.parsecd","com.apple.parsec-fbf","com.apple.proactiveeventtrackerd"]},{"id":"search","name":"Spotlight & Search","downside":"Spotlight and Settings search return no results.","approxMemoryMB":50,"labels":["com.apple.searchd","com.apple.searchtoold","com.apple.spotlightknowledged","com.apple.spotlightknowledged.updater","com.apple.corespotlightservice"]},{"id":"icloud","name":"iCloud & Apple Account","downside":"iCloud sync, Apple Account, Keychain, and backup workflows will not work.","approxMemoryMB":100,"labels":["com.apple.appleaccountd","com.apple.appleaccounttransparencyd","com.apple.appleidsetupd","com.apple.akd","com.apple.amsaccountsd","com.apple.amsengagementd","com.apple.amsondevicestoraged","com.apple.cloudd","com.apple.cloudphotod","com.apple.ckdiscretionaryd","com.apple.cloudsettingssyncagent","com.apple.bird","com.apple.syncdefaultsd","com.apple.cdpd","com.apple.sosd","com.apple.SecureBackupDaemon","com.apple.TrustedPeersHelper","com.apple.protectedcloudstorage.protectedcloudkeysyncing","com.apple.icloudmailagent","com.apple.icloudsubscriptionoptimizerd","com.apple.communicationtrustd"]},{"id":"store","name":"App Store, Push & Media","downside":"Remote push notifications and StoreKit or App Store testing will not work.","approxMemoryMB":80,"labels":["com.apple.appstored","com.apple.appstorecomponentsd","com.apple.apsd","com.apple.itunescloudd","com.apple.itunesstored","com.apple.storekitd","com.apple.amsaccountsd","com.apple.amsengagementd","com.apple.amsondevicestoraged","com.apple.passd","com.apple.financed","com.apple.videosubscriptionsd","com.apple.assetsubscriptiond","com.apple.musicd"]},{"id":"pim","name":"Mail, Calendar & Contacts","downside":"Contacts, Calendar, Reminders, and Mail-backed pickers or sync may fail.","approxMemoryMB":80,"labels":["com.apple.email.maild","com.apple.exchangesyncd","com.apple.dataaccess.dataaccessd","com.apple.calaccessd","com.apple.remindd","com.apple.contactsd","com.apple.contacts.postersyncd","com.apple.peopled"]},{"id":"web","name":"Safari Sync & Web Services","downside":"Universal links and Safari sync or background web services will not work.","approxMemoryMB":50,"labels":["com.apple.SafariBookmarksSyncAgent","com.apple.Safari.History","com.apple.Safari.passwordbreachd","com.apple.Safari.SafeBrowsing.Service","com.apple.safarifetcherd","com.apple.WebBookmarks.webbookmarksd","com.apple.webkit.adattributiond","com.apple.webkit.webpushd","com.apple.webprivacyd","com.apple.swcd"]},{"id":"family","name":"Family & Screen Time","downside":"Family Sharing, Screen Time, and usage tracking stop working.","approxMemoryMB":65,"labels":["com.apple.familycircled","com.apple.FamilyControlsAgent","com.apple.familynotification","com.apple.askpermissiond","com.apple.asktod","com.apple.ScreenTimeAgent","com.apple.ScreenTimeSettingsAgent","com.apple.UsageTrackingAgent"]},{"id":"health","name":"Health, Home & Fitness","downside":"HealthKit, HomeKit, and Fitness integrations will not work.","approxMemoryMB":135,"labels":["com.apple.healthd","com.apple.healthappd","com.apple.healthcontentd","com.apple.healtheventsd","com.apple.healthrecordsd","com.apple.finhealthd","com.apple.homed","com.apple.homeeventsd","com.apple.fitcore","com.apple.fitcore.session","com.apple.fitnesscoachingd","com.apple.fitnessintelligenced","com.apple.activityawardsd","com.apple.activitysharingd"]},{"id":"photos","name":"Photos & Media Analysis","downside":"Photo picker, Photos-library workflows, and media analysis may fail.","approxMemoryMB":60,"labels":["com.apple.photoanalysisd","com.apple.photosface","com.apple.mediaanalysisd","com.apple.mediaanalysisd.service","com.apple.mediastream.mstreamd","com.apple.medialibraryd","com.apple.assetsd","com.apple.assetsd.nebulad"]},{"id":"apps","name":"News, Weather, Maps & Games","downside":"News, Weather, Maps background data, and game-controller services are unavailable.","approxMemoryMB":90,"labels":["com.apple.newsd","com.apple.weatherd","com.apple.Maps.mapssyncd","com.apple.Maps.mapspushd","com.apple.Maps.geocorrectiond","com.apple.maps.destinationd","com.apple.MapKit.SnapshotService","com.apple.jetpackassetd","com.apple.tipsd","com.apple.gamed","com.apple.gamesaved","com.apple.GameController.gamecontrollerd"]},{"id":"messaging","name":"Messaging & FaceTime","downside":"iMessage, FaceTime, and related identity services will not work.","approxMemoryMB":60,"labels":["com.apple.identityservicesd","com.apple.ids_simd","com.apple.imautomatichistorydeletionagent","com.apple.imcore.imtransferagent","com.apple.imdpersistence.IMDPersistenceAgent","com.apple.facetimemessagestored","com.apple.telephonyutilities.callservicesd"]},{"id":"connectivity","name":"Sharing & Device Connectivity","downside":"AirDrop, Continuity, CarPlay, Watch, and Find My connectivity will not work.","approxMemoryMB":65,"labels":["com.apple.rapportd","com.apple.companiond","com.apple.carkitd","com.apple.wcd","com.apple.tvremoted","com.apple.avatarsd","com.apple.stickersd","com.apple.sociallayerd","com.apple.announced","com.apple.navd","com.apple.findmy.findmylocated"]},{"id":"telemetry","name":"Ads, Diagnostics & Telemetry","downside":"DeviceCheck plus analytics, diagnostics, and feedback services are unavailable.","approxMemoryMB":105,"labels":["com.apple.ap.adprivacyd","com.apple.ap.promotedcontentd","com.apple.diagnosticextensionsd","com.apple.feedbackd","com.apple.rtcreportingd","com.apple.securityuploadd","com.apple.geoanalyticsd","com.apple.triald","com.apple.followupd","com.apple.purplebuddy.budd","com.apple.devicecheckd"]},{"id":"other","name":"Other Background Services","downside":"Wallet, merchant, business, asset, and miscellaneous background services are unavailable.","approxMemoryMB":195,"labels":["com.apple.financed","com.apple.passd","com.apple.merchantd","com.apple.coreidvd","com.apple.businessservicesd","com.apple.deviceaccessd","com.apple.replicatord","com.apple.linkd","com.apple.ind","com.apple.storagedatad","com.apple.StatusKitAgent","com.apple.countryd","com.apple.mobileassetd","com.apple.managedconfiguration.passcodenagd"]}];function Ms(){const e=new Set(ks);const t=new Set;for(const s of Ce)for(const i of s.labels)if(!e.has(i))t.add(i);return[...t].sort()}function Ee(e){return e==="slim"?Ms():[]}function _s(e){return bo("sha256").update(e+"\n"+Ee(e).join("\n")).digest("hex").slice(0,16)}import{promises as q,existsSync as $t,readFileSync as ko}from"fs";import C from"path";import{AsyncLocalStorage as Mo}from"async_hooks";import{createHash as _o,randomBytes as we}from"crypto";import{promises as $e}from"fs";import It from"path";import{randomBytes as Eo}from"crypto";import{spawn as $o}from"child_process";var xe=new Set;function Bt(){return xe.size}function Io(){for(const e of xe){try{e.kill("SIGKILL")}catch{}}}function _(e,t,s={}){const{timeoutMs:i=3e4,maxBytes:o=4*1024*1024}=s;return new Promise(n=>{const a=$o(e,t,{env:s.env??process.env,stdio:[s.input==null?"ignore":"pipe","pipe","pipe"]});xe.add(a);let r="";let c="";let l=false;a.stdout.on("data",h=>{if(r.length<o)r+=h.toString("utf8")});a.stderr.on("data",h=>{if(c.length<o)c+=h.toString("utf8")});if(s.input!=null)a.stdin.end(s.input);const d=setTimeout(()=>{l=true;a.kill("SIGTERM");setTimeout(()=>a.kill("SIGKILL"),2e3).unref?.()},i);a.on("error",h=>{xe.delete(a);clearTimeout(d);n({code:null,stdout:r,stderr:c+String(h),timedOut:l})});a.on("close",h=>{xe.delete(a);clearTimeout(d);n({code:h,stdout:r,stderr:c,timedOut:l})})})}async function L(e,t,s={}){const i=await _(e,t,s);if(i.timedOut)throw new Error(`${e} ${t.slice(0,3).join(" ")} timed out after ${s.timeoutMs??3e4} ms`);if(i.code!==0)throw new Error(`${e} ${t.slice(0,3).join(" ")} failed (${i.code}): ${(i.stderr||i.stdout).trim().slice(0,500)}`);return i.stdout}async function tt(){const e=await L("ps",["-axww","-o","pid=,ppid=,lstart=,stat=,comm="],{timeoutMs:15e3});const t=await L("ps",["-axww","-o","pid=,command="],{timeoutMs:15e3});const s=new Map;for(const o of t.split("\n")){const n=/^\s*(\d+)\s+(.*)$/.exec(o);if(n)s.set(Number(n[1]),n[2])}const i=[];for(const o of e.split("\n")){const n=/^\s*(\d+)\s+(\d+)\s+(\w{3}\s+\w{3}\s+\d+\s+[\d:]+\s+\d{4})\s+(\S+)\s+(.*)$/.exec(o);if(!n)continue;const a=Number(n[1]);i.push({pid:a,ppid:Number(n[2]),start:n[3].replace(/\s+/g," "),stat:n[4],comm:n[5].trim(),command:s.get(a)??n[5].trim()})}return i}function Ot(e,t){const s=new Map;const i=new Map;for(const c of e){i.set(c.pid,c);const l=s.get(c.ppid)??[];l.push(c);s.set(c.ppid,l)}const o=[];const n=i.get(t);if(!n)return o;const a=[n];const r=new Set;while(a.length){const c=a.pop();if(r.has(c.pid))continue;r.add(c.pid);o.push(c);for(const l of s.get(c.pid)??[])a.push(l)}return o}async function Ie(e){const t=await _("ps",["-o","lstart=","-p",String(e)],{timeoutMs:5e3});const s=t.stdout.trim().replace(/\s+/g," ");return t.code===0&&s?s:null}async function J(e,t,s=false){if(!Number.isInteger(e)||e<=0)return false;try{process.kill(e,0)}catch(o){if(o.code!=="EPERM")return false}if(!t)return true;const i=await Ie(e);if(i===null)return s;return i===t}function st(e=process.env){return Object.fromEntries(Object.entries(e).filter(([t])=>!t.startsWith("SIMCTL_CHILD_")))}var T=e=>new Promise(t=>setTimeout(t,e));var Be=process.env.BUOY_FARM_DISABLED_ROOT||"/private/var/tmp";function Es(e,t=Be){if(!/^[0-9A-F-]{36}$/i.test(e))throw new Error(`not a UDID: ${e}`);return It.join(t,`com.apple.CoreSimulator.SimDevice.${e}`)}function $s(e,t=Be){return It.join(Es(e,t),"disabled.plist")}async function Is(e,t=Be){const s=$s(e,t);let i;try{i=await $e.lstat(s)}catch{return{}}if(!i.isFile())throw new Error(`refusing ${s}: not a regular file`);const o=await L("plutil",["-convert","json","-o","-",s],{timeoutMs:1e4});const n=JSON.parse(o);const a={};for(const[r,c]of Object.entries(n))if(typeof c==="boolean")a[r]=c;return a}function Bo(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function Oo(e){const t=Object.keys(e).sort();let s='<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0">\n<dict>\n';for(const i of t)s+=` <key>${Bo(i)}</key>
|
|
1
|
+
import{createRequire as So}from"module";const Qr=So(import.meta.url);var te=1;var et=1;var Et={parkAfterMinutes:10,maxConcurrentBoots:3,reserveRamGB:24,reserveDiskGB:40,slimSimGB:2,stockSimGB:6,cloneDiskGB:2,freezePilot:false,personLeaseHours:8,runCapMinutes:60,keepRunsHours:24,fairMinFreeShare:.25,fairMaxSwingShare:.12,fairMaxThermalLevel:0,fairMaxSwapGrowthMB:256,phoneProfile:"iphone-se-2nd-gen",phoneOnLimit:"warn",phoneCapMB:0,trimIdleHours:24,keepWarmPerTemplate:2};var p=class extends Error{constructor(e,t,s,i=false){super(t);this.code=e;this.next=s;this.retryable=i;this.name="FarmError"}toJSON(){return{code:this.code,message:this.message,next:this.next,retryable:this.retryable}}};import{createHash as bo}from"crypto";var ks=["com.apple.sharingd"];var Ce=[{"id":"widgets","name":"Widgets & Wallpaper","downside":"Home and Lock Screen widgets, wallpaper posters, and Live Activities stop updating.","approxMemoryMB":675,"labels":["com.apple.PosterBoard","com.apple.chronod","com.apple.liveactivitiesd"]},{"id":"siri","name":"Siri & Intelligence","downside":"Siri, speech features, and Apple Intelligence services are unavailable.","approxMemoryMB":265,"labels":["com.apple.assistantd","com.apple.assistant_cdmd","com.apple.assistant_service","com.apple.siriactionsd","com.apple.siriinferenced","com.apple.siriknowledged","com.apple.sirittsd","com.apple.siri.context.service","com.apple.siri.acousticsignature","com.apple.corespeechd","com.apple.voiced","com.apple.voicebankingd","com.apple.speechmodeltrainingd","com.apple.intelligenceplatformd","com.apple.intelligencecontextd","com.apple.intelligenceflowd","com.apple.intelligencetasksd","com.apple.generativeexperiencesd","com.apple.knowledgeconstructiond","com.apple.naturallanguaged","com.apple.textunderstandingd","com.apple.modelcatalogd","com.apple.modelmanagerd","com.apple.mlhostd","com.apple.mlruntimed","com.apple.suggestd","com.apple.parsecd","com.apple.parsec-fbf","com.apple.proactiveeventtrackerd"]},{"id":"search","name":"Spotlight & Search","downside":"Spotlight and Settings search return no results.","approxMemoryMB":50,"labels":["com.apple.searchd","com.apple.searchtoold","com.apple.spotlightknowledged","com.apple.spotlightknowledged.updater","com.apple.corespotlightservice"]},{"id":"icloud","name":"iCloud & Apple Account","downside":"iCloud sync, Apple Account, Keychain, and backup workflows will not work.","approxMemoryMB":100,"labels":["com.apple.appleaccountd","com.apple.appleaccounttransparencyd","com.apple.appleidsetupd","com.apple.akd","com.apple.amsaccountsd","com.apple.amsengagementd","com.apple.amsondevicestoraged","com.apple.cloudd","com.apple.cloudphotod","com.apple.ckdiscretionaryd","com.apple.cloudsettingssyncagent","com.apple.bird","com.apple.syncdefaultsd","com.apple.cdpd","com.apple.sosd","com.apple.SecureBackupDaemon","com.apple.TrustedPeersHelper","com.apple.protectedcloudstorage.protectedcloudkeysyncing","com.apple.icloudmailagent","com.apple.icloudsubscriptionoptimizerd","com.apple.communicationtrustd"]},{"id":"store","name":"App Store, Push & Media","downside":"Remote push notifications and StoreKit or App Store testing will not work.","approxMemoryMB":80,"labels":["com.apple.appstored","com.apple.appstorecomponentsd","com.apple.apsd","com.apple.itunescloudd","com.apple.itunesstored","com.apple.storekitd","com.apple.amsaccountsd","com.apple.amsengagementd","com.apple.amsondevicestoraged","com.apple.passd","com.apple.financed","com.apple.videosubscriptionsd","com.apple.assetsubscriptiond","com.apple.musicd"]},{"id":"pim","name":"Mail, Calendar & Contacts","downside":"Contacts, Calendar, Reminders, and Mail-backed pickers or sync may fail.","approxMemoryMB":80,"labels":["com.apple.email.maild","com.apple.exchangesyncd","com.apple.dataaccess.dataaccessd","com.apple.calaccessd","com.apple.remindd","com.apple.contactsd","com.apple.contacts.postersyncd","com.apple.peopled"]},{"id":"web","name":"Safari Sync & Web Services","downside":"Universal links and Safari sync or background web services will not work.","approxMemoryMB":50,"labels":["com.apple.SafariBookmarksSyncAgent","com.apple.Safari.History","com.apple.Safari.passwordbreachd","com.apple.Safari.SafeBrowsing.Service","com.apple.safarifetcherd","com.apple.WebBookmarks.webbookmarksd","com.apple.webkit.adattributiond","com.apple.webkit.webpushd","com.apple.webprivacyd","com.apple.swcd"]},{"id":"family","name":"Family & Screen Time","downside":"Family Sharing, Screen Time, and usage tracking stop working.","approxMemoryMB":65,"labels":["com.apple.familycircled","com.apple.FamilyControlsAgent","com.apple.familynotification","com.apple.askpermissiond","com.apple.asktod","com.apple.ScreenTimeAgent","com.apple.ScreenTimeSettingsAgent","com.apple.UsageTrackingAgent"]},{"id":"health","name":"Health, Home & Fitness","downside":"HealthKit, HomeKit, and Fitness integrations will not work.","approxMemoryMB":135,"labels":["com.apple.healthd","com.apple.healthappd","com.apple.healthcontentd","com.apple.healtheventsd","com.apple.healthrecordsd","com.apple.finhealthd","com.apple.homed","com.apple.homeeventsd","com.apple.fitcore","com.apple.fitcore.session","com.apple.fitnesscoachingd","com.apple.fitnessintelligenced","com.apple.activityawardsd","com.apple.activitysharingd"]},{"id":"photos","name":"Photos & Media Analysis","downside":"Photo picker, Photos-library workflows, and media analysis may fail.","approxMemoryMB":60,"labels":["com.apple.photoanalysisd","com.apple.photosface","com.apple.mediaanalysisd","com.apple.mediaanalysisd.service","com.apple.mediastream.mstreamd","com.apple.medialibraryd","com.apple.assetsd","com.apple.assetsd.nebulad"]},{"id":"apps","name":"News, Weather, Maps & Games","downside":"News, Weather, Maps background data, and game-controller services are unavailable.","approxMemoryMB":90,"labels":["com.apple.newsd","com.apple.weatherd","com.apple.Maps.mapssyncd","com.apple.Maps.mapspushd","com.apple.Maps.geocorrectiond","com.apple.maps.destinationd","com.apple.MapKit.SnapshotService","com.apple.jetpackassetd","com.apple.tipsd","com.apple.gamed","com.apple.gamesaved","com.apple.GameController.gamecontrollerd"]},{"id":"messaging","name":"Messaging & FaceTime","downside":"iMessage, FaceTime, and related identity services will not work.","approxMemoryMB":60,"labels":["com.apple.identityservicesd","com.apple.ids_simd","com.apple.imautomatichistorydeletionagent","com.apple.imcore.imtransferagent","com.apple.imdpersistence.IMDPersistenceAgent","com.apple.facetimemessagestored","com.apple.telephonyutilities.callservicesd"]},{"id":"connectivity","name":"Sharing & Device Connectivity","downside":"AirDrop, Continuity, CarPlay, Watch, and Find My connectivity will not work.","approxMemoryMB":65,"labels":["com.apple.rapportd","com.apple.companiond","com.apple.carkitd","com.apple.wcd","com.apple.tvremoted","com.apple.avatarsd","com.apple.stickersd","com.apple.sociallayerd","com.apple.announced","com.apple.navd","com.apple.findmy.findmylocated"]},{"id":"telemetry","name":"Ads, Diagnostics & Telemetry","downside":"DeviceCheck plus analytics, diagnostics, and feedback services are unavailable.","approxMemoryMB":105,"labels":["com.apple.ap.adprivacyd","com.apple.ap.promotedcontentd","com.apple.diagnosticextensionsd","com.apple.feedbackd","com.apple.rtcreportingd","com.apple.securityuploadd","com.apple.geoanalyticsd","com.apple.triald","com.apple.followupd","com.apple.purplebuddy.budd","com.apple.devicecheckd"]},{"id":"other","name":"Other Background Services","downside":"Wallet, merchant, business, asset, and miscellaneous background services are unavailable.","approxMemoryMB":195,"labels":["com.apple.financed","com.apple.passd","com.apple.merchantd","com.apple.coreidvd","com.apple.businessservicesd","com.apple.deviceaccessd","com.apple.replicatord","com.apple.linkd","com.apple.ind","com.apple.storagedatad","com.apple.StatusKitAgent","com.apple.countryd","com.apple.mobileassetd","com.apple.managedconfiguration.passcodenagd"]}];function Ms(){const e=new Set(ks);const t=new Set;for(const s of Ce)for(const i of s.labels)if(!e.has(i))t.add(i);return[...t].sort()}function Ee(e){return e==="slim"?Ms():[]}function _s(e){return bo("sha256").update(e+"\n"+Ee(e).join("\n")).digest("hex").slice(0,16)}import{promises as q,existsSync as $t,readFileSync as ko}from"fs";import C from"path";import{AsyncLocalStorage as Mo}from"async_hooks";import{createHash as _o,randomBytes as we}from"crypto";import{promises as $e}from"fs";import It from"path";import{randomBytes as Eo}from"crypto";import{spawn as $o}from"child_process";var xe=new Set;function Bt(){return xe.size}function Io(){for(const e of xe){try{e.kill("SIGKILL")}catch{}}}function _(e,t,s={}){const{timeoutMs:i=3e4,maxBytes:o=4*1024*1024}=s;return new Promise(n=>{const a=$o(e,t,{env:s.env??process.env,stdio:[s.input==null?"ignore":"pipe","pipe","pipe"]});xe.add(a);let r="";let c="";let l=false;a.stdout.on("data",h=>{if(r.length<o)r+=h.toString("utf8")});a.stderr.on("data",h=>{if(c.length<o)c+=h.toString("utf8")});if(s.input!=null)a.stdin.end(s.input);const d=setTimeout(()=>{l=true;a.kill("SIGTERM");setTimeout(()=>a.kill("SIGKILL"),2e3).unref?.()},i);a.on("error",h=>{xe.delete(a);clearTimeout(d);n({code:null,stdout:r,stderr:c+String(h),timedOut:l})});a.on("close",h=>{xe.delete(a);clearTimeout(d);n({code:h,stdout:r,stderr:c,timedOut:l})})})}async function L(e,t,s={}){const i=await _(e,t,s);if(i.timedOut)throw new Error(`${e} ${t.slice(0,3).join(" ")} timed out after ${s.timeoutMs??3e4} ms`);if(i.code!==0)throw new Error(`${e} ${t.slice(0,3).join(" ")} failed (${i.code}): ${(i.stderr||i.stdout).trim().slice(0,500)}`);return i.stdout}async function tt(){const e=await L("ps",["-axww","-o","pid=,ppid=,lstart=,stat=,comm="],{timeoutMs:15e3});const t=await L("ps",["-axww","-o","pid=,command="],{timeoutMs:15e3});const s=new Map;for(const o of t.split("\n")){const n=/^\s*(\d+)\s+(.*)$/.exec(o);if(n)s.set(Number(n[1]),n[2])}const i=[];for(const o of e.split("\n")){const n=/^\s*(\d+)\s+(\d+)\s+(\w{3}\s+\w{3}\s+\d+\s+[\d:]+\s+\d{4})\s+(\S+)\s+(.*)$/.exec(o);if(!n)continue;const a=Number(n[1]);i.push({pid:a,ppid:Number(n[2]),start:n[3].replace(/\s+/g," "),stat:n[4],comm:n[5].trim(),command:s.get(a)??n[5].trim()})}return i}function Ot(e,t){const s=new Map;const i=new Map;for(const c of e){i.set(c.pid,c);const l=s.get(c.ppid)??[];l.push(c);s.set(c.ppid,l)}const o=[];const n=i.get(t);if(!n)return o;const a=[n];const r=new Set;while(a.length){const c=a.pop();if(r.has(c.pid))continue;r.add(c.pid);o.push(c);for(const l of s.get(c.pid)??[])a.push(l)}return o}async function Ie(e){const t=await _("ps",["-o","lstart=","-p",String(e)],{timeoutMs:5e3});const s=t.stdout.trim().replace(/\s+/g," ");return t.code===0&&s?s:null}async function J(e,t,s=false){if(!Number.isInteger(e)||e<=0)return false;try{process.kill(e,0)}catch(o){if(o.code!=="EPERM")return false}if(!t)return true;const i=await Ie(e);if(i===null)return s;return i===t}function st(e=process.env){return Object.fromEntries(Object.entries(e).filter(([t])=>!t.startsWith("SIMCTL_CHILD_")))}var T=e=>new Promise(t=>setTimeout(t,e));var Be=process.env.BUOY_FARM_DISABLED_ROOT||"/private/var/tmp";function Es(e,t=Be){if(!/^[0-9A-F-]{36}$/i.test(e))throw new Error(`not a UDID: ${e}`);return It.join(t,`com.apple.CoreSimulator.SimDevice.${e}`)}function $s(e,t=Be){return It.join(Es(e,t),"disabled.plist")}async function Is(e,t=Be){const s=$s(e,t);let i;try{i=await $e.lstat(s)}catch{return{}}if(!i.isFile())throw new Error(`refusing ${s}: not a regular file`);const o=await L("plutil",["-convert","json","-o","-",s],{timeoutMs:1e4});const n=JSON.parse(o);const a={};for(const[r,c]of Object.entries(n))if(typeof c==="boolean")a[r]=c;return a}function Bo(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function Oo(e){const t=Object.keys(e).sort();let s='<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0">\n<dict>\n';for(const i of t)s+=` <key>${Bo(i)}</key>
|
|
2
2
|
<${e[i]?"true":"false"}/>
|
|
3
|
-
`;return s+"</dict>\n</plist>\n"}async function Bs(e,t,s=Be){const i=Es(e,s);await $e.mkdir(i,{recursive:true});const o=await $e.lstat(i);if(!o.isDirectory())throw new Error(`refusing ${i}: not a directory`);const n=await Is(e,s);const a=It.join(i,"buoy-farm-prior.json");let r={};try{r=JSON.parse(await $e.readFile(a,"utf8"))}catch{}const c={...n};for(const l of t){if(!(l in r))r[l]=l in n?n[l]:null;c[l]=true}await Os(a,JSON.stringify(r,null,2)+"\n");await Os($s(e,s),Oo(c))}async function To(e,t,s=Be){const i=await Is(e,s);return t.every(o=>i[o]===true)}async function Os(e,t){const s=`${e}.${Eo(4).toString("hex")}.tmp`;const i=await $e.open(s,"w",420);try{await i.writeFile(t);await i.sync()}finally{await i.close()}await $e.rename(s,e)}import{promises as W,existsSync as ge,readFileSync as
|
|
4
|
-
`)}}}await s(e);return t.digest("hex").slice(0,16)}async function Ro(e){const t=Ts("sha256");const s=O.join(e,"Info.plist");t.update(await W.readFile(s));const i=JSON.parse(await L("plutil",["-convert","json","-o","-",s],{timeoutMs:1e4}));const o=O.join(e,String(i.CFBundleExecutable??""));const n=await W.stat(o);t.update(`${n.size}:${Math.floor(n.mtimeMs)}`);return t.digest("hex").slice(0,16)}async function Po(e,t){const s=async i=>{const o=await W.readFile(O.join(i,"Info.plist"));const n=JSON.parse(await L("plutil",["-convert","json","-o","-",O.join(i,"Info.plist")],{timeoutMs:1e4}));const a=await W.stat(O.join(i,String(n.CFBundleExecutable??"")));return`${o.toString("base64")}:${a.size}`};try{return await s(e)===await s(t)}catch{return false}}async function No(e){const t=JSON.parse(await L("plutil",["-convert","json","-o","-",O.join(e,"Info.plist")],{timeoutMs:1e4}));if(!t.CFBundleIdentifier)throw new Error(`${e} has no CFBundleIdentifier`);return String(t.CFBundleIdentifier)}async function it(e,t){const s=O.join(e,"Containers/Data/Application");let i;try{i=await W.readdir(s)}catch{return null}for(const o of i){const n=O.join(s,o,".com.apple.mobile_container_manager.metadata.plist");if(!ge(n))continue;const a=await _("plutil",["-extract","MCMMetadataIdentifier","raw","-o","-",n],{timeoutMs:5e3});if(a.code===0&&a.stdout.trim()===t)return O.join(s,o)}return null}function Co(e,t){return O.join(e,"Library/Application Support",t,"RCTAsyncLocalStorage_V1")}async function As(e,t,s,i){i();await W.mkdir(t,{recursive:true});const o=["-a","--delete"];for(const n of s)o.push("--exclude",n);o.push(e.replace(/\/?$/,"/"),t.replace(/\/?$/,"/"));i();await L("rsync",o,{timeoutMs:6e4})}async function Rs(e,t,s,i=()=>{}){i();const o=Le(s);if(o)throw new Error(o);const n=[...Ds.map(c=>`react-buoy/${c}`),`react-buoy/${Do}`];if(ge(O.join(s,"Documents")))await As(O.join(s,"Documents"),O.join(e,"Documents"),n,i);if(ge(O.join(s,"AsyncStorage/manifest.json"))){await As(O.join(s,"AsyncStorage"),Co(e,t),[],i)}const a=O.join(s,"Preferences",`${t}.plist`);if(ge(a)){i();await W.mkdir(O.join(e,"Library/Preferences"),{recursive:true});await W.copyFile(a,O.join(e,"Library/Preferences",`${t}.plist`))}const r=O.join(e,"Documents/react-buoy");try{for(const c of await W.readdir(r)){i();if(c.startsWith("@buoy~1floating-tool~1"))await W.rm(O.join(r,c),{force:true,recursive:true})}}catch{}}async function ot(e,t=()=>{}){t();const s=[];const i=O.join(e,"Documents/react-buoy");let o=[];try{o=await W.readdir(i)}catch{return s}for(const n of o){if(Ds.includes(n)||n.startsWith("@buoy~1floating-tool~1")){t();await W.rm(O.join(i,n),{force:true,recursive:true});s.push(n)}}return s}async function Ps(e){let t;try{t=await W.readFile(O.join(e,"Documents/react-buoy/@react_buoy_sync_device_id.json"),"utf8")}catch{return null}try{const s=JSON.parse(t);if(typeof s==="string")return s||null;if(typeof s?.value==="string")return s.value||null}catch{}return t.trim()||null}var Ns=2*60*6e4;var xo=10;var Lo=5;var Uo=.8;var ye=e=>Math.round(e*10)/10;var jo=e=>{if(!e.length)return 0;const t=[...e].sort((i,o)=>i-o);const s=t.length>>1;return t.length%2?t[s]:(t[s-1]+t[s])/2};var Cs=class{constructor(e,t,s=1e3,i=Date.now){this.host=e;this.target=t;this.periodMs=s;this.now=i;this.samples=[];this.prev=null;this.pids=[];this.treeAge=0;this.treeKey="";this.sampling=false;this.ticks=0;this.lastProcs=null;this.rates={ours:0,graphics:0,gpuPct:null};this.cpuCount=0}async tick(){if(this.sampling)return;this.sampling=true;try{const e=this.target();if(!e){this.prev=null;this.treeKey="";return}const t=`${e.leaseId}:${e.udids.join(",")}`;if(t!==this.treeKey||++this.treeAge>=xo){const f=await Promise.all(e.udids.map(w=>this.host.simTree(w)));this.pids=f.flat().map(w=>w.pid);this.treeAge=0;if(t!==this.treeKey){this.prev=null;this.lastProcs=null;this.ticks=0;this.rates={ours:0,graphics:0,gpuPct:null}}this.treeKey=t}const s=this.ticks++;const i=await this.host.loadCounters(this.pids,s<2||s%Lo===0);this.cpuCount=i.cpuCount;const o=this.now();const n=this.prev;this.prev={...i,at:o,leaseId:e.leaseId};const a=f=>(i.hostTotalMs-f)/Math.max(1,i.cpuCount);if(i.pidsCpuMs!==null&&i.graphicsCpuMs!==null){const f=this.lastProcs;const w=f?a(f.hostTotalMs):0;if(f&&w>0){this.rates.ours=Math.max(0,(i.pidsCpuMs-f.pidsCpuMs)/w);this.rates.graphics=Math.max(0,(i.graphicsCpuMs-f.graphicsCpuMs)/w)}this.rates.gpuPct=i.gpuPct;this.lastProcs={hostTotalMs:i.hostTotalMs,pidsCpuMs:i.pidsCpuMs,graphicsCpuMs:i.graphicsCpuMs}}if(!n||n.leaseId!==e.leaseId)return;const r=a(n.hostTotalMs);if(r<=0)return;const c=Math.max(0,(i.hostBusyMs-n.hostBusyMs)/r);const l=this.rates.ours;const d=this.rates.graphics;this.samples.push({at:Math.round((o+n.at)/2),leaseId:e.leaseId,freeCores:ye(Math.max(0,i.cpuCount-c)),ourCores:ye(l),graphicsCores:ye(d),outsideCores:ye(Math.max(0,c-l-d)),gpuPct:this.rates.gpuPct,memLevel:i.memPressureLevel,swapMB:i.swapUsedMB,thermal:i.thermalLevel});const h=o-Ns;while(this.samples.length&&this.samples[0].at<h)this.samples.shift()}finally{this.sampling=false}}before(e,t){for(let s=this.samples.length-1;s>=0;s--){const i=this.samples[s];if(i.at<t)return i.leaseId===e?i:void 0}return void 0}latest(){return this.samples[this.samples.length-1]}verdicts(e,t,s){const i=this.periodMs/2;const o=t.map(a=>{const r=this.samples.filter(l=>l.at>=a.from-i&&l.at<=a.to+i);const c=r.filter(l=>l.leaseId===e);return{w:a,all:r,mine:c}});const n=jo(o.filter(a=>a.mine.length).map(a=>Tt(a.mine.map(r=>r.outsideCores))));return o.map(({w:a,all:r,mine:c})=>{const l=Math.max(1,Math.round((a.to-a.from)/this.periodMs));const d={id:a.id,fair:false,seconds:c.length};if(!r.length&&(a.from>this.now()+6e4||a.to<this.now()-Ns)){return{...d,reason:"This run's time doesn't match the Mac's clock. Was the app's clock moved? Put it back and run again."}}if(!c.length||c.length<r.length||c.length<Math.floor(l*Uo)){return{...d,reason:"No load record for all of this run. Hold perf-slot for the whole test."}}const h=c.map(y=>y.outsideCores);const f=c.map(y=>y.gpuPct).filter(y=>y!==null);const w=c.map(y=>y.thermal).filter(y=>y!==null);const v={...d,freeCoresMin:Math.min(...c.map(y=>y.freeCores)),outsideCoresAvg:ye(Tt(h)),outsideCoresMax:Math.max(...h),ourCoresAvg:ye(Tt(c.map(y=>y.ourCores))),graphicsCoresMax:Math.max(...c.map(y=>y.graphicsCores)),gpuMaxPct:f.length?Math.max(...f):null,swapGrowthMB:Math.round(Math.max(0,c[c.length-1].swapMB-(this.before(e,a.from)?.swapMB??c[0].swapMB))),thermalMax:w.length?Math.max(...w):null};if(v.thermalMax!=null&&v.thermalMax>s.maxThermalLevel){return{...v,reason:"The Mac got hot and slowed itself down. Let it cool, then run again."}}if(c.some(y=>y.memLevel>=4)){return{...v,reason:"The Mac ran low on memory. Close apps or stop sims you don't need."}}if(v.swapGrowthMB>s.maxSwapGrowthMB){return{...v,reason:`The Mac swapped ${v.swapGrowthMB} MB of memory to disk.`}}if(v.freeCoresMin<s.minFreeCores){return{...v,reason:`The Mac ran out of spare CPU (${v.freeCoresMin} cores free, needs ${s.minFreeCores}).`}}const k=ye(v.outsideCoresMax-n);if(k>s.maxSwingCores){return{...v,reason:`Other work on the Mac jumped by ${k} cores during this run.`}}return{...v,fair:true}})}};function Tt(e){return e.length?e.reduce((t,s)=>t+s,0)/e.length:0}function xs(e){const t=e.trim().split(":").map(Number);if(!t.length||t.some(s=>!Number.isFinite(s)))return 0;return Math.round(t.reduce((s,i)=>s*60+i,0)*1e3)}import{spawn as Ls}from"child_process";import{randomBytes as Fo}from"crypto";import{existsSync as Dt,mkdirSync as Go,openSync as Wo,closeSync as Ho,promises as ve,writeFileSync as Us}from"fs";import qo from"net";import Y from"path";import{createHash as Yo}from"crypto";import{createReadStream as zo,createWriteStream as Ko,existsSync as Ue,promises as se,readFileSync as Qo}from"fs";import At from"os";import j from"path";import{Readable as Vo}from"stream";import{pipeline as js}from"stream/promises";var je="https://dl.google.com/android/repository/";var Jo="channel-0";var ne={api:36,tag:"aosp_atd",abi:Xo()};function Xo(){return At.arch()==="arm64"?"arm64-v8a":"x86_64"}function nt(e){return`system-images/android-${e.api}/${e.tag}/${e.abi}/`}function Fs(e){return j.join(e,"sdk")}function Rt(e=process.env){const t=At.homedir();const s=[e.ANDROID_HOME,e.ANDROID_SDK_ROOT,j.join(t,"Library/Android/sdk"),j.join(t,"Android/Sdk")];return[...new Set(s.filter(i=>!!i))]}function Gs(e){try{const t=/Pkg\.Revision=([\d.]+)/.exec(Qo(j.join(e,"emulator/source.properties"),"utf8"));return t?.[1]??null}catch{return null}}function Pt(e,t){const s=e.split(".").map(Number);const i=t.split(".").map(Number);for(let o=0;o<Math.max(s.length,i.length);o++){const n=(s[o]??0)-(i[o]??0);if(n)return n}return 0}var Ws="35.4.9";function Fe(e,t,s=ne){const i=j.join(e,"emulator",process.platform==="win32"?"emulator.exe":"emulator");const o=j.join(e,"platform-tools",process.platform==="win32"?"adb.exe":"adb");const n=Gs(e);if(!Ue(i)||!Ue(o)||!n)return null;return{root:e,source:t,emulator:i,emulatorVersion:n,adb:o,hasImage:Ue(j.join(e,nt(s),"system.img"))}}function Ge(e,t=ne,s="auto"){const i=Fe(Fs(e),"buoy",t);if(s!=="system"&&i?.hasImage&&Pt(i.emulatorVersion,Ws)>=0)return i;if(s==="buoy")return i;for(const o of Rt()){const n=Fe(o,"system",t);if(n?.hasImage&&Pt(n.emulatorVersion,Ws)>=0)return n}return s==="system"?null:i}function Zo(e){return[...e.matchAll(/<remotePackage path="([^"]+)">([\s\S]*?)<\/remotePackage>/g)].map(t=>({path:t[1],body:t[2]}))}function en(e){const t=/<revision>([\s\S]*?)<\/revision>/.exec(e)?.[1]??"";return["major","minor","micro"].map(s=>new RegExp(`<${s}>(\\d+)</${s}>`).exec(t)?.[1]).filter(Boolean).join(".")}function tn(){return process.platform==="darwin"?"macosx":process.platform==="win32"?"windows":"linux"}function sn(){return At.arch()==="arm64"?"aarch64":"x64"}function Nt(e,t,s,i,o={}){const n=o.os??tn();const a=o.arch??sn();let r=null;for(const c of Zo(e)){if(c.path!==t)continue;if(!c.body.includes(`<channelRef ref="${Jo}"/>`))continue;const l=en(c.body);const d=/<uses-license ref="([^"]+)"/.exec(c.body)?.[1]??"";for(const h of c.body.matchAll(/<archive>([\s\S]*?)<\/archive>/g)){const f=h[1];const w=/<host-os>([^<]+)<\/host-os>/.exec(f)?.[1];const v=/<host-arch>([^<]+)<\/host-arch>/.exec(f)?.[1];if(w&&w!==n)continue;if(v&&v!==a)continue;const k=/<url>([^<]+)<\/url>/.exec(f)?.[1];const y=/<checksum type="sha1">([0-9a-f]+)<\/checksum>/.exec(f)?.[1];const b=Number(/<size>(\d+)<\/size>/.exec(f)?.[1]??0);if(!k||!y)continue;const E=/<display-name>([^<]+)<\/display-name>/.exec(c.body)?.[1]??t;if(!r||Pt(l,r.rev)>0){r={rev:l,a:{name:`${E} ${l}`,url:s+k,sha1:y,size:b,license:d,dest:i}}}}}return r?.a??null}function Hs(e,t){const s=new RegExp(`<license id="${t}" type="text">([\\s\\S]*?)</license>`).exec(e);return s?s[1].replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&").trim():null}async function qs(e){const t=await fetch(e);if(!t.ok)throw new Error(`GET ${e} failed: ${t.status}`);return t.text()}async function on(e=ne){const t=await qs(`${je}repository2-3.xml`);const s=`${je}sys-img/${e.tag}/`;const i=await qs(`${s}sys-img2-3.xml`);const o=Nt(t,"emulator",je,"emulator");const n=Nt(t,"platform-tools",je,"platform-tools");const a=Nt(i,`system-images;android-${e.api};${e.tag};${e.abi}`,s,nt(e));const r=[!o&&"emulator",!n&&"platform-tools",!a&&`${e.tag} image for Android ${e.api}`].filter(Boolean);if(r.length)throw new Error(`Google's list has no stable ${r.join(", ")} for this computer.`);const c=[o,n,a];const l={};for(const d of c){if(l[d.license])continue;l[d.license]=Hs(t,d.license)??Hs(i,d.license)??`(See ${je} for license ${d.license}.)`}return{archives:c,licenses:l}}async function Ys(e){const t=Yo("sha1");await js(zo(e),t);return t.digest("hex")}async function nn(e,t,s=()=>{}){if(process.platform==="win32")throw new Error("The Android farm can't set up its own SDK on Windows yet.");const i=Fs(e);const o=j.join(e,"download");await se.mkdir(o,{recursive:true});await Promise.all(t.archives.map(async a=>{const r=j.join(i,a.dest);if(a.dest==="emulator"?Gs(i):Ue(j.join(r,a.dest==="platform-tools"?"adb":"system.img"))){s(`${a.name}: already here.`);return}const c=j.join(o,j.basename(a.url));if(!Ue(c)||await Ys(c)!==a.sha1){s(`Downloading ${a.name} (${Math.round(a.size/1024**2)} MB)\u2026`);const h=await fetch(a.url);if(!h.ok||!h.body)throw new Error(`GET ${a.url} failed: ${h.status}`);await js(Vo.fromWeb(h.body),Ko(c));const f=await Ys(c);if(f!==a.sha1)throw new Error(`${a.name} failed its checksum (${f}).`)}const l=j.join(o,`unzip-${j.basename(a.url)}`);await se.rm(l,{recursive:true,force:true});await se.mkdir(l,{recursive:true});await L("unzip",["-q",c,"-d",l],{timeoutMs:15*6e4});const[d]=await se.readdir(l);await se.mkdir(j.dirname(r),{recursive:true});await se.rm(r,{recursive:true,force:true});await se.rename(j.join(l,d),r);await se.rm(l,{recursive:true,force:true});await se.rm(c,{force:true});s(`${a.name}: ready.`)}));await se.rm(o,{recursive:true,force:true});const n=Fe(i,"buoy");if(!n)throw new Error(`The SDK at ${i} is not complete after the download.`);return n}import{existsSync as an,promises as Ct,readFileSync as rn}from"fs";import cn from"path";var xt="android-3gb";var zs={"android-3gb":{name:"Low-end Android (3 GB)",ramMB:3072,cores:4,width:720,height:1600,density:320,heapGrowthMB:192,heapMB:512,source:"built in"},"pixel-4a":{name:"Pixel 4a",ramMB:6144,cores:8,width:1080,height:2340,density:440,heapGrowthMB:256,heapMB:512,source:"built in"}};function Ks(e){return cn.join(e,"phones.json")}function Lt(e){const t={...zs};const s=Ks(e);if(an(s)){try{Object.assign(t,JSON.parse(rn(s,"utf8")))}catch{}}return t}async function ln(e,t,s){const i=Ks(e);let o={};try{o=JSON.parse(await Ct.readFile(i,"utf8"))}catch{}o[t]=s;await Ct.mkdir(e,{recursive:true});await Ct.writeFile(i,JSON.stringify(o,null,2)+"\n")}var dn=[1024,1536,2048,3072,4096,6144,8192,12288,16384,24576];function pn(e,t){const s=h=>new RegExp(`\\[${h.replace(/\./g,"\\.")}\\]: \\[([^\\]]*)\\]`).exec(e.props)?.[1]??"";const i=Number(/MemTotal:\s+(\d+)/.exec(e.meminfo)?.[1]??0);const o=i?dn.find(h=>h>=i/1024)??Math.ceil(i/1024/1024)*1024:0;const n=/Override size: (\d+)x(\d+)/.exec(e.wmSize)??/Physical size: (\d+)x(\d+)/.exec(e.wmSize);const a=/Override density: (\d+)/.exec(e.wmDensity)??/Physical density: (\d+)/.exec(e.wmDensity);const r=h=>Number(/^(\d+)m$/i.exec(h)?.[1]??0);const c=s("ro.product.model")||"Android phone";const l={name:c,ramMB:o||3072,cores:Number(e.nproc.trim())||4,width:n?Number(n[1]):1080,height:n?Number(n[2]):2400,density:a?Number(a[1]):420,heapGrowthMB:r(s("dalvik.vm.heapgrowthlimit"))||256,heapMB:r(s("dalvik.vm.heapsize"))||512,source:t};const d=c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"android-phone";return{id:d,phone:l}}import{promises as bc,readFileSync as un}from"fs";import Ut from"os";import jt from"path";import{promises as hn,existsSync as Ft,mkdirSync as Gt,readFileSync as Se,renameSync as Wt,writeFileSync as at,rmSync as We,openSync as mn,fsyncSync as fn,closeSync as wn,chmodSync as gn,readdirSync as yn,statSync as Qs}from"fs";import vn from"os";import H from"path";import{createHash as Sn,randomBytes as He}from"crypto";function A(){return process.env.BUOY_FARM_HOME||H.join(vn.homedir(),".buoy","farm")}var X=(e=A())=>({home:e,lock:H.join(e,"owner.lock"),lockOwner:H.join(e,"owner.lock","owner.json"),socket:H.join(e,"farmd.sock"),token:H.join(e,"token"),state:H.join(e,"state.json"),journal:H.join(e,"journal.ndjson"),log:H.join(e,"farmd.log"),shots:H.join(e,"shots")});function Ht(e=A()){Gt(e,{recursive:true,mode:448});try{gn(e,448)}catch{}}function Vs(e=A()){const t=X(e).token;try{const s=Se(t,"utf8").trim();if(s)return s}catch{}Ht(e);try{at(t,He(24).toString("hex")+"\n",{mode:384,flag:"wx"})}catch(s){if(s.code!=="EEXIST")throw s}for(let s=0;s<20;s++){const i=Se(t,"utf8").trim();if(i)return i;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,25)}throw new Error(`farm token at ${t} is empty`)}async function qe(e=A()){try{return JSON.parse(await hn.readFile(X(e).lockOwner,"utf8"))}catch{return null}}async function Ye(e){return!!e&&await J(e.pid,e.start,true)}async function bn(e,t){const s=H.join(e,"owner.claim");for(let i=0;i<20;i++){try{Gt(s,{mode:448});at(H.join(s,"pid"),`${process.pid}
|
|
3
|
+
`;return s+"</dict>\n</plist>\n"}async function Bs(e,t,s=Be){const i=Es(e,s);await $e.mkdir(i,{recursive:true});const o=await $e.lstat(i);if(!o.isDirectory())throw new Error(`refusing ${i}: not a directory`);const n=await Is(e,s);const a=It.join(i,"buoy-farm-prior.json");let r={};try{r=JSON.parse(await $e.readFile(a,"utf8"))}catch{}const c={...n};for(const l of t){if(!(l in r))r[l]=l in n?n[l]:null;c[l]=true}await Os(a,JSON.stringify(r,null,2)+"\n");await Os($s(e,s),Oo(c))}async function To(e,t,s=Be){const i=await Is(e,s);return t.every(o=>i[o]===true)}async function Os(e,t){const s=`${e}.${Eo(4).toString("hex")}.tmp`;const i=await $e.open(s,"w",420);try{await i.writeFile(t);await i.sync()}finally{await i.close()}await $e.rename(s,e)}import{promises as W,existsSync as ge,readFileSync as ac}from"fs";import O from"path";import{createHash as Ts}from"crypto";var Ds=["@react_buoy_sync_device_id.json","@react_buoy_install.json"];var Do="@buoy~1floating-tool~1*";function Le(e){if(!ge(O.join(e,"seed.json")))return`No seed at ${e}. Run: pnpm e2e:pool seed`;if(ge(O.join(e,"Documents/buoy-license"))){for(const t of["buoy-gg-license.json","buoy-gg-device-fingerprint.json"]){if(!ge(O.join(e,"Documents/buoy-license",t)))return`The seed lacks ${t}.`}}return null}async function Ao(e){const t=Ts("sha256");async function s(i){let o;try{o=await W.readdir(i,{withFileTypes:true})}catch{return}o.sort((n,a)=>n.name.localeCompare(a.name));for(const n of o){const a=O.join(i,n.name);if(n.isDirectory())await s(a);else{const r=await W.stat(a);t.update(`${O.relative(e,a)}:${r.size}:${Math.floor(r.mtimeMs)}
|
|
4
|
+
`)}}}await s(e);return t.digest("hex").slice(0,16)}async function Ro(e){const t=Ts("sha256");const s=O.join(e,"Info.plist");t.update(await W.readFile(s));const i=JSON.parse(await L("plutil",["-convert","json","-o","-",s],{timeoutMs:1e4}));const o=O.join(e,String(i.CFBundleExecutable??""));const n=await W.stat(o);t.update(`${n.size}:${Math.floor(n.mtimeMs)}`);return t.digest("hex").slice(0,16)}async function Po(e,t){const s=async i=>{const o=await W.readFile(O.join(i,"Info.plist"));const n=JSON.parse(await L("plutil",["-convert","json","-o","-",O.join(i,"Info.plist")],{timeoutMs:1e4}));const a=await W.stat(O.join(i,String(n.CFBundleExecutable??"")));return`${o.toString("base64")}:${a.size}`};try{return await s(e)===await s(t)}catch{return false}}async function No(e){const t=JSON.parse(await L("plutil",["-convert","json","-o","-",O.join(e,"Info.plist")],{timeoutMs:1e4}));if(!t.CFBundleIdentifier)throw new Error(`${e} has no CFBundleIdentifier`);return String(t.CFBundleIdentifier)}async function it(e,t){const s=O.join(e,"Containers/Data/Application");let i;try{i=await W.readdir(s)}catch{return null}for(const o of i){const n=O.join(s,o,".com.apple.mobile_container_manager.metadata.plist");if(!ge(n))continue;const a=await _("plutil",["-extract","MCMMetadataIdentifier","raw","-o","-",n],{timeoutMs:5e3});if(a.code===0&&a.stdout.trim()===t)return O.join(s,o)}return null}function Co(e,t){return O.join(e,"Library/Application Support",t,"RCTAsyncLocalStorage_V1")}async function As(e,t,s,i){i();await W.mkdir(t,{recursive:true});const o=["-a","--delete"];for(const n of s)o.push("--exclude",n);o.push(e.replace(/\/?$/,"/"),t.replace(/\/?$/,"/"));i();await L("rsync",o,{timeoutMs:6e4})}async function Rs(e,t,s,i=()=>{}){i();const o=Le(s);if(o)throw new Error(o);const n=[...Ds.map(c=>`react-buoy/${c}`),`react-buoy/${Do}`];if(ge(O.join(s,"Documents")))await As(O.join(s,"Documents"),O.join(e,"Documents"),n,i);if(ge(O.join(s,"AsyncStorage/manifest.json"))){await As(O.join(s,"AsyncStorage"),Co(e,t),[],i)}const a=O.join(s,"Preferences",`${t}.plist`);if(ge(a)){i();await W.mkdir(O.join(e,"Library/Preferences"),{recursive:true});await W.copyFile(a,O.join(e,"Library/Preferences",`${t}.plist`))}const r=O.join(e,"Documents/react-buoy");try{for(const c of await W.readdir(r)){i();if(c.startsWith("@buoy~1floating-tool~1"))await W.rm(O.join(r,c),{force:true,recursive:true})}}catch{}}async function ot(e,t=()=>{}){t();const s=[];const i=O.join(e,"Documents/react-buoy");let o=[];try{o=await W.readdir(i)}catch{return s}for(const n of o){if(Ds.includes(n)||n.startsWith("@buoy~1floating-tool~1")){t();await W.rm(O.join(i,n),{force:true,recursive:true});s.push(n)}}return s}async function Ps(e){let t;try{t=await W.readFile(O.join(e,"Documents/react-buoy/@react_buoy_sync_device_id.json"),"utf8")}catch{return null}try{const s=JSON.parse(t);if(typeof s==="string")return s||null;if(typeof s?.value==="string")return s.value||null}catch{}return t.trim()||null}var Ns=2*60*6e4;var xo=10;var Lo=5;var Uo=.8;var ye=e=>Math.round(e*10)/10;var jo=e=>{if(!e.length)return 0;const t=[...e].sort((i,o)=>i-o);const s=t.length>>1;return t.length%2?t[s]:(t[s-1]+t[s])/2};var Cs=class{constructor(e,t,s=1e3,i=Date.now){this.host=e;this.target=t;this.periodMs=s;this.now=i;this.samples=[];this.prev=null;this.pids=[];this.treeAge=0;this.treeKey="";this.sampling=false;this.ticks=0;this.lastProcs=null;this.rates={ours:0,graphics:0,gpuPct:null};this.cpuCount=0}async tick(){if(this.sampling)return;this.sampling=true;try{const e=this.target();if(!e){this.prev=null;this.treeKey="";return}const t=`${e.leaseId}:${e.udids.join(",")}`;if(t!==this.treeKey||++this.treeAge>=xo){const f=await Promise.all(e.udids.map(w=>this.host.simTree(w)));this.pids=f.flat().map(w=>w.pid);this.treeAge=0;if(t!==this.treeKey){this.prev=null;this.lastProcs=null;this.ticks=0;this.rates={ours:0,graphics:0,gpuPct:null}}this.treeKey=t}const s=this.ticks++;const i=await this.host.loadCounters(this.pids,s<2||s%Lo===0);this.cpuCount=i.cpuCount;const o=this.now();const n=this.prev;this.prev={...i,at:o,leaseId:e.leaseId};const a=f=>(i.hostTotalMs-f)/Math.max(1,i.cpuCount);if(i.pidsCpuMs!==null&&i.graphicsCpuMs!==null){const f=this.lastProcs;const w=f?a(f.hostTotalMs):0;if(f&&w>0){this.rates.ours=Math.max(0,(i.pidsCpuMs-f.pidsCpuMs)/w);this.rates.graphics=Math.max(0,(i.graphicsCpuMs-f.graphicsCpuMs)/w)}this.rates.gpuPct=i.gpuPct;this.lastProcs={hostTotalMs:i.hostTotalMs,pidsCpuMs:i.pidsCpuMs,graphicsCpuMs:i.graphicsCpuMs}}if(!n||n.leaseId!==e.leaseId)return;const r=a(n.hostTotalMs);if(r<=0)return;const c=Math.max(0,(i.hostBusyMs-n.hostBusyMs)/r);const l=this.rates.ours;const d=this.rates.graphics;this.samples.push({at:Math.round((o+n.at)/2),leaseId:e.leaseId,freeCores:ye(Math.max(0,i.cpuCount-c)),ourCores:ye(l),graphicsCores:ye(d),outsideCores:ye(Math.max(0,c-l-d)),gpuPct:this.rates.gpuPct,memLevel:i.memPressureLevel,swapMB:i.swapUsedMB,thermal:i.thermalLevel});const h=o-Ns;while(this.samples.length&&this.samples[0].at<h)this.samples.shift()}finally{this.sampling=false}}before(e,t){for(let s=this.samples.length-1;s>=0;s--){const i=this.samples[s];if(i.at<t)return i.leaseId===e?i:void 0}return void 0}latest(){return this.samples[this.samples.length-1]}verdicts(e,t,s){const i=this.periodMs/2;const o=t.map(a=>{const r=this.samples.filter(l=>l.at>=a.from-i&&l.at<=a.to+i);const c=r.filter(l=>l.leaseId===e);return{w:a,all:r,mine:c}});const n=jo(o.filter(a=>a.mine.length).map(a=>Tt(a.mine.map(r=>r.outsideCores))));return o.map(({w:a,all:r,mine:c})=>{const l=Math.max(1,Math.round((a.to-a.from)/this.periodMs));const d={id:a.id,fair:false,seconds:c.length};if(!r.length&&(a.from>this.now()+6e4||a.to<this.now()-Ns)){return{...d,reason:"This run's time doesn't match the Mac's clock. Was the app's clock moved? Put it back and run again."}}if(!c.length||c.length<r.length||c.length<Math.floor(l*Uo)){return{...d,reason:"No load record for all of this run. Hold perf-slot for the whole test."}}const h=c.map(y=>y.outsideCores);const f=c.map(y=>y.gpuPct).filter(y=>y!==null);const w=c.map(y=>y.thermal).filter(y=>y!==null);const v={...d,freeCoresMin:Math.min(...c.map(y=>y.freeCores)),outsideCoresAvg:ye(Tt(h)),outsideCoresMax:Math.max(...h),ourCoresAvg:ye(Tt(c.map(y=>y.ourCores))),graphicsCoresMax:Math.max(...c.map(y=>y.graphicsCores)),gpuMaxPct:f.length?Math.max(...f):null,swapGrowthMB:Math.round(Math.max(0,c[c.length-1].swapMB-(this.before(e,a.from)?.swapMB??c[0].swapMB))),thermalMax:w.length?Math.max(...w):null};if(v.thermalMax!=null&&v.thermalMax>s.maxThermalLevel){return{...v,reason:"The Mac got hot and slowed itself down. Let it cool, then run again."}}if(c.some(y=>y.memLevel>=4)){return{...v,reason:"The Mac ran low on memory. Close apps or stop sims you don't need."}}if(v.swapGrowthMB>s.maxSwapGrowthMB){return{...v,reason:`The Mac swapped ${v.swapGrowthMB} MB of memory to disk.`}}if(v.freeCoresMin<s.minFreeCores){return{...v,reason:`The Mac ran out of spare CPU (${v.freeCoresMin} cores free, needs ${s.minFreeCores}).`}}const k=ye(v.outsideCoresMax-n);if(k>s.maxSwingCores){return{...v,reason:`Other work on the Mac jumped by ${k} cores during this run.`}}return{...v,fair:true}})}};function Tt(e){return e.length?e.reduce((t,s)=>t+s,0)/e.length:0}function xs(e){const t=e.trim().split(":").map(Number);if(!t.length||t.some(s=>!Number.isFinite(s)))return 0;return Math.round(t.reduce((s,i)=>s*60+i,0)*1e3)}import{spawn as Ls}from"child_process";import{randomBytes as Fo}from"crypto";import{existsSync as Dt,mkdirSync as Go,openSync as Wo,closeSync as Ho,promises as ve,writeFileSync as Us}from"fs";import qo from"net";import Y from"path";import{createHash as Yo}from"crypto";import{createReadStream as zo,createWriteStream as Ko,existsSync as Ue,promises as se,readFileSync as Qo}from"fs";import At from"os";import j from"path";import{Readable as Vo}from"stream";import{pipeline as js}from"stream/promises";var je="https://dl.google.com/android/repository/";var Jo="channel-0";var ne={api:36,tag:"aosp_atd",abi:Xo()};function Xo(){return At.arch()==="arm64"?"arm64-v8a":"x86_64"}function nt(e){return`system-images/android-${e.api}/${e.tag}/${e.abi}/`}function Fs(e){return j.join(e,"sdk")}function Rt(e=process.env){const t=At.homedir();const s=[e.ANDROID_HOME,e.ANDROID_SDK_ROOT,j.join(t,"Library/Android/sdk"),j.join(t,"Android/Sdk")];return[...new Set(s.filter(i=>!!i))]}function Gs(e){try{const t=/Pkg\.Revision=([\d.]+)/.exec(Qo(j.join(e,"emulator/source.properties"),"utf8"));return t?.[1]??null}catch{return null}}function Pt(e,t){const s=e.split(".").map(Number);const i=t.split(".").map(Number);for(let o=0;o<Math.max(s.length,i.length);o++){const n=(s[o]??0)-(i[o]??0);if(n)return n}return 0}var Ws="35.4.9";function Fe(e,t,s=ne){const i=j.join(e,"emulator",process.platform==="win32"?"emulator.exe":"emulator");const o=j.join(e,"platform-tools",process.platform==="win32"?"adb.exe":"adb");const n=Gs(e);if(!Ue(i)||!Ue(o)||!n)return null;return{root:e,source:t,emulator:i,emulatorVersion:n,adb:o,hasImage:Ue(j.join(e,nt(s),"system.img"))}}function Ge(e,t=ne,s="auto"){const i=Fe(Fs(e),"buoy",t);if(s!=="system"&&i?.hasImage&&Pt(i.emulatorVersion,Ws)>=0)return i;if(s==="buoy")return i;for(const o of Rt()){const n=Fe(o,"system",t);if(n?.hasImage&&Pt(n.emulatorVersion,Ws)>=0)return n}return s==="system"?null:i}function Zo(e){return[...e.matchAll(/<remotePackage path="([^"]+)">([\s\S]*?)<\/remotePackage>/g)].map(t=>({path:t[1],body:t[2]}))}function en(e){const t=/<revision>([\s\S]*?)<\/revision>/.exec(e)?.[1]??"";return["major","minor","micro"].map(s=>new RegExp(`<${s}>(\\d+)</${s}>`).exec(t)?.[1]).filter(Boolean).join(".")}function tn(){return process.platform==="darwin"?"macosx":process.platform==="win32"?"windows":"linux"}function sn(){return At.arch()==="arm64"?"aarch64":"x64"}function Nt(e,t,s,i,o={}){const n=o.os??tn();const a=o.arch??sn();let r=null;for(const c of Zo(e)){if(c.path!==t)continue;if(!c.body.includes(`<channelRef ref="${Jo}"/>`))continue;const l=en(c.body);const d=/<uses-license ref="([^"]+)"/.exec(c.body)?.[1]??"";for(const h of c.body.matchAll(/<archive>([\s\S]*?)<\/archive>/g)){const f=h[1];const w=/<host-os>([^<]+)<\/host-os>/.exec(f)?.[1];const v=/<host-arch>([^<]+)<\/host-arch>/.exec(f)?.[1];if(w&&w!==n)continue;if(v&&v!==a)continue;const k=/<url>([^<]+)<\/url>/.exec(f)?.[1];const y=/<checksum type="sha1">([0-9a-f]+)<\/checksum>/.exec(f)?.[1];const b=Number(/<size>(\d+)<\/size>/.exec(f)?.[1]??0);if(!k||!y)continue;const E=/<display-name>([^<]+)<\/display-name>/.exec(c.body)?.[1]??t;if(!r||Pt(l,r.rev)>0){r={rev:l,a:{name:`${E} ${l}`,url:s+k,sha1:y,size:b,license:d,dest:i}}}}}return r?.a??null}function Hs(e,t){const s=new RegExp(`<license id="${t}" type="text">([\\s\\S]*?)</license>`).exec(e);return s?s[1].replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&").trim():null}async function qs(e){const t=await fetch(e);if(!t.ok)throw new Error(`GET ${e} failed: ${t.status}`);return t.text()}async function on(e=ne){const t=await qs(`${je}repository2-3.xml`);const s=`${je}sys-img/${e.tag}/`;const i=await qs(`${s}sys-img2-3.xml`);const o=Nt(t,"emulator",je,"emulator");const n=Nt(t,"platform-tools",je,"platform-tools");const a=Nt(i,`system-images;android-${e.api};${e.tag};${e.abi}`,s,nt(e));const r=[!o&&"emulator",!n&&"platform-tools",!a&&`${e.tag} image for Android ${e.api}`].filter(Boolean);if(r.length)throw new Error(`Google's list has no stable ${r.join(", ")} for this computer.`);const c=[o,n,a];const l={};for(const d of c){if(l[d.license])continue;l[d.license]=Hs(t,d.license)??Hs(i,d.license)??`(See ${je} for license ${d.license}.)`}return{archives:c,licenses:l}}async function Ys(e){const t=Yo("sha1");await js(zo(e),t);return t.digest("hex")}async function nn(e,t,s=()=>{}){if(process.platform==="win32")throw new Error("The Android farm can't set up its own SDK on Windows yet.");const i=Fs(e);const o=j.join(e,"download");await se.mkdir(o,{recursive:true});await Promise.all(t.archives.map(async a=>{const r=j.join(i,a.dest);if(a.dest==="emulator"?Gs(i):Ue(j.join(r,a.dest==="platform-tools"?"adb":"system.img"))){s(`${a.name}: already here.`);return}const c=j.join(o,j.basename(a.url));if(!Ue(c)||await Ys(c)!==a.sha1){s(`Downloading ${a.name} (${Math.round(a.size/1024**2)} MB)\u2026`);const h=await fetch(a.url);if(!h.ok||!h.body)throw new Error(`GET ${a.url} failed: ${h.status}`);await js(Vo.fromWeb(h.body),Ko(c));const f=await Ys(c);if(f!==a.sha1)throw new Error(`${a.name} failed its checksum (${f}).`)}const l=j.join(o,`unzip-${j.basename(a.url)}`);await se.rm(l,{recursive:true,force:true});await se.mkdir(l,{recursive:true});await L("unzip",["-q",c,"-d",l],{timeoutMs:15*6e4});const[d]=await se.readdir(l);await se.mkdir(j.dirname(r),{recursive:true});await se.rm(r,{recursive:true,force:true});await se.rename(j.join(l,d),r);await se.rm(l,{recursive:true,force:true});await se.rm(c,{force:true});s(`${a.name}: ready.`)}));await se.rm(o,{recursive:true,force:true});const n=Fe(i,"buoy");if(!n)throw new Error(`The SDK at ${i} is not complete after the download.`);return n}import{existsSync as an,promises as Ct,readFileSync as rn}from"fs";import cn from"path";var xt="android-3gb";var zs={"android-3gb":{name:"Low-end Android (3 GB)",ramMB:3072,cores:4,width:720,height:1600,density:320,heapGrowthMB:192,heapMB:512,source:"built in"},"pixel-4a":{name:"Pixel 4a",ramMB:6144,cores:8,width:1080,height:2340,density:440,heapGrowthMB:256,heapMB:512,source:"built in"}};function Ks(e){return cn.join(e,"phones.json")}function Lt(e){const t={...zs};const s=Ks(e);if(an(s)){try{Object.assign(t,JSON.parse(rn(s,"utf8")))}catch{}}return t}async function ln(e,t,s){const i=Ks(e);let o={};try{o=JSON.parse(await Ct.readFile(i,"utf8"))}catch{}o[t]=s;await Ct.mkdir(e,{recursive:true});await Ct.writeFile(i,JSON.stringify(o,null,2)+"\n")}var dn=[1024,1536,2048,3072,4096,6144,8192,12288,16384,24576];function pn(e,t){const s=h=>new RegExp(`\\[${h.replace(/\./g,"\\.")}\\]: \\[([^\\]]*)\\]`).exec(e.props)?.[1]??"";const i=Number(/MemTotal:\s+(\d+)/.exec(e.meminfo)?.[1]??0);const o=i?dn.find(h=>h>=i/1024)??Math.ceil(i/1024/1024)*1024:0;const n=/Override size: (\d+)x(\d+)/.exec(e.wmSize)??/Physical size: (\d+)x(\d+)/.exec(e.wmSize);const a=/Override density: (\d+)/.exec(e.wmDensity)??/Physical density: (\d+)/.exec(e.wmDensity);const r=h=>Number(/^(\d+)m$/i.exec(h)?.[1]??0);const c=s("ro.product.model")||"Android phone";const l={name:c,ramMB:o||3072,cores:Number(e.nproc.trim())||4,width:n?Number(n[1]):1080,height:n?Number(n[2]):2400,density:a?Number(a[1]):420,heapGrowthMB:r(s("dalvik.vm.heapgrowthlimit"))||256,heapMB:r(s("dalvik.vm.heapsize"))||512,source:t};const d=c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"android-phone";return{id:d,phone:l}}import{promises as Mc,readFileSync as un}from"fs";import Ut from"os";import jt from"path";import{promises as hn,existsSync as Ft,mkdirSync as Gt,readFileSync as Se,renameSync as Wt,writeFileSync as at,rmSync as We,openSync as mn,fsyncSync as fn,closeSync as wn,chmodSync as gn,readdirSync as yn,statSync as Qs}from"fs";import vn from"os";import H from"path";import{createHash as Sn,randomBytes as He}from"crypto";function A(){return process.env.BUOY_FARM_HOME||H.join(vn.homedir(),".buoy","farm")}var X=(e=A())=>({home:e,lock:H.join(e,"owner.lock"),lockOwner:H.join(e,"owner.lock","owner.json"),socket:H.join(e,"farmd.sock"),token:H.join(e,"token"),state:H.join(e,"state.json"),journal:H.join(e,"journal.ndjson"),log:H.join(e,"farmd.log"),shots:H.join(e,"shots")});function Ht(e=A()){Gt(e,{recursive:true,mode:448});try{gn(e,448)}catch{}}function Vs(e=A()){const t=X(e).token;try{const s=Se(t,"utf8").trim();if(s)return s}catch{}Ht(e);try{at(t,He(24).toString("hex")+"\n",{mode:384,flag:"wx"})}catch(s){if(s.code!=="EEXIST")throw s}for(let s=0;s<20;s++){const i=Se(t,"utf8").trim();if(i)return i;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,25)}throw new Error(`farm token at ${t} is empty`)}async function qe(e=A()){try{return JSON.parse(await hn.readFile(X(e).lockOwner,"utf8"))}catch{return null}}async function Ye(e){return!!e&&await J(e.pid,e.start,true)}async function bn(e,t){const s=H.join(e,"owner.claim");for(let i=0;i<20;i++){try{Gt(s,{mode:448});at(H.join(s,"pid"),`${process.pid}
|
|
5
5
|
${await Ie(process.pid)??""}`);try{return await t()}finally{We(s,{recursive:true,force:true})}}catch(o){if(o.code!=="EEXIST")throw o;const n=Qs(s,{throwIfNoEntry:false});if(n&&Date.now()-n.mtimeMs>3e4){let a=true;try{const[r,c]=Se(H.join(s,"pid"),"utf8").split("\n");a=!await J(Number(r),c||void 0)}catch{}if(a){try{Wt(s,H.join(e,`owner.claim-dead-${He(4).toString("hex")}`))}catch{}}}await new Promise(a=>setTimeout(a,100))}}return null}async function kn(e,t,s=A()){Ht(s);const i=X(s);const o=await Ie(process.pid)??"";for(let n=0;n<3;n++){try{Gt(i.lock,{mode:448})}catch(r){if(r.code!=="EEXIST")throw r;const c=await qe(s);if(c&&await Ye(c))return null;if(!c){await new Promise(h=>setTimeout(h,300));const d=await qe(s);if(d&&await Ye(d))return null}const l=await bn(s,async()=>{const d=await qe(s);if(d&&await Ye(d))return false;if(!Ft(i.lock))return true;Wt(i.lock,H.join(s,`owner.stale-${He(4).toString("hex")}`));return true});if(l===false)return null;continue}const a={pid:process.pid,start:o,version:e,host:t,since:new Date().toISOString()};at(i.lockOwner,JSON.stringify(a),{mode:384});Mn(s);return{info:a,release(){try{const r=JSON.parse(Se(i.lockOwner,"utf8"));if(r.pid!==process.pid)return}catch{return}try{We(i.socket,{force:true})}catch{}We(i.lock,{recursive:true,force:true})}}}return null}function Mn(e){try{for(const t of yn(e)){if(t.startsWith("owner.stale-")||t.startsWith("owner.claim-dead-"))We(H.join(e,t),{recursive:true,force:true})}}catch{}}function Js(){return{version:et,seq:0,farmId:He(6).toString("hex"),nextIndex:1,templates:{},sims:{},orphans:{},leases:{},runs:{},locks:{},requests:{},events:[],settings:{...Et}}}var Xs=e=>Sn("sha256").update(JSON.stringify(e)).digest("hex").slice(0,12);function Zs(e,t,s){const i=mn(e,s,384);try{at(i,t);fn(i)}finally{wn(i)}}var ei=class{constructor(e=A()){this.fenced=false;this.pending=[];this.open=new Map;this.p=X(e);Ht(e);this.state=this.load()}get shotsPath(){return this.p.shots}get homeDir(){return this.p.home}fence(){this.fenced=true}assertActive(){if(this.fenced)throw new Error("This farm has stopped.")}load(){let e=Js();if(Ft(this.p.state)){const o=JSON.parse(Se(this.p.state,"utf8"));if(o.version>et){throw new Error(`farm state is version ${o.version}; this farmd understands ${et}. Update Buoy.`)}e={...Js(),...o,settings:{...Et,...o.settings}}}delete e.settings.activeSlots;const t=new Map;const s=new Set;let i=e.seq;if(Ft(this.p.journal)){for(const o of Se(this.p.journal,"utf8").split("\n")){if(!o.trim())continue;let n;try{n=JSON.parse(o)}catch{continue}const{sum:a,...r}=n;if(Xs(r)!==a||n.seq<=e.seq)continue;i=Math.max(i,n.seq);if(n.type==="intent")t.set(n.seq,n);else{t.delete(n.seq);s.add(n.seq)}}}for(const o of e.openIntents??[]){if(!s.has(o.seq)&&!t.has(o.seq))t.set(o.seq,{...o,type:"intent",sum:""})}this.pending=[...t.values()].sort((o,n)=>o.seq-n.seq);for(const o of this.pending)this.open.set(o.seq,o);e.seq=i;e.openIntents=[];return e}intent(e,t){this.assertActive();const s=++this.state.seq;const i={seq:s,at:new Date().toISOString(),type:"intent",op:e,data:t};this.append(i);this.open.set(s,{...i,sum:""});return s}result(e,t,s){this.assertActive();this.open.delete(e);this.pending=this.pending.filter(i=>i.seq!==e);this.save();this.append({seq:e,at:new Date().toISOString(),type:"result",op:t,data:s})}append(e){this.assertActive();Zs(this.p.journal,JSON.stringify({...e,sum:Xs(e)})+"\n","a")}save(){this.assertActive();const e=`${this.p.state}.${He(4).toString("hex")}.tmp`;this.state.openIntents=[...this.open.values()].map(({seq:t,at:s,op:i,data:o})=>({seq:t,at:s,op:i,data:o}));Zs(e,JSON.stringify(this.state,null,1),"w");Wt(e,this.p.state);try{if(Qs(this.p.journal).size>2*1024*1024)We(this.p.journal,{force:true})}catch{}}event(e){this.assertActive();this.state.events.push({at:new Date().toISOString(),...e});if(this.state.events.length>300)this.state.events.splice(0,this.state.events.length-300)}};function _n(e=A()){try{const t=JSON.parse(Se(X(e).state,"utf8"));return new Set([...Object.keys(t.sims??{}),...Object.keys(t.orphans??{}),...Object.values(t.templates??{}).map(s=>s.udid)])}catch{return new Set}}var de=Number(process.env.BUOY_FARM_ADB_PORT)||5137;var En=1.3;function ze(e=A()){return jt.join(e,"android")}function ti(e){const t=s=>{const i=s.exec(e);return i?Number(i[1]):null};return{frames:t(/Total frames rendered: (\d+)/)??0,jankyPct:t(/Janky frames: \d+ \(([\d.]+)%\)/),p50:t(/50th percentile: (\d+)ms/),p90:t(/90th percentile: (\d+)ms/),p99:t(/99th percentile: (\d+)ms/)}}function $n(e){if(!e.length)return null;const t=[...e].sort((i,o)=>i-o);const s=Math.floor(t.length/2);return t.length%2?t[s]:Math.round((t[s-1]+t[s])/2)}function si(e){if(/Successfully loaded snapshot|Loading snapshot '?default_boot'? .*(done|succeeded)|snapshot.*loaded/i.test(e))return"snapshot";if(/Cold boot|failed to load snapshot|Snapshot load failed|could not load snapshot/i.test(e))return"cold";return"unknown"}async function In(){const e=Ut.totalmem()/1024**3;let t=Ut.freemem()/1024**3;if(process.platform==="darwin"){const o=await _("vm_stat",[],{timeoutMs:1e4});const n=Number(/page size of (\d+)/.exec(o.stdout)?.[1]??16384);const a=r=>Number(new RegExp(`${r}:\\s+(\\d+)`).exec(o.stdout)?.[1]??0);t=(a("Pages free")+a("Pages inactive")+a("Pages speculative")+a("Pages purgeable"))*n/1024**3}const s=await _("df",["-k",Ut.homedir()],{timeoutMs:1e4});const i=Number((s.stdout.trim().split("\n").pop()??"").split(/\s+/)[3]??0);return{availableGB:t,totalGB:e,freeDiskGB:i/1024**2}}async function Bn(e){if(process.platform==="darwin"){const i=await _("footprint",[String(e)],{timeoutMs:3e4});const o=/Footprint: ([\d.]+) (MB|GB|KB)/.exec(i.stdout);if(o)return Math.round(Number(o[1])*(o[2]==="GB"?1024:o[2]==="KB"?1/1024:1))}const t=await _("ps",["-o","rss=","-p",String(e)],{timeoutMs:5e3});const s=Number(t.stdout.trim());return s?Math.round(s/1024):null}async function ii(e){const t=await _("ps",["-o","time=","-p",String(e)],{timeoutMs:5e3});const s=/(?:(\d+)-)?(?:(\d+):)?(\d+):(\d+(?:\.\d+)?)/.exec(t.stdout.trim());if(!s)return null;const[,i,o,n,a]=s;return((Number(i??0)*24+Number(o??0))*60+Number(n))*6e4+Number(a)*1e3}function qt(e,t){return oi(t).get(e)??null}function oi(e){const t=new Map;const s=a=>{try{return JSON.parse(un(a,"utf8"))}catch{return null}};const i=(a,r)=>{for(const c of Object.values(r??{})){const l=a?.[c.templateId];if(!l?.sdkRoot||!On(c.pid)||t.has(c.serial))continue;t.set(c.serial,{adb:jt.join(l.sdkRoot,"platform-tools","adb"),port:de})}};const o=s(X(e??A()).state);i(o?.androidTemplates,o?.androidCopies);const n=s(jt.join(ze(e),"state.json"));if(!o?.androidImported)i(n?.templates,n?.copies);return t}function On(e){try{process.kill(e,0);return true}catch(t){return t.code==="EPERM"}}var ni=5800;var ai=5998;var ri="BuoyFarm_";var Tn="sync_device_id|react_buoy_install";var Dn=["files/react-buoy","shared_prefs","app_webview","databases","app_flutter"];var ci=Number(process.env.BUOY_BROKER_PORT)||42831;var li=class{constructor(e={}){this.dir=ze(e.home);this.avdHome=Y.join(this.dir,"avd");this.adbPort=e.adbPort??de;this.sdkPref=e.sdk??"auto"}sdkFor(e=ne){const t=Ge(this.dir,e,this.sdkPref);return t?.hasImage?t:null}sdk(e=ne){const t=Ge(this.dir,e,this.sdkPref);if(!t)throw new Error("No Android SDK with an emulator and the slim image yet. Run: npx @buoy-gg/mcp farm android setup");if(!t.hasImage)throw new Error(`The SDK at ${t.root} has no ${nt(e)} image. Run: npx @buoy-gg/mcp farm android setup`);return t}sdkOf(e){const t=this.sdk(e.image);if(t.root!==e.sdkRoot){const s=Ge(this.dir,e.image,t.source==="buoy"?"system":"buoy");if(s?.root===e.sdkRoot)return s}return t}env(e){return{...process.env,ANDROID_HOME:e.root,ANDROID_SDK_ROOT:e.root,ANDROID_AVD_HOME:this.avdHome,ANDROID_ADB_SERVER_PORT:String(this.adbPort)}}run(e,t,s=3e4){return _(e.adb,t,{timeoutMs:s,env:this.env(e)})}adb(e,t,s=3e4){return this.run(this.sdkOf(e),t,s)}async shell(e,t,s,i=3e4){const o=await this.run(e,["-s",t,"shell",s],i);if(o.timedOut)throw new Error(`adb shell on ${t} timed out: ${s}`);if(o.code!==0)throw new Error(`adb shell on ${t} failed: ${s}: ${(o.stderr||o.stdout).trim().slice(0,300)}`);return o.stdout}stale(e){if(!e.usable)return e.note??"not ready";let t;try{t=this.sdkOf(e)}catch(s){return s.message}if(t.root!==e.sdkRoot||t.emulatorVersion!==e.emulatorVersion){return`It was saved with emulator ${e.emulatorVersion}; this SDK has ${t.emulatorVersion}. Snapshots don't load across versions.`}if(!Dt(Y.join(this.avdHome,`${e.avd}.avd`,"snapshots","default_boot","ram.bin")))return"Its snapshot is gone.";return null}async freePort(e){const t=s=>new Promise(i=>{const o=qo.createServer();o.once("error",()=>i(false));o.listen(s,"127.0.0.1",()=>o.close(()=>i(true)))});for(let s=ni;s<=ai;s+=2){if(e.has(s))continue;if(await t(s)&&await t(s+1))return s}throw new Error(`No free emulator port from ${ni} to ${ai}.`)}async launch(e,t,s,i,o){const n=Y.join(this.dir,"logs");await ve.mkdir(n,{recursive:true});const a=Y.join(n,o);const r=Wo(a,"w");const c=["-avd",t,"-port",String(s),"-gpu","host","-no-audio","-no-boot-anim","-camera-back","none","-camera-front","none",...i];const l=Ls(e.emulator,c,{detached:true,stdio:["ignore",r,r],env:this.env(e)});Ho(r);l.unref();if(!l.pid)throw new Error("The emulator did not start.");const d=await Ie(l.pid)??"";return{pid:l.pid,pidStart:d,log:a}}async waitBooted(e,t,s,i){const o=Date.now()+i;while(Date.now()<o){if(!await J(s))throw new Error(`The emulator for ${t} stopped while booting.`);const n=await this.run(e,["-s",t,"shell","getprop","sys.boot_completed"],5e3);if(n.code===0&&n.stdout.trim()==="1")return;await T(250)}throw new Error(`${t} did not finish booting in ${Math.round(i/1e3)} s.`)}async stopEmulator(e,t,s,i){if(e)await this.run(e,["-s",t,"emu","kill"],1e4);for(let o=0;o<300;o++){if(!await J(s,i))return;await T(100)}if(await J(s,i)){try{process.kill(s,"SIGKILL")}catch{}}}async startCopy(e,t,s={}){const i=this.sdkOf(e);await this.run(i,["start-server"],2e4);const o=`emulator-${t}`;const n=["-read-only","-no-snapshot-save",...s.window?[]:["-no-window"]];const a=await this.launch(i,e.avd,t,n,`${o}.log`);return{serial:o,port:t,...a}}async readyCopy(e,t,s={}){const i=this.sdkOf(e);await this.waitBooted(i,t.serial,t.pid,s.timeoutMs??5*6e4);let o="unknown";try{o=si(await ve.readFile(t.log,"utf8"))??"unknown"}catch{}await this.shell(i,t.serial,"setprop debug.hwui.drawing_enabled 1; logcat -c");for(const n of[`${ci}`,...e.reverse??[],...s.reverse??[]]){const[a,r]=n.split(":");const c=await this.run(i,["-s",t.serial,"reverse",`tcp:${a}`,`tcp:${r??a}`],1e4);if(c.code!==0)throw new Error(`Could not link port ${a} on ${t.serial}: ${(c.stderr||c.stdout).trim().slice(0,200)}`)}return{bootedFrom:o}}async stopCopy(e,t){let s=null;try{s=e?this.sdkOf(e):this.sdkFor(ne)}catch{}if(await J(t.pid,t.pidStart))await this.stopEmulator(s,t.serial,t.pid,t.pidStart)}alive(e,t){return J(e,t)}async treePids(e){return Ot(await tt(),e).map(t=>t.pid)}async findEmulators(){const e=[];for(const t of await tt()){const s=/-avd (\S+)/.exec(t.command)?.[1];const i=Number(/-port (\d+)/.exec(t.command)?.[1]);if(!s?.startsWith(ri)||!i)continue;if(e.some(o=>o.port===i))continue;e.push({pid:t.pid,pidStart:t.start,port:i,avd:s})}return e}async screenshot(e,t,s,i=2e4){const o=this.sdkOf(e);const n=await new Promise(a=>{const r=Ls(o.adb,["-s",t,"exec-out","screencap","-p"],{env:this.env(o)});const c=[];r.stdout.on("data",d=>c.push(d));r.on("error",()=>a({code:-1,buf:Buffer.alloc(0)}));const l=setTimeout(()=>r.kill("SIGKILL"),i);r.on("close",d=>{clearTimeout(l);a({code:d,buf:Buffer.concat(c)})})});if(n.code!==0||n.buf.length<100)return false;await ve.mkdir(Y.dirname(Y.resolve(s)),{recursive:true});await ve.writeFile(s,n.buf);return true}async launchApp(e,t,s){const i=this.sdkOf(e);await this.shell(i,t,`am force-stop ${e.packageName}`);const o=s??e.launchUrl;const n=o?`am start -W -a android.intent.action.VIEW -d ${di(o)} ${e.packageName}`:`am start -W -n ${e.activity}`;const a=await this.shell(i,t,n,12e4);const r=/TotalTime: (\d+)/.exec(a);return{totalMs:r?Number(r[1]):null,output:a.trim()}}async openUrl(e,t,s){await this.shell(this.sdkOf(e),t,`am start -a android.intent.action.VIEW -d ${di(s)} ${e.packageName}`,6e4)}async install(e,t,s){const i=this.sdkOf(e);const o=await this.run(i,["-s",t,"install","-r","-g",Y.resolve(s)],10*6e4);if(o.code!==0||!/Success/.test(o.stdout))throw new Error(`${t}: install failed: ${(o.stderr||o.stdout).trim().slice(0,300)}`);await this.shell(i,t,`cmd package compile -m speed -f ${e.packageName}`,10*6e4)}async installId(e,t){const s=await this.run(this.sdkOf(e),["-s",t,"shell",`run-as ${e.packageName} cat files/react-buoy/@react_buoy_sync_device_id.json`],5e3);const i=s.code===0?s.stdout.trim().replace(/^"|"$/g,""):"";return/^[\w-]{4,64}$/.test(i)?i:null}async appMemory(e,t){const s=this.sdkOf(e);const i=Number((await this.shell(s,t,`pidof ${e.packageName}; true`)).trim().split(/\s+/)[0])||null;if(!i)return{pid:null,pssMB:null};const o=await this.shell(s,t,`dumpsys meminfo ${i}`,2e4).catch(()=>"");const n=Number(/TOTAL PSS:\s+(\d+)/.exec(o)?.[1]??/TOTAL\s+(\d+)/.exec(o)?.[1]??0);return{pid:i,pssMB:n?Math.round(n/1024):null}}async memoryKill(e,t,s){const i=await this.shell(this.sdkOf(e),t,"logcat -d -b events -s am_kill:I lowmemorykiller:I; true",15e3).catch(()=>"");for(const o of i.split("\n")){const n=/am_kill\s*:\s*\[\d+,(\d+),([^,]+),-?\d+,([^\]]*)\]/.exec(o);if(n&&Number(n[1])===s&&n[2].trim()===e.packageName&&/low ?mem|lmk|oom|memory/i.test(n[3]))return n[3].trim()}return null}writeAvd(e,t,s){const i=Y.join(this.avdHome,`${e}.avd`);Go(i,{recursive:true});const o={AvdId:e,"avd.ini.displayname":e.replace(/_/g," "),"avd.ini.encoding":"UTF-8","abi.type":s.abi,"hw.cpu.arch":s.abi==="arm64-v8a"?"arm64":"x86_64","image.sysdir.1":nt(s),"tag.id":s.tag,"tag.display":s.tag==="aosp_atd"?"AOSP ATD":"Google ATD",target:`android-${s.api}`,"hw.ramSize":t.ramMB,"hw.cpu.ncore":t.cores,"hw.lcd.width":t.width,"hw.lcd.height":t.height,"hw.lcd.density":t.density,"disk.dataPartition.size":"6G","hw.gpu.enabled":"yes","hw.gpu.mode":"host","hw.keyboard":"yes","hw.audioInput":"no","hw.audioOutput":"no","hw.camera.back":"none","hw.camera.front":"none","fastboot.forceColdBoot":"no","fastboot.forceFastBoot":"yes",showDeviceFrame:"no"};Us(Y.join(i,"config.ini"),Object.entries(o).map(([n,a])=>`${n}=${a}`).join("\n")+"\n");Us(Y.join(this.avdHome,`${e}.ini`),`avd.ini.encoding=UTF-8
|
|
6
6
|
path=${i}
|
|
7
7
|
path.rel=avd/${e}.avd
|
|
@@ -579,6 +579,7 @@ ${S.length-U} passed, ${U} failed${G?`, ${G} not run`:""}. ${u.length} Chromes,
|
|
|
579
579
|
remove-template <id> Delete a template and all its sims (none may be in use)
|
|
580
580
|
acquire <n> [--template id] [--purpose text] [--launch]
|
|
581
581
|
Take n sims and hold them until Ctrl-C
|
|
582
|
+
(24 hours at most)
|
|
582
583
|
park|wake|reset|rebuild|delete <udid>
|
|
583
584
|
end-lease <leaseId> Force-end a lease (its sims are rebuilt)
|
|
584
585
|
settings [key=value ...] Show or change settings
|
|
@@ -594,4 +595,4 @@ ${S.length-U} passed, ${U} failed${G?`, ${G} not run`:""}. ${u.length} Chromes,
|
|
|
594
595
|
stop [--now] Stop the farm service and park free sims
|
|
595
596
|
--now Stop even if leases are still held
|
|
596
597
|
farmd Run the farm service in this process
|
|
597
|
-
`;var
|
|
598
|
+
`;var Tl=Mt("pnpm farm");function z(e,t){const s=e.indexOf(`--${t}`);if(s<0)return void 0;const i=e[s+1];if(!i||i.startsWith("--"))throw new p("BAD_REQUEST",`--${t} needs a value.`);return i}var Gr=24*36e5;async function Wr(e,t,s=process,i=o=>console.error(o)){const o=new Date(t.deadlineAt);i(`Holding these sims until Ctrl-C. The farm ends the lease at ${o.toLocaleString()} at the latest.`);const n=await new Promise(a=>{const r=()=>l("signal");const c=setTimeout(()=>l("deadline"),Math.max(0,o.getTime()-Date.now()));function l(d){clearTimeout(c);s.off("SIGINT",r);s.off("SIGTERM",r);a(d)}s.once("SIGINT",r);s.once("SIGTERM",r)});if(n==="deadline")return"The lease reached its time limit, so the farm took the sims back.";await e.release(t.leaseId,t.epoch);return"Released."}async function Hr(e){return ts({label:`CLI (${ba.userInfo().username})`,launcher:es(e,["farmd"])})}function P(e){console.log(typeof e==="string"?e:JSON.stringify(e,null,2))}async function go(e,t,s){if(s)return s;const i=await e.call("status");const o=i.templates.filter(n=>n.usable);if(o.length===0)throw new p("NO_TEMPLATE","No template yet.",`Run: ${t} setup`);return o[o.length-1].id}function qr(e){const t=[`Pool ${e.counts.pool} \xB7 awake ${e.counts.awake} \xB7 in use ${e.counts.leased} \xB7 room for about ${e.budget.roomForMoreSims} more`,`Memory ${e.budget.availableMemGB} GB free (${e.budget.memPressure}) \xB7 disk ${e.budget.freeDiskGB} GB free \xB7 load ${e.budget.loadAvg1}/${e.budget.cpuCount}`];for(const s of e.templates){t.push(`Template ${s.id} ${s.name}: ${s.usable?"ready":s.note??"not ready"} (${s.profile}, ${s.runtime.split(".").pop()})`);t.push(` seed: ${s.seedDir??"none"} \xB7 launch URL: ${s.launchUrl??"none"}`)}for(const s of e.sims){t.push(` ${s.name.padEnd(14)} ${s.power.padEnd(8)} ${s.health.padEnd(7)} ${s.profile.padEnd(7)} ${s.owner?`in use by ${s.owner}`:""} ${s.udid}`);const i=s.phone;if(i?.status==="on"){t.push(` as ${i.phoneName}${i.peakMB?`, peak ${i.peakMB} MB`:""}${i.overLimit?", WENT PAST THE PHONE'S LIMIT":""}${i.ended?` (closed: ${i.ended})`:""}`)}else if(i?.status==="fallback"){t.push(` plain sim app: ${i.note??"the phone profile did not load"}`)}}for(const s of e.orphans??[])t.push(` ${s.name} ${s.udid}: held after crash`);for(const s of e.recentEvents.slice(-8))t.push(` \xB7 ${new Date(s.at).toLocaleTimeString(void 0,{hour12:false})} ${s.message}`);if(e.outsideSims)t.push(`Other sims (never touched): ${e.outsideSims.length}`);return t.join("\n")}async function Yr(e,{prog:t,entry:s,chromeKeeperArgs:i}){const[o,...n]=e;if(!o||o==="help"||o==="--help")return P(Mt(t));if(o==="android")return Hi(n,t,s);if(o==="chrome")return wo(n,t,[s,...i??["chrome","keeper"]]);zr(o,n);if(o==="farmd"){const r=await Pi({hostLabel:"node",idleExitMs:10*6e4,onExit:()=>process.exit(0)});if(!r){console.error("Another farm service is already running.");process.exit(0)}for(const c of["SIGTERM","SIGINT"])process.on(c,()=>void r.stop(c));return}if(o==="phone"&&n[0]!=="use"){const r=n[0];if(r==="list"||!r){const c=Oe();for(const[l,d]of Object.entries(c)){P(`${l}: ${d.name} (${d.productType}), ${d.ramMB} MB RAM, ${d.cpus} CPUs, app limit ${d.limitMB} MB, first warning ${d.warnMB} MB, iOS ${d.ios}, measured ${d.measuredAt}`)}return}if(r==="measure"){const c=await Fi({device:z(n,"device"),log:l=>console.log(l)});P(`Saved "${c.id}": ${c.phone.ramMB} MB RAM, ${c.phone.cpus} CPUs, app limit ${c.phone.limitMB} MB, first warning ${c.phone.warnMB} MB.`);if(c.previous&&c.previous.limitMB!==c.phone.limitMB)P(`(The limit was ${c.previous.limitMB} MB before.)`);P(`Use it with: ${t} phone use ${c.id}`);return}throw new p("BAD_REQUEST",`Unknown phone command ${r}.`,"Try: phone list, phone use <id|off>, phone measure")}if(o==="doctor"){const r=new Zt;const c=await r.hostStats();const l=await qe();const d=await r.listDevices().catch(()=>[]);const h=Ve();const f=h?Ui.join(h,"example-dev-build/artifacts/pool-seed"):null;const w=h?{exampleBuild:ut(),seed:f?Le(f)??"ok":"none"}:{};P({xcode:await r.xcodeBuild(),runtimes:[...new Set(d.map(v=>v.runtime.split(".").pop()))],freeDiskGB:Math.floor(c.freeDiskBytes/1024**3),availableMemGB:Math.floor(c.availableMemBytes/1024**3),memPressure:c.memPressure,farmService:l?{...l,alive:await Ye(l)}:"not running",socket:Sa(X().socket),...w,slimLabels:Ee("slim").length,slimTurnsOff:Ce.map(v=>v.name)});return}const a=await Hr(s);try{switch(o){case"status":{const r=await a.call("status",{outside:n.includes("--outside")});return P(n.includes("--json")?r:qr(r))}case"setup":{const r=Ve();const c={appPath:z(n,"app")??ut(),seedDir:n.includes("--no-seed")?null:z(n,"seed")??(r?Ui.join(r,"example-dev-build/artifacts/pool-seed"):void 0),launchUrl:z(n,"launch-url"),deviceType:z(n,"device")??"com.apple.CoreSimulator.SimDeviceType.iPhone-17-Pro",runtime:z(n,"runtime")??"com.apple.CoreSimulator.SimRuntime.iOS-26-3",profile:z(n,"profile")??"slim",metroPort:Number(z(n,"metro")??8802)};if(!c.appPath)throw new p("BAD_REQUEST","No app build found.","Pass --app <path.app>.");if(!c.seedDir&&!n.includes("--no-seed"))throw new p("NO_SEED","No seed folder found.","Pass --seed <dir>, or --no-seed for an app that needs no saved data.");if(n.includes("--dry-run")){const l=await a.call("budget",{ramGB:6,diskGB:4});return P({wouldCreateTemplate:c,seed:c.seedDir?Le(c.seedDir)??"ok":"none",slimTurnsOff:c.profile==="slim"?Ce.map(d=>`${d.name}: ${d.downside}`):[],budget:l.ok?"ok":l.reason,roomForSims:l.roomFor})}return P(await a.call("setup",c,{timeoutMs:15*6e4,requestId:`setup-${Date.now()}`}))}case"grow":case"shrink":{const r=await go(a,t,z(n,"template"));return P(await a.call(o,{templateId:r,count:Number(n[0]??1)},{timeoutMs:30*6e4,requestId:`${o}-${Date.now()}`}))}case"acquire":{const r=await go(a,t,z(n,"template"));const c=await a.acquire({templateId:r,count:Number(n[0]??1),purpose:z(n,"purpose")??"CLI",launch:n.includes("--launch"),ttlMs:Gr});P(c);return P(await Wr(a,c))}case"remove-template":if(!n[0])throw new p("BAD_REQUEST",`Usage: ${t} remove-template <id>`);return P(await a.call("removeTemplate",{templateId:n[0]},{timeoutMs:30*6e4,requestId:`rmt-${n[0]}-${Date.now()}`}));case"park":case"wake":case"reset":case"rebuild":case"delete":if(!n[0])throw new p("BAD_REQUEST",`Usage: ${t} ${o} <udid>`);return P(await a.call(o,{udid:n[0]},{timeoutMs:5*6e4,requestId:`${o}-${n[0]}-${Date.now()}`}));case"stop":return P(await a.call("shutdown",{ifIdle:!n.includes("--now")}));case"end-lease":return P(await a.call("endLease",{leaseId:n[0],force:true},{requestId:`end-${n[0]}`}));case"phone":{if(!n[1])throw new p("BAD_REQUEST","phone use needs a phone id or off.",`See: ${t} phone list`);const r=await a.call("settings",{phoneProfile:n[1]});return P(r.phoneProfile==="off"?"Apps now launch as plain simulator apps.":`Apps now launch as ${Oe()[r.phoneProfile]?.name??r.phoneProfile}. Apps that are already open keep their old setting until the farm launches them again.`)}case"settings":{if(n.length===0)return P((await a.call("status")).settings);const r={};for(const c of n){const[l,d]=c.split("=");r[l]=d==="true"?true:d==="false"?false:Number.isNaN(Number(d))?d:Number(d)}return P(await a.call("settings",r))}default:P(Mt(t));process.exitCode=2}}finally{a.close()}}function zr(e,t){const s={setup:["app","seed","launch-url","device","runtime","profile","metro"],grow:["template"],shrink:["template"],acquire:["template","purpose"],phone:["device"]};for(const i of s[e]??[])z(t,i);if(e==="setup"){if(t.includes("--no-seed")&&t.includes("--seed"))throw new p("BAD_REQUEST","Use --seed or --no-seed.");const i=z(t,"profile");const o=Number(z(t,"metro")??8802);if(i&&!["slim","stock"].includes(i))throw new p("BAD_REQUEST","Use slim or stock.");if(!Number.isInteger(o)||o<1||o>65535)throw new p("BAD_REQUEST","Use a port from 1 to 65535.")}}export{te as PROTOCOL_VERSION,et as STATE_VERSION,Et as DEFAULT_SETTINGS,p as FarmError,ks as ALWAYS_ENABLED,Ce as SLIM_CATEGORIES,Ms as slimLabels,Ee as profileLabels,_s as profileHash,st as bootEnv,it as findDataContainer,Ps as readBuoyInstallId,Cs as LoadMeter,xs as parseCpuTime,xt as DEFAULT_ANDROID_PHONE,zs as BUILT_IN_ANDROID_PHONES,Lt as loadAndroidPhones,A as farmHome,X as paths,ei as Store,_n as farmOwnedUdids,de as ANDROID_ADB_PORT,ze as androidHome,ti as parseGfxinfo,si as classifyBootLog,qt as farmAdbTarget,oi as farmAdbTargets,li as EmulatorHost,pi as BUILT_IN_PHONES,ui as DEFAULT_PHONE,zt as PHONE_OFF,ct as phoneDir,Oe as loadPhones,fi as savePhone,wi as defaultCapMB,gi as profileVars,Kt as joinInsertList,Ke as launchFilePath,lt as eventsFilePath,yi as writeLaunchFile,dt as removeLaunchFile,vi as readLaunchFile,Qt as simLaunchEnv,Si as parseEvents,bi as summarize,pt as readSummary,ki as buildDylib,Mi as LocalDylibBuilder,re as copyCostGB,Bi as Engine,Oi as crashLoop,Zt as SimctlHost,Pi as startFarmd,es as nodeLauncher,Ci as FarmClient,ts as connectFarm,Ve as findRepoRoot,ut as findExampleBuild,xi as defaultSeedDir,ha as farmDefaults,ya as detectAgent,va as agentLabel,Fi as measurePhone,ns as androidHelp,Hi as runAndroidCommand,F as PINNED_VERSION,Ne as findShell,yt as installShell,Ji as PipeCdp,St as PHONE_VIEWPORT,hs as DESKTOP_VIEWPORT,ms as ChromeFarm,V as chromeFarmDir,_e as DEFAULT_CAP_MB,pe as keeperCall,ue as keeperAlive,lo as ensureKeeper,po as chromeHelp,Ze as coreInfo,vs as suggestCounts,wo as runChromeCommand,Mt as farmHelp,Yr as runFarmCommand};
|